SMA Home-Manager Multicast-Messages Auswertung

OP #7497865
Lesenswert?

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.

#7497936
Lesenswert?

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.

OP #7498086
Lesenswert?

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!

#7498217
Lesenswert?

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.

#7499028
Lesenswert?

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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren