homeassistant-solax-modbus
homeassistant-solax-modbus copied to clipboard
add optional scan_interval for sensors
I added the "scan_interval" option for each sensor.
I implemented everything, grouping by interval, etc. Of course it doesn't really make sense with many groups. When not defined (<=0), the default hub interval is used.
I'm using scan_interval = 3s for very fast updates (only the grid power, I intend to use it as feedback), 10s for a few fast updates (PV Voltage, Power, Battery Power). Everything else is at default, 1min for me.
I hope someone else finds this useful... I also have another plugin where I'm using this, it's quite basic at this time.
Gabriel
I added a few other changes: internal sensors (helpers for selects), plugin/device model First public version for Solinteg inverter
Forgot to mention. All changes are backward compatible. No modifications required for plug-ins, everything remains the same without changes.
With using different polling intervals due you find out are getting a lot of blocks to read? I'm just wondering if on some Inverters it will overload them, as some Inverters don't fully comply with Modbus and might struggle with even more requests.
On my SolaX I'm only reading 5 blocks, although the first one really only needs to be read on start up.
2024-04-13 21:18:20.225 INFO (MainThread) [custom_components.solax_modbus.sensor] SolaX returning holding block: 0x0 0x7 [0]
2024-04-13 21:18:20.225 INFO (MainThread) [custom_components.solax_modbus.sensor] SolaX returning holding block: 0x7d 0xbc [125, 129, 130, 131, 132, 133, 139, 140, 141, 142, 143, 144, 145, 146, 148, 154, 156, 166, 170, 175, 180, 181, 182, 186, 187]
2024-04-13 21:18:20.225 INFO (MainThread) [custom_components.solax_modbus.sensor] SolaX returning holding block: 0xe8 0x118 [232, 233, 253, 254, 256, 258, 259, 260, 263, 264, 265, 266, 267, 271, 272, 273, 274, 275, 277, 278, 279]
2024-04-13 21:18:20.225 INFO (MainThread) [custom_components.solax_modbus.sensor] SolaX returning input block: 0x0 0x55 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 19, 20, 21, 22, 23, 24, 28, 29, 32, 33, 35, 36, 37, 70, 72, 74, 80, 82, 84]
2024-04-13 21:18:20.225 INFO (MainThread) [custom_components.solax_modbus.sensor] SolaX returning input block: 0x66 0xba [102, 103, 104, 105, 140, 145, 146, 148, 150, 152, 154, 156, 168, 170, 172, 174, 176, 184, 185]
I'm able to reliably poll at 1s. But other Inverts struggle below 5, having even more blocks to read could put further strain on them?
On my inverter (Solinteg) I also have no problems, I'm reading only power related in 5s, a few other in 15s, the rest with 60s. I have just checked... 60s group: 2024-04-18 10:07:40.753 INFO (MainThread) ... PV returning holding block: 0x271b 0x2780 2024-04-18 10:07:40.753 INFO (MainThread) ... PV returning holding block: 0x2af2 0x2b0e 2024-04-18 10:07:40.753 INFO (MainThread) ... PV returning holding block: 0x61bc 0x6210 2024-04-18 10:07:40.754 INFO (MainThread) ... PV returning holding block: 0x762e 0x7630 2024-04-18 10:07:40.754 INFO (MainThread) ... PV returning holding block: 0x7918 0x798c 2024-04-18 10:07:40.754 INFO (MainThread) ... PV returning holding block: 0x7d03 0x7d04 2024-04-18 10:07:40.754 INFO (MainThread) ... PV returning holding block: 0x80e9 0x8100 2024-04-18 10:07:40.754 INFO (MainThread) ... PV returning holding block: 0xc350 0xc357 2024-04-18 10:07:40.754 INFO (MainThread) ... PV returning holding block: 0xcd16 0xcd7c
15s group: 2024-04-18 10:07:40.769 INFO (MainThread) ... PV returning holding block: 0x2779 0x277a 2024-04-18 10:07:40.769 INFO (MainThread) ... PV returning holding block: 0x2b1e 0x2b3a 2024-04-18 10:07:40.769 INFO (MainThread) ... PV returning holding block: 0x7616 0x7634 2024-04-18 10:07:40.769 INFO (MainThread) ... PV returning holding block: 0x80e8 0x80e9
5s group: 2024-04-18 10:07:40.771 INFO (MainThread) ... PV returning holding block: 0x2af8 0x2b16 [11000, 11016, 11028]
Maybe another option would be helpful, min delay between reading blocks. Right now all blocks are are read one after the other, but when someone has problems, e.g. 0.1..1 s delay between blocks could help
This is also helpful
I added a few other changes: internal sensors (helpers for selects),
I don't like having duplicated sensors for selects/numbers, therefore "internal" flag is used to avoid publishing.
plugin/device model
Just nice to read
All is visible in my solinteg plugin
Another question... I'm quite new to HA / Python / Asyncio. I don't know if the callbacks from async_track_time_interval could be parallel? If yes, async_refresh_modbus_data and below might not work properly; a lock would easily solve this.
I don't know if the callbacks from async_track_time_interval could be parallel?
I'm not great with python either.
If yes, async_refresh_modbus_data and below might not work properly; a lock would easily solve this.
We previously had to remove locks, as that was causing issues on some Inverters. Although at the moment it's difficult to know if an issue is: Integration, Inverter or pyModbus driven at the moment as I can't replicate any of the issues and there is know problems with pyModbus it seems.
On my inverter (Solinteg) I also have no problems, I'm reading only power related in 5s, a few other in 15s, the rest with 60s. I have just checked...
So you are having to do 14 transactions to read far fewer registers than am doing with 5 transactions on mine. I would have expected that to increase the workload.
Modbus should be able to return over 120 registers in a single transaction. I know on the Solis we have had to cut this down to 40 registers in a block. The docs state you can only read 50 at once which is short of the Modbus standard and we found more than 40 was a problem.
Perhaps the issue with some Inverters is they don't have a fast enough CPU / Microcontroller or enough space to cache so many registers?
I see you have the following set:
INTERVAL_MPPT = 0 #not special
Does that mean your not reading the PV stuff, as you're using a Hybrid Inverter as an AC battery system with no PV connected?
Or does the poll interval default to what you have set in the config_flow?
I don't know if the callbacks from async_track_time_interval could be parallel?
I'm not great with python either.
If yes, async_refresh_modbus_data and below might not work properly; a lock would easily solve this.
We previously had to remove locks, as that was causing issues on some Inverters. Although at the moment it's difficult to know if an issue is: Integration, Inverter or pyModbus driven at the moment as I can't replicate any of the issues and there is know problems with pyModbus it seems.
I mean avoiding parallel /reentrant calls; a lock should be no problem, will try to read about this..
On my inverter (Solinteg) I also have no problems, I'm reading only power related in 5s, a few other in 15s, the rest with 60s. I have just checked...
So you are having to do 14 transactions to read far fewer registers than am doing with 5 transactions on mine. I would have expected that to increase the workload.
Modbus should be able to return over 120 registers in a single transaction. I know on the Solis we have had to cut this down to 40 registers in a block. The docs state you can only read 50 at once which is short of the Modbus standard and we found more than 40 was a problem.
Perhaps the issue with some Inverters is they don't have a fast enough CPU / Microcontroller or enough space to cache so many registers?
This depends on inverter; mine uses a lot of virtual addresses. But the "fast" reads is only 1 block; many blocks are in 60s interval, a lot better. My changes don't enforce anything; one can test whether to read faster.
I see you have the following set:
INTERVAL_MPPT = 0 #not special
Does that mean your not reading the PV stuff, as you're using a Hybrid Inverter as an AC battery system with no PV connected? Or does the poll interval default to what you have set in the config_flow?
Yes, I used that constant to read some MPPT related fields (V,A,P); to debug MPPT function itself. But generally yes, the interval is only used when > 0, otherwise the default config value. See SolaXModbusHub.entity_group()