Skip to content

v1.0.5: Code quality, performance, and stability improvements (#26-#40)#42

Merged
traktore-org merged 34 commits into
mainfrom
develop
Apr 18, 2026
Merged

v1.0.5: Code quality, performance, and stability improvements (#26-#40)#42
traktore-org merged 34 commits into
mainfrom
develop

Conversation

@traktore-org
Copy link
Copy Markdown
Owner

Summary

  • 15 improvement issues across performance, stability, usability, accessibility, and code quality
  • Coordinator refactored (CC ~25 → ~12) with narrowed exception handling
  • EV retry with exponential backoff, battery protection error recovery
  • Frontend: memory leak fixes, debounced updates, ARIA labels, entity status indicator
  • Config flow entity validation, notification flap suppression, shared JS constants

Test plan

  • Deploy to HA-TEST via deploy-test.sh
  • validate-sem.sh — all 7 checks passed (199 entities, 0 errors)
  • Coordinator cycles: 0.001-0.037s success
  • Deploy to HA-PROD after merge

Closes #26, #27, #28, #29, #30, #31, #32, #33, #34, #35, #36, #37, #38, #39, #40, #41

🤖 Generated with Claude Code

github-actions Bot and others added 30 commits April 12, 2026 19:38
- Sync all code from dev repo (yearly seeding, flow card, tests)
- Add sem-flow-card with reverse/invert toggles
- Add yearly sensor seeding from HA recorder (#21)
- Add 16 new tests for flow card injection and cleanup (#19)
- Update manifest.json to point to sem-community
- Add issue redirect template for community users
- Update .gitignore for dev-only files
- Remove orphaned root-level shims

This repo is now the primary development AND HACS distribution repo.
Issues migrated from traktore-org/solar_energy_management.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
load_device_discovery.py, load_management.py, dashboard_generator.py
are backward-compat shims that __init__.py imports from.
utility_signals.py is actual runtime code.
Also removed dashboard_generator.py from .gitignore (it's needed).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The dev repo used 2.7.x versioning — sem-community uses its own
versioning starting from 1.0.0. This release includes flow card,
yearly seeding, and test coverage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extend battery discharge control auto-detection to support:
- SolAX (solax-modbus)
- DEYE / Sunsynk (ha-solarman)
- Growatt
- Sofar
- Solis
- Generic fallback (discharge_power_limit)

Also remove hardcoded KEBA sensor defaults from sensor_reader
(users must configure or auto-detect via config flow).

5 new test cases for platform-specific detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New sensors:
- sensor.sem_battery_cycles_estimated — lifetime throughput / capacity
- sensor.sem_battery_health_score — estimated capacity retention %

Dashboard: Battery Health card on System tab showing health, cycles,
daily charge/discharge, temperature, and SOC.

Also restored TROUBLESHOOTING.md and USER_GUIDE.md removed during
repo migration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Renamed _should_reenable_keba() → _should_reenable_charger() with
updated docstring. The stall detection logic is already generic (works
with any charger) — the method name was the only KEBA-specific part.

The CurrentControlDevice class already abstracts charger control via
the charger_service parameter — no structural changes needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- test_dashboard_generator: set hass.data={} (real dict, not MagicMock)
  so DOMAIN lookup and .items() work correctly
- test_ev_energy_fix: update KEBA auto-detect test to expect None
  (auto-detection removed in #5)
- test_yearly_seeding: fix sys.modules patching — include parent
  recorder module for dynamic import to work

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Battery Health card to Battery tab (was only on System tab)
  Shows health score, cycles, temperature with color-coded icon
- Remove redundant Battery SOC gauge (hero + chart already show it)
- Remove duplicate Battery Health card from System tab
- Remove temperature from Power & Status secondary (now in health card)
- Add accessibility text labels to status chips:
  - Battery chip: appends "Low" when SOC<30, "Full" when >80
  - Peak Load card: primary title now includes "Safe/Warning/Critical"
- Add error handling to EV Economics template (no data yet → friendly text)
- Handle unavailable states in Battery Health template

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ig entities

New number entities:
- number.sem_ev_km_per_kwh (default 5.5 km/kWh, range 3-10)
  Replaces hardcoded "18" in Cost/100km calc (now cost × 100 / km_per_kwh)
- number.sem_public_charging_rate (default 0.55 CHF/kWh, range 0-2)
  Replaces hardcoded 0.55 in public charging comparison

Dashboard changes:
- EV Economics card uses new config entities
- EV Daily Progress: replaced fixed-max gauge with mushroom-template-card
  that shows daily/target kWh with percentage and color-coded icon
  (no longer truncates when target > 10 kWh)

Translations updated for all 6 locales + strings.json.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…afe names

- Standardize chart heights: all 24h/detail charts at 200px, Sankey at 280px
  (was inconsistent mix of 180/200/300)
- Add Observer Mode alert at top of Home tab (conditional, only when active)
  Makes it obvious when system is read-only; tap navigates to Control tab
- Remove hardcoded currency from entity names
  ev_km_per_kwh: "EV Efficiency" (was "EV Efficiency (km/kWh)")
  public_charging_rate: "Public Charging Rate" (was "... (CHF/kWh)")
  HA displays the unit separately based on user's locale/currency config

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change Home tab status chips alignment from 'center' to 'justify' —
spreads chips evenly with better wrapping behavior on narrow screens.
(5 chips at center can overflow awkwardly on <400px viewports.)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ROI "How Savings Are Calculated" fold expanded by default
  Important context (formula, rates, lifetime impact) — shouldn't be hidden
- Tariff Rates section label clarity:
  Display cards → "Current Import/Export Rate" (reflects live/dynamic value)
  Input cards → "Static Import/Export Rate" (user-set fallback)
  Previously both said just "Import Rate" / "Export Rate" — confusing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…95d912)

Changes from upstream:
- Battery split colors: pink (#f06292) charge, teal (#4db6ac) discharge
- Optional inverter node (show_inverter config, default true)
- Grid daily shows net import/export
- Split click targets: battery SOC vs power open different histories
- Grid daily text opens daily import energy history

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Inverter node moved down 25px to prevent overlap with solar node.
All nodes below shifted accordingly, viewbox expanded to 800.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
generate_dashboard now:
- Uses timestamp (not manifest version) for ?v= cache busting on all
  SEM card resources — ensures browsers reload JS after every regen
- Removes orphaned resource entries for cards that no longer exist
- New resources also get ?v= timestamp on creation

Fixes: card JS changes not visible despite hard refresh (browser
served cached ?v=1.0.4 URL until version changed).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e8f81c)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…2ec50)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create sem-shared.js with canonical color palette, formatPower/formatEnergy
utilities, animation duration calculator, and interaction timing constants.
Update sem-chart-card and sem-flow-card to use shared constants with
graceful fallback. Register sem-shared.js as Lovelace resource (loaded
before other cards for global availability).

Closes #33

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move entity ID patterns to consts/core.py as named constants:
- ENTITY_OBSERVER_MODE_SWITCH, ENTITY_SOLAR_POWER, ENTITY_FORECAST_NIGHT_REDUCTION
- WEATHER_ENTITY_CANDIDATES (tuple for ordered fallback)
- STATE_UNKNOWN, STATE_UNAVAILABLE (replaces magic strings)

Update coordinator.py and forecast_reader.py to use these constants
instead of scattered string literals.

Closes #36

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ackoff, error recovery (#34, #26, #27, #28)

#34 Narrow exception handling:
- Replace 10+ bare `except Exception` with specific types (HomeAssistantError,
  ServiceValidationError, ValueError, TypeError, AttributeError)
- Add logging to silent `pass` blocks (price optimization fallback)
- Split notification errors into data errors vs service failures

#26 Cache forecast source and surplus window:
- Cache detected forecast source; only re-detect if entity becomes unavailable
- Cache surplus window estimate; only recalculate when forecast data changes
  (compare signature of remaining_kwh + peak_time)

#27 Exponential backoff for EV device retry:
- Replace linear 30-retry loop with exponential backoff (10s, 20s, 40s... 320s)
- Validate setup success before stopping retries
- Log at WARNING after 3+ failures; log final failure with actionable message

#28 Error recovery for battery protection and load management:
- Reset battery_protection_active on service call failure (prevents stale state)
- Separate service errors from data errors in load management

Closes #34, #26, #27, #28

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…, #31, #38)

#30 Memory leaks and DOM thrashing:
- sem-period-selector-card: add disconnectedCallback with button listener cleanup
- sem-system-diagram-card: add animation frame cleanup to disconnectedCallback
- sem-flow-card & sem-system-diagram-card: debounce _updateFlows() with 100ms timer
- Clean up timers in disconnectedCallback to prevent orphaned timeouts

#31 Accessibility support:
- sem-period-selector-card: add role="button", aria-label, aria-pressed to buttons
- sem-system-diagram-card: add role="img" and descriptive aria-label to SVG

#38 Entity error states:
- sem-system-diagram-card: track entity availability across 6 core sensors,
  display warning indicator when sensors are unavailable/unknown

Closes #30, #31, #38

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Storage validation:
- Add _validate_energy_data() that checks all accumulators are numeric
  and within sane range (<100 MWh). Rejects corrupted storage with a
  warning and starts fresh instead of propagating bad values.
- Narrow storage exception types to OSError/ValueError/TypeError

Migration safety:
- Wrap v1→v2 migration in try/except; on failure, log error and return
  False to keep original config intact instead of partial modification

Closes #37

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- binary_sensor.py: Replace warning/info availability logging with debug
  level (transitions are normal during coordinator reconnection, the old
  _logged_unavailable flag never reset on entity recreation causing spam)
- sensor.py: Same debug-level availability logging fix; add last_reset
  returning Jan 1 for yearly TOTAL sensors so HA statistics system can
  correctly aggregate yearly data
- number.py: available property already existed (confirmed)

Closes #39

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
)

- Preserve user-set priorities during device discovery: mark priorities
  with user_set_priority flag, skip overwriting during merge
- Replace hardcoded 30s discovery delay with retry approach: if fewer
  devices found than stored, retry up to 3 times at 15s intervals
- Add _cleanup_shed_list() that removes devices from shed list when
  they're already off or removed, preventing stale shedding state

Closes #40

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add entity existence validation for optional EV charger entity fields
in both install and reconfigure flows. Non-empty entity IDs that don't
exist in HA now show "entity_not_found" error instead of silently
accepting invalid IDs that fail at runtime.

Add translations for entity_not_found error (en, de).

Closes #32

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
belinea4071 and others added 4 commits April 18, 2026 11:13
- Flap suppression: for solar charging states (which oscillate with
  clouds), require state to be stable for 60s before sending notification.
  Prevents 3+ notifications in 30s during variable weather.
- KEBA service validation: check has_service("notify","keba_display")
  once at first use; skip silently if KEBA integration not installed
  instead of catching exception every cycle.

Closes #35

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract two large blocks from _async_update_data into dedicated methods:

- _update_analytics_phases(): forecast, tracker, tariff, surplus controller,
  device runtimes, PV analytics, energy assistant, utility signals (~120 lines)
- _send_notifications(): state-change and event-based notifications (~45 lines)

The main update method now reads as a clear pipeline: read sensors → calculate
energy/flows → EV control → battery protection → load management → analytics →
build data → notifications → persist. Each phase is independently testable.

Closes #29

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add state validation for optional entity IDs in the EV charger config step:
entities that exist but report "unknown" or "unavailable" now trigger a
warning log so the user is aware of potential issues at setup time.

The config flow already validates:
- Energy Dashboard completeness (abort if missing components)
- Required EV sensors exist and are valid (via HardwareDetector)
- Optional entity IDs exist in HA (entity_not_found error)

Closes #32

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Document recent improvements across performance, stability, usability,
accessibility, and code quality categories.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@traktore-org traktore-org merged commit 847ac1c into main Apr 18, 2026
3 of 11 checks passed
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