e3dc-mqtt-ruby
A Ruby bridge between E3DC solar battery storage systems and MQTT, using the RSCP protocol. Ruby port of e3dc-mqtt-go / e3dc-mqtt-rs with feature parity for the read side.
Repository: https://github.com/isnogudus/e3dc-mqtt-ruby
Features
- Real-time power values (PV, battery, grid, home, wallbox)
- Battery state of charge, cycle count, cell voltages/temperatures
- Daily statistics (production, consumption, autarky)
- Delta-based publishing (only changed values hit the broker)
- Aligned polling intervals (ticks on clock boundaries)
- TLS with verification toggle, LWT
- Pure-Ruby RSCP implementation — no C extensions, no FFI
- Complete RSCP tag registry (3564 tags, auto-generated from the Go reference)
Requirements
- Ruby ≥ 3.4 (uses
Data.define) - An E3DC system with the RSCP interface enabled
- An MQTT broker
Installation
bundle install
cp config.toml.example config.toml
$EDITOR config.toml # fill in RSCP host/user/password/key + MQTT
Configuration
log_level = "INFO" # DEBUG, INFO, WARN, ERROR
[e3dc]
host = "192.168.1.100"
port = 5033 # default
username = "your_username"
password = "your_password"
key = "your_rscp_key"
interval = "5s" # polling interval (min 5s)
statistic_update_interval = "5m"
[mqtt]
url = "ssl://broker:8883" # or tcp://broker:1883
root = "e3dc" # topic prefix
client_id = "e3dc-mqtt-ruby"
username = "" # optional
password = "" # optional
tls_verify = true # set false for self-signed certs
Running
bundle exec bin/e3dc-mqtt -c config.toml
For a one-shot liveness probe without touching MQTT:
bundle exec bin/probe -c config.toml
The bridge follows a "let it crash" model — on errors it exits with a specific code and a supervisor (systemd, runit, Docker) should restart it.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Clean shutdown |
| 1 | Configuration error |
| 4 | E3DC connection error |
| 5 | MQTT connection error |
| 6 | System-info error |
| 10 | Status publish error |
| 11 | Statistics publish error |
| 12 | Battery publish error |
MQTT topics
All topics are prefixed with {root}/{model}-{serial}/.
online— retained LWT (true/false)info— retained JSON system infostatus/…— 5-second cadence (pv, grid, battery, autarky, …)status_sums/…—statistic_update_intervalcadence (daily totals)status/battery:N/…andstatus/battery:N/dcb:M/…— battery detail
Full topic list: see e3dc-mqtt-go README.
Architecture
lib/e3dc_mqtt/
├── config.rb TOML loader + validation
├── types.rb Data.define value types (Status, BatteryData, …)
├── app.rb Main loop, aligned tickers, signals
├── e3dc.rb High-level E3DC client (status, info, stats, batteries)
├── mqtt_client.rb Delta-publish, JSON, LWT, TLS verify toggle
└── rscp/ Pure-Ruby RSCP protocol
├── constants.rb Frame layout, control-field masks
├── data_type.rb 18 RSCP types (pack/unpack)
├── message.rb Message value + codec (with container recursion)
├── frame.rb Frame writer/reader + CRC32
├── rijndael256.rb Rijndael-256 CBC (32-byte block, 14 rounds)
├── tags.rb Generated: 3564 tags, 712 declared data types
└── client.rb TCP + auth + send/receive (stateful CBC)
Regenerating the tag registry
The tag registry in lib/e3dc_mqtt/rscp/tags.rb
is generated from the Go reference's tag.go and tag_datatype.go. To
pick up new tags when the Go library updates:
ruby tools/generate_tags.rb # uses default Go module cache path
ruby tools/generate_tags.rb /path/to/go-rscp/rscp
Tests
bundle exec rake test
Covers the config loader, the RSCP framing round-trip, Rijndael-256 against known Go-reference vectors, the tag registry, and an end-to-end loopback test of the RSCP client (real TCP server, full auth handshake, stateful CBC across messages).
Credits
Ported from and verified against these upstream projects:
- spali/go-rscp — the Go RSCP library. Structural
reference for framing, tag registry, data-type marshalling, and the
client/auth flow.
tools/generate_tags.rbparses its sources verbatim. - azihsoyn/rijndael256 — the Go Rijndael-256 implementation the rscp/rijndael256.rb port is based on. The single-block and CBC outputs match byte-for-byte. The original ancestor is agl/pond.
- isnogudus/e3dc-mqtt-go — the Go MQTT bridge.
Blueprint for the high-level
E3DC::Clientstructure, MQTT topic naming, delta publishing, and the daily-statistics boundary logic. - isnogudus/e3dc-mqtt-rs — the Rust MQTT bridge. Cross-checked for protocol details and tag coverage.
License
MIT — see LICENSE. Third-party attributions (for the Rijndael-256 port and the go-rscp-derived tag registry) are preserved in NOTICE.