Опять про BLE, температуру и датчики Xiaomi

термометр xiaomi не подключается. Не так давно, удалось мне обзавестись известными датчиками температуры и влажности от Xiaomi. Эти датчики заслуженно приобрели широкую известность, так как при своей достаточно низкой цене,…

Опять про BLE, температуру и датчики Xiaomi

Не так давно, удалось мне обзавестись известными датчиками температуры и влажности от Xiaomi. Эти датчики заслуженно приобрели широкую известность, так как при своей достаточно низкой цене, достаточно удобны в использовании, а также умеют передавать свои показания по протоколу BLE в тот же Mi Home. К тому же весь Интернет завален вариантами подключения этих сенсоров к Home Assistant, MajorDoMo и другим системам.

Но мне этого показалось мало и захотелось все сделать по-своему (не спрашивайте меня зачем и почему, просто захотелось). А именно, захотелось прочитать данные с датчиков, которые развешены по всему дому и как-нибудь интересно с ними поработать. Потому я покопался в своих электронных закромах и нашел там модуль ESP32.

Быстрое гугление показало: ESP32 — это то, что мне нужно. Он умеет Bluetooth и WiFi, программируется из Arduino IDE и позволит мне получить показания с датчика и отправить их по WiFi куда нужно (хоть на домашний сервер, хоть в облако). К тому же, очень быстро нашелся простой и понятный туториал, который как раз решал мою задачу. Но как выяснилось, не все так просто.

Первые проблемы

Как часто бывает с примерами из Интернета, код не заработал. А ведь так хотелось… Очевидно, что нужно разбираться с этим дальше.

Не смотря на то, что у меня в закромах лежат всякие ESP32, по основному роду деятельности я прикладной разработчик. Ковыряюсь с железками (как и многие, я полагаю) только в качестве хобби. Потому достаточно быстро пришло понимание того, что без закапывания в детали дальше продвинуться не получится. Потому пришлось изучить код, немного спецификацию BLE и понять как это устроено. По результатам разбирательств пришло некоторое понимание того, как оно работает, ну и сразу же захотелось этим с кем-нибудь поделиться.

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

Обычно устройства BLE умеют работать в 2-х режимах. Назовем их широковещательный (discover mode) и подключенный (connection mode). В широковещательном режиме устройство может рассылать пакеты, позволяющие другим Bluetooth устройствам обнаружить его и установить соединение при необходимости. При дальнейшем установлении соединения устройства могут обмениваться данными и командами. Некоторые устройства упаковывают какие-то данные о себе прямо в широковещательные пакеты. Это некоторым образом упрощает взамодействие с устройством, а также в числе прочих средств позволяет экономить энергию.

Сенсор Xiaomi умеет работать в двух режимах, и в Интернетах можно найти примеры работы как с широковещательными пакетами так и в режиме соединения. В найденном ранее руководстве используется вариант подслушивания широковещательных пакетов. Достаточно просто чтобы можно было быстро разобраться. Осталось только выяснить, что же не так.

Так что все-таки сломалось?

Код примера работает достаточно просто. При старте устройства инициализируется процесс сканирования устройств и устанавливается класс, функции которого будут вызываться при получении пакетов от устройств (advertising пакеты).

Пакеты от устройств обрабатываются в этой функции:

Очевидно, проблема где-то здесь.

Основное действие в этом коде происходит в конструкции switch, где проверяется значение 11го байта в service data массиве. Проблема только в том, что в моем случае массив данных был меньше 11 байт. Осталось выяснить почему.

Каждый advertising пакет помимо информации о возможности соединения с устройством может содержать пакет данных (payload). Этот пакет содержит расширенные данные об устройстве, также данные о сервисах, которые поддерживает устройство. В одном пакете может быть информация о нескольких сервисах. Типичный payload моих устройств выглядит так (это отдельные байты в шестнадцатиричной системе счисления):

Информация здесь кодируется достаточно просто. Первый байт (в примере 0x02) задает размер блока в байтах. За ним следует байт, который указыает назначение блока (подробно о типах блоков здесь). Затем следуют данные в зависимости от типа блока. Ну и дальше все повторяется (опять появляется длина блока) пока не закончится пакет данных.

Нас больше всего интересют блоки с типом 0x16, которые отвеают за service data, т. е. за данные, описывающие отдельные функции устройства. В нашем примере таких блоков 2:

Если присмотреться поближе, то можно заметить, что 11й байт в первом блоке очень похож, на тот, что ожидает наш switch (0x0A). А второй блок как раз похож на тот, слишком короткий блок, на который мы ссылались в начале. Похоже здесь и порылась собака. Похоже, что наш код ожидает видеть первый блок, а получает второй.

Почему так вышло?

Может у нас какие-то не такие устройства, а может у автора кода другие, но факт остается фактом, у нас оно так не работает. Самое время посмотреть в исходники библиотеки ESP32 для Arduino. Не будем вдаваться в подробности, но по этому коду видно, что getServiceData должен иметь параметр с индексом блока данных, который найден в пакете. Т. е. в библиотеке предусмотрена возможность того, что payload может содержать несколько блоков service data. Однако, не все так просто. Оказывается, что эта ветка изменений на момент написания этой заметки еще не опубликована (текущая версия релиза 1.0.4). И просто так скачав в Arduino IDE все необходимое для ESP32 через Boards Manager будет получена более старая версия библиотеки. И как раз в этой версии функция getServiceData() всегда возвращает последний блок service data. Это не очень приятно, но всегда можно использовать последнюю версию библиотеки. Главное, что мы смогли понять в чем была проблема.

Финальный код

С новой библиотекой решить проблему можно будет очень просто. Но не очень хочется создавать зависимость от новой версии библиотеки. Мы можем добавить простой код, который сделает то, что нужно нам нужно и так. Для этого нам нужен код, который в payload найдет нужный нам блок service data (в примере ниже функция findServiceData).

Вывод

Вся проделанная работа в очередной раз показыает, что не всегда код из Интернета хорошо работает. Будь-то пример для ESP32 или кусок кода со StackOverflow, крайне желательно все же понимать как оно работает. Всегда могут появиться не самые стандартные случаи, которые заставят код развалиться. Хорошо, когда это происходит в хобби-проектах, но, очевидно, никому не хотелось бы наталкиваться на подобные случаи в боевом коде. Давайте будем осторожны с использованием чужого кода, ну или по крайней мере попытаемся в нем разбираться.

Как-то длинновато получилось, но надеюсь, что кому-то это будет полезно. Со своей же стороны, надеюсь, что этому эксперименту будет продолжение, и данные температуры все же будут отправлены дальше.

Xiaomi датчик температуры и влажности

Если вы решили внедрить систему «умный дом», то наверняка ставили перед собой вопрос о автоматизации управления микроклиматом. Автоматическое включение кондиционера, когда становится жарко, или включить увлажнитель, когда воздух слишком сухой — звучит неплохо, правда? Но системе автоматизации необходимо собирать показатели текущего состояния воздуха. Для этого есть специальный датчик температуры и влажности Xiaomi temperature sensor.

Датчик температуры и влажности Xiaomi

Конечно, обычные ртутные градусники еще не скоро канут в лету, и современные электронные датчики не так широко распространены, но, без сомнения, будущее за современными гаджетами. Что может обычный термометр? Показать температуру. А что еще можно хотеть от термометра, выполняет свою функцию, да и ладно.

А что умеет датчик температуры от Xiaomi?

Во первых, это датчик температуры и влажности. Соответственно он может показать в два раза больше информации обычного градусника. Но, разумеется это не главное его достоинство. В первую очередь датчик можно подключить к системе «Умный дом», следить за показаниями удаленно и использовать эти показания в сценариях автоматизации.

А знать температуру, иногда, очень важно. Например дома, когда в комнате спит ребенок, температура должна быть постоянной. Или в серверной комнате, когда работа кондиционера жизненно важна для серверов.

Внешний вид датчика температуры и влажности Xiaomi

Как выглядит температурный датчик Xiaomi

Круглая таблетка из матово-белого пластика, диаметром 3.5 сантиметра и сантиметр в высоту, со значком термометра по центру. Снизу расположено отверстие для забора воздуха, а сверху кнопка сопряжения. В наличии синяя светодиодная индикация, которая поможет вам при сопряжении устройства.

Питается датчик от батарейки CR2032. Для замены батарейки необходимо повернуть заднюю крышку на 10 градусов против часовой стрелки.

Xiaomi mijia датчик температуры и влажности замена батарейки

Полные характеристики устройства:

Характеристики датчика температуры Xiaomi

Производитель Xiaomi, Mijia
Модель WSDCGQ01LM
Материал корпуса Матово-белый пластик
Рабочая температура -20℃—60℃
Питание Батарейка CR2032
Модули связи ZigBee
Цена ≈ 600 рублей.
Габариты (корпус) 35 мм x 10 мм
Вес 15 гр.

Датчик температуры и влажности Xiaomi

Несмотря на то, что температурный диапазон явно рассчитан на улицу, в инструкции указано, что использовать датчик можно только в помещении. Это объясняется отсутствием защиты от влаги, т. е. даже мелкий дождь может привести датчик в негодность.

Поскольку датчик температуры использует протокол ZigBee, для его работы необходим один из шлюзов экосистемы автоматизации Xiaomi. Без него он не сможет показать вам температуру.

Подключение датчика температуры в приложении MiHome

Подключаем устройство по стандартному сценарию: заходим в MiHome и нажимаем на добавление нового устройства вручную. Следуя инструкции, зажимаем кнопку датчика температуры на 5 секунд, после чего отпускаем. Индикатор должен мигнуть 3 раза синим цветом, а женский голос из шлюза оповестить о удачном подключении.

Xiaomi подключение датчика температуры и влажности

Стандартные, для подключения датчиков, настройки имени и местоположения:

Подключение датчика температуры Xiaomi

После подключения, разместите датчик в желаемом месте. Можно как приклеить на стену, так и просто положить его в любое место. Необходимо только учитывать, чтобы место было сухое и недоступное для влаги. Разумеется, нам захочется поместить датчик на улицу и если у вас частный дом, то крепим на крыльцо под крышу и не переживаем. А так кто на что горазд, кто то вырезает низ пластиковой бутылки и её накрывает датчик, кто то разрезал мячик для тенниса и засунул датчик внутрь. Тут нужно подходить индивидуально к каждому случаю.

А сейчас давайте зайдем в плагин датчика, найти его можно зайдя в шлюз, устройства и там находим датчик температуры. В зависимости от состояния окружающей среды, фон в плагине датчика температуры меняет цвет:

Изменение цвета фона в зависимости от температуры

В настройках плагина можно настроить отправку оповещения, когда показатели выходят за рамки комфортных, для этого необходимо активировать соответствующую настройку:

Напоминания датчика температуры Xiaomi

Динамику изменения температуры и влажности можно посмотреть на графике. Можно построить график за день, неделю или месяц:

Динамика температуры на графике Xiaomi

Сценарии для датчика температуры и влажности Xiaomi

В зависимости от показателей датчика, можно запускать сценарии. Всего доступно 4 действия:

1. Если температура выше заданного значения;

2. Если температура ниже заданного значения;

3. Если влажность выше заданного значения;

4. Если влажность ниже заданного значения.

Xiaomi датчик температуры в сценариях

Пороговое значение задается вами, при настройке сценария:

Датчик температуры Xiaomi значение для сценария

Действие на сценарий можно привязать практически любое, от простой отправки оповещения, до включения печки или кондиционера. В совокупности с дополнительными датчиками, сценарии можно усложнять. Например, включать увлажнитель воздуха при низкой влажности только в том случае, если закрыто окно.

При любой автоматизации, умным дом не назовешь, если он даже не знает температуру и влажность внутренних помещений, так что если у вас еще нет датчика температуры и влажности, то стоит задуматься о его приобретении.

Купить датчик температуры Xiaomi

Как и все устройства умного дома Xiaomi, датчик температуры проще всего заказать с доставкой в магазине FoxPox. ru за 850 рублей (для Москвы). Или же заказать с Aliexpress или GearBest.

Так же есть расширенная версия датчика температуры под брендом Aqara, способным контролировать еще и атмосферное давление. А если вам нужен датчик температуры с экраном, то стоит присмотреться к Mijia bluetooth гигротермографу.