I can report the same issue. I have seen complaints about it in other forums but couldnât find a solution, so I decided to figure out myself what the root cause may be.
Problem description:
From time to time reading data from the SMA Home Manger 20 using the SMA energy meter binding the result gives unplausible values. Event log output in this case:
2021-12-04 10:34:30.249 [INFO ] [openhab.event.ItemCommandEvent ] - Item 'SMAHomeManager20PowerIn' received command REFRESH
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20PowerIn' changed from 205.6999969482422 to 3361995
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20EnergyIn' changed from 885.0010375976562 to -1747646808064
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20EnergyOut' changed from 3630.896240234375 to 0.0
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20PowerOutL1' changed from 93.69999694824219 to 0.0
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20EnergyInL1' changed from 243.31028747558594 to 0.0
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20EnergyOutL1' changed from 5090.23095703125 to 0.0
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20PowerInL2' changed from 158.10000610351562 to 0.0
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20EnergyInL2' changed from 832.591552734375 to 0.0
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20PowerInL3' changed from 141.3000030517578 to 0.0
2021-12-04 10:34:30.287 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SMAHomeManager20EnergyInL3' changed from 1268.43359375 to 0.0
- PowerIn and EnergyIn show crazy values while the others are zero. Other users report different values for PowerIn and EnergyIn but in the same system the powerIn value always remain the same, while the energyIn value varies.
- The wrong readings appear in irregular intervals, fluctuating from 3 to 4 per hour to one per hour or even to no wrong reading for several hours. The following reading gives always correct values.
- The issue correlates with the latest HM update to revision 2.07.5.R which I received in october 22.
System environment:
-
OS: Debian buster
-
HW: 2 x Raspberry Pi 4B+ with 4 GB
-
openHabian: Release build 3.1.0
-
Java: openjdk version â11.0.12â 2021-07-20 LTS
OpenJDK Runtime Environment Zulu11.50+19-CA (build 11.0.12+7-LTS)
OpenJDK Client VM Zulu11.50+19-CA (build 11.0.12+7-LTS, mixed mode)
-
Binding: org.openhab.binding.smaenergymeter 3.1.0
My working hypothesis was that the HM20 protocol has changed slightly with the update.
For debugging I have set up a new openhab installation on my Win 10 desktop PC. I also wanted to see if the problem is system independant (which it is). I used the openHAB 3.1.0 Stable Runtime with Zulu Java 11 for this purpose.
The definition of things, items and rules was text based, stripped down to the bare mimimum needed to read the energy meter values. The polling was rate is set to 2s.
In parallel I started wireshark to monitor the data packets sent out from the HM2 (IP address 192.168.178.39).
Wrong readings are reported to the openhab log file.
My findings
openhab.log
2021-12-04 09:50:04.559 [WARN ] [ore.model.script.PV.rules::HM20 test] - SMAHomeManager20PowerIn yields a wrong value: 3361995, read the next packet
2021-12-04 09:51:06.554 [WARN ] [ore.model.script.PV.rules::HM20 test] - SMAHomeManager20PowerIn yields a wrong value: 3361995, read the next packet
2021-12-04 10:07:38.557 [WARN ] [ore.model.script.PV.rules::HM20 test] - SMAHomeManager20PowerIn yields a wrong value: 3361995, read the next packet
2021-12-04 10:34:30.550 [WARN ] [ore.model.script.PV.rules::HM20 test] - SMAHomeManager20PowerIn yields a wrong value: 3361995, read the next packet
2021-12-04 10:46:54.548 [WARN ] [ore.model.script.PV.rules::HM20 test] - SMAHomeManager20PowerIn yields a wrong value: 3361995, read the next packet
2021-12-04 12:12:40.542 [WARN ] [ore.model.script.PV.rules::HM20 test] - SMAHomeManager20PowerIn yields a wrong value: 3361995, read the next packet
The wireshark log running in parallel shows two types of UDP packets:
26993 10:34:29,623483 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
26994 10:34:29,823679 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
26997 10:34:30,023156 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
27002 10:34:30,223461 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
27005 10:34:30,286745 192.168.178.39 192.168.178.255 UDP 100 9522 â 9522 Len=58
27008 10:34:30,422973 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
27011 10:34:30,624331 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
27017 10:34:30,822646 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
27020 10:34:31,022682 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
27021 10:34:31,222812 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
27073 10:34:31,422488 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
27078 10:34:31,622976 192.168.178.39 239.12.255.254 UDP 650 35938 â 9522 Len=608
- UDP multicast packets to IPV4 multicast address 239.12.255.254, port 9522 with payload length of 608 bytes. The packets are sent in 200 ms intervals (default for HM20) and contain valid energy meter data.
- UDP broadcast packets to 192.168.178.255, payload length 58 bytes. The packets are sent in 30 s intervals.
Observation: Always when an unplausible reading is reported in the openhab log, there appears a corresponding broadcast packet in the wireshark log, e.g. see log entries at 10:34:30.
The comparison of the packet content shows interesting results (Address 0X0000 = start of payload data, multicast packet is truncated, original serialnumber changed to 0X01020304):
Multicast packet, sent every 200 ms
0000 53 4d 41 00 "S", "M", "A", 0
0004 00 04 02 a0 Data length: 4 byte, Tag 0 ??
0008 00 00 00 01 Group 1
000C 02 4c Data length: 588 bytes
000E 00 10 Tag: âSMA Net 2â, Version 0
0010 60 69 Protocol- ID: Emeter protocol
0012 01 74 01 02 03 04 Emeter ID: SUSy-ID: 0x0174 (373d), Serialnumber: 0x01020304
0018 80 2a d8 f7 Ticker, ms since start
001C 00 01 04 00 PowerIn identifier, 4 Bytes, resolution 0.1W
0020 00 00 00 00 PowerIn value, 4 Bytes
0024 00 01 08 00 EnergyIn identifier
0028 00 00 00 00 bd b6 f1 30 EnergyIn value, 8 bytes, resolution 1 WS
....
Broadcast packet, sent approx every 30s - 31 s
0000 53 4d 41 00 "S", "M", "A", 0
0004 00 04 02 a0 Data length: 4 byte, Tag 0 ??
0008 00 00 00 01 Group 1
000C 00 26 Data length: 38 bytes
000E 00 10 Tag: âSMA Net 2â, Version 0
0010 60 65 Protocol- ID
0012 09 a0 ff ff ff ff ?
0018 ff ff 00 00 ?
001C 74 01 04 03 Emeter ID: SUSy-ID: 0x0174 (373d), Serialnumber: 0x01020304
0020 02 01 00 00 Emeter ID: Serialnumber
0024 00 00 00 00 ?
0028 f3 e3 00 02 00 00 00 00 ?
0030 00 00 00 00 ?
- Both packets start with similar headers
- In the broadcast packet the SUSy-ID and the Serialnumber are shifted towards addresses used for powerIn and energyIn in the mutlicast packet
- SUSy-ID / Serialnumber endianess: Multicast packet: Big endian, Broadcast packet: Little endian
Assumption: The broadcast packet is erranously taken as multicast packet. In this case:
- powerIn reads to 0X02010000 and energyIn reads to 0XF3E2000200000000.
- powerIn value divided by ten (as done by the binding) gives 3.361.996 which is equal the reported value + 1.
- energyIn value divided by 3600000 gives -1.747.646.853.012 which is close to but not equal to the reported value of -1.747.646.808.064.
Looking into the binding source code it seems to me that only the SMA string is checked. (I donât speak java just C but I tried my best). A datagram length check seems not to be implemented, so different packets with the same SMA string are not differentiated.
String sma = new String(Arrays.copyOfRange(bytes, 0x00, 0x03));
if (!sma.equals("SMA")) {
throw new IOException("Not a SMA telegram." + sma);
}
Conclusion:
My theory is that the binding receives both packets. Since only the SMA string is checked wrong values are read from the broadcast packet.
The theory is supported by the following facts:
- the broadcast packet appears always at the same time when a wrong value is logged
- the wrong values appear relatively seldom in irregular intervals due to the long time interval of 30s between the broadcast packets combined with the asynchronous polling of the energy meter
- the powerIn value remains always the same and differs from the serial number only by one
- the header of both datagrams start with the âSMAâ string and only this string is checked in the code
I have to admit that there are some weak points:
The values reported by the binding are close but not equal to the values found in the multicast packet.
I also have no explanation why the binding receives both packets. However Iâm lacking enough knowledge about about java and multicast / broadcast networking to give a final judgement. May be I overlooked something.
So whats next?
I would recommend to check the protocol id in addition to the âSMAâ string: ID 0x6069 at position 0x10. All datagrams with a different value should be discarded. As said my java knowledge is close to 0 but hopefully someone else from the community can take the job.
The question is how to proceed when a wrong packet is detected: Reread the multicast datagram or throw an exception?
In the first case the 200 ms time frame must be observed. Worst case the next valid datagram comes 200 ms later. Donât know if such a long delay is acceptable.
The second case minimizes cpu time of the binding but may result in an unacceptable long time interval until the energy meter values are updated, depending on the polling rate. I use a 10 s polling interval, so worst case the energy meter values remain unchanged for 20 s.
And may be someone else can shed some light on the weak points mentioned above.