feat: parse RestoreV5/V4 clock schedule fields and fix turn_clock_off wiping day+night brightness#65
Merged
Conversation
dahlb
reviewed
Jul 2, 2026
…clock brightness to None
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.
Summary
The current clock behavior on RestoreV5/V4 is broken. Turning the clock off does not work properly —
turn_clock_offoverwritesclock.iwith a hard-coded655, which wipes both the day and night brightness (they're packed into that single value).For a consumer like Home Assistant this means a user can turn the clock light off, but can't meaningfully turn it back on (it returns at ~0% and looks dark) and changing brightness does nothing, until brightness is reset in the Hatch app.
turn_clock_offalso XOR-toggles the ON flag, so an "off" call can even flip the clock back on.Separately, the device's clock schedule (
turnOffModeand the on/off/dim/bright times) is never parsed, so consumers can't read the clock's mode or schedule at all.This PR fixes the broken
turn_clock_offbehavior and adds parsing for the five clock schedule fields. Tested locally against real RestoreV5 hardware (fw 10.1.625) and everything works (details below).Two related clock improvements for
RestoreV5(andRestoreV4, which subclasses it viaclass RestoreV4(RestoreV5): pass).1. Parse the clock display schedule
The device shadow's
clockobject reports the full display schedule, but_update_local_stateonly readsclock.iandclock.flags, so the schedule is unavailable to consumers:This adds five instance attributes and parses them incrementally (only when the key is present, since shadow deltas are partial):
They are also added to
__repr__. This makes it possible to expose the clock mode (Always On / Off at Night / Always Off) and the on/off/dim/bright times, and to tell which brightness channel (clock_daytimevsclock_nighttime) the device is currently displaying.2. Fix
turn_clock_offwiping day+night brightnessRestoreV5.turn_clock_off()currently writes a hard-codedclock.i = 655and XOR-toggles the clock ON flag:On RestoreV5/V4,
clock.iis a single 32-bit value packing both brightnesses:(nighttime_16bit << 16) | daytime_16bit(seepack_dual_percentages/unpack_dual_percentagesin the same module).655unpacks to nighttime = 0%, daytime = 1%, so turning the clock off from Home Assistant destroys both stored brightnesses. The device then shows a near-black clock until the user re-sets brightness in the Hatch app.Two problems:
i: 655overwrites the packed brightnesses instead of preserving them.flags ^ RIOT_FLAGS_CLOCK_ON(XOR) toggles the bit. If the shadow's flag state is ever out of sync, an "off" call can flip the clock back on.Fix — clear the ON flag explicitly (AND-NOT instead of XOR) and preserve the stored brightness.
clock_nighttime/clock_daytimenow default toNone(unknown) until the device reportsclock.i, and the packed brightness is only re-sent when both channels are known — so an off call that happens before any clock state has arrived clears the flag without zeroing the device's stored brightness:pack_dual_percentagesandRIOT_FLAGS_CLOCK_ONare already defined in this module, so no new imports are needed.set_clockand theclockproperty fall back to0when a channel is still unknown.Testing
turnOffMode,turnOffAt,turnOnAt,turnDimAt,turnBrightAt; all five now surface on the device object.turnOffMode="never"(Always On), setting nighttime=10% / daytime=100% made the physical clock display dim — confirming Always On uses the nighttime channel.turn_clock_off: after the patched off-call the device echoed both brightnesses preserved andis_clock_on: 0; turning it back on restored the ON state without touching brightness.