Read Error: 'NoneType' object has no attribute 'write'

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: <IP_ADDRESS>: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'

Made a quick update with the ideas above, let me know

Thanks for the quick update!
Looks like the add-on is killing itself now and the watchdog restarts it. These errors are consistently occurring after a restart though, far too often in my opinion.
2022-02-11 02:51:12,623 DEBUG   publish homeassistant/select/XXXX/system_mode_voltages/config
2022-02-11 02:51:12,625 DEBUG   PUBLISH 1R homeassistant/select/2107307119/system_mode_voltages/config, {"unique_id": "2107307119_system_mode_voltages", "device": {"identifiers": ["XXXX"], "manufacturer": "Sunsynk", "model": "Inverter<PHONE_NUMBER>", "name": "Sunsynk Inverter XXXX"}, "state_topic": "SUNSYNK/status/2107307119/system_mode_voltages", "name": " System Mode Voltages", "availability": [{"topic": "SUNSYNK/status/2107307119/availability"}], "command_topic": "SUNSYNK/status/2107307119/system_mode_voltages_set", "options": ["UPDATE"]}
2022-02-11 02:51:13,012 DEBUG   send: 0x0 0x2 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0xa
2022-02-11 02:51:13,015 DEBUG   Adding transaction 2
2022-02-11 02:51:13,283 DEBUG   recv: 0x0 0x2 0x0 0x0 0x0 0xe 0x1 0x3 0x14 0x1 0x42 0x1 0x42 0x0 0x0 0x1 0x42 0xff 0xf0 0x0
2022-02-11 02:51:13,284 DEBUG   Processing: 0x0 0x2 0x0 0x0 0x0 0xe 0x1 0x3 0x14 0x1 0x42 0x1 0x42 0x0 0x0 0x1 0x42 0xff 0xf0 0x0
2022-02-11 02:51:13,284 DEBUG   Factory Response[ReadHoldingRegistersResponse: 3]
2022-02-11 02:51:13,284 ERROR   unpack requires a buffer of 2 bytes
2022-02-11 02:51:13,295 ERROR   Fatal error: protocol.data_received() call failed.
handle_traceback: Handle created at (most recent call last):
  File "/usr/src/app/./run.py", line 250, 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 0x7fb5eeee2910>
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-11 02:51:13,306 DEBUG   Client disconnected from modbus server: Modbus Error: [Input/Output] Unable to decode request
2022-02-11 02:51:13,306 DEBUG   Getting transaction 2
2022-02-11 02:51:13,307 INFO    Protocol lost connection.
2022-02-11 02:51:13,313 ERROR   Read Error: Modbus Error: [Connection] Connection lost during request
2022-02-11 02:51:13,313 INFO    Retrying individual sensors: ['Battery SOC:last', 'Grid load:step:mean', 'Grid CT load:step:mean', 'Inverter Output:step:mean', 'Load Power:step:mean', 'PV1 power:step:mean', 'PV2 power:step:mean', 'Battery power:step:mean', 'Battery current:step:mean', 'Battery voltage:step:mean']
2022-02-11 02:51:13,337 DEBUG   send: 0x0 0x3 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xb8 0x0 0x1
2022-02-11 02:51:13,342 ERROR   Read ErrorBattery SOC: 'NoneType' object has no attribute 'write'
2022-02-11 02:51:13,366 DEBUG   send: 0x0 0x4 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xa9 0x0 0x1
2022-02-11 02:51:13,366 ERROR   Read ErrorGrid load: 'NoneType' object has no attribute 'write'
2022-02-11 02:51:13,389 DEBUG   send: 0x0 0x5 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0xac 0x0 0x1
2022-02-11 02:51:13,389 ERROR   Read ErrorGrid CT load: 'NoneType' object has no attribute 'write'
Traceback (most recent call last):
  File "/usr/src/app/./run.py", line 155, in read
    await SUNSYNK.read(sensors)
  File "/usr/local/lib/python3.9/site-packages/sunsynk/sunsynk.py", line 100, in read
    r_r = await self.client.read_holding_registers(
  File "/usr/local/lib/python3.9/site-packages/pymodbus/client/asynchronous/async_io/__init__.py", line 34, in execute
    req = self._execute(request)
  File "/usr/local/lib/python3.9/site-packages/pymodbus/client/asynchronous/async_io/__init__.py", line 141, in _execute
    self.write_transport(packet)
  File "/usr/local/lib/python3.9/site-packages/pymodbus/client/asynchronous/async_io/__init__.py", line 131, in write_transport
    return self.transport.write(packet)
AttributeError: 'NoneType' object has no attribute 'write'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/src/app/./run.py", line 250, in <module>
    LOOP.run_until_complete(main(LOOP))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/usr/src/app/./run.py", line 216, in main
    await read([f.sensor for f in SENSORS], retry_single=True)
  File "/usr/src/app/./run.py", line 174, in read
    await read([sen], msg=sen.name, retry_single=False)
  File "/usr/src/app/./run.py", line 168, in read
    raise Exception(f"Multiple Modbus read errors: {err}") from err
Exception: Multiple Modbus read errors: 'NoneType' object has no attribute 'write'
[cmd] ./run.py exited 1
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.

Another error I seem to get after a restart is the following:
2022-02-11 02:57:35,187 INFO    Loading HASS OS configuration
2022-02-11 02:57:35,189 INFO    Filter *last used for ['battery_soc']
2022-02-11 02:57:35,189 INFO    Filter *step used for ['grid_load', 'grid_ct_load', 'inverter_output', 'load_power', 'pv1_power', 'pv2_power', 'battery_power', 'battery_current', 'battery_voltage']
2022-02-11 02:57:35,190 DEBUG   Using selector: EpollSelector
2022-02-11 02:57:35,191 DEBUG   Connecting.
2022-02-11 02:57:35,211 DEBUG   Client connected to modbus server
2022-02-11 02:57:35,212 INFO    Protocol made connection.
2022-02-11 02:57:35,213 DEBUG   <asyncio.TransportSocket fd=8, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('<IP_ADDRESS>', 47742), raddr=('<IP_ADDRESS>', 8899)> connected to <IP_ADDRESS>:8899: (<_SelectorSocketTransport fd=8 read=polling write=<idle, bufsize=0>>, <pymodbus.client.asynchronous.async_io.ModbusClientProtocol object at 0x7f9c7a91dc10>)
2022-02-11 02:57:35,213 INFO    Connected to <IP_ADDRESS>:8899.
2022-02-11 02:57:35,214 DEBUG   send: 0x0 0x1 0x0 0x0 0x0 0x6 0x1 0x3 0x0 0x3 0x0 0x5
2022-02-11 02:57:35,215 DEBUG   Adding transaction 1
2022-02-11 02:57:35,726 DEBUG   recv: 0x0 0x1 0x0 0x0 0x0 0xe 0xf0 0x1 0x69 0x0 0x0 0x1 0x69 0x6c 0xd6 0x1 0x3 0xa 0x32 0x31
2022-02-11 02:57:35,730 DEBUG   Processing: 0x0 0x1 0x0 0x0 0x0 0xe 0xf0 0x1 0x69 0x0 0x0 0x1 0x69 0x6c 0xd6 0x1 0x3 0xa 0x32 0x31
2022-02-11 02:57:35,730 DEBUG   Factory Response[ReadCoilsResponse: 1]
2022-02-11 02:57:35,732 DEBUG   Getting transaction 1
2022-02-11 02:57:35,739 ERROR   Read Error: 'ReadCoilsResponse' object has no attribute 'registers'
2022-02-11 02:57:35,739 INFO    ############################################################
2022-02-11 02:57:35,739 INFO    No response on the Modbus interface, try checking the wiring to the Inverter, the USB-to-RS485 converter, etc
2022-02-11 02:57:35,740 INFO    ############################################################
2022-02-11 02:57:35,742 CRITICAL This Add-On will terminate in 30 seconds, use the Supervisor Watchdog to restart automatically.

Will have to check why you still get the stack trace…
but if it finally restarts (after 3 errors) and cannot connect there might be an issue with you tcp-rtu bridge. What do you use there? Is it still alive?

Looking at the port number being used by any chance are you connecting to the solarman wifi device that plugs into the WiFi/RS232 port?

So yes, I should have disclosed this part at the beginning.
I waited more than one month for the USR-630 to arrive from China. In the meantime, I did manage to set up polling the solarman wifi dongle directly using some python scripts sourced from here which I tweaked to have a run loop, etc. This has been working well, except for causing a bit less data to be uploaded to solarman - it seems the dongle isn't very powerful and polling it frequently causes certain load to occur either on it or the inverter or both (I am not sure). See below screenshot for the effect of the frequent polling:

Now that my USR-630 arrived, I would like to switch over to using it, this was the intention all along. I would also like to use this addon, and stop polling the solarman wifi dongle using the customised python scripts.
I did have both running at the same time last night:

Custom python scripts running and polling the solarman wifi dongle, publishing to a MQTT broker used by my main Home Assistant Core installation running in Docker - this gives me near-realtime data because my polling is fairly aggressive (with exponential backoff implemented when a timeout occurs).
@kellerza's awesome add-on running within a separate Home Assistant OS installation in a virtual machine, connecting to the USR-630, which is connected to the BMS RS485 port on the inverter.

It did occur to me that potentially 1 might interfere with 2, so I turned 1 off by just switching off the Docker container. This I did after my last post. I let only point 2 run for 3 hours with the watchdog restarting it where necessary. This was the result, notice how little data I got:

So obviously a lot of timeouts and errors occur with this addon connecting to the USR-630. I get much better data at this stage using the custom python scripts polling the solarman wifi dongle. I would however like to change to this addon and the USR-630 as mentioned above, but don't want to switch yet until I get more stable and reliable data.
I am open to suggestions on how to go proceed, I thought of even physically disconnecting the solarman dongle whilst testing this addon with the USR-630 to see if the results are better.

Im not sure what the use of the USR-630 is but why dont you just use one of these
I use one connected to a spare RasPi with Docker installed and mbusd. This works for me barring the random read issues but i get near realtime data without interruptions

The USR-630 is meant to perform the same function as:

The Raspberry Pi
with the USB to RS485 Converter plugged into it
and expose it via TCP

All in one.
I may as a last resort source a Raspberry Pi + converter as you have suggested, but I thought the USR-630 should be able to do this easily since that is what it was purpose built for.

Further tests - the timeouts seem to have been entirely eliminated after stopping of polling the solarman dongle, removing the dongle from the inverter and connecting the USR-W630 in its place via RS232.
I am running a modbus cli which allows me to read one or more registers via the command line. This tool used to get timeouts, but after executing it as fast as I could many times over and over via the command line, I haven't been able to get a single timeout when reading registers. It succeeds every time.
The add-on however keeps throwing the Exception: Multiple Modbus read errors: 'NoneType' object has no attribute 'write' error after a successful read.
I have tried many permutations of the USR-W630's configuration (Adaptive baud rate, UART AutoFrame, Registered Packet Type, Modbus Polling enable/disable) and they don't seem to make a difference.

The biggest differences are that you use a tool with umodbus as library and the addon uses pymodbus. The one might retry a bit different…
However I’ve never seen this with mbusd as gateway, so something is probably unique with the W630. Mbusb claims to do advanced rety
the exception you see is simply the client that disconnected.
the addon does also request data much quicker than what you can execute a command line tool repeatedly.
For now all I can think of is trying to reconnect more aggressively (but the fact that the addon cant read the serial number after the watchdog restart indicates that the bridge is not available, so not sure if it will help)

@Ivan-L you can try the (dev) version of the addon... should be visible after you "Check for updates" in the addon store
I've tried the following two PORT_URLs:

tcp://<IP_ADDRESS>:502 to mbusd
serial:///dev/ttyUSB0 direct serial

Thank you @kellerza ! I really didn't expect you to swap out the entire modbus library used!
I managed to install the (dev) version of the addon, but it fails to start, maybe I am doing something silly?
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] done.
[services.d] starting services
[services.d] done.
ifelse: fatal: unable to exec ./run.py: Permission denied
[cmd] ./run.py exited 126
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.

run.py was not executable, please try again

Thanks, that works! I will test this thoroughly. I actually re-did my HA installs last night because my main HA install was HA Core in Docker on my NAS, whereas I was testing this add-on in a completely separate virtual machine with HassOS. I now got HA Supervised to work on my NAS in Docker because the VM was very sluggish. I just have some final MQTT issues to resolve and will get to testing this straight after!

@kellerza I saw you put up a PR with some extra error handling and in the meantime I have set up a local version of this plugin so I can diagnose things better. I cherry picked your error handling and added my own verbose output.
I am learning to speak Modbus over TCP now, but it's daunting 😄
I am documenting this here for my own purposes as well.
Modbus ADU and MBAP (source).

The Application Data Unit (ADU) for Modbus messages carried over a TCP/IP are
build out of two components: a MBAP header and a PDU.
The MBAP header is 7 bytes long

The MBAP header contains the following fields:

Field
Length (bytes)
Description

Transaction identifier
2
Identification of a Modbus request/response transaction.

Protocol identifier
2
Protocol ID, is 0 for Modbus.

Length
2
Number of following bytes

Unit identifier
1
Identification of a remote slave

Read Holding Registers  (source)
The payload for the ReadHoldingRegisters function is as follows.

Implement Modbus function code 03.
The request PDU with function code 03 must be 5 bytes:

Field
Length (bytes)

Function code
1

Starting address
2

Quantity
2

The reponse PDU varies in length, depending on the request.

Field
Length (bytes)

Function code
1

Byte count
1

Register values
Quantity * 2

Analysis
With the above in mind, here is an extract from my logs with the extra verbose output when no error occurs:
2022-02-20 20:55:55,899 DEBUG   send_message_tcp adu: b'u+\x00\x00\x00\x06\x01\x03\x00\xba\x00\x06'
2022-02-20 20:55:55,968 DEBUG     response_error_adu: b'u+\x00\x00\x00\x0f\x01\x03\x0c'
2022-02-20 20:55:55,968 DEBUG     response_error_adu[7:]: b'\x03\x0c'
2022-02-20 20:55:55,968 DEBUG     response_remainder: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x0f'
2022-02-20 20:55:55,969 DEBUG   Request registers: [186, 187, 190, 191] glen=6. Response [0, 0, 0, 0, 7, 15] len=6. regs={186: 0, 187: 0, 188: 0, 189: 0, 190: 7, 191: 15}
2022-02-20 20:55:55,969 DEBUG   PV1 power low=0 high=0 value=0W
2022-02-20 20:55:55,969 DEBUG   PV2 power low=0 high=0 value=0W
2022-02-20 20:55:55,969 DEBUG   Battery power low=7 high=0 value=7W
2022-02-20 20:55:55,969 DEBUG   Battery current low=15 high=0 value=0.15A

Here is my interpretation of the above.
Addon says: b'u+\x00\x00\x00\x06\x01\x03\x00\xba\x00\x06', which is:
Transaction Id: 29995
Protocol: 0
Length: 6
Unit id: 1
Function code: 3
Start address: 186
Quantity: 6 (note here that only 4 registers were requested by the add-on, but they were not contiguous, so 6 satisfies the query)
The inverter responds: b'u+\x00\x00\x00\x0f\x01\x03\x0c' (first part ADU) and b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x0f' (remainder), which is:
Transaction Id: 29995
Protocol: 0
Length: 15
Unit id: 1
Function code: 3
Byte count:  12
Values: (0, 0, 0, 0, 7, 15)
The above all looks great for successful reads.
Now for the unsuccessful reads.

Now here is an extract from the logs where things failed.
2022-02-20 21:59:43,239 DEBUG   send_message_tcp adu (transaction ID b'\x92-'): b'\x92-\x00\x00\x00\x06\x01\x03\x00\xb7\x00\t'
2022-02-20 21:59:43,298 DEBUG     response_error_adu: b'\x92-\x00\x00\x00\x0e\x01\x03\x12'
2022-02-20 21:59:43,299 DEBUG     response_error_adu[7:]: b'\x03\x12'
2022-02-20 21:59:43,318 DEBUG     response_remainder: b'\x13P\x00U\x02&\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00'
2022-02-20 21:59:43,320 DEBUG   Request registers: [183, 186, 187, 190, 191] glen=9. Response [4944, 85, 550, 0, 0, 0, 0, 0, 1280] len=9. regs={183: 4944, 184: 85, 185: 550, 186: 0, 187: 0, 188: 0, 189: 0, 190: 0, 191: 1280}
2022-02-20 21:59:43,321 DEBUG   PV1 power low=0 high=0 value=0W
2022-02-20 21:59:43,321 DEBUG   PV2 power low=0 high=0 value=0W
2022-02-20 21:59:43,321 DEBUG   Battery power low=0 high=0 value=8W
2022-02-20 21:59:43,321 DEBUG   Battery current low=1280 high=0 value=0.17A
2022-02-20 21:59:43,321 DEBUG   Battery voltage low=4944 high=0 value=49.44V
2022-02-20 21:59:44,056 DEBUG   send_message_tcp adu (transaction ID b'I\xe7'): b'I\xe7\x00\x00\x00\x06\x01\x03\x00\xa9\x00\x01'
2022-02-20 21:59:44,118 DEBUG     response_error_adu: b'\x00\x08\x00\x11I\xe7\x00\x00\x00'
2022-02-20 21:59:44,119 DEBUG     response_error_adu[7:]: b'\x00\x00'
2022-02-20 21:59:44,119 ERROR   Read Error: Exception('(1,169,1) 0')
2022-02-20 21:59:45,058 DEBUG   send_message_tcp adu (transaction ID b'\xed\xba'): b'\xed\xba\x00\x00\x00\x06\x01\x03\x00\xa9\x00\x01'
2022-02-20 21:59:45,119 DEBUG     response_error_adu: b'\x05\x01\x03\x02\x026\xed\xba\x00'
2022-02-20 21:59:45,120 DEBUG     response_error_adu[7:]: b'\xba\x00'
2022-02-20 21:59:45,120 ERROR   Read Error: Exception('(1,169,1) 0')
2022-02-20 21:59:46,061 DEBUG   send_message_tcp adu (transaction ID b'\xb4\x91'): b'\xb4\x91\x00\x00\x00\x06\x01\x03\x00\xa9\x00\x01'
2022-02-20 21:59:46,119 DEBUG     response_error_adu: b'\x00\x00\x05\x01\x03\x02\x026\xb4'
2022-02-20 21:59:46,119 DEBUG     response_error_adu[7:]: b'6\xb4'
2022-02-20 21:59:46,119 ERROR   Read Error: Exception('(1,169,1) 180')
2022-02-20 21:59:47,064 DEBUG   send_message_tcp adu (transaction ID b'h\xf5'): b'h\xf5\x00\x00\x00\x06\x01\x03\x00\xa9\x00\x01'
2022-02-20 21:59:47,064 DEBUG     response_error_adu: b'\x91\x00\x00\x00\x05\x01\x03\x02\x02'
2022-02-20 21:59:47,064 DEBUG     response_error_adu[7:]: b'\x02\x02'
2022-02-20 21:59:47,128 DEBUG     response_remainder: b'6h'
2022-02-20 21:59:47,129 WARNING Did not complete read, only read 13/1
2022-02-20 21:59:47,129 DEBUG   Request registers: [169] glen=1. Response [0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1] len=13. regs={169: 0, 170: 1, 171: 1, 172: 0, 173: 1, 174: 1, 175: 0, 176: 0, 177: 0, 178: 1, 179: 0, 180: 1, 181: 1}
2022-02-20 21:59:47,129 DEBUG   Grid load low=0 high=0 value=566W
2022-02-20 21:59:47,129 DEBUG   Load Power low=1 high=0 value=548W
2022-02-20 21:59:47,130 DEBUG   send_message_tcp adu (transaction ID b'\x84Y'): b'\x84Y\x00\x00\x00\x06\x01\x03\x00\xb2\x00\x01'
2022-02-20 21:59:47,130 DEBUG     response_error_adu: b'\xf5\x00\x00\x00\x05\x01\x03\x02\x02'
2022-02-20 21:59:47,130 DEBUG     response_error_adu[7:]: b'\x02\x02'
2022-02-20 21:59:47,198 DEBUG     response_remainder: b';\x84'
2022-02-20 21:59:47,199 WARNING Did not complete read, only read 14/1
2022-02-20 21:59:47,199 DEBUG   Request registers: [178] glen=1. Response [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1] len=14. regs={178: 1, 179: 1, 180: 0, 181: 1, 182: 1, 183: 1, 184: 0, 185: 0, 186: 1, 187: 0, 188: 0, 189: 0, 190: 0, 191: 1}
2022-02-20 21:59:47,199 DEBUG   Load Power low=1 high=0 value=1W
2022-02-20 21:59:47,199 DEBUG   PV1 power low=1 high=0 value=0W
2022-02-20 21:59:47,200 DEBUG   PV2 power low=0 high=0 value=0W
2022-02-20 21:59:47,200 DEBUG   Battery power low=0 high=0 value=0W
2022-02-20 21:59:47,200 DEBUG   Battery current low=1 high=0 value=12.8A
2022-02-20 21:59:47,200 DEBUG   send_message_tcp adu (transaction ID b'\x00Z'): b'\x00Z\x00\x00\x00\x06\x01\x03\x00\xba\x00\x06'
2022-02-20 21:59:47,200 DEBUG     response_error_adu: b'Y\x00\x00\x00\x05\x01\x03\x02\x02'
2022-02-20 21:59:47,201 DEBUG     response_error_adu[7:]: b'\x02\x02'
2022-02-20 21:59:47,279 DEBUG     response_remainder: b'(\x00Z\x00\x00\x00\x0f\x01\x03\x0c\x00\x00'
2022-02-20 21:59:47,279 ERROR   Read Error: Exception('(1,186,6) unpack requires a buffer of 2 bytes')
Traceback (most recent call last):
  File "/usr/src/app/usunsynk.py", line 34, in read
    r_r = await self.client.read_holding_registers(
  File "/usr/src/app/async_modbus.py", line 182, in read_holding_registers
    return await self._send_message(request)
  File "/usr/src/app/async_modbus.py", line 143, in _send_message
    return await self.protocol._async_send_message(
  File "/usr/src/app/async_modbus.py", line 53, in send_message_tcp
    return tcp.parse_response_adu(response_error_adu + response_remainder, adu)
  File "/usr/local/lib/python3.9/site-packages/umodbus/client/tcp.py", line 235, in parse_response_adu
    function = create_function_from_response_pdu(resp_pdu, req_adu)
  File "/usr/local/lib/python3.9/site-packages/umodbus/functions.py", line 138, in create_function_from_response_pdu
    return function.create_from_response_pdu(resp_pdu, req_pdu)
  File "/usr/local/lib/python3.9/site-packages/umodbus/functions.py", line 550, in create_from_response_pdu
    bytes_ = struct.unpack(fmt, resp_pdu[2:])
struct.error: unpack requires a buffer of 2 bytes

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/app/./run.py", line 155, in read
    await SUNSYNK.read(sensors)
  File "/usr/src/app/usunsynk.py", line 38, in read
    raise Exception(f"({self.unit_id},{grp[0]},{glen}) {err}")
Exception: (1,186,6) unpack requires a buffer of 2 bytes

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/app/./run.py", line 250, in <module>
    LOOP.run_until_complete(main(LOOP))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/usr/src/app/./run.py", line 236, in main
    await polltask
  File "/usr/src/app/./run.py", line 228, in poll_sensors
    if await read([f.sensor for f in fsensors]):
  File "/usr/src/app/./run.py", line 168, in read
    raise Exception(f"Multiple Modbus read errors: {err}") from err
Exception: Multiple Modbus read errors: (1,186,6) unpack requires a buffer of 2 bytes
[cmd] ./run.py exited 1
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.

Note the first read is successful, I included it for comparison purposes.
request:
(37421, 0, 6, 1)
(3, 183, 9)
response:
(37421, 0, 14, 1)
(3, 18)
remainder:
(4944, 85, 550, 0, 0, 0, 0, 0, 1280)

The second read failed.
request:
(18919, 0, 6, 1)
(3, 169, 1)
response:
(8, 17, 18919, 0)

Whoa, the response transaction ID does not match the request transaction ID. Furthermore, the response unit ID is 0. Finally, the function code is 17, not 3! This is the cause of the issues. Now I need to find out how we end up in this state.

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!!

@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.

Seems like you nailed it @Ivan-L !!
The intention of allow_gap was to get a balance between the protocol overheads and the data read. If there are unintended consequences when reading undefined registers, like 185 above, we really should not be doing it!
Since there are filters involved we do not need to read everything every second (an ever increasing kwh measurement is a good example, its safe to skip a few) and the amount of registers that needs to be read/output of group_sensors might change...

Thanks @kellerza !
Not sure if I did something wrong here though, but the latest version crashes:
2022-02-22 06:50:45,579 INFO    MQTT: Connecting to sunsynk@core-mosquitto:1883
2022-02-22 06:50:45,617 INFO    MQTT: Connection successful
2022-02-22 06:50:46,156 WARNING Removing HASS MQTT discovery info homeassistant/select/XXXXXX/system_mode_voltages/config
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3452, in _thread_main
    self.loop_forever(retry_first_connection=True)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1779, in loop_forever
    rc = self.loop(timeout, max_packets)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1181, in loop
    rc = self.loop_read(max_packets)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1572, in loop_read
    rc = self._packet_read()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2310, in _packet_read
    rc = self._packet_handle()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2936, in _packet_handle
    return self._handle_publish()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3216, in _handle_publish
    self._handle_on_message(message)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3444, in _handle_on_message
    self.on_message(self, self._userdata, message)
  File "/usr/src/app/mqtt.py", line 247, in __on_message
    _loop.create_task(self.publish(topic, None, retain=True))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 433, in create_task
    task = tasks.Task(coro, loop=self, name=name)
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 748, in call_soon
    self._check_thread()
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 785, in _check_thread
    raise RuntimeError(
RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one
2022-02-22 06:50:46,201 ERROR   Task was destroyed but it is pending!
source_traceback: Object created at (most recent call last):
  File "/usr/local/lib/python3.9/threading.py", line 912, in _bootstrap
    self._bootstrap_inner()
  File "/usr/local/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3452, in _thread_main
    self.loop_forever(retry_first_connection=True)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1779, in loop_forever
    rc = self.loop(timeout, max_packets)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1181, in loop
    rc = self.loop_read(max_packets)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1572, in loop_read
    rc = self._packet_read()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2310, in _packet_read
    rc = self._packet_handle()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2936, in _packet_handle
    return self._handle_publish()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3216, in _handle_publish
    self._handle_on_message(message)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3444, in _handle_on_message
    self.on_message(self, self._userdata, message)
  File "/usr/src/app/mqtt.py", line 247, in __on_message
    _loop.create_task(self.publish(topic, None, retain=True))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 433, in create_task
    task = tasks.Task(coro, loop=self, name=name)
task: <Task pending name='Task-3' coro=<MQTTClient.publish() running at /usr/src/app/mqtt.py:187> created at /usr/local/lib/python3.9/asyncio/base_events.py:433>
/usr/local/lib/python3.9/threading.py:956: RuntimeWarning: coroutine 'MQTTClient.publish' was never awaited
  self._invoke_excepthook(self)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Traceback (most recent call last):
  File "/usr/src/app/filter.py", line 113, in tick
    self.active = [self.list[self.idx]]
IndexError: list index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/app/./run.py", line 252, in <module>
    LOOP.run_until_complete(main(LOOP))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/usr/src/app/./run.py", line 238, in main
    await polltask
  File "/usr/src/app/./run.py", line 224, in poll_sensors
    RROBIN.tick()
  File "/usr/src/app/filter.py", line 116, in tick
    self.active = [self.list[0]]
IndexError: list index out of range
[cmd] ./run.py exited 1
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.

For now add at least one sensor with round_robin filter
try battery_soc or prog1_time

I already had battery_soc. It looks like there is a failure removing old (removed) sensor discovery info. I worked around this by deleting the device created by the add-on and having it recreated. Now I'm only left with this error:
2022-02-22 08:59:13,370 INFO    MQTT: Connecting to sunsynk@core-mosquitto:1883
2022-02-22 08:59:13,397 INFO    MQTT: Connection successful
Traceback (most recent call last):
  File "/usr/src/app/filter.py", line 113, in tick
    self.active = [self.list[self.idx]]
IndexError: list index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/app/./run.py", line 252, in <module>
    LOOP.run_until_complete(main(LOOP))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/usr/src/app/./run.py", line 238, in main
    await polltask
  File "/usr/src/app/./run.py", line 224, in poll_sensors
    RROBIN.tick()
  File "/usr/src/app/filter.py", line 116, in tick
    self.active = [self.list[0]]
IndexError: list index out of range
[cmd] ./run.py exited 1
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.

Config:
SENSORS:
  - battery_soc
  - grid_power
  - grid_voltage
  - load_power
  - essential_power
  - non_essential_power
  - pv1_power
  - pv2_power
  - battery_power
  - battery_current
  - battery_voltage
  - day_grid_import
  - day_grid_export
  - day_pv_energy
  - day_battery_charge
  - day_battery_discharge
PROFILES:
  - system_mode
  - system_mode_voltages

Sensor adding/removing should be working much better in this release as well
I updated it, but serial / fault or prog* are round_robin filters by default

Thanks, I get further but now I get the following error. In hindsight I probably should have created a separate issue for these new errors.
2022-02-22 09:40:36,034 INFO    Profile System Mode action UPDATE
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/sunsynk/usunsynk.py", line 49, in read
    r_r = await self.client.read_holding_registers(
  File "/usr/local/lib/python3.9/site-packages/async_modbus/core.py", line 174, in read_holding_registers
    return await self._send_message(request)
  File "/usr/local/lib/python3.9/site-packages/async_modbus/core.py", line 135, in _send_message
    return await self.protocol._async_send_message(
  File "/usr/local/lib/python3.9/site-packages/async_modbus/core.py", line 36, in send_message_tcp
    tcp.raise_for_exception_adu(response_error_adu)
  File "/usr/local/lib/python3.9/site-packages/umodbus/client/tcp.py", line 247, in raise_for_exception_adu
    pdu_to_function_code_or_raise_error(resp_pdu)
  File "/usr/local/lib/python3.9/site-packages/umodbus/functions.py", line 118, in pdu_to_function_code_or_raise_error
    raise error_code_to_exception_map[error_code]
KeyError: 0

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/app/./run.py", line 252, in <module>
    LOOP.run_until_complete(main(LOOP))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/usr/src/app/./run.py", line 246, in main
    await profile_poll(SUNSYNK)
  File "/usr/src/app/profiles.py", line 179, in profile_poll
    await ss.read(profile.sensors)
  File "/usr/local/lib/python3.9/site-packages/sunsynk/usunsynk.py", line 53, in read
    raise Exception(  # pylint: disable=raise-missing-from
[cmd] ./run.py exited 1
[cont-finish.d] executing container finish scripts...
Exception: (1,268,12) 0
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.

I then removed - system_mode_voltages to avoid that error, which caused a new error:
2022-02-22 09:42:27,169 WARNING Removing HASS MQTT discovery info homeassistant/select/2107307119/system_mode_voltages/config
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3452, in _thread_main
    self.loop_forever(retry_first_connection=True)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1779, in loop_forever
    rc = self.loop(timeout, max_packets)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1181, in loop
    rc = self.loop_read(max_packets)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1572, in loop_read
    rc = self._packet_read()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2310, in _packet_read
    rc = self._packet_handle()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2936, in _packet_handle
    return self._handle_publish()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3216, in _handle_publish
    self._handle_on_message(message)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3444, in _handle_on_message
    self.on_message(self, self._userdata, message)
  File "/usr/src/app/mqtt.py", line 247, in __on_message
    _loop.create_task(self.publish(topic, None, retain=True))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 433, in create_task
    task = tasks.Task(coro, loop=self, name=name)
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 748, in call_soon
    self._check_thread()
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 785, in _check_thread
    raise RuntimeError(
RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one
2022-02-22 09:42:27,221 ERROR   Task was destroyed but it is pending!
source_traceback: Object created at (most recent call last):
  File "/usr/local/lib/python3.9/threading.py", line 912, in _bootstrap
    self._bootstrap_inner()
  File "/usr/local/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3452, in _thread_main
    self.loop_forever(retry_first_connection=True)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1779, in loop_forever
    rc = self.loop(timeout, max_packets)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1181, in loop
    rc = self.loop_read(max_packets)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 1572, in loop_read
    rc = self._packet_read()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2310, in _packet_read
    rc = self._packet_handle()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 2936, in _packet_handle
    return self._handle_publish()
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3216, in _handle_publish
    self._handle_on_message(message)
  File "/usr/local/lib/python3.9/site-packages/paho/mqtt/client.py", line 3444, in _handle_on_message
    self.on_message(self, self._userdata, message)
  File "/usr/src/app/mqtt.py", line 247, in __on_message
    _loop.create_task(self.publish(topic, None, retain=True))
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 433, in create_task
    task = tasks.Task(coro, loop=self, name=name)
task: <Task pending name='Task-3' coro=<MQTTClient.publish() running at /usr/src/app/mqtt.py:187> created at /usr/local/lib/python3.9/asyncio/base_events.py:433>
/usr/local/lib/python3.9/threading.py:956: RuntimeWarning: coroutine 'MQTTClient.publish' was never awaited
  self._invoke_excepthook(self)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
2022-02-22 09:42:29,451 INFO    Profile System Mode action UPDATE
2022-02-22 09:42:29,623 INFO    Updating entity options: ['UPDATE']
2022-02-22 09:42:29,626 INFO    publish SUNSYNK/status/XXXXX/system_mode new_839
2022-02-22 09:42:29,743 ERROR   Read Error: (1,166,2) 0

Deleted the device, restarted the add-on.
Now things seem back to normal, just migrating from grid_load to grid_power at the moment.
I post the above because other users may get these issues as well.

It becomes really interesting once you add your inverter to home assistant's Energy management (then you dont need the day_ sensors, as you get day/month year and much more)
see here for sensors and then configure in your HASS energy management

The KeyError 0 is something unique returned from the USB-W630 (it is not a valid Modbus error!) but will try catch that and fail more gracefully.
For now try removing system_mode as well, just an empty PROFILES: [] - you could try adding the individual sensos that is part of profiles to see if they read properly

So the KeyError 0 issue was previously caused by 4 leading bytes being present in a next subsequent read after reading a bad register (185). I wouldn't specifically catch that error. I actually gave that some thought. It might be better to compare modbus tcp request and response transaction IDs. If they do not match, then thrown an error. The KeyError 0 is just a side effect of this. I'll investigate in more detail to see why this happened for Profile System Mode action UPDATE

So the KeyError 0 issue was previously caused by 4 leading bytes being present in a next subsequent read after reading a bad register (185). I wouldn't specifically catch that error. I actually gave that some thought. It might be better to compare modbus tcp request and response transaction IDs

I'll leave this one as a PR for you, since I'm not really able to generate these faults (at least not from what I've seen with direct serial access or via mbusb)

Happy with that, will look at doing a PR some time this week 👍
Also happy to live with these errors if I am the only one getting them since I now know how to work around them.
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:

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

So I've just tried the following now to rule out a few things.
I stopped my custom python scripts from polling the solarman WiFi dongle and disconnected the dongle entirely. I then disconnected the USR-630 from the inverter BMS RS485 port and connected the USR-630 to the RS232 port where the solarman WiFi dongle was connected to. I used the serial cable that came with the USR-630.

Hi @Ivan-L
I just wanted to confirm whether you were able to communicate with the inverter using the RS232 port, or only using the RS485 port? The above sounds a lot like you were using the RS232 port? If so, can you confirm the protocol that was being used?
Thanks so much!

Hi @RoganDawes,
With the USR-W630 you are able to communicate either through the RS232 port or the RS485 (BMS485) port on the inverter, i.e. the ports are interchangeable. The only extra gotcha with the RS485/BMS485 port is that you should be using Lithium Mode 0 on the inverter. If you are using anything other than 0, then the behaviour of the RS485/BMS485 port may change and your only option may be using the RS232 for monitoring, which would mean that the data logger/dongle would need to be disconnected. I used the RS232 for many months because I found it more stable.
I have since stopped using the USR-W630 and have switched to a Pi Zero W 2 instead and now use the RS485/BMS485 port for monitoring.

That's great, thank you for responding. That suggests that the dongle is indeed using modbus as a protocol, and it might be possible/easy to either convince the dongle to connect to your own server by providing a hosts entry on the router, or via iptables rules. Or alternatively, just flashing the dongle with your own firmware.

it might be possible/easy to either convince the dongle to connect to your own server by providing a hosts entry on the router, or via iptables rules. Or alternatively, just flashing the dongle with your own firmware.

Why would you want to do that though?

it might be possible/easy to either convince the dongle to connect to your own server by providing a hosts entry on the router, or via iptables rules. Or alternatively, just flashing the dongle with your own firmware.

Why would you want to do that though?

To reuse existing hardware that is known working, rather than buying an RS485 dongle and making your own cable, then troubleshooting it? To eliminate the always active WiFi access point that the Sunsynk dongle leaves broadcasting with a psk of 12345678, that might compromise your actual WiFi credentials?

To reuse existing hardware that is known working, rather than buying an RS485 dongle and making your own cable, then troubleshooting it?

I'm not sure whether you'd be able to use the dongle as a pure Modbus TCP to Modbus RTU gateway, like say mbusd on a PI or a USR-W630, but I stand to be corrected. I initially started by polling the dongle with some custom Python scripts but quickly found that the current add-on was much more reliable in terms of getting data every second. The dongle hardware felt flimsy and by polling it, it actually started uploading less data to the cloud, i.e. there would be gaps in the data. Also the dongle would become unresponsive more often the more aggressive I made the custom Python scripts at polling. In the end I left the dongle to only upload to Solarman and use it for the odd firmware update.
There have been some projects which have continued to try to poll the dongle, like the following, though I have not tested them since I'm so happy with the current add-on (especially with writable sensors):
https://github.com/StephanJoubert/home_assistant_solarman
If you do craft some custom firmware for the dongle or manage to put it to good use, then do let us know, that would be very interesting 😄 I see that there have been some hacking attempts here:
https://powerforum.co.za/topic/12604-sunsynk-wifi-dongle-hacking/
But creating a cable and using a PI (or other Modbus gateway) seems simpler. For me at least, I can use the PI for monitoring the BMS in addition to monitoring the inverter.

To eliminate the always active WiFi access point that the Sunsynk dongle leaves broadcasting with a psk of 12345678

I wasn't aware of this. I'll see if I can repro this on my side as that would be very problematic if that is the case.


add EmitterBuilder.combine

Do we have a Monoid on our hands? :)

Do we have a Monoid on our hands? :)

Oh yes, good idea for VDomModifier and EmitterBuilder.

There are even more typeclasses like monads and functors, we should really add for some outwatch types that we currently lack. I have some defined in my app, but I need some time to put them in a PR.

@LukaJCB I have updated the PR to add Monoid instances for VDomModifier and EmitterBuilder as well as adding Functor and Bifunctor for EmitterBuilder.


[Bug] Consecutive calls to setExtraLibs fails to update an interface definition

Reproducible in vscode.dev or in VS Code Desktop?

[X] Not reproducible in vscode.dev or VS Code Desktop

Reproducible in the monaco editor playground?

[ ] Not reproducible in the monaco editor playground

Monaco Editor Playground Code
function updateModelDefinition(propertyName) {
    var filePath = 'ts:filename/model.d.ts';
    var content = `interface Model { ${propertyName}: string }`;
    monaco.languages.typescript.typescriptDefaults.setExtraLibs([{filePath, content}]);
}

monaco.editor.create(document.getElementById('container'), {
	value: `const test: Model = {}`,
	language: 'typescript'
});

// This call works as expected
updateModelDefinition("immediate")

// Bug: Any future calls to setExtraLibs seem to be ignored
setTimeout(() => updateModelDefinition("afterTwoSeconds"), 2000);

setTimeout(() => updateModelDefinition("afterFiveSeconds"), 5000);

Reproduction Steps
Click run in the playground and wait a few seconds to let the timeouts fire and observe that the consecutive calls to setExtraLibs does not have the expected effect.
Actual (Problematic) Behavior
The editor keeps using the code provided by the first call to setExtraLibs, even if its called multiple times with new input.
Observe that the error in the playground example is incorrect:
Property 'immediate' is missing in type '{}' but required in type 'Model'.
Expected Behavior
The editor should respect the most recent call to setExtraLibs.
The playground example should after 2 seconds yield the error:
Property 'afterTwoSeconds' is missing in type '{}' but required in type 'Model'.
The playground example should after 5 seconds yield the error:
Property 'afterFiveSeconds' is missing in type '{}' but required in type 'Model'.

setExtraLibs has this in description

Remove all existing extra libs and set the additional source files to the language service.

You do not change the filepath while updating libs, so the lib is added as new version of existing one. Check it by adding this code to your update method: console.log(monaco.languages.typescript.typescriptDefaults._extraLibs) and see version: 1, version: 2.
If you change  var filePath = 'ts:filename/model.d.ts';  to  var filePath = 'lib:' + propertyName + '/model.d.ts'; then your calls will affect.
I don't use extra libs, I just add my files as new models and everything works fine. Maybe you need to think about this way.

@pennywort I tried your suggestion and while it's true your approach makes setExtraLibs have an effect, it's still seems to not work properly. When I try your suggestion, monaco seems to combine some of the calls to setExtraLibs, which is even more confusing. The documentation says that setExtraLibs clears all previous libs and replaces with the new input.
With your approach I get this error instead:

Which is very strange. It remembers the first call, and the last, but not the intermediate.
Btw, is there anywhere I can read about how to work with models and extra libs? The monaco editor website only has examples and a pretty slim api doc. It's really hard to grasp how you're supposed to use certain APIs.

Yes, this strange effects are fixed by adding model for each extra lib (libs are used for d.ts accordingly to docs).
By the way, this is recommended in playground:
var libUri = 'ts:filename/facts.d.ts';
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, libUri);
// When resolving definitions and references, the editor will try to use created models.
// Creating a model for the library allows "peek definition/references" commands to work with the library.

If you add the model for each lib, everything will work as you expect.
If you want dynamically manipulate your libs you may need this:
const extraLibs = [];
function updateModelDefinition(propertyName) {
    var filePath = `ts:${propertyName}/model.d.ts`;
    var content = `interface Model { ${propertyName}: string }`;
    const extraLib = monaco.languages.typescript.typescriptDefaults.addExtraLib(content, filePath);
    const model = monaco.editor.createModel(content, 'typescript', monaco.Uri.parse(filePath));
    model.removeMe = true;
    extraLib.removeMe = true;
    extraLibs.push(extraLib);
}

monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);

monaco.editor.create(document.getElementById('container'), {
	value: `const test: Model = {}`,
	language: 'typescript'
});

setTimeout(() => {
    console.log('now removing models and libs...');
    console.log('models count: ', monaco.editor.getModels().length);
    monaco.editor.getModels().forEach(model => model.removeMe && model.dispose());
    extraLibs.forEach(lib => lib.removeMe && lib.dispose());
    console.log('models count: ', monaco.editor.getModels().length);
}, 10000)

// This call works as expected
updateModelDefinition("immediate")

// Bug: Any future calls to setExtraLibs seem to be ignored
setTimeout(() => {
    console.log(monaco.languages.typescript.typescriptDefaults._extraLibs)
    updateModelDefinition("afterTwoSeconds")
}, 2000)

setTimeout(() => {
    console.log(monaco.languages.typescript.typescriptDefaults._extraLibs)
    updateModelDefinition("afterFiveSeconds")
}, 5000);

You may play with commenting line where models are added and see the result of this. So I can't tell you how to use and combine models, libs and whatever correctly. I'm flying blind when working with monaco.
It would be great to have a video guide or an article with good practices and approaches.

@kasper573 @pennywort  , I think #4544 fixes this issue, but it seems like we need some more community approvals to continue. Could you look and test that PR?


Android Studio 1.1+ works with Java 7 and 8

As of version 1.1, Android Studio already bundles this on Info.plist:
<key>JVMVersion</key>
<string>1.6*,1.7+</string>

From what I'm seeing on my machine, with jdk1.8.0_20, we don't need to show the caveats for users nor need to set a environment variable. What the Android Studio is doing is the same we did some time ago, updating the Info.plist to 1.6+.
After this version, I think we can close #7996 too.

yeeeey! :tada: I wish to see similar news about other IntelliJ IDEs... :smiley:
I will have a look at this most likely on Saturday, really just want to double check that everything works with both Java 7 & 8. If another maintainer thinks it's too late for this, feel free to test & merge.

This is going to be merged in a separate commit because it still requires Java.
The credit (git author) still goes to you.
Thanks.


[Question] How to return a dict model?

Hello, I want to use get_genshin_user but printed in dict model, not a class model. Is it possible to return a dict model?

user = client.get_genshin_user(uid)
return user.dict()


The example file does not generate the same pdf as in the result folder in GitHub

Hi, thanks for sharing your interesting work.
I have tried with the AHYIJDV sample file:
python hrosad_offline.py  --myphd_id AHYIJDV --heart_rate AHYIJDV_hr.csv --steps AHYIJDV_steps.csv -outliers_fraction 0.1  --random_seed 10
the result pdf file in the Github does not match the result I got.
It seems you have not updated your results on GitHub after your latest modification of hrosad_offline.py
https://github.com/gireeshkbogu/AnomalyDetect/commit/37fa5759842c4539f657ebcc160052a8da296895
The pity thing is the result, which is most updated one, does not seem sexy!!!
Best Regards

Can you please show me what did you get?


Ramp up James on cloud.gov team

This is the standard onboarding checklist that we use to help new team members join cloud.gov. @jameshupp, you've worked on cloud.gov before so perhaps you are already familiar with some of these resources and materials. Nonetheless, take a look and feel free to ask me about anything at all.
Directions:
James and Nikki: Try to go through your checklists in order.
Nikki: If you can’t complete any of the items on your checklist personally, you are responsible for ensuring that an appropriate person does it.
James's checklist

[ ] Take judicious notes on what about this onboarding process or cloud.gov is confusing or frustrating. If you notice a problem (especially with things like documentation), you are more than welcome to fix it! At the very least, please share this information with your buddy (or someone) at some point so we can make the team/platform better. (You can also file issues and pull-requests on the template for Onboarding issues.)
[ ] Figure out who your onboarding buddy is (they should reach out to you) and make sure this issue is assigned to them)
[ ] Read the team onboarding document for more context about cloud.gov
[ ] Read the "What is it?" presentation for a rundown of what cloud.gov is and does
[ ] Read through the Introduction section of docs.cloud.gov for a broader understanding of cloud.gov, especially as we present it to potential customers/users
[ ] Read the January 2016 cloud.gov "Executive Business Case" document for greater context about cloud.gov's potential impact in government
[ ] Try to deploy a sample application to cloud.gov to get familiar with the basics of the PaaS from a user's perspective
[ ] Check out the roadmap to get a high-level view of recently-completed, in-progress, and upcoming features
[ ] Install the ZenHub browser extension to enable you to see kanban boards, hierarchical issues, and burndown charts in GitHub
[ ] Read the Delivery Process document to learn about how we work
[ ] Read the Incident Response Policy and Incident Response Guide. Coordinate with your onboarding buddy to go through Incident Response Training within 60 days of joining the team
[ ] Read the Contingency Planning Policy and Contingency Plan. Coordinate with your onboarding buddy to go through Contingency Planning training annually
[ ] Read the Configuration Management Policy and Configuration Management Plan. Coordinate with your onboarding buddy to go through Configuration Management training
[ ] Subscribe to the cloud.gov team calendar (click the + in the bottom right) so you know when assorted team meetings are happening in the various streams
[ ] Join the cloud.gov support Google Group, so you can see how we handle non-18F support and get visibility of technical discussions happening with outside groups
[ ] Figure out what themes you're likely to work in, and complete the checklist below that relates to it
[ ] Once you've finished the remaining checklists below, make suggestions for steps that would have improved your onboarding experience as pull-requests on the onboarding checklist template used to make this issue

Skyporter-specific items

[x] view cg-product as a board, filter by the Skyporter label to see existing issues that we have

Buddy checklist

[x] Introduce yourself to the new team member and give them some of your background so they know who you are
[ ] Make sure they're listed in the list of people working on the project
[ ] Add them to the @cloud-gov-team in Slack’s Team Directory (which also adds them to the right channels)
[ ] Add them to the recurring cloud.gov meetings that are relevant for them in the team calendar
[ ] Setup a cloud.gov user account for them via the “send an invite” page
[ ] Identify a straightforward, well-groomed story in progress that involves their skills domain, schedule a meeting with the owner for an introduction (if it's not you), and setup pairing sessions several times in the first week on the project.
[ ] Identify a straightforward, well-groomed first story, ideally something they could conceivably complete in their first two/three weeks using their existing skills. Discuss the context with them, then make them the assignee for the card.
[ ] Make suggestions for how your onboarding experience could have been improved as PRs on the onboarding template.
[ ] Confirm they have 2FA enabled for GitHub, and ask #admins-github to have them added to the @18F/cloud.gov team on GitHub

Oops we have duplicate issues! See https://github.com/18F/cg-product/issues/334 - Nikki and James, up to you how you'd like to resolve this - feel free to close mine if that's easiest. :)

It doesn't matter to me who the buddy is, though I remember @brittag volunteering at the stand-up yesterday. We should use the other issue because it is based on the latest version of the Onboarding Checklist, which includes a bunch of compliance-specific points.

Since this is a dupe, I'm closing it. @jameshupp always feel free to ping me. And I will keep sending you relevant resources related to the business side of things.


bump to 1.9.3

tested a lot on a temporary branch to ensure beta builds would work, along with updates to publishing on main. Bumping above the current 1.9.1 and 1.9.2 tests in branch, to bring main up to 1.9.3 and avoid collisions.

:tada: This PR is included in version 1.0.0 :tada:
The release is available on GitHub release
Your semantic-release bot :package::rocket:


StackedBar chart  with Horizontal bars

Hello,
I want to show StackedBar chart with Horizontal bars . but can not find how to do it.
can you please guide.
Thanks,

I also facing the same issue. Please provide the answer.

I need something like this

any of you find a solution to the above?


pkg/*/statefulset.go: Do not mutate shared object

Users have reported high CPU usage of the Prometheus Operator when
adding an annotation to a Prometheus object. The Operator would update
the respective StatefulSet in an infinite loop.
Whether a given StatefulSet needs updating is determined by the hash of
the inputs needed to generate the StatefulSet, which is calculated and
then attached to the StatefulSet as an annotation. On subsequent
reconciliations this hash is compared to the hash of the new inputs.
The function to build the StatefulSet definition is passed the
Prometheus object. This is done by value, not by reference. This does
not enforce a deep copy but merely a shallow copy. In the build function
the new StatefulSet would inherit the annotation map of the Prometheus
object. Next the input hash would be added to this map, resulting in
both the Statefulset having the hash annotation, as intended, as well as
the Prometheus object (same map, shared as a reference).
On subsequent reconciliations the same Prometheus object is used to
calculate the input hash, this time accidentally containing the has
annotation from the previous run. Even though the actual inputs never
changed, this results in a new hash, thereby updating the StatefulSet,
...
The solution is to deep copy the Prometheus object before using it in
the StatefulSet build function, thereby never mutating the annotations
of the Prometheus object. Same measure is taken for the Alertmanager
StatefulSet build function.

Related to https://github.com/coreos/prometheus-operator/issues/1659

I would create a patch release once this is merged. What do you think @brancz @squat @s-urbaniak?

I would create a patch release once this is merged. What do you think @brancz @squat @s-urbaniak?

Sounds good.

This commit breaks the following test: https://github.com/coreos/prometheus-operator/blob/master/pkg/prometheus/statefulset_test.go#L57
This is expected, because the test checks that labels and annotations are identical on the prometheus object and the statefulset, even though the statefulset gets new annotations: https://github.com/coreos/prometheus-operator/blob/33a84937182c3f2b159dd6a5e9501afc11826d87/pkg/prometheus/statefulset.go#L174.
We need to adjust the test to check that all prometheus object annotation are included in the statefulset annotations, not that they are equal.

I would create a patch release once this is merged. What do you think @brancz @squat @s-urbaniak?
sounds fine with me :heavy_check_mark:

lgtm on green!

Thanks for the feedback!


feature: added config pg schema

feature: added config pg schema
chore: bump version to 2.0.0-beta.8

@MKRhere Hi! I need to configure Postgres schema, please do review
Best regards,
Nikolay.


Users should be allowed to replace non-edited default pull request templates

Currently, VSTS pull requests only allow a user to "append" the description field when adding an alternative pull request template from the "Add a template" drop-down. However, there exists a common scenario in which a user creates a new pull request with the intent of using an alternative pull request template other than the default template. For this scenario, the user has to manually clear the description field of the pull request prior to adding the desired alternative template.
Perhaps an action item should be created that will allow users to conveniently replace non-edited pull request descriptions, that have been pre-populated with default pull request templates, with the desired alternative templates.

Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

ID: a297d54f-48b3-1b68-e828-15d1559d9b2d
Version Independent ID: fd9dcb35-72f9-f5a9-e0c0-75c3e59ba8d9
Content: Improve your pull request descriptions using pull request templates - Azure Repos
Content Source: docs/repos/git/pull-request-templates.md
Product: devops
GitHub Login: @steved0x
Microsoft Alias: sdanie

@eddylu94 That is a great feature idea. I am going to pass that along to the product team. Feature requests and product feedback carry more weight when they come directly from customers, so if you had a moment, please file your request here and it will go straight to the team: https://developercommunity.visualstudio.com/spaces/21/index.html
Thank you.


License ?

Hello, under what license is this project released under ? I would like to study it to figure out some implementation details from your paper. Thank you.

Thanks for your interest. The project is under Apache-2.0 license.


fluent-plugin-elasticsearch should be upgraded to avoid Content-Type deprecation warnings

With Elasticsearch >= 5.3, REST requests without a Content-Type will generate a warning log :
Content type detection for rest requests is deprecated

This has been fixed in fluent-plugin-elasticsearch 1.9.4 via https://github.com/uken/fluent-plugin-elasticsearch/pull/250
Is it possible to bump the version at least to this one ? The current latest version is 1.9.5.

Sounds good to me. Would you be able to send in a PR?

Sure ! work in progress.

Awesome thanks @cbonte!

PR #27 is available.

Hi @jimmidyson ! Is it possible to merge the PR ? Also, is it possible to plan a new release ?
Thanks.

Done @cbonte! v1.21 should be available on Docker Hub soon.

Upgraded with the 1.21 image, everything looks OK. I close the issue ;-)

Thanks!


attic check results in error "attic: Error: Inconsistency detected. Please run "attic check ...""

I try to extract a backup, "attic list" took ages and finally exited with the error message:
attic: Error: Inconsistency detected. Please run "attic check ..."
running "attic check ..." exits the archive consistency check with the same error message.
Also trying to execute check with --repair does not succeed.
I'm running attic 0.13 on a fresh Ubuntu 15.10.
Any idea how I get my data back?

come to freenode irc #attic maybe we can find a solution. create a copy of your backup repo for experiments.

Thanks for the help!
It turned out for some reason the manifest got lost. Updating to 0.16 and running attic check --repair fixed the problem.


[StyleCop] Fix all warnings in Bot.Schema.Test project

Add trailing comma in multi-line initializers

Replaced with #1505


Any idea if a PHP API example is....

Any idea if a PHP API example is in the works????
Do you have any opensource PHP stuff for eGauge?

There is nothing actively being developed for the purposes of PHP examples.
What is the particular functionality you are looking for (fetching historical, instantaneous, capturing push, etc...)?


Added reference to the TextField to be able to focus via refs

This should be backwards compatible
Tested using the updated component

Can you provide a more detailed example please?
I don't know how to access it if it's defined inside PasswordInputText.
We need to be able to call focus() on the input from the TextField

I am updating my code so you can refer latest code for this.


Add metrics for Resiliency

We need to add request count and error rates for:

Retries
Circuit Breakers
Timeouts

The label should contain the component name and namespace.
Before Merging complete docs https://github.com/dapr/docs/issues/2401

Metric Name
Description
Type
Tags

total
Number of resiliency policies loaded
UnitDimensionless
name  namespace  policy

count
Number of times a resiliency policy has been executed
UnitDimensionless
name  namespace  policy

Tags

Name
Description

name
Name of the resiliency policy

namespace
The namespace of the policy

policy
Values: retry, timeout, circuitbreaker

total and count are not descriptive enough since they are measuring different things (loaded count vs execution count). Does it make sense to have total since there is always one policy per name, not?
I propose we just have count or execution_count and it would avoid the confusion.
If we really think load_total is needed, we can have loaded or load_count and it would always emit this metric when the given policy is loaded.

I think that removing the policy tag makes more sense now. LGTM.

What is the meaning of name tag? Is it the policy's name?

@artursouza updated the list based on convo.

would it be useful to capture more detailed metrics for circuit breakers like, number of times operation was called in half-open state and open state ?
I declared on chat that I would work on  this but I had to take couple days off recently. Sorry for not starting this earlier.

I was thinking about following metrics:

Metric name
Description
Type
Tags

circuitbreaker_too_many_req/count
The number of execution attempts in half-open state when request count is over maxRequest
UnitDimensionless
app_id, namespace, operation_name, name (optional)

circuitbreaker_half_open/failure_count
The number of execution failures when cb is in half-open state and request count < maxRequest
UnitDimensionless
app_id, namespace, operation_name, name (optional)

circuitbreaker_open/count
The number of execution attempts in open state.
UnitDimensionless
app_id, namespace, operation_name, name (optional)

Tags:
operation_name - operation name for Policy
name - would be optional since it's cb.Name is part of operation_name
It might be useful to have those metrics for troubleshooting.

I was thinking about following metrics:
Metric name	Description	Type	Tags
circuitbreaker_too_many_req/count	The number of execution attempts in half-open state when request count is over maxRequest	UnitDimensionless	app_id, namespace, operation_name, name (optional)
circuitbreaker_half_open/failure_count	The number of execution failures when cb is in half-open state and request count < maxRequest	UnitDimensionless	app_id, namespace, operation_name, name (optional)
circuitbreaker_open/count	The number of execution attempts in open state.	UnitDimensionless	app_id, namespace, operation_name, name (optional)
Tags: operation_name - operation name for Policy name - would be optional since cb.Name is part of operation_name
It might be useful to have those metrics for troubleshooting.

@piotrkpc These are good metrics to have for troubleshooting as you pointed out. my only concern is in regards to making metrics volume size bigger. This is already an issue today, as Dapr metrics are already rather verbose and when sent to an out-of-cluster metrics store, this incurs some serious egress fees. Considering this is used for troubleshooting mainly (as opposed to monitoring aggregated data points), I'm asking myself if it won't be easier to diagnose issues using more verbose debug logs for resiliency which we're adding over time.
I suggest we do this in stages: would it be OK for you to open a PR that adds the metrics proposed here while we continue the discussion?