Skip to content

Sync the appliance clock from the bridge host - #81

Merged
QuiteYellow merged 2 commits into
mainfrom
feat/demo-appliance-clock-sync
Sep 8, 2026
Merged

Sync the appliance clock from the bridge host#81
QuiteYellow merged 2 commits into
mainfrom
feat/demo-appliance-clock-sync

Conversation

@QuiteYellow

Copy link
Copy Markdown
Owner

Closes #79.

An appliance kept off the internet has no way to correct its own clock, so its display drifts. The demo bridge now writes the host's local wall clock to /configuration/vs/0 as x.com.samsung.da.currentTime, on a timer and on a Home Assistant button.

I closed #79 saying the appliances expose nothing to write. I had searched 86 device-tree dumps for a writable time field; the field is write-only, so no dump could have carried it, and the search could not have found it however long I ran it. LocalThings #404 / #428 had already verified it on a TP1X range.

Hardware

Reference oven, TP1X_DA-KS-OVEN-0107X, on the Unraid deployment:

17:43:39  clock sync (periodic) /configuration/vs/0 = 2026-09-08T17:43:38 -> 2.04
17:48:09  clock sync (mqtt)     /configuration/vs/0 = 2026-09-08T17:48:09 -> 2.04

I set the oven's panel clock to 19:47 by hand and synced at 17:48; the panel moved to 17:48. A GET of the resource still returns nothing, so the panel is the only read-back there is.

Why the demo and not the library

post() already sends this, so the library needs no new surface. Home Assistant users get the feature from LocalThings' own Sync clock button, shipped in #428. What was missing here was an example of running it on a schedule, which is what this adds.

Shape

ClockSyncTask is a session worker like KeepaliveTask and ObserveRefreshTask, but its schedule outlives the session: last_sync_ts travels through the bridge, so a connection that flaps still writes on the configured interval. A descriptor declares where its class takes the write through a ClockSync spec, and the task is only built once the seed shows the device carries the resource.

Two things the write must not do:

  • Reach the state cache. handle_command merges a successful write optimistically, and a write-only field has nothing to merge into, so the button is handled off the descriptor command path. A test fails if it is ever folded back in.
  • Carry a wrong host clock. A timestamp outside the device certificate's validity window can break certificate verification and leave the appliance unresponsive, which both LocalThings and the SmartThings forum thread the field came from warn about. A host reading outside PLAUSIBLE_FROM/PLAUSIBLE_UNTIL skips the write, so a container that boots before NTP lands writes nothing.

Oven-only for now. /configuration/vs/0 is writable on the dryer too, but the laundry dumps carry TimeSync_NotSupported and I have not tried the clock field there.

CLOCK_SYNC_INTERVAL_H defaults to 24 hours; 0 turns off both the timer and the button.

Tests

tests/test_clock_sync.py, 18 cases: wire format, rejection handling, the host-clock gate, the schedule across reconnects, resource-absent and interval-0 gating, and the cache one above. Full suite 757 passed.

An appliance kept off the internet cannot correct its own clock, so its
display drifts with nothing to pull it back. Issue #79 asked for this
and I closed it on the wrong reasoning: I searched 86 device-tree dumps
for a writable time field and found none. The field is write-only, so no
dump could ever have carried it. LocalThings #404 / #428 had it already,
verified there on a TP1X range.

x.com.samsung.da.currentTime on /configuration/vs/0 takes a local wall
clock, YYYY-MM-DDTHH:MM:SS, no offset. It answers 2.04 on the reference
oven here too. Setting the panel to a wrong time by hand and syncing
moves the panel, which is the part a response code cannot show.

ClockSyncTask is a session worker in the shape of KeepaliveTask and
ObserveRefreshTask, but its schedule outlives the session: last_sync_ts
travels through the bridge, so a connection that flaps still writes on
the configured interval. A descriptor declares where its class takes the
write, and the task is only built once the seed shows the device carries
the resource.

Two things the write must not do. It must not reach the state cache:
handle_command merges a successful write optimistically, and there is
nothing here to merge into, so the button is handled off that path. And
it must not carry a wrong host clock. A timestamp outside the device
certificate's validity window can break certificate verification and
leave the appliance unresponsive, so a host reading outside a plausible
window skips the write.

The library needs nothing for this: post() already sends it, and Home
Assistant users get the same feature from LocalThings' own Sync clock
button. This is the demo bridge only. Oven-only for now;
/configuration/vs/0 is writable on the dryer too, but the laundry dumps
carry TimeSync_NotSupported and the clock field is untried there.

CLOCK_SYNC_INTERVAL_H defaults to 24 hours and 0 turns off both the
timer and the button.

Claude-Session: https://claude.ai/code/session_01UJBUFo8zZWrebGqf6gUzcL
check_share_safety.py rejects a literal date-time in public files,
because a real one leaks when someone was doing something. The docstring
example and the format assertion carried one apiece. The example now
shows the shape, and the test parses what was written and compares it to
the datetime it fed in, which pins the format at least as tightly.

Claude-Session: https://claude.ai/code/session_01UJBUFo8zZWrebGqf6gUzcL
@QuiteYellow
QuiteYellow merged commit 5803f7d into main Sep 8, 2026
8 checks passed
@QuiteYellow
QuiteYellow deleted the feat/demo-appliance-clock-sync branch September 8, 2026 17:55
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.

Feature request: Automatic device clock synchronization

1 participant