Skip to content

fix(heating): read the 115#/215#/315# parameter as a program, not a temperature - #87

Closed
gdluck wants to merge 1 commit into
OpenWebNet-HA:masterfrom
gdluck:fix/who4-holiday-plan-program
Closed

gdluck wants to merge 1 commit into
OpenWebNet-HA:masterfrom
gdluck:fix/who4-holiday-plan-program

Conversation

@gdluck

@gdluck gdluck commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Requested by A · project thread

Before: *4*115#1102*#0## was read as "heat at -10.2 °C" (set_temperature = -10.2, message_type = hvac_mode_target).

After: it is read as "heating, holiday daily plan, program 2" (program = 2, set_temperature = None, message_type = hvac_mode). The event also exposes program for the 11xx / 21xx / 31xx WHATs and scenario for 12xx / 22xx / 32xx. 110#T, 210#T and 312#T#2 keep reading the temperature.

Evidence

Spec. p. 56 and p. 64: the WHAT of the weekend / holiday plan is 115#parameterH (heating) or 215#parameterH (conditioning), where parameterH is the weekly program to resume, 1101-1103 / 2101-2103. It is not a temperature field; temperatures appear only in 110#T / 210#T (p. 23, p. 56).

libqtdevices TS10_1_0_23. thermal_device.cpp:

 65: 	WIN_WEEKEND = 115,               // weekend operation (festivo)
 66: 	WIN_PROGRAM = 1100,              // weekly program (1 out of 3)
 67: 	WIN_SCENARIO = 1200,             // scenario (1 out of 16, 99zones thermal regulator only)
209: 	int command = commandRange(what);
210: 	int program = what - command;
240: 	case SUM_WEEKEND:
241: 		values_list[DIM_PROGRAM] = msg.whatArgN(0) % 100;
246: 	case SUM_PROGRAM:
247: 		values_list[DIM_PROGRAM] = program;
252: 	case SUM_SCENARIO:
253: 		values_list[DIM_SCENARIO] = program;
285: 	case WIN_WEEKEND:
286: 		values_list[DIM_PROGRAM] = msg.whatArgN(0) % 100;

The parameter of 115/215 is whatArgN(0) % 100, a program number; commandRange() (:350-358) splits 1102 into command 1100 + program 2.

Why the old reading produced -10.2 °C: in BTicino's 4-digit temperature convention a value of 1000 or more is negative (libqtcommon TS10_1_0_23 scaleconversion.cpp:57-67, bt2Celsius(); its tests feed *#4*Z*0*1039## and *#4*Z*15*1*1010*1111## as -3.9 °C and -1.0 °C, test/test_scenevodevicescond.cpp:451-453, 495), so 1102 taken as a temperature is -10.2 °C. The same digits are a program code when they follow 115#, which is what this change distinguishes.

Firmware. bt_termo (results/termo.tsv and termo_f454, termo_F459, termo_f461, termo_F450.tsv, identical on all five):

Frame Reply Bus body Reading
*4*115#1102*#0## ACK D1 00 03 02 C1 14 01 00 byte 6 = 14 holiday plan heating, byte 7 = 01 → program 2
*4*215#2102*#0## ACK D1 00 03 02 C1 24 01 00 same for conditioning (24)
*4*1102*#0## ACK D1 00 03 02 C1 11 01 00 program 2 heating, same byte 7
*4*2102*#0## ACK D1 00 03 02 C1 21 01 00 program 2 conditioning
*4*1203*#0## ACK D1 00 03 02 C1 13 02 00 scenario 3
*4*3113*#0## ACK D1 00 03 02 C1 01 0C 00 program 13 generic
*4*3209*#0## ACK D1 00 03 02 C1 03 08 00 scenario 9 generic

The #1102 parameter is forwarded as the one-byte program index (01, zero-based), in the same byte the plain program command uses. There is no temperature on the bus. Compare the real setpoint write *#4*#0*#14*0250*1## → D1 00 03 02 C1 12 32 00 (32 = 25.0 °C), REPORT.md 2.1.

How

OWNd/message/heating.py: a 115/215/315 frame with a parameter sets program = int(param) % 100 and keeps hvac_mode; the existing "mode with parameter = target temperature" branch now runs only for the other WHATs. New program / scenario properties. Tests: tests/test_who4_holiday_plan_program.py. pytest: 1241 passed, 1 skipped.


How to check. libqtdevices quotes are from tag TS10_1_0_23 of OpenWebNet-HA/libqtdevices (BTicino's 2010 touch-screen client, used only as a second client, not as the reference). Firmware rows are replays of the exact frame on the original gateway translator binaries (ARM, from the MyHomeServer1, F454, F459, F461 and F450 images) under QEMU on a fake SCS bus: ACK = *#*1##, NACK = *#*0##, the bus body is what the program put on the SCS bus (hex, without the A8 / checksum / A3 framing). Spec = Legrand/BTicino "Open Web Net Language, WHO = 4" v2.0.0 (2013-11-27). Raw logs, command lists, the harness and the report are in firmware_validation.zip (results/<program>[_<image>].tsv, results/*.cl / *.stub / *.mon, REPORT.md). The firmware images themselves are not included.

Split out of #86 so each change can be checked on its own; the eight slices (#87-#94) merge together in any order without conflicts, and the merged union passes 1285 tests with 100 % coverage of OWNd/message (checked locally on 2026-10-07 after the review rework of #94).

🤖 Generated with Claude Code

https://claude.ai/code/session_018oHp1P4vxxoFnaLUUZpbpZ

…emperature

OWNd parsed *4*115#1102*#0## as "heat at -10.2 °C". The parameter of the
holiday-plan WHATs 115/215/315 is the weekly program the central unit
resumes afterwards (Legrand WHO 4 v2.0.0 p. 56 and p. 64: "115#parameterH",
parameterH = 1101-1103). libqtdevices TS10_1_0_23 reads it as
whatArgN(0) % 100 (thermal_device.cpp:241, 286). The gateway firmware
(bt_termo on MyHomeServer1, F454, F459, F461, F450) accepts the frame and
forwards it as D1 00 03 02 C1 14 01 00: byte 7 is the program number,
there is no temperature field.

The event now exposes program (also for 11xx/21xx/31xx WHATs) and
scenario (12xx/22xx/32xx), and keeps hvac_mode as its type. 110#T,
210#T and 312#T#2 still read the temperature.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018oHp1P4vxxoFnaLUUZpbpZ
@gdluck
gdluck force-pushed the fix/who4-holiday-plan-program branch from 824a080 to 3cd1811 Compare October 7, 2026 17:22
@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!

@gdluck

gdluck commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #97, which carries this change verbatim together with the other WHO 4 heating fixes. Closing as agreed in OpenWebNet-HA/MyHOME#649.

@gdluck gdluck closed this Oct 7, 2026
GreenGrassBlueOcean added a commit that referenced this pull request Oct 16, 2026
…#88, #89, #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>
GreenGrassBlueOcean added a commit that referenced this pull request Oct 16, 2026
…d-heating

fix(heating): correct season status, holiday programs, and CU diagnostics (#87, #88, #89, #94)
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.

2 participants