bartwell

 
<<< Назад

Маячки в MajorDoMo: дом узнаёт, что вы пришли

В модуле Android Wear и приложении Majordomo Wear появились маячки. Небольшая плата ESP32 у двери (или в любом другом месте) замечает ваш телефон, и MajorDoMo выполняет то, что вы сами для этого места настроили: включает свет, говорит «Добро пожаловать», открывает электрозамок. Телефон при этом лежит в кармане — ничего доставать и нажимать не нужно.

Как это работает

Решение принимает только MajorDoMo. Маячок — лишь посредник между телефоном и сервером: он ничем не управляет и не хранит ничьих ключей.

  1. Маячок — плата ESP32-C6 — постоянно вещает по Bluetooth Low Energy и подключена к домашнему Wi-Fi.
  2. Телефон в кармане замечает маячок. Система будит приложение Majordomo Wear сама, даже если оно закрыто и экран выключен.
  3. Приложение подключается к маячку и получает от сервера одноразовое задание.
  4. Телефон подписывает задание своим ключом. Ключ создаётся в защищённом хранилище телефона и никогда его не покидает.
  5. Маячок по Wi-Fi передаёт подпись модулю. Модуль проверяет её, узнаёт, чей это телефон, и запускает действие этого маячка: ваш PHP-код или метод объекта.
  6. Ответ сервера возвращается на телефон. Если хотите, он покажет уведомление, например «Прихожая: свет включен».

Всё занимает 2–4 секунды от момента, когда телефон увидел маячок. В одном доме можно поставить сколько угодно маячков с разными действиями: у входной двери, в гараже, у калитки.

Что понадобится

Что Требования
Плата ESP32-C6 с flash от 4 МБ и USB. Проверено на Super Mini ESP32-C6, подойдёт и ESP32-C6-DevKitC-1. C3, S3 и классический ESP32 не поддерживаются
Питание 5 В там, где будет стоять маячок; для прошивки — USB-кабель с передачей данных
Сеть Wi-Fi 2,4 ГГц, из которого плата видит ваш MajorDoMo
Сервер Модуль Android Wear 0.2.5 или новее
Телефон Android 12 и новее или iPhone с iOS 16.2 и новее; приложение Majordomo Wear 4.4.3 или новее

Плата недорогая, а паять ничего не придётся: достаточно установить Arduino IDE.
На часах Wear OS и Android TV маячков нет.

Прошиваем и подключаем маячок

Прошивка лежит прямо в модуле: «Android Wear» → «Маячки» → «Помощь», ссылка «Скачать прошивку». Там же подробная инструкция; здесь — коротко.

  1. Установите Arduino IDE 2.x. В Boards Manager добавьте ядро esp32 by Espressif Systems 3.3.2, в Library Manager — NimBLE-Arduino 2.3.6 и ArduinoJson 7.4.2.
  2. Распакуйте архив и откройте MajordomoBleGate.ino. Плата — ESP32C6 Dev Module, Partition Scheme — Huge APP (3MB No OTA/1MB SPIFFS), USB CDC On Boot — Enabled. Нажмите Upload.
  3. В MajorDoMo откройте «Маячки», введите название (например, «Прихожая») и нажмите «Добавить и получить код». Код из шести цифр действует 10 минут.
  4. Плата без настроек поднимает сеть Wi-Fi MDW-Setup-XXXX. Подключитесь к ней с телефона — страница настройки откроется сама (или откройте http://192.168.4.1/).
  5. Введите домашний Wi-Fi 2,4 ГГц, адрес MajorDoMo и код привязки. Плата перезапустится, светодиод станет зелёным, а в карточке маячка появится «в сети».

В эфире маячок называется по своему названию латиницей («Прихожая» → Prikhozh), в роутере — mdw-prikhozhaya. Так его легко найти в BLE-сканере и в списке клиентов. Сброс настроек — удержать кнопку BOOT 5 секунд.

Подключаем телефон

  1. Обновите Majordomo Wear до 4.4.3 или новее и откройте его. Как только приложение загрузит меню с вашего сервера, в настройках появится раздел «Маячки», а телефон сам зарегистрируется на сервере.
  2. В MajorDoMo на вкладке «Маячки» → «Устройства» нажмите «Подтвердить» у нового телефона и выберите, чей он. Без подтверждения телефон ничего запустить не сможет.
  3. В приложении откройте «Маячки», включите «Действия у маячков» и выдайте разрешения. На iPhone понадобится ещё геолокация «Всегда»: именно она позволяет iOS разбудить приложение рядом с маячком. Сами координаты приложение не использует.
  4. На Android подойдите к маячку и нажмите «Привязать» — система покажет окно, где будет только этот маячок. Это нужно один раз для каждого маячка: именно привязка разрешает Android будить приложение в фоне. На iPhone маячки находятся сами.
  5. По желанию включите «Сообщать о срабатывании»: телефон покажет уведомление с названием маячка и ответом сервера. На время настройки удобно включить и «Показывать и ошибки».

У одного человека может быть несколько телефонов: каждый регистрируется отдельно со своим ключом, а потерянный можно выключить одной кнопкой в «Устройствах».

Пишем действие

У каждого маячка есть поле «Действие при появлении»: PHP-код (как у пунктов меню) или метод объекта, например Hall.onArrival. Код пишется на уровне маячка, а кто подошёл и с какого телефона, приходит в $params:

Ключ Что это
user, userTitle Объект владельца телефона и его описание, например ivan и «Иван»
device, deviceId, platform Имя телефона, его номер в модуле, android или ios
controller, controllerId Название и идентификатор маячка
rssi Уровень сигнала телефона у маячка — справочно
lastSeen Когда этот телефон в прошлый раз прошёл проверку у этого маячка (Unix-время, 0 — впервые)

Что вернуть:

Возврат Итог Что увидит человек
строку, например 'Свет включен' выполнено эту строку в уведомлении
ничего пропущено запись в журнале; уведомление — по настройкам приложения
false отклонено «отклонено»
array('result' => 'ignore', 'message' => 'Уже дома') как указано сообщение из массива

Итог сам ничего не делает — делает только ваш код. Предупреждения PHP его не прерывают, а исключение даёт «пропущено». Вывод echo в ответ не попадает.

Пример 1. Свет в прихожей, когда темно.

if (!gg('ThisComputer.isDark')) {
    return array('result' => 'ignore', 'message' => 'Светло');
}
callMethod('HallLight.turnOn');
say('Пришёл ' . $params['userTitle']);
return 'Свет в прихожей включен';

Пример 2. Электрозамок — только жильцам и только если человек действительно пришёл. Здесь жильцы — объекты класса HouseOwners со свойством atHome, которое выставляется по телефону в Wi-Fi (например, модулем роутера), и lastTimeAtHome — время последней смены atHome. Подставьте свои объекты.

$u = $params['user'];
$residents = array();
foreach ((array)getObjectsByClass('HouseOwners') as $o) {
    $residents[] = $o['TITLE'];
}
if (!in_array($u, $residents, true)) {
    return array('result' => 'ignore', 'message' => 'Нет данных о присутствии');
}
// Телефон давно в домашнем Wi-Fi — человек дома, это не приход.
if (gg($u . '.atHome') && time() - (int)gg($u . '.lastTimeAtHome') > 300) {
    return array('result' => 'ignore', 'message' => 'Уже дома');
}
// Двое пришли вместе — открываем один раз за 20 секунд.
SQLSelectOne("SELECT GET_LOCK('front_door', 5) AS L");
$already = time() - (int)gg('FrontDoor.openedAt') < 20;
if (!$already) {
    setGlobal('FrontDoor.openedAt', time());
}
SQLSelectOne("SELECT RELEASE_LOCK('front_door') AS R");
if ($already) {
    return 'Дверь уже открыта';
}
callMethod('FrontDoor.open');
return 'Дверь открыта';

Блокировка в MySQL нужна потому, что телефоны двух человек могут прийти в одну и ту же секунду: без неё оба обработчика решат, что «ещё не открывали».

Чтобы не срабатывало зря

Главная трудность не в том, чтобы заметить телефон, а в том, чтобы отличить «пришёл» от «и так рядом». Если маячок стоит у входной двери, а телефон лежит дома на границе слышимости, система может то терять маячок, то находить снова. Защита строится в три слоя.

Порог ухода в приложении. Настройка «Считать уходом, если маячка не было», по умолчанию 5 минут, можно от 1 до 120. Приходом считается только появление маячка после того, как его не было видно дольше порога. Короткие пропадания не вызывают ни обмена, ни уведомления. Вдобавок к одному маячку телефон подключается не чаще раза в 30 секунд.

Проверки в действии. Для света лишнее срабатывание безобидно, для замка — нет. Для всего, что открывает, проверяйте, что человека действительно не было дома, по тому источнику присутствия, что у вас есть: Wi-Fi, датчик входной двери, режим «Никого нет дома». Телефонам, чьё присутствие проверить нечем (тестовым, гостевым), лучше не открывать ничего — как в примере 2.

Место для маячка. Ставьте его так, чтобы там, где телефон обычно лежит дома, он либо уверенно слышен, либо не слышен совсем. Хуже всего — граница: в журнале это видно по сигналу около −80…−90 дБм и частым повторам.

Журналы. В модуле на вкладке «Журнал» видна каждая попытка: кто, у какого маячка, с каким сигналом и что решило действие. В приложении есть свой журнал с кнопкой «Поделиться». На время настройки включите уведомления с ошибками и поживите с новым маячком пару дней, прежде чем доверять ему замок.

Безопасность и ограничения

Что защищено:

  • У каждого телефона свой ключ ECDSA P-256. Закрытая часть хранится в Android Keystore или Secure Enclave и из телефона не извлекается.
  • Каждое задание одноразовое и живёт секунды (по умолчанию 20): записанный обмен нельзя повторить.
  • Новый телефон ничего не может, пока администратор его не подтвердит.
  • Запросы маячка к серверу подписаны его секретом: другое устройство в сети не выдаст себя за маячок.

Что важно знать:

  • Нет защиты от ретрансляции. Двое злоумышленников с радиомостами могут переслать обмен с вашим телефоном, даже если вы далеко. Это та же атака, что на бесключевой доступ в автомобилях. Не делайте маячок единственной защитой входной двери или сигнализации — он хорош для света, приветствий, калитки или тамбура за надёжной дверью.
  • modules/android_wear/ble.php — только из локальной сети. Маячкам и так не нужен внешний доступ, а модуль не ограничивает частоту запросов и перебор кода привязки.
  • Без MajorDoMo ничего не сработает. Маячок не принимает решений сам, и без Wi-Fi или сервера он просто молчит. Оставляйте обычный способ открыть дверь.
  • Уровень сигнала — не расстояние. rssi передаётся справочно, строить на нём защиту нельзя.

Ссылки

Вопросы и предложения — в обсуждении модуля. Если что-то не работает, приложите журнал из приложения и строки из вкладки «Журнал» модуля.

Обсуждение (0) (1)

Тамбов, Россия