SML Protokoll identifiziren und zerlegen

wäre auch mein Ansatz.

Man übernimmt die interessanten Daten in Variablen evtl. dazu ein dirty flag ob gerade ein Empfang statt findet
und wenn der CRC richtig ist (der sollte sich ja zur Laufzeit mitrechnen lassen) - dirty wieder auf false setzen.

Oder wenn man es sich vom RAM Verbrauch leisten kann, je eine Variable für "letzter validierter Wert" und "eingegangener Wert - CRC prüfung ausständig". Dann kann man dem Anwender einfach immer die letzten validen Daten im API zurückgeben.

oder überhaupt:
Der Anwender "registriert" die für ihn interessanten OBIS-Codes und nur diese werden daher auch ausgewertet und zur Verfügung gestellt (oder "belegen RAM").

Hallo,
ich denke das ist ein bisschen schwierig, letztlich müsste man dazu erst die Längeangaben einlesen , dann die dazu gehörige Anzahl an bytes in einen kleinen buffer, den dann auswerten also eventuell mehrfach links schieben , und dann weitermachen.
Ich denke es gibt aber auch kaum mehr als 400-500 byte, Im Notfall kann man mit einem Probelesen die Länge ermitteln und dann den Sketch einmal neu durch den Compiler jagen. Wenn das nicht in einen UNO passt, muss halt was anderes her. Aber gehen wird das auch.

Das war auch mein Ansatz siehe #378

Heinz

Anfänglich war ich auch unsicher, ob ich die Daten gleich beim Einlesen auswerte oder erst nach Speichern in einem Feld. Mit einem ESP32 und damit mehr RAM fällt die Entscheidung für ein Feld natürlich leichter. Meine Argumente:

  1. Wie schon in #402 erwähnt, fällt die Bildung von Werten leichter, weil beim Feld die nächsten n Bytes leicht genutzt werden können, ist nur eine Schleife.
  2. Die CRC-Berechnung des ESP32 erwartet ein Feld zur Auswertung. Damit war für mich die Entscheidung endgültig gefallen.

Beim Einlesen suche ich nur nach Start- und Endesequenz und werte gleich die Prüfsumme aus. Ist diese falsch, lese ich weiter ein, ist sie richtig, starte ich die Auswertung.

Sollten die Nachrichten für einen UNO zu groß sein, sollte man einen µC mit mehr RAM wählen, kostet keine Reichtümer :slightly_smiling_face:

Au contraire, mon cher. :grin:

Der CRC berechnet die Checksumme sequentiell (CCITT16 - siehe Lammert Bies), und da der Rest streng hierarchisch ist, braucht man nur einen Stack für ein komplettes Paket, keinen Puffer. Man muss nur die CRC-Berechnung immer byteweise miterledigen mit jedem gelesenen Byte.

Nunc est bibendum, ich hatte Latein!

Kritische Fragen:

  1. Hast Du das schon mal auf einem UNO probiert?
  2. Ist die Berechnung auf einem UNO während des Mitlesens schnell genug, um das Mitlesen nicht zu stark zu bremsen?
  3. static uint16_t crc_tabccitt[256]; benötigt 500 Bytes Speicher, kein Gewinn, oder?

Wenn das auf einem UNO gut läuft, wäre es eine Überlegung wert :slightly_smiling_face:

  1. nein. Meine letzte Uno-Aktivität liegt Jahre zurück
  2. würde ich annehmen, das ist wenig Aufwand pro Schritt
  3. aber fix 500 Byte vorberechnet im PROGMEM, nicht dynamisch viel im RAM

Zu 1. Schade.
Zu 2. Ich auch wegen der Tabelle.
Zu 3. Ja.

Sieht nach einer Alternative aus, danke dafür :slightly_smiling_face:

Wenn man es richtig machen will, dann aber zweimal.
Einmal über die gesamte SML_Datei und einmal über die einzelne SML_Nachricht.

Ich habe mich im Übrigen auch von CCITT blenden lassen,

was ein Irrweg ist. Denn im nächsten Absatz heisst es:

(Quelle: SML-Feinspec V 1.0 - Darum will ich unbedingt nochmal in die Normen schaun...)

Aber zum Glück war ich nicht der Erste und habe mich jetzt für die Variante aus dem Thread CRC16 CITT Problem entschieden.

@agmue Ich habe mich auch für den Puffer entschieden. Da ich das für einen UNO kompiliere behalte ich den Speicher im Auge. :face_with_monocle:

Die Berechnung bleibt aber dennoch gleich, nur die Polynomwerte sind ggfs. andere.

Also ein Blick in die lib brachte nur großes Staunen, wie unterschiedlich gerechnet wird... :wink:
Im Übrigen wird dort mit einem 1024er Block gerechnet, In der Norm sollen es wohl 256 Werte sein..... (unreflektiertes höhrensagen)
Bei dem, was ich bisher gelesen habe, kann ich das bald beten.

Durch Probieren habe ich diese Berechnung, die seit mehreren Tagen funktioniert, für den ESP32 gefunden:

        // CRC-16/X25, poly = 0x1021, init = 0xffff, refin = true, refout = true, xorout = 0xffff
        crcWert = (~crc16_le((uint16_t)~(0xffff), smlArray, smlIdx - 1)) ^ 0xffff;

Also 16 Bit und X25. Die Tabelle steht im ROM, wenn ich es richtig verstanden habe.

Vermutlich weißt Du das aber längst :slightly_smiling_face:

#273 :slight_smile:

Bei mitlerweile über 400 Beiträgen ist mir die Übersicht abhanden gekommen :roll_eyes:

Umso besser, wenn Du sie noch hast.

Kurzer Zwischendstand. Ich habe nach mehr als 2 Jahren zum ersten Mal einen kompletten Tag - eigentlich sogar 2 - nicht mal Forum gelesen... Und auch sonst musste ich leider Abwege gehen.
Zudem bin ich festgebissen an der CRC und dem Versuch die SML-Elemente in struct's zu packen. Aber dazu mache ich was eigenes auf.
Da der TO mich auch wissen lies, das er derzeit eingeschränkt testen könnte, verzichte ich mal auf Zwischenlösungen und bau das komplett fertig.
Es wird hier also etwas ruhig bleiben.

Hier funktionierender Arduino-Parser für SML Daten: libSML - parsing Smart Meter Language protocol