Nous travaillons localement avec le capteur CO₂ Xiaomi ClearGrass Air Detector, sans serveurs chinois



Pendant longtemps, j'avais prévu d'introduire un capteur de dioxyde de carbone CO₂ dans la domotique. En termes de prix / qualité / fonction / apparence, le détecteur d'air Xiaomi ClearGrass s'est avéré être le meilleur pour moi. L'analyseur de qualité de l'air contient des capteurs:

  1. CO₂
  2. tVOC (composés organiques volatils)
  3. PM2,5
  4. Température
  5. Humidité

ClearGrass a un écran de haute qualité avec de grands angles de vision et une batterie pour 6 heures d'autonomie. Le prix de l'ordre de 130 $ pour un tel appareil le traduit dans le segment incontournable! Une grande critique peut être lue sur mysku.ru .

L'analyseur peut être ajouté à l'application native qingping + ou MiHome , dans les deux cas, les données transitent par des serveurs chinois, ce qui ne me convenait absolument pas. J'ai décidé de trouver comment obtenir les données du capteur localement sans utiliser de serveurs distants tiers.

1. Étude du trafic


La première étape a été de voir comment ClearGrass transfère les données vers l'application qingping + . ClearGrass se connecte à Internet via Wi-Fi. Pour écouter le trafic, j'ai levé un point d'accès sur le Raspberry Pi Wi-Fi et commencé tcpdump pour collecter des informations:

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

L'analyse du trafic a montré que ClearGrass accède à environ 5 adresses IP différentes et, au 154.8.191.174, il transmet des données de qualité de l'air non cryptées à l'aide du protocole MQTT .



2. Nous emballons le trafic de ClearGrass sur le Raspberry Pi


Après avoir un peu expérimenté avec iptables, je suis arrivé à cette règle:

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

Il se lit comme suit: "Tout le nouveau trafic sur l'interface wlan0 de 192.168.115.19 (IP ClearGrass) doit être redirigé localement." Je ne suis pas un grand connaisseur des iptables, donc je serai heureux des suggestions et des améliorations. Il y a un inconvénient dans cette règle, si l'analyseur est déjà connecté au Raspberry Pi, le trafic ne sera pas redirigé. Vous devez d'abord exécuter la règle et ensuite seulement connecter ClearGrass au Raspberry Pi via Wi-Fi.

En conséquence, après avoir récupéré le courtier de moustiques MQTT sur le Raspberry Pi, j'ai vu que l'analyseur transmet des données sur la qualité de l'air une fois par minute.

3. Nano-courtier MQTT sur JS pour la domotique Z-Way


En tant que serveur domotique, j'utilise Z-Way, qui prend en charge de nombreux appareils Z-Wave et la possibilité d'écrire des scripts dans JS.



Malheureusement pour Z-Way, il n'y a pas de courtier MQTT dans JS (contrairement aux systèmes basés sur node.js), j'ai donc décidé d'écrire un courtier minimal qui n'accepte que les données de cet analyseur et ne peut rien faire d'autre. Sans lire particulièrement la documentation, j'ai regardé la communication entre l'analyseur et le moustique et j'ai compilé la séquence suivante:

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

En conséquence, un simple script JS est né:

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();

Bien sûr, bien que beaucoup ne soit pas pris en compte, par exemple, dans une prémisse, PING et MESSAGE peuvent venir, mais je vais manquer une partie de cela. Peut-être qu'à l'avenir, j'utiliserai la base de code aedes pour créer un courtier MQTT pour Z-Way. Et pour le moment, l'objectif était l'opportunité fondamentale d'obtenir localement des données sur la qualité de l'air à partir de l'analyseur Xiaomi ClearGrass Air Detector et cet objectif a été atteint.

À l'avenir, je souhaite installer la version Z-Wave du reniflard TION S3 et la contrôler en fonction des données de ClearGrass.

All Articles