The Huawei SUN2000 SDongle has an annoying trait you only trip over once you want to connect more than one device: it accepts exactly one concurrent Modbus-TCP connection. The moment Home Assistant polls it, the AC·THOR stops getting answers; let evcc squeeze in and one of the two gets dropped. In my setup three clients wanted to read the same registers at once — and the dongle let exactly one through.

The usual advice is: use the ha-modbusproxy add-on. It works. But I wanted to understand what happens underneath, and I didn't want a black-box container for something that, at its core, is surprisingly small. So I wrote the proxy myself: roughly 300 lines of asyncio Python that poll the SDongle once every 10 seconds into an in-memory register cache and serve FC3 reads to any number of parallel clients. This post is the developer deep-dive to my concept post on caching Modbus proxies — that one is about the why, this one is about the how, down to the byte level.

The problem: one upstream, many clients

Modbus-TCP is a simple request-response protocol, but the SDongle is designed as a slave with exactly one master. Multiple masters at once aren't part of the standard, and Huawei enforces that hard. The solution is a proxy that behaves toward the dongle like the one permitted master, and toward every other device like a Modbus slave itself. The second half is the key: it answers client reads not by forwarding to the dongle, but from a cache. That way the dongle only ever sees one calm, periodic poller, no matter how many clients hang off the back.