Давно планировал внедрить в домашнюю автоматизацию датчик углекислого газа CO?. По соотношению цена/качество/функции/внешний вид лучшим для меня оказался Xiaomi ClearGrass Air Detector. Анализатор качества воздуха содержит датчики:
- CO?
- tVOC (летучие органические соединения)
- PM2.5
- Температуры
- Влажности
У ClearGrass качественный экран с большими углами обзора и аккумулятор на 6 часов автономной работы. Цена в районе 130$ за такой девайс переводит его в сегмент маст хэв! Большой обзор можно почитать на mysku.ru.
Анализатор можно добавить в родное приложение qingping+ или MiHome, в обоих случаях данные ходят через китайские сервера, что меня категорически не устраивало. Я решил разобраться, как можно получить данные с датчика локально без использования сторонних удаленных серверов.
1. Изучение трафика
Первым делом нужно было посмотреть, как ClearGrass передает данные в приложение qingping+. ClearGrass подключается к интернет по Wi-Fi. Чтобы слушать трафик я поднял на Raspberry Pi Wi-Fi точку доступа и запустил tcpdump собирать информацию:
sudo tcpdump -i wlan0 -vv -s0 -X -n port 1883 -s 65535 -w cleargrass.pcap
Анализ трафика показал, что ClearGrass обращается примерно к 5 разным IP адресам, а на 154.8.191.174 передает в незашифрованном виде по протоколу MQTT данные о качестве воздуха.
2. Заворачиваем трафик с ClearGrass на Raspberry Pi
Немного поэкспериментировав с iptables я пришел к такому правилу:
sudo iptables -i wlan0 -t nat -A PREROUTING -s 192.168.115.19 -j REDIRECT
Читается оно так: «Весь новый трафик на интерфейсе wlan0 от 192.168.115.19 (IP ClearGrass) перенаправлять локально». Я не большой знаток iptables, поэтому буду рад предложениям и улучшениям. В этом правиле есть минус, если анализатор уже подключен к Raspberry Pi, то трафик не будет перенаправляться. Сначала нужно запустить правило и только затем подключить ClearGrass к Raspberry Pi по Wi-Fi.
В итоге, подняв MQTT брокер mosquitto на Raspberry Pi я увидел, что анализатор передает данные о качестве воздуха раз в минуты.
3. MQTT нано-брокер на JS для домашней автоматизации Z-Way
В качестве сервера домашней автоматизации я использую Z-Way, который поддерживает множество Z-Wave устройств и возможность писать скрипты на JS.
К сожалению для Z-Way нет MQTT брокера на JS (в отличие от систем на базе node.js), поэтому я решил написать минимальные брокер, который только принимает данные от этого анализатора и ничего больше не умеет. Не читая особо документацию я посмотрел на общение между анализатором и mosquitto и составил следующую последовательность:
MQTT PROTOCOL
Connect Command (sensor -> broker)
0x10 - Connect Command
Connect Ack (broker -> sensor)
0x20 - Connect Ack
0x02 - Len 2
0x00
0x00 - Connection Accepted
Subscribe Request (sensor -> broker)
0x82 - 0b1000 0010; 0b1000 - Subscribe Request
Subscribe Ack (broker -> sensor)
0x90 - 0b1001 0000; 0b1001 - Subscribe Ack
0x03 - Len 3
0x00
0x08 - Message identifier 8
0x00 - Fire and Forget
Ping Request (sensor -> broker)
0xC0 - Ping Request
0x00 - Len 0
Ping Response (broker -> sensor)
0xD0 - Ping Response
0x00 - Len 0
Publish Message (sensor -> broker)
0x30 - Publish Message
0x96
0x04 - Len 534
В итоге родился простой JS скрипт:
mqttSocket.reusable();
mqttSocket.bind(1883);
mqttSocket.onrecv = function(data, host, port) {
var arr = new Uint8Array(data);
switch(arr[0]) {
// PING
case 0xC0:
console.log("---------- MQTT PING RESPONSE");
this.send([0xD0, 0x00]);
break;
// CONNECT
case 0x10:
console.log("---------- MQTT CONNECT ACK");
this.send([0x20, 0x02, 0x00, 0x00]);
break;
// SUBSCRIBE
case 0x82:
console.log("---------- MQTT SUBSCRIBE ACK");
this.send([0x90, 0x03, arr[2], arr[3], 0x00]);
break;
// PUBLISH
case 0x30:
var sensorPayload = self.getPayload(arr);
var sensorMessage = sensorPayload.substr(sensorPayload.indexOf('{'), sensorPayload.lastIndexOf('}'));
var sensorObj = JSON.parse(sensorMessage);
console.logJS("---------- MQTT MESSAGE:", sensorObj);
console.logJS("---------- CO2: ", sensorObj.data.co2);
self.vDevCO2.set("metrics:level", sensorObj.data.co2);
break;
}
};
mqttSocket.listen();
Конечно пока многое не учитывается, например в одной посылке, может прийти и PING, и MESSAGE, а я что-то из этого пропущу. Возможно в будущем я использую кодовую базу aedes для создания MQTT брокера для Z-Way. А на данный момент целью была принципиальная возможность получить локально данные о качестве воздуха с анализатора Xiaomi ClearGrass Air Detector и эта цель достигнута.
В перспективе хочу установить Z-Wave версию бризера TION S3 и управлять им основываясь на данных от ClearGrass.
Self_Perfection
На хабре упоминали, что можно снимать показания с помощью python-miio. Не пробовали такой подход?
aivs Автор
python-miio это то, что я попробовал первым делом. Чтобы заработала python-miio нужно из приложения mihome на телефоне вытащить токен, для этого на комп нужно сделать не зашифрованный бэкап, у меня выходило 50 Гб, столько места не было на компе и проще оказалось найти другой телефон. Я вытащил бэкап, с помощью токена подключился к 1 раз ClearGrass и второй раз уже не смогу. Я опять сделал бэкап и вытащил токен, но он уже был другой. Опять подключился успешно 1 раз, на второй раз уже не подключалось. Третий раз сделал бэкап, токен поменялся. Возможно это защита. Т.е. python-miio не работает с ClearGrass таким способом. Хотелось бы, конечно вариант попроще.
AkaZLOY
Есть модифицированная версия Mi Home, которая в информации об устройстве указывает токен.
aivs Автор
Это работает только на Android.
myz0ne
Токен можно вытащить при помощи mitm на телефон. Я использовал sslsplit. Тоже не хотелось запариваться с бэкапом.
osmanpasha
А как работает эта библиотека? Перехватывает трафик от устройства на китайский сервер? Т.е. при использовании библиотеки, что мешает устройству слать телеметрию в Китай?
aivs Автор
Устройство так и шлет данные в китай, но еще должно отвечать на локальные запросы.
tmin10
Я своим запретил выходить в интернет, разрешена только локальная сеть. Все данные у меня собираются в InfluxDB, что даёт визуализировать их в графане. Минус — сценарии тоже на питоне писать надо, родные только через облако работают.
amarkevich
Обновился на днях до версии 3.4.5_0142, заметил
Settings — Server
— China Mainland
— Abroad
Вот только непонятно, что во втором пункте имеется ввиду.
Envek
Кажется, должны быть варианты попроще, потому что вот тут люди брали готовую библиотеку на python и тащили данные к себе в прометей: https://habr.com/ru/post/482352/#comment_21085236
Возможно, есть вариант опрашивать сам девайс.
P.S> Меня уже опередили выше с таким же комментарием!
Mogwaika
Мне кажется проще и дешевле датчики на рассыпухе взять и описание к ним есть сразу…
aivs Автор
Ну нет, хороший дизайн, качественный экран, профессиональный датчик CO2, вряд ли самому дешевле получится. Еще и время сколько. Я в свое время уже надел датчиков, сейчас уже лень.
Mogwaika
за 130$ можно купить пару scd30 или гору s8… И зачем там экран, если вы хотите куда-то интегрировать?
aivs Автор
Так и экран полезен, иногда поглядываю на него.
Mogwaika
За сотку можно китайский смартфон купить и гору датчиков на него вывести.
sergeymakinen
Я правильно понимаю, что трюк с заворачиванием трафика можно в любом случае провернуть только после регистрации устройства у китайцев (чтобы оно начало отправлять данные)?
aivs Автор
Не могу точно сказать, как минимум я один раз проверил, что что анализатор работает с оригинальным приложением. А потом уже посмотрел трафик и он постоянно передает данные на китайский сервер, хотя сейчас анализатор ни к чему не привязан.