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

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

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

Зато батарейки CR2032 хватает на несколько лет. Есть ещё версия с блютусом, но она чуть менее изящная – эдакий толстый блинчик.

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

Градусник Xiaomi lywsd03mmc. Прошивка и настройка его в Home Assistant.

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

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

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

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

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

[NEW] Controller 00:1A:7D:DA:71:13 fett [default] [NEW] Device 3F:59:C8:80:70:BE LYWSD02 [NEW] Device 4C:65:A8:DC:0D:AF MJ_HT_V1

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

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

from bluepy import btle mac = ‘3F:59:C8:80:70:BE’ p = btle.Peripheral(mac) for s in p.getServices(): print(‘Service:’, s.uuid) for c in s.getCharacteristics(): print(‘tCharacteristic:’, c.uuid) print(‘tt’, c.propertiesToString()) if c.supportsRead(): print(‘tt’, c.read())

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

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

Как ускорить телефон Xiaomi redmi 9 note

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

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

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

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

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

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

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

class MyDelegate(btle.DefaultDelegate): def handleNotification(self, cHandle, data): print(data) mac_addr = ‘3F:59:C8:80:70:BE’ p = btle.Peripheral(mac_addr) p.setDelegate(MyDelegate()) uuid = ‘EBE0CCC1-7A0A-4B0C-8A1A-6FF2997DA3A6’ # Метод всегда возвращает список, потому что может работать с диапазоном адресов ch = p.getCharacteristics(uuid=uuid)[0] # Получаем дескрипторы для характеристики desc = ch.getDescriptors(forUUID=0x2902)[0] # Значение байта, который нужно отправить был найден методом научного тыка desc.write(0x01.to_bytes(2, byteorder=»little»), withResponse=True) while True: p.waitForNotifications(5.0)

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

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

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

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

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

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

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

def parse(v): print([x for x in v]) print(».format(int.from_bytes(data, byteorder=’big’))) print(».format(int.from_bytes(data, byteorder=’little’)))

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

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

Xiaomi redmi note 8 global version что это

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

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

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

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

def handleNotification(self, cHandle, data): temp = data[:2] humid = data[2] unpacked = struct.unpack(‘H’, temp)[0] print(data, unpacked, -45 + 175 * unpacked / 2 ** 19, sep=’t’)

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

b’,n2′ 2604 -44.130821228027344 b’-n2′ 2605 -44.1304874420166 b’+n2′ 2603 -44.131155014038086 b’,n2′ 2604 -44.130821228027344

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

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

def handleNotification(self, cHandle, data): humid_bytes = data[2] temp_bytes = data[:2] humidity = humid_bytes temperature = struct.unpack(‘H’, temp_bytes)[0] / 100 print(temperature, humidity)

Эпилог

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

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

Ссылки:

  • Страничка датчика на mi.com
  • Документация к bluepy
  • Сенсор SHTC3
  • Сервисы и характеристики MJ_HT_V1
  • Сервисы и характеристики LYWSD02
  • Репозиторий с черновой версией интеграции в Home Assistant

Источник: habr.com

Работа с датчиком температуры Xiaomi Mijia BLE в Home Assistant

Ниже приводится пример подключения Bluetooth датчика температуры и влажности Xiaomi Mijia BLE MJ_HT_V1 (круглый с дисплеем) к контроллеру с установленным Home Assistant Core (см. Установка Home Assistant Core в виртуальное окружение python ).

Для подключения датчика необходимо определить его MAC-адрес и внести изменения в конфигурационный файл Home Assistant.

Определение MAC-адреса датчика

Включите датчик и расположите его рядом с контроллером или на небольшом расстоянии с прямой видимостью. Запустите утилиту bluetoothctl и включите режим сканирования Bluetooth устройств:

$ bluetoothctl [bluetooth]# scan on

Информация об обнаруженных устройствах будет выводиться в окно терминала.

Датчик отправляет данные примерно каждые 30 сек и информация от датчика должна появиться через некоторое время. Нас интересует устройство с идентификатором MJ_HT_V1:

[NEW] Device 4C:65:A8:D4:5E:BF MJ_HT_V1

Это и есть искомый датчик и его MAC-адрес — 4C:65:A8:D4:5E:BF .

Остановите процесс сканирования:

[bluetooth]# scan off

Вывести список найденных устройств:

[bluetooth]# devices Device 4C:65:A8:D4:5E:BF MJ_HT_V1

В данном списке также должно присутствовать искомой устройство:

Device 4C:65:A8:D4:5E:BF MJ_HT_V1

Выйдите из утилиты:

[bluetooth]# exit

Добавление датчика в Home Assistant

Home Assistant имеет встроенную поддержку датчиков Xiaomi Mijia BLE MJ_HT_V1 с помощью интеграции mitemp_bt.

В файл конфигурации .homeassistant/configuration.yaml необходимо добавить следующие строки:

sensor: — platform: mitemp_bt mac: «4C:65:A8:D4:5E:BF» name: living_room_wall_temp force_update: true median: 3 monitored_conditions: — temperature — humidity — battery

  • mac — MAC-адрес датчика.
  • name — Отображаемое в Home Assistant имя датчика.
  • force_update — Принудительно обновлять данные от датчика в Home Assistant даже если они не меняются.
  • median — Позволяет исключить ошибки от датчика (резкие изменения значения температуры и влажности). В данном примере передаются усредненные данные за 3 отсчета.
  • monitored_conditions — Параметры, которые нужно отслеживать. В данном примере это: температура влажность и заряд батарейки.
Лучшее оружие для Сяоми

После внесения изменений в файл конфигурации необходимо перезапустить сервер Home Assistant.

Источник: docs.jethome.ru

Подключение датчика Xiaomi LYWSD03MMC с стоковой прошивкой к Home Assistant.

В прошлой статье я описал, как прошить данный градусник LYWSD03MMC, как изменить его некоторые отображаемые параметры и как его добавить в Home Assistant с альтернативной прошивкой.

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

Итак ну приступим сразу к делу. Так как данный датчик у нас отправляет шифрованные послания на стоковой прошивке, нам необходим ключ для дешифрации данных. Чтоб получить данный ключ, нам необходимо:

  1. Зайти на сайт: https://atc1441.github.io/TelinkFlasher.html
  2. На данном сайте нажать кнопку “Connect” и найти в списке наше устройство, оно будет называться LYWSD03MMC.
  3. После подключения, необходимо нажать кнопку “Do Activation”. И появится следующее:

Вот нас какраз интересует Mi Bind Key. Копируем его.

Теперь переходим в Home Assistant.

Заходим в HACS. (Если не знаете что такое HACS и как его установить, то в этой статье я попытался описать данный процесс. Статья: http://psenyukov.ru/%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-hacs-%d0%b2-home-assistant/)

В HACS заходим в Integrations, далее нажимаем на “+” и в открывшемся окне ищем “Xiaomi passive BLE monitor sensor platform” И устанавливаем его. После установки в меню HACS->Integrations появится данная интеграция:

Теперь необходимо перезагрузить сервер. Настройки->Сервер->Перезагрузить.

После перезагрузки заходим в Configuration.yaml и Пишем следующее:

sensor: — platform: mitemp_bt rounding: True decimals: 1 period: 60 log_spikes: False use_median: False active_scan: False hci_interface: 0 batt_entities: False encryptors: ‘A4:C1:38:93:3B:A5′: ’71b0f8c2e9582b81d7c343874f65e4b5’ sensor_names: ‘A4:C1:38:31:6E:1A’: ‘Балкон’
encryptors: ‘A4:C1:38:93:3B:A5′: ’71b0f8c2e9582b81d7c343874f65e4b5’

Это первое значение: блютуз мак адрес нашего датчика. Второе значение это какраз ключ шифрования который мы получили с сайта и записали ранее.

Так как после добавления устройства, когда оно появится в системе Home Assistant у нее будет имя по mac адресу. Это не очень удобно. Поэтому блок ниже и служит, для того чтоб удобно описать наши датчики. В данном случае датчику присвоено имя “Балкон”

sensor_names: ‘A4:C1:38:31:6E:1A’: ‘Балкон’

Все после прописи датчика в configuration.yaml и перезапуска системы. Примерно через 10 минут наш датчик должен появиться в системе и называться как mi temperature Балкон и mi humidity Балкон. Все датчики добавленные через интеграцию “Xiaomi passive BLE monitor sensor platform” Будут начинаться на “mi“.

Какие же всетаки плюсы и минусы данного метода добавления устройства.

Плюс безусловно это то, что данные датчики смогут по прежнему работать в системе умного дома Mi Home параллельно с системой умного дома Home Assistant.

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

У меня таких 3 датчика. И сейчас 2 из них на стоковой прошивке, а один на альтернативной с интервалом показаний раз в 5 минут. Вот теперь я за ними понаблюдаю и выясню сильно ли частота изменения показаний влияет на разряд батарейки.

Данный способ интеграции в Home Assistant и разбор самого датчика до винтиков я постарался показать в данном видео:

Источник: psenyukov.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
Китай Покупай