Skip to content

modbusproxy: write: i/o timeout for external clients since 0.313.0 without explicit timeout setting #32687

Description

@th3-w1ll

Summary

Since 0.313.0, an external Modbus TCP client connecting through evcc's modbusproxy gets write: i/o timeout errors when the upstream Modbus device is slow to answer specific register groups (e.g. Huawei Smart Power Sensor via SUN2000). The proxy handles the request, but by the time the response is ready to be written back to the client, an internal timeout has fired and the client's connection is torn down.

Setting an explicit timeout: 60s on the modbusproxy entry eliminates the errors immediately — same value that the huawei-sun2000 meter template already uses internally. Without it, the proxy uses a default that is too aggressive for this backend since #31996.

Environment

  • evcc 0.313.2 (Home Assistant Add-on, 49686a9f_evcc, but the proxy code path is generic)
  • Upstream: Huawei SUN2000-8KTL-M1 + Luna2000 battery + DDSU666-H Smart Power Sensor over Modbus TCP
  • External client through the proxy: Home Assistant wlcrs/huawei_solar v2.1.1 (this integration migrated to a new Modbus library — tModbus — in its own 2.0 release, which likely surfaces the regression here because its client-side read timing is tighter than the previous pyModbus-based client)

Symptom

evcc itself reads everything correctly (its own meters all have timeout: 60s):

[site  ] DEBUG 2026/08/10 13:09:29 pv 1 power: 5716W
[site  ] DEBUG 2026/08/10 13:09:29 battery 1 soc: 100%
[site  ] DEBUG 2026/08/10 13:09:29 battery 1 power: -0W
[site  ] DEBUG 2026/08/10 13:09:28 grid power: -5269W

But every 60–90s, the proxy logs a failed write to the HA client:

[proxy-5200] DEBUG 2026/08/10 13:35:08 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:33:13 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:32:31 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:31:18 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout

Downstream in HA, the huawei_solar power-meter coordinator ends up with all sensor.stromzahler_*_wirkleistung entities in unavailable, while the inverter and battery coordinators continue to work (they poll the fast register groups). This looked at first glance like a device-side failure, but the FusionSolar app and evcc itself see the meter fine — only the traffic through the proxy fails.

Steps to reproduce

  1. Run evcc 0.313.x with a modbusproxy entry pointing at a Huawei SUN2000 (or any Modbus TCP backend that has a slower register group like a downstream power meter over RS485).
  2. Connect an external Modbus TCP client (e.g. HA huawei_solar v2.x) to the proxy port.
  3. Watch the evcc log — after a few minutes, [proxy-5200] failed to write response: write tcp ...: i/o timeout errors start appearing, and the external client's coordinator for the slower register groups goes stale/unavailable.

Configuration details (redacted)

meters:
  - type: template
    template: huawei-sun2000
    id: 1
    host: 192.168.178.194
    port: 502
    usage: pv
    modbus: tcpip
    timeout: 60s
    name: pv2
  - name: my_battery
    type: template
    template: huawei-sun2000
    usage: battery
    id: 1
    host: 192.168.178.194
    port: 502
    modbus: tcpip
    timeout: 60s
    # ...
  - name: my_grid
    type: template
    template: huawei-sun2000
    usage: grid
    id: 1
    host: 192.168.178.194
    port: 502
    modbus: tcpip
    timeout: 60s

# BEFORE FIX — no timeout, uses default, causes `write: i/o timeout`
modbusproxy:
  - port: 5200
    uri: 192.168.178.194:502

# AFTER FIX — explicit timeout matches the meters, no more errors
modbusproxy:
  - port: 5200
    uri: 192.168.178.194:502
    timeout: 60s

Log details

Before the workaround (excerpt from docker logs/HA supervisor logs, filtered on proxy):

[proxy-5200] DEBUG 2026/08/10 13:39:30 modbus proxy for 192.168.178.194:502 listening at :5200
[proxy-5200] DEBUG 2026/08/10 13:35:08 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:33:13 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:32:31 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:31:18 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:23:06 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:15:59 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:14:46 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:11:31 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:09:27 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout
[proxy-5200] DEBUG 2026/08/10 13:08:16 failed to write response: write tcp 192.168.178.189:5200->192.168.178.189:51646: i/o timeout

After adding timeout: 60s and restarting evcc — no more i/o timeout entries; the external client's coordinators recover on the next poll cycle and stay stable.

Root cause hypothesis

PR #31996 (0.313.0, "Modbus: unify delay and timeout settings") migrated server/modbus/proxy.go's StartProxy(port, config modbus.Settings, ...) to the new unified Settings.Connection(ctx) path. That path is fine for consumers that pass an explicit Timeout in their config, but a modbusproxy entry without a timeout key ends up with the zero-value Duration, which downstream translates into a much tighter default than the pre-0.313 pyModbus behavior. For a backend like a Huawei-attached Smart Power Sensor (which is measurably slower than the inverter's own registers), that default is too aggressive.

Notably, the meter templates for huawei-sun2000-inverter / -hybrid gained timeout: 15s device-level defaults in the same PR; the proxy path did not get an analogous default.

Suggested fix

Two independent options — either one would prevent the silent regression:

  1. Sensible default timeout for modbusproxy entries. A single default (say, 10–15s — same magnitude as the huawei-sun2000 template default) would cover all normal upstream latencies. Users who need more can still override, but nobody's proxy silently breaks after an upgrade.
  2. Document the timeout (and delay) options for modbusproxy explicitly in the docs / config UI. Currently the modbusproxy config docs don't mention them, so there's no discoverable path from the symptom to the fix — I only found timeout by reading the changed source.

Ideally both. Happy to test a fix on my setup.

Additional context

  • On this setup, the Huawei power meter is a downstream RS485 slave behind the SUN2000 (Modbus register block accessed via the inverter's own Modbus TCP port 502). It is measurably slower to answer than the inverter's local register bank, which is why the proxy timeout hits only that data path and not the inverter/battery coordinators of the same client.
  • Rolling back the evcc add-on to a specific old version through the HA Supervisor was not possible for this add-on (the store only carries the latest tag), so identifying the version-related regression required reading the release notes; the config-side workaround is a much better path anyway.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions