[Modul] SML-Counter zur Integration der Infrarotschnittstelle von Haushaltszählern

Hab die CRC-Prüfung fertig. Schicke ich dir heute Abend zu.
Kannst dann auch implementieren.

sehr cool :sunglasses:

V1.04 Neu: Checksummen-Test von @mischo22 ergänzt

Dank der super Unterstützung von @mischo22 hat das Modul jetzt auch einen Checksummen-Test. Dieser Test überprüft, ob der empfangene Datensatz fehlerfrei ist. Ist das nicht der Fall, so wird dieser verworfen und unabhängig vom eingestellten Aktualisierungsinterval der nächste eintreffende Datensatz ausgewertet.

Die Version ist wie immer zunächst als Beta verfügbar. Die Stable folgt in Kürze. Die V1.03 wird es nicht als Stable geben.

Grüße
Jürgen

Hab gerade die Beta getestet: funktioniert nicht.
Im Debuglog steht „SML-String not valid“

@Silberstreifen hast du das mal mit meinem String oben getestet?

Hallo Michael,
ja ich habe den String, den Du mitgeschickt und auch den Teilstring oben getestet und beide liefen bei mir einwandfrei durch.

Allerdings ist der gestern mitgeschickte String so ja nicht aus meinem Modul. Der hat noch die Startsequenz enthalten, die bei mir im Cutter entfernt und nur für die CRC-Prüfung ergänzt wird.

Kannst Du mir den String aus dem Modul-Debug schicken? Dann gucke ich, was da schiefläuft.

Grüße
Jürgen

Der CRC-Check benötigt den gesamten String incl Startsequenz „1b 1b 1b 1b“ und der CRC-Checksumme am Ende.
Sonst kann die Checksumme nicht berechnet werden, da die Startsequenz mit in die Checksumme fließt.

Du musst also „1b 1b 1b 1b 01 01 01 01“ wieder an die Daten vom Cutter vorstellen und dann das Ende suchen (Endekennung „1b 1b 1b 1b 1a“ + Füllbyte + 2x CRC-Bytes danach).
Wenn das zusammengebaut ist, damit weiterarbeiten.

Bitte warte noch mit einer Modul Einreichung: Von „stable“ sind wir noch weit entfernt.

Noch was:

Einige Geräte senden auch SML und Plaintext gemischt wie:

v1.4.6.7
Energy Master RTG
SML(...)

Daher kann immer noch was hinter der SML-Nachricht kommen, was der Cutter nicht abschneidet.

Also ich habe mal ein wenig mit dem Splitter gespielt und bin zum Entschluss gekommen, dass wir da nicht weiterkommen.

das Problem ist, das mal zwar den Splitter so einstellen kann, dass die Start- und Endesequenz erkannt wird, wir aber dann die CRC-Bytes danach nicht mehr haben.

Bei meinem ABL-Modul hatte ich das gleiche Problem.
Ich hatte das dann ohne Splitter gelöst.

Also Splitter weg, die Daten kommen vom COM-Port oder Client Socket direkt.

Der Ablauf ist wie folgt (bei Receive Data):
Empfangene Daten an einen Buffer anfügen.
Prüfen ob Startsequez „1b 1b 1b 1b 01 01 01 01“ gefunden wird.
Alles vor der Startsequenz entfernen.
Nun prüfen, ob die Endsequenz „1b 1b 1b 1b 1a“ gefunden wird.
Wenn ja, prüfen, ob danach noch weitere 3 Bytes vorhanden sind (mittels String länge).
Nun diesen String incl. der drei Bytes danach aus dem Buffer kopieren und auch dort löschen.
jetzt haben wir das komplette SML-Paket.

Das ist im Modul auch so implementiert.
Der Cutter schneidet die Startsequenz zwar raus. Diese ergänze ich dann aber wieder für die crc-Prüfung. Das funktioniert wunderbar.

ok, hast Du da mal einen Beispiel-Datensatz für mich?

So habe ich auch angefangen. Das ist aber keine gute Lösung, da der Cutter deutlich effizienter arbeitet als das PHP-Modul. Wenn Du das ohne Cutter machst, dann schaufelst Du Dir die gesamte Thread-Queue voll. Schwächere oder größere Systeme können damit überlastet werden.

Schicke mir mal problematische Datensätze aus dem Modul-Debug. Ich bin überzeugt davon, dass da noch eine Menge geht.
Grüße
Jürgen

Beispiel siehe oben…

Warum der Splitter effizienter sein soll, kann ich nicht nachvollziehen.
Der Macht auch nix anderes…

Die Daten kommen ja nicht Byteweise, sondern meist in einem Schwung von so 20 Byte und mehr.

Hier mein log:

01.02.2022, 12:29:02 |             Received | 76 09 00 13 00 00 00 32 6D 55 62 00 62 00 72 65 00 00 01 01 76 01 01 05 00 10 79 58 0B 0A 01 4B 46 4D 00 00 01 6A 32 72 62 01 65 00 10 79 58 62 01 63 11 2B 00 76 09 00 13 00 00 00 32 6D 56 62 00 62 00 72 65 00 00 07 01 77 01 0B 0A 01 4B 46 4D 00 00 01 6A 32 07 01 00 62 0A 7F 7F 72 62 01 65 00 10 79 58 74 77 07 01 00 60 32 01 01 01 01 01 01 04 4B 46 4D 01 77 07 01 00 60 01 00 7F 01 01 01 01 0B 0A 01 4B 46 4D 00 00 01 6A 32 01 77 07 01 00 01 08 00 7F 65 00 04 19 04 01 62 1E 52 03 69 00 00 00 00 00 00 00 00 01 77 07 01 00 02 08 00 7F 01 01 62 1E 52 03 69 00 00 00 00 00 00 00 20 01 01 01 63 5A 11 00 76 09 00 13 00 00 00 32 6D 57 62 00 62 00 72 65 00 00 02 01 71 01 63 3C 34 00 00 1B 1B 1B 1B 1A 01 29 54 

01.02.2022, 12:29:01 |                Error | SML-String not valid


Ich habe mal die Empfangenen daten von mir genommen und mal den CRC geprüft: Fehler!
Was ich gefunden habe, ist dass das vorletzte Byte (angeblich Füllbyte) nicht 0x00 ist, wie im Beispiel aus dem Internet, sondern 0x01.
Eventuell ist hier die Checksummenberechnung hier anders. werde das mal herausfinden…

Hier übrigends die offizielle Beschreigung des Protokolls:

Das kann nicht der Grund sein. Bei mir ist das Füllbyte 0x03 und die crc-Berechnung passt.

Das Byte gibt an, wie viele Füllbytes der Nachricht hinzugefügt wurden, damit die gesamte Nachricht ein vielfaches von 4 (Länge der Escape-Sequenz) ist. Das kann sich auch zwischenzeitlich ändern, je nach Nachricht.

hat also nichts mit der Prüfsumme zu tun.

Ich suche weiter…

Wieder etwas schlauer (Seite 68 in der BSI-Spezifikation):

Das Regelwerk wird wie folgt definiert:

Beginn, Ende sowie weitere Merkmale einer Nachricht werden über Escape-Sequenzen gekennzeichnet.

Eine Escape-Sequenz wird mit einer Escape-Zeichenfolge eingeleitet. An diese EscapeZeichenfolge schließt sich das der Nachricht hinzugefügte Merkmal (Beginn, Ende, …) an.

Tritt im Nutzlastdatenstrom selbst die Escape-Zeichenfolge an beliebiger Stelle auf, wird diese
selbst als Escape-Sequenz übertragen. In diesem Fall ist das der Nachricht hinzugefügte
Merkmal die Escape-Zeichenfolge (sie wird damit zweimal nacheinander übertragen).

Die Anzahl der Bytes im Nutzlastdatenstrom wird am Ende immer auf eine restfrei durch die
Anzahl der Bytes der Escape-Zeichenfolge teilbare Menge erweitert. Zur Erweiterung werden
jeweils Bytes mit dem Inhalt ‚00‘ (hex) verwendet.

Als Escape-Zeichenfolge wird die Byte-Kette ‚1b 1b 1b 1b‘ (Angabe in hex.) festgelegt.

ich ziehe den Hut. Diesen Abschnitt habe ich schon ein paarmal durchgelesen und verstehe ihn immer noch nicht… :unamused:

Ich versuche es mal zu erklären:

Am Anfang haben wir reine SML-Daten, ohne Escapesequenz am Anfang und ohne SML-Version (01 01 01 01).

Damit diese Daten sicher versendet werden können, werden nun diese gekapselt in
ein Transportprotokoll. Das geht wie folgt:

Als erstes werden die SML-Daten vorbereitet.
Diese müssen auf ein vielfaches von der Länge der Escapesequenz „verlängert“ werden.
Die Escapesequenz ist 4 Byte lang, daher müssen die SML-Daten ein vielfaches von 4 lang sein.
Dazu wird am Ende so lange 0x00 angefügt bis die Nachricht ein vielfaches von 4 lang ist.
Die Anzahl der angefügten Bytes merken wir uns für später.

Sollte in den SML-Daten bereits die Zeichenfolge der Escape-Sequenz „1B 1B 1B 1B“ enthalten sein, so wird diese doppelt übertragen => maskiert.
Aus „1B 1B 1B 1B“ wird „1B 1B 1B 1B 1B 1B 1B 1B“.

Nun bauen wir das Transportpaket. Dieses verpackt die vorbereiteten SML-Daten und sorgt für eine sichere Übertragung.

Eine SML-Transportpaket beginnt mit der Escape Sequenz „1B 1B 1B 1B“ und der Protokollversion „01 01 01 01“ als Startsequenz.

Danach kommen die vorbereiteten die SML-Daten von oben.

Am Ende folgt wieder die Escapesequenz gefolgt von einer Dateiende Sequenz, die folgenden Aufbau hat:

  1. Byte: „1A“
  2. Byte: Anzahl der hinzugefügten Füllbytes von oben
  3. Byte: CRC zur Sicherung des gesamten Pakets (ohne die CRC-Bytes)
  4. Byte: CRC zur Sicherung des gesamten Pakets (ohne die CRC-Bytes)

Das Dekodieren sollet wie folgt ablaufen:

  1. Ein SML-Paket extrahieren also vom Start „1B 1B 1B 1B 01 01 01 01“ bis 1B 1B 1B 1B 1A xx xx xx"
    Hier ist bereits das Problem, dass der Splitter dafür nicht verwendbar ist: Wir kennen nicht das Ende genau.
  2. Nun prüfen wir das Paket, ob es gültig ist. Also Checksumme am Ende überprüfen.
  3. Checksumme (2 Bytes am Ende) entfernen
  4. Letztes Byte (Anzahl Füllbytes) merken und entfernen
  5. Endesequenz entfernen, also „1B 1B 1B 1B 1A“ am Ende
  6. Startsequenz entfernen, also „1B 1B 1B 1B 01 01 01 01“ an Anfang.
  7. Maskierung entfernen: Suche nach „1B 1B 1B 1B 1B 1B 1B 1B“ und ersetze durch „1B 1B 1B 1B“
  8. Anzahl der gemerkten Füllbytes am Ende entfernen
  9. Nun ist das Paket wieder im Urzustand und kann geparst werden.

Ich hoffe das ist so verständlich.

OK, mit den SML-Beispielen aus dem Internet funktioniert meine CRC-Berechnung ohne Probleme.
Mit meinem Zähler zuhause aber nicht.
Die CRC-Berechnung ist aber korrekt.

Was ich aber gefunden habe:
Einige Hersteller implementieren die CRC-Prüfung etwas anders.
Hier Sind die Bytes gespiegelt oder invertiert, bevor der CRC berechnet wird.

@Silberstreifen Kannst du die CRC Erkennung deaktivierbar machen über die Konfigurationsseite der Instanz? Dann kann ich erstmal überhaupt prüfen, ob das dekodieren funktioniert.

Danke für die Aufschlüsselung. Ich glaube aber, dass wir uns das Leben gar nicht so schwer machen müssen. Bisher sind alle Deine Datensätze bei mir durchgelaufen und haben sinnhafte Ergebnissse geliefert. Das einzige, was aktuell nicht zu 100% funktioniert, ist der CRC-Check, richtig?

Wenn das so ist, dann müssen wir uns mal die Wahrscheinlichkeit angucken, dass ein Datensatz defekt ist und trotzdem durchläuft.

Der Anteil der für uns tatsächlich interessanten Daten liegt typischerweise bei ca. 20% Der Anteil der im Datensatz befindlichen Sprungadressen, Start- und Endsequenzen, etc. liegt auch bei ca. 20%. Die Wahrscheinlichkeit ist damit sehr gering, dass

  1. Nur genau ein Byte falsch gesendet wird
  2. Diese eine Byte genau in den relevanten Nutzdaten ist

Typischerweise sind defekte Datensätze an mehreren Stellen defekt. Und wenn eine Sprungadresse oder die Startsequenz defekt sind, wird der Datensatz sowieso als defekt aussortiert.

Ich würde die CRC-Erkennung deaktivierbar machen und fertig ist.
Grüße
Jürgen

oh, hat sich überschnitten. Ich bringe den Schalter in die nächste Beta.