Skip to content

Ebus integration#179

Merged
cayossarian merged 80 commits intomainfrom
ebus_integration
Mar 9, 2026
Merged

Ebus integration#179
cayossarian merged 80 commits intomainfrom
ebus_integration

Conversation

@cayossarian
Copy link
Member

SPAN v2 eBus/Homie MQTT

cayossarian and others added 30 commits February 19, 2026 16:32
Replace the entire v1 data path (SpanPanelClient -> SpanPanelApi ->
SpanPanel -> polling coordinator) with span-panel-api 2.0's MQTT-based
SpanMqttClient and SpanPanelSnapshot model.

Key changes:
- Coordinator switches from 15s REST poll to MQTT push with fallback poll
- All v1 data models removed (SpanPanel, SpanPanelCircuit, SpanPanelData,
  SpanPanelHardwareStatus, SpanPanelStorageBattery, SpanPanelApi)
- Solar virtual sensors removed; PV is a standard circuit in v2
- Config flow rewritten for v2 passphrase-based auth
- Simulation mode preserved using DynamicSimulationEngine
- Entity unique IDs unchanged for seamless migration
- PV/EVSE lug-based circuits excluded from switch/select entities
- Circuit naming matches v1 behavior (None for unnamed in friendly mode)
PV circuits (device_type="pv") now use produced-consumed for net energy
(positive when generating), matching v1 solar sensor behavior. Consumer
circuits keep consumed-produced (positive when consuming).

Also clean up temporary debug logging added during MQTT connection
troubleshooting and add broker ACL bug documentation.
Add mqtt-sensor-topic.md covering the two-layer approach for v2 sensor
alignment (replacing v1 shim sensors with honest MQTT values) and the
MQTT topology bridge for republishing panel layout data.

Also fix vendor cloud binary sensor name and reformat existing docs.
- Add PV inverter metadata (vendor, product, nameplate capacity) as
  attributes on both panel-level PV Power sensor and circuit-level PV
  power sensors
- Add BESS metadata attributes on Battery Power sensor
- Restructure README for v2 MQTT push architecture
- Extract v1 legacy content to docs/v1-legacy.md
- Add developer documentation
- Fix attribute naming: remove _a suffixes, use consistent snake_case
- Expand lugs documentation for upstream/downstream sensors
- Refactor entity summary and sensor factory for v2 alignment
Circuit priority control was non-functional in v1 — now works in v2 via
MQTT /set topics. Updated entity reference, changelog section, and
troubleshooting to reflect the working control and clarify shed semantics.
Add configurable snapshot update interval (0-15s, default 1s) to
rate-limit build_snapshot() dispatches from high-frequency MQTT
messages. Removes stale v1 options (scan interval, battery enable)
from the configuration UI. Syncs translations across all locales.
Version bump for v2 eBus MQTT release. Fixes import sorting and
removes unused datetime import from test files.
Both CI workflows now use a matrix of Python 3.13 and 3.14 with
allow-prereleases, matching the span-panel-api CI configuration.
The SPAN panel reports power_flow_pv as negative (power flowing into
the panel). Negate the value so PV production displays as positive,
matching user expectations and the circuit-level PV convention.
The library negates active-power so positive=consumption, but for PV
circuits production should read as positive. Negate PV circuit power
in the value_fn, matching the panel-level PV Power sensor convention.
Extract reload handling, migration checks, and solar migration into
a shared _run_post_update_tasks() method called from both
_on_snapshot_push() and _async_update_data(). During active MQTT
streaming, HA's DataUpdateCoordinator resets its fallback poll timer
on every push, so the polling path effectively never fires. Without
this change, reload requests from name sync and capability detection
were never acted on in streaming mode.
Add firmware gate in async_migrate_entry that probes the panel before
any schema changes — if the panel is still on v1 firmware or is
unreachable, migration returns False and the schema stays untouched so
the user can safely roll back to the prior integration version.

For confirmed v2 panels, raise ConfigEntryAuthFailed (not
ConfigEntryNotReady) for v1 entries, missing MQTT credentials, and
SpanPanelAuthError during MQTT connect — triggering HA's built-in
reauthentication notification.

Add choose_v2_auth menu step offering passphrase or proof-of-proximity
(door bypass) authentication for both upgrade and fresh install flows.
Repurpose the dead auth_proximity step for v2 door-bypass registration.
Extract _store_v2_auth_result and _async_finalize_v2_auth helpers to
eliminate credential storage duplication between auth paths.
…file

Prettier reformatted table column widths in README.md and
ebus_migration_architecture.md. Poetry lockfile updated to drop
unused click dependency.
SPAN panels occasionally report lower energy readings, which HA interprets
as counter resets creating negative spikes in the energy dashboard. This adds
a cumulative offset per sensor so HA never sees a decrease.

- Extend SpanEnergyExtraStoredData with energy_offset, last_panel_reading,
  last_dip_delta fields for persistence across restarts
- Override _process_raw_value in SpanEnergySensorBase to detect dips (>=1 Wh
  threshold) and apply cumulative offset transparently
- Add sensor attributes (energy_offset, last_dip_delta) for diagnostics
- Batch dip notifications via coordinator with translated messages
  (en, es, fr, ja, pt) loaded at runtime via async_get_translations
- Config flow checkbox defaults ON for new installs; options toggle defaults
  OFF for existing installs (no schema migration needed)
- Disabling clears all accumulated offsets on next reload
- Design doc, changelog, readme, and 26 unit tests
Add full EV charger entity support for SPAN Drive and other EVSE devices
commissioned on the panel. Each charger appears as a separate sub-device
with manufacturer, model, serial, and software version in device info.

Entities per charger:
- Charger Status (enum sensor with OCPP states, translated)
- Advertised Current (measurement sensor in amps)
- Lock State (enum sensor, translated)
- Charging (binary sensor, BATTERY_CHARGING device class)
- EV Connected (binary sensor, PLUG device class)

Includes capability detection triggering reload on EVSE appearance,
"EV Charger" circuit name fallback, simulation support, translations
in 5 languages (en, es, fr, ja, pt), and 28 new tests.

Requires span-panel-api >= 2.0.2 for SpanEvseSnapshot model.
Add EVSE helper functions (build_evse_unique_id,
build_evse_unique_id_for_entry, resolve_evse_display_suffix) following
the existing pure-function + _for_entry wrapper pattern. Add panel
name prefix to EVSE device names for cross-panel collision avoidance
and HA bulk rename support.

Update evse_device_info() with panel_name and display_suffix params.
Refactor sensors/evse.py and binary_sensor.py to use shared helpers.

Sync simulation configs: 32-tab has 1 SPAN Drive, 40-tab has 2.
- Add developer analysis and user migration guide for DSM State
  multi-signal derivation from eBus signals
- Update README entity table: DSM State replaces DSM Grid State
- Update CHANGELOG: DSM Grid State deprecated, DSM State improved
- Restore dsm_state sensor reading from snapshot.dsm_state
- Add dsm_grid_state as deprecated alias reading dsm_state value
- Remove v4-to-v5 migration that deleted dsm_state entities
- Update factory and tests for renamed snapshot field
Document the 5 remaining plain string sensors that need conversion to
device_class=ENUM with lowercase options and translations for HA core
compliance, including migration approach and breaking change guidance.
…ation code

Convert dsm_state, dsm_grid_state, current_run_config, main_relay_state,
and vendor_cloud sensors to SensorDeviceClass.ENUM with lowercase state
values and translated display names. Add state translations across all
5 languages.

Remove post-install entity naming options from config flow (keep initial
setup choice only). Delete EntityIdMigrationManager (995 lines) and all
coordinator migration hooks — users must be on v1.3.1 before upgrading,
so this code is unreachable. Clean dead functions from config_flow_utils.
…vices

Energy dip compensation handles counter dips automatically, making these
database-manipulating services unnecessary. Remove the services/ directory,
service definitions, main meter monitoring, associated tests, and all
references in __init__.py, coordinator.py, README, and CHANGELOG.
Unwrap the sensors/ subdirectory package into flat root-level files
to align with HA core integration structure while preserving modularity:

- sensors/base.py -> sensor_base.py (sensor-specific base classes)
- sensors/panel.py -> sensor_panel.py (panel-level sensor entities)
- sensors/circuit.py -> sensor_circuit.py (circuit sensor entities)
- sensors/evse.py -> sensor_evse.py (EVSE sensor entities)
- sensors/factory.py -> merged into sensor.py (platform setup + factory)
- sensors/__init__.py -> removed (re-export shim no longer needed)

Move capability detection functions (has_bess, has_pv, has_power_flows,
has_evse, detect_capabilities) from sensors/factory.py to helpers.py
where they belong as utility functions used across platforms.

Update work plan §1.2 with the modular flat-file approach.

All 247 tests pass.
…ity base, PARALLEL_UPDATES)

- Add SpanPanelRuntimeData and SpanPanelConfigEntry type alias, replace
  hass.data[DOMAIN] dict with typed entry.runtime_data across all platforms
- Create entity.py with SpanPanelEntity base class providing shared
  _attr_has_entity_name and _build_device_info() for all platforms
- Add PARALLEL_UPDATES to all platform modules (0 for read-only, 1 for
  command platforms)
- Remove redundant CoordinatorEntity imports and duplicate device info
  construction from binary_sensor, button, switch, select, sensor_base
- Mark Bronze rules 2.1-2.4 as completed in HA core work plan
Remove completed Bronze rules (runtime_data, entity base, PARALLEL_UPDATES,
action-setup), flatten §1.2 to config flow utils only, remove satisfied
rows from Bronze/Gold tables, renumber Silver sections, update Current
Alignment and Estimated Scope.
Add async_step_reconfigure to allow updating the panel host address
without removing the config entry. Uses _abort_if_unique_id_mismatch
to prevent switching to a different panel.

Add 20 new tests covering all v2 config flow paths: proximity auth,
error recovery, duplicate entry prevention, zeroconf edge cases,
end-to-end entry creation, reauth via proximity, and reconfigure
(success, connection error, serial mismatch, empty host, recovery).

Update work plan to reflect verified Bronze rules and completed
reconfigure flow (moved from Gold).
When a config entry fails setup (e.g. ConfigEntryAuthFailed before
runtime_data is assigned), unloading or removing the entry would crash
with AttributeError on runtime_data. Guard the shutdown call and remove
the redundant async_remove_entry which duplicated the unload call that
HA core already performs.
Remove completed Bronze rules from Phase 2 (config flow tests,
appropriate-polling, entity-event-setup, test-before-configure,
test-before-setup, unique-config-entry). Remove completed Silver
rules (config-entry-unloading, reauthentication-flow). Remove
completed Gold rule (entity-device-class, reconfiguration-flow).
Add all to Current Alignment section. Update estimated scope.
… entity categories

- Create diagnostics.py with async_get_config_entry_diagnostics and credential redaction
- Create icons.json with default and state-based icons for all entity types
- Add translation_key to all panel-level sensor and binary sensor descriptions
- Add entity name entries to strings.json for all translated entities
- Add exception translations section to strings.json
- Add EntityCategory.DIAGNOSTIC to status/monitoring sensors and binary sensors
- Add EntityCategory.CONFIG to circuit priority select
- Remove all hardcoded _attr_icon and icon= from Python entity code
- Change unknown api_version from ConfigEntryNotReady to ConfigEntryError
- Add async_remove_config_entry_device for stale sub-device removal
- Update work plan with completed Gold items
Promote all panel-level, BESS metadata, PV metadata, and EVSE
attributes from extra_state_attributes to first-class HA entities
with proper translation_key naming, icons, and entity categories.

- Add BESS sub-device with metadata sensors (vendor, model, serial,
  firmware, nameplate capacity, SoE kWh) via bess_device_info()
- Add PV metadata sensors (vendor, product, nameplate capacity)
- Add EVSE sensors (status, advertised current, lock state)
- Add panel diagnostic sensors (L1/L2 voltage, upstream/downstream
  lug currents, main breaker rating)
- Add grid_islandable binary sensor, move bess_connected to BESS device
- Add per-circuit current and breaker rating sensors
- Sync translations/en.json with strings.json (fixes generic names)
- Fix sensor_base fallback to use None for numeric sensors instead
  of STATE_UNKNOWN (prevents HA ValueError on device_class mismatch)
- Fix _attr_name AttributeError for translation_key-only entities
- Remove promoted attributes from extra_state_attributes
- Add 51 tests for promoted sensor definitions and conditional creation
- Bump span-panel-api to 2.2.2
Document BESS sub-device, panel diagnostic sensors, circuit
current/breaker rating, PV metadata, Grid Islandable binary sensor,
and consolidated power sensor attributes.
Use cast() for TypedDict construction from dict[str, Any] in
config_flow. Add explicit type annotation to circuit dict lookup
in select to satisfy no-any-return.
- Add extra_state_attributes (tabs, voltage) to SpanPanelCircuitsSwitch
  and SpanPanelCircuitsSelect so all circuit-related entities expose
  panel position information
- Remove overly strict last_update_success guard from
  extra_state_attributes in sensor classes; checking coordinator.data
  is sufficient
- Remove unnecessary str() wrapping on tabs and voltage attribute values
…ensors

The device_type attribute duplicated information already available
through the entity's own device classification.
Add span_panel/panel_topology WebSocket command that returns the full
physical layout (circuits, tabs, entity mappings, sub-devices) in a
single call for custom card rendering.

Improve switch responsiveness by holding optimistic state for up to 10s
after a toggle, preventing UI bounce when the coordinator refresh
returns stale data before the relay settles.
@cayossarian cayossarian merged commit a487b8d into main Mar 9, 2026
7 checks passed
@cayossarian cayossarian deleted the ebus_integration branch March 9, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant