Smart Message Language (sml) - Parsen der Stromzähler-Ausgabe

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Ekkehard
Beiträge: 98
Registriert: So 12. Feb 2023, 12:42
OS, Lazarus, FPC: Windows Lazarus 4.0, FPC 3.2.2
CPU-Target: 64-Bit
Wohnort: Hildesheim

Smart Message Language (sml) - Parsen der Stromzähler-Ausgabe

Beitrag von Ekkehard »

Hallo Ihr Lieben,
in Kurzform: Gibt es einen einfachen "Smart Message Language"-Parser (sml) in Pascal für Lazarus? Wenn ja, wo?

https://de.wikipedia.org/wiki/Smart_Message_Language

In Langform:
Ich beschäftige mich gerade mit meinem Stromzähler.
Hintergrund ist der Betrieb eines Balkonkraftwerkes, dessen Strom ich nicht verschenken, sondern möglichst vollständig selbst verbrauchen möchte. Dazu muss ich wissen, wieviel Strom im Augenblick verbraucht (=bezogen), bzw erzeugt (=ins Stromnetz abgegeben) wird, um entsprechend die Abgabe aus dem PV-System (Zendure, sehr einfache Kommunikation über TCP und WLAN) zu steuern.
Der verbaute Zähler, ein DZG DWSB20.2H, besitzt eine Infrarot-Schnittstelle, auf der etwa einmal pro Sekunde ein Datenpaket die aktellen Daten des Zählers seriell ausgegeben werden. Um das zu lesen habe ich mir eine kleine Hardware gebastelt, die ich an den seriellen Input-Pin eines Raspberry Pi angeschlossen habe und mittels eines kleinen Lazarus Programms einlesen kann.
Jetzt kommt endlich die Software ins Spiel.
Die Daten kommen in einem etwas seltsamen Binärformat. Hier eine schöne Seite, wo das erklärt wird: https://www.schatenseite.de/2016/05/30/ ... -auslesen/.

Das ist nicht schwer zur parsen, aber ich dachte, wenn das schon jemand mal gemacht hat muss ich das Rad ja nicht neu erfinden.

Andersherum, wenn ich sowas mache, dann könnte es ja auch für andere interessant sein.
Interessant auch deshalb, weil der Stromzähler die Daten liefert, für die man sonst extra Messtechnik kaufen müsste. Und so kann man mit einem billigen Raspberry einige Fliegen mit einer Klatsche fangen, weil das Teil dafür alles hat (serielle Schnittstelle, WLAN, Ausgabepins und vor allem die Lazarus-IDE :D ).
(Ja, es gibt fertige Leseköpfe mit WLAN, die man mit einem Magneten auf den Zähler "klebt", aber der Zählerschrank ist aus Metall und dann brauche ich einen extra Router. Außerdem kann der Lesekopf nicht mit dem PV-Modul reden, dass könnte nur wieder ein anderes Modul. Und am Ende gibt es immer noch, gerade Nachmittags überschüssigen Strom, den ich dann gerne für die Warmwassererwärmung verwenden würde. Da muss ich mit einigen Relais die drei Heizstäbe so schalten, dass ich die Zustände Aus, 330W, 500W, 660W und 1000W erzeugen kann. Alles läuft deshalb auf diesen Raspberry mit Lazarus hinaus)

Liebe Grüße aus Hildesheim

Hier noch ein kurzer kommentierter Ausriss aus den zu parsenden Daten, näheres im o.a. Link. Es fehlen insbesondere die Einleitungssequenz und der Schluss mit der Prüfsumme, hier geht es aber nur um einen kurzen Eindruck.

Code: Alles auswählen

xx00: xx xx xx xx 77 07 01 00   01 08 00 ff 64 1c 01 04 	....w␇␁␀  ␁␈␀.d␜␁␄
xx10: 72 62 01 64 da d0 f5 62   1e 52 ff 54 71 f4 5c 01 	rb␁d...b  ␞R.Tq.\␁
xx20: 77 07 01 00 02 08 00 ff   01 72 62 01 64 da d0 f5 	w␇␁␀␂␈␀.  ␁rb␁d...
xx30: 62 1e 52 ff 54 0e fd 93   01 77 07 01 00 10 07 00 	b␞R.T␎..  ␁w␇␁␀␐␇␀
xx40: ff 01 01 62 1b 52 fe 53   52 81 01 xx xx xx xx xx 	.␁␁b␛R.S  R.␁.....

77                       // 7x = Liste, x7 = 7 Einträge folgen:  Liste mit 7 Einträgen 
  07 01 00 01 08 00 ff   // 0x = Bytestring, x7 = 7 Bytes inklusive diesem: objName "1.8.0" akkumulierter Verbrauch = Zählerstand
  64 1c 01 04            // 6x=Unsigned Int, x4 = Länge inkl diesem, also 3 Bytes folgen: Status
  72                     // valTime 
    62 01                
    64 da d0 f5          
  62 1e                 // 6x=Unsigned Int, x2 = Länge inkl diesem, also ein Byte folgt: Unit 1E, sehr wahrscheinlich Wh
  52 ff                  // 5x=Signed Int: Scaler FF = -1
  54 71 f4 5c            // Value 0x71F45C = 7468124 => eine Stelle nach rechts 746812,4 => 746,8 kWh
  01                     // Ein leerer Bytestring: ValueSignature (OPTIONAL)
  
77                       // Liste mit 7 Einträgen
  07 01 00 02 08 00 ff   // ObjName "1.8.2" akkumulierte Einspeisung = Zählerstand
  01                     // Status (OPTIONAL) 
  72                     // valTime
    62 01 
    64 da d0 f5     
  62 1e                 // Unit 1E, sehr wahrscheinlich Wh 
  52 ff                 // Scaler FF = -1
  54 0e fd 93           // Value 0x0EFD93 = 982419  => eine Stelle nach rechts 98241,9 => 98,2 kWh
  01                    // ValueSignature (OPTIONAL)
  
77                      // Liste mit 7 Einträgen
  07 01 00 10 07 00 ff  // objName "1.16.7" Wirkleistung = aktueller Verbrauch
  01                    // Status (OPTIONAL)
  01                    // valTime (OPTIONAL)
  62 1b                 // Unit 1B, sehr wahrschinlich W 
  52 fe                 // Scaler FE = -2
  53 52 81              // Value 0x5281 = 21121 => zwei Stellen nach rechts 211,21W
  01                    // ValueSignature (OPTIONAL)

Antworten