Skip to content

Fix event re-firing, spot price timezone/staleness, reauth and token handling#2

Merged
andreasthell merged 2 commits into
mainfrom
claude/sharp-pascal-amkvxx
Jun 11, 2026
Merged

Fix event re-firing, spot price timezone/staleness, reauth and token handling#2
andreasthell merged 2 commits into
mainfrom
claude/sharp-pascal-amkvxx

Conversation

@andreasthell

Copy link
Copy Markdown
Owner

Fixes the seven correctness/compatibility issues found in the code review:

  1. Event entities re-fired duplicate events after a failed refreshDataUpdateCoordinator notifies listeners on every refresh, including failed ones where coordinator.data still holds the previous payload. Event entities now skip processing when last_update_success is false, so a stale cm10_status_changed / new_logbook_entries / new_news_items signal can't trigger the same events once per failed cycle during an API outage.

  2. Spot price used the host's local timezone — slot timestamps from /ems/spotprice are naive Swedish local time, but they were compared against the server's local clock. On any HA host outside Europe/Stockholm (e.g. a UTC cloud VM) the wrong slot was selected. Comparison now uses an explicit ZoneInfo("Europe/Stockholm") clock, and the fetch date range uses Sweden's "today" as well.

  3. Spot price sensor lagged up to an hour — the current slot was only selected at fetch time (every 60 min) even though slots are 15 min. The day's price list is now cached and the current slot is re-selected on every 60-second coordinator cycle (_select_spot_price, covered by new unit tests).

  4. Declared minimum HA version was wrong — the code uses ConfigFlowResult (2024.2), data_updates (2024.4) and _get_reauth_entry (2024.11), but hacs.json claimed 2024.1.0. Bumped to 2024.11.0 (README updated to match).

  5. Reauth could silently rebind the entry to a different account — the reauth form accepted any valid credentials, leaving the entry's unique_id and device pointing at the old account. The flow now rejects a username that doesn't match the entry's unique_id (new account_mismatch error string in en/sv) and pre-fills the existing email.

  6. A server-side 401 never invalidated the cached JWT — a revoked/rejected token caused repeated failures until its local expiry (up to 24 h in the fallback path). _get/_get_text now drop the cached JWT on 401 so the next cycle re-authenticates.

  7. Monthly revenue broke on explicit null NetRevenuer.get("NetRevenue", 0) returns None for JSON nulls, making sum() raise and leaving the sensor silently stale. Now coalesced with or 0.

Tests: 49 passed (6 new for spot price slot selection), ruff check/format clean.

https://claude.ai/code/session_01UKMpv4yQmMeG86GiRnvfkU


Generated by Claude Code

claude added 2 commits June 11, 2026 08:04
…handling

- Event entities: skip processing on failed coordinator refreshes so
  stale signals (CM10 status change, logbook/news entries) don't fire
  duplicate events on every failed cycle.
- Spot price: compare slots against Europe/Stockholm local time instead
  of the host's local time, and re-select the current 15-min slot every
  coordinator cycle instead of only at the hourly fetch.
- Use Sweden's calendar date for the spot price fetch range.
- Reauth flow: reject credentials for a different account instead of
  silently rebinding the entry; pre-fill the existing email.
- API client: invalidate the cached JWT when the server returns 401 so
  the next cycle re-authenticates instead of looping until local expiry.
- Monthly revenue: tolerate explicit null NetRevenue values.
- Raise minimum Home Assistant version to 2024.11 (ConfigFlowResult,
  _get_reauth_entry and data_updates are newer than the claimed 2024.1).

https://claude.ai/code/session_01UKMpv4yQmMeG86GiRnvfkU
@andreasthell andreasthell merged commit f3f25cb into main Jun 11, 2026
3 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.

2 participants