Hallo, ich konnte mit Hilfe hier aus dem Forum mittels ESP01S Multicast- messages vom SMA Homemanager2 und Energymeter empfangen. Meine Beispiele liefert alles was in der Message steckt. Ich brauche aber nur paar bestimmte Werte daraus und bin jetzt dabei die Ausgaben zu durchforsten und nur das was für mich interessant ist auszuwählen. Dabei bin ich auf folgende Dinge gestoßen dir mir im Moment nicht ergründlich sind. - Ich bekomme einen Timestampwert. Welche Zeit ist das ? Epochtime wäre zu weit in der Zukunft. - Es gibt da eine OBIS Wert 0:73.4.0 , der ist in der SMA Doku zum Protokoll aber nicht aufgeführt. - dann gibt es am Ende noch paar Bytes die auch nicht dokumentiert sind. Hier ein Beispiel: 0 4 2 A0 0 0 0 1 defaultGroup=1 2 4C 0 10 60 69 1 74 protocolID=24681, susyID=372, serial=3011230234, timestamp=2572600805 0:1.4.0=49 0:1.8.0=506032560.00 ..... ..... 0:71.4.0=910 0:72.4.0=224305 0:73.4.0=758 144:0.0.0=Strange measurement skipped 2:13.6.82=Strange measurement skipped Hat da vielleicht jemand weitere Kenntnisse dazu oder Hinweise auf Dokumentation dazu und kann mir helfen? Das SMA Dokument zum Protokoll habe ich. Danke für sachdienliche Hinweise.
:
Bearbeitet durch User
Wie schon geschrieben: Bei mir läuft das über node-red, das Parsen des UDP-Packets hab ich in Javascript. Für deinen ESP-Beispielcode hab ich das KI-Gestützt in Arduino-C++ übersetzt. Ob da die Byteorder passt, ob irgendwelche integer-promotions den int64 kaputt machen, usw. bitte selber prüfen. Als MSP430-Entwickler sollten dir die C-Fallstricke an der Stelle ja bekannt sein. Für die Datenübertragung ESP->MSP430 ist das als Dezimalzahl eh "suboptimal", der liest das einfacher als HEX oder Binär... d.H. das ganze rumgerechne ist eher für den Menschen der an der Seriellen mitliest. Ansonsten, das ist meine Feld-Config:
1 | const WsToWh=1.0/3600.0; |
2 | |
3 | const felder={ |
4 | "0:1.8.0": { name: "Summe_Bezug", factor: WsToWh, db: true }, |
5 | "0:1.4.0": { name: "Wirkleistung_Summe_Plus", factor: 0.1 }, |
6 | |
7 | "0:2.8.0": { name: "Summe_Einspeisung", factor: WsToWh, db:true }, |
8 | "0:2.4.0": { name: "Wirkleistung_Summe_Minus", factor: 0.1 }, |
9 | |
10 | "0:3.8.0": { name: "Blindleistung_Summe_Saldo_Plus", factor: WsToWh }, |
11 | "0:3.4.0": { name: "Blindleistung_Summe_Plus", factor: 0.1 }, |
12 | |
13 | "0:4.8.0": { name: "Blindleistung_Summe_Saldo_Minus", factor: WsToWh }, |
14 | "0:4.4.0": { name: "Blindleistung_Summe_Minus", factor: 0.1 }, |
15 | |
16 | "0:9.8.0": { name: "Scheinleistung_Summe_Saldo_Plus", factor: WsToWh }, |
17 | "0:9.4.0": { name: "Scheinleistung_Summe_Plus", factor: 0.1 }, |
18 | |
19 | "0:10.8.0": { name: "Scheinleistung_Summe_Saldo_Minus", factor: WsToWh }, |
20 | "0:10.4.0": { name: "Scheinleistung_Summe_Minus", factor: 0.1 }, |
21 | |
22 | "0:13.4.0": { name: "Leistungsfaktor", factor: 0.001 }, |
23 | |
24 | // dieser Block wiederholt sich für jede Phase:
|
25 | "0:21.8.0": { name: "Summe_L1_Bezug", factor: WsToWh }, |
26 | "0:21.4.0": { name: "Wirkleistung_L1_Plus", factor: 0.1 }, |
27 | "0:22.8.0": { name: "Summe_L1_Einspeisung", factor: WsToWh }, |
28 | "0:22.4.0": { name: "Wirkleistung_L1_Minus", factor: 0.1 }, |
29 | "0:23.4.0": { name: "Blindleistung_L1_Plus", factor: 0.1 }, |
30 | "0:24.4.0": { name: "Blindleistung_L1_Minus", factor: 0.1 }, |
31 | "0:23.8.0": { name: "Blindleistung_L1_Saldo_Plus", factor: WsToWh }, |
32 | "0:24.8.0": { name: "Blindleistung_L1_Saldo_Minus", factor: WsToWh }, |
33 | "0:29.4.0": { name: "Scheinleistung_L1_Plus", factor: 0.1 }, |
34 | "0:30.4.0": { name: "Scheinleistung_L1_Minus", factor: 0.1 }, |
35 | "0:29.8.0": { name: "Scheinleistung_L1_Saldo_Plus", factor: WsToWh }, |
36 | "0:30.8.0": { name: "Scheinleistung_L1_Saldo_Minus", factor: WsToWh }, |
37 | "0:31.4.0": { name: "Strom_L1", factor: 0.001, db: true }, |
38 | "0:32.4.0": { name: "Spannung_L1", factor: 0.1, db: true }, |
39 | "0:33.4.0": { name: "Leistungsfaktor_L1", factor: 0.001 }, |
40 | |
41 | "0:41.8.0": { name: "Summe_L2_Bezug", factor: WsToWh }, |
42 | "0:41.4.0": { name: "Wirkleistung_L2_Plus", factor: 0.1 }, |
43 | "0:42.8.0": { name: "Summe_L2_Einspeisung", factor: WsToWh }, |
44 | "0:42.4.0": { name: "Wirkleistung_L2_Minus", factor: 0.1}, |
45 | "0:43.4.0": { name: "Blindleistung_L2_Plus", factor: 0.1 }, |
46 | "0:44.4.0": { name: "Blindleistung_L2_Minus", factor: 0.1 }, |
47 | "0:43.8.0": { name: "Blindleistung_L2_Saldo_Plus", factor: WsToWh }, |
48 | "0:44.8.0": { name: "Blindleistung_L2_Saldo_Minus", factor: WsToWh }, |
49 | "0:49.4.0": { name: "Scheinleistung_L2_Plus", factor: 0.1 }, |
50 | "0:50.4.0": { name: "Scheinleistung_L2_Minus", factor: 0.1 }, |
51 | "0:49.8.0": { name: "Scheinleistung_L2_Saldo_Plus", factor: WsToWh }, |
52 | "0:50.8.0": { name: "Scheinleistung_L2_Saldo_Minus", factor: WsToWh }, |
53 | "0:51.4.0": { name: "Strom_L2", factor: 0.001, db: true }, |
54 | "0:52.4.0": { name: "Spannung_L2", factor: 0.1, db: true }, |
55 | "0:53.4.0": { name: "Leistungsfaktor_L2", factor: 0.001 }, |
56 | |
57 | "0:61.8.0": { name: "Summe_L3_Bezug", factor: WsToWh }, |
58 | "0:61.4.0": { name: "Wirkleistung_L3_Plus", factor: 0.1 }, |
59 | "0:62.8.0": { name: "Summe_L3_Einspeisung", factor: WsToWh }, |
60 | "0:62.4.0": { name: "Wirkleistung_L3_Minus", factor: 0.1 }, |
61 | "0:63.4.0": { name: "Blindleistung_L3_Plus", factor: 0.1 }, |
62 | "0:64.4.0": { name: "Blindleistung_L3_Minus", factor: 0.1 }, |
63 | "0:63.8.0": { name: "Blindleistung_L3_Saldo_Plus", factor: WsToWh }, |
64 | "0:64.8.0": { name: "Blindleistung_L3_Saldo_Minus", factor: WsToWh }, |
65 | "0:69.4.0": { name: "Scheinleistung_L3_Plus", factor: 0.1 }, |
66 | "0:70.4.0": { name: "Scheinleistung_L3_Minus", factor: 0.1 }, |
67 | "0:69.8.0": { name: "Scheinleistung_L3_Saldo_Plus", factor: WsToWh }, |
68 | "0:70.8.0": { name: "Scheinleistung_L3_Saldo_Minus", factor: WsToWh }, |
69 | "0:71.4.0": { name: "Strom_L3", factor: 0.001, db: true }, |
70 | "0:72.4.0": { name: "Spannung_L3", factor: 0.1, db: true }, |
71 | "0:73.4.0": { name: "Leistungsfaktor_L3", factor: 0.001 } |
jeweils mit Namen und Umrechnungsfaktor (Zählerwerte sind in Wattsekunden, Spannungen in 0.1V usw), das "db"-Flag markiert die Werte die ich zur Auswertung in der Datenbank speichere. Der Datenblock für jede Phase ist immer gleich, nur um 20 verschoben, startet bei 21, 41, 61. So kommst du auch ohne explizite Dokumentation auf den 0:73.4.0 er Wert. Was das 144er Feld bedeutet, weiß ich auch nicht. und "2:13.6.82" macht wenig Sinn. Könnte sein, dass da der Parser-Code irgendwie aus dem Tritt gekommen ist, und die Feldgrenzen nicht mehr richtig erwischt. Evtl. wegen falscher Länge des 144er Feldes davor? Wenn die Werte danach nicht interessieren, könntest du die Bearbeitung auch gleich an der Stelle abbrechen. Und der Timestamp sagt bei mir auch nix aus, kommt auch über Minuten immer derselbe Wert.
Danke Ernst für die erneute Hilfe! Ohne deine Unterstützung und Vorbereitung wäre ich nicht soweit gekommen. Da ich jetzt sowohl die serielle Schnittstelle in beiden Richtungen und einen TCP Server betreiben und auch noch die Multicast Messages mitlesen kann, gebe ich meine AT-FW Version auf. Der MSP430 bleibt natürlich. Diese eigene ESP01S FW-Version erleichtert das Ganze ungemein. Mit der Darstellung der Multicast Messages oben komme ich weiter, danke für die ausführliche Beschreibung. Zu 144:0.0.0 habe ich was in der Doku EMETER-Protokoll-TI-de-10.pdf gefunden. Wird als Softwareversion mit 4 Byte angegeben. Der Timestampwert zählt bei mir schon hoch, deshalb dachte ich zuerst an Epochtime, aber da wäre heute der 12. April 2053. Wäre schön gewesen wenn man daraus noch die Uhrzeit ermitteln könnte. Habe jetzt wieder neues "Futter" . Danke nochmals für die äußerst hilfreich Unterstützung!
:
Bearbeitet durch User
Bot N. schrieb: > Zu 144:0.0.0 habe ich was in der Doku EMETER-Protokoll-TI-de-10.pdf > gefunden. Wird als Softwareversion mit 4 Byte angegeben. Beitrag "Re: ESP01S: TCP Server und UDP Multicast" Dann also ein
1 | } if (index==144) { |
2 | // Optional: Versionsnummer auslesen... aber interessiert die?
|
3 | offset += 4; |
vor dem
1 | } else { |
2 | // Strange
|
ergänzen... dann sollte auch das "2:13.6.82" - Feld weg sein.
:
Bearbeitet durch User
Danke, nein , Versionsnummer und vieles andere interessiert nicht. Mir ging es nur ums Verständnis der Daten. Grüße und schönes WE
:
Bearbeitet durch User
Hi, habe dank der 2 Beiträge hier, es geschaft meinen Home Manger 2.0 auzulesen. Habe noch einen Punkt: Mein Timestamp ist negativ und zählt somit runter Richtung 0. -1482800258#Leistung=699.40 -1482799263#Leistung=715.50 -1482798268#Leistung=722.80 -1482797263#Leistung=710.50 @Bot N.: Könntest du mir deinen ESP Code zukommen lassen zum Vergleich?!
1 | #include <ESP8266WiFi.h> |
2 | #include <ESP8266WiFiSTA.h> |
3 | #include <WiFiUdp.h> |
4 | #define LED D4
|
5 | const char* ssid = "********"; |
6 | const char* password = "********"; |
7 | unsigned int multicastPort = 9522; // local port to listen on |
8 | IPAddress multicastIP(239, 12, 255, 254); |
9 | WiFiUDP Udp; |
10 | static void initWiFi() { |
11 | WiFi.mode(WIFI_STA); |
12 | WiFi.begin(ssid, password); |
13 | Serial.print("Connecting to WiFi .."); |
14 | while (WiFi.status() != WL_CONNECTED) { |
15 | Serial.print('.'); |
16 | delay(500); |
17 | }
|
18 | Serial.println(WiFi.localIP()); |
19 | }
|
20 | static void Soutput(int kanal, int index, int art, int tarif, String Bezeichnung, double value, int timestamp){ |
21 | Serial.print (timestamp); |
22 | Serial.print ('#'); |
23 | //Serial.print(kanal);
|
24 | //Serial.print(':');
|
25 | //Serial.print(index);
|
26 | //Serial.print('.');
|
27 | //Serial.print(art);
|
28 | //Serial.print('.');
|
29 | //Serial.print(tarif);
|
30 | //Serial.print('#');
|
31 | Serial.print(Bezeichnung); |
32 | Serial.print('='); |
33 | Serial.println(value); |
34 | }
|
35 | void setup() { |
36 | pinMode(LED, OUTPUT); // Setzen des PINs als Ausgang |
37 | Serial.begin(57600); |
38 | Serial.println("Connecting..."); |
39 | initWiFi(); |
40 | Udp.begin(multicastPort); |
41 | #ifdef ESP8266
|
42 | Udp.beginMulticast(WiFi.localIP(), multicastIP, multicastPort); |
43 | #else
|
44 | Udp.beginMulticast(multicastIP, multicastPort); |
45 | #endif
|
46 | }
|
47 | void loop() { |
48 | digitalWrite(LED, !(digitalRead(LED))); // LED umschalten |
49 | uint8_t buffer[1024]; |
50 | int packetSize = Udp.parsePacket(); |
51 | String Bezeichnung; |
52 | double Pbezug = 0; |
53 | double Peinspeisung = 0; |
54 | double Leistung = 0; |
55 | uint32_t timestampalt = 0; |
56 | bool output = false; |
57 | if (packetSize) { |
58 | int rSize = Udp.read(buffer, 1024); |
59 | if (buffer[0] != 'S' || buffer[1] != 'M' || buffer[2] != 'A') { |
60 | Serial.println("Not an SMA packet?"); |
61 | return; |
62 | }
|
63 | uint16_t grouplen; |
64 | uint16_t grouptag; |
65 | uint8_t* offset = buffer + 4; |
66 | do { |
67 | grouplen = (offset[0] << 8) + offset[1]; |
68 | grouptag = (offset[2] << 8) + offset[3]; |
69 | offset += 4; |
70 | if (grouplen == 0xffff) return; |
71 | if (grouptag == 0x02A0 && grouplen == 4) { |
72 | offset += 4; |
73 | } else if (grouptag == 0x0010) { |
74 | uint8_t* endOfGroup = offset + grouplen; |
75 | uint16_t protocolID = (offset[0] << 8) + offset[1]; |
76 | offset += 2; |
77 | uint16_t susyID = (offset[0] << 8) + offset[1]; |
78 | offset += 2; |
79 | uint32_t serial = (offset[0] << 24) + (offset[1] << 16) + (offset[2] << 8) + offset[3]; |
80 | offset += 4; |
81 | uint32_t timestamp = (offset[0] << 24) + (offset[1] << 16) + (offset[2] << 8) + offset[3]; |
82 | offset += 4; |
83 | while (offset < endOfGroup) { |
84 | uint8_t kanal = offset[0]; |
85 | uint8_t index = offset[1]; |
86 | uint8_t art = offset[2]; |
87 | uint8_t tarif = offset[3]; |
88 | offset += 4; |
89 | if (art == 8) { |
90 | uint64_t data = ((uint64_t)offset[0] << 56) + |
91 | ((uint64_t)offset[1] << 48) + |
92 | ((uint64_t)offset[2] << 40) + |
93 | ((uint64_t)offset[3] << 32) + |
94 | ((uint64_t)offset[4] << 24) + |
95 | ((uint64_t)offset[5] << 16) + |
96 | ((uint64_t)offset[6] << 8) + |
97 | offset[7]; |
98 | offset += 8; |
99 | } else if (art == 4) { |
100 | uint32_t data = (offset[0] << 24) + |
101 | (offset[1] << 16) + |
102 | (offset[2] << 8) + |
103 | offset[3]; |
104 | offset += 4; |
105 | switch (index) { |
106 | case 1: |
107 | Pbezug = data * 0.1; |
108 | break; |
109 | case 2: |
110 | Peinspeisung = data * 0.1; |
111 | output = true; |
112 | break; |
113 | default:
|
114 | Bezeichnung = "Data : "; |
115 | break; // Wird nicht benötigt, wenn Statement(s) vorhanden sind |
116 | }
|
117 | if (output == true){ |
118 | Leistung = Peinspeisung - Pbezug; |
119 | Soutput(kanal, index, art, tarif, "Leistung", Leistung, timestamp); |
120 | output = false; |
121 | }
|
122 | } else if (kanal==144) { |
123 | // Optional: Versionsnummer auslesen... aber interessiert die?
|
124 | offset += 4; |
125 | } else { |
126 | offset += art; |
127 | Serial.println("Strange measurement skipped"); |
128 | }
|
129 | }
|
130 | } else if (grouptag == 0) { |
131 | // end marker
|
132 | offset += grouplen; |
133 | } else { |
134 | Serial.print("unhandled group "); |
135 | Serial.print(grouptag); |
136 | Serial.print(" with len="); |
137 | Serial.println(grouplen); |
138 | offset += grouplen; |
139 | }
|
140 | } while (grouplen > 0 && offset + 4 < buffer + rSize); |
141 | }
|
142 | }
|
:
Bearbeitet durch User
Ich benutze hier den originalen Teil des Sourcecodes von Ernst B. hier im Forum. Beitrag "ESP01S: TCP Server und UDP Multicast" Habe da nichts geändert. Meine Timestamp zählt aufwärts, ist aber leider keine Uhrzeit. Ich ignoriere diesen Wert. Hoffe das hilft weiter.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.