Stromzähler auslesen – Sagemcom Siconia Smarty BZ-plus mit Tasmota SML

Hardware:

  • Zählertyp: Sagemcom Smarty BZ plus von Digimeto / Sachsennetze
  • Hichi IR Lesekopf TTL-Variante (Bezug über diverse Kanäle möglich z.b. hier)
  • ESP D1 Mini

Software:

  • aktuelles Tasmota Image kompiliert mit Tasmocompiler auf Gitpod
  • Tasmota SML Treiber

Wichtige Referenzen:

Grundlagen – https://tasmota.github.io/docs/Smart-Meter-Interface/

Anleitung Zähler – DIGImeto_Sagemcom_smarty_Bedienungsanleitung_Web.pdf

Wissenswertes zum SML-Protokoll – http://www.stefan-weigert.de/php_loader/sml.php

SML-Decoder zur Script-Erzeugung – https://tasmota-sml-parser.dicp.net/

Die Geschichte:

Im www gab es leider keine Anleitung bzw. Tasmota Script, das auf meinen Zähler passt.

Der Zähler bietet Auslesemöglichkeiten über D0 und SML an. SML wird in 2 Varianten unterstützt (einfacher und erweiterter Datensatz). Ich entschied mich für die SML Variante mit erweiterten Datensatz. Ich fand es im sinnvollsten, einfach die periodisch gesendeten Telegramme abzugreifen, ohne irgendetwas senden zu müssen.

Und so ging ich auch vor. Vorab hatte ich bei Digimeto den Freischaltcode angefordert um die so genannte INFO-Schnittstelle im Einstellungsmenü des Zählers zu aktivieren. Weiterhin habe ich die PIN-Abfrage deaktiviert, um mir daraus eventuell resuliteriende Probleme zu ersparen. Das alles ist sehr gut in der Anleitung des Zählers beschrieben, weshalb ich darauf nicht weiter eingehen möchte. Nun versprach ich mir eine problemlose Inbetriebnahme des ganzen. Die Tasmota Auslesescripts für diese Methode sind ja sehr überschaubar und verständlich.
Ein Tasmota Image habe ich mit Hilfe des Tasmo-Compilers (GUI) selbst gebaut. Geflasht auf den ESP mit esptool auf einem Linux System. Alles ziemlich straight forward. Dafür gibt es Anleitungen en masse, deshalb hier keine Details.

Das erste Script mit einem dump des Zähleroutputs und dem WEB-SML-Parser erstellt, und zumindest hatte ich auf Anhieb einen Teilerfolg. Die aktuelle Wirkleistung konnte ich zuverlässig auslesen. Aber das wars dann auch. Ich kam einfach nicht an die Zählerstände ran und so ging ich in die Grundlagenforschung…

Auf dem Weg zum funktionierenden Script ist folgende Zerlegung des SML-Telegramms meines Zählers entstanden:

1b 1b 1b 1b #Escape Sequenz
01 01 01 01 #Start Version 1.0
76 #Liste mit 6 Einträgen (1. SML Nachricht in diesem Telegramm)
05 00 00 00 00 #transactionId: "0"
62 00 #groupNo:
62 00 #abortOnError:
72 #messageBody: Liste mit 2 Einträgen
65 00 00 01 01 #getOpenResponse:
76 #Liste mit 6 Einträgen
01 #codepage: ohne Wert
01 #clientId: ohne Wert
05 00 00 00 00 #reqFileId:
0b xx xx xx xx xx xx xx xx xx xx #serverID: (0b(HEX)=11Bytes Länge)
72 #refTime: ohne Wert
62 01 #choice: secIndex
65 02 cf 33 69 #Liste mit 9 Einträgen
01 #smlVersion: ohne Wert
63 be c4 #CRC Prüfsumme der zweiten Nachricht
00 #Ende der ersten SML Nachricht
76 #Liste mit 6 Einträgen (2. SML Nachricht in diesem Telegramm)
05 00 00 00 01 #transactionId: "1"
62 00 #groupNo:
62 00 #abortOnError:
72 #messageBody: Liste mit 2 Einträgen
65 00 00 07 01 #getListResponse:
77 #Liste mit 7 Einträgen
01 #clientId: ohne Wert
0b xx xx xx xx xx xx xx xx xx xx #serverID:
07 01 00 62 0a ff ff #ListName:
72 #Liste mit 2 Einträgen
62 01 #choice: secIndex
65 02 cf 33 69 #secIndex: (Uptime)
79 #Liste mit 9 Einträgen
77 #Liste mit 7 Einträgen
07 01 00 60 32 01 01 #Herstellerkennung vid
01 #status: -
01 #valTime: -
01 #Einheit: -
01 #scaler: -
04 53 41 47 #Ascii-UTF8-Wert: 0x534147 "SAG"
01 #valueSignature: ohne Wert
77
07 01 00 60 01 00 ff #Geräte-Indentifikation
01 #status: -
01 #valTime: -
01 #Einheit: -
01 #scaler: -
0b xx xx xx xx xx xx xx xx xx xx #Nicht weiter zerlegen s. Aufdruck Zähler
01 #valueSignature: ohne Wert
77 #Liste mit 7 Einträgen
07 01 00 01 08 00 ff #Totalregister Wirkenergie (Bezug) - name: WEBT
65 00 1c 01 04 #status: wert = "1835268" (Type zu status Unsigned32)
72 #valTime:
62 01 #type: Wert = "01" => SML_Time = "0x01" => secIndex
65 02 cf 33 69 #minOccurs: Wert = "47133545" => 4713545 s
62 1e #Einheit: 1e = "Wh"
52 ff #scaler: ff(integer)=-1(dezimal) -> 10^-1 = 0.1
69 00 00 00 00 05 5d 47 a7 #unsigned-Wert: 89999271 => 8999,9271 kWh, Type zu value Unsigned64
01 #valueSignature: ohne Wert
77 #Liste mit 7 Einträgen
07 01 00 01 08 01 ff #Tarifregister 1 Wirkenergie (Bezug) - name: WEB1
01 #status: -
72 #valTime: -
62 01 #Wert = "1"
65 02 cf 33 69 #Wert = "47133545"
62 1e #Einheit: 1e = "Wh"
52 ff #scaler: ff(integer)=-1(dezimal) -> 10^-1 = 0.1
69 00 00 00 00 03 07 f0 59 #Unsigned-Wert: 50851929 => 5085,1929 kWh
01 #valueSignature: ohne Wert
77 #Liste mit 7 Einträgen
07 01 00 01 08 02 ff #Tarifregister 2 Wirkenergie (Bezug) - name: WEB2
01 #status: -
72 #valTime: -
62 01 #Wert = "1"
65 02 cf 33 69 #Wert = "47133545"
62 1e #Einheit: 1e = "Wh"
52 ff #scaler: ff(integer)=-1(dezimal) -> 10^-1 = 0.1
69 00 00 00 00 02 55 57 4f #Unsigned-Wert: 39147343 => 3914,7343 kWh
01 #valueSignature: ohne Wert
77 #Liste mit 7 Einträgen
07 01 00 02 08 00 ff #Totalregister Wirkenergie (Lieferung) - name: WELT
01 #status: -
72 #valTime: -
62 01 #Wert = "1"
65 02 cf 33 69 #Wert = "47133545"
62 1e #Einheit: 1e = "Wh"
52 ff #scaler: ff(integer)=-1(dezimal) -> 10^-1 = 0.1
69 00 00 00 00 00 07 1c 7e #Unsigned-Wert: 466046 => 46,6046 kWh
01 #valueSignature: ohne Wert
77 #Liste mit 7 Einträgen
07 01 00 02 08 01 ff #Tarifregister 1 Wirkenergie (Lieferung) - name: WEL1
01 #status: -
72 #valTime: -
62 01 #Wert = "1"
65 02 cf 33 69 #Wert = "47133545"
62 1e #Einheit: 1e = "Wh"
52 ff #scaler: ff(integer)=-1(dezimal) -> 10^-1 = 0.1
69 00 00 00 00 00 05 de b0 #Unsigned-Wert: 384688 => 38,4688 kWh
01 #valueSignature: ohne Wert
77 #Liste mit 7 Einträgen
07 01 00 02 08 02 ff #Tarifregister 2 Wirkenergie (Lieferung) - name: WEL1
01 #status: -
72 #valTime: -
62 01 #Wert = "1"
65 02 cf 33 69 #Wert = "47133545"
62 1e #Einheit: 1e = "Wh"
52 ff #scaler: ff(integer)=-1(dezimal) -> 10^-1 = 0.1
69 00 00 00 00 00 01 3d ce #Unsigned-Wert: 81358 => 8,1358 kWh
01 #valueSignature: ohne Wert
77 #Liste mit 7 Einträgen
07 01 00 10 07 00 ff #Momentane Wirkleistung - name: MWL
01 #status: -
01 #valTime: -
62 1b #Einheit: 1b = "W"
52 00 #scaler: 0(integer)=0(dezimal) -> 10^0 = 1
59 00 00 00 00 00 00 02 0c #integer-Wert: 524
01 #valueSignature: ohne Wert
01 #listSignature: ohne Wert
01 #actGatewayTime: ohne Wert
63 47 ec #CRC Prüfsumme der zweiten Nachricht
00 #Ende der zweiten SML Nachricht
76 #Liste mit 6 Einträgen (3. SML Nachricht in diesem Telegramm)
05 00 00 00 02 #transactionId: "0"
62 00 #groupNo:
62 00 #abortOnError:
72 #messageBody: Liste mit 2 Einträgen
65 00 00 02 01 #getCloseResponse:
71 #Liste mit einem Eintrag
01 #? ohne Wert
63 2f 35 #CRC Prüfsumme der dritten Nachricht
00 #Ende der zweiten SML Nachricht
1b 1b 1b 1b #Escape Sequenz
1a 00 a9 b5 #1a + Füllbyte + CRC (2Bytes) des gesamten Telegrammes

Das dekodierte Telegramm deckt sich inhaltlich mit dem Handbuch des Zählers. Mehr gibts nicht.- Weitere oft nachgefragte Messwerte wie zum Beispiel „Leistung je Phase“ werden nicht ausgegeben. Da es sich um einen 2-Tarifzähler handelt gibt es die Zählerstände für die Tarife einzeln.

Ich hatte nun vor, die Smart Meter Seite mit den Erkenntnissen nochmal gezielt durchzuarbeiten. Und landete schließlich bei den special options. Bei special option 3 angekommen, durchfuhr mich eine Ahnung. Mit Hilfe dieser Option lässt sich die maximale Länge eines einzulesenden SML-Telegramms anpassen. Und das passte auch ins Bild. Ich hatte schone längere Zeit das Gefühl, dass der dump die Zahlen zwar enthält, aber der Tasmota Parser gar nicht alles einliest. Es kam gelegentlich dazu, dass Werte zwischen Decoder Zeilen hin und her zu springen schienen. Nun, ums kurz zu machen, die Zeile „1,=so3.512“ löste die Probleme.  Es ist nun alles auslesbar, was angeboten wird.

Hier das Script:

>D
>B
=>sensor53 r
>M 1
+1,3,s,0,9600,SAGBZ+
1,=so3.512
1,77070100010800ff@1000,Wirkenergie Bezug (tot),kWh,webt_kwh,3
1,77070100010801ff@1000,Wirkenergie Bezug (T1),kWh,web1_kwh,3
1,77070100010802ff@1000,Wirkenergie Bezug (T2),kWh,web2_kwh,3
1,77070100020800ff@1000,Wirkenergie Lief. (tot),kWh,welt_kwh,3
1,77070100020801ff@1000,Wirkenergie Lief. (T1),kWh,wel1_kwh,3
1,77070100020802ff@1000,Wirkenergie Lief. (T2),kWh,wel2_kwh,3
1,77070100100700ff@1,Momentane Wirkleistung,W,mwl_W,0
;1,77070100600100ff@#,Geräte ID,,did,0
;1,7707010060320101@#1x,Herstellerkennung,,vid,0
#

Geräte-ID und Herstellerkennung lese ich nicht aus. Dabei gab es auch noch manchmal Wertesprünge, deshalb auskommentiert.

Und hier das Ergebnis:

Viel Spaß beim Nachbasteln!