How wertigpar/ha-emaldo works
1. Overall shape
This is a Home Assistant custom integration, not a standalone app. Home Assistant loads custom_components/emaldo, creates entities and services from a config entry, and the integration continuously syncs Emaldo battery state into Home Assistant entities.
2. Main external boundary
The integration talks to Emaldo through two channels: a REST API for authentication, battery/power snapshots, and schedule data, and a separate end-to-end encrypted UDP channel for override and real-time control operations. That split is the core architectural boundary in the repo.
3. Bundled Emaldo client library
custom_components/emaldo/emaldo_lib/ is the integration’s internal SDK for Emaldo. It contains the REST client, crypto helpers, E2E UDP transport, constants, and exception types. The Home Assistant layer depends on this library rather than calling the API directly.
4. Setup and lifecycle
config_flow.py handles initial setup, reconfiguration, and options. __init__.py wires the config entry into Home Assistant, forwards setup to the entity platforms, and keeps the integration reloadable without removal. This is the lifecycle boundary for credentials and polling settings.
5. Shared runtime state
The integration uses a shared client pattern so multiple entities and coordinators operate on the same authenticated Emaldo session and cached state. That avoids duplicated logins and keeps REST and E2E activity coordinated per Home Assistant config entry.
6. Real-time and daily data coordinator
coordinator.py is the main polling loop for battery, power, and daily energy data. It drives the fast-changing sensors and keeps last-known values when Emaldo is temporarily unreachable, using retry/backoff behavior rather than failing the entities outright.
7. Schedule and override coordinator
schedule_coordinator.py is the schedule-focused subsystem. It polls on a separate schedule, reads the AI plan plus any user override slots, and exposes chart-ready schedule data. It also handles the “next-day schedule ready” event when tomorrow’s plan first appears.
8. Entity platform split
The entity files map Emaldo capabilities onto Home Assistant entity types:
• sensor.py for power, energy, module diagnostics, balancing state, and schedule sensors
• switch.py for control toggles like third-party PV, sell-back, AI range override, and emergency charge
• number.py for numeric setpoints such as EV fixed charge amount and battery reserve thresholds
• select.py for mode selection such as EV charge mode
• time.py for emergency charge window start/end
• calendar.py for schedule visualization
These entities are mostly thin views over coordinator state and client actions.
9. Service-driven control plane
services.py exposes the higher-level mutation API: set slot ranges, apply bulk schedules, reset to internal AI plan, refresh schedule data, write EV charging schedules, backfill solar history, and set AI battery range. This is the main write path for automations and optimizer integrations.
10. Data model and schedule encoding
A major architectural detail is the 15-minute slot model. Schedule overrides are stored as byte values where 0 means idle, 1–100 encode charge targets, 128 means no override, and 129–255 encode discharge targets. The chart sensor surfaces this as structured attributes for dashboards, while services convert human-friendly actions into slot bytes.
11. Dynamic and model-specific behavior
The integration adapts entity creation to the detected Emaldo device family. Power Core-only entities such as EV controls and certain realtime solar sensors are only created when supported, while per-module battery sensors are registered dynamically after the first successful battery poll.
12. Operational resilience
The repo is built around unreliable external connectivity: the integration tolerates REST failures, retries E2E access, and keeps stale-but-useful sensor state until recovery. That makes the key diagrammatic flow “Emaldo cloud / E2E server ↔ coordinators ↔ entities/services ↔ Home Assistant,” with coordinators acting as the isolation layer between network volatility and entity state.
13. Packaging and Home Assistant metadata
manifest.json, services.yaml, strings.json, and the translations/ files provide Home Assistant metadata, service schemas, and localization. hacs.json marks it for HACS distribution, so the repo is packaged as an installable HA custom integration rather than a general Python library.
Main entry points: __init__.py Entry setup · services.py Services · client.py REST client · shared_client.py Shared client
Components 20
Home Assistant integration
Lifecycle, coordinators, platforms, and service layer inside the custom integration.
- Entry setup · Config entry setup, unload, and reload wiring for the integration.
custom_components/emaldo/__init__.py - Config flow · Initial setup, reconfiguration, and options management.
custom_components/emaldo/config_flow.py - Shared client · Per-entry shared authenticated client and cached runtime state.
custom_components/emaldo/shared_client.py - Realtime coordinator · Main polling loop for battery, power, and daily energy state with retry and stale-state handling.
custom_components/emaldo/coordinator.py - Schedule coordinator · Polls AI plan and override slots, and publishes chart-ready schedule state.
custom_components/emaldo/schedule_coordinator.py - Services · Service layer for schedule writes, resets, refreshes, charging history, and AI range updates.
custom_components/emaldo/services.py - Sensors · Power, energy, diagnostics, balancing, and schedule sensor entities.
custom_components/emaldo/sensor.py - Switches · Control toggles for PV, sell-back, AI override, and emergency charge.
custom_components/emaldo/switch.py - Numbers · Numeric setpoints such as EV charge amount and battery reserve thresholds.
custom_components/emaldo/number.py - Selectors · Mode selectors such as EV charging mode.
custom_components/emaldo/select.py - Time entities · Emergency charge window start and end controls.
custom_components/emaldo/time.py - Calendar · Schedule visualization entity for plan and override timelines.
custom_components/emaldo/calendar.py
Bundled Emaldo SDK
Internal client library that handles REST, crypto, and E2E transport toward Emaldo.
- REST client · Authenticated REST API client for Emaldo cloud operations.
custom_components/emaldo/emaldo_lib/client.py - UDP transport · Encrypted E2E channel implementation for control traffic.
custom_components/emaldo/emaldo_lib/e2e.py - Crypto helpers · Cryptographic primitives and message handling for the E2E transport.
custom_components/emaldo/emaldo_lib/crypto.py - SDK constants · Shared protocol and API constants for the bundled Emaldo client library.
custom_components/emaldo/emaldo_lib/const.py - SDK errors · Exception types used by the bundled Emaldo client library.
custom_components/emaldo/emaldo_lib/exceptions.py
Other components
- Home Assistant · Host platform that loads the custom integration and owns entities, services, and config entries.
- Emaldo cloud · REST backend used for authentication, snapshots, schedules, and account data.
- E2E channel · Encrypted UDP path used for override and real-time control operations.
Connections 39
- Home Assistant → Entry setup: loads · Home Assistant loads the config entry and integration entrypoint.
- Home Assistant → Config flow: setup UI · Home Assistant drives initial setup and reconfiguration through config flows.
- Entry setup → Shared client: creates · Integration entrypoint initializes shared per-entry runtime state.
- Entry setup → Realtime coordinator: starts · Entry setup starts the realtime coordinator.
- Entry setup → Schedule coordinator: starts · Entry setup starts the schedule coordinator.
- Entry setup → Services: registers · Integration entrypoint exposes service handlers.
- Entry setup → Sensors: forwards · Platform setup forwards entity creation to the sensor platform.
- Entry setup → Switches: forwards · Platform setup forwards entity creation to the switch platform.
- Entry setup → Numbers: forwards · Platform setup forwards entity creation to the number platform.
- Entry setup → Selectors: forwards · Platform setup forwards entity creation to the select platform.
- Entry setup → Time entities: forwards · Platform setup forwards entity creation to the time platform.
- Entry setup → Calendar: forwards · Platform setup forwards entity creation to the calendar platform.
- Config flow → Shared client: persists · Setup and options changes feed credentials and polling settings into shared runtime state.
- Shared client → REST client: uses · Shared runtime state wraps the authenticated REST client.
- Shared client → UDP transport: uses · Shared runtime state coordinates encrypted control transport.
- REST client → Emaldo cloud: REST · REST client communicates with Emaldo cloud services.
- UDP transport → Crypto helpers: encrypts · UDP transport relies on crypto helpers for secured message exchange.
- UDP transport → E2E channel: UDP · Encrypted control traffic flows over the external UDP channel.
- Realtime coordinator → Shared client: reads · Realtime polling uses the shared authenticated session and cached data.
- Realtime coordinator → REST client: polls · Realtime polling fetches snapshots and battery state from the REST API.
- Realtime coordinator → Sensors: updates · Coordinator state is exposed through sensor entities.
- Schedule coordinator → Shared client: reads · Schedule polling uses the shared authenticated session.
- Schedule coordinator → REST client: polls · Schedule data and AI plan data are read from the REST API.
- Schedule coordinator → Calendar: feeds · Schedule coordinator drives chart-ready calendar state.
- Services → Shared client: mutates · Service calls use the shared client state and credentials.
- Services → REST client: writes · High-level mutations are translated into REST API calls.
- Services → UDP transport: controls · Some service actions are delivered through the encrypted control channel.
- Sensors → Realtime coordinator: subscribes · Sensor entities render realtime coordinator state.
- Sensors → Schedule coordinator: subscribes · Schedule sensors render schedule coordinator state.
- Switches → Services: invokes · Control switches call into the service layer.
- Numbers → Services: invokes · Numeric setpoints are persisted through services.
- Selectors → Services: invokes · Selection changes are applied through services.
- Time entities → Services: invokes · Time window controls are persisted through services.
- Calendar → Schedule coordinator: renders · Calendar entity visualizes schedule coordinator data.
- REST client → SDK constants: depends on · REST client uses shared protocol constants.
- REST client → SDK errors: raises · REST client surfaces library exceptions.
- UDP transport → SDK constants: depends on · Transport implementation uses shared protocol constants.
- UDP transport → SDK errors: raises · Transport implementation surfaces library exceptions.
- Crypto helpers → SDK constants: depends on · Crypto helpers use shared protocol constants.