Как я данные с BLE-градусника от Xiaomi забирал

термометр и гигрометр xiaomi не подключается по. Предыстория: в качестве одного из хобби у меня случился «Умный дом». Хочется красивых устройств, но при этом ещё хочется свободы и приватности. Поэтому занимаюсь скрещиванием ужика Xiaomi с ёжиком…

Как я данные с BLE-градусника от Xiaomi забирал

Предыстория: в качестве одного из хобби у меня случился «Умный дом». Хочется красивых устройств, но при этом ещё хочется свободы и приватности. Поэтому занимаюсь скрещиванием ужика Xiaomi с ёжиком Home Assistant.

Для поддержания комфортных условий нам нужно знать, а что вообще у нас дома происходит. Короче говоря, нужны сенсоры. Их у Xiaomi есть много разных, но больше всего мне понравился квадратный градусник на электронных чернилах. Вот только он совсем не умный, в том смысле, что не предоставляет вообще никаких интерфейсов, кроме графического – ни тебе WiFi, ни BLE, ни ZigBee. Зато батарейки CR2032 хватает на несколько лет. Есть ещё версия с блютусом, но она чуть менее изящная – эдакий толстый блинчик.

И вот в начале весны был анонсирован новый датчик температуры/влажности, на электронных чернилах, с BLE, да ещё и с часами. Часы мне не особенно-то и нужны, а вот всё остальное немедленно подавило все рациональные доводы и градусник был заказан на одном из популярных интернет-магазинов, по предзаказу. Ехало оно ехало, и наконец приехало.

В приложение MiHome датчик добавился без проблем (у меня англоязычный интерфейс везде, с русской версией MiHome, говорят, были трудности перевода). Показывает текущие значения и историю изменения показаний.

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

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

Первый подход к снаряду

Для начала, открываем терминал на убунте и запускаем bluetoothctl. Видим следующее:

MJ_HT_V1 – это старый датчик температуры, LYWSD02 – новый. Разница в формате именования модели несколько настораживает.

Дальше надо как-то почитать, а какие данные вообще у нас могут быть получены. Открыл исходники библиотеки mitemp, которая используется в Home Assistant для получения данных со старого датчика. Там нашёл, что используется библиотека blewrap, которая, в свою очередь, является обёрткой над двумя питоновскими библиотеками для работы с BLE. Столько много слоёв мне ни к чему, будем использовать bluepy. Документация есть, её не много и не мало, читаем и пишем скрипт, который проходит по всем полям данных, которые есть на устройстве.

В целом, всё просто – BLE-устройство предоставляет набор сервисов, каждый из которых состоит из набора характеристик. Каждая характеристика может быть одного из 8 типов, для одной характеристики можно указать несколько типов одновременно. Сервисы и характеристики идентифицируются двумя способами – адресом в виде HEX-значения и UUID. С UUID мне работать как-то привычнее.

Итак я считал все характеристики для обоих датчиков, посмотрел на них и понял, что снова под маркой Xiaomi продаются устройства от совершенно разных производителей. Среди значений старого датчика было найдено «Cleargrass Inc», а в новом – «miaomiaoce. com». Структура сервисов и характеристик у этих двух датчиков также абсолютно разные, да и список характеристик у нового датчика длиннее в два раза. Тут стало понятно, что нужно писать свою собственную библиотеку для интеграции с датчиком (нет, я конечно сначала погуглил, может есть чего полезного по запросу LYWSD02, но ничего толкового гугл не выдал).

Как же всё-таки получить данные?

Среди имеющихся типов характеристик, кроме READ, есть ещё WRITE и NOTIFY. WRITE – для отправки данных на устройство, а NOTIFY – для получения данных. Есть ещё одновременно WRITE NOTIFY – устройство будет отправлять данные только после того, как на них подпишутся, отправив нужный байт командой WRITE.

Попытки сделать что-то руками не принесли никакого результата, был достигнут первый рубеж отчаяния, но в этот момент я обчитался статей про поделки на базе чипов от Nordic Semiconductors и поставил на смартфон программу nRF Connect. С её помощью я смог подписаться на все сервисы, которые предоставляло устройство, сохранил логи ответов и стал пытаться понять, что в них лежит.

Вот эти тройные стрелки активируют подписку.

Особенностью старого датчика было то, что данные о температуре и влажности приходили в виде UTF-строки, новый же всё отдавал в бинарном виде.

Подписка на уведомления

Чтобы получать данные с датчика, нужно отправить запрос на подписку. В библиотеке mitemp для этого отправлялись два байта на характеристику, но непонятно, откуда брать её Тут я посмотрел на то, как выглядит структура данных для старого датчика в nRF Connect и заметил, что нужный адрес указан для характеристики с данными, как некий дескриптор. Тогда я снова стал читать документацию к bluepy и понял, что адрес дескриптора легко можно получить из объекта характеристики. Осталось только написать класс с методом-колбеком, в который будут поступать данные из уведомления.

Отделяем зёрна от плевел

К счастью, только три характеристики были помечены как WRITE NOTIFY, при этом данные приходили с различной частотой и, эм. визуальными особенностями.

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

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

Предположим, то третья характеристика – это полезные данные о температуре и влажности. Для подтверждения гипотезы был проведён физический эксперимент – подошёл к датчику и грубо надышал на него. На дисплее резко увеличились значения данных, а в терминале – поменялись байтики. Ура, данные где-то рядом.

Разбор данных

Я обычно работаю с текстовыми данными (получи данные по HTTP в виде JSON/xml, положи их в файл или в базу), поэтому не очень понимал, как подступиться к задаче. Поэтому начал пытаться трансформировать данные разными способами, которые можно сделать из питона. Написал вот такую функцию-конвертилку и стал смотреть, как это соотносится с данными на экране датчика.

В консоль посыпались строчки разной степени непонятности, однако третий байт всегда был числом, и это число совпадало со значением влажности. Для верности я ещё раз подышал на датчик – и значения влажности на экране и в третьем байте изменились одинаково!

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

На пути к успеху

В этот момент я ещё раз посмотрел на описание датчика и увидел, что внутри стоит датчик от Swiss Sensirion. Наверно, стоило с этого начинать, но это же не наш метод. На сайте Swiss Sensirion была найдена пачка датчиков, и даташиты к ним. В даташите, кроме всего прочего была найдена формула для конвертации байт, передаваемых по шине I2C в число.

Но… Получались очень странные значения. Что-то типа -34.66, а у меня было явно теплее. От грусти и печали я даже вскрыл датчик и проверил, а правда ли там сенсор от Swiss Sensirion. Выяснилось, что правда, но с индексом SHTC3, и для него нужна чуть-чуть другая формула.

Однако, всё равно данные после преобразования даже близко не были похожи на реальные. Тут я ещё больше загрустил, открыл исходники библиотеки для SHTC3 от Adafruit и стал пытаться адаптировать код трансформации из C++ в питон. Вывел всё в табличку – сырые данные, преобразованную сишную структуру и результат.

Получил что-то такое:

Да… как-то холодно… Но, стоп, подождите, а что это за 2604? Это же оно, 26.0 градусов на экране! Для подтверждения гипотезы снова унёс датчик на батарею, проверил – значения совпадают.

В итоге, получаем такой код преобразования данных:

Эпилог

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

Сейчас данные передаются в Home Assistant, дальше нужно допилить код интеграции и, возможно, переписать её с bluepy на bleak, поскольку bleak использует async/await и лучше подойдёт для Home Assistant, написанного aiohttp.

Xiaomi Mijia 2: температура и влажность дома в одном устройстве

Друзья! Распродажа 11.11 на AliExpress для меня не прошла бесследно. Уже много чего приехало, а еще сколько ожидается… Вот и решил начать понемногу писать обзоры на новоприбывшую технику. Сегодня посмотрим на термометр-гигрометр Xiaomi Mijia 2 с Bluetooth. Даю обратную связь по прошествии недели использования.

Зачем он нужен?

Я выделяю две основные причины покупки себе такой игрушки:

  1. Следить за температурой и влажностью в доме . Если вы тоже немного техногик, или простого градусника стало не хватать – этот девайс и все покажет очень точно, и еще сохранит в телефоне, и покажет все изменения во времени во всех комнатах (если тоже брать несколько). Особенно актуально с началом отопительного сезона – когда жарко и воздух сухой. Отлично мотивирует к оптимизации домашнего климата. Ну и просто классная игрушка для мужиков (не зря входила в эту ежемесячную подборку).
  2. Собираем умный дом . Это прекрасный датчик для умного дома в экосистеме Xiaomi. Просела влажность – включит увлажнитель. Упала температура – включит обогреватель или нагреет батарею. С охлаждением у них вроде как тоже есть кондиционер, но лично мне его пока воочию увидеть у нас не удалось. В общем отличный старт с такой маленькой умной игрушки.

Где заказывал?

Как и сказал выше, заказал его на AliExpress здесь:

Отмечу, что очень непривычно быстро дошел до меня. Обычно посылки едут около 3 недель, эта умудрилась приехать через 10 дней после заказа. Еще один важный нюанс – цена. На момент моей покупки (у вас скорее всего цена будет другая, т. к. я брал еще и с купонами) одно устройство обходилось примерно в 400 рублей. НО если брать набором из 4 штук – весь комплект обойдется в 800 рублей (по 200 руб. за штуку). Разумеется, взял набор. Хоть и переплатил больше планируемого, зато обвешал всю квартиру датчиками, да еще и на подарок один остался. Да, это очень приятный подарок.

Xiaomi Mijia 2 - Комплект из 4 коробок

Что в комплекте?

  • Сам термометр-гигрометр.
  • Батарейка CR2032 (она установлена под крышкой).
  • Двусторонний скотч (очень приятное дополнение, можно сразу лепить куда угодно).
  • Инструкция (она на китайском, прикладывать сюда не буду, опишу как есть).

Xiaomi Mijia 2 - Комплектация

Как включить?

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

Xiaomi Mijia 2 - Батарейка

Внешний вид и использование

Как только появляются цифры, лепим в удобное место у себя дома и наслаждаемся видом:

Xiaomi Mijia 2 - На стене

Приятный белый матовый пластик – нигде не портит общий вид. Очень компактный (43x43x12.5 мм) и легкий. Постоянно включен (все видно отлично, батарейки по отзывам хватает на год работы) и не светится (по мне только хорошо, больше батарейка будет жить, а ночью можно зайти в приложение).

  • Температура. Измеряет до десятых градуса.
  • Влажность. В процентах.
  • Есть рожица.

Немного про рожицу. В нормальных условиях (температура 19-27 °C, влажность 20-85%) она по-китайски улыбается. Во всех остальных случаях эта «энгри бёрдс» начинает нервничать:

Рожица на термометре-гигрометре

Не используйте его как уличный, рабочий диапазон температур – 0-60 °C.

Приложение

Не забываем, что этот термометр-гигрометр на борту имеет модуль Bluetooth 4.2, а это значит, что его можно сопрягать с нашим телефоном с помощью приложения для экосистемы умного дома Xiaomi – Mi Home.

Качаем его в любом родном сторе:

  • Play Market
  • App Store

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

  1. Заходим в приложение и авторизуемся (если вы пользуетесь телефоном Xiaomi – тут уже все пройдет автоматом). Нажимаем вот на этот знак «плюсика»:

Mi Home - Добавление устройства

  1. В этом большом списке девайсов для умного дома ищем наш термометр:
  1. Будет произведен поиск устройства и подключение к нему:

Mi Home - Поиск устройства

Mi Home - Устройство Добавлено

  1. Выбираем комнату, в которой находится этот датчик (можно задать и свою):

Mi Home - Выбор комнаты

  1. Можно сразу же переименовать устройство (если у вас несколько – рекомендую):

Mi Home - Переименовывание устройства

Все. Можно уже работать с устройством. Вот так выглядит главный экран:

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

Показан текущая температура, влажность и график изменений. Если щелкнуть по кнопке «История» появится уже более подробная статистика – это оставляю на вас.

Чтобы попасть в настройки, на экране нашего градусника щелкаем вот по этим трем точкам:

Mi Home - Датчик температуры и влажности - Вход в настройки

Здесь уже можно переименовать устройство, выбрать ему заново комнату или поделиться с семьей. А еще именно здесь расположен пункт «Автоматизация», с помощью которого вы и можете управлять другими устройствами своего умного дома на основе показаний этого датчика:

Mi Home - Датчик температуры и влажности - Автоматизация

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

А за сим заканчиваю статью. Текущая ситуация в комнате не очень – температура под 26, влажность около 29, так что ожидаются и другие статьи по теме климата. До скорых встреч на нашем проекте WiFiGid!