wills106 / homeassistant-solax-modbus

SolaX Power Modbus custom_component for Home Assistant (Supports some AlphaESS, Growatt, Sofar, Solinteg, Solis, SRNE, Swatten)
317 stars 101 forks source link

[Bug]: Growatt - 'MOD x' Unknown state on all entities after upgrade #979

Closed Zvolli closed 2 months ago

Zvolli commented 2 months ago

Describe the bug

After upgrading to 2024.08.6 all entities are in a "unknown" state. Followed instructions after warning by removing SolaX and re-install but this had no effect. Tried uninstalling and downgrade to 2024.08.2 but it is downloading 202.08.6 version regardless.

image

Integration Version

2024.08.6

Homeassistant core version

2024.7.4

Inverter brand

Growatt

Plugin used

plugin_growatt.py

Serial prefix

DL1.0ZBAA

Connection Method

ESP32 modus bridge for RS485

Detailed Error Log

home-assistant_2024-08-05T08-08-42.780Z.log

_Logger: homeassistant.components.sensor Source: helpers/entity_platform.py:364 integration: Sensor (documentation, issues) First occurred: 8:55:05 AM (1 occurrences) Last logged: 8:55:05 AM

Error while setting up growatt_server_api platform for sensor Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 364, in _async_setup_platform await asyncio.shield(awaitable) File "/config/custom_components/growatt_server_api/sensor.py", line 88, in async_setup_entry devices, plant_id = await hass.async_add_executor_job(get_device_list, api, config) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 58, in run result = self.fn(*self.args, **self.kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/growatt_server_api/sensor.py", line 51, in get_device_list user_id = login_response["user"]["id"]


KeyError: 'user'

Logger: aiohttp.server
Source: /usr/local/lib/python3.12/site-packages/aiohttp/web_protocol.py:421
First occurred: 8:59:30 AM (5 occurrences)
Last logged: 9:54:39 AM_
---------------------------------------------------------------------------------------------------------------------------------------
_Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_protocol.py", line 350, in data_received
    messages, upgraded, tail = self._request_parser.feed_data(data)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "aiohttp/_http_parser.pyx", line 557, in aiohttp._http_parser.HttpParser.feed_data
aiohttp.http_exceptions.BadStatusLine: 400, message:
  Invalid method encountered:

    b'\x16\x03\x01'
      ^_

### Additional context

_No response_
Ivootje66 commented 2 months ago

Same here, tried everything. I use some of the enteties in my automatisations which don’t work also anymore.

Ivootje66 commented 2 months ago

Update 8-8 : Deleted the last version of Solax en manually installed version 2024.05.07 through zip file.

Now everyting is working again. Also (for now) disabled automatic polling for updates for the Solax integration.

mikaabra commented 2 months ago

Same problem here, upgraded to latest solax-modbus version 2024.08.8 and HA 2024.8.1 and got entity result unknowns. Deleted the device and tried to recreate it again, just get unknowns still.

Growatt 15KTL3-X using modbus TCP via a waveshare RS485-ethernet gateway.

My own modbus entities I have created myself (before the solax integration worked with my inverter) still works as expected, so this seems to be a solax-modbus problem.

I downgraded to 2024.05.7 and now everything works again.

JohNan commented 2 months ago

I have the same problem. I enabled debug logs and saw these lines

2024-08-22 22:19:20.715 DEBUG (MainThread) [custom_components.solax_modbus] device group inverter
2024-08-22 22:19:20.716 DEBUG (MainThread) [custom_components.solax_modbus] Growatt modbus holding block start: 0x9 end: 0x33  len: 42
2024-08-22 22:19:20.846 DEBUG (MainThread) [custom_components.solax_modbus] treating register 0x09 : firmware_version
2024-08-22 22:19:20.847 DEBUG (MainThread) [custom_components.solax_modbus] treating register 0x0c : firmware_control_version
2024-08-22 22:19:20.847 DEBUG (MainThread) [custom_components.solax_modbus] treating register 0x0f : language
2024-08-22 22:19:20.847 DEBUG (MainThread) [custom_components.solax_modbus] skipping bytes 12
2024-08-22 22:19:20.847 DEBUG (MainThread) [custom_components.solax_modbus] treating register 0x16 : select_baud_rate
2024-08-22 22:19:20.847 DEBUG (MainThread) [custom_components.solax_modbus] treating register 0x17 : serialnumber
2024-08-22 22:19:20.848 DEBUG (MainThread) [custom_components.solax_modbus] treating register 0x1c : inverter_module
2024-08-22 22:19:20.848 DEBUG (MainThread) [custom_components.solax_modbus] skipping bytes 30
2024-08-22 22:19:20.848 DEBUG (MainThread) [custom_components.solax_modbus] treating register 0x2d : rtc
2024-08-22 22:19:20.848 DEBUG (MainThread) [custom_components.solax_modbus] Growatt modbus holding block start: 0x7a end: 0xbb9  len: 2879
2024-08-22 22:19:21.596 INFO (MainThread) [custom_components.solax_modbus] read_error : Growatt cannot read holding registers at device 1 position 0x7a
2024-08-22 22:19:21.600 DEBUG (MainThread) [custom_components.solax_modbus] assuming sleep mode - slowing down by factor 10
2024-08-22 22:19:21.600 DEBUG (MainThread) [custom_components.solax_modbus] device group read done

Not sure if it helps, but at least it says that it wasn't able to read some registers.

I have another integration also for my Inverter and that works. So something happened to SolaX with the 2024.8 release

cracyfloyd commented 2 months ago

I have the same problem. Growatt 6000TL3-XH, ARK XH Batterysystem and using modbus TCP via a waveshare RS485-ethernet gateway. With Version 2024.05.7 all works well.

wills106 commented 2 months ago

Just released 2024.08.12 removing "Inverter Module" may or may not help.

cracyfloyd commented 2 months ago

Just released 2024.08.12 removing "Inverter Module" may or may not help.

For me the last version doesnt solve the problem. Growatt 6000TL3-XH, ARK XH Battery System using modbus TCP via a waveshare RS485-ethernet gateway. I ve tested a little bit more and i can say thats the last version that run is 2024.08.2

wills106 commented 2 months ago

@cracyfloyd what errors are you getting in the error log? If there are non check you have the correct level of warnings as per the FAQ

cracyfloyd commented 2 months ago

@cracyfloyd what errors are you getting in the error log? If there are non check you have the correct level of warnings as per the FAQ

Here is a debug log after restart.

solaxerror.txt

cracyfloyd commented 2 months ago

@cracyfloyd what errors are you getting in the error log? If there are non check you have the correct level of warnings as per the FAQ

Another Error log: home-assistant_2024-08-26T08-11-25.975Z.log

JohNan commented 2 months ago

When debugging the code I get an exception that is not visible in the logs. Reading the holding registers throws this exception: Exception Response(131, 3, IllegalFunction) from AsyncModbusTcpClient.

I've tried to found out why this happens but cannot understand why.

regs: [9, 12, 15, 22, 23, 45, 3000]

TonyMathiesen commented 2 months ago

I have a MOD TL-XH (SN Prefix DN1) but believe it is the same issue as DL1. (Both GEN3) 2024.05.7 worked fine - now found what is causing it in 2024.08.1x, at least it worked for me to modify the plugin_growatt.py file.

GEN3 needs to be removed from register 3000: image

As this register is for something different according to the Modbus documentation v.1.24 I found: image

JohNan commented 2 months ago

I can confirm that removing GEN3 from those two sensors solves it. Thank you @TonyMathiesen

wills106 commented 2 months ago

Just released 2024.08.13

Zvolli commented 2 months ago

Confirming that the 2024.08.13 solved the unknown state. However import and export on MOD inverter are still missing

wills106 commented 2 months ago

However import and export on MOD inverter are still missing

Were they there previously? Or have they always been missing?

Zvolli commented 2 months ago

Always missing to my knowledge. We actually discussed this in a previous post/ticket. Something that you where missing the correct address from Growatt.

wills106 commented 2 months ago

It might be worth either yourself @Zvolli or @JohNan / @TonyMathiesen to try and add GEN3 to some of the GEN2 or GEN4 looking import / export values.

The MOD inverters seem to overlap the two main register sets. (GEN2, GEN3 & GEN4 aren't actual Generation differences like on SolaX, but I'm trying to split the register sets out somehow)

TonyMathiesen commented 2 months ago

Yes you are right. There are overlapping registers making it tricky to understand with the limited documentation available. I have played around with it for two days trying understand the logic in order to get it added into Home Assistant.

What I have found os far for the the MOD TL-XH (most likely the same for TL-X): It uses 8-bit holding registers in the range 0-124 and 3000-3124. It used a mixture of 8/16-bit input registers in the range 3000-3124, 3125-3249 AND the two ranges 3000-3124 are overlapping and creates confussion and conflicts.

I have gotten the majority for them to work and added some additional to my plugin_growatt.py file. Will just make a description of what I have modified and added. If one of you can maybe assist with the pull request and stuff - as I am not programmer and only know how to comment.

wills106 commented 2 months ago

I think @iobrokerneu with #791 maybe able to help as well.

Hopefully with the 4 of you we can get better support of the MOD series. Or at least further break down the differences if there are any?

Zvolli commented 2 months ago

Sure I’ll do whatever I can from my side 😊

TonyMathiesen commented 2 months ago

For Growatt MOD TL-XH (likely also TL-X) GEN3 changes to the plugin file:

Adds configuration: EPS Switch (register 3079) EMS Discharging Rate (register 3036) EMS Discharging Stop SOC (register 3037) EMS Charging Rate (register 3047) EMS Charging Stop SOC (register 3048)

Adds sensor for: EPS Switch (register 3079) - to update value for configuration entity EMS Discharging Rate (register 3036) - to update value for configuration entity EMS Discharging Stop SOC (register 3037) - to update value for configuration entity EMS Charging Rate (register 3047) - to update value for configuration entity EMS Charging Stop SOC (register 3048) - to update value for configuration entity Total Grid Import (register 3069)

Removes sensor for: Battery current (register 3170). There is a readout but scale is all wrong on mine.

Removes from config catagory, as they are sensor / readouts to update the value of the configuration entities or see current state: Limit Grid Export (register 122) Grid Export Limit (register 123)

Correct typo: "bettery_combined_power" to "battery_combined_power"

https://pastebin.com/YNgxX8eJ

TonyMathiesen commented 2 months ago

Above allows to control these as from the web UI: image

Please note that these setting are not depending on any priority mode like "Load first", "Grid first", "Battery first". Despite the documentation naming of the register. Also the values for these wrong in the documentation. I have set the naming to reflect the app and web UI, also set the native minimum to 10 SOC levels in the plugin file, to avoid accidental complete discharging of the battery.

TonyMathiesen commented 2 months ago

@Zvolli After several hours yesterday I have also managed to get the Time Slot 1 to work for setting the priority mode: image However, there we need someone who can support with changes to the below three plugin files, as it needs to be able to write uint16 bit (value above 32767), which I could not get it to do without changing the other files. Currently it is not at all pretty, as I have just copied existing functions and modified them to slightly. But it works 😊

init.py file number.py const.py

If you or other know how to program these files, then I can share what I did to get it to work 😉 I believe my hack of these files is not the way to do it.

ABRUUS commented 2 months ago

It sounds very interesting. I have a MID 20KTL3-XH (BP) inverter and I think it is the same issues. Could you share your edited files?

TonyMathiesen commented 2 months ago

@ABRUUS Sure..

To explain how it is working. First explaining bits from the documentation: image

I have added Time 1 Start and Time 1 End under configuration, and in these fields I input (from an automation) the decimal input to set them. Important: Set start first, and then immediate after end time. If not done within seconds or with overlapping times from the other time slots, then the inverter will not accept the change. image And under diagnostics I added the same to verify the change in registers: image

Then I created some helpers to be able to set the inputs with correct decimals (bits). Green is controlled directly from plugin, yellow is helpers: image

plugin_growatt.py ( https://pastebin.com/KRa1m9SX ) Add number entities (line: 267-312): _time_1_start (register 3038) time_1end (register 3039) Add sensor entities (for verification) (line 4455-4472): _time_1_start (register 3038) time_1end (register 3039)

In general that could be sufficient and also work with "option_dict = TIME_OPTIONS_GEN4" as they follow same build up. At least for 3039. However 3038 there we need to add based on bits. For mode (bit 13,14): Load first = 0, Battery first = +8192, Grid first = +16384 For enable (bit 15): Disable = 0, Enable = +32768 .. Which brings us over int16 .... - and this is where I had to do some modifications to the other files. Took hours to figure out, and a lot for HA restarts..

This is where I need someone to make this right. What I did is: file: number.py Modify "async_set_native_value" with a copy of "WRITE_MULTISINGLE_MODBUS" to a unsigned version "WRITE_MULTISINGLE_MODBUS_UNSIGNED" Line 2, 144-148, 154-158 (file: https://pastebin.com/j5JMibuT )

file: init.py Copy function "async_write_registers_single" as "async_write_registers_single_unsigned" with line 618 changed to "builder.add16bituint(payload)" Line 607-629 (with change in line 618) (file: https://pastebin.com/3rSwmsje )

file: const.py Add "WRITE_MULTISINGLE_MODBUS_UNSIGNED" Line 96 (file: https://pastebin.com/sEtrC1QL )

This allows me to set the registers with an automation which translates the helpers into the decimals that needs to go into the register and verify settings on next read 😉 .. I know that it is not so pretty yet... Please note: In the post regarding the battery / EMS settings, about charge/discharge rates and stop SOC levels. These seems to be global settings and will change the behavior of the inverter despite priority/run mode. But with both options exposed to HA you can make automations to control how you would like.

ABRUUS commented 2 months ago

Very nice job @TonyMathiesen! These modifications actually make it possible to set the SOC (min, max, discharge and charge power). The only thing I’m not able to control is the priority. It automatically switch back when I try to set it. Does it work with your inverter? The time slot also seems to be in another layout. Did you do something to integrate the helpers or are they included in the files? Growatt MID KTL3-XH (BP) is a hybrid inverter and also returns serial DN1 like the MOD. image

TonyMathiesen commented 2 months ago

@ABRUUS I have made pull request to add the EMS / Battery controls in pull request #1025 and some other updates and corrections. Note that this is without the Time 1 Start and Time 1 End in, as it requires modifications of the other files in the way that is currently.

I have removed the selector for priority, as it is not the way to change mode for TL-XH. I have kept the sensor to see current mode.

In the comment above https://github.com/wills106/homeassistant-solax-modbus/issues/979#issuecomment-2316075923: The first picture with the red circles are the ones you also have, which is the ones from the integration. The next picture with green and yellow is a dashboard card, where the green are from the integration. The yellows are HA Helpers: 2x input_datetime, 2x input_select and 1 input_button. When pressing th button it calls an automation, that converts the time to decimal: minutes + hour*256. And then for time_1_start it adds:

For mode (bit 13,14): Load first = 0, Battery first = +8192, Grid first = +16384 For enable (bit 15): Disable = 0, Enable = +32768

.. And this is where the other files modifications come in, as time_1_start then comes over 32768. Hopefully someone can help with getting the plugin to support REGISTER_U16.

An example: Setting start time to 2:00 and end time 5:30, mode: battery_first, enabled image Time 1 End: 5 hours 256 + 30 minutes = 1310 Time 1 Start: 2 hours 256 + 0 minutes = 512 + battery first mode (+8192) + enabled (+32768) = 41472

Which is accepted by the inverter: image

JeroenZwartAssen commented 2 months ago

Hi all,

I’m new to GitHub and I’m not sure if I post it in the correct discussion.

@Zvolli mentioned above the export (grid limit) functionality not working correctly and I had the same issue. I’ve a MOD TL-XH and I did some research about it, because Growatt is not very generous with its documentation.

This link describes the fallback register 3000 for grid limitation. https://midsummerwholesale.co.uk/pdfs/growatt-2500-6000tl-xe-export-limitation.pdf

Also the fallback register is described in this document, however the description is very poor. https://www.amosplanet.org/wp-content/uploads/2022/12/%E9%80%9A%E4%BF%A1%E5%8D%8F%E8%AE%AEMAX_Growatt-Inverter-Modbus-RTU-Protocol_II-V1_13_20190116-English.pdf

I’ve added the follow code to make it work. But I’m not sure if I did it correct with the GEN version thing. Also the existing register 122 is needed to enable (meter1) the grid export limit.

GrowattModbusNumberEntityDescription( name = "The power rate when export Limit failed", key = "ExportLimitFailedPowerRate", register = 3000, fmt = "i", scale = 0.1, native_min_value = 0, native_max_value = 100, native_step = 1, native_unit_of_measurement = PERCENTAGE, allowedtypes = GEN | GEN2 | GEN3 | GEN4, entity_category = EntityCategory.CONFIG, icon = "mdi:transmission-tower-export",

And

GrowattModbusSensorEntityDescription( name = "The power rate when export Limit failed", key = "ExportLimitFailedPowerRate", native_unit_of_measurement = PERCENTAGE, register = 3000, unit = REGISTER_S16, scale = 0.1, allowedtypes = GEN | GEN2 | GEN3 | GEN4, entity_registry_enabled_default = False, entity_category = EntityCategory.CONFIG, icon = "mdi:transmission-tower-export", ),

TonyMathiesen commented 2 months ago

Hi @JeroenZwartAssen It should be working in the current version. I have the grid export limitation working on my MOD TL-HX inverter. I simply use the "Limit Grid Export" holding register 122 together with "Grid Export Limit" holding register 123.

image

When I want to disable export if negative price, then I set to "Meter 1" and +1% percent. The reason I select +1% instead of 0%, is that I notice on my main meter that if 0% then it imports a tiny amount and I would rather export a tiny amount instead of paying higher price of a tiny amount import. When normal mode, I have it as disabled and 0%.

JeroenZwartAssen commented 2 months ago

@TonyMathiesen thank you for your reply. In my case, if I use register 123 the converter is not reacting correctly. When i do 1% or 100% in both situations it exports 100 watt, independent of the chosen percentage.

I don’t know if it’s important to mention. I don’t have a external meter installed.

TonyMathiesen commented 2 months ago

By external meter, do you mean that you don't have a smart meter connected just after your main circuit breaker? Because in that case you cannot use export limitation. It needs either a smart meter or some CT clamps connected, otherwise the inverter does not know how to adjust. It is also required in order to compensate between the three phases. I don't know if yours are 3 phase or single phase.

JeroenZwartAssen commented 2 months ago

@TonyMathiesen, that does make sense. I have a 3 phase setup. I don’t have a RS485 meter or a CT clamp connected. So as you explained, it can’t adjust. That’s also explains why register 3000 is working for me. I have to admit that after changing register 3000, the adjustment of the converter is quite rough.

TonyMathiesen commented 2 months ago

@JeroenZwartAssen I agree with you, the documentation from Growatt could be a lot better. And also I'm new to github, made my first pull request today 😂 I got my system installed two weeks ago and have spend the last week on trying to understand how it is working and now I have the majority working through this integration.

One can limit export if there is a meter or CT clamps. With the added battery control you can now control when to charge or discharge with automations. I also can set the mode to charge from the grid in a given time frame if necessary, however not yet in the integration as it requires a bit more work.

You should consider adding a meter or clamps, as with the 3 phase it can adjust by itself if you consume more on one phase and adjust accordingly.