Record the clock the device stamps its own messages with - #34
Merged
Merged
Conversation
Every timestamp the integration holds is arrival time, so a pump run reported the instant a device reconnects after an outage is indistinguishable from one that happened at that moment. That has now been seen twice, both times within a dozen seconds of the device getting a working token back, and #17 wants to compute inflow and pump health from run timing. The device sends utcunixtime on every message and it was being dropped. Parse it into BbsReading, and record the gap between it and arrival on the device state. The gap alone proves nothing -- device clocks drift, so a constant offset is ordinary. What discriminates is a jump: the sensor shows what is normal for the device, and the pump-run event carries the offset of the message that reported the run. A run whose figure sits far from the usual one waited somewhere before it was delivered. If the device restamps on send instead of keeping the original time, the offset will stay flat through the next outage and that answers the question too. Nothing depends on the field: a message without it, or with one that cannot be read, parses as before and leaves the last known offset alone rather than fabricating a zero.
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.
Towards #25, and a prerequisite for #17.
Every timestamp we hold is arrival time. That is why a backup run reported at
the instant the device reconnects after an outage cannot be told apart from one
that actually happened then — the ambiguity #25 exists to record, now seen
twice (2026-08-21 00:30, 12 s after re-auth; 2026-08-22 22:45, 11 s after).
#17is built entirely on run timing, so if the device replays queued eventsits arithmetic is fed fiction precisely when the system is under stress.
The device has been telling us all along:
utcunixtimerides on every message,in milliseconds, and no production code read it. Only test fixtures contained
it.
What this does
BbsReading.device_time—utcunixtimeparsed to an aware UTC datetime.DeviceState.clock_offset_seconds— arrival minus that, updated per message.sensor.<device>_device_clock_offset(diagnostic) — what is normal for thisdevice.
clock_offset_secondson the pump-run event — the offset of the message thatcarried the run.
The raw number settles nothing on its own, which is why it is exposed as a
pair. Device clocks drift, so a steady offset of any size is ordinary; a run
whose figure sits far from the device's usual one is a message that waited. And
if the device restamps on send rather than keeping the original time, the offset
stays flat through the next outage — which answers the question in the other
direction.
The sensor is deliberately named
device_clock_offsetrather thanclock_error: it is clock drift plus transit time, the two cannot beseparated from here, and for "was this made now or made earlier and held" they
do not need to be.
Safety
Nothing depends on the field. A message without
utcunixtime, or with one thatcannot be read, parses exactly as before — and an unreadable value leaves the
last known offset in place rather than fabricating a zero. Tests cover both.
12 new tests, TDD, each seen failing first; one of them caught a wrong epoch
conversion in the test I had written. 209 pass.
core/still imports nohomeassistant.Not yet verified live
The parser tests run against real captured bodies, so the field and its units
are confirmed on the wire. What is not confirmed is what the live device's
offset actually looks like day to day — that needs a deploy, and the real answer
to #25 needs the next vendor outage.