Homeassistant-Growatt-Local-Modbus
Homeassistant-Growatt-Local-Modbus copied to clipboard
Supporting MID 15KTL3-X
Hi,
I have a Growatt MID 15KTL3-X. It seems to not currently be supported by this project (when trying to add it, it says "device didn't respond"). I've found the modbus registers for it and have it working by using the following config in HA:
modbus:
- name: "growatt-tcp"
type: tcp
host: 192.168.200.230
port: 502
sensors:
- name: "growatt-tcp power"
unit_of_measurement: W
device_class: power
slave: 1
address: 1
input_type: input
scan_interval: 15
data_type: int32
count: 2
scale: 0.1
This maps to the modbus input registers as found in the PDF at https://www.photovoltaicsolar.in/Growatt_Manual/MAX%20Series%20Modbus%20RTU%20Protocol.pdf
First group
--
0. | Inverter Status | Inverter run state | 0:waiting, 1:normal, 3:fault
1. | Ppv H | Input power (high) | 0.1W
2. | Ppv L | Input power (low) | 0.1W
This is similar but not the same to the ones already in this project, which seems to be float instead of int32.
GrowattDeviceRegisters(
name=ATTR_INPUT_POWER, register=1, value_type=float, length=2
),
When I use a modbus client directly to the device I get the following information which matches above pdf:
$ docker run --rm oitc/modbus-client:latest -s 192.168.200.230 -p 502 -t 4 -r 0 -l 4 -i 1
HEX16 UINT16 INT16 BIT HEX32 \
register
30000 0x0001 1 1 0000000000000001 0x00010000
30001 0x0002 2 2 0000000000000010 0x00020001
30002 0x5502 21762 21762 0101010100000010 0x55020002
30003 0x18D0 6352 6352 0001100011010000 0x18D05502
Now, I can go through and manually adding all of these registers in my HA configuration.yaml and solve my own problem, but I'd rather solve it for everybody by contributing to this project.
Do you believe my inverter uses a different protocol version other than the 1.20 and 3.15 already supported so my inverter would need to add a new protocol version? So it'd basically need a new file to inverter_120.py and inverter_315.py?
If it's needed, I'd like to do the work to add inverter.py file for my inverter but I would need help getting started. I can run this modbus-client (or anything else) to help identifying the device to help start the work.
Hi,
I suspect that the used modbus framer for a direct connection to the device is different then how it’s currently configured.
I tested it with a serial to network conversion. However because you get the message that device didn’t respond. I think the cause is the framer.
This would be the item to look at: https://github.com/WouterTuinstra/Homeassistant-Growatt-Local-Modbus/blob/0ba0f232038d7f38ee37d1e4981ce04698150368/custom_components/growatt_local/API/growatt.py#L169
I use "Modbus over TCP" and not "modbus RTU over TCP" (the gateway I use converts from RTU to standard modbus as well as serial<->tcp), and looking at that code it seems to default to "Modbus RTU over TCP"?
I added:
from pymodbus.framer.socket_framer import ModbusSocketFramer
and then changed the framer to:
if network_type.lower() == "tcp":
self.client = AsyncModbusTcpClient(
host,
port if port else Defaults.TcpPort,
framer=ModbusSocketFramer,
timeout=timeout,
retries=retries,
)
Then everything works. So to support both of these modes one way would be that the current mode should be renamed to "TCP Modbus RTU" and there needs to be a new mode added called "TCP Modbus" that instead uses the socket framer?
PS. There are several entities that don't work properly, have wrong values etc, so the "everything works" might be an exaggeration. But approx half of the entities are getting data that are somewhat sane. I'll try to correlate what works and doesn't in the code and see if I can see something in common.
I have added the option to select the Framer protocol used in the config flow.
Most likely when items don't align you will have to use the other protocol version. My expectation is that you need to use Protocol version 1.20
Thanks, I've tried it out but I now get "unknown error occured" when I first try to connect (when I enter the modbus server IP, port, modbus ID and modbus tcp/rtu settings).
This is what I found that seemed relevant in the log
Log Details (WARNING)
This error originated from a custom integration.
Logger: custom_components.growatt_local.API.growatt
Source: custom_components/growatt_local/API/growatt.py:369
Integration: Growatt Local ([documentation](https://github.com/WouterTuinstra/homeassistant-growatt-local-modbus), [issues](https://github.com/WouterTuinstra/Homeassistant-Growatt-Local-Modbus/issues))
First occurred: 15:37:38 (7 occurrences)
Last logged: 15:50:14
Inverter Modbus version not default supported.
Log Details (ERROR)
This error originated from a custom integration.
Logger: aiohttp.server
Source: custom_components/growatt_local/API/growatt.py:74
Integration: Growatt Local ([documentation](https://github.com/WouterTuinstra/homeassistant-growatt-local-modbus), [issues](https://github.com/WouterTuinstra/Homeassistant-Growatt-Local-Modbus/issues))
First occurred: 15:37:38 (9 occurrences)
Last logged: 15:50:14
Error handling request
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_protocol.py", line 433, in _handle_request
resp = await request_handler(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_app.py", line 504, in _handle
resp = await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/aiohttp/web_middlewares.py", line 117, in impl
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 85, in security_filter_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 100, in forwarded_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 28, in request_context_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 80, in ban_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 236, in auth_middleware
return await handler(request)
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 148, in handle
result = await handler(request, **request.match_info)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 181, in post
return await super().post(request, flow_id)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 72, in wrapper
result = await method(view, request, data, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 110, in post
result = await self._flow_mgr.async_configure(flow_id, data)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 297, in async_configure
result = await self._async_handle_step(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 393, in _async_handle_step
result: FlowResult = await getattr(flow, method)(user_input)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/config/custom_components/growatt_local/config_flow.py", line 383, in async_step_network
await server.close()
File "/config/custom_components/growatt_local/API/growatt.py", line 74, in close
await self.client.close()
TypeError: object NoneType can't be used in 'await' expression
Never mind, on a hunch I restarted the entire machine (and not just HA itself) and then it worked to connect. Will try with 1.20 now.
Most of the sensors look fine now, the only one that looks wrong is "reactive wattage".
Sensors
AC frequency
49.99 Hz
Input 1 Amperage
9.0 A
Input 1 energy today
13.3 kWh
Input 1 total energy
3,178.2 kWh
Input 1 voltage
595.3 V
Input 1 Wattage
5,357.7 W
Input 2 Amperage
9.1 A
Input 2 energy today
13.8 kWh
Input 2 voltage
600.4 V
Input 2 Wattage
5,463.6 W
Intelligent Power Management temperature
63.1 °C
Internal wattage
10,821.3 W
Output 1 Amperage
14.8 A
Output 1 voltage
235.7 V
Output 1 Wattage
3,488.3 W
Output 2 Amperage
14.8 A
Output 2 voltage
236.6 V
Output 2 Wattage
3,501.6 W
Output 3 Amperage
14.9 A
Output 3 voltage
236.6 V
Output 3 Wattage
3,525.3 W
Output power
10,700.3 W
Reactive wattage
247,372,185.6 W
Real power output percentage
0%
Running hours
1197:38:02
Status
Normal
Temperature
74.3 °C
Total energy input
6,404.4 kWh
Total energy produced
6,615.6 kWh
Allright nice to hear that it works, the modbus version warning is not really relevant. Although if you don't mind to share I would like to know what device information has been extracted. This is reported in the complete Home Assistant logs somewhere as a informational message.
The reactive wattage contained a copying error when I added the new protocol. I have updated the register value.
Can confirm now that reactive wattage looks much more reasonable. The only thing that shows up in the main overview is:
"Firmware: DL1.0ZBAA"
This is correct. I tried to turn on debug logging and reload the integration but the only thing I see are below. I removed the integration, restarted the machine (I got the same error again when trying to re-add), then added again, but nothing showed up in the log that seemed informative. If you can give better tip on how to get this information I'd gladly try.
2023-07-16 17:08:01.841 DEBUG (MainThread) [custom_components.growatt_local] Finished fetching growatt_local data in 0.343 seconds (success: True)
2023-07-16 17:08:03.934 DEBUG (MainThread) [custom_components.growatt_local.API.utils] split sequence keys: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 35, 36, 37, 38, 39, 40, 41, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 91, 92, 93, 94, 101, 104, 105, 234, 235]
2023-07-16 17:08:03.935 DEBUG (MainThread) [custom_components.growatt_local.API.utils] split sequence indexes based on key seperation: {11, 39}
2023-07-16 17:08:03.935 DEBUG (MainThread) [custom_components.growatt_local.API.utils] split sequence indexes based on maximum length: {36, 39}
2023-07-16 17:08:03.935 DEBUG (MainThread) [custom_components.growatt_local.API.utils] split sequence commom indexes: {39}
2023-07-16 17:08:03.935 DEBUG (MainThread) [custom_components.growatt_local.API.utils] determined key seqences ['start: 35, end: 106', 'start: 234, end: 236', 'start: 0, end: 11']
2023-07-16 17:08:03.945 DEBUG (MainThread) [custom_components.growatt_local] Finished fetching growatt_local data in 0.011 seconds (success: True)
2023-07-16 17:08:13.515 DEBUG (MainThread) [custom_components.growatt_local] Finished fetching growatt_local data in 0.318 seconds (success: True)
The device information is only added to the logs when creating the device in HA