SPAN Official v2 API Ebus integration#104
Merged
cayossarian merged 18 commits intomainfrom Feb 27, 2026
Merged
Conversation
When parallel requests share a client via get_all_data(), one request failing can destroy the shared client while others are in-flight. Those requests then fail with ReadError, WriteError, or CloseError (all subclasses of NetworkError) which were not being caught by the retry logic. This fix extends the exception handling in _retry_with_backoff() to catch these network errors alongside RemoteProtocolError, applying the same immediate retry with client recreation strategy. Fixes #89 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove REST client (~1430 lines), generated OpenAPI client (~2000 lines), virtual circuits, delay registry, and all v1-specific code. SPAN Panel v2 firmware users get MQTT/Homie transport exclusively. Retained: SpanPanelSnapshot contract, simulation engine, phase validation, 3 PEP 544 protocols (SpanPanelClientProtocol, CircuitControlProtocol, StreamingCapableProtocol). Removed: SpanRestClient, SpanPanelClient shim, generated_client/, CircuitCorrelationProtocol, REST-only exceptions, ~22 REST test files, example scripts. Circuit correlation moves to integration layer. Dependencies: paho-mqtt now required (was optional), attrs and python-dateutil removed. 217 tests passing, 86.5% coverage.
…b synthesis Branches were a v1 REST concept. Simulation now uses the same unmapped tab synthesis pattern as the MQTT transport — gaps in occupied tab positions are filled with zero-power SpanCircuitSnapshot entries (circuit_id=unmapped_tab_N).
Replace thread-based paho-mqtt wrapper with event-loop-driven architecture matching Home Assistant core: - Add AsyncMQTTClient with NullLock replacing paho's 7 internal locks - Drive socket I/O via add_reader/add_writer instead of loop_start() - Remove threading.Lock, call_soon_threadsafe from MQTT callbacks - Use loop_misc() periodic timer for keepalive - Manage reconnection in async loop with exponential backoff - Add hand-rolled MQTT mock fixture in conftest following HA core pattern - Add paho-mqtt to pre-commit mypy/pylint additional_dependencies
Test files should describe what they test, not which migration phase created them. Names are stable beyond the refactor.
Add Step 7 documenting the AsyncMqttBridge refactor to match HA core's event-loop-driven MQTT pattern.
…it power units - Fix LUGS node type detection: actual types are energy.ebus.device.lugs.upstream/downstream (not generic .lugs) - Correct energy field mapping for LUGS: imported-energy = consumed, exported-energy = produced (was swapped) - Fix circuit active-power units: values are in watts, not kW (removes erroneous * 1000 multiplication) - Treat PV/EVSE as metadata nodes: extract device_type and relative_position from feed references instead of building them as circuits directly - Add relative_position field to SpanCircuitSnapshot for detecting lug-based vs breaker-connected PV/EVSE
…ice types - Append UUID suffix to client name for panel uniqueness - Use hopPassphrase field name per SPAN v2 API spec - Support optional passphrase (None for door-bypass registration) - Wait up to 10s for circuit name retained messages after device ready - Derive device_type from simulation template energy profile mode
Remove the Last Will and Testament that published "lost" (retained) to the panel's Homie $state topic. A consumer must never publish to the device's state topic — when our client disconnected ungracefully, the LWT overwrote the panel's retained $state=ready with "lost", making all subsequent connections time out waiting for a ready state that would never arrive. Recovery required a panel power cycle. Also move tls_set() into the executor alongside connect() to avoid blocking the event loop with ssl.SSLContext.load_verify_locations().
Parse PV inverter metadata (vendor-name, product-name, nameplate-capacity) into new SpanPVSnapshot model. Extend SpanBatterySnapshot with BESS metadata fields. Parse upstream/downstream lugs per-phase current (l1-current, l2-current). Parse power-flows node (pv, battery, grid, site). Improve dsm_grid_state multi-signal heuristic and run_config tri-state derivation. - New SpanPVSnapshot model on SpanPanelSnapshot.pv - SpanBatterySnapshot gains vendor_name, product_name, nameplate_capacity_kwh - SpanPanelSnapshot gains power_flow_*, upstream/downstream l1/l2_current_a - homie.py: _build_pv(), extended _build_battery(), improved derivations - Simulation engine updated for new snapshot fields
Panel MQTT topics use dashless UUIDs (e.g. 941d6a8b41ab4c57a6b8be14b5981fe6) but denormalize_circuit_id was adding dashes, publishing to non-existent topics. Relay and priority set commands now use the circuit_id as-is.
- Define format-markdown as Poetry script in pyproject.toml - Create scripts/__init__.py to make scripts directory importable - Fixes task failure when running 'poetry run format-markdown'
Add snapshot_interval parameter (default 1.0s) that rate-limits build_snapshot() + callback dispatch using asyncio.TimerHandle. MQTT messages continue updating the Homie property store immediately; only the expensive snapshot rebuild is gated. Set to 0 for no debounce.
Resolves Bandit B108 (insecure temp file/directory usage).
Replace assert in connection.py with a proper RuntimeError to avoid removal under optimised bytecode (Bandit B101). Update CI matrix and standalone jobs from Python 3.12 to 3.13.
….14 to CI numpy has no 3.14 wheels, causing source compilation that hangs CI. It was never imported in source code — leftover from v1. Also removes attrs and python-dateutil which were removed in the v2 rewrite. Adds Python 3.14 to CI matrix with allow-prereleases.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v2 eBus integration