tjhowse / modbus4mqtt

Modbus TCP <-> MQTT glue. YAML configuration. Robust.
Other
75 stars 33 forks source link

Huawei SUN2000 #39

Open gahujipo opened 1 year ago

gahujipo commented 1 year ago

I'd like to use modbus4mqtt to read my data from my two HUAWEI SUN2000 inverters because I am not happy with my current solution. The problem is that most of the interesting registers are of type INT32 or UINT32. When do you think you are able to merge #29 ?

tjhowse commented 1 year ago

Hi Gahujipo!

I've picked up work on this PR again. I've made all the required changes and I am in the process of writing some unit tests. I've just uncovered an uncertainty around the byte ordering of multi-register values in modbus. I will look into the spec tomorrow to see if it has an opinion. I'm assuming that if a 32b number is split over two 16b registers 1 and 2, register 2 will contain the high bits, but I will check this. I should be finished with this in a few days.

Thanks, tjhowse.

gahujipo commented 1 year ago

Hi, wow, this was fast. 👍 What I've seen in Modbus so far is that the register order depends strongly on the manufacturer. In my current solution there is an option to specify whether it is LowWord/HighWord or HighWord/LowWord. In the case of the SUN2000 it is LowWord/HighWord. Maybe this should be a parameter which can be set by the user in the config file? In addition to that, in my current solution there is an option to specify whether the value is split over two registers in case of (U)INT32 or over 4 registers in case of an (U)INT64.

What I didn't find (at least in the docs of modbus4mqtt) either was the option to set HighByte/LowByte (Big Endian) or LowByte/HighByte (Little Endian). I did a quick research and found out that Modbus in general is a "big-endian" protocol but even there seem to be some manufacturers which implement that with little-endian, even when those are some few exceptions.

tjhowse commented 1 year ago

Alrighty, I've published a v0.6.0_rc1 for testing here: https://pypi.org/project/modbus4mqtt/0.6.0rc1/

Let us know how you go! I added a word_order setting to the configuration that defaults to highlow to account for devices that might be weird.

gahujipo commented 1 year ago

That's awesome. Thank you very much. I'll test it and let you know in the next days. Are you interested in a PR with the yaml file for the Huawei SUN2000 inverters or is that not your objective?

tjhowse commented 1 year ago

That would be fantastic! We're slowly putting together a library of inverter maps. More the merrier!

nicx commented 1 year ago

@gahujipo any progress to your solution? maybe you could share your yaml for the huawei sun2000? ;)

nicx commented 1 year ago

@tjhowse tried it with a SUN2000 by myself with this config:

ip: 192.168.0.1
port: 502
update_rate: 5
address_offset: 0
word_order: lowhigh
scan_batching: 1
registers:
  - pub_topic: "modbus4mqtt/battery_discharge_power"
    address: 47077
    table: 'holding'
    type: int32

but I always get an error:

023-03-16 09:38:35 ERROR    Failed to read 1 holding table registers starting from 47077: Exception Response(131, 3, IllegalAddress)
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 181, in _scan_value_range
    return result.registers
AttributeError: 'ExceptionResponse' object has no attribute 'registers'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 88, in poll
    values = self._scan_value_range(table, group, self._scan_batching)
  File "/usr/local/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 184, in _scan_value_range
    raise ValueError("Failed to read {} {} table registers starting from {}: {}".format(count, table, start, result))
ValueError: Failed to read 1 holding table registers starting from 47077: Exception Response(131, 3, IllegalAddress)
2023-03-16 09:38:36 ERROR    Failed to read 1 holding table registers starting from 47078: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 181, in _scan_value_range
    return result.registers
AttributeError: 'ModbusIOException' object has no attribute 'registers'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 88, in poll
    values = self._scan_value_range(table, group, self._scan_batching)
  File "/usr/local/lib/python3.9/site-packages/modbus4mqtt/modbus_interface.py", line 184, in _scan_value_range
    raise ValueError("Failed to read {} {} table registers starting from {}: {}".format(count, table, start, result))
ValueError: Failed to read 1 holding table registers starting from 47078: Modbus Error: [Input/Output] Modbus Error: [Invalid Message] No response received, expected at least 8 bytes (0 received)
2023-03-16 09:38:36 WARNING  Couldn't get value from register 47077 in table holding

Any help what I could do? :)

tjhowse commented 1 year ago

That address is probably not valid for your inverter. It might be in octal format? Did you get it from some documentation somewhere? Does that specify the number format? Lots of docs like to prepend a "4" to mean "holding register table". Try address 7077 and see if it works better.

nicx commented 1 year ago

the address is correct, with other modbus solution I can get the value. even in the official documentation of Huawei SUN2000 modbus protocol doc. Anyway I tried it with "7077", same error.

gahujipo commented 1 year ago

@gahujipo any progress to your solution? maybe you could share your yaml for the huawei sun2000? ;)

No progress on my side. I didn't want to lose my statistics during the winter, but in the next future I'll give it another try.

nicx commented 1 year ago

any help or idea from others? :)

gahujipo commented 1 year ago

The Huawei inverters have a limited polling rate of 1 request per 5 seconds. Otherwise you get back a device busy error code. You have a bigger request interval than that, right?

nicx commented 1 year ago

@gahujipo I tried it with 1 register every 10 seconds, even with 60s interval I get the same error. when try to interpreting the log file I just not found the correct parameters for the request/answer format of Huawei?!