Trabajamos con el sensor CO₂ Xiaomi ClearGrass Air Detector localmente, sin servidores chinos



Durante mucho tiempo planeé introducir un sensor de dióxido de carbono CO₂ en la automatización del hogar. En términos de precio / calidad / función / apariencia, el Detector de aire Xiaomi ClearGrass resultó ser el mejor para mí. El analizador de calidad del aire contiene sensores:

  1. CO₂
  2. tVOC (compuestos orgánicos volátiles)
  3. PM2.5
  4. Temperatura
  5. Humedad

ClearGrass tiene una pantalla de alta calidad con grandes ángulos de visión y una batería que dura 6 horas. ¡El precio en la región de $ 130 para un dispositivo de este tipo se traduce en el segmento imprescindible! Gran revisión se puede leer en mysku.ru .

El analizador se puede agregar a la aplicación nativa qingping + o MiHome , en ambos casos los datos pasan por servidores chinos, lo que categóricamente no me convenía. Decidí descubrir cómo obtener datos del sensor localmente sin usar servidores remotos de terceros.

1. Estudiar el tráfico


El primer paso fue ver cómo ClearGrass transfiere datos a la aplicación qingping + . ClearGrass se conecta a Internet a través de Wi-Fi. Para escuchar el tráfico, levanté un punto de acceso en el Raspberry Pi Wi-Fi y comencé tcpdump para recopilar información:

sudo tcpdump -i wlan0 -vv -s0 -X -n port 1883 -s 65535 -w cleargrass.pcap

El análisis del tráfico mostró que ClearGrass accede a aproximadamente 5 direcciones IP diferentes, y en 154.8.191.174 transmite datos de calidad del aire sin cifrar utilizando el protocolo MQTT .



2. Envolvemos el tráfico de ClearGrass en la Raspberry Pi


Después de experimentar un poco con iptables, llegué a esta regla:

sudo iptables -i wlan0 -t nat -A PREROUTING -s 192.168.115.19 -j REDIRECT

Se lee así: "Todo el tráfico nuevo en la interfaz wlan0 de 192.168.115.19 (IP ClearGrass) debe redirigirse localmente". No soy un gran conocedor de iptables, por lo que me complacerá recibir sugerencias y mejoras. Hay una desventaja en esta regla, si el analizador ya está conectado a la Raspberry Pi, entonces el tráfico no será redirigido. Primero debe ejecutar la regla y solo luego conectar ClearGrass a la Raspberry Pi a través de Wi-Fi.

Como resultado, después de recoger el agente de mosquitto MQTT en la Raspberry Pi, vi que el analizador transmite datos de calidad del aire una vez por minuto.

3. MQTT nano-broker en JS para domótica Z-Way


Como servidor de automatización del hogar, uso Z-Way, que admite muchos dispositivos Z-Wave y la capacidad de escribir scripts en JS.



Desafortunadamente para Z-Way no hay un agente MQTT en JS (a diferencia de los sistemas basados ​​en node.js), así que decidí escribir un agente mínimo que solo acepte datos de este analizador y no pueda hacer nada más. Sin leer particularmente la documentación, miré la comunicación entre el analizador y el mosquitto y compilé la siguiente secuencia:

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

Como resultado, nació un simple script 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();

Por supuesto, aunque no se tiene mucho en cuenta, por ejemplo, en una premisa, tanto PING como MESSAGE pueden aparecer, pero extrañaré algo de esto. Quizás en el futuro usaré la base de código de Aedes para crear un corredor MQTT para Z-Way. Y en este momento, el objetivo era la oportunidad fundamental de obtener datos locales sobre la calidad del aire del analizador Xiaomi ClearGrass Air Detector y este objetivo se logró.

En el futuro, quiero instalar la versión Z-Wave del respiradero TION S3 y controlarlo en función de los datos de ClearGrass.

All Articles