Hi there,
in Home Assistant 2021.2.3 there is a bug with the edl21 platform.
I use the Weidmann Electronics USB IR Reader.
If I set the following in configuration.yaml:
2021-02-23 21:25:25 ERROR (MainThread) [homeassistant] Error doing job: Exception in callback SerialTransport._read_ready()
Traceback (most recent call last):
File "/usr/local/lib/python3.8/asyncio/events.py", line 81, in _run
self._context.run(self._callback, *self._args)
File "/usr/local/lib/python3.8/site-packages/serial_asyncio/__init__.py", line 119, in _read_ready
self._protocol.data_received(data)
File "/usr/local/lib/python3.8/site-packages/sml/asyncio.py", line 61, in data_received
res = self.parse_frame(self._buf)
File "/usr/local/lib/python3.8/site-packages/sml/__init__.py", line 415, in parse_frame
obj = SmlFrame(SmlBase.__unescape(frame[8:-8-padding]))
File "/usr/local/lib/python3.8/site-packages/sml/__init__.py", line 377, in __init__
self.append(SmlMessage(self.bits))
File "/usr/local/lib/python3.8/site-packages/sml/__init__.py", line 316, in __init__
raise SmlParserError('CRC16 mismatch')
sml.SmlParserError: CRC16 mismatch
The Devicedata was read only once before crashing.
Any hints to get rid of this?
I have the same problem, the reason might be a faulty implementation of the checksum on the sending side (that should be the smart meter).
Some hints I found (sorry german):
thanks for your reply!
German is no problem.
I´m a native german
(Du bist dem Namen nach auch deutsch?)
Unfortunately the linked posts could not help. The update to Core 2021.3.2 did not bring any improvement either. There is no other choice than to hope that someone will fix the problems in the EDL21 code.
Ja ich bin Deutscher
But to continue in english: I have a feeling - based on what I read in the links - there might be a problem with the meter itself not sending the right checksum. Are you using an ISKRA MT175 or MT176?
I have the ISKRA MT631.
With older versions of HA it worked like a charm.
I try to find a solution without these crc checks an post it here if it workes
Ah, interesting that it worked before. I dont have a setup which easily allows me to change the code (and dont have much time at the moment). One idea would be that older versions didnt check the CRC)
I have traced it down to a problem with pysml. The pysml lib does assume the CRC 16 is always 16 bit long. But for values < 256 the serialization of the ISK does - correctly I guess - store it with a 1 byte serialization only.
I have set up a unit test for that with the faulty package and the patch I have done does not show the error anymore.
Not sure how I can test it within hassio but I will inform the pysml lib owner about it.
diff --git a/sml/__init__.py b/sml/__init__.py
index 3c26e01..d25c8a8 100644
--- a/sml/__init__.py
+++ b/sml/__init__.py
@@ -303,7 +303,9 @@ class SmlMessage(dict):
if tag != 7 or length != 6 or tlsize != 1:
raise SmlParserError('Message does not start with 0x76')
- values = self._read_list(length)
+ values,lastLength = self._read_list(length)
+ # the last key is the crc, but it may consume different number of bytes (if the CRC is smaller than 256 it is serialised in 1 byte only)
+ crcLength=lastLength
for key, val in zip(self.__FIELDS, values):
self[key] = val
@@ -312,7 +314,7 @@ class SmlMessage(dict):
end = self._bits.pos
msg_bytes = self._bits[start:end].bytes
- if Crc.crc16(msg_bytes[:-4]) != self['crc16']:
+ if Crc.crc16(msg_bytes[:-(crcLength+1)]) != self['crc16']:
raise SmlParserError('CRC16 mismatch')
self['messageBody'] = SmlChoice.create(self.__CHOICES,
@@ -340,6 +342,7 @@ class SmlMessage(dict):
def _read_list(self, count: int, nesting: int = 0) -> list:
res = []
+ lastLength=0
logger.debug("%s[*] List of %d items", nesting * ' ', count)
for i in range(count):
@@ -347,7 +350,7 @@ class SmlMessage(dict):
tag, length, tlsize = self._read_tag_length()
logger.debug("%s[+] Tag: %#x, Len: %d", nesting * ' ', tag, length)
-
+ if length > 0: lastLength = length
if tag == 0 and length == 0:
value = None
elif tag == 0 and length >= tlsize:
@@ -357,7 +360,7 @@ class SmlMessage(dict):
elif tag == 6 and length > tlsize:
value = self._bits.read('uintbe:%d' % ((length - tlsize) * 8))
elif tag == 7 and length > 0:
- value = self._read_list(length, nesting + 1)
+ value,length = self._read_list(length, nesting + 1)
else:
raise SmlParserError('Unknown TL field')
@@ -365,7 +368,7 @@ class SmlMessage(dict):
res.append(value)
assert len(res) == count
- return res
+ return res,lastLength
class SmlFrame(list):
@@ -411,10 +414,12 @@ class SmlBase:
frame = match.group(0)
padding = frame[-3]
- if padding < 4 and Crc.verify_fcs(frame):
- obj = SmlFrame(SmlBase.__unescape(frame[8:-8-padding]))
- return [match.end(), obj]
-
+ try:
+ if padding < 4 and Crc.verify_fcs(frame):
+ obj = SmlFrame(SmlBase.__unescape(frame[8:-8-padding]))
+ return [match.end(), obj]
+ except:
+ return [match.end()]
start = match.start()
assert match.end() > end
end = match.end()
Unfortunally its not fixed yet.
Today i made the core update to 2021.5.
The Issue still exists.
But I found a dirty way to fix it anymore with the patch above in this thread.
I dont know how to apply this patch because the binary “patch” isnt present inside the core.
But I made the changes manually and it seems to work.
I continue to watch it and write my findings here.
Interesting. It is definately fixed for me. Ran since I last posted and not one CRC16 entry in the log, the data also looks fine. Before I had thousands of exceptions.
I am also having the ISKRA MT631 + Weidmann Elektronik Schreib-/Lesekopf USB and
HA is: Container Version 2021.9.4.
All I get is one relevant sensor (positive_active_energy_total), but not the current usage or so. 2 more sensors are created but not relevant (metering_point_id_1 and negative_active_energy_total).
The pin is entered and the normal display is showing what it should.
Have you done any initialization steps from command line or anyelse but configuring it like that:
Hi,
it is not sufficient to disable the PIN to get the full data set. I think i do have the same model and at the first try i also received only the (rounded) total energy.
In the smart meters menu there is another option labeled “Inf” (“Info”) which has to be switched to ON to receive the full data.