Add support to zone power settings - #341
Open
chegancasb wants to merge 3 commits into
Open
Conversation
foXaCe
added a commit
to foXaCe/hon
that referenced
this pull request
Aug 8, 2026
…mName, password-change error, program helpers Adapt interesting upstream (gvigroux/hon) PRs to the refactored fork: - gvigroux#336: appliances without a command set (e.g. TVs) handled gracefully (debug log, no error) - gvigroux#335: optional 'series' field in load_commands (no KeyError) - gvigroux#332: add programName to startProgram commands for WM/WD - gvigroux#318: detect ChangePassword redirect -> HonPasswordChangeRequiredError, actionable config flow error (password_change_required) in user/reauth/reconfigure + translations - gvigroux#317: limit 'Get programs details' button to oven/dishwasher (PROGRAM_HELPER_APPLIANCE_TYPES) + don't propagate 'program' parameter in start_command - Ignored gvigroux#341 (induction hob) and gvigroux#342 (pt-PT) per decision - 3 new tests (password change, missing series, button OV/DW), 410 total
foXaCe
added a commit
to foXaCe/hon
that referenced
this pull request
Aug 8, 2026
* chore: overhaul state file
* docs: overhaul state (phase 0/0.5/1 done)
* refactor: architecture & coordinator
- New typed coordinator HonBaseCoordinator (DataUpdateCoordinator[HonDevice]) with _async_setup one-shot (commands+statistics), UpdateFailed, async_set
- Modern config entry lifecycle: entry.runtime_data, ConfigEntryAuthFailed (translatable), ConfigEntryNotReady, async_on_unload, add_update_listener
- Typed exceptions (HonAuthenticationError/HonConnectionError/HonRateLimitError)
- OptionsFlow with configurable update_interval (30-3600s)
- Cleaned reauth + reconfigure flows (removed dead commented code, modern selectors)
- All platforms migrated from hass.data[DOMAIN] to entry.runtime_data
* docs: overhaul state (phase 2 done)
* refactor: modular structure
- Split monoliths into api/ (client, exceptions, models) and devices/ (base, per-platform entity classes)
- Platforms reduced to async_setup_entry importing from devices/
- Added helpers.py (snake_case, get_key, minutes_until)
- Deduplicated HonBaseEntity (device_info/attributes shared, no more 3x copy)
- Implemented 3 orphan service handlers (turn_off_oven/washingmachine/purifier)
- Removed dead code (async_get_device_ids duplicate, commented blocks, TODO orphans)
- Fixed translation_key bug in HonBaseChildLockStatus
- Fixed get_setting log spam (warning -> debug)
- Replaced deprecated CONCENTRATION_* constants with UnitOfDensity/UnitOfRatio
* docs: overhaul state (phase 3 done)
* fix: api client robustness
- Shared aiohttp session via async_get_clientsession (drop ssl=False private session)
- ClientTimeout(total=30) on every request
- Exponential backoff retry on 429/5xx/ClientError/Timeout (2^n up to 8s)
- Automatic token refresh on 401 with re-entrancy guard (no infinite loop)
- HonRateLimitError for HTTP 429
- Responses closed properly (async with), return parsed JSON
- Eliminated _LOGGER f-strings (lazy %s logging), removed setup log spam
- Fixed non-existent async_get_state call in washing machine service (connectivity via coordinator)
- datetime.utcnow() -> datetime.now(UTC)
* docs: overhaul state (phase 4 done)
* feat: modernize entities
- has_entity_name=True everywhere (HA prefixes device name)
- Unified unique_id format {entry.unique_id}_{mac}_{key} via coordinator.unique_id_prefix
- ConfigEntry VERSION 1->2 + async_migrate_entry: prefix existing unique ids with {email}_ (54 UID stable, verified)
- Activate number & select platforms (were dead code); merged duplicate entity creation, fixed missing .send() on start_command, fixed native_unit_of_measurement typo, fixed HonSelect MRO (HonDevice, SelectEntity) -> (HonBaseEntity, SelectEntity)
- update_sensor matches new prefixed unique_id format
* docs: overhaul state (phase 5 done)
* fix: config flow & fr translations
- Create strings.json (single source of truth, 1329 keys, parity strict with en/fr)
- Full French translations (was 5% coverage) with vouvoiement, strict key parity verified
- Clean dirty en.json data (lockStatuslockStatus, newline keys, test/ending states, broken config error)
- Add entity.binary_sensor.lockstatus + exceptions.auth_failed translations
- Clean services.yaml: typos (Botton->Bottom, ºC->°C), inconsistent defaults (30°->30, 400 rpm->400, 15 min->15), simplify huge send_custom_request default
- Align all 28 YAML services with handlers
- hassfest: 0 invalid integrations
* docs: overhaul state (phase 6 done)
* chore: typing + docstrings + hassfest
- from __future__ import annotations on all 30 files
- mypy --strict: 0 errors (fixed async_get_options_flow to new 2026.8 @staticmethod @callback pattern)
- 237 docstrings added across 22 files
- Switch available log spam: warning -> debug
- manifest.json: add loggers
- hassfest: 0 invalid integrations
* docs: overhaul state (phase 7 done)
* test: exhaustive test suite, coverage >= 90%
- 402 tests, 96% coverage (100% on all critical modules)
- tests/: conftest, config_flow (20), init (9), coordinator (13), client (38), helpers (11), parameter (25), device (44), command (11), services (7), devices/* (sensor, binary_sensor, switch, number, select, button, climate, water_heater)
- Fixed 2 real bugs found by tests:
* HonOptionsFlowHandler overwrote read-only config_entry (options flow crashed on HA >= 2026.7)
* HonDevice.set wrote into a recreated dict (value never persisted)
- ruff check+format green on code and tests, mypy strict green
- pre-commit mypy: run on whole package (pass_filenames=false) to avoid namespace collision
* docs: overhaul state (phase 8 done)
* chore: final validation, changelog, architecture
- Remove .overhaul-state.md (overhaul complete)
- CHANGELOG.md updated with all phases
- ARCHITECTURE.md rewritten for the modular structure
- Parallelize appliance context loading at setup (6.91s vs 8.93s baseline, faster boot)
- Remove duplicate load_commands/load_statistics calls (already in coordinator _async_setup)
* feat: localize entities (FR) + config flow & options translations + diagnostics
- Entity names moved from hard-coded English _attr_name to translation_key (HA resolves FR/EN): 100 keys added (sensor, binary_sensor, switch, button), strict parity strings/en/fr (1432 keys)
- Fixed invalid auto translation keys (start_time, statistics_programs_counter, water_hardness, haier_detergent_weight...)
- Config flow + options flow fully translated to French
- Added diagnostics.py (entry/appliances/coordinators/devices/entities snapshot, async_redact_data)
- Fixed options flow 500 error (async_get_options_flow passed config_entry to constructor that takes none)
- Tests updated to assert translation_key; added test_diagnostics; 404 tests, 96% coverage
- hassfest green, mypy strict green, unique_id stability preserved (71/71)
* feat: system health, README/docs update
- system_health.py: cloud reachability, appliance count, coordinator update status
- Tests for system health (406 tests total, 96% coverage)
- README: document options flow and reauth
- CHANGELOG: record system health + translations
* feat: localize button notifications + mode/phase/error entity names
- Button notifications (programs/settings details) in French, program titles translated via entity translations (program: value kept raw for the service call)
- Add missing 'name' to mode/phase/error/program translations (were state-only, entities showed no name)
- Fix fr.json using English names for wash_program_phase/washingmachine_error
- Add test asserting French notification text + translated title
- hassfest green, 407 tests, parity strict (1449 keys)
* perf: cut config entry setup time ~2.5x
- Remove redundant per-platform refreshes at setup: sensor (1x), switch (9x), climate (re-first-refresh after __init__ already refreshed)
- Parallelize load_commands + load_statistics in coordinator _async_setup
- Config entry setup: ~3.5-4s vs 8.93s baseline (measured on HA dev, 2 appliances)
- authorize (~2.1s, 3 dependent CIAM calls) is the remaining dominant cost
- Update test_sensor_platform (no longer awaits per-appliance refresh)
- 407 tests green, mypy/ruff green, 71 entities stable
* fix: audit findings — branding, min HA version, parallel updates, docs
- Add brand/ assets (icon 256/512, logo) for Bronze 'brands' rule (local bundle, modern 2026.3 method)
- Fix hacs.json + README min HA version 2024.1 -> 2026.7 (code uses UnitOfDensity/UnitOfRatio from 2026.7)
- Add PARALLEL_UPDATES to all platforms (0 for read-only with coordinator, 1 for action platforms) — Silver 'parallel-updates'
- README: add Removal, Data updates, Use cases, Examples, Known limitations sections — Gold docs rules
- Audit against Quality Scale of 2026-08-09, HA 2026.8
* fix: sanitize sensitive payload logging (CodeQL)
- CodeQL: 2 high-severity alerts logging full command payloads (mac, parameters) in debug
- Sanitize all payload logs in api/client.py: log mac/type/command/resultCode only, never full payloads or appliance lists
- Sanitize appliance list log in __init__.py (MAC addresses only)
* feat: adapt upstream PRs — empty command set, optional series, programName, password-change error, program helpers
Adapt interesting upstream (gvigroux/hon) PRs to the refactored fork:
- gvigroux#336: appliances without a command set (e.g. TVs) handled gracefully (debug log, no error)
- gvigroux#335: optional 'series' field in load_commands (no KeyError)
- gvigroux#332: add programName to startProgram commands for WM/WD
- gvigroux#318: detect ChangePassword redirect -> HonPasswordChangeRequiredError, actionable config flow error (password_change_required) in user/reauth/reconfigure + translations
- gvigroux#317: limit 'Get programs details' button to oven/dishwasher (PROGRAM_HELPER_APPLIANCE_TYPES) + don't propagate 'program' parameter in start_command
- Ignored gvigroux#341 (induction hob) and gvigroux#342 (pt-PT) per decision
- 3 new tests (password change, missing series, button OV/DW), 410 total
* fix: remove MAC identifiers from logs (CodeQL)
- CodeQL flags MAC addresses and appliance identifiers as sensitive data even in debug logs
- Replace identifier-bearing logs with counts/result codes only (appliances loaded N, resultCode, command type)
- No MAC/email/serial identifiers logged anywhere anymore
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.
Reported on #340
The Problem
For Haier Induction Hobs (Appliance type: IH), specifically model HAISJ64MC, the integration code in
sensor.pytries to map entities totempZ1,tempZ2, andtempZ3.However, in the tested Haier Hob appliance telemetry firmware, these
tempZXregisters are stale (frozen at 0 since the appliance was registered in hOn). Furthermore,tempZ4is entirely missing from the loop insensor.py, leaving 4-zone hobs with only 3 blind entities.The real-time operational power levels are sent inside the shadow payload under
powerZ1,powerZ2,powerZ3, andpowerZ4.Proposed Fix
The integration should expose the
powerZXtelemetry amongst other settings.Adds a section to explicitly register
powerZ{i}variables insensor.py:And new helper classes to read the dynamic state:
the missing temperature zone4 is fixed (although not used in the test appliance) with:
It also includes a set of new binary sensors extending the already present sensors.
binary_sensor.pyis updated with:And new helper classes to read the dynamic state: