Skip to content

Release v2.6.1 - #14

Merged
telard-pixel merged 2 commits into
mainfrom
dev
Jun 15, 2026
Merged

Release v2.6.1#14
telard-pixel merged 2 commits into
mainfrom
dev

Conversation

@telard-pixel

@telard-pixel telard-pixel commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Automated release PR for v2.6.1.

Summary by CodeRabbit

  • Bug Fixes

    • Improved program selection resolution by adjusting priority order for identifying selected programs. Better handles edge cases when numeric program codes cannot be mapped to program names.
  • Tests

    • Added regression test to verify program selection works correctly in edge case scenarios.

tis24dev and others added 2 commits June 15, 2026 20:01
…tion

On real appliances the program option list is built from a list of program
names, so the lookup map is keyed by name (name->name) and a numeric prCode
can never match it. current_option tried the numeric settings.prCode/prCode
keys before startProgram.program, which still resolved correctly via the
fallback chain but logged a misleading 'non mappato' DEBUG line on every
poll (hundreds per hour on washer+dryer).

Reorder the key list so the name-yielding keys (programName, settings.program,
startProgram.program, program) are tried before the numeric prCode keys.
current_option now resolves on the first mappable name and no longer emits
spurious 'non mappato' noise for codes that were never mappable. Behaviour
for code->name maps (numeric prCode genuinely in the map) is unchanged: the
prCode keys are still tried, just last.

Add a regression test reproducing the production case (name-keyed map, device
exposing an unmappable numeric prCode plus the name via startProgram.program)
asserting current_option returns the name without logging 'non mappato'.
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8362ceb0-8a5f-41c6-965a-9b85ed9836df

📥 Commits

Reviewing files that changed from the base of the PR and between d2fe413 and 6196565.

📒 Files selected for processing (3)
  • custom_components/haier_hon/manifest.json
  • custom_components/haier_hon/select.py
  • tests/test_program_select.py

📝 Walkthrough

Walkthrough

HonProgramSelect.current_option is updated to check name-based attribute keys (programName, settings.program, startProgram.program, program) before numeric code keys (settings.prCode, startProgram.prCode, prCode). A regression test validates the new priority. The manifest version is bumped from 2.6.0 to 2.6.1.

Changes

Program select key priority fix

Layer / File(s) Summary
current_option key priority reorder and regression test
custom_components/haier_hon/select.py, tests/test_program_select.py
Name-based keys (programName, settings.program, startProgram.program, program) are now checked before numeric code keys (settings.prCode, startProgram.prCode, prCode). A regression test asserts that current_option resolves via startProgram when attributes.prCode is numeric and unmappable, and that no "non mappato" debug entries are emitted.
Manifest version bump
custom_components/haier_hon/manifest.json
version updated from 2.6.0 to 2.6.1.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • telard-pixel/haier_hon#7: Also modifies HonProgramSelect.current_option and tests/test_program_select.py around the same startProgram/prCode program-name resolution logic that this PR further refines.

Poem

🐇 A rabbit sorts keys with the greatest of care,
Names come before numbers — that's only fair!
startProgram shines first in the lookup parade,
No "non mappato" noise shall the debug logs invade.
Bump the version and hop, for the fix has been made! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Release v2.6.1' clearly and concisely summarizes the main change—a version bump release—which aligns with the manifest version update from 2.6.0 to 2.6.1 and the PR's purpose as an automated release pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Comment @coderabbitai help to get the list of available commands and usage tips.

@telard-pixel
telard-pixel merged commit e2f924b into main Jun 15, 2026
9 checks passed
tis24dev added a commit that referenced this pull request Jun 23, 2026
…t refresh

Audit findings #1 (HIGH) and #14, plus the concurrent-refresh race.

_check_headers refreshed the OAuth token before EVERY request whenever a
refresh_token was present (#1): with several appliances and the asyncio.gather
in load_commands, that is dozens of POST /services/oauth2/token per coordinator
cycle (token is valid 8h), risking cloud rate-limit/block. A single 401 also
cascaded into 3 refreshes (#14: pre-refresh + loop0 + recursion).

Refresh only when there is no usable in-RAM token (first request / restart with a
persisted refresh_token) or the token is near expiry; the 401 recovery in
_intercept is unchanged, and since refresh() resets _expires the recursive
_check_headers no longer fires a second time. An asyncio.Lock (on the connection,
not the create()-replaced HonAuth) with a re-check collapses a concurrent burst
into a single refresh, so a rotating IdP cannot invalidate the shared token
mid-flight.

Tests: no pre-refresh when fresh (#1), single refresh on 401 (#14), refresh on
expires-soon, restart-with-token refreshes not logins, concurrent burst -> 1
refresh (lock).
tis24dev added a commit that referenced this pull request Jun 23, 2026
…t refresh

Audit findings #1 (HIGH) and #14, plus the concurrent-refresh race.

_check_headers refreshed the OAuth token before EVERY request whenever a
refresh_token was present (#1): with several appliances and the asyncio.gather
in load_commands, that is dozens of POST /services/oauth2/token per coordinator
cycle (token is valid 8h), risking cloud rate-limit/block. A single 401 also
cascaded into 3 refreshes (#14: pre-refresh + loop0 + recursion).

Refresh only when there is no usable in-RAM token (first request / restart with a
persisted refresh_token) or the token is near expiry; the 401 recovery in
_intercept is unchanged, and since refresh() resets _expires the recursive
_check_headers no longer fires a second time. An asyncio.Lock (on the connection,
not the create()-replaced HonAuth) with a re-check collapses a concurrent burst
into a single refresh, so a rotating IdP cannot invalidate the shared token
mid-flight.

Tests: no pre-refresh when fresh (#1), single refresh on 401 (#14), refresh on
expires-soon, restart-with-token refreshes not logins, concurrent burst -> 1
refresh (lock).
tis24dev added a commit that referenced this pull request Jun 23, 2026
…t refresh

Audit findings #1 (HIGH) and #14, plus the concurrent-refresh race.

_check_headers refreshed the OAuth token before EVERY request whenever a
refresh_token was present (#1): with several appliances and the asyncio.gather
in load_commands, that is dozens of POST /services/oauth2/token per coordinator
cycle (token is valid 8h), risking cloud rate-limit/block. A single 401 also
cascaded into 3 refreshes (#14: pre-refresh + loop0 + recursion).

Refresh only when there is no usable in-RAM token (first request / restart with a
persisted refresh_token) or the token is near expiry; the 401 recovery in
_intercept is unchanged, and since refresh() resets _expires the recursive
_check_headers no longer fires a second time. An asyncio.Lock (on the connection,
not the create()-replaced HonAuth) with a re-check collapses a concurrent burst
into a single refresh, so a rotating IdP cannot invalidate the shared token
mid-flight.

Tests: no pre-refresh when fresh (#1), single refresh on 401 (#14), refresh on
expires-soon, restart-with-token refreshes not logins, concurrent burst -> 1
refresh (lock).
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