Smart Message Language — Stromzähler auslesen

Die Augen des Stromzählers

Die Augen des Stromzählers

Gestern habe ich mich mal intensiv mit meinem Stromzähler auseinander gesetzt. Das ist ein ziemlich neumodisches Gerät, ein Iskra MT175. Dieses Modell verfügt über eine Infrarotschnittstelle (nach DIN EN 62056-21) mit der die Zählerstände ausgelesen werden, und das muss natürlich ausprobiert werden.

Zu dem Zweck habe ich mir eine Hardware gebastelt die die Daten auslesen kann. Dazu später mehr, in einem anderen Beitrag. Mein Zähler überträgt etwa alle zwei Sekunden einen Datensatz. Automatisch, ohne dass ich ihn darum bitten müsste. Wenn ich den auslese erhalte ich einen formschönen Haufen Hex-Code, ähnlich diesem:

Wie man unschwer erkennt habe ich private Daten anonymisiert. Lacht nicht! :-D

Nachdem ich da längere Zeit mit verbracht habe weiß ich mittlerweile ziemlich genau was da steht. Und damit andere einen besseren Einstieg finden schreibe ich das mal hier auf.

Die Sprache nennt sich Smart Message Language (SML). Es gibt auch Zähler die die Daten in anderen Formaten, oder direkt im ASCII-Format ausgeben. SML ist aber ein Standard, und wird von vielen Herstellern genutzt. Wie das funktioniert kann man zum Beispiel in der Technischen Richtlinie BSI TR-03109-1 beim Bundesamt für Sicherheit in der Informationstechnik nachlesen. Wenn man das tut kann man den Datensatz da oben tatsächlich lesbar machen:

Die ersten vier Bytes sind einfach eine Markierung für den Anfang der Übertragung, in der zweiten Zeile steht dass wir Version 1 des Protokolls lesen.

Als nächstes müssen wir ein wichtiges Konzept verstehen. Das erste Byte der folgenden Nachricht lautet ’76‘. Man muss das als Nibbles sehen, und bei Hex-Zahlen bedeutet das Ziffer für Ziffer. Das erste Nibble ‚7‘ können wir auf Seite 42 (natürlich ;-) ) des oben verlinkten Dokumentes nachschlagen. Da steht eine Tabelle mit einer Zeile ‚X111LLLL‘. Jetzt matcht das binäre ‚X111‘ auf das erste Nibble, also haben wir es hier mit einer Liste zu tun. Das zweite Nibble gibt die Länge an, wir erwarten also eine Liste mit 6 Elementen.

Das erste Byte der folgenden Zeilen ist jeweils nach dem gleichen Schema aufgebaut. In der Regel steht das erste Nibble für den Datentypen, das zweite für die Länge — merkwürdigerweise bei einfachen Datentypen die Länge inclusive dieses Längen-Bytes. Datentyp 0 in Zeile 4 ist laut Seite 42 ein Octet String. Die 5 sagt dass dieser Teil einschliesslich der Längenangabe 5 Bytes umfasst, wir erwarten nach der Länge also noch vier Bytes. Auf Seite 17 des Dokumentes steht dass hier eine Transaktions-ID kommen muss.

Nachdem das Prinzip klar sein sollte werde ich nicht mehr alles haarklein entschlüsseln. Das heisst: ich habe schon. Aber an dieser Stelle überlasse ich das mal dem geneigten Leser. :-)

Man sieht durch die Einrückung ziemlich deutlich dass man sich den Datensatz gut als Liste von Listen vorstellen kann. Außen wird eine Liste mit sechs Elementen angekündigt (76), darin stehen ein Octet String (beginnt mit 0, Zeile 4), zwei Unsigned Integer (6, Zeilen 5 und 6), eine weitere Liste mit zwei Elementen (72, Zeile 7), ein weiterer Unsigned Integer (6, Zeile 16) mit der Prüfsumme und eine Markierung für das Ende der Nachricht (00, Zeile 17). Die Liste mit den zwei Elementen enthält wiederum einen Unsigned Integer (6, Zeile 8 ) und eine Liste mit sechs Elementen (76, Zeile 9). Die meisten dieser sechs Elemente sind Octet Strings die samt des Längen-Bytes eine Länge von 1 haben (01), also leere Strings. Ein String (Zeile 12) enthält eine File-ID, einer (Zeile 13) die Server-ID. Letztere kann man auch direkt auf dem Gerät lesen, die ist aufgedruckt. Beruhigend. :-)

Jetzt wird es ernst: eine weitere Liste mit sechs Elementen (76), die ersten Zeilen entsprechen dem Block oben:

Enthalten ist eine Liste mit zwei Elementen (72, Zeile 22). Der erste Octet String (Zeile 23) gibt den Typ der Nachricht an, es ist ein getListResponse. Der wiederum besteht auf sieben Elementen (77, Zeile 24). Interessant ist hier vielleicht das vierte Element (72, Zeile 28. An dieser Stelle soll die aktuelle Zeit stehen, und die kann auf verschiedene Weise angegeben werden. Erklärt ist das auf Seite 22 des BSI-Dokumentes, dementsprechend haben wir es hier durch die 01 in Zeile 29 mit einem secIndex zu tun. In Zeile 30 folgt dann der Wert. Die Zahl 0x018A4D15 entspricht in etwa der Zeit die das Gerät hier eingebaut ist, das wird also eine Art Betriebsstundenzähler sein.

Die Liste die in Zeile 31 startet ist das fünfte Element der Liste aus Zeile 24. Und hier kommt der wirklich spannende Teil: die Messdaten. Naja, und ein paar Meta-Daten. Erst das Kürzel des Herstellers Iskra (ASCII-Codes in Zeile 38), dann nochmal die bereits bekannte Server ID. Die nächsten drei Elemente enthalten die verbrauchte Energie (die Kilowattstunden), sowohl als Summe als auch aufgesplittet in zwei Tarife — wenn man denn zwei Tarife hat.

Hier kommen wir übrigens zu einem Teil den ich noch nicht verstanden habe: in Zeile 50 wird ein Status angegeben. Wenn mir jemand sagen kann was der bedeutet: immer her damit! 0x0182 ist dezimal 386, darauf kann ich mir keinen Reim machen.

Die Energiewerte muss man übrigens durch 10.000 teilen um auf die kWh zu kommen die am Gerät angezeigt werden.

In Zeile 78 steht die aktuelle Leistung, also wie viel Watt tatsächlich in diesem Moment verbraucht werden. In Zeile 86 folgt ein ‚public key‘. Der steht auch auf dem Gerät, ich nehme an der ist relevant wenn der Zähler wirklich ’nach Hause telefoniert‘. Die SML-Kommunikation funktioniert nämlich nicht nur über die Infrarot-Schnittstelle, sondern bei Bedarf auch über die Stromleitung. So kann der Anbieter Verbrauchswerte ablesen ohne dass dafür jemand zu Besuch kommen muss.

Die beiden Werte in Zeile 88 und 89 sind optional und vervollständigen so die Liste die in Zeile 24 begonnen wurde.

Oh, noch ein interessanter Punkt zu Zeile 86: das Nibble ‚8‘ ist eigenlich eine 0, also wieder ein Octet String. Da aber das Most Significant Bit gesetzt ist wird daraus eine 8, und das bedeutet dass die Länge der folgenden Daten nicht nur durch das zweite Nibble — die 3 — angegeben wird, sondern zusätzlich durch das folgende Byte. Nützlich, denn mit nur einem Nibble könnte man maximal 15 Bytes ankündigen (nachdem eines für die Länge draufgegangen ist). So kommen wir auf 0x32 == 50 Bytes. Ausreichend also für 48 Bytes Public Key und zwei Bytes Längenangabe.

Es folgen noch eine Prüfsumme und das förmliche Ende der zweiten Nachricht:

Die dritte Nachricht ist einfach nur da um das Ende der Übertragung anzukündigen.

Zu guter Letzt folgt in Zeile 102 nochmal die vom Anfang bekannte Escape-Sequenz, dann 1A um wirklich die Nachricht abzuschließen und nochmal drei Bytes für eine Prüfsumme.

Jetzt noch was in eigener Sache: viele Blogs schließen ihre Artikel grundsätzlich mit einer Frage an die Leser, um Kommentare zu fischen. Ich finde das penetrant, und mache das in der Regel nicht. Aber nach diesem furztrockenen (!) Artikel erlaube ich mir das ausnahmsweise mal: bitte ein Handzeichen von allen die bis hier durchgehalten haben! Muss kein Lob sein, ein Hallo Welt genügt. :-D

119 Kommentare

  1. Super hilfreich. Danke. Hab ein paar Abende völlig planlos vor den binären Daten und der Norm vom BSI gestanden und nix kapiert. Jetzt gehts.

  2. Danke für die Einführung.
    Wir haben seit kurzem genau so einen Zähler wie Du. Und In Hinblick auf eine mögliche PV wollte ich mal für ein paar Wochen den Stomverbrauch protokollieren und in einer Grafik zu sehen, wie sich der Stromverbrauch bei uns so im Tages- und Wochenverlauf darstellt. Anscheinend zu naiv dachte ich, daß es dafür bereits 1001 fertige Lösungen zum mehr oder minder einfachen Nachbau gibt, am einfachsten etwas drauf stöpseln, nach ein paar Tagen an den PC anstöpfseln, Daten einlesen und feritg. Aber weit gefehlt. Anscheinend muß man immer das Rad erneut selbst erfinden und sich umfänglich in eine ungaubliche Menge unterschiedlichster Dinge einarbeiten, das würde ein Riesen-Pojekt und Aufwand werden. In das Volkszähler-Dingens reingeschaut und nur Bahnhof verstanden. dito bei vielen anderen Seiten. Und das alles nur um für kurze Zeit die Daten zu sammeln etc… och nee. Denn das ganze interessiert mich ja überhaupt nicht, ich will nur für einige Zet die Verbrauchswerte. Das ist doch kein Selbstzweck, warum soll ich mir ständig den Verbrauch aschauen. Die Zeit für die Neuerfindung des Rads habe ich nicht, bin ja nur Hobbyist, verdiene meine Brötchen anderweitig und muß die knappe Freizeit für Dinge verwenden, die wirklich wichtig sind und gemacht werden müssen. Schade.

  3. Wer eine super Lösung, die auch auf Anhieb funktioniert, für sein Smarten Stromzähler sucht, sollte mal nach dem GitHub Projekt: „sml2mqtt“ suchen.

      1. Die Doku ist wirklich absolut grottig. Wenn man sich mit Linux und/oder Docker nicht auskennt, hat man da verloren. Zur von sml2mqtt unterstützten Hardware und wie sie angeschlossen werden soll steht auch nichts drin.

  4. Dear Ronald,
    Thank you for your great article. I have used this knowledge to create a battery powered Arduino (Standalone Atmega328P to be precise) that reads out the data with an Infrared sensor. After that, it looks for the start sequence for my data of interest (1B 52 00 55) and converts the „Wirkleistung Total“ to decimal, after which it gets transmitted using a 433 MHz module. Many similar devices are available on the market. I found that commercial options either did not satisfy my needs, or they were too expensive. The „Volkszaehler“ (volkszaehler.org) is a great project, but it relies on an ESP, which uses too much power as I do not have a power socket near my power meter. I can highly recommend this way. Thanks a lot for your article.
    Arthur

  5. Danke! The this world and the „free“ Internet needs people like you!
    I have to transfer your knowledge now to a Holley that needs a signal every 2 min to avoid the PIN.

  6. Super Blog. Danke dafür!
    Ich habe nur noch ein Verständnisproblem: wo finde ich in dem HEX-Stream die SML Werte z.B. 1.8.0 wieder?
    Bei mir wurde ein Holley EHZ541 eingebaut. Da kann man mit eine Taschenlampe (lange/kurze Pulse) auf andere Ausgabewerte umschalten. Das müsste doch auch mit dem Sensor machbar sein. Nur die Ausgabe geht ja über /dev/ttyS0 mit 9600Baud wie soll ich da 2sek / 5sek Dauerlicht erzeugen???
    OK viele Fragen, aber der Winter ist ja noch lang zum Basteln.

    1. Danke fuer Dein Lob!
      Puh, bei den Fragen kann ich Dir leider nicht weiterhelfen. Ich habe mich damals intensiv mit dem Thema beschaeftigt und was gebaut. Das funktioniert, aber seitdem habe ich das nicht weiter bearbeitet…
      Und leider musste ich hier auch die Mailbenachrichtigung fuer neue Kommentare abschalten. So kann ich Dir nur raten Dich an ein passendes Forum zu wenden.

    2. Wenn du die Kommunikation über ein Microcontrollerboard (Arduino Nano / RPi pico etc.) abwickelst, kannst du ganz einfach den Pin, an dem die Sende-LED hängt, von UART auf OUTPUT setzen und die LED explizit ein- und ausschalten.

    3. Ich behalf mir beim Iskra MT631 damit, den optischen Tastkopf abzunehmen, mit der Taschenlampe die PIN einzugeben und „Inf“ (zusatzdaten) einzuschalten, und dann den Tastkopf wieder aufzusetzen.

  7. Vielen Dank für die Einführung in das am Ende doch recht „simple“ Format!

    Um evtl. die „Ratebasis“ auf ein etwas größeres Fundament zu setzen – die „Zeile 50“ bei uns sieht so aus:
    64 00 02 80
    Kann es evtl. etwas mit dem Umschaltzeitpunkt Tarif 1 / 2 zu tun haben?
    Die letzten Stellen der Server-ID – zumindest bei unserem Zähler – wenn man den Hersteller-Prefix weglässt – entspricht der Zähler-ID auf dem Typenschild (Hex Dec konvertieren).
    Was mir fehlt ist die „Zählernummer“ des Netzbetreibers – die hab ich auch nach mehrfachem Jonglieren der Ausgaben nicht auffinden können…

  8. Unter https://www.sw-bb.de/fileadmin/user_upload/seitenstruktur/wir-ueber-uns/netze-pflichten/veroeffentlichungen/messstellenbetrieb/mt175-bedienungsanleitung.pdf findet sich auf S.34 folgendes zum Statuswort:
    Länge: 2 Bytes. Verwendete Bits: 9, 8, 7, 1, 0 (alle anderen Bits sind 0)
    Bit 9 gesetzt: OBIS Tarif 2
    Bit 8 gesetzt: OBIS Tarif 1
    Bit 7 gesetzt: Zähler funktioniert oberhalb der Anlaufschwelle
    Bit 7 nicht gesetzt: Zähler im Leerlauf
    Bit 1 gesetzt: Telegramm wurde wegen des geänderten Energieregister-Wertes generiert
    Bit 1 nicht gesetzt: Telegramm ist synchron mit dem Zeitintervall generiert
    Bit 0 gesetzt: Fehler im Betrieb
    Bit 0 nicht gesetzt: kein Fehler

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

;-) :-) :-D :-| :-/ :-( :-P more »