Repository navigation
fix(heating,gateway): address review follow-ups on #116 (MH201 in device type 200, dead _is_active assignment, fixture comments) - #119
Conversation
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
fedem95
left a comment
There was a problem hiding this comment.
Thanks for picking these up. Tested 6869de1: 1354 passed locally (test_metadata deselected, local env), CI green. The fan-branch _is_active = True removals don't change behaviour, since the final bool(...) already covers cooling_fan_on/fan_on, and the nine dimension 19 cases in test_f461_live_plant.py still pass. Approving.
One nit on the new comment, non-blocking: model 10 comes from my MH201 on 3.6.27 only; I haven't seen a *#1013 reply from a 3.3.6. And the other gateways in the traces were asked *#1013*0*1##, not *#1013**1##, so "*#1013**1## tells them apart" is only shown for the MH201 so far. Maybe: "WHO 1013 dimension 1 tells them apart (the MH201 on 3.6.27 answers only *#1013**1##, model 10)".
(The README also gains the missing door_entry.py coverage row, which isn't in the summary.)
|
Thanks @fedem95! Addressed both points in
|
074dca3 to
7635b9f
Compare
…ice type 200, dead _is_active assignment, fixture comments)
…and WHO 13 comments
7635b9f to
13dc38f
Compare
Related: #116 (review 5538969896), #119, #97, #117, OpenWebNet-HA/MyHOME#370, OpenWebNet-HA/MyHOME#466, and OpenWebNet-HA/MyHOME#714.
What is the problem?
Following the merge of #116 (
fix(heating,gateway): dimension 19 is_active, plain protection form and device type 200 from a live F461 capture) and #97 (feat/who4-consolidated-heating), post-merge review by @fedem95 (review 5538969896) and follow-up review on this PR (review 5540201753) plus themastermerge of#97identified five items:200omittedMH201:OWNd/message/gateway.pymapped*#13**15*200##to"F454 / MyHomeServer1 / MH202 / F461 / H4890"and described it as"shared by every Linux-based gateway generation". However, physicalMH201gateways (which are catalogued in the firmware oracle on030644as a bare-metal image rather than one of the Linux gateways emulated by QEMU) also reply*#13**15*200##on firmware3.3.6and3.6.27. Furthermore, onMH201(fw3.6.27), WHO 1013 dimension 1 only distinguishes the model when queried with an emptyWHERE(*#1013**1##→*#1013**1*10*15*0*5##, model10), whereas*#1013*0*1##is NACKed and no unsolicited WHO 1013 frame is pushed after the200reply.self._is_activeassignments in WHO 4 Dimension 19 (OWNd/message/heating.py):After #116 consolidated
self._is_active = bool(self._is_cooling or self._is_heating or self._cooling_fan_on or self._fan_on)at the end of the dimension 19 block, the initialself._is_active = self._is_cooling | self._is_heatingassignment and the twoself._is_active = Trueassignments inside the cooling/heating fan-speed branches were unconditionally overwritten and redundant.OWNd/message/heating.pyandtests/test_f461_live_plant.py:Two comments in
OWNd/message/heating.pystill referencedtests/fixtures/f461_live_2026-10-15/(removed inca0519ewhen the F461 frames were inlined intotests/test_f461_live_plant.py) and the legacyoracle3/out/termo_f461.tsvpath (now superseded by the canonicalthermo-zone-mode.tsv,ownd-pr82-heating.tsv, andthermo-ts10.tsvsuites inown-firmware-oracle), and the module docstring intests/test_f461_live_plant.pydid not yet listMH201under device type200.OWNd/message/door_entry.pyrow inREADME.mdandscripts/sync_documentation.py:The coverage table in
README.mdandCOMPONENT_NOTESinscripts/sync_documentation.pywere missing an entry forOWNd/message/door_entry.py(WHO 6 & WHO 8).#116and PR#97on WHO 4 bare WHAT0/1season frames (tests/test_f461_live_plant.py):PR
#97(6af9377) aligned bare*4*0*Z##/*4*1*Z##frames with the Legrand WHO 4 specification (season == "conditioning"/"heating",message_type == "hvac_season",mode is None), causingtest_season_frames_and_area_zero_lights_parse_as_before(added in#116asserting.mode == "heat"/"cool") to fail onpull_requestmerge commits againstmaster.How is it solved?
MH201in WHO 13 code200and document firmware oracle provenance (OWNd/message/gateway.py):self._device_typefor WHO 13 dimension 15 code200to"F454 / MyHomeServer1 / MH202 / F461 / H4890 / MH201".200is shared across modern gateways (F454,MyHomeServer1,MH202,F461,H4890; plus emulatedF450/F459/F460intrace-corpus.tsv) andMH201(fw3.3.6,3.6.27; catalogued on030644outside the Linux QEMU fleet), and thatWHO 1013 dimension 1 tells them apart (the MH201 on 3.6.27 answers only *#1013**1##, model 10, and NACKs *#1013*0*1##).tests/test_profiles.pyandtests/test_f461_live_plant.py.self._is_activeassignments (OWNd/message/heating.py):self._is_active = self._is_cooling | self._is_heatingassignment and the two redundantself._is_active = Trueassignments in the cooling and heating fan-coil branches, leaving the single authoritativebool(self._is_cooling or self._is_heating or self._cooling_fan_on or self._fan_on)computation after both sides are parsed.OWNd/message/heating.py,tests/test_f461_live_plant.py):tests/test_f461_live_plant.py.oracle3/out/termo_f461.tsvcomment inOWNHeatingCommand.set_modewith exactown-firmware-oraclesuite references (thermo-zone-mode.tsv,ownd-pr82-heating.tsv, andthermo-ts10.tsv) and SCS bus telegrams (D1 00 03 02 C2 ZZ 00 00for311,93 ZZ 30 04/93 ZZ 30 0Ffor plain zone302/303, andD1 00 03 02 C2 ZZ 07 00for#Zcentral-unit302).door_entry.pydocumentation (README.md,scripts/sync_documentation.py):"OWNd/message/door_entry.py": "WHO 6 & WHO 8: Door entry, electric lock, and video intercom events/commands"toCOMPONENT_NOTESinscripts/sync_documentation.pyand added the corresponding 100% coverage row toREADME.md.master(6af9377) and align F461 season assertion (tests/test_f461_live_plant.py):test_season_frames_and_area_zero_lights_parse_as_beforeto assertOWNEvent.parse("*4*1*2##").season == "heating" and OWNEvent.parse("*4*0*2##").season == "conditioning".How is it tested?
tests/test_f461_live_plant.py: All 17 F461 live-plant tests pass, including all 9 WHO 4 dimension 19 actuator/fan-coil combinations (5*1,5*0,8*0,1*5,5*5,0*6,0*1,1*0,0*0),test_device_type_200_is_not_a_single_model(asserting"MH201" in msg.device_type), andtest_season_frames_and_area_zero_lights_parse_as_before.tests/test_profiles.py:test_owngateway_event_propertiesverifiesOWNGatewayEvent("*#13**15*200##").device_type == "F454 / MyHomeServer1 / MH202 / F461 / H4890 / MH201"anddevice_type_code == "200".pytest:1,488 passed, 1 skippedon rebasedmaster.4,808 / 4,808statements across all 25 modules verified byscripts/verify_coverage.py).ruff check,mypy,scripts/verify_library_standards.py, andscripts/sync_documentation.py --check: 0 violations.Where are the traces (real and firmware oracle)?
Real Hardware Traces:
2.0.11, captured 2026-10-15):OWNd:tests/test_f461_live_plant.py(GATEWAY_FRAMES,ACKED_FRAMES,NACKED_FRAMES,EVENTS_AFTER), including*#13**15*200##followed by*#1013**1*134*15*5*0##, WHO 4 dimension 19 frames (*#4*2*19*5*1##,*#4*2*19*5*0##,*#4*2*19*8*0##), season frames (*4*1*2##,*4*0*2##), and standalone protection mode transitions (*4*302*2##→*4*202*2##).MyHOMEtrace corpus attests/fixtures/traces/f461_live_2026-10-15/(OpenWebNet-HA/MyHOME#714).3.6.27and3.3.6):3.6.27(captured 2026-10-14 by @fedem95): Reports*#13**15*200##, NACKs*#1013*0*1##, and answers*#1013**1##with*#1013**1*10*15*0*5##(model10); plant fixture archived inOpenWebNet-HA/MyHOMEattests/fixtures/plants/mh201_physical_plant/.3.3.6: Reports*#13**15*200##inOpenWebNet-HA/MyHOMEattests/fixtures/traces/issue_466/myhome_sweep_MH201_all_2026-09-25T19-11-35.json(OpenWebNet-HA/MyHOME#466).OpenWebNet-HA/MyHOMEissues #370 and #466 and catalogued intests/golden/frames/who13_gateway.yaml.Firmware Oracle Traces & Disassembly (
OpenWebNet-HA/own-firmware-oracle, synced intests/golden/firmware_oracle.json,tests/oracle/who4_facts.json, & #117):*#13**15##) & WHO 1013 Dimension 1 (*#1013*0*1##) (trace-corpussuite,results/<PRODUCT>/<VERSION>/oracle/full/trace-corpus.tsv):F450020010,F453AV030014,F454020051,F459020105,F460020012,F461020011,H4684020054,MH200020102,MH200N010108,MH202010024,MyHomeServer1028206):F450,F454,F459,F460,F461,MH202, andMyHomeServer1all reply*#13**15*200##(whileH4684replies*#13**15*13##,MH200replies*#13**15*4##, andF453AV/MH200Nreply*#13**15*0##).MH201(030644, SHA-2568972720b01d1...) is catalogued inresults/mcp_index.json(status: "catalogued"), not among the Linux QEMU-emulated targets.*#1013*0*1##withACK(H4684emits*#1013**1*19##,MH200emits*#1013**1*4##, and the unprovisioned Linux images emit*#1013**1*0*0*0*0##whenAS_ITEM_SYSTEMis unpopulated in the clean QEMU rootfs), whereas on physical hardwareMH201(fw3.6.27) NACKs*#1013*0*1##and answers only*#1013**1##(*#1013**1*10*15*0*5##).ownd-pr82-heating,thermo-zone-mode,thermo-central-mode,thermo-ts10suites):311): Plain*4*311*1##and*4*311*99##are NACKed by all 11 emulated gateways with zero bus frames emitted, whereas#Z(*4*311*#1##,*4*311*#99##,*4*311*#23#1##) is translated and dispatched onto the SCS bus (24 30 36 44 31 30 30 30 33 30 32 43 32 30 31 30 30 30 30 0d→D1 00 03 02 C2 01 00 00).302/102/202/303): Emulatedbt_termotranslates plain zone commands into direct 4-byte SCS zone telegrams (e.g.,*4*302*23##→93 17 30 04;*4*303*1##→24 30 34 39 33 30 31 33 30 30 46 0d/93 01 30 0Finthermo-zone-mode.tsv), whereas#Zcommands (*4*302*#23##,*4*302*#23#1##,*4*102*#0##,*4*202*#0##) are translated into extendedD1central-unit frames (D1 00 03 02 C2 17 07 00/24 30 36 44 31 30 31 30 33 30 32 43 32 31 37 30 37 30 30 0dinthermo-ts10.tsv).thermo-valvesuite &tests/oracle/who4_facts.json):*#4*1*19##is replayed inresults/<PRODUCT>/<VERSION>/oracle/full/thermo-valve.tsv(no virtual fan-coil/valve actuator is attached on the emulated bus to emit*#4*Z*19*COOL*HEAT##responses, so the 9 actuator/fan-coil combinations are verified via the live F461 capture intests/test_f461_live_plant.py), andtests/oracle/who4_facts.json(1,745 decoded firmware facts) verifies the WHO 4 season contract (*4*0*Z##/*4*1*Z##).