Давно планировал внедрить в домашнюю автоматизацию датчик углекислого газа 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.