Repository navigation
Conversation
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
MyHomeServer1 README: "OWnd" typo; the alarm gate, the config-flow identification and the liveness probe rows name MyHOME OpenWebNet-HA#803, OpenWebNet-HA#804, OpenWebNet-HA#806. F461 README: the "What this capture backs" table extends to MyHOME OpenWebNet-HA#800-OpenWebNet-HA#806 (OpenWebNet-HA#802 the dimension 27 wire form, OpenWebNet-HA#803 *michnovka#5*0##, OpenWebNet-HA#804 the WHO 13 / 1013 identification replies, OpenWebNet-HA#806 the *OpenWebNet-HA#13**0## echo; OpenWebNet-HA#800 / OpenWebNet-HA#801 / OpenWebNet-HA#805 have no frame in this capture); it states that f461_live_2026-10-15 holds the dimension 22 reboot behind OWNd OpenWebNet-HA#136, the *4*311*2## / *4*311*#2## pair behind OWNd OpenWebNet-HA#137 and probe_area0 behind OWNd OpenWebNet-HA#141 / MyHOME OpenWebNet-HA#798; and one sentence says reply_time_s is measured while tx.t is reconstructed from the probe log. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1a42c6d to
6cb5b33
Compare
MyHomeServer1 README: "OWnd" typo; the alarm gate, the config-flow identification and the liveness probe rows name MyHOME #803, #804, #806. F461 README: the "What this capture backs" table extends to MyHOME #800-#806 (#802 the dimension 27 wire form, #803 *#5*0##, #804 the WHO 13 / 1013 identification replies, #806 the *#13**0## echo; #800 / #801 / #805 have no frame in this capture); it states that f461_live_2026-10-15 holds the dimension 22 reboot behind OWNd #136, the *4*311*2## / *4*311*#2## pair behind OWNd #137 and probe_area0 behind OWNd #141 / MyHOME #798; and one sentence says reply_time_s is measured while tx.t is reconstructed from the probe log. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
6cb5b33 to
e58474b
Compare
…non-blocking polls (OpenWebNet-HA#123) After 600 s without a bus frame (keepalive ACKs excluded) send `*OpenWebNet-HA#13**0##` on the command session and expect its reply on the event session within 30 s. A miss recycles the event session only on gateways known to echo (seen echo, OWNd profile flag, then an F461 table: the physical F461 2.0.11 delivers the reply on the event session); three misses raise the `event_session_silent` repair. Silence alone never recycles, so OpenWebNet-HA#640's position on quiet plants stands. The event-triggered WHO 4 zone poll uses a non-blocking send so the reader never waits on a full queue (OpenWebNet-HA#123, OpenWebNet-HA#135, OpenWebNet-HA#158, OpenWebNet-HA#164). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
e58474b to
d35f5b9
Compare
GreenGrassBlueOcean
left a comment
There was a problem hiding this comment.
Code & Protocol Review
The core direction here is well thought out: probing an idle (600 s) monitor session with *#13**0## on the command pool, excluding *#*1## OWNSignaling keepalive ACKs as bus evidence, gating recycles on proven echo behavior so quiet plants (#640) never cycle needlessly, and switching the event-triggered WHO 4 Dimension 14 poll to send_status_request_nowait so _process_message never blocks on a full queue. Verified locally against both editable OWNd and pinned OWNd==2.0.0b11 (96 passed, 0 strict-mypy regressions on pinned OWNd, docs/translations/HA standards checks green).
Requesting changes for a few functional regressions and repair-lifecycle edge cases uncovered during protocol and concurrency review:
- [High] Active
*#13**0##polling triggersunconfigured_timezonerepairs onMyHomeServer1(andF460):- Before this PR,
MyHOMEnever actively sentrequest_time()(*#13**0##) orrequest_datetime()(*#13**22##), soGatewayIdentityMixin._handle_gateway_diagnostics(identity.py:375-383) was purely passive. - Both the Firmware Oracle (
F460,F461,MyHomeServer1) and PR #799's liveMyHomeServer13.87.13 capture (tests/fixtures/traces/myhomeserver1_live_2026-10-24) return*#13**0*HH*MM*SS*999##onevt, yetidentity.py:378only exemptsF461(WHO 1013code134). As written, every quietMyHomeServer1plant will raise a falseunconfigured_timezonerepair after the first 10-minute idle probe.
- Before this PR,
- [Medium]
event_session_silentrepair stays stuck during active bus traffic and becomes orphaned across entry reloads:_probe_missesandevent_session_silent_{entry_id}are only cleared inside_probe_once(). Once raised, normal daytime bus frames update_last_rx_atin_dispatch_event_frames, postponing_liveness_probe()indefinitely while leaving"gateway stopped reporting bus events"stuck in the UI until 10 minutes of total silence occur.- If the user reloads the integration (or saves Options / Reconfigures) while the issue is open,
async_unload_entrydoes not clearevent_session_silent_{entry_id}and the newEventSessionRunnerstarts with_probe_misses = 0—soif self._probe_misses:skips_delete_probe_issue()on subsequent healthy probes and orphans the issue until HA restarts.
- [Medium] Pinned
OWNd==2.0.0b11logsWARNING: Data received is not a messageevery 10 minutes on0530/124timezones:_is_time_echohandles the raw-string fallback whenOWNd==2.0.0b11fails to parse*#13**0*...*0530##/124(OWNd #144 is not yet in the pinned wheel), but_dispatch_event_framesstill passes that rawstrinto_process_message, hittinggateway_events.py:274(WARNING: Data received is not a message) every 10 minutes in half-hour timezone regions.
- [Medium]
MYHOMESERVER1missing fromEVENT_PROBE_ECHO_MODELS, mid-probe socket-drop race, and_probe_echo_seenoverridingechoes_event_session_probe = False— detailed inline below.
Non-blocking follow-ups
identity.py:583-589(_request_object_model): Also runs synchronously inside_process_messageand manually callsself.send_buffer.put_nowait(...)without cancelling the orphanwrittenfuture onQueueFullor catchingQueueShutDown; reusingself._command_pool.send_status_request_nowait(cmd)cleans up both.diagnostics.py&gateway.pyexports: Exporting_probe_echo_seen,_probe_misses, andprofile.echoes_event_session_probein config-entry diagnostics will make field reports immediately show which models echo*#13**0##in the wild; consider re-exportingEVENT_PROBE_*ingateway.py.__all__alongsideEVENT_STALL_TIMEOUT/EVENT_RESTART_BACKOFF_*.- PR description template: Before taking this out of Draft, please align the PR body sections with
.github/pull_request_template.md(including## State Diagramand## What does the Firmware Oracle / Encyclopedia say).
| self._last_probe_at = time.monotonic() | ||
| silent_for = self._last_probe_at - self._last_rx_at | ||
| # Never wait for room in a full queue: the probe is retried after the next idle period. | ||
| written = self.handler._command_pool.send_status_request_nowait(OWNGatewayCommand.request_time()) |
There was a problem hiding this comment.
High — Active *#13**0## probing triggers unconfigured_timezone (999) on MyHomeServer1:
Prior to this PR, OWNGatewayCommand.request_time() (*#13**0##) and request_datetime() (*#13**22##) were never actively sent by MyHOME. Sending *#13**0## every 10 minutes on idle plants feeds the echoed OWNGatewayEvent(dimension=0) into GatewayIdentityMixin._handle_gateway_diagnostics (custom_components/myhome/identity.py:375-383), which raises unconfigured_timezone whenever dim_val[3] == "999" and only exempts F461 (WHO 1013 code 134).
Both the Firmware Oracle (F460, F461, MyHomeServer1) and PR #799's live MyHomeServer1 3.87.13 capture (tests/fixtures/traces/myhomeserver1_live_2026-10-24: *#13**0*16*19*49*999##, *#13**0*16*22*38*999## on evt) return 999 in Dimension 0 on modern Home + Project firmware (which also has no legacy web clock UI at http://<gateway_ip>). Please ensure MyHomeServer1 (and F460 if applicable) is exempted or that internal liveness probes do not raise false unconfigured_timezone repairs every 10 minutes.
| if message is not None and not isinstance(message, OWNSignaling): | ||
| self._last_rx_at = time.monotonic() | ||
| if _is_time_echo(message): | ||
| self._last_echo_at = self._last_rx_at | ||
| self._rx_event.set() |
There was a problem hiding this comment.
Medium — event_session_silent stays stuck while the bus is active and orphans across entry reloads:
- Stuck during active bus traffic:
_probe_missesandevent_session_silent_{entry_id}are only cleared inside_probe_once()(lines 387–390). If 3 missed probes raiseevent_session_silentovernight and the session recovers, normal daytime bus frames arriving every few minutes keep advancingself._last_rx_athere, postponing_liveness_probe()(delay = max(_last_rx_at, _last_probe_at) + 600 - now). The"gateway stopped reporting bus events"warning remains stuck in the UI while bus events are actively flowing, until 10 minutes of total silence allow a probe to run. - Orphaned on reload: On config-entry reload (e.g. Options save / Reconfigure),
async_unload_entrydoes not deleteevent_session_silent_{entry_id}, and the newEventSessionRunnerinitializesself._probe_misses = 0. When the next probe succeeds,if self._probe_misses:at line 387 isFalse, so_delete_probe_issue()is never called and the issue stays orphaned for the rest of HA's uptime.
Clearing _probe_misses (and withdrawing any raised probe issue via a dedicated _probe_issue_raised: bool flag or unconditional delete on first healthy frame + in async_unload_entry) right here when any non-signaling frame arrives resolves both issues cleanly.
| if isinstance(message, OWNGatewayEvent): | ||
| return message.dimension == 0 | ||
| return str(message).startswith("*#13**0*") |
There was a problem hiding this comment.
Medium — Pinned OWNd==2.0.0b11 logs WARNING every 10 minutes on unparsed 0530 / 124 echoes (+ strict-typing nit):
- Against
manifest.json's pinnedOWNd==2.0.0b11(without OWNd Fix/invalid is on for light #144),*#13**0*20*42*07*0530##(seen in Firmware Oraclewho13-clock-readbackon F450) and*#13**0*...*124##raiseValueErrorinOWNMessage.parse(), soOWNEventSession.get_next()yields the rawstr. Line 67 counts it for the probe, but_dispatch_event_frames(line 329) still passes that rawstrtoself.handler._process_message(message)→gateway_events.py:274, emittingWARNING: Data received is not a message: '*#13**0*20*42*07*0530##'every 10 minutes on quiet plants in half-hour timezones. Either suppress that warning ingateway_events.pywhen_is_time_echo(message)matches, or coordinate bumpingmanifest.jsononce OWNd Fix/invalid is on for light #144 is released. - Nit:
return bool(message.dimension == 0)on line 66 avoidsmypy --strict[no-any-return]when runningscripts/typing_ratchet.pyin editable environments whereOWNdis untyped.
| # Models seen to deliver the ``*#13**0##`` reply on the event session (physical F461 | ||
| # 2.0.11). Fallback for OWNd profiles without an ``echoes_event_session_probe`` flag; | ||
| # the flag belongs in OWNd (#381 pattern). | ||
| EVENT_PROBE_ECHO_MODELS = frozenset({"F461"}) |
There was a problem hiding this comment.
Medium — MYHOMESERVER1 missing from EVENT_PROBE_ECHO_MODELS (and #123 / #164 coverage note):
- PR test(trace): ingest live F461 2.0.11 2026-10-23 capture and MyHomeServer1 3.87.13 reads behind OWNd #136-#142 and MyHOME #791-#798 #799 (
tests/fixtures/traces/myhomeserver1_live_2026-10-24) proved on physicalMyHomeServer13.87.13 that*#13**0##is echoed onevt(run1_identify,run3_reads_lights_addresses_humidity). Without"MYHOMESERVER1"inEVENT_PROBE_ECHO_MODELS(untilOWNdcarriesechoes_event_session_probe), aMyHomeServer1whose event session is already silent from startup/reload has_probe_echo_seen == Falseand will never be recycled or raiseevent_session_silent. Once the999timezone handling is updated,"MYHOMESERVER1"should be included here (and noted in.github/release-notes/2.0.0b16.md). - Also note for issue linking:
#123was reported on anF454and#164on anF453, whose existing traces intests/fixtures/traces/are mergedBusMonitorcaptures that do not distinguishcmdvsevtdelivery for*#13**0##. Worth noting in the PR body / release notes that F454/F453 are only covered if they echo*#13**0##onevt.
| if self._probe_echo_seen: | ||
| return True | ||
| if isinstance(flag, bool): | ||
| return flag |
There was a problem hiding this comment.
Medium — Explicit profile.echoes_event_session_probe is False should not be overridden by _probe_echo_seen:
Per OpenWebNet Encyclopedia ownkb:chunk:r000309, WHO 13 Dimension 0 value frames can appear on monitor sessions as server-originated or external-supervisor traffic. If a gateway whose OWNd profile is hardware-verified not to echo its own command-session *#13**0## (flag is False) happens to deliver a spontaneous/supervisor *#13**0*...## frame inside a 30 s probe window once, _probe_echo_seen latches True for the lifetime of EventSessionRunner and will falsely recycle that gateway every 10 minutes on quiet nights.
Consider checking if isinstance(flag, bool): return flag before if self._probe_echo_seen: return True so _probe_echo_seen only resolves unverified (flag is None) profiles.
| while self._last_rx_at <= written_at and (remaining := deadline - time.monotonic()) > 0: | ||
| self._rx_event.clear() | ||
| with contextlib.suppress(TimeoutError): | ||
| await asyncio.wait_for(self._rx_event.wait(), timeout=remaining) | ||
| if self._last_rx_at > written_at: | ||
| # Any frame proves the event path; only the time reply proves this gateway echoes. | ||
| if self._last_echo_at > written_at: | ||
| self._probe_echo_seen = True | ||
| if self._probe_misses: | ||
| LOGGER.info("%s Event session answers the liveness probe again.", self.log_id) | ||
| self._delete_probe_issue() | ||
| self._probe_misses = 0 | ||
| return True | ||
| if not self._probe_echo_expected(): | ||
| LOGGER.debug( | ||
| "%s `*#13**0##` was not echoed on the event session; this gateway has never " | ||
| "echoed it, so the session is kept.", | ||
| self.log_id, | ||
| ) | ||
| return True | ||
| self._probe_misses += 1 |
There was a problem hiding this comment.
Medium — Re-check self.is_connected after waiting EVENT_PROBE_TIMEOUT:
_liveness_probe checks if not self.is_connected: before calling _probe_once(), which then waits up to 30 s here. If the TCP socket drops a few seconds after written_at (so self.is_connected flips False and OWNEventSession.get_next() is already reconnecting under the stall watchdog), waking at deadline without re-checking self.is_connected counts a false _probe_misses += 1 and forces _probe_recycle = True mid-reconnect.
Adding if not self.is_connected: return True before line 392 keeps socket drops strictly under OWNd and the stall watchdog.
| 2. Restart the gateway. | ||
|
|
||
| ### How it clears | ||
| The issue is withdrawn as soon as a probe is echoed again. |
There was a problem hiding this comment.
Nit — Wording mismatch with _probe_once recovery condition (repairs.py:124 & repair-issues.md:58):
Both this section and async_delete_event_session_silent_issue's docstring say the issue clears "once a probe is echoed again", whereas _probe_once() clears on any bus frame (self._last_rx_at > written_at, matching strings.json's "when the gateway answers again"). Updating both to reflect that any received bus event or probe echo clears the issue keeps the docs and code aligned.
|
@gdluck I cannot keep asking myself if this is really a problem. The issues mentioned in this pr are based upon 0.9.x. versions not on the revised v2. I cannot stop thinking that this a medicine for a cure that does not exist... |
|
Fair point: the issues this PR cites (#123, #135, #158, #164) were reported on 0.9.x, and nothing on v2 shows the problem (the only live observation today was that the probe never fired in 12 minutes because the F461 broadcasts its clock hourly). Closing it and dropping the branch; no medicine without a diagnosis. If a v2 trace ever shows a silently dead event session, the capture can reopen the question. |
Requested by A
Design feedback welcome: this is the active side of the "TCP up, bus dead" trade-off that #640 documented and left open.
What is the problem
Several reports describe the same failure: the event session stays connected, commands still go out and are answered, but bus updates stop arriving until the integration is reloaded (#123 on an F454, #164 on an F453; #135 and #158 describe the symptom without naming the gateway; the #123 reporter self-healed on Jeedom by reading the gateway time every 5 minutes). #640 (#637) rightly removed the passive inactivity timeout: a quiet plant is not a dead plant, and a 65-minute teardown on the MH201 produced reconnect churn and spurious warnings. OS TCP keepalive catches a dead socket, but not a live socket on which the gateway has stopped relaying the bus.
This PR adds an end-to-end probe that fires only after real silence and only draws a conclusion on gateways known to echo it. It does not reintroduce a passive timeout: silence alone never recycles anything, and a gateway that is not known to echo the probe is never recycled either.
Refs #123, #135, #158, #164, #640 (all closed).
What is the solution
gateway_sessions.py:EVENT_PROBE_IDLE = 600 s,EVENT_PROBE_TIMEOUT = 30 s,EVENT_PROBE_REPAIR_AFTER = 3,EVENT_PROBE_ECHO_MODELS = {"F461"}._read_event_sessionstarts one_liveness_probetask per event session and cancels it with the session. The read loop (_dispatch_event_frames) stamps_last_rx_atfor every frame that is notOWNSignaling, so the profile keepalive ACKs (*#*1##) keep TCP alive but do not count as bus traffic. The probe's echo is recognised by_is_time_echo: anOWNGatewayEventwith dimension 0 as OWNd parses*#13**0*HH*MM*SS*TZ##(the test(trace): ingest live F461 2.0.11 2026-10-23 capture and MyHomeServer1 3.87.13 reads behind OWNd #136-#142 and MyHOME #791-#798 #799 rows carryownd_class: OWNGatewayEvent), with the raw-string prefix*#13**0*as the fallback for a reply the pinned OWNd hands back unparsed. The keepalive itself is untouched.*#13**0##is queued on this gateway's own command pool withsend_status_request_nowait(never blocks on a full queue; if it cannot be written there is no verdict). Once written, the probe waits 30 s for any frame on the event session:listening_looprecreates it with the normal 5 s backoff (_run_event_sessionlogs DEBUG instead of "stalled"). After 3 consecutive misses a repair issueevent_session_silentis raised; it clears on the next echo.getattr(profile, "echoes_event_session_probe", None),None= unverified) and falls back toEVENT_PROBE_ECHO_MODELS; a seen echo wins over both. The flag belongs in OWNd (fix(gateway): close idle command sessions before the gateway drops them #381 pattern); the table is the stop-gap._update_event_watchdogdoes not disarm the watchdog while a probe recycle is pending (a late frame cannot cancel the recycle after the probe decided).CommandWorkerPool.send_status_request_nowait(+_envelopehelper shared with_enqueue);MyHOMEGatewayHandler.send_status_request_nowaitwith the same delegated / standby routing assend_status_request.gateway_events.py: the event-triggered WHO 4 zone poll (after a dimension 14 echo) uses the non-blocking path; a full queue skips the poll at DEBUG instead of blocking the event read loop (the zone's own pushes and the next poll still update it). This was the one place where the reader could wait on the sender.repairs.py,strings.json(+translations/en.jsonviamanage_translations.py sync-en),docs/diagnostics/repair-issues.md: theevent_session_silentissue.tests/test_event_session_liveness.py(new, 22 cases): connected-but-silent F461 session is recycled and repaired after 2 misses (constants patched); an echoed probe keeps the session and marks the gateway; unrelated traffic keeps the session but does not prove an echo; a gateway that never echoed is not recycled; keepalive ACKs do not hide a dead bus; an unsent probe is not a miss; a full send queue does not block the event reader (failed before); the event-triggered poll is queued when there is room (guard); the profile flag decides before the table (4 cases) and a seen echo outweighs it; no probe while disconnected; a probe exception is logged and the probe keeps running; the first echo after a miss withdraws the repair; the repair issue is created / deleted in the issue registry; the non-blocking path follows the delegated / standby routing;_is_time_echoon the parsedOWNGatewayEvent(dimension 0 yes, the date dimension 1 no, a light event no) and the raw-string fallback. Updated:test_gateway.py::test_listening_loop_other_eventsandtest_issue_674_f455_climate_trace.py::test_gateway_events_skips_zone_status_query_on_physical_gatewaysassert the non-blocking path..github/release-notes/2.0.0b16.md: one line under "Other behaviour changes".Companion PR: None in OWNd yet: the
echoes_event_session_probeprofile flag this PR reads first is proposed, not opened (#381 pattern).State Diagram
stateDiagram-v2 direction TB state "Event session liveness probe (per open event session)" as Probe { [*] --> Idle Idle --> Idle : any non-keepalive frame on the event session stamps _last_rx_at Idle --> Probing : 600 s without a bus frame while connected - *#13**0## queued nowait on the command session Probing --> Idle : queue full or session unavailable - no verdict , DEBUG, retried after the next idle period Probing --> Echoed : *#13**0*HH*MM*SS*TZ## , OWNGatewayEvent dimension 0 on the event session within 30 s - echo seen, misses 0, repair withdrawn Probing --> Alive : any other frame within 30 s - alive, misses 0 , does not prove an echo Probing --> Missed : no frame within 30 s Missed --> Idle : gateway never seen to echo, profile flag not True, model not in the table - DEBUG, session kept Missed --> Recycle : echo seen before, or profile flag True, or model in {F461} - WARNING, miss + 1, watchdog expired, listening_loop recreates the session Recycle --> Repair : 3 consecutive misses - repair issue event_session_silent Repair --> Echoed : next echo clears the issue Echoed --> Idle Alive --> Idle } state "Before this PR" as Before { [*] --> TcpOnly : OS TCP keepalive only - a live socket on which the gateway stopped relaying the bus is never noticed , #640 removed the passive timeout on purpose }Hardware Verification
*#13**0##sent on the command session is answered there and the reply is also delivered on the event session, parsed by OWNd asOWNGatewayEvent(rows below). This is the echo the probe relies on, and the reason the fallback table holds only the F461.*#13**0##ACKed in 94 ms and 23 ms, the reply echoed on the event session both times (rows below). This unit behaves like the F461. The fallback table stays at{F461}(one unit, two observations); the runtime learns the echo on the first probe anyway, so a MyHomeServer1 is recycled from its second silent probe on without any table entry. AddingMyHomeServer1to the table on the strength of this capture is a one-line change if you prefer it.*#13**27##reply at 14:16:12 the local HA sent nothing for 12 min; the bus was silent until 14:20:00, when the F461 broadcast its own clock (*#13**#1*06*24*10*2026##,*#13**#0*17*20*00*##), which reset the silence window (the window then ran 8 min 38 s to the end of the test). HA sent no*#13**0##probe and performed no reconnect in the whole 12 min (expected: nothing before 600 s of silence). The echo path was seen at 14:09:13 in the services scenario (*#13**0##answered and echoed on the event session). The recycle path therefore has no live capture; a forced event-only stall (dropping the event flow on the HA host with a firewall rule) is the live test still to do, and a run on an F454 / MH200 / MH201 bench would be welcome.How is it tested
tests/test_event_session_liveness.py(new, 22 cases, listed above) and the two updated tests.EVENT_PROBE_*constants; failures on the missing non-blocking sender and_is_time_echo, plus the 2 updated tests), 65 pass; all pass after.master(f04d8aa, the behaviour of the 2.0.0b11 pin): 4440 passed, 1 skipped (basev2-phase1-architectureddc6d60: 4418 passed, 1 skipped).scripts/verify_ownd_coverage.py100 %,scripts/typing_ratchet.py0 errors (baseline 0),ruff check .,scripts/verify_ha_standards.py,scripts/sync_documentation.py --check,scripts/manage_translations.py checkall pass.Live retest (2026-10-24)
Consensus label: core liveness not exercised (hourly F461 clock broadcasts reset the silence window); no spurious probe or reconnect in 12 min; the echo path was seen.
Where are the traces
*#13**0##echoed on the event sessiontests/fixtures/traces/f461_live_2026-10-23/runrun1_oracle_replay_readonlysteporacle_who13, and runrun2_reviewer_reads(trace PR: #799, merged)*#13**0##→ ACK in 8 ms with*#13**0*23*38*50*999##on the command session and the same frame on the event session (note: who13_time_echoed_on_evt,ownd_class: OWNGatewayEvent); run 2:*#13**0*00*02*31*999##likewisetests/fixtures/traces/myhomeserver1_live_2026-10-24/runsrun1_identifyandrun3_reads_lights_addresses_humidity(trace PR: #799, merged)*#13**0##→ ACK in 94 ms / 23 ms with*#13**0*16*19*49*999##/*#13**0*16*22*38*999##on both sessions (ownd_class: OWNGatewayEvent)tests/fixtures/traces/f461_live_2026-10-23/runrun6_event_session_ha_fixed_integration(trace PR: #799, merged)*#13**#1*…##/*#13**#0*…##on the event session count as traffic;*#*1##does notWhat does the Firmware Oracle / Encyclopedia say
Published rows (
results/<P>/<V>/oracle/full/who13-clock.tsv, index 53f9514),*#13**0##:ack/outwith*#13**0*{UTC}*{M}*{S}*<tz>##on all 12 emulated gateways: time zone001on F450 020010, F454 020051, F459 020105;000on F453 010100, F453AV 030014, H4684 020054, MH200 020102, MH200N 010108, MH202 010024;999on F460 020012, F461 020011, MyHomeServer1 028206. The oracle sees the command session only, so it says the probe is harmless everywhere, not that it is echoed on the event session; the echo is a live fact for the F461 and the MyHomeServer1 only.Note on #593: OWNd b9 raised
ValueErroron an event-side*#13**0##; the pinned OWNd parses the reply asOWNGatewayEvent, which is what_is_time_echomatches, with the raw prefix as the fallback.Checklist
What is the problem,What is the solution,State Diagram,How is it tested,Where are the traces,What does the Firmware Oracle / Encyclopedia say).pytest,ruff, andscripts/verify_ha_standards.pypass.🤖 Generated with Claude Code