feat: add GatewayMQTT component for ESP32 MQTT integration#3557
feat: add GatewayMQTT component for ESP32 MQTT integration#3557
Conversation
Code Review: GatewayMQTT ComponentVerdict: Approve Correctness
Minor Issues (follow-up)
Test Coverage12 tests covering protobuf round-trip, entity mapping, plan serialization, command format, EMS entities, and JWT token handling. Good coverage for v1. 🤖 Generated with Claude Code |
|
From an infra perspective the 'proto' directory won't be downloaded by default by the installed |
|
OSS community cant really use this stand alone so im not sure what we should do about this. |
|
Good points, let me address each: Proto directory: The Protobuf library size: Import guard: Agreed — I'll wrap the protobuf import in a try/except so if the library isn't installed the component simply doesn't register. PredBat continues to work normally without it. This is SaaS-only functionality anyway so OSS users won't be affected. I'll push the import guard fix shortly. |
apps/predbat/gateway.py
Outdated
| self.set_state_wrapper(f"sensor.{pfx}_battery_current", bat.current_a) | ||
| self.set_state_wrapper(f"sensor.{pfx}_battery_temperature", bat.temperature_c) | ||
| if bat.capacity_wh: | ||
| self.set_state_wrapper(f"sensor.{pfx}_battery_capacity", bat.capacity_wh) |
There was a problem hiding this comment.
soc_max unit mismatch: this injects raw Wh from the proto (e.g. 15970) but PredBat's soc_max expects kWh (e.g. 15.97) when soc_units: "%". The energy counter entities already divide by 1000 — this needs the same.
| self.set_state_wrapper(f"sensor.{pfx}_battery_capacity", bat.capacity_wh) | |
| self.set_state_wrapper(f"sensor.{pfx}_battery_capacity", round(bat.capacity_wh / 1000.0, 2)) |
Code reviewFound 1 issue:
batpred/apps/predbat/gateway.py Lines 57 to 59 in 2052d61 Proto schema (no batpred/apps/predbat/proto/gateway_status.proto Lines 8 to 18 in 2052d61 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Code reviewFound 3 issues:
batpred/apps/predbat/gateway.py Lines 371 to 373 in 4cecb2e
batpred/apps/predbat/gateway.py Lines 20 to 26 in 4cecb2e batpred/apps/predbat/components.py Lines 36 to 42 in 4cecb2e
batpred/apps/predbat/gateway.py Lines 718 to 723 in 4cecb2e 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Bug: test asserts raw Wh instead of converted kWh for battery_capacity
self.set_state_wrapper(f"sensor.{pfx}_battery_capacity", round(bat.capacity_wh / 1000.0, 2))But the test asserts the unconverted value: assert entities["predbat_gateway_battery_capacity"] == 9500 # should be 9.5This test will fail. Fix: |
Code reviewFound 6 issues:
batpred/apps/predbat/gateway.py Lines 286 to 289 in 1948a9f
batpred/apps/predbat/gateway.py Lines 614 to 645 in 1948a9f
batpred/apps/predbat/gateway.py Lines 637 to 640 in 1948a9f
batpred/apps/predbat/predbat.py Lines 842 to 845 in 1948a9f
batpred/apps/predbat/tests/test_gateway.py Lines 1 to 10 in 1948a9f
batpred/apps/predbat/gateway.py Lines 460 to 465 in 1948a9f 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
…xecution Add Python protobuf definitions matching the ESP32 firmware proto schema: - GatewayStatus with device diagnostics (uptime, RSSI, heap, log level) - BatteryStatus including depth_of_discharge_pct and rate_max_w - InverterEntry with managed flag, schedule, EMS, and energy counters - ExecutionPlan for cloud-to-gateway schedule publishing Proto is synced with src/predbat-gateway/include/proto/gateway_status.proto. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GatewayMQTT is a ComponentBase-derived component that bridges ESP32 gateway devices to PredBat via MQTT. Key capabilities: - MQTT connection with TLS, auto-reconnect, and exponential backoff - Protobuf telemetry decoding → Home Assistant entity injection - Per-inverter entity mapping with auto-config from gateway status - EMS multi-inverter aggregate entity support (GivEnergy EMS) - JWT token refresh via oauth-refresh edge function - Execution plan publishing (charge/export windows → protobuf → MQTT) - Plan deduplication and periodic re-publish for reliability - Proto3-compatible sub-message checks using ByteSize() > 0 - Battery DoD from firmware telemetry with apps.yaml fallback - Correct charge/discharge rate conversion using MINUTE_WATT Registers GWMQTT inverter type and GatewayMQTT in COMPONENT_LIST with all required config args wired via set_arg(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comprehensive tests covering: - Protobuf encode/decode roundtrip and entity mapping - Plan serialization (entries, empty plan, version monotonicity) - MQTT command format (mode, charge rate, reserve, schedule slots) - EMS aggregate entity generation for multi-inverter setups - JWT token expiry extraction and refresh threshold logic - Plan hook conversion (charge/export windows, caps, edge cases) - Empty window plan publishing (clears gateway schedule) Tests work both with pytest (local dev) and without (CI runner): - pytest.approx replaced with approx_equal() helper - pytest import made conditional - run_gateway_tests() wrapper registered in unit_test.py TEST_REGISTRY Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1948a9f to
1505651
Compare
GivEnergy Cloud returns "24:00:00" for discharge_end_time (meaning midnight/end of day). This is valid ISO 8601 but crashes strptime. Normalise to "00:00:00" before parsing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
INVERTER_DEFin config.py for ESP32 gateway MQTT integrationgateway.py— full MQTT component (aiomqtt) with telemetry decoding, command publishing, token refresh, exponential backoff reconnectionGatewayMQTTinCOMPONENT_LIST(components.py) with conditional importautomatic_config()for PredBatset_arg()registration on first telemetryTest plan
🤖 Generated with Claude Code