Работаем с датчиком CO₂ Xiaomi ClearGrass Air Detector локально, без китайских серверов

от автора

Давно планировал внедрить в домашнюю автоматизацию датчик углекислого газа CO₂. По соотношению цена/качество/функции/внешний вид лучшим для меня оказался Xiaomi ClearGrass Air Detector. Анализатор качества воздуха содержит датчики:

  1. CO₂
  2. tVOC (летучие органические соединения)
  3. PM2.5
  4. Температуры
  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.

ссылка на оригинал статьи https://habr.com/ru/post/493220/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *