Marstek Device Open API (UDP)
This repository communicates with Marstek devices using the Open API over UDP as documented in docs/marstek_device_openapi.MD.
In code, this is encapsulated by the py-marstek library (pymarstek).
When to Use
- •You need to change how device data is fetched (polling)
- •You’re debugging connectivity or “no data” scenarios
- •You’re adding new data points that might require additional Open API methods
Transport & Message Shape
- •Transport is UDP to the device (default port 30000).
- •Messages are JSON objects with a
methodandparams, e.g.:- •Discovery:
Marstek.GetDevice - •Status:
ES.GetStatus,ES.GetMode,Bat.GetStatus,PV.GetStatus,EM.GetStatus - •Control:
ES.SetMode
- •Discovery:
Discovery pattern from the spec:
- •A UDP broadcast may first receive a
Parse errorresponse (devices reacting to a non-JSON broadcast probe). - •Then send a proper JSON request with
method: Marstek.GetDeviceto receive the device’s metadata includingip,ble_mac,wifi_mac,device, andver.
Key Objects & Calls (in this repo)
- •Library client:
pymarstek.MarstekUDPClient - •Used patterns:
- •
await udp_client.discover_devices(...)(config flow + scanner) - •
await udp_client.send_request(...)(setup connectivity check) - •
await udp_client.get_device_status(...)(coordinator polling)
- •
Important library behavior (current implementation):
- •
get_device_status(...)can return default values on failure instead of raising. - •The coordinator treats
device_mode == "Unknown"as “no valid data received” and falls back to previouscoordinator.data.
Error Handling Contract
The integration aims to be resilient to device/network flakiness:
- •Timeouts / OSError / ValueError
- •Meaning: UDP request did not complete, network unreachable, or response parse issues.
- •Behavior in polling: log a warning and return previous data (entities keep last-known values instead of flapping).
- •Behavior in setup: raise
ConfigEntryNotReadyto let HA retry while the scanner updates IP if needed.
Local API enablement:
- •Devices must have OPEN API enabled in the Marstek app or discovery/polling will fail.
Concurrency Guidance
Marstek devices can be sensitive to request bursts.
- •Prefer one request per update interval.
- •Avoid parallel requests.
- •Keep all I/O in the coordinator (entities read from coordinator data).
- •All device I/O must stay async; do not introduce blocking sockets or file access on the event loop.
Control actions (ES.SetMode):
- •Pause polling for the target host while sending a command + verifying the result (see
custom_components/marstek/device_action.py). - •Use retries + backoff; UDP packets may be dropped.
Practical Debugging Steps
- •If discovery finds no devices:
- •Confirm device is on the same LAN segment and OPEN API is enabled.
- •Confirm UDP port (default 30000) is not blocked.
- •If polling returns stale/default data:
- •Check logs for
device_mode=Unknownwarnings (indicates no valid response). - •Validate the device IP in the config entry; scanner should update it automatically.
- •Check logs for
When NOT to Use
- •Don’t implement raw UDP handling in entities; keep it inside
pymarstek+ coordinator. - •Don’t add extra Open API calls per poll cycle unless you can justify the added device load.