- Rust 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
DHCP can give the device a new address. The program looks the name up again after each failed query, so it follows the device without a restart. |
||
| .cargo | ||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| clippy.toml | ||
| LICENSE-APACHE | ||
| LICENSE-MIT | ||
| README.md | ||
marstek-mqtt
Reads a Marstek device over the local Open API and publishes its values to MQTT, one value per topic.
Topics
<base>/<ble_mac>/status online | offline (retained, last will)
<base>/<ble_mac>/meter/<field> EM.GetStatus CT meter
<base>/<ble_mac>/mode/<field> ES.GetMode operating mode, battery grid power
<base>/<ble_mac>/energy/<field> ES.GetStatus energy counters
<base>/<ble_mac>/battery/<field> Bat.GetStatus battery state
<base>/<ble_mac>/device/<field> Marstek.GetDevice identity (retained)
<base>/<ble_mac>/bluetooth/state BLE.GetStatus
<base> is marstek unless set otherwise. <ble_mac> is the
Bluetooth MAC of the device, which stays the same when its IP address
changes. A field name ends with its unit, for example
total_power_w or input_energy_wh. The payload is the plain value:
-62, true, auto.
Signs: ongrid_power_w is negative while the battery charges. The
meter powers are negative while the house feeds into the grid.
mosquitto_sub -h mqtt -v -t 'marstek/+/meter/total_power_w'
Timing
The device answers one request at a time and drops many of them. The program sends one query after the other with 1 s between two requests. With the default intervals, the meter values and the mode values arrive about every 2.5 s each. A query that fails publishes nothing. While the broker is away, values are dropped.
Options
Every option can also come from the environment variable in brackets.
--device (MARSTEK_DEVICE) host or host:port of the device
--mqtt-host (MQTT_HOST) MQTT broker
--mqtt-port (MQTT_PORT) default 1883
--mqtt-user (MQTT_USER) with --mqtt-pass
--mqtt-pass (MQTT_PASS) with --mqtt-user
--base-topic (MARSTEK_BASE_TOPIC) default marstek
--timeout (MARSTEK_TIMEOUT) seconds, default 5
--meter-interval (MARSTEK_METER_INTERVAL) seconds, default 0 (as often as possible)
--mode-interval (MARSTEK_MODE_INTERVAL) seconds, default 0 (as often as possible)
--energy-interval (MARSTEK_ENERGY_INTERVAL) seconds, default 10
--battery-interval (MARSTEK_BATTERY_INTERVAL) seconds, default 30
--device-interval (MARSTEK_DEVICE_INTERVAL) seconds, default 300
The device host is a name or an IPv4 address. After a failed query, the program looks the name up again, so it follows the device when DHCP gives it a new address.
The connection to the broker uses no TLS.
Build
The marstek library comes from an SSH remote, so cargo fetches it
with the git CLI (see .cargo/config.toml).
A static binary that runs on Alpine Linux:
rustup target add x86_64-unknown-linux-musl
cargo build --release --target x86_64-unknown-linux-musl