Skip to content

test(trace): ingest the F461 2.0.11 heating comfort / eco preset capture (dimension 12 split from 14) - #812

Merged
GreenGrassBlueOcean merged 2 commits into
OpenWebNet-HA:v2-phase1-architecturefrom
gdluck:test/trace-f461-live-2026-10-24-presets
Oct 25, 2026
Merged

GreenGrassBlueOcean merged 2 commits into
OpenWebNet-HA:v2-phase1-architecturefrom
gdluck:test/trace-f461-live-2026-10-24-presets

Conversation

@gdluck

@gdluck gdluck commented Oct 24, 2026 •

Copy link
Copy Markdown

Requested by A

Refs #791

What is the problem

The review of #810 (review 5639746797, "Follow-up PRs / issues", item 1) asked for a small follow-up trace: in f461_live_2026-10-24 run 4 the heating comfort template *#4*2*#7*1*3## had been sent from a 21.0 baseline that already matched the KW4691's comfort preset, the "eco" request there was *#4*2*#7*2*3## (context 2 / state 3, cooling comfort, not heating eco *#4*2*#7*1*4##), and no dimension 14 read was sent while the preset was active. The capture was run the same evening and its results were posted on #791 (comment 6388993746); this PR puts the frames in the repository, as tests/fixtures/traces/f461_live_2026-10-24/ did for the first capture.


What is the solution

A new derived trace archive, tests/fixtures/traces/f461_presets_live_2026-10-24/ (named after f461_who14_live_2026-10-18: gateway, topic, live, date), in the exact format of f461_live_2026-10-24 (command-session replies at their request's t with t_estimated, events_after bounded by the ACK, one monotonic t axis with per-run t_offset, probe_segments with listener_offset_s, synthetic MAC 00:03:50:00:10:23 / IP 192.0.2.92, generic climate.climate_zone_2), plus tests/test_f461_presets_live_2026_10_24_trace.py (9 tests) and one entry in PHYSICAL_ONLY_TX_FRAMES.

  • Plant: BTicino F461 2.0.11, Living Now KW4691 standalone thermostat at zone 2 (BT-F430/2 valve as actuator 1, BT-F430/4 fan coil as actuator 2), heating season, no central unit; the same local Home Assistant as in test(trace): ingest live F461 2.0.11 2026-10-24 climate setpoint capture (knob, antifreeze split, presets, bezel, HA write) #810 (integration at fix(climate): show the setpoint in force (dimension 12), keep dimension 14 as the commanded value #791's head, PyPI OWNd pin, not restarted since) wrote climate.set_temperature.
  • Sessions: one event-only listener (20:08:44 UTC, 1800 s) and two probe invocations with their own command session. Both runs take their event frames from the listener; the probe's rows are placed on the listener clock through the frames both sessions received (capture.runs[].probe_segments[].listener_offset_s; the probe's own event log matched the listener's frames exactly over every request window before it was dropped). Home Assistant's only request in the window, the *#4*2*#14*0235*3## write at 20:11:20 UTC, is listed in capture.home_assistant_requests from its debug log (not included); its echo is in the frames and it has no tx / result row. Home Assistant sent no poll between the listener start and the write (its debug log shows only frames received).
  • Runs (capture.runs): run1_heating_comfort_then_heating_eco 103 rows / 36 frames (20:08:49-20:10:22 UTC), run2_home_assistant_write_realigns 19 / 11 (20:11:20-20:12:04 UTC); 47 event-session frames and 122 rows in all. The listener's frames after 20:12:04 UTC (clock, humidity, temperature) are not included.
  • Privacy: MAC and IP in the gateway block only (no WHO 13 identity frame was exchanged); no password, no local paths, no logs or diagnostics, no room-named entity id. python scripts/anonymize_plant_fixture.py --check on the three new files: 0 with personal data; tests/test_fixture_privacy.py passes.
  • tests/test_trace_oracle_validation.py: *#4*2*#7*1*4## joins PHYSICAL_ONLY_TX_FRAMES (no oracle stimulus for the dimension 7 templates; tier 1 failed on exactly that frame before the entry); the *#4*2*#7*1*3## entry's note now also records this capture's reply (from 23.5). Tier 4: every rx frame parses in the pinned OWNd; *4*107*2## / *4*108*2## parse with mode = None on the pinned OWNd (heating: WHAT 107 / 108 / 208 (zone eco / comfort mode echoes of a KW4691 behind an F461) are not decoded OWNd#146), so no pending_decoder_rx entry is needed; the test accepts the decoded heating eco / comfort as well, so OWNd's conformance job stays green when "Failed to set up" issue #146 lands. python scripts/update_trace_matrix.py was run: the F461 row already covers WHO 4 and 13, README.md / docs/trace-availability.md are unchanged.
  • Naming: *#4*2*#7*1*4## is context 1 (heating), state 4 (eco), heating eco; *#4*2*#7*1*3## is heating comfort. The archive's steps are baseline_poll, heating_comfort, heating_eco, poll_after_ha_write; the test locals use the same names.

State Diagram

sequenceDiagram
    participant Z as F461 zone 2 KW4691
    participant P as probe
    participant H as Home Assistant
    Note over Z,H: run 1, baseline 12 = 14 = 23.5
    P->>Z: *#4*2##
    Z-->>P: 0, *#4*2*12*0235*3##, *4*1*2##, *#4*2*14*0235*3##, 13
    Note over Z,H: heating comfort template
    P->>Z: *#4*2*#7*1*3##
    Z-->>P: *#4*2*7*1*3##, *#4*2*12*0210*3##, *4*108*2##
    P->>Z: *#4*2*12## and *#4*2*14## at +1 s and +13 s
    Z-->>P: 12 = 21.0 with *4*108*2##, 14 = 23.5
    Note over Z,H: heating eco template
    P->>Z: *#4*2*#7*1*4##
    Z-->>P: *#4*2*7*1*4##, *#4*2*12*0180*3##, *4*107*2##
    P->>Z: *#4*2*12## and *#4*2*14## at +1 s, +13 s and +48 s
    Z-->>P: 12 = 18.0 with *4*107*2##, 14 = 23.5
    P->>Z: *#4*2## at +15.5 s
    Z-->>P: 0, *#4*2*12*0180*3##, *4*107*2##, *#4*2*14*0235*3##, 13
    Note over Z,H: run 2, the write realigns both
    H->>Z: *#4*2*#14*0235*3##
    Z-->>H: *4*1*2##, *#4*2*12*0235*3##, *4*1*2##, *#4*2*0*0238##
    P->>Z: *#4*2## 7.4 s later
    Z-->>P: 0, *#4*2*12*0235*3##, *4*1*2##, *#4*2*14*0235*3##, 13
Loading

Review follow-up (review 5642383839)

  1. WHAT 107 / 108 / 208 pinned to mode is None, a cross-repo deadlock once heating: WHAT 107 / 108 / 208 (zone eco / comfort mode echoes of a KW4691 behind an F461) are not decoded OWNd#146 lands → 5ff109d: both locations relaxed as suggested, tests/test_f461_presets_live_2026_10_24_trace.py (107 / 108: mode in (None, "heat"), season in (None, "heating")) and the merged tests/test_f461_live_2026_10_24_trace.py (108 → heat / heating, 208 → cool / conditioning), with the "mode is unknown" log asserted only for the None case (a second-opinion review pointed out that a decoder might keep that log string). The replay test needs no change (noted in its docstring that mode = None is the pinned behaviour).
  2. Rounding nit → 5ff109d: the poll 15.53 s into eco is +15.5 s in the test docstring, the archive purpose and the sequence diagram, as in the README.

Hardware Verification

F461 2.0.11, KW4691 zone 2, 2026-10-24 20:08-20:12 UTC; every frame is in the archive.

  • A heating preset moves dimension 12 and leaves dimension 14 at the last commanded value. *#4*2*#7*1*3## from 12 = 14 = 23.5 (ACK 68 ms) was echoed as *#4*2*7*1*3##, *#4*2*12*0210*3##, *4*108*2##, *#4*2*0*0238##; *#4*2*12## answered *#4*2*12*0210*3##, *4*108*2## and *#4*2*14## answered *#4*2*14*0235*3## at +1 s and at +13 s. *#4*2*#7*1*4## 15.5 s later (ACK 89 ms) was echoed as *#4*2*7*1*4##, *#4*2*12*0180*3##, *4*107*2##, *#4*2*0*0238##; dimension 12 read 18.0 (with *4*107*2##) and dimension 14 read 23.5 at +1 s, +13 s and +48 s. Every 12 / 14 pair read after the comfort echo differed (21.0 / 23.5 twice, 18.0 / 23.5 three times); nothing realigned them while a preset was active. The split was observed for 48 s into eco; how long it lasts beyond that was not measured.
  • The mode frame takes the season frame's place. With a preset active *#4*2*12## returns *4*108*2## / *4*107*2## where the heating season returns *4*1*2##, and the *#4*2## poll 15.5 s into eco answered *#4*2*0*0238##, *#4*2*12*0180*3##, *4*107*2##, *#4*2*14*0235*3##, *#4*2*13*00##, as *4*102*2## does in antifreeze (f461_live_2026-10-24 run 3). The season frame appears once in run 1 (the baseline poll).
  • A Home Assistant write while 12 != 14 realigns both and brings the season frame back. climate.set_temperature 23.5 at 20:11:20 UTC, 2 min into eco: *4*1*2##, *#4*2*12*0235*3##, *4*1*2##, *#4*2*0*0238## (no dimension 14 frame, as for every dimension 14 write of f461_live_2026-10-24); the *#4*2## sent 7.4 s after the echo (result at 8.8 s, ACK 1.44 s) read 0, 12 = 23.5, *4*1*2##, 14 = 23.5, 13. 43 s after the write the valve reported itself off (*#4*2#1*#20*0##, *#4*2#1*20*0##); no actuator frame accompanied the preset changes.
  • Timings. Single reads ACKed in 95-149 ms, the three *#4*2## polls in 1.30-1.44 s, the two template writes in 68 / 89 ms; a template's echo reached the event session 35-50 ms after its ACK. No dimension 14 frame other than a read reply and no dimension 7 frame other than the two template echoes is in the capture; the *#4*2*60*40## at 20:10:22 UTC arrived with no request in either log.
  • Entity replay (base branch, pinned OWNd). Fed run 1's event frames, the climate entity shows 23.5, then 21.0 after the comfort echo and 18.0 after the eco echo, hvac_mode: heat throughout (the dimension 14 read replies do not move the shown setpoint, the mode frames 107 / 108 leave the mode alone, the dimension 7 heating context keeps heat); run 2's echo moves it to 23.5 at once. This is the behaviour fix(climate): show the setpoint in force (dimension 12), keep dimension 14 as the commanded value #791 merged, now pinned on the preset path.

How is it tested

  • pytest tests/test_f461_presets_live_2026_10_24_trace.py: 9 passed. Schema and synthetic identity, every frame parses in the pinned OWNd (with the zone state eco / comfort in the heating context and mode = None for 107 / 108), result rows consistent with their tx / rx rows (a template write has no reply and its echo arrived after the ACK), the comfort and eco facts above with their offsets (+1.1 / +13.3 / +47.8 s for dimension 12, +2.2 / +14.4 / +49.0 s for dimension 14), the "no realignment while a preset is active" statement over every pair read, the write echo and the poll of run 2, and two replays of the event frames through the climate entity as it is on the base branch (23.5 -> 21.0 -> 18.0 in heat; 18.0 -> 23.5 on the write echo).
  • pytest tests/test_trace_oracle_validation.py tests/test_device_health_corpus.py tests/test_fixture_privacy.py: 254 passed (tier 1 failed on *#4*2*#7*1*4## before the PHYSICAL_ONLY_TX_FRAMES entry: 1 failed, 253 passed).
  • Full suite against the PyPI-pinned OWNd behaviour (plain upstream OWNd master, f04d8aa, no fix PR applied): pytest tests/ -n 4 --cov=custom_components.myhome: 4533 passed, 1 skipped, 100 % statement coverage (16,080 / 16,080).
  • 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 (3 files, 0 with personal data): all pass.

Where are the traces

Subsystem Capture Plant Frames verified by this PR
Heating comfort from 23.5 tests/fixtures/traces/f461_presets_live_2026-10-24/myhome_trace_F461_presets_live_2026-10-24.json, run1_heating_comfort_then_heating_eco, step heating_comfort F461 2.0.11, KW4691 zone 2 *#4*2*#7*1*3## -> *#4*2*7*1*3##, *#4*2*12*0210*3##, *4*108*2##; *#4*2*12## -> *#4*2*12*0210*3##, *4*108*2##; *#4*2*14## -> *#4*2*14*0235*3## (+1 s, +13 s)
Heating eco same file, same run, step heating_eco same *#4*2*#7*1*4## -> *#4*2*7*1*4##, *#4*2*12*0180*3##, *4*107*2##; *#4*2*12## -> *#4*2*12*0180*3##, *4*107*2##; *#4*2*14## -> *#4*2*14*0235*3## (+1 s, +13 s, +48 s); *#4*2## -> 0, 12 = 0180, *4*107*2##, 14 = 0235, 13
Write while split same file, run2_home_assistant_write_realigns same *#4*2*#14*0235*3## (Home Assistant) -> *4*1*2##, *#4*2*12*0235*3##, *4*1*2##, *#4*2*0*0238##; *#4*2## -> 0, 12 = 0235, *4*1*2##, 14 = 0235, 13; *#4*2#1*#20*0##, *#4*2#1*20*0##
Cooling comfort and the comfort template from 21.0 (referenced, not duplicated) tests/fixtures/traces/f461_live_2026-10-24/, run4_preset_templates (#810) same plant, 19:02-19:10 UTC *#4*2*#7*1*3## -> *#4*2*12*0210*3## (unchanged); *#4*2*#7*2*3## -> *#4*2*7*2*3##, *#4*2*12*0250*3##, *4*208*2##

What does the Firmware Oracle / Encyclopedia say

  1. Firmware Oracle: the emulated gateways have no thermostat behind them, so no oracle row produces a dimension 12 / 14 pair or a dimension 7 echo; *#4*2##, *#4*2*12## and *#4*2*14## canonicalise to existing verdicts (tier 1 passes), while *#4*2*#7*1*4## has no stimulus and joins *#4*2*#7*1*3## / *#4*2*#7*2*3## in PHYSICAL_ONLY_TX_FRAMES with its live reply. The ACK timings (reads 95-149 ms, template writes 68-89 ms, *#4*2## 1.30-1.44 s) match the F461 rows of f461_live_2026-10-23 and f461_live_2026-10-24.
  2. OpenWebNet Encyclopedia (WHO 4 dimensions): dimension 7 is *#4*where*#7*[CONTEXT]*[STATE]## with context 1 heating / 2 cooling and state 3 comfort / 4 eco, so *#4*2*#7*1*3## is heating comfort and *#4*2*#7*1*4## heating eco; dimension 12 is the complete probe status with the setpoint in force, dimension 14 the commanded setpoint. The mode frames *4*107*2## / *4*108*2## that the KW4691 returns in the season frame's place while a preset is active are decoded by neither (heating: WHAT 107 / 108 / 208 (zone eco / comfort mode echoes of a KW4691 behind an F461) are not decoded OWNd#146 tracks them, now backed by eight occurrences in run 1 next to the *4*108*2## / *4*208*2## of f461_live_2026-10-24 run 4).

Checklist

  • PR Description: Follows the structured sections above (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).
  • Trace-Backed (if protocol/device change): The fixture is the physical trace itself; every test pins a frame of it.
  • V2 Architecture: N/A (fixture and tests only; the entity replays go through handle_event()).
  • Tests & Linters: pytest, ruff, and scripts/verify_ha_standards.py pass.

🤖 Generated with Claude Code

…ure (dimension 12 split from 14)

Follow-up asked for in the review of OpenWebNet-HA#810: from a 23.5 baseline on the
physical F461 2.0.11 + Living Now KW4691 (zone 2, heating season), the
dimension 7 templates *michnovka#4*2*michnovka#7*1*3## (heating comfort) and *michnovka#4*2*michnovka#7*1*4##
(heating eco), each followed at once by reads of dimension 12 and 14, a
*michnovka#4*2## poll and reads 48 s into eco, then Home Assistant's
climate.set_temperature 23.5 while the two dimensions differed
(2026-10-24 20:08-20:12 UTC; results posted on OpenWebNet-HA#791).

What the plant said: a heating preset moves dimension 12 (21.0, then 18.0)
and leaves dimension 14 at the last commanded value (23.5) for as long as
it was observed (48 s); the mode frame *4*108*2## / *4*107*2## takes the
season frame's place in the dimension 12 and *michnovka#4*2## replies; the write is
echoed as *4*1*2##, *michnovka#4*2*12*0235*3##, *4*1*2##, *michnovka#4*2*0*0238## and the
poll 7.4 s later reads 12 = 14 = 23.5. On the base branch the climate
entity shows 23.5 -> 21.0 -> 18.0 in heat and 23.5 after the write.

Archive tests/fixtures/traces/f461_presets_live_2026-10-24/ in the format
of f461_live_2026-10-24 (47 event-session frames, 122 rows, two runs, one
listener, probe rows aligned to the listener clock, t_estimated on the
command-session replies, events_after bounded by the ACK, synthetic MAC /
IP), its README, tests/test_f461_presets_live_2026_10_24_trace.py (9 tests)
and *michnovka#4*2*michnovka#7*1*4## in PHYSICAL_ONLY_TX_FRAMES (no oracle stimulus; tier 1
failed on it before). *4*107*2## / *4*108*2## parse with mode = None
(OpenWebNet-HA/OWNd#146).

Refs OpenWebNet-HA#791

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@GreenGrassBlueOcean GreenGrassBlueOcean left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clean follow-up capture on the physical F461 2.0.11 + KW4691 plant — this closes item 1 from #810 review 5639746797 cleanly. Archive schema, monotonic t / t_estimated / events_after invariants, UTC math, privacy checks (0 findings), PHYSICAL_ONLY_TX_FRAMES coverage, and the 8-section PR #778 template all check out.

Requesting one small test adjustment before merge so we don't create a cross-repo CI deadlock when OpenWebNet-HA/OWNd#146 lands:


Blocking: make WHAT 107 / 108 / 208 assertions forward-compatible with OpenWebNet-HA/OWNd#146

OpenWebNet-HA/OWNd's .github/workflows/myhome-conformance.yml (MyHOME test suite job) is a required CI check on every OWNd PR: it checks out OpenWebNet-HA/MyHOME (v2-phase1-architecture), installs the OWNd PR checkout in place of the pinned release, and runs pytest tests.

Right now, two trace tests hard-pin mode is None and human_readable_log == "Zone 2's mode is unknown.":

  1. tests/test_f461_presets_live_2026_10_24_trace.py lines 297–301 (this PR) for *4*107*2## / *4*108*2##.
  2. tests/test_f461_live_2026_10_24_trace.py lines 292–296 (merged in #810) for *4*108*2## / *4*208*2##.

As soon as an OWNd PR implements OpenWebNet-HA/OWNd#146 (decoding 107 / 108 as heating eco / comfort with mode == "heat", season == "heating" and 207 / 208 as cooling eco / comfort with mode == "cool", season == "conditioning"), OWNd's required MyHOME test suite gate will fail on both assertions before MyHOME can bump its OWNd== pin.

Please relax both locations to accept both pre-OWNd#146 (None) and post-OWNd#146 ("heat" / "cool" with matching season), following the dual-OWNd pattern in tests/test_message_edges.py:194,201 (see inline suggestion on tests/test_f461_presets_live_2026_10_24_trace.py, and apply the analogous (None, "heat") / (None, "cool") update to tests/test_f461_live_2026_10_24_trace.py:292-296).

(Note: I verified test_replay_presets_show_dimension_12_and_keep_heating at lines 445–472 against climate.py — MESSAGE_TYPE_MODE sets HVACMode.HEAT on CLIMATE_MODE_HEAT and only calls _show_nominal() when prev_mode == HVACMode.OFF, so the entity replay already stays green after OWNd#146; only the docstring note (mode = None) at line 449 would become historical.)


Minor / non-blocking

  • Rounding nit (+15.5 s vs +16 s): the *#4*2## zone poll in heating_eco (t = 53.394 vs t = 37.864, +15.53 s) is written as +15.5 s in README.md (lines 67, 82) and Hardware Verification, and rounded to +16 s in the Mermaid sequence diagram, capture.runs[0].purpose (JSON line 21), and tests/test_f461_presets_live_2026_10_24_trace.py docstring (line 24). Optional to align while touching the test file.
  • Once updated, please mark the PR Ready for review and we can merge right away.

Comment on lines +297 to +301
# the mode frames 107 / 108 parse but carry no mode the pinned OWNd knows (OpenWebNet-HA/OWNd#146)
for raw in (MODE_ECO, MODE_COMFORT):
msg = OWNMessage.parse(raw)
assert msg is not None and msg.zone == 2 and getattr(msg, "mode", None) is None
assert msg.human_readable_log == "Zone 2's mode is unknown."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accept both pinned OWNd <= 2.0.0b11 (mode is None) and OpenWebNet-HA/OWNd#146 (mode == "heat", season == "heating") so OWNd's myhome-conformance.yml gate stays green when OWNd#146 opens (please apply the matching (None, "heat") / (None, "cool") relaxation to tests/test_f461_live_2026_10_24_trace.py:292-296 in this PR as well):

Suggested change
# the mode frames 107 / 108 parse but carry no mode the pinned OWNd knows (OpenWebNet-HA/OWNd#146)
for raw in (MODE_ECO, MODE_COMFORT):
msg = OWNMessage.parse(raw)
assert msg is not None and msg.zone == 2 and getattr(msg, "mode", None) is None
assert msg.human_readable_log == "Zone 2's mode is unknown."
# WHAT 107 / 108: pinned OWNd <= 2.0.0b11 leaves mode = None; OpenWebNet-HA/OWNd#146 decodes them as heating eco / comfort.
for raw in (MODE_ECO, MODE_COMFORT):
msg = OWNMessage.parse(raw)
assert msg is not None and msg.zone == 2
assert getattr(msg, "mode", None) in (None, "heat")
assert getattr(msg, "season", None) in (None, "heating")
assert (getattr(msg, "mode", None) is None) == (
msg.human_readable_log == "Zone 2's mode is unknown."
)

…ide the pinned None

Review of OpenWebNet-HA#812 (5642383839): OWNd's required MyHOME conformance job runs
this suite against every OWNd PR, so the two trace tests that pinned
`mode is None` for *4*107*2##, *4*108*2## and *4*208*2## would fail the
moment OpenWebNet-HA/OWNd#146 decodes them (heating eco / comfort,
cooling comfort). Both locations (this PR's presets test and the merged
f461_live_2026-10-24 test) now accept None or the decoded mode / season,
with the "mode is unknown" log tied to the None case, as
tests/test_message_edges.py does for the two OWNd generations.

Rounding nit: the *michnovka#4*2## poll 15.53 s into eco is written +15.5 s
everywhere (test docstring, archive purpose), as in the README.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@gdluck
gdluck marked this pull request as ready for review October 25, 2026 09:56
@gdluck

gdluck commented Oct 25, 2026

Copy link
Copy Markdown
Author

Done in 5ff109d and marked ready for review.

  1. Forward-compatible WHAT 107 / 108 / 208 assertions: both locations relaxed as you suggested, this PR's tests/test_f461_presets_live_2026_10_24_trace.py (107 / 108: mode in (None, "heat"), season in (None, "heating")) and the merged tests/test_f461_live_2026_10_24_trace.py (108 → heat / heating, 208 → cool / conditioning). One difference from the suggestion: the "Zone 2's mode is unknown." log is asserted only when mode is None rather than as a two-way equality, so an OWnd that decodes the mode but keeps that log string would not fail the gate either. The replay test stays as it is; its docstring now says mode = None is the pinned behaviour.
  2. Rounding: the poll 15.53 s into eco reads +15.5 s in the test docstring, the archive purpose and the sequence diagram, as in the README.

pytest tests/test_f461_presets_live_2026_10_24_trace.py tests/test_f461_live_2026_10_24_trace.py: 23 passed; anonymize_plant_fixture.py --check 0 findings; ruff clean.

@GreenGrassBlueOcean GreenGrassBlueOcean left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — thanks for the quick turnaround! Both trace tests (test_f461_presets_live_2026_10_24_trace.py and test_f461_live_2026_10_24_trace.py) now keep OWNd's myhome-conformance.yml gate green across both pinned OWNd and OpenWebNet-HA/OWNd#146, and the +15.5 s rounding is aligned throughout.

@GreenGrassBlueOcean
GreenGrassBlueOcean merged commit 089fef5 into OpenWebNet-HA:v2-phase1-architecture Oct 25, 2026
16 checks passed
GreenGrassBlueOcean pushed a commit that referenced this pull request Oct 26, 2026
…ixtures hold (#799, #810, #815 follow-up)

Read against the fixture rows rather than the PR texts:

- f461_live_2026-10-23 README: run 1 is 165 read-only requests in total
  (134 mirrored from the oracle suites plus 31 plant reads), not 165 plus 31;
  the setpoint write `*#4*2*#14*0235*3##` is followed by dimension 12 at
  once and no dimension 14 is pushed: the "dimension 14 catches up 0.3 s
  later" was the 12 -> 14 gap inside the reply to the probe's own `*#4*2##`
  2.8 s later. test_setpoint_write_mode_3_restores_the_setpoint_in_force
  asserted only evt.index(12) < evt.index(14), which the poll reply order
  satisfies by itself; it now asserts that no dimension 14 follows the write
  before the next request, and its docstring matches.
- test_replay_run4b_zone_2_through_the_climate_entity said "valve off" for a
  run without any dimension 19 / 20 frame and never asserted the commanded
  setpoint: the docstring drops the valve, the body asserts
  _target_temperature == 23.5.
- myhomeserver1_live_2026-10-24 README: 33 zones report a temperature (zone
  43 has an actuator but no dimension 0), 34 answer the actuator request; the
  all-zone actuator test's docstring counts the 43 frames its body asserts
  (44 only with the earlier zone 35 reply).
- test_trace_oracle_validation note for `*#4*0*60##`: the MyHomeServer1 ACK
  came at 0.50 s with 8 replies; the 17th zone answered by 0.97 s.
- test_replay_knob_turn_shows_dimension_12 (#810) claimed "dimension 14
  changes nothing" on a run whose every dimension 14 frame carries the
  dimension 12 value, 18.0; the values cannot tell the two apart, so the test
  asserts the dimension 12 hold flag, which only a dimension 12 report sets,
  and says where the discriminating replay is (#812).
- test_replay_action_sequence_matches_the_recorded_entity_states (#815)
  compared the replay and the record with two separate literals; it now
  compares the recorded actions with the replay's first changes and says
  the trailing idle was read back, not recorded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@gdluck

gdluck commented Oct 26, 2026

Copy link
Copy Markdown
Author

Record note from the WHO 4 PDF audit of 2026-10-26 (no change requested): the dimension 7 preset templates (*#4*2*7*1*3##, *#4*2*7*2*3##) and the WHAT 107 / 108 / 208 frames this capture ingests are not in the Legrand WHO 4 document (its dimension table p. 7 stops at 0 / 11..14 / 19 / 20 / 22 / 30, WHATs are listed on p. 5); the Encyclopedia records them from captures, and OWNd#146 tracks the decoder. Firmware-observed on the F461 2.0.11; the document is silent, not contradicted.

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.

3 participants