v0.4.1
🌬️ DKNCloud-HASS v0.4.1
✅ Stable release for the 0.4.x line.
Focus: experimental HEAT_COOL support, a unified write pipeline, hardened config flows, and safer unload/diagnostics — with regression tests to keep it that way.
🚀 Highlights (since 0.4.0)
-
❄️ Experimental HEAT_COOL mode (P2=4)
- Optional HEAT_COOL exposure in climate entities when the modes bitmask advertises index 3 and the new “Enable experimental HEAT_COOL mode” toggle is enabled.
- While in HEAT_COOL, the integration routes:
- Temperature setpoints via P7.
- Fan speeds via P3.
- New diagnostic sensor
heat_cool_supportedis derived from the modes bitstring so installers can confirm HEAT_COOL compatibility directly from Home Assistant.
-
📊 Better diagnostics & scenary visibility
- New diagnostic sensor
preset_modeexposes the current scenary as a history-friendly preset value (home / away / sleep). - Diagnostics regression coverage ensures tokens, MAC addresses, and GPS coordinates remain fully redacted.
- Offline/online persistent notifications are scheduled from the coordinator listener so banners appear reliably in the UI.
- New diagnostic sensor
-
🔌 Unified write pipeline & smarter power switch
- Power switch service now proxies the sibling climate entity to reuse:
- Away handling.
- Optimistic overlays.
- Refresh semantics.
A direct P1 fallback is kept when the climate entity is disabled or missing.
- All write paths (climate, switch fallback, numbers) share a per-device
asyncio.Lock, ensuring concurrent UI/automation writes are serialized and predictable. - Post-write refresh scheduling is coalesced per config entry to avoid redundant refresh bursts after a sequence of commands.
- Power switch service now proxies the sibling climate entity to reuse:
-
🔁 Safer unloads & lifecycle management
- Config entry unload preserves integration state when any platform raises, and logs a warning when a platform unload fails.
- Per-entry scheduled callbacks and transient locks are always cancelled/cleared during unload, avoiding dangling timers while preserving partial teardown state.
- Unload cleanup is guarded behind bucket-existence checks so missing buckets no longer raise.
- Cancel-handle failures are logged at debug level, leaving a trace without polluting normal logs.
-
🧩 Resilient overlays, migrations & IDs
- Optimistic overlay expiration guard now uses a tuple-based
isinstancecheck, preventingTypeErroron Python 3.11+. - Config entries store normalized unique IDs; the config flow aborts duplicates and migrates existing installs to the new identifier scheme via Home Assistant’s update helper.
- Config entry migration now bumps versions using the HA helper instead of direct assignment, preventing startup crashes.
- Optimistic overlay expiration guard now uses a tuple-based
-
🔐 Hardened config flows & input validation
- Rejects empty or whitespace-only emails before unique-ID assignment or login, avoiding invalid identifiers and unnecessary API calls.
- Normalizes the username on every redisplayed form to strip whitespace-only input and keep defaults consistent across all error cases.
- Validates missing or empty passwords defensively before attempting login to avoid wasted API calls and potential
KeyErrors in tests. - Config-flow input handling remains aligned with Home Assistant naming conventions, and the shallow copy used to normalize form defaults is documented.
-
🧪 Test coverage & tooling upgrades
- Climate unit tests enforce that HEAT_COOL exposure is gated behind both device capability and the experimental opt-in flag.
- Diagnostics regression coverage guards redaction of tokens, MAC addresses, and GPS coordinates.
- Switch regression coverage validates timeout resilience,
HomeAssistantErrorfallbacks, missing climate proxies, unexpected exceptions, and_send_eventwarning propagation. - Tooling retargets Black formatting to Python 3.14 using Black 25.9’s
py314flag and keeps Ruff aligned with the same baseline. - No functional changes vs. the last 0.4.1 pre-release; this build promotes the 0.4.1 line to stable and aligns metadata/changelog formatting.
🧾 Detailed changes – 0.4.1
Added
- Optional HEAT_COOL (P2=4) exposure in climate entities when the modes bitmask advertises index 3 and the new “Enable experimental HEAT_COOL mode” toggle is enabled. The integration routes setpoints to P7 and fan speeds to P3 while in this experimental mode.
- Diagnostic sensor
heat_cool_supportedderived from the modes bitstring so installers can verify HEAT_COOL compatibility from Home Assistant. - Diagnostic sensor
preset_modeto expose the current scenary as a history-friendly preset value (home / away / sleep).
Changed
- Options UI keeps the HEAT_COOL toggle visible at all times and clarifies that the opt-in only becomes active once a compatible installation is detected.
- Tooling: retarget Black formatting to Python 3.14 using Black 25.9’s
py314target flag (currently accepted even if not yet officially documented) and keep Ruff aligned. - Renamed the experimental P2=4 mode to
HVACMode.HEAT_COOLthroughout the integration and ensured fan/temperature writes always use the cold path (P7/P3). Historical changelog entries that mentioned “AUTO” refer to this same mode. - Documented the HEAT_COOL opt-in policy in
info.md, removed “AUTO” terminology, and surfaced the updated options-flow toggle copy (EN/ES) that calls out the P7/P3 routing. - Updated the power switch service to proxy the sibling climate entity for consistent away handling, optimistic overlays, and refresh semantics, while retaining a direct P1 fallback when the climate entity is disabled or missing.
- Coalesced post-write refresh scheduling per config entry to avoid redundant refresh bursts after consecutive commands.
- Ensured all write paths (climate, switch fallback, numbers) share a per-device
asyncio.Lockto serialize command ordering when UI and automations issue concurrent updates. - Added climate unit tests that lock HEAT_COOL exposure behind device capability and the experimental opt-in flag.
- Added diagnostics regression coverage to ensure tokens, MAC addresses, and GPS coordinates remain redacted.
- Added switch regression coverage for timeout resilience,
HomeAssistantErrorfallbacks, missing climate proxies, unexpected exceptions, and_send_eventwarning propagation. - Clarified the config entry setup docstring now that migrations are handled separately.
- Bumped integration version metadata to keep documentation and manifest aligned.
- Captured changelog formatting updates and aligned metadata as part of promoting the 0.4.1 series from pre-release to stable, with no functional changes compared to the last pre-release build.
Fixed
- Scheduled persistent notification create/dismiss coroutines from the coordinator listener so offline/online banners appear reliably in Home Assistant.
- Prevented the optimistic overlay expiration guard from raising
TypeErroron Python 3.11+ by replacing the union-basedisinstancecheck with a tuple-based guard. - Ensured config entries store normalized unique IDs, abort duplicates in the config flow, and migrate existing installs to the new identifier scheme.
- Fixed the config entry migration to bump versions via Home Assistant’s update helper, preventing startup crashes from direct assignment.
- Ensured config entry unload preserves integration state when any platform raises.
- Logged a warning when a platform unload reports failure and left scheduled callbacks untouched so partial teardowns stay visible.
- Documented the fallback offline/online notification copy so translations remain the single source of truth.
- Logged cancel-handle failures at debug level during unload so resilient cleanup still leaves a trace for debugging.
- Elevated
ServiceNotFoundlogs in the power switch to warning level so removed or renamed climate proxies remain visible while the entity falls back to direct P1 control. - Guarded
_send_eventwith climate-style warning logs and exception propagation to distinguish P1 API failures from proxy failures. - Always cancelled per-entry scheduled callbacks and cleared transient locks during config entry unload, even when some platforms failed to unload, to avoid dangling timers while still preserving partial teardown state.
- Guarded config entry unload cleanup behind bucket existence checks so missing buckets no longer raise, ensuring cleanup only runs when the entry data is present.
- Rejected empty or whitespace-only emails in the config flow before assigning unique IDs or attempting login, preventing invalid identifiers and unnecessary API calls.
- Normalized the username for every redisplayed config form to remove whitespace-only input and keep defaults consistent across all error cases.
- Validated missing or empty passwords defensively before attempting login to avoid unnecessary API calls and potential
KeyErrors during tests. - Kept config-flow input handling aligned with Home Assistant naming conventions and documented the shallow copy used to normalize form defaults.
Full Changelog: v0.4.0...v0.4.1