This release is mainly Refactoring code with minor bug fixes.
Why Refactor? think of it like cleaning the kitchen while you cook. You aren't changing the menu or serving a new dish; you're just making sure the workspace is organized so you don't trip over a drawer or lose the salt when things get busy.
Architecture
- Extracted API layer into api/ package — http_client.py, websocket_client.py, exceptions.py with re-exports from init.py
- ldata_service.py now focuses on data orchestration; transport concerns are isolated
Massive API Call Reduction & Wi-Fi Stability
- 98.3% Reduction in Cloud Traffic: Shifted the integration's primary data source to the event-driven WebSocket stream. Background REST API polling for V2 (WHEMS) panels has plummeted from ~7,200 calls/day down to just ~120 calls/day.
- Eliminated Network Stress: Removed the aggressive 60-second bandwidth toggle (which forced the panel to drop/rebuild its cloud connection constantly). This completely resolves transient 0W spikes and 6-minute WebSocket data lockups.
- Hourly Hardware Sync: The heavy polling loop (Panel RSSI + CT Energy fetch + Bandwidth Toggle) now runs on a strict 1-hour timer to cleanly sync hardware data without overwhelming the panel.
Real-Time "Sensor Fusion" (Riemann Sums)
- Sub-Second Energy Dashboards: The Leviton cloud only pushes lifetime kWh updates every ~15 minutes, causing blocky dashboards. The integration now features a local Riemann Sum Integrator that calculates instantaneous kWh based on the high-speed Wattage stream.
- Smooth True-Ups: Every 1 hour, the integration fetches the exact hardware lifetime counters from the panel and seamlessly absorbs the difference into the software drift. Dashboards never freeze or jump backward.
New entities / Options
- Breaker Daily Import sensor — only created for breakers with non-zero import (solar detection: skipped when consumption > 0 and import == 0)
- Blink LED switch per breaker — diagnostic category, controllable via PUT /ResidentialBreakers/{id} with {"blinkLED": true/false}, always created (not gated on breaker control)
- Breaker ID shown in device info via serial_number field
- Added new "Log Raw Websocket String" option
Bug fixes
- Removed Zero-Transition Protection as no longer needed
- ClientConnectionResetError on WS subscription sends — _ws_send_subscriptions now guards ws.closed and catches connection resets cleanly
- Fire-and-forget heartbeat task now tracked and cancelled on disconnect
- Panel hardware field now uses panel_type instead of hardcoded "LDATA"
- Added CT clamp channel # to Device info an log warnings if not configured
- Clarified naming of "Three Phase" option as it was misleading.
- Clarified naming of "Log Full Websocket Data" to "Log All Parsed Data" option as it was misleading.
Entity cleanup
- All listener registrations moved from init to async_added_to_hass across all sensor, binary sensor, and switch classes
- Breaker Status binary sensor moved to Diagnostic category
- Cloud Connected sensor moved to DIAGNOSTIC group
- BLE RSSI sensor has 5 dBm deadband filter to reduce DB writes
- Removed unused _LEG2_POSITIONS from const.py
Code quality
- Consistent aiohttp.ClientTimeout(total=N) across all HTTP calls
- Lazy % logging in coordinator (was f-strings)
- Logger name consistency — API modules use LOGGER_NAME from const.py instead of hardcoded strings
- Silent except Exception: pass handlers replaced with _LOGGER.debug throughout http_client.py and ldata_service.py