Repository navigation
test(trace): ingest the F461 and MyHomeServer1 captures of 2026-10-25 (actuator status, fan speed and humidity per zone) - #815
Conversation
… (actuator status, fan speed and humidity per zone) Two physical captures behind OpenWebNet-HA#792 (actuator status at startup, hvac_action from dimension 20) and OpenWebNet-HA#793 (humidity gate), asked for in review 5642758778 of OpenWebNet-HA#792. f461_actuators_live_2026-10-25: a local Home Assistant at OpenWebNet-HA#792's head restarted with an event-only listener on the F461 2.0.11 / KW4691 zone 2 plant. The startup sweep is followed by *michnovka#4*#0*20##, answered by both actuators within 0.13 s (ACK after 2.13 s); climate.set_temperature 26.0 makes the valve report itself on 2.2 s after the dimension 12 echo (*michnovka#4*2#1*OpenWebNet-HA#20*1##, then *michnovka#4*2#1*20*1##), the restore to 23.5 makes it report itself off 2.1 s after the echo; the fan coil stays 5 / off. Every request is Home Assistant's, from its debug log, placed on the listener clock (source: home_assistant, t_estimated). The replay through the climate entity gives hvac_action idle -> heating -> idle and 23.5 -> 26.0 -> 23.5; the actuators attribute is asserted only where the entity exposes it. myhomeserver1_live_2026-10-25: status reads only on the MyHomeServer1 3.87.13 plant (zones 35-70): *michnovka#4*#0*20## ACKed in 0.50 s ahead of a 1.9 s burst of 43 distinct actuator frames (34 Z#1, 5 Z#2, the pumps 0#1..0#4, every one off); per zone *michnovka#4*Z*19## / *michnovka#4*Z*20## ACK on 34 zones and NACK on 54 / 56, *michnovka#4*Z*11## NACK on all 36 (the fan-speed dimension is refused on a valve zone), *michnovka#4*Z*60## ACK on the 17 zones with a probe and NACK on 19, *michnovka#4*0*60## answers the same 17; a 600 s listen with the house's own traffic. The replay of zones 35 and 47 through the climate entity gives idle with every actuator off; the pump frames have no route key and reach no zone. The 34 per-zone *michnovka#4*Z*60## reads join PHYSICAL_ONLY_TX_FRAMES (no oracle stimulus for a per-zone humidity read). Every rx frame parses in the pinned OWNd; the 'OpenWebNet-HA#20' command forms parse as OWNHeatingCommand (OpenWebNet-HA/OWNd#138 decodes them, both are accepted). Synthetic MACs 00:03:50:00:10:25 / 00:03:50:00:10:26, documentation IPs; no log, no local path. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
GreenGrassBlueOcean
left a comment
There was a problem hiding this comment.
Audit of PR #815 (b8b72b5b)
Branch / Base: gdluck:test/trace-f461-actuators-live-2026-10-25 (b8b72b5b) → v2-phase1-architecture (089fef51) — 7 files (+19,611 / -3)
Verification & Trace Forensics:
- GitHub CI & Validators: All 16 check-runs pass, Codecov diff coverage is 100%, and
pytest(OWNd==2.0.0b11+OWNddev),ruff check,scripts/verify_ha_standards.py,scripts/sync_documentation.py --check,scripts/typing_ratchet.py,scripts/update_trace_matrix.py, andscripts/anonymize_plant_fixture.py --check(0 with personal data) all pass cleanly. - Physical Trace Authenticity (Verified):
myhomeserver1_live_2026-10-25(MyHomeServer1fw3.87.13, 677evtframes / 1,224 rows): verified genuine hardware capture — 7 / 7 outlier NACKs (2.81–5.81 s) coincide with spontaneous background house traffic resetting the gateway's SCS bus-quiet window (vs 1 / 52 normal2.09–2.19 sNACKs), 42 / 43 positions in the*#4*#0*20##burst arrive in a non-deterministic CSMA/CA order relative to2026-10-24, internal WHO 13 reads answer in17–25 msvs139–290 ms(median 185 ms) on the 9600-baud SCS bus, the12:50:00→13:00:00Sunday25/10/2026clock broadcasts sit600.048 sapart under manual TZ999, all 34 active zones / 17 humidity probes / 74 of 75 WHO 1 addresses match2026-10-24, and all 36*#4*Z*60##annotations inPHYSICAL_ONLY_TX_FRAMESmatch the session log rows.f461_actuators_live_2026-10-25(F461fw2.0.11, 20evtframes / 51 rows): verified genuineOWNEventSessioncapture with reconstructed HAcmdrows transparently marked (source: "home_assistant",t_estimated: true,1–2 msspread across all 10 dual-loggedrun1replies, matching #792 comment6395632510and the[306, 1, 326, 93] ms*#4*2##burst fingerprint off461_live_2026-10-23/-24).
Findings to Address Before Merge
1. [High — Cross-PR CI Break with #792] Replay tests hardcode "valve": False in ._actuator_states
- Where:
tests/test_f461_actuators_live_2026_10_25_trace.pylines507and517:assert zone.hvac_action == HVACAction.HEATING and zone._actuator_states == {"valve": False, "2": False, "1": True}assert zone._actuator_states == {"valve": False, "2": False, "1": False}
tests/test_myhomeserver1_live_2026_10_25_trace.pyline461:assert fan_coil._actuator_states == {"2": False, "1": False, "valve": False}, "dimension 19 adds the valve key"
- What happens: The PR description states "The
actuatorsattribute is asserted only when the entity exposes it (#792), so the module stays green on both sides of that merge." However, #792 (4a41da61, commita24ad505) separates Dimension 19 (self._zone_active) fromself._actuator_statesso"valve"is no longer added. Mergingb8b72b5b+4a41da61immediately fails bothtest_replay_hvac_action_idle_heating_idleandtest_replay_actuator_burst_gives_idle_and_pumps_reach_no_zone({'1': True, '2': False} != {'1': True, '2': False, 'valve': False}). - Recommendation: Assert the per-actuator keys
"1"and"2"(as line498already does), or branch on"actuators" in zone.extra_state_attributes({"1": ..., "2": ...}when#792is present vs{..., "valve": False}on base) so both modules actually pass before and after#792merges.
2. [Low — Wrong Companion PR Citation] OpenWebNet-HA/OWNd#138 does not cover *#4*Z#N*#20*V##
- Where: PR body (2×),
tests/fixtures/traces/f461_actuators_live_2026-10-25/README.md(L97,L113),tests/fixtures/traces/myhomeserver1_live_2026-10-25/README.md(L70,L91),tests/test_f461_actuators_live_2026_10_25_trace.py(L32,L318), andtests/test_myhomeserver1_live_2026_10_25_trace.py(L255). - What happens:
OpenWebNet-HA/OWNd#138(fix(message): parse '#'-prefixed dimension 14 setpoint values) only parses#-prefixed dimension values on Dimension 14 (*#4*#1*14*#0230*1##), and itstest_hash_values_elsewhere_still_do_not_parseexplicitly rejects#elsewhere.*#4*2#1*#20*1##/*#4*Z#1*#20*0##have a#-prefixed dimension number (DIMENSION_WRITINGecho) and are not covered byOWNd#138. - Recommendation: Drop the
(OpenWebNet-HA/OWNd#138)attribution (or note that noOWNdPR covers#20write-form echoes yet while keeping the forward-compatibleOWNHeatingEventbranch in the parser assertions).
3. [Nit — Forward-Compatibility] Avoid pinning cmd.is_status_request == False on WHO 4 dimension reads
- Where:
tests/test_f461_actuators_live_2026_10_25_trace.pyline302(assert bool(cmd.is_status_request) == r["is_status_request"]). - What happens: In the fixture,
*#4*2*60##,*#4*2*19##, and*#4*#0*20##record"is_status_request": false(OWNd <= 2.0.0b11). IfOWNdlater classifiesis_dimension_requestframes asis_status_request = True, line302will failOWNd's conformance gate (whereas line401checks only the static JSON fieldtx["is_status_request"], andmyhomeserver1_live_2026-10-25does not assert equality againstOWNCommand.parse). Allowingcmd.is_dimension_requestwhenr["is_status_request"] is Falsekeeps the test forward-compatible.
| if r["dir"] == "tx": | ||
| cmd = OWNCommand.parse(r["frame"]) | ||
| assert cmd is not None, r | ||
| assert bool(cmd.is_status_request) == r["is_status_request"], r |
There was a problem hiding this comment.
If OWNd later classifies WHO 4 dimension reads (*#4*2*60##, *#4*2*19##, *#4*#0*20##, where cmd.is_dimension_request is True) as is_status_request = True, this strict equality against the captured r["is_status_request"] (False) will fail OWNd CI. Allowing bool(cmd.is_status_request) == r["is_status_request"] or getattr(cmd, "is_dimension_request", False) keeps this forward-compatible while still pinning tx["is_status_request"] on the archive row at line 401.
| assert OWNMessage.parse(FAN_COIL_OFF).fan_on is False, "value 5 is the fan-coil side off (OWNd's dimension 20 >= 5 rule)" | ||
| # the '#20' command form the F461 emits 3 - 37 ms before each status form: the pinned OWNd | ||
| # (<= 2.0.0b11) parses it as a command with no zone (the integration logs "Unsupported message | ||
| # type" and the entity never sees it); OpenWebNet-HA/OWNd#138 decodes the '#'-prefixed dimension |
There was a problem hiding this comment.
OpenWebNet-HA/OWNd#138 only parses #-prefixed values on Dimension 14 (*#4*#1*14*#0230*1##) and explicitly rejects # elsewhere — it does not decode #-prefixed dimension numbers like *#4*2#1*#20*1##. Please update this reference here, in the module docstrings (test_f461_...: L32, test_myhomeserver1_...: L255), in both fixture README.md files, and in the PR description (keeping the else event-decoding branch itself is great).
| assert seen[0][1:] == (HVACAction.IDLE, 26.0, HVACMode.HEAT), "the echo moves the setpoint, not the action" | ||
| assert all(action == HVACAction.IDLE for frame, action, *_ in seen if not frame.startswith("*#4*2#1")), "idle until the valve reports" | ||
| assert seen[-1] == (VALVE_ON, HVACAction.HEATING, 26.0, HVACMode.HEAT) | ||
| assert zone.hvac_action == HVACAction.HEATING and zone._actuator_states == {"valve": False, "2": False, "1": True} |
There was a problem hiding this comment.
Hardcoding "valve": False here and at line 517 breaks as soon as #792 (a24ad505) merges, because #792 moves Dimension 19 onto self._zone_active (zone._actuator_states becomes {"2": False, "1": True} / {"2": False, "1": False}). Please check keys "1" and "2" (as line 498 does) or branch on "actuators" in zone.extra_state_attributes so the test stays green on both sides of #792.
| assert valve.extra_state_attributes["fan_coil_heating"] is False and valve.extra_state_attributes["fan_coil_cooling"] is False | ||
| assert fan_coil.hvac_action == HVACAction.IDLE and fan_coil.current_humidity == 58.0 | ||
| assert fan_coil.extra_state_attributes["fan_coil_cooling"] is True and fan_coil.extra_state_attributes["fan_coil_heating"] is False | ||
| assert fan_coil._actuator_states == {"2": False, "1": False, "valve": False}, "dimension 19 adds the valve key" |
There was a problem hiding this comment.
Same cross-PR break with #792 as in test_f461_actuators_live_2026_10_25_trace.py:507,517: on #792, Dimension 19 sets self._zone_active rather than inserting "valve" into self._actuator_states, so fan_coil._actuator_states is {"2": False, "1": False} and this assertion fails.
…; drop the OWNd#138 attribution Review of OpenWebNet-HA#815 (5644290768): the replay tests asserted the whole _actuator_states dict including the base branch's "valve" key, which OpenWebNet-HA#792 moves to _zone_active; they now assert the per-actuator keys only. The 'OpenWebNet-HA#20' write-form echoes are not covered by OpenWebNet-HA/OWNd#138 (dimension 14 values only), so that attribution is removed from the READMEs and tests. The F461 tx check accepts is_dimension_request beside the archived is_status_request value, so a later OWNd classification cannot fail the conformance gate. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for the forensic pass; the three points are in 50c740e.
Privacy check 0 findings, ruff clean; the full suite is unchanged apart from these three modules' assertions. |
5641f91
into
OpenWebNet-HA:v2-phase1-architecture
Requested by A
Refs #792, #793
What is the problem
Review 5642758778 of #792 asked for the 2026-10-25 active valve-switching capture (
*#4*2#1*20*1##on 23.5 -> 26.0 °C, comment 6395632510) to be committed if the raw capture was still on disk, and for the climate entity tests to be tied to the real plant traces (the actuator burst of a MyHomeServer1 replayed throughMyHOMEClimate, pump frames0#1..0#4creating no zone). The convention since #714 / #753 / #799 is that every physical capture is ingested astests/fixtures/traces/<id>/with a README and a replay test module. This PR backs #792 with two captures of 2026-10-25, one per gateway family, without touching the integration.What is the solution
Two derived trace archives in the format of
f461_presets_live_2026-10-24(#812) andmyhomeserver1_live_2026-10-24(#799), each with its README and replay test module, plus 34 entries inPHYSICAL_ONLY_TX_FRAMES.tests/fixtures/traces/f461_actuators_live_2026-10-25/(20 event-session frames, 51 rows, 3 runs;tests/test_f461_actuators_live_2026_10_25_trace.py, 10 tests)0e44bcd7, PyPI OWNd pin) was restarted with an event-only listener on the bus.tx/ command-sessionrx/resultrow carriessource: "home_assistant"andt_estimated: true;tx.tis the worker's hand-over,result.tthe ACK, and the replies sit at the time the log collected each one.capture.home_assistant_entity_statesholds the entity's recorded service calls and state changes for the first write (the harness's second call was dropped by Home Assistant and is listed with that note; the restore went through REST and its state change was read back, not recorded).run1_startup_sweep_and_actuator_request(08:31:43-08:31:48 UTC,*#2*05##,*#4*2##,*#4*2*60##,*#4*2*19##,*#4*#0*20##),run2_setpoint_26_0_valve_on(08:32:59-08:33:02),run3_restore_23_5_valve_off(08:35:55-08:35:57).00:03:50:00:10:25and IP192.0.2.92in thegatewayblock only (no WHO 13 frame was exchanged); genericclimate.climate_zone_2; no log, no diagnostics, no local path.tests/fixtures/traces/myhomeserver1_live_2026-10-25/(677 frames, 1224 rows, 4 runs;tests/test_myhomeserver1_live_2026_10_25_trace.py, 10 tests)myhomeserver1_live_2026-10-24(WHO 4 zones 35-70; 34 zones answer, 54 and 56 do not exist; fan coilsZ#2on 47, 48, 57, 60, 70; pumps0#1-0#4; humidity probes on 17 zones). Status reads only, probe on its own command + event session, 1.2 s pause per request.run1_identify_and_all_zones_actuators(*#13**16##,*#13**0##,*#4*#0*20##),run2_per_zone_reads_19_20_11_60(zones 35..70 x*#4*Z*19##,*#4*Z*20##,*#4*Z*11##,*#4*Z*60##, 144 requests),run3_general_humidity(*#4*0*60##),run4_listen_600_s.00:03:50:00:10:26and IP192.0.2.9in thegatewayblock only (no*#13**12##was sent); the gateway identity repeats the 2026-10-24 fixture (noted ingateway.identification_note).tests/test_trace_oracle_validation.py: the 34 per-zone*#4*Z*60##reads (zones 36-70 but 39) joinPHYSICAL_ONLY_TX_FRAMESwith their live reply (no oracle stimulus for a per-zone humidity read; tier 1 failed on exactly those 34 frames before the entries); the*#4*35*60##,*#4*39*60##and*#4*2*60##notes record this capture's replies. Every other request (dimensions 19 / 20 / 11,*#4*#0*20##, the dimension 14 writes,*#2*05##) canonicalises to an existing verdict. Tier 4: every rx frame parses in the pinned OWNd;*#4*2#1*#20*1##/*#4*Z#1*#20*0##(the dimension written as#20) parse asOWNHeatingCommandwith no zone, so nopending_decoder_rxentry is needed; the tests accept an event decoding as well (no OWNd change decodes the#20write-form echo yet).python scripts/update_trace_matrix.pywas run: the F461 and MyHomeServer1 rows already cover WHO 1 / 2 / 4 / 13,README.md/docs/trace-availability.mdare unchanged. No release-notes edit, as test(trace): ingest live F461 2.0.11 2026-10-24 climate setpoint capture (knob, antifreeze split, presets, bezel, HA write) #810 / test(trace): ingest the F461 2.0.11 heating comfort / eco preset capture (dimension 12 split from 14) #812.State Diagram
sequenceDiagram participant Z as F461 zone 2 KW4691 participant H as Home Assistant (#792 head) Note over Z,H: run 1, startup H->>Z: *#4*2##, *#4*2*60##, *#4*2*19## Z-->>H: 0, 12 = 23.5, *4*1*2##, 14 = 23.5, 13; 60 = 34; *#4*2*19*5*0## H->>Z: *#4*#0*20## (+0.75 s) Z-->>H: *#4*2#2*20*5## (+88 ms), *#4*2#1*20*0## (+128 ms), ACK at +2.13 s Note over Z,H: run 2, climate.set_temperature 26.0 H->>Z: *#4*2*#14*0260*3## (ACK 90 ms, no reply) Z-->>H: *#4*2*12*0260*3##, *4*1*2##, *#4*2*0*0240## Z-->>H: *#4*2#1*#20*1## (+2.2 s), *#4*2#1*20*1## (+37 ms): heating Note over Z,H: run 3, climate.set_temperature 23.5 H->>Z: *#4*2*#14*0235*3## (ACK 104 ms, no reply) Z-->>H: *#4*2*12*0235*3##, *4*1*2##, *#4*2*0*0240## Z-->>H: *#4*2#1*#20*0## (+2.1 s), *#4*2#1*20*0## (+3 ms): idleReview follow-up (review 5644290768)
_actuator_statesas a whole dict (with the base branch's"valve"key) now assert the per-actuator keys"1"/"2"only, so both modules pass before and after feat(climate): request actuator status (dimension 20) on add and after reconnect, expose actuators, derive hvac_action #792 merges (checked against feat(climate): request actuator status (dimension 20) on add and after reconnect, expose actuators, derive hvac_action #792's head).#-prefixed dimension values on dimension 14 only; the*#4*Z#N*#20*V##write-form echo has no OWNd decoder yet. The attribution is dropped from both READMEs, both test modules and this description; the forward-compatible event-decoding branch stays.is_status_requestpin: the F461 module acceptscmd.is_dimension_requestbeside the archivedis_status_requestvalue, so a later OWNd that classes dimension reads as status requests does not fail its conformance gate; the archive row itself is still pinned.Hardware Verification
F461 2.0.11, KW4691 zone 2, 2026-10-25 08:31-08:36 UTC (every frame in the archive):
*#4*#0*20##, sent 0.75 s after the startup sweep's last ACK, was answered by*#4*2#2*20*5##(fan coil, off) at +88 ms and*#4*2#1*20*0##(valve, off) at +128 ms; the ACK came 2.13 s after the request, 2.0 s after the last reply. With feat(climate): request actuator status (dimension 20) on add and after reconnect, expose actuators, derive hvac_action #792 the entity showedhvac_action: idle,actuators: {"1": "off", "2": "off"}12.1 s after it was added; on the previous build the first dimension 20 frame after a start was the F461's periodic broadcast 56 min later (not in the archive).*#4*2*#14*0260*3##(ACK 90 ms, no reply) was echoed as*#4*2*12*0260*3##,*4*1*2##,*#4*2*0*0240##(no dimension 14 frame); 2.203 s after the echo*#4*2#1*#20*1##, 37 ms later*#4*2#1*20*1##. The restore (*#4*2*#14*0235*3##, ACK 104 ms) was echoed the same way; 2.126 s later*#4*2#1*#20*0##, then*#4*2#1*20*0##3 ms later. The fan coil sent nothing but its startup reply.hvac_actionNoneuntil*#4*2*19*5*0##,idlethrough the startup actuator replies,heatingon*#4*2#1*20*1##,idleon*#4*2#1*20*0##; the setpoint follows the dimension 12 echoes 23.5 -> 26.0 -> 23.5 inheat. Theactuatorsattribute is asserted only when the entity exposes it (feat(climate): request actuator status (dimension 20) on add and after reconnect, expose actuators, derive hvac_action #792), and the internal actuator states are asserted per key"1"/"2"(the base branch adds a"valve"key from dimension 19, feat(climate): request actuator status (dimension 20) on add and after reconnect, expose actuators, derive hvac_action #792 moves that to_zone_active), so the modules stay green on both sides of that merge.MyHomeServer1 3.87.13, zones 35-70, 2026-10-25 10:46-11:02 UTC:
*#4*#0*20##: ACK in 0.50 s with 8 frames on the command session; the event session received 47 frames from +0.18 s to +1.91 s (39 after the ACK), 43 distinct: 34Z#1, 5Z#2at 5,0#1-0#4; every actuator off (the same 43 frames as the 2026-10-24 capture).*#4*Z*19##/*#4*Z*20##: ACK on 34 zones in 0.16-0.25 s, NACK after 2.1 s on 54 and 56; a fan-coil zone reads*#4*Z*19*5*0##and answersZ#2andZ#1.*#4*Z*11##: NACK on all 36 zones (the fan-speed dimension is refused on a valve zone, the F461's heating-season split off461_live_2026-10-15).*#4*Z*60##: ACK on the 17 zones with a probe (0.19-0.29 s), NACK on the other 19;*#4*0*60##answers the same 17 in 0.66 s._zone_route_keys): bothidlewith every actuator off, zone 47 withfan_mode: auto/running_fan_speed: off; the pump frames have no route key and reach no entity; the per-zone reads keep both idle and give zone 47 its humidity; the listen gives both their heating season. Nine spontaneous valve off reports, each*#4*Z#1*#20*0##then the status form within 50 ms, each about 2 s after the zone's pump call.How is it tested
pytest tests/test_f461_actuators_live_2026_10_25_trace.py: 10 passed. Schema and synthetic identity, every frame parses in the pinned OWNd (the#20command form asOWNHeatingCommand, an event decoding accepted), result rows consistent with theirtx/rxrows (replies between the request and its ACK, writes with no reply and their echo after the ACK), the startup sweep, the actuator request answered within 0.2 s, the two writes and their valve reports with offsets, the fan coil staying 5 / off, and two replays through the climate entity (idle -> heating -> idle; the recorded live states).pytest tests/test_myhomeserver1_live_2026_10_25_trace.py: 10 passed. Schema, parsing and route keys (zone frames to their zone, pump frames to none, a pump call to its zone), result-row consistency with NACKs, identification, the 43-frame burst, dimensions 19 / 20 per zone, dimension 11 refused everywhere, humidity only where a probe exists (per zone and general), the house's traffic, and the replay of zones 35 and 47.pytest tests/test_trace_oracle_validation.py tests/test_device_health_corpus.py tests/test_fixture_privacy.py: 256 passed (tier 1 failed on the 34 per-zone humidity reads before thePHYSICAL_ONLY_TX_FRAMESentries).master, f04d8aa, no fix PR applied):pytest tests/ -n 4 --cov=custom_components.myhome: 4581 passed, 1 skipped, 100 % statement coverage (16,151 / 16,151).ruff check .,scripts/typing_ratchet.py(0 strict errors),scripts/verify_ha_standards.py,scripts/sync_documentation.py --check,scripts/update_trace_matrix.py(no change),scripts/anonymize_plant_fixture.py --check(6 files, 0 with personal data): all pass.Where are the traces
tests/fixtures/traces/f461_actuators_live_2026-10-25/myhome_trace_F461_actuators_live_2026-10-25.json,run1_startup_sweep_and_actuator_request*#4*2##->0, 12, *4*1*2##, 14, 13;*#4*2*19##->*#4*2*19*5*0##;*#4*#0*20##->*#4*2#2*20*5##,*#4*2#1*20*0##(+88 / +128 ms, ACK +2.13 s)run2_setpoint_26_0_valve_on*#4*2*#14*0260*3##->*#4*2*12*0260*3##,*4*1*2##,*#4*2*0*0240##;*#4*2#1*#20*1##,*#4*2#1*20*1##(+2.2 s)run3_restore_23_5_valve_off*#4*2*#14*0235*3##->*#4*2*12*0235*3##,*4*1*2##,*#4*2*0*0240##;*#4*2#1*#20*0##,*#4*2#1*20*0##(+2.1 s)tests/fixtures/traces/myhomeserver1_live_2026-10-25/myhome_trace_MyHomeServer1_live_2026-10-25.json,run1_identify_and_all_zones_actuators*#4*#0*20##-> 43 distinct*#4*Z#1*20*0##/*#4*Z#2*20*5##/*#4*0#N*20*0##run2_per_zone_reads_19_20_11_60,run3_general_humidity*#4*Z*19##,*#4*Z*20##(34 ACK / 2 NACK),*#4*Z*11##(36 NACK),*#4*Z*60##(17 ACK / 19 NACK),*#4*0*60##(17 zones)f461_live_2026-10-23run 6,myhomeserver1_live_2026-10-24run 2 (#799)*#4*2#1*20*0##+*#4*2#2*20*5##2.2 s after a zone poll;*#4*#0*20##-> 43 actuator framesWhat does the Firmware Oracle / Encyclopedia say
*#4*#0*20##,*#4*Z*19##,*#4*Z*20##,*#4*Z*11##and the dimension 14 writes canonicalise to existing verdicts (tier 1 passes), while the per-zone*#4*Z*60##reads have no stimulus and are recorded inPHYSICAL_ONLY_TX_FRAMESwith their live replies. own-firmware-oracle#60 (*#4*#0*20##forwarding matrix) gets the physical reply orders and ACK timings of both families (F461: both actuators within 0.13 s, ACK after 2.13 s; MyHomeServer1: ACK in 0.50 s ahead of a 1.9 s burst).*#4*Z#N*20*V##with V 0 / 1 for a valve and 5-8 for a fan coil, dimension 19 the valve status per side, dimension 11 the fan speed; the*#4*Z#N*#20*V##form the F461 and the MyHomeServer1 emit before each status form is the write form of the same dimension, decoded by neither the Encyclopedia nor the pinned OWNd; no OWNd PR covers it yet (fix(message): parse '#'-prefixed dimension 14 setpoint values OWNd#138 only parses#-prefixed dimension values on dimension 14).Checklist
What is the problem,What is the solution,State Diagram,Hardware Verification,How is it tested,Where are the traces,What does the Firmware Oracle / Encyclopedia say,Checklist).handle_event()and the platform's route keys).pytest,ruff, andscripts/verify_ha_standards.pypass.🤖 Generated with Claude Code