MI Sensor mit BLE Gateway

Wer mit ESP8266 und anderen Prozessoren bastelt, wird sehr früh einfach Temperaturen und Feuchtigkeit messen und drauf kommen, dass ein Muster schnell erstellt ist aber die Verteilung in allen Räumen im Haus in Arbeit ausartet. Man braucht ein Gehäuse, einen Einbauplatz und Energieversorgung. Mittlerweile gibt es aber auch einige fertige und sehr günstige Sensoren, die diese Daten per BTLE einfach in den näheren Umkreis, und entsprechend unsicher, verteilen und mit einer schnöden Knopfzelle monatelang laufen. Ich vermeide zwar auch Batterien aber bei so geringem Energieverbrauch dürfte ein Netzteil die schlechtere Ökobilanz haben.

MI Sensor und andere

Mitte 2021 bin ich das erste mal auf kleine Sensoren aufmerksam geworden, die Temperatur und Luftfeuchtigkeit messen. Eigentlich wollte ich die billigen Teile mit CR2032-Knopfzelle und einer Laufzeit von bis zu 1 Jahre nur an einigen stellen im Haus an die Wand kleben, z.B. Bad, Waschraum, Tierställe. Für unter 5€ ist das sehr schnell gemacht. Eine Internet-Suche zeigt eine Vielzahl dieser Geräte:

Interessanterweise messen die nicht nur die Daten sondern senden diese auch per Bluetooth LE in regelmäßigen Abständen (ca. 10 Min) in die Umgebung. Mit einer passenden App auf dem Smartphone können Sie diese Daten auch aus einigen Metern Entfernung erhalten.

Ich finde es schon spannend, wenn solche Geräte per BTLE immer wieder senden und mit einer Knopfzelle so lange damit hinkommen.

ATCNetz-Firmware

Leider hat MI das Protokoll so implementiert, dass die Daten nicht "frei lesbar" sind. Die App muss sich mit dem BTLE-Gerät verbinden und handelt einen Schlüssel aus. Das erschwert eine eigene Weiterverarbeitung natürlich. Aber dann wird es interessant, denn Aaron Christophel hat nicht nur einen Weg gefunden, die Geräte zu analysieren, den Prozessor als "Telink TLSR Mikrocontroller" zu identifizieren und das Protokoll zu verstehen. Er hat gleich eine neue Custom Firmware geschrieben, die neben den gemessenen Daten auch diese Information unverschlüsselt per BTLE Meldung regelmäßig absetzt.

4$ Xiaomi thermometer custom firmware LYWSD03MMC BLE TLSR8251
https://www.youtube.com/watch?v=NXKzFG61lNs

Getoppt wird das ganze durch eine Webseite, über sie die per Chrom/Edge auf Basis der Chromium-Engine die vorhandenen MI-Sensoren direkt über Bluetooth neu flashen können.

Das hat etwas von Teufelszeug, dass ein Browser, der früher als "Sandbox" beworben wurde nun ohne Adminrechte direkt meinen Bluetooth-Stack nutzen kann, um andere Geräte zu steuern. Allerdings bedeutet das auch, dass speziell die Mi-Geräte keinen Schutz gegen "überflashen" haben, wenn man nur nahe genug am Gerät dran ist. Es gib keine Taste und auch keine zeitliche Beschränkung der Flashfunktion nach Einlegen der Batterie. Das design hat hier durchaus Lücken. In sensiblen Bereichen würde ich mich nicht auf die Messwerte verlassen.

Aber es ist wirklich so einfach:

  1. Firmware von https://GitHub.com/atc1441/ATC_MiThermometer/releases herunterladen
    Blog-Artikel http://atcnetz.blogspot.com/2020/09/custom-firmware-fur-das-4-xiaomi.html
    Mittlerweile verweist der Autor auf https://GitHub.com/pvvx/ATC_MiThermometer, wo jemand anderes die Firmware verbessert hat
  2. WebFlasher
    Ich nutz mittlerweile https://pvvx.GitHub.io/ATC_MiThermometer/TelinkMiFlasher.html
    Das Original findet sich noch auf https://atc1441.GitHub.io/TelinkFlasher.html
  3. Mit dem Thermometer verbinden

    Das Gerät sollt mit "LYWSD03" beginnen. Es kann etwas dauern, bis das Device erscheint, da es batteriesparend selten sendet.
  4. Thermometer "aktivieren".
  5. Firmware auswählen und flashen

Danach sehen Sie im Display fast keinen Unterschied. Nur manchmal erscheint unten ein Batterie-Symbol, was eher wie eine "Leere Batterie"-Warnung aussieht. Das LCD-Symbol wurde aber zweckentfremdet, denn anstatt der Feuchtigkeit wird dann der Batteriezustand in Prozent angezeigt. Sehr pfiffig gelöst.

Hinweis: Tasmota kann mittlerweile die original-Firmware und die ATC-Firmware lesen. Siehe unter Tasmota

OpenMQTTGateway

Wenn Sie nun ein oder mehrere dieser Geräte verteilt haben und diese munter ihre Daten per BTLE melden, dann muss natürlich noch ein Empfänger her. Ein Smartphone oder PC sind möglich aber schlecht automatisierbar. Aber es gibt auf Basis des ESP32-Chips gleich mehrere Projekte, die BTLE-Meldungen einsammeln und z.B. per MQTT an einen Server weiter leiten. Wir müssen also gar nicht mehr selbst etwas entwickeln, sondern eigentlich nur die passende Firmware laden, flashen, konfigurieren und in der Nähe der Sender platzieren. Je nach Größe der Wohnung reicht vielleicht ein Empfänger im Flur oder pro Stockwerk. Der ESP muss allerdings auch per WLAN eingebunden werden können.

Zuerst habe ich mir dazu das OpenMQTTGateway angeschaut, welches nicht nur BTLE einsammeln kann, sondern auch noch 433MHz, LoRa, IR, RS232 und zusätzliche Sensoren per I2C, 1-Wire oder Analog lesen und Aktoren auslösen kann.

Es kann direkt per Webseite auf den ESP32 geflasht werden. Da reicht ein M5Lite von M5Stack für unter 10€ mit einem USB-Netzteil oder am USB-Anschluss ihres Routers. (z.B. Fritz!Box (max. 900mA).


https://docs.openmqttgateway.com/upload/web-install.html

So langsam wird mir Chromium als Plattform unheimlich und angenehm zugleich. Natürlich werde ich hier nach dem USB-Port gefragt. Nach dem Neustart des Device findet sich wieder ein neues WLAN in ihrer Umgebung mit dem Namen "OpenMQTTGateway_ESP32_ATOM_BLE" o.ä.. Das Default-Kennwort ist "your_password". Wenn Sie sich mit ihrem Smartphone oder PC damit verbinden bekommen Sie eine IP-Adresse aus dem Bereich 192.168.4.x und das Gateway betreibt auf 192.168.4.1 einen minimalen Webserver zur Konfiguration des WLAN und der MQTT-Einstellungen. Nach den einmaligen Einstellungen ist das Gateway aber nicht mehr per Browser o.ä. erreichbar, sondern wird auch per MQTT konfiguriert.

Tasmota

Dann habe ich festgestellt, dass es die Tasmota-Firmware auch für den ESP32 samt Bluetooth-Support gibt. Also habe ich ein zweites ESP32-Board genommen und auch hier per Browser die Firmware installiert.


https://tasmota.GitHub.io/install/

Natürlich können Sie die Firmware auch manuell herunterladen und installieren

Bluetooth-Firmware
http://ota.tasmota.com/tasmota32/release/tasmota32-bluetooth.bin

Die Erstkonfiguration geht wieder über das temporär aufgespannte WLAN oder die serielle Konsole. In den Einstellungen zu Bluetooth musste ich dann noch die Checkbox setzen. Nach kurzer Zeit sind dann die BTLE-Beacons erschienen und sogar auf der Homepage wurden die Werte direkt angezeigt.

Das funktioniert natürlich nur für Datenformate, die Tasmota erkennt.

Tasmota versteht u.a. die Ergebnisse der ATC-Firmware aber meldete keine generischen BTLE-Meldungen. Das kann gut sein, weil man im MQTT-Service dann nur die "verstandenen" Geräte hat. Wer aber mit Tasmota einen BTLE-Scanner betreiben will, ist hier dann falsch.

Mittlerweile kann Tasmota aber auch die Werte der nativen MI-Firmware (Erkennbar am LYWSD03) lesen

Unter dem blauen "WAIT" führt ein Link zur Flash-Seite. https://tasmota.GitHub.io/ble_key_extractor/?cb=<ip des ESP32>%2Fmikey&mac=<macaddresse>

Wenn Sie sich beim WLAN vertippen und daher die WLAN Authentifizierung fehl schlägt, dann startet das Gateway wieder im Start-Mode und sie können die Daten erneut eingeben. Leider gibt das Gateway über die serielle Schnittstelle des ESP32 keine Diagnosedaten aus und erlaubt auch keine Steuerung. Da ist Tasmota etwas weiter. OpenMQTTGateway ist nur eine Firmware von vielen. Hier ein paar Links zu weiteren Projekten und ich bin sicher, es gibt noch mehr:

Natürlich gibt es aus kommerzielle Lösungen, die primär mit Support und fertiges Hardware werben. Die Links sind keine Empfehlung oder Referenz und nicht alle nutzen einen ESP32

Eigenbau

So schwer ist es aber auch nicht, sich per Arduino ein eignes Gateway zu bauen. Wir brauchen ja nur drei Komponenten

  • WLAN Verbindung
    Das muss man ja nicht "perfekt" mit einer Webseite und Setup-WLAN machen. Wenn ich per Arduino den Quellcode habe, kann ich die Daten im Code hinterlegen
  • BTLE-Scanner Code
    Auch hierzu gibt es viele Beispiele im Netz
  • MQTT-Verbindung
    Mittels fertiger Libraries ist auch diese Hürde schnell zu meistern

Der Vorteil eines eigenen Code ist, dass er viel schlanker sein kann, individuelle Anpassungen einfach möglich sind und man recht genau sieht, was der Code tut. Damit sie nicht bei 0 und einer leeren C++-Datei starten, lohnt sich schon mal der Blick in andere Projekte:

MQTT-Daten

Ich habe mir einfach Mosquitto installiert. Die Software gibt es als Docker-Container, Windows oder Linux Installationsquelle und kann auf einem kleinen Raspberry, aber oft auch auf ihrem NAS System laufen. Ich habe meine alte Synology DS216j dafür verwendet, die eh läuft und kein Stress mit der zusätzlichen Last hat.

Einen schnellen Einblick der zum MQTT-Server gesendeten Daten liefern ebenfalls kostenfreie Tools wie MQTTExplorer von Thomas Nordquist

Hier sehen Sie dann die Daten, wenn der MI-Sensor was sendet, Das MQTT-Gateway dies hört und korrekt verarbeitet an den MQTT-Server sendet.

  • Hier die Daten des Tasmota-Systems

    Tasmota schreibt jeden BTLE-Beacon immer nach "/Sensor". Wenn also mehrere Meldungen kommen, sehen Sie hier direkt immer nur die letzte Message. Vorherige Meldungen bekommen Sie aber über die History in MQTT Explorer

    Ihr Client muss also nicht nur das Topic sondern auch den Payload prüfen. Die MAC-Adresse des Device wäre nett aber hat dann Probleme, wenn sich die MAC-Adresse immer wieder ändert.
  • Sensordaten von OpenMQTTGateway
    Anders verhält sich das OpenMQTTGateway, welches einfach jede MAC-Adresse des BTLE-Geräts als Topic verwendet.

Ich kann ja problemlos auch mehrere MQTT-Gateways parallel betreiben. Es gibt keine Bindung zwischen dem BTLE-Gerät und einem Gateway.

Die Daten können auch mit dem Mosquitto_Sub.exe ausgewertet werden:

C:\Program Files\mosquitto>mosquitto_sub -h 192.168.178.10 -t tele/tasmota_156324/SENSOR
{"Time":"2021-10-04T00:40:01","ATC18fb56":{"mac":"a4c13818fb56","Temperature":23.4,"Humidity":50.0,"DewPoint":12.4,"Battery":83,"RSSI":-60}}
{"Time":"2021-10-04T00:40:13","ESP32":{"Temperature":42.8},"TempUnit":"C"}
{"Time":"2021-10-04T00:45:01","ATC18fb56":{"mac":"a4c13818fb56","Temperature":23.3,"Humidity":50.0,"DewPoint":12.3,"Battery":83,"RSSI":-64}}
{"Time":"2021-10-04T00:45:13","ESP32":{"Temperature":43.3},"TempUnit":"C"}
{"Time":"2021-10-04T00:50:01","ATC18fb56":{"mac":"a4c13818fb56","Temperature":23.3,"Humidity":50.0,"DewPoint":12.3,"Battery":83,"RSSI":-64}}
{"Time":"2021-10-04T00:50:13","ESP32":{"Temperature":43.3},"TempUnit":"C"}
{"Time":"2021-10-04T00:55:01","ATC18fb56":{"mac":"a4c13818fb56","Temperature":23.2,"Humidity":50.1,"DewPoint":12.3,"Battery":83,"RSSI":-63}}
{"Time":"2021-10-04T00:55:13","ESP32":{"Temperature":43.3},"TempUnit":"C"}
{"Time":"2021-10-04T01:00:01","ATC18fb56":{"mac":"a4c13818fb56","Temperature":23.3,"Humidity":50.0,"DewPoint":12.3,"Battery":83,"RSSI":-59}}

Auswerten

Ein anderer Akteur könnte sich nun direkt hier per "Subscribe" die Daten holen oder wie nutzen eine Brücke, die diese Daten direkt in eine Datenbank schreibt. Selbst das einfach MQTT-Explorer kann Werte als Grafik darstellen.

Sie werden sehr viele Seiten finden, die numerische MQTT-Daten in eine INFLUX-Datenbank übertragen und dann per Grafana o.ä. auswerten. Es gibt aber auch andere "Heimautomatisierungsprojekte", die direkte MQTT auslesen und visualisieren.

PRTG-Monitoring

Hinweis: Die PRTG MQTT-Funktion ist aktuell noch Beta und funktionierte bei mir auch noch nicht. Der Abschnitt wird überarbeitet, sobald ich eine Lösung gefunden habe.

Es muss aber nicht immer Grafana sein. Auch andere Überwachungssysteme können MQTT-Daten auslesen, da MQTT mittlerweile schon ein Quasi-Standard ist. Daher können Sie über den Weg z.B. auch die Umgebung in Servern und Räumen o.ä. überwachen. Damit kommen "Monitoring-Lösungen" als mögliche Konsumenten der Information ins Blickfeld. Einige können direkt MQTT sprechen, während andere Dienste einen Vermittler brauchen.

Ich habe meinen Sensor einfach per als Sensor in PRTG eingebunden. Zuerst schaue ich mir die Payload an, denn das Topic ist ja bei mir gleich und aus der Payload muss PRTG die Werte auslesen:

Entsprechend der Beschreibung habe ich dann hinterlegt:

Topic               : tele/tasmota_156324/SENSOR
Channel #1 JSONPath : $.ATC18fb56.Temperature
Channel #2 JSONPath : $.ATC18fb56.Humidy
Channel #3 JSONPath : $.ATC18fb56.Battery
Channel #4 JSONPath : $.ATC18fb56.RSSI

Allerdings konnte PRTG so eine Daten lesen. Im Logfile habe ich dann den Hinweis gefunden, dass Tasmota hier wohl zwei Messages sendet und PRTG nur die zweite Meldung liest.

2021-09-30 19:45:23.668365 DEBG TId   41676 Result of Sensor 2216> MQTT Client - PRTG_F7D14: Message received on topic: tele/tasmota_156324/SENSOR
2021-09-30 19:45:23.668365 DEBG TId   41676 Result of Sensor 2216> Received on topic "tele/tasmota_156324/SENSOR" with payload bytes: 140 and payload:
{"Time":"2021-09-30T20:45:22","ATC18fb56":{"mac":"a4c13818fb56","Temperature":23.4,"Humidity":47.0,"DewPoint":11.4,"Battery":83,"RSSI":-66}}
2021-09-30 19:45:37.697615 DEBG TId   41676 Result of Sensor 2216> MQTT Client - PRTG_F7D14: Message received on topic: tele/tasmota_156324/SENSOR
2021-09-30 19:45:37.697615 DEBG TId   41676 Result of Sensor 2216> Received on topic "tele/tasmota_156324/SENSOR" with payload bytes: 74 and payload:
{"Time":"2021-09-30T20:45:36","ESP32":{"Temperature":53.3},"TempUnit":"C"}
2021-09-30 19:46:09.015979 DEBG TId   20184 Result of Sensor 2216> #################### Enter sensor scan ####################
2021-09-30 19:46:09.015979 DEBG TId   20184 Result of Sensor 2216> Working with message: {"Time":"2021-09-30T20:45:36","ESP32":{"Temperature":53.3},"TempUnit":"C"}
2021-09-30 19:46:09.016978 DEBG TId   20184 Result of Sensor 2216> Processing channel 1 with json path: $.ATC18fb56.Temperature
2021-09-30 19:46:09.016978 DEBG TId   20184 Result of Sensor 2216> Error while processing channel #1 with json path: $.ATC18fb56.Temperature: The queried field is empty. Internal Message: $.ATC18fb56.Temperature
2021-09-30 19:46:09.016978 DEBG TId   20184 Result of Sensor 2216> Processing channel 2 with json path: $.ATC18fb56.Humidy
2021-09-30 19:46:09.016978 DEBG TId   20184 Result of Sensor 2216> Error while processing channel #2 with json path: $.ATC18fb56.Humidy: The queried field is empty. Internal Message: $.ATC18fb56.Humidy
2021-09-30 19:46:09.016978 DEBG TId   20184 Result of Sensor 2216> Processing channel 3 with json path: $.ATC18fb56.Battery
2021-09-30 19:46:09.016978 DEBG TId   20184 Result of Sensor 2216> Error while processing channel #3 with json path: $.ATC18fb56.Battery: The queried field is empty. Internal Message: $.ATC18fb56.Battery
2021-09-30 19:46:09.016978 DEBG TId   20184 Result of Sensor 2216> Processing channel 4 with json path: $.ATC18fb56.RSSI
2021-09-30 19:46:09.016978 DEBG TId   20184 Result of Sensor 2216> Error while processing channel #4 with json path: $.ATC18fb56.RSSI: The queried field is empty. Internal Message: $.ATC18fb56.RSSI
2021-09-30 19:46:09.017977 DEBG TId   20184 Result of Sensor 2216> #################### Exit sensor scan  ####################

Der Abstand beträgt 14 Sekunden aber aus mir nicht weiter verständlichen Gründen, parst PRTG nur den zweiten "falschen" String.

Das muss ich noch mal weiter beobachten, ob das nun eine Besonderheit/Bug der MQTT-Funktion von PRTG ist.

Location Services?

Die kleinen MI-Geräte senden zumindest mit der alternativen Firmware immer mit der gleichen MAC-Adresse. Damit lassen sich natürlich weitere Anwendungsfälle kontruieren,

  • Ich will wissen, wo ich bin
    Wenn mein Gerät die IDs der verschiedenen BLTE-Sender samt der Position kennt, kann über die Empfangsstärke in etwas die Entfernung ermittelt werden. Ich kann also für mich ermitteln, wo ich in etwas bin. Eine App auf dem Smartphone oder z.B. Teams könnten direkt den Ort ermitteln.
  • Was Haus will wissen, wo wer ist
    Wenn ich im Haus nun ausreichend BTLE-Scanner verteilt habe, weil diese sowieso im Zimmer etwas schalten oder Umgebungsdaten messen und nebenbei die Daten von BTLE-Sendern einsammeln, dann können Sie auch mein Smartphone oder ein BTLE-Token erkennen, welches ich bei mir trage und damit meine Position ermitteln. Ich bin zwar immer noch ein Freud der "Bewegungsmelder" zum Schalten von Licht im Keller aber wie wäre eine Annäherung an die Haustür, bei der eine intelligente Klingel dann mich erkennt, signalisiert und beim Druck auf den Klingelknopf die Tür öffnen statt zu klingeln?
  • "Verlust"-Meldung
    Besonders schützenswerte Gegenstände könne man aber auch mit einem BTLE-Token versehen, welche immer mal wieder eine Meldung absetzt. So könne ein System schnell Alarm schlagen, wenn ein Gerät nicht mehr "sichtbar" ist.

Lange Zeit habe ich BTLE keine große Bedeutung zugemessen aber mit dem MI-Device, welches sehr wenig Energie benötigt, ist das ein interessantes Spielfeld.

Weitere Links