Repository navigation
fix(heating): correct season status, holiday programs, and CU diagnostics (#87, #88, #89, #94) - #97
Conversation
…nWebNet-HA#87, OpenWebNet-HA#88, OpenWebNet-HA#89, OpenWebNet-HA#94) Consolidate the four domain-focused WHO 4 heating improvements into a single cohesive branch: 1. WHAT 1 / 0 decoded as season (MESSAGE_TYPE_SEASON: hvac_season) with typed .season attribute (heating / conditioning), leaving .mode as None so season updates do not flip active AUTO/manual operating modes (OWNd#94). 2. WHAT 115#/215#/315# parameter read as weekly program (1..16), not negative temperature, exposing .program and .scenario properties on OWNHeatingEvent (OWNd#87). 3. WHAT 13xxx (heating) and 23xxx (conditioning) holiday days assigned to respective seasonal modes rather than generic auto, exposing .holiday_days (OWNd#88). 4. WHATs 22, 23, 24, 30, and 31 recognized as central unit system status frames with descriptive telemetry logs, leaving mode as None (OWNd#89). Co-authored-by: gdluck <9041273+gdluck@users.noreply.github.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…rogram 13DDD#P, 23DDD#P and 33DDD#P (what set_central_holiday sends) carry the weekly program the plant resumes after the holiday, like 115#P. Only 115/215/315 were handled, so 13005#1102 still decoded as a -10.2 degree setpoint and the other two came back as hvac_mode_target with no temperature. They now give program=P, set_temperature=None and message_type hvac_mode. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… vacation frames The Encyclopedia WHO 4 vacation forms use 3101..3103 for 13DDD / 23DDD / 33DDD, so cover 13005#3102 and 23005#3102 (both used to read as -10.2 degrees). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
@gdluck I'm not approving this yet. We keep this as one PR, so it needs the evidence and changes below before it can merge. The firmware replays and most of the cited evidence come from your oracle work, so I'm asking you for them. Checked against current DoneMulti-day vacation frames with a program were still read as a setpoint. The spec forms are OWNd suite: 1272 passed, ruff clean. Requested from you, @gdluckTraces, for the claims nothing I can reach confirms:
Code and description changes:
Merge conditionThe season change is the only one that alters behaviour for consumers: after it, WHAT 1/0 no longer produce a mode. A MyHOME checkout without MyHOME#657 fails 11 tests with this OWNd. Because this stays one PR, the release carrying it must ship together with #657, and items 1 to 4 should be resolved before merge. Verified
|
Update: what the existing traces show, and what is still missingI went through the trace fixtures already in OpenWebNet-HA/MyHOME Item 1, WHAT 1 / 0 is the season: covered by three plantsIn my review I wrote that no capture shows a zone whose mode is not implied by the season. Three captures do:
The same slot after dim 12 also shows what the frame really is. When the zone is not running it holds Still missing for item 1: case (b) from my review, a season frame that contradicts the reported mode. That is a plant switching season while the central reports a zone in program or manual of the other season ( Item 5, central-unit status WHATs: coveredReal frames exist on three plants:
22, 23 and 24 go through the new central-status branch. 21 goes through the existing remote-control branch. Item 2, firmware replays: we do this ourselvesNone of the oracle checkouts contains the replays quoted in the description ( Item 4,
|
…perature Neither the Legrand WHO 4 specification nor any capture has a WHAT 0 or 1 with a parameter: the only setpoint write is *OpenWebNet-HA#4*#Z*OpenWebNet-HA#14*T*M##, and no trace in OpenWebNet-HA/MyHOME tests/fixtures/traces contains *4*0#... or *4*1#.... ee6a538 parsed them as heat / cool with a target temperature, which contradicts reading bare WHAT 0 / 1 as the season. They now fall through to the unknown branch: no mode, no season, no message type, no setpoint. Review item 4 on OpenWebNet-HA#97. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…R #97) Add the thermo-holiday-program suite and run it on all ten emulated gateways, each with the reset policy of its committed thermo-ts10 run. It holds the frames OpenWebNet-HA/OWNd#97 quotes as replayed (review item 2), plus their neighbours so differences can be read from the bytes: every return program of 115# / 215# / 315#, day counts 1, 5 and 255, the seasonal program in the multi-day form, holiday WHATs without a program, and two setpoint writes for comparison. What the bus shows (MyHomeServer1, MH200N, MH202, F453AV, F454, F459, H4684 agree; F461 NACKs but still emits the same telegram; F460 NACKs; F450 crashes as in its other suites): - 115#110P / 215#210P / 315#310P -> C1 14/24/04 (P-1) 00: a program index, no temperature byte. A setpoint write gives C1 12 2A (21.0 C). - 13DDD#PPPP / 23DDD / 33DDD -> C1 15/25/05 DDD (PP-1): day count, then program. 13005#3102 and 13005#1102 give the same bytes, so the translator only reads the last two digits (OWNd's % 100). - 13005 and 33005 without a program are NACKed; 115 without one is ACKed as program 1. - *4*1*23## / *4*0*23## go to the bus on every gateway; F454 and MH202 NACK them anyway. Regenerate results/mcp_index.json (412 inputs) and the README metrics. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…irmware 3.0.20 The 99-zone thermo central's firmware ships inside the TiThermo 2.0 download on bticino.be (same vendor pages as MH200N and H4684): Version 2_0.zip -> 3550_030020.fwz (ZipCrypto, password = model) -> 3550_030020.mot, Motorola S-records for a Mitsubishi M16C. It is the only first-hand source for what a central reports while a holiday or vacation runs (OpenWebNet-HA/OWNd#97, review item 3). - catalog/3550/030020.yaml, modelled on H4684: wrapper + inner .fwz hashes, "$PRODUCT" password, the bundled TiThermo20.EXE acknowledged in undecoded_ok. No manifest is committed: oracle.yml builds it in Actions once this is on main, and reproduce.yml re-checks it weekly. - sync_readme: 3550 as auxiliary, non-Linux hardware with its own fleet row; thermostats (H4691/LN4691/KM4691) and 4-zone centrals (L4600/4, N4600/4) added to Excluded Hardware, since no firmware for them is published. - findings/3550/README.md: provenance and the static facts verified so far (memory map, vector tables, bus line templates, holiday menus). - results/mcp_index.json and README regenerated (14 catalogued gateways). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
I've made the traces as much as possible. The holiday function works as expected. I also set the central unit to "Antifreeze" and "Off." Heating/Cooling: As you can see, I set one zone from "Heat" to "Cool" in the APP from Freedompro. The central unit switched immediately from "Winter" to "Summer." The same goes for switching from "Summer" to "Winter." But the central unit leaves the actual program and switch to “Antifreeze”.Good luck. I'm interested to see how it goes. Best regards, NorbertAm 10.10.2026 um 00:28 schrieb GreenGrassBlueOcean ***@***.***>:GreenGrassBlueOcean left a comment (OpenWebNet-HA/OWNd#97)
Update: what the existing traces show, and what is still missing
I went through the trace fixtures already in OpenWebNet-HA/MyHOME v2-phase1-architecture (tests/fixtures/traces/) against the open items in my review above. Two of the five items are covered by traces we already have. Two we can close ourselves. One needs a new capture from the community.
Item 1, WHAT 1 / 0 is the season: covered by three plants
In my review I wrote that no capture shows a zone whose mode is not implied by the season. Three captures do:
F453AV, firmware 3.0.14 (issue_619/myhome_sweep_F453AV_all_2026-10-04T19-45-11.json, @nce2704). In one status burst, zone 4 sends dim 12 and *4*1*4##. 0.6 s later the central reports *4*111*#4## (weekly program, heating) for the same zone. Zone 7 does the same (*4*1*7##, then *4*111*#7##). The plant reports "heating" and "programmed" for one zone at the same time, so WHAT 1 cannot be the manual-heating mode.
F454 2.0 with MyHomeServer1 running the program (issue_429/xtimmy86x_capture.24092026.00-13.txt, @xtimmy86x). A 13 h passive trace with all seven zones in automatic. At the 06:00 and 09:00 schedule steps, every zone sends *4*1*Z## next to its new dim 12, and nothing comes from Home Assistant. On master, every schedule step switches all seven zones to manual heat.
MyHomeServer1 2.87.13, Home+Control (issue_429/myhome_trace_MyHomeServer1_who4_2026-09-23T22-45-26.json, @TheDarkWizard). The 22:45 schedule step to "Summer ECO" sends *4*0*Z## on zones 1-3. The manual 20 °C write at 22:37 sends the same *4*0*2##, so the frame does not depend on manual versus programmed operation.
The same slot after dim 12 also shows what the frame really is. When the zone is not running it holds *4*303*Z## (OFF: F453AV zones 5 and 6), *4*102*Z## (antifreeze) or *4*202*Z## (thermal protection: OpenWebNet-HA/MyHOME#429 restart trace, OpenWebNet-HA/MyHOME#453 H4890 trace). So the zone reports its operating state, 0/1 meaning "running in conditioning/heating". That fits the "zone operation mode acquire frame" reading in this PR. 303, 102 and 202 must keep setting the mode, and they do.
Still missing for item 1: case (b) from my review, a season frame that contradicts the reported mode. That is a plant switching season while the central reports a zone in program or manual of the other season (*4*0*Z## after *4*111*#Z##, or *4*1*Z## after *4*210*#Z##). I no longer consider this blocking, but it would close the question.
Item 5, central-unit status WHATs: covered
Real frames exist on three plants:
*4*22*#0## and *4*24*#0##: F454 with a 99-zone central (issue_629/myhome_trace_F454_all_2026-10-05T11-14-00.json, @ricdijk)
*4*24*#0##: MH200N (issue_466/myhome_sweep_MH200N_all_2026-09-25T14-40-10.json)
*4*23*#0##, plus *4*21*#0## and *4*202*#0##: MyHomeServer1 + H4890 (issue_453/, @nicolacavallo84)
22, 23 and 24 go through the new central-status branch. 21 goes through the existing remote-control branch.
Item 2, firmware replays: we do this ourselves
None of the oracle checkouts contains the replays quoted in the description (115#1102, 215#2102, 13005#3102, 23005#3102, 33005#3102, *4*1*23##, *4*0*23##). I'll add them as cases to own-firmware-oracle and regenerate the index. @gdluck, if you already have these results stored somewhere, a pointer saves the rerun.
Item 4, *4*1#T / *4*0#T: remove
No trace has these frames, and the Encyclopedia has no such form. Its only setpoint write is *#4*#Z*#14*T*M##. Unless someone has a capture, I'll remove the handling and its test (added in 0f62c22, again in ee6a538).
Item 3, holiday and vacation reports: needs a new capture
No trace in the repository contains a single 115#, 215#, 13DDD, 23DDD or 33DDD frame. We still can't tell what a plant reports while a holiday or vacation runs. Does the report carry #P? Does DDD count down? Is the ordinal after 115#/215# the form the command used? That decides whether program and holiday_days mean what the properties say.
This needs a plant with a central unit. You three have one on the bus:
@nicolacavallo84: 3550 central unit, MyHomeServer1 + H4890 (OpenWebNet-HA/MyHOME#453)
@ricdijk: F454 with a 99-zone central (OpenWebNet-HA/MyHOME#629)
@nce2704: F453AV, central reporting *4*111*#Z## (OpenWebNet-HA/MyHOME#619)
If you can, please:
Start a capture on the MyHOME card (all WHO, or the WHO 4 filter).
On the central unit (or the MyHOME app), set a vacation of a few days, choosing the weekly program to return to. Leave it running for a minute.
Do the same with a daily holiday (holiday plan), if your central offers it.
Send *#4*#0## and *#4*#Z## for one zone while it runs, and again after cancelling.
If the vacation can stay active past midnight, a second capture the next day shows whether the day count drops.
Attach the export and tell us the gateway model and firmware, which program you selected, and how many days.
@nce2704, your plant is also the best one for the missing item 1 case: leave the monitor running while you switch the plant between heating and cooling with zones in program, and poll *#4*#Z## before and after.
Status
Items 1 and 5 are covered by existing traces. Items 2 and 4 are work on our side. Only item 3 waits on a community capture. The merge condition is unchanged: the release carrying this ships together with OpenWebNet-HA/MyHOME#657.
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
Hi @nce2704, Thank you very much for capturing this! Your observations about switching between heating and cooling (where the central unit switches seasons globally and drops into Antifreeze) provide fantastic real-world confirmation of the mode-decoupling behavior. One note: when replying by email, GitHub automatically strips attachments, so the trace files did not come through to the comment. Could you drag and drop the Thank you again for your help! |
|
Hi, thanks! Here are the trace files from my BTicino installation. They are attached directly to this comment. myhome_trace_F453AV_who4_2026-10-11T11-13-06 Antifreeze ON.json |
OpenWebNet-HA#97) Frames from the captures @nce2704 attached to OWNd#97 (holiday ON/expiry, heat->cool season switch, antifreeze, central OFF, weekly-program baseline).
Status after the F453AV captures (@nce2704, thank you)I replayed all six attached captures (F453AV, central unit #0) through this branch. Every WHO 4 status frame decodes as intended, so no parser change was needed. The frames are now pinned in Now confirmed by real traces
Still needed
|
|
@ricdijk, your 99-zone central (F454, FW 1.0.34) from OpenWebNet-HA/MyHOME#697 could close two of the items above. Only if you have the time and the owner agrees to press the buttons: 1. Multi-day vacation (item 3, the one we need most). We only have the daily holiday (
We want any 2. Item 1, case (b). Put one zone in manual and another in its programme, then switch the season on the central panel. Does How to capture: Contributing. You already read the source and tested a patch on your plant, so you're very welcome to turn the trace into a test yourself: a PR with the frames pinned in a test (like |
|
Thanks for the clear list, and for splitting the questions out.I can't do either capture right now, and I won't be able to do anything at all before this weekend. Nobody is at the house for the next days, and I can't operate the central panel or the app myself: I only have access through Home Assistant. The owner has to press the buttons, and I can follow along on the bus.From the weekend on I will look at it, and try both together with the owner if that works out. I will post a trace for each part with a note on which step it belongs to. Since it depends on the owner, I can't give a date for the captures yet.Two things from my side:- For the season-switch test (item 1, case b): in my 20:07 trace in MyHOME#697 every zone was following the central. I will check first which zones are in manual and which in their programme, so the test can show something different.- I'm happy to turn the traces into a test myself, or to attach them here. Tell me which you prefer.I can test things from the Home Assistant side in the meantime, if a Home Assistant-only check would help.Verstuurd vanaf mijn iPhoneOp 12 okt 2026 om 23:46 heeft GreenGrassBlueOcean ***@***.***> het volgende geschreven:GreenGrassBlueOcean left a comment (OpenWebNet-HA/OWNd#97)
@ricdijk, your 99-zone central (F454, FW 1.0.34) from OpenWebNet-HA/MyHOME#697 could close two of the items above. Only if you have the time and the owner agrees to press the buttons:
1. Multi-day vacation (item 3, the one we need most). We only have the daily holiday (115#). Please capture the bus while you:
Start a vacation ("vacanze") for 2 days from the central, the MyHome/Home + Control app or MyHOME_Suite. Note which one you used.
Wait a minute, then (if you can) leave it running past midnight, so we see whether DDD counts down.
Cancel the vacation.
We want any *4*13DDD…, *4*23DDD…, *4*33DDD… and *4*3000… frames, and whether a #P program number follows.
2. Item 1, case (b). Put one zone in manual and another in its programme, then switch the season on the central panel. Does *4*0*Z## or *4*1*Z## appear for those zones, or only the central frames and *4*202*Z## / *4*102*Z##? Your 20:07 trace in MyHOME#697 shows the latter for zones that were following the central.
How to capture: custom:myhome-bus-card → "Export Trace", or Settings → Devices & Services → MyHOME → Download diagnostics. Please say which step each part belongs to. Bus frames hold only numeric codes; scripts/anonymize_plant_fixture.py in OpenWebNet-HA/MyHOME strips the rest.
Contributing. You already read the source and tested a patch on your plant, so you're very welcome to turn the trace into a test yourself: a PR with the frames pinned in a test (like tests/test_who4_f453av_traces.py on this branch) is the most useful form. If you'd rather not, just attach the trace here and we'll add it. Either way, thank you.
—Reply to this email directly, view it on GitHub, or unsubscribe.Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
|
Thanks @ricdijk, and no pressure on the timing; it depends on the owner, so whenever it works out.
The central unit's 102 / 202 frames from your plant are also in OpenWebNet-HA/MyHOME#699. |
… firmware contracts
Item 3 Resolved: Binary Disassembly of Gateway (
|
fedem95
left a comment
There was a problem hiding this comment.
Approved
The WHO 4 parsing changes are now backed by real gateway traces, firmware replays, and regression tests. The MyHOME compatibility change is merged, and all checks pass.
Note: Multi-day vacation status and countdown are validated through firmware disassembly and a synthetic trace fixture, rather than a live plant capture.
6af9377
into
OpenWebNet-HA:master
Consolidated WHO 4 Thermoregulation & Climate Fixes
This pull request consolidates four domain-focused WHO 4 heating/thermoregulation fixes (originally submitted in #87, #88, #89, and #94) into a single, cohesive, firmware-validated PR for the next OWNd release.
1. What is the issue?
Prior to this PR, OWNd had four distinct protocol parsing defects in WHO 4 (Thermoregulation):
Conflation of HVAC Season with Operating Mode (
WHAT 1 / 0) — fix(heating): decode WHAT 1 / 0 as the season, not an operating mode #94:*4*1*Z##and*4*0*Z##were parsed as operating modesmode = "heat"andmode = "cool"withmessage_type = "hvac_mode".1("heating mode") and0("conditioning mode") are zone operation mode acquire frames indicating the active season (winter/summer). Gateways broadcast them next to temperature/setpoint reports.auto), receiving a season status frame from the gateway flippedmodeto manual\"heat\"or\"cool\", breaking the climate entity's schedule state. Consumers had no way to inspect season without reading the private_what.Holiday Plan Program Parameter Misparsed as Negative Temperature (
WHAT 115# / 215# / 315#) — fix(heating): read the 115#/215#/315# parameter as a program, not a temperature #87:*4*115#1102*#0##, the parameter1102specifies the weekly program index (program 2) to resume following holiday operation.who4_temperature("1102"). Under BTicino's 4-digit signed temperature format (values1102was decoded as-10.2 °C, settingset_temperature = -10.2andmessage_type = "hvac_mode_target".Heating & Cooling Holiday Days Misclassified as Generic AUTO (
WHAT 13xxx / 23xxx) — fix(heating): 13xxx and 23xxx are holiday days in heating / conditioning mode #88:13001..13255(holiday days in heating mode) and23001..23255(holiday days in conditioning mode) were grouped with generic33xxxand parsed asCLIMATE_MODE_AUTO.xxx= 1..255 days) was completely discarded.Central Unit Diagnostic Telemetry Logged as Unknown (
WHAT 22, 23, 24, 30, 31) — fix(heating): name the central unit status WHATs 22, 23, 24, 30 and 31 #89:*4*22*#0##probe OFF,23probe in antifreeze,24probe in manual,30failure discovered,31battery KO) fell through to the unhandled fallback.\"Zone #0's mode is unknown\") flooded the logs, obscuring real central unit hardware alarms.2. How is it fixed?
The changes in
OWNd/message/heating.pyandOWNd/message/__init__.pyaddress each defect cleanly without breaking existing consumers:Decouple Season from Operating Mode:
MESSAGE_TYPE_SEASON = "hvac_season",SEASON_HEATING = "heating", andSEASON_CONDITIONING = "conditioning".OWNHeatingEvent.season -> str | None.0or1without parameters: parsed asmessage_type = MESSAGE_TYPE_SEASON,season = "heating" | "conditioning", leavingmode = None. This prevents season frames from overriding active manual/auto/off states.0or1with a parameter (*4*1#0215*1##,*4*0#0215*1##) is in neither the specification nor any capture (the only setpoint write is*#4*#Z*#14*T*M##), so it is parsed as an unknown WHAT:mode = None,season = None,message_type = None,set_temperature = None(43526a6). Unrecognized WHATs leaveseason = Noneandmessage_type = None..seasonstrictly within its validated branch (1xx/11xx/12xx/13xxx->heating,2xx/21xx/22xx/23xxx->conditioning, generic3xx->None).Parse Holiday Plan and Vacation Parameters as Program Number:
WHAT in (115, 215, 315)as well as multi-day vacation frames13DDD#P,23DDD#P,33DDD#P: decoded asprogram = int(param) % 100(1102/3102-> program2).set_temperatureremainsNone, andmessage_typestayshvac_mode.OWNHeatingEvent.program -> int | NoneandOWNHeatingEvent.scenario -> int | None(supporting weekly programs 1..3 for seasonal, 1..16 for generic, and scenarios 1..16 on12xx/22xx/32xx).Map Seasonal Holiday Days & Expose Duration:
13001..13255mapped toCLIMATE_MODE_HEAT(season = "heating").23001..23255mapped toCLIMATE_MODE_COOL(season = "conditioning").33001..33255retained asCLIMATE_MODE_AUTO(season = None).OWNHeatingEvent.holiday_days -> int | Nonecomputed asmode % 1000.Recognize Central Unit Diagnostic Status WHATs:
22, 23, 24, 30, 31with descriptive telemetry logs (e.g.23->\"Zone #0's central unit reports at least one probe is in antifreeze\").mode = Noneandseason = None, avoiding spurious "unknown mode" logs while preserving downstream stability.Frame Parsing Comparison Table
master*4*1*23##mode="heat",type="hvac_mode"mode=None,season="heating",type="hvac_season"*4*0*23##mode="cool",type="hvac_mode"mode=None,season="conditioning",type="hvac_season"*4*115#1101*#0##(contributed in MyHOME#692)mode="heat",set_temp=-10.1,type="hvac_mode_target"mode="heat",program=1,set_temp=None,type="hvac_mode"*4*115#1102*#0##mode="heat",set_temp=-10.2,type="hvac_mode_target"mode="heat",program=2,set_temp=None,type="hvac_mode"*4*215#2102*#0##mode="cool",set_temp=None,type="hvac_mode"mode="cool",program=2,set_temp=None,type="hvac_mode"*4*13005#3102*#0##mode="auto",set_temp=-10.2,type="hvac_mode_target"mode="heat",season="heating",program=2,holiday_days=5,type="hvac_mode"*4*23005#3102*#0##mode="auto",set_temp=None,type="hvac_mode"mode="cool",season="conditioning",program=2,holiday_days=5,type="hvac_mode"*4*33005#3102*#0##mode="auto",set_temp=None,type="hvac_mode"mode="auto",season=None,program=2,holiday_days=5,type="hvac_mode"*4*13001*1##mode="auto",holiday_days=Nonemode="heat",season="heating",holiday_days=1,type="hvac_mode"*4*23001*1##mode="auto",holiday_days=Nonemode="cool",season="conditioning",holiday_days=1,type="hvac_mode"*4*33004*#0##mode="auto",holiday_days=Nonemode="auto",season=None,holiday_days=4,type="hvac_mode"*4*23*#0##\"mode is unknown\",mode=None\"at least one probe is in antifreeze\",mode=None*4*30*#0##\"mode is unknown\",mode=None\"a failure was discovered\",mode=None*4*31*#0##\"mode is unknown\",mode=None\"the central unit battery is KO\",mode=None3. How is it tested?
Dedicated Unit Test Suites:
tests/test_who4_season.py: verifies bare WHAT 0/1 frames emitMESSAGE_TYPE_SEASONwithmode is Noneand correctseason, tests a 13-row matrix of season-specific mode WHATs, verifies non-mode frames haveseason is None, and verifies unrecognised WHATs (150,1104,1199,13000,13256,1#0215,0#0215) leaveseason is Noneandmessage_type is None.tests/test_who4_holiday_plan_program.py: verifies115#1102,215#2102,13005#3102,23005#3102,33005#3102extractprogram == 2withset_temperature is None, verifies program/scenario exposure across1102,2102,3113,1203,3209, and asserts genuine setpoint frames (110#0215,312#0220#2) still read target temperatures.tests/test_who4_central_status_whats.py: verifies diagnostic status logging for WHATs22, 23, 24, 30, 31(asserting WHAT 23 logs "antifreeze") withmode is None, and verifies unhandled WHATs (e.g.999) still log unknown.tests/test_who4_f453av_traces.py: pins all 6 physical trace scenarios from @nce2704 on Central Unit #0.tests/test_message_edges.py: verifies holiday day counts and seasonal modes for13001,23001, and33004.tests/test_issue_77_firmware_findings.py: updated central mode test matrix to assert season reading for WHAT 1 / 0.tests/test_message_exhaustive.py: updated mode-target test to use documented standard*4*110#0215*1##.Coverage and Test Suite Results:
pytest tests: 1,370 passed, 1 skipped.OWNd/message/heating.py(709/709 statements) and across all 24 modules ofOWNd(3,870 / 3,870 statements).verify_library_standards.pyandruff check: 100% clean.4. How is it covered in real traces?
All changes are grounded in seven independent layers of evidence:
Live Gateway Emitted Corpus (
hex2own_corpus.tsv, 26,810 lines):*4*1*Z##and 19 lines of*4*0*Z##.*4*1*Z##or*4*0*Z##broadcasts (F0byte translates to*4*1*Z##,F1translates to*4*0*Z##). This empirical correlation proves they are season status telemetry, not operating mode changes.Multi-Gateway Firmware Replays (
thermo-holiday-programacross 10 Gateway Models):thermo-holiday-programsuite of own-firmware-oracle (replayed green across all 10 catalogued gateways: F450, F453AV, F454, F459, F460, F461, H4684, MH200N, MH202, and MyHomeServer1, synced inresults/mcp_index.json):*4*115#1102*#0##is ACKed and translated bybt_termointo SCS telegramD1 00 03 02 C1 14 01 00(byte 6 =14holiday plan heating, byte 7 =01program 2). There is no temperature byte on the bus (contrast with real setpoint*#4*#0*#14*0250*1##->... C1 12 32 00where32= 25.0°C).*4*215#2102*#0##is ACKed and translated into conditioning holiday plan telegram (program 2).*4*13005#3102*#0##,*4*23005#3102*#0##, and*4*33005#3102*#0##are ACKed and emitD1 00 03 02 C1 05 05 01(byte 7 =05days, byte 8 =01program 2).*4*1*23##and*4*0*23##are ACKed and emitted as93 17 30 01and93 17 30 00.Official Legrand Protocol Specification:
0as "Conditioning Mode",1as "Heating Mode"; defines115#parameterH/215#parameterHwhereparameterHis weekly program1101..1103/2101..2103.0and1are designated as "zone operation mode acquire frame" alongside setpoint reports, distinct from operating mode commands (110,111,103).13xxxas holiday days heating,23xxxas holiday days conditioning; defines22, 23, 24, 30, 31as central unit system status reports (with 23 defined as "at least one probe in antifreeze").Reference Touchscreen Client Implementation (
libqtdevicesTS10_1_0_23):probe_device.cpp:240-253: on receivingHEATING(1) orCONDITIONING(0), preserves activeST_MANUALandST_AUTOstates without resetting them.thermal_device.cpp:240-241, 285-286: parseswhatArgN(0) % 100as the program index.thermal_device.cpp:258-262, 303-307: assignsSUM_HOLIDAY(23000) to summer season andWIN_HOLIDAY(13000) to winter season.thermal_device.cpp:47-48, 215-217: parses diagnostic status WHATs30(MALFUNCTIONING_FOUND) and31(BATTERY_KO) without altering mode.Physical Gateway Central Unit #0 & Holiday Bus Captures (
tests/fixtures/traces/issue_619/, test(trace): add authentic BTicino F453AV Central Unit #0 and WHO 4 trace fixtures (#619) MyHOME#692):#0(OWNd#97 comment 6110745254):myhome_trace_F453AV_who4_2026-10-11T11-02-55.Holiday.ON.json): When Daily Holiday was turned ON on Central Unit#0, the gateway emitted*4*115#1101*#0##. On master,1101was routed towho4_temperature()and misparsed as-10.1 °C. Under this PR, it is correctly parsed asprogram = 1101 % 100 = 1,mode = "heat",set_temperature = None, andmessage_type = "hvac_mode".myhome_trace_F453AV_who4_2026-10-11T11-10-23.Holiday.OFF.automatically.json): Upon expiration, the central unit broadcast*4*1101*#0##, cleanly restoring weekly program 1.myhome_trace_F453AV_who4_2026-10-11T10-29-57.json): Demonstrates zone heating season frames*4*1*Z##coexisting with active weekly program reports*4*111*#Z##without displacing the zone's active schedule mode.myhome_trace_F453AV_who4_2026-10-11T11-15-50.one.zone.to.cool.json): Switching a zone from Heat to Cool in the Freedompro app immediately triggered Central Unit#0to switch the plant from Winter to Summer into Thermal Protection (*4*202*#0##), resetting setpoints to cooling targets.Antifreeze.ON.json&Central.to.OFF.json): Central transitions*4*102*#0##and*4*103*#0##broadcast to subzones (#Z) and physical actuators (Z), accompanied by diagnostic status flags*4*21*#0##and*4*22*#0##.tests/test_who4_f453av_traces.py.3550 Temperature Control Central Unit (99 zones):
catalog/3550/030020.yaml, firmware 3.0.20, Mitsubishi M16C).$0490003000,$06D1000302F0000000) and independent menus for daily holiday (HOLIDAY/FESTIVO) and multi-day vacation (HOLIDAYS/FERIE).Downstream Integration:
Replaces and closes #87, #88, #89, and #94.
Co-authored-by: gdluck 9041273+gdluck@users.noreply.github.com