sunsynk: Read Errors: USR-W630

Thanks for this great add-on! I am using it with Deye SUN-3.6/5K-SG03LP1-EU and a USR-630.

When I restart the add-on, it does get the first set of values from the USR-630, however shortly afterwards, an error occurs and the add-on goes into a bad state and does not recover. Below is an extract from the logs. Any idea what write function it is trying to call? I am only trying to read sensor data, not write anything.

Relevant config:

PORT: ''
PORT_ADDRESS: 10.0.1.66:8899
PROFILES: 0
SUNSYNK_ID: 'XXXXXX'
SENSORS:
  - battery_soc
  - grid_load
  - grid_ct_load
  - inverter_output
  - load_power
  - pv1_power
  - pv2_power
  - battery_power
  - battery_current
  - battery_voltage

Log:

2022-02-10 21:22:05,449 DEBUG   Inverter Output low=65521 high=0 value=-16W
2022-02-10 21:22:05,450 DEBUG   Load Power low=1596 high=0 value=1597W
2022-02-10 21:22:05,450 DEBUG   send: 0x0 0x5 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xb7 0x0 0x9
2022-02-10 21:22:05,451 DEBUG   Adding transaction 5
2022-02-10 21:22:06,136 DEBUG   recv: 0x0 0x5 0x0 0x0 0x0 0xe 0x1 0x3 0x12 0x13 0x85 0x0 0x51 0x6 0x34 0x0 0x0 0x0 0x2 0x0
2022-02-10 21:22:06,136 DEBUG   Processing: 0x0 0x5 0x0 0x0 0x0 0xe 0x1 0x3 0x12 0x13 0x85 0x0 0x51 0x6 0x34 0x0 0x0 0x0 0x2 0x0
2022-02-10 21:22:06,137 DEBUG   Factory Response[ReadHoldingRegistersResponse: 3]
2022-02-10 21:22:06,138 ERROR   unpack requires a buffer of 2 bytes
2022-02-10 21:22:06,138 ERROR   Fatal error: protocol.data_received() call failed.
handle_traceback: Handle created at (most recent call last):
  File "/usr/src/app/./run.py", line 236, in <module>
    LOOP.run_until_complete(main(LOOP))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 629, in run_until_complete
    self.run_forever()
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 596, in run_forever
    self._run_once()
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 1882, in _run_once
    handle._run()
  File "/usr/local/lib/python3.9/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/local/lib/python3.9/asyncio/selector_events.py", line 754, in _add_reader
    self._loop._add_reader(fd, callback, *args)
  File "/usr/local/lib/python3.9/asyncio/selector_events.py", line 259, in _add_reader
    handle = events.Handle(callback, args, self, None)
protocol: <pymodbus.client.asynchronous.async_io.ModbusClientProtocol object at 0x7f2207c44f10>
transport: <_SelectorSocketTransport fd=8 read=polling write=<idle, bufsize=0>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/asyncio/selector_events.py", line 870, in _read_ready__data_received
    self._protocol.data_received(data)
  File "/usr/local/lib/python3.9/site-packages/pymodbus/client/asynchronous/async_io/__init__.py", line 204, in data_received
    self._dataReceived(data)
  File "/usr/local/lib/python3.9/site-packages/pymodbus/client/asynchronous/async_io/__init__.py", line 151, in _dataReceived
    self.framer.processIncomingPacket(data, self._handleResponse, unit=unit)
  File "/usr/local/lib/python3.9/site-packages/pymodbus/framer/socket_framer.py", line 153, in processIncomingPacket
    self._process(callback)
  File "/usr/local/lib/python3.9/site-packages/pymodbus/framer/socket_framer.py", line 175, in _process
    raise ModbusIOException("Unable to decode request")
pymodbus.exceptions.ModbusIOException: Modbus Error: [Input/Output] Unable to decode request
2022-02-10 21:22:06,142 DEBUG   Client disconnected from modbus server: Modbus Error: [Input/Output] Unable to decode request
2022-02-10 21:22:06,143 DEBUG   Getting transaction 5
2022-02-10 21:22:06,145 INFO    Protocol lost connection.
2022-02-10 21:22:06,151 ERROR   Read Error: Modbus Error: [Connection] Connection lost during request
2022-02-10 21:22:06,154 DEBUG   send: 0x0 0x6 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:06,155 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:07,166 DEBUG   send: 0x0 0x7 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:07,173 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:08,170 DEBUG   send: 0x0 0x8 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:08,178 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:09,174 DEBUG   send: 0x0 0x9 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:09,176 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:10,178 DEBUG   send: 0x0 0xa 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:10,182 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:11,182 DEBUG   send: 0x0 0xb 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:11,184 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:12,187 DEBUG   send: 0x0 0xc 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:12,187 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:13,193 DEBUG   send: 0x0 0xd 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:13,194 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:14,194 DEBUG   send: 0x0 0xe 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:14,195 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:15,198 DEBUG   send: 0x0 0xf 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:15,199 ERROR   Read Error: 'NoneType' object has no attribute 'write'
2022-02-10 21:22:16,202 DEBUG   send: 0x0 0x10 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-10 21:22:16,206 ERROR   Read Error: 'NoneType' object has no attribute 'write'

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 39 (36 by maintainers)

Most upvoted comments

In my setup I have a SMA energy meter wired to the essentials and non-essentials and they give slightly different readings

The value on the house&pool is from Sunsynk and the main value to the icon is from the SMA energy meter (but both of these are filtered… so very likely that what I’m seeing is a result of that), but would appreciate feedback

image

Happy with that, will look at doing a PR some time this week 👍 Also happy to tackle the new error if I am the only one getting it since I now know how to work around it now. Though the allow_gap = 1 change did fix all of my previous errors.

Thanks for all of your help @kellerza !

P.S. I love the new essential & non-essential load sensors, you can see them in action here: image

I got it!

When the add-on reads registers [183, 186, 187, 190, 191], the subsequent read consistently fails and causes the above error. When only reading registers [186, 187, 190, 191], subsequent reads succeed. The add-on sometimes picks the one query over the other, I am not certain what the criteria is.

Register 185 is undefined in the Sunsynk Modbus docs. The add-on reads all registers in a non-contiguous range provided that the gap is not greater than 3. My strong submission is that reading register 185 causes an extra leading 4 bytes to be present with the next read, which causes that read to be invalid. The add-on does read that register in the case of the first query above.

The solution? I forced the add-on to only read contiguous registers by setting allow_gap = 1 when uSunsynk calls groupSensors here.

async def read(self, sensors: Sequence[Sensor]) -> None:
        """Read a list of sensors."""
        for grp in group_sensors(sensors, allow_gap = 1):
            glen = grp[-1] - grp[0] + 1

Therefore if the add-on needs to read registers [183, 186, 187, 190, 191] it will read them in 3 batches; [183], [186, 187] and [190, 191]. This does not appear to introduce any noticeable performance penalty, it in fact appears to have solved all of my problems!

Look at these beautiful solid lines without any gaps - the add-on has not restarted at all because the error has not occurred even once in the last 30 minutes!! image

@kellerza I am not sure whether you would like to make the above change (allow_gap = 1) permanent for the add-on - my suggestion would be yes because that would avoid unnecessarily reading registers which users have not configured and more importantly it will avoid reading registers which cause side effects as described above.