Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
proto_heating.h
Go to the documentation of this file.
1#pragma once
2
3/// @file proto_heating.h
4/// @brief Pure codec for the private register protocol of 2W heaters (CMD_WRITE_PRIVATE 0x20).
5/// @ingroup hioc_protocol
6///
7/// A heater with an adjustable setpoint (node type 52, subtype 1) exposes its state as 16-bit
8/// registers `0x01xx`, read with `0C 60 01 <reg>` and written with `0C 61 01 <reg> <value>`; the
9/// device answers with CMD_WRITE_PRIVATE_ACK (0x21) echoing the header, followed by the value. Values
10/// are little-endian. An Atlantic AGILIA IO radiator answers every read and write this way
11/// (tests/corpus/captures/exchange/atlantic_agilia_exchange_{status_read,setpoint_and_off_read_back,mode_read_back}.yaml,
12/// pinned by corpus_heating_test.cpp).
13///
14/// One descriptor table (`HEATING_FUNCTIONS` in the .cpp) lists every register this component
15/// uses: its access (read-only, read/write, write-only) and how its value is encoded. The same row
16/// drives the get payload, the set payload and the decoder of the reply, so a register is described
17/// exactly once. This module is pure: it does not touch a device record or the radio —
18/// proto_commands.h's create_write_private() frames a payload.
19///
20/// Confirmed on that radiator: the setpoint, mode (all four writable values), room temperature,
21/// regulator and maximum-setpoint registers. The presence register has been written and acknowledged,
22/// with no visible effect observed; the window and open-window-detection registers have only been read
23/// at rest.
24///
25/// An Atlantic Adelis towel dryer answers the same protocol and adds its own registers: its mode
26/// (0x0136), its temporary state (boost or drying, 0x013E), its working rate (0x0126), the temperature
27/// it holds right now (0x0137) and its eco setback (0x0104). They have been read on two units in every
28/// state (tests/corpus/captures/probe/atlantic_adelis_probe_*.yaml); writing 0x0136 and 0x013E is
29/// confirmed against the display, the others are read-only.
30///
31/// A Sauter Hekla heater adds a night light: on/off in register 0x0144 (`01` / `00`, read on a heater
32/// with the light on and off, and written as `0C 61 01 44 <value>` by the heater's own Cozytouch
33/// controller) and, most likely, its brightness in 0x0142 (reads 100 with the light at full) (issue #222).
34
35#include "proto_frame.h"
36
37#include <cmath>
38#include <cstddef>
39#include <cstdint>
40
41namespace esphome {
42namespace home_io_control {
43
44/// @brief Registers and functions of a 2W heater, one row of the descriptor table each.
45///
46/// The `SET_*` names are the functions of the `heating_control` action; the same row is also the
47/// register's read path (reading SET_TEMPERATURE reads the comfort setpoint).
48enum class HeatingFunction : uint8_t {
49 POWER_ON, ///< Register 0x012C, read: the paired-device list. Logged, never decoded.
50 SET_TEMPERATURE, ///< Register 0x0103, read/write: comfort setpoint, tenths of a degree.
51 SET_MODE, ///< Register 0x0100, read/write: operating mode (HeatingMode).
52 SET_PRESENCE, ///< Register 0x0110, write-only: someone is in the room (1) or not (0).
53 SET_OPEN_WINDOW_DETECTION, ///< Register 0x0106, read/write: open-window detection on (1) or off (0).
54 MIDNIGHT_SYNC, ///< Register 0x0130, read: the comfort/eco/auto setpoint block. Logged, never decoded.
55 ROOM_TEMPERATURE, ///< Register 0x0115, read-only: measured room temperature, signed hundredths of a degree.
56 REGULATOR_STATE, ///< Register 0x0117, read-only: 0 none, 1 standby, 2 heating.
57 MAX_SETPOINT, ///< Register 0x0102, read-only: highest setpoint the heater accepts, tenths of a degree.
58 WINDOW_OPEN, ///< Register 0x010E, read-only: the heater's window sensor, 0 closed / 1 open.
59 TOWEL_MODE, ///< Register 0x0136, read/write: a towel dryer's mode (TowelDryerMode).
60 TEMPORARY_STATE, ///< Register 0x013E, read/write: a towel dryer's temporary state (HeatingTemporaryState).
61 WORKING_RATE, ///< Register 0x0126, read-only: share of the time the element heats, 0-100 %.
62 TEMPERATURE_IN_FORCE, ///< Register 0x0137, read-only: the temperature a towel dryer holds right now, tenths of a
63 ///< degree. Only a temperature while no boost or drying runs (it reads 1 and 2 there).
64 ///< \todo Confirm on a second towel dryer (the reads so far are from one unit).
65 ECO_SETBACK, ///< Register 0x0104, read-only: how far below the comfort setpoint a towel dryer's eco
66 ///< period heats, tenths of a kelvin.
67 NIGHT_LIGHT, ///< Register 0x0144, read/write: a heater's night light on (1) or off (0).
68 NIGHT_LIGHT_BRIGHTNESS, ///< Register 0x0142, read/write: the night light's brightness, 0-100 %, 16-bit.
69 ///< \todo Confirm on a real heater that the value is a percentage and that a
70 ///< write dims the light (issue #222).
71};
72
73/// @brief Operating modes of the mode register (HeatingFunction::SET_MODE).
74enum class HeatingMode : uint8_t {
75 AUTO = 0x00, ///< Automatic mode; the device manages the setpoint itself.
76 MANUAL = 0x01, ///< Manual mode; follows the last written setpoint.
77 PROG = 0x02, ///< Program mode; the device runs its own stored weekly schedule.
78 EXTERNAL_SETPOINT = 0x03, ///< Setpoint comes from an external controller. Readable, never written by this
79 ///< component. Not named EXTERNAL: the Arduino core defines that as a macro.
80 OFF = 0x04, ///< Off / standby.
81};
82
83/// @brief Modes of a towel dryer's mode register (HeatingFunction::TOWEL_MODE).
84/// @details OFF, PROG and MANUAL are the values two Atlantic Adelis units report with their display
85/// showing off, PROG and MANUEL (issue #202, corpus atlantic_adelis_probe_mode_reads).
86enum class TowelDryerMode : uint8_t {
87 OFF = 0x00, ///< Off (standby).
88 AUTO = 0x01, ///< Defined by the register's range, never seen on a device; never written here.
89 PROG = 0x02, ///< Program mode: the device runs its own weekly program.
90 MANUAL = 0x03, ///< Manual mode: the device holds the comfort setpoint.
91};
92
93/// @brief Temporary states of a towel dryer (HeatingFunction::TEMPORARY_STATE): a timed run on top of
94/// the mode, which the mode register does not show.
95enum class HeatingTemporaryState : uint8_t {
96 NONE = 0x00, ///< No temporary state: the mode applies.
97 BOOST = 0x01, ///< Boost: full power for the boost duration.
98 DRYING = 0x02, ///< Drying: full power for the drying duration.
99};
100
101/// @brief Regulator states of the regulator register (HeatingFunction::REGULATOR_STATE).
102enum class HeatingRegulatorState : uint8_t {
103 NONE = 0x00, ///< No regulation active.
104 STANDBY = 0x01, ///< Regulating, the element is idle.
105 HEATING = 0x02, ///< The element is heating.
106};
107
108/// @brief Lowest setpoint this codec will encode.
109///
110/// The conventional frost-protection setpoint, safely representable as wire value 70.
111constexpr float HEATING_TEMP_MIN_C = 7.0F;
112
113/// @brief Highest setpoint this codec will encode.
114///
115/// The setpoint register is a 16-bit little-endian value in tenths of a degree; 28.0 °C (`18 01`) is
116/// the ceiling Atlantic radiator manuals document and the value an AGILIA IO radiator reports in its
117/// maximum setpoint register (tests/corpus/captures/exchange/atlantic_agilia_exchange_status_read.yaml).
118/// No setpoint above 25.5 °C (a non-zero high byte) has been written on hardware yet.
119constexpr float HEATING_TEMP_MAX_C = 28.0F;
120
121/// @brief Largest payload any function produces: a set of a 16-bit value (4-byte header + 2 value bytes).
122constexpr size_t HEATING_PAYLOAD_MAX_SIZE = 6;
123
124/// @brief Leading payload byte, common to every function. Its meaning is unconfirmed; do not read a
125/// semantic (for example "device class") into it.
126constexpr uint8_t HEATING_PAYLOAD_PREFIX = 0x0C;
127
128/// @brief Payload byte at index 2: the high byte of the 16-bit register number, constant `0x01`.
129constexpr uint8_t HEATING_REGISTER_HIGH_BYTE = 0x01;
130
131/// @brief Payload byte at index 1 of a read ("get") request.
132constexpr uint8_t HEATING_DIRECTION_GET = 0x60;
133
134/// @brief Payload byte at index 1 of a write ("set") request.
135constexpr uint8_t HEATING_DIRECTION_SET = 0x61;
136
137/// @brief Measured value in a reading when the heater reports a sensor fault (raw `-1`).
138/// A reading stores it as NaN, the same as "never read".
139constexpr int16_t HEATING_SENSOR_FAULT_RAW = -1;
140
141/// @brief Default encoding range of a temperature main parameter, in degrees Celsius. The main
142/// parameter spans HEATING_TEMPERATURE_MP_SPAN steps over [min, max]; this range is the one a device
143/// is assumed to use unless the YAML says otherwise (`min_temperature:` / `max_temperature:`).
144static constexpr float HEATING_TEMPERATURE_RANGE_MIN_C = -40.0F;
145static constexpr float HEATING_TEMPERATURE_RANGE_MAX_C = 80.0F; ///< See HEATING_TEMPERATURE_RANGE_MIN_C.
146
147/// @brief Highest night light brightness (HeatingFunction::NIGHT_LIGHT_BRIGHTNESS): a percentage, so
148/// this value is full brightness.
150
151/// @brief Offset of the first value byte in a register reply: the four header bytes it echoes.
152constexpr size_t HEATING_REPLY_VALUE_OFFSET = 4;
153
154/// @brief Register 0x0119: the heater's model name, ASCII, not terminated ("ADELIS 2 DIGIT" on an
155/// Atlantic Adelis, corpus atlantic_adelis_probe_register_01_sweep). Read raw for a log line; no
156/// HeatingFunction decodes it.
157constexpr uint8_t HEATING_REGISTER_MODEL_NAME = 0x19;
158
159/// @brief Stable lowercase name for a heating function ("power_on", "set_temperature", ...).
160/// @param fn Function.
161/// @return Null-terminated string; "unknown" for an out-of-range value.
163
164/// @brief Whether the register behind a function can be written.
165/// @param fn Function.
166/// @return true for a read/write or write-only register; false for a read-only one or an
167/// out-of-range value.
169
170/// @brief Whether the register behind a function can be read.
171/// @param fn Function.
172/// @return true for a read/write or read-only register; false for a write-only one or an
173/// out-of-range value.
175
176/// @brief Low byte of the 0x01xx register behind a function.
177/// @param fn Function.
178/// @param[out] register_low The register's low byte; untouched when false is returned.
179/// @return false for an out-of-range value.
180bool heating_function_register(HeatingFunction fn, uint8_t &register_low);
181
182/// @brief Is this frame a register reply that echoes a request for this register?
183/// @details A CMD_WRITE_PRIVATE_ACK whose data starts with `0C 60 <reg_hi> <reg_lo>` (a read) or
184/// `0C 61 <reg_hi> <reg_lo>` (a write). The value bytes, if any, follow at
185/// HEATING_REPLY_VALUE_OFFSET; a register the device does not hold is answered with none.
186/// @param reply The device's reply frame.
187/// @param reg_hi High byte of the register the request addressed.
188/// @param reg_lo Low byte of the register the request addressed.
189/// @return true when the reply is the register's echo.
190bool heating_reply_echoes_register(const IoFrame &reply, uint8_t reg_hi, uint8_t reg_lo);
191
192/// @brief Encode a write ("set") of one register into a CMD_WRITE_PRIVATE (0x20) payload.
193///
194/// `value` is interpreted by the register's encoding:
195/// - SET_TEMPERATURE: degrees Celsius within [HEATING_TEMP_MIN_C, HEATING_TEMP_MAX_C], encoded as
196/// a 16-bit little-endian value in tenths of a degree, round-half-away-from-zero(10 * value).
197/// - SET_MODE: a HeatingMode value widened to float; must be AUTO, MANUAL, PROG or OFF.
198/// - SET_PRESENCE, SET_OPEN_WINDOW_DETECTION: 0 or 1.
199/// - TOWEL_MODE: a TowelDryerMode value widened to float (0-3).
200/// - TEMPORARY_STATE: a HeatingTemporaryState value widened to float (0-2).
201/// - NIGHT_LIGHT: 0 or 1.
202/// - NIGHT_LIGHT_BRIGHTNESS: an integral percentage 0-100, encoded as a 16-bit little-endian value.
203/// A read-only register (including POWER_ON, MIDNIGHT_SYNC and the measurement registers) is never
204/// encoded as a write, and out-of-range, non-integral (for enum/binary encodings) or non-finite
205/// input is rejected: a byte derived from a truncating or wrapping cast is never emitted.
206/// @param fn Register to write.
207/// @param value Register-specific value (see above).
208/// @param out Output buffer of HEATING_PAYLOAD_MAX_SIZE bytes.
209/// @return Number of payload bytes written (5 or 6), or 0 on invalid input or a read-only register.
210size_t encode_heating_write(HeatingFunction fn, float value, uint8_t out[HEATING_PAYLOAD_MAX_SIZE]);
211
212/// @brief Encode a read ("get") of one register into a CMD_WRITE_PRIVATE (0x20) payload.
213/// @param fn Register to read.
214/// @param out Output buffer of HEATING_PAYLOAD_MAX_SIZE bytes.
215/// @return 4 (the payload is always `0C 60 01 <reg>`), or 0 for a write-only register or an
216/// out-of-range value.
218
219/// @brief Encode a read ("get") of an arbitrary register into a CMD_WRITE_PRIVATE (0x20) payload.
220///
221/// The diagnostic `register_00` / `register_01` probes ask a device for a register no
222/// HeatingFunction names. The request is always `0C 60 <reg_hi> <reg_lo>`: the direction byte is
223/// HEATING_DIRECTION_GET and this function has no parameter that could change it, so the write
224/// direction (HEATING_DIRECTION_SET) cannot be produced from here for any input.
225/// \todo Register family 0x00xx is untested on hardware. Family 0x01xx is the one encode_heating_read()
226/// already sends to Atlantic radiators.
227/// @param reg_hi High byte of the 16-bit register number.
228/// @param reg_lo Low byte of the 16-bit register number.
229/// @param out Output buffer of HEATING_PAYLOAD_MAX_SIZE bytes.
230/// @return Always 4 (`0C 60 <reg_hi> <reg_lo>`).
231size_t encode_heating_register_read(uint8_t reg_hi, uint8_t reg_lo, uint8_t out[HEATING_PAYLOAD_MAX_SIZE]);
232
233/// @brief Encode the function the `heating_control` action runs: a read for a read-only register,
234/// a write for every other.
235///
236/// POWER_ON and MIDNIGHT_SYNC are reads (their `value` is ignored); the measurement registers are
237/// reads too; the others are writes as in encode_heating_write().
238/// @param fn Function to encode.
239/// @param value Function-specific value (ignored for a read).
240/// @param out Output buffer of HEATING_PAYLOAD_MAX_SIZE bytes.
241/// @return Number of payload bytes written (4, 5 or 6), or 0 on invalid input.
242size_t encode_heating_payload(HeatingFunction fn, float value, uint8_t out[HEATING_PAYLOAD_MAX_SIZE]);
243
244/// @brief Decode the value a heater answered a register read or write with.
245///
246/// Accepts a CMD_WRITE_PRIVATE_ACK (0x21) whose data starts with `0C 60 01 <reg>` or
247/// `0C 61 01 <reg>` for this function's register, followed by at least the register's value bytes.
248/// Anything else (another command, another register, a truncated value, a function without a typed
249/// decode such as POWER_ON) is "no value".
250///
251/// The value is returned in natural units: degrees Celsius for the temperature registers, the raw
252/// byte for the others. A byte above its register's range (a mode, a state, a percentage) is
253/// "no value". A raw `-1` on the room-temperature register is a sensor fault: it decodes
254/// as NaN with `true` returned, because the heater did answer.
255/// @param reply The device's reply frame.
256/// @param fn Register the request addressed.
257/// @param[out] value Decoded value; untouched when `false` is returned.
258/// @return true when the reply carries a value for this register.
259bool decode_heating_reply(const IoFrame &reply, HeatingFunction fn, float &value);
260
261/// @brief What the hub has read from one heater so far.
262///
263/// Every field starts as "never read" (NaN, or -1 for the byte registers). Only a decoded reply
264/// changes a field, so what an entity shows from here is observed, never predicted.
266 float room_temperature_c{NAN}; ///< Measured room temperature; NaN until read or on a sensor fault.
267 float setpoint_c{NAN}; ///< Comfort setpoint as the heater holds it; NaN until read.
268 float max_setpoint_c{NAN}; ///< Highest setpoint the heater accepts; NaN until read.
269 int16_t mode{-1}; ///< HeatingMode value; -1 until read.
270 int16_t regulator{-1}; ///< HeatingRegulatorState value; -1 until read.
271 int16_t window_open{-1}; ///< 0 closed / 1 open; -1 until read.
272 int16_t open_window_detection{-1}; ///< 1 detection on / 0 off; -1 until read.
273 int16_t towel_mode{-1}; ///< TowelDryerMode value; -1 until read.
274 int16_t temporary_state{-1}; ///< HeatingTemporaryState value; -1 until read.
275 int16_t working_rate{-1}; ///< Working rate, 0-100 %; -1 until read.
276 float in_force_temperature_c{NAN}; ///< A towel dryer's temperature in force (register 0x0137); NaN until read.
277 float eco_setback_k{NAN}; ///< A towel dryer's eco setback (register 0x0104); NaN until read.
278 int16_t night_light{-1}; ///< Night light 1 on / 0 off; -1 until read.
279 int16_t night_light_brightness{-1}; ///< Night light brightness, 0-100 %; -1 until read.
280 int16_t level{-1}; ///< Low byte of the main parameter of a heater commanded with a prefixed
281 ///< value: a heating level, or a setpoint alias. -1 until a status reply
282 ///< carried one, and again after a reply that carried a plain
283 ///< temperature. Set by the hub's status path, not by store().
284 int32_t main_parameter{-1}; ///< The raw current main parameter of a heater commanded with an EXECUTE
285 ///< (a temperature, an alias or a level); -1 until a status reply
286 ///< carried one. Set by the hub's status path, not by store().
287
288 /// @brief Fold one decoded register value into the readings.
289 /// @param fn Register the value was read from.
290 /// @param value Value as returned by decode_heating_reply().
291 /// @return true when `fn` is a register the readings hold (and the field was set).
292 bool store(HeatingFunction fn, float value);
293
294 /// @brief Forget a register's value: it reads as "never read" again.
295 /// @param fn Register.
296 /// @return true when `fn` is a register the readings hold.
297 bool clear(HeatingFunction fn);
298
299 /// @brief Has this register been read yet?
300 /// @param fn Register.
301 /// @return true when the readings hold a value for `fn`; false for "never read" and for a function
302 /// the readings do not hold.
303 [[nodiscard]] bool has(HeatingFunction fn) const;
304
305 /// @brief The stored temperature of a register read in degrees.
306 /// @param fn Register.
307 /// @return The temperature (a setback in kelvin), or NaN when it has not been read or `fn` is not a
308 /// temperature register the readings hold.
309 [[nodiscard]] float temperature_of(HeatingFunction fn) const;
310
311 /// @brief The stored integer value of a register (a mode, a state, a flag, a percentage).
312 /// @details Lets a heating profile name the register its card reads (its mode or preset register)
313 /// instead of the caller picking a field.
314 /// @param fn Register.
315 /// @return The value, or -1 when it has not been read or `fn` is not an integer register the
316 /// readings hold (the temperatures are not).
317 [[nodiscard]] int16_t value_of(HeatingFunction fn) const;
318};
319
320} // namespace home_io_control
321} // namespace esphome
constexpr size_t HEATING_REPLY_VALUE_OFFSET
Offset of the first value byte in a register reply: the four header bytes it echoes.
bool decode_heating_reply(const IoFrame &reply, HeatingFunction fn, float &value)
Decode the value a heater answered a register read or write with.
constexpr size_t HEATING_PAYLOAD_MAX_SIZE
Largest payload any function produces: a set of a 16-bit value (4-byte header + 2 value bytes).
HeatingRegulatorState
Regulator states of the regulator register (HeatingFunction::REGULATOR_STATE).
@ STANDBY
Regulating, the element is idle.
@ AUTO
The heater's automatic mode (its own schedule and target).
Definition proto_dhw.h:146
size_t encode_heating_payload(HeatingFunction fn, float value, uint8_t out[HEATING_PAYLOAD_MAX_SIZE])
Encode the function the heating_control action runs: a read for a read-only register,...
HeatingFunction
Registers and functions of a 2W heater, one row of the descriptor table each.
@ MIDNIGHT_SYNC
Register 0x0130, read: the comfort/eco/auto setpoint block. Logged, never decoded.
@ TOWEL_MODE
Register 0x0136, read/write: a towel dryer's mode (TowelDryerMode).
@ ROOM_TEMPERATURE
Register 0x0115, read-only: measured room temperature, signed hundredths of a degree.
@ WORKING_RATE
Register 0x0126, read-only: share of the time the element heats, 0-100 %.
@ NIGHT_LIGHT
Register 0x0144, read/write: a heater's night light on (1) or off (0).
@ MAX_SETPOINT
Register 0x0102, read-only: highest setpoint the heater accepts, tenths of a degree.
@ POWER_ON
Register 0x012C, read: the paired-device list. Logged, never decoded.
@ TEMPORARY_STATE
Register 0x013E, read/write: a towel dryer's temporary state (HeatingTemporaryState).
@ SET_PRESENCE
Register 0x0110, write-only: someone is in the room (1) or not (0).
@ NIGHT_LIGHT_BRIGHTNESS
Register 0x0142, read/write: the night light's brightness, 0-100 %, 16-bit.
@ REGULATOR_STATE
Register 0x0117, read-only: 0 none, 1 standby, 2 heating.
@ WINDOW_OPEN
Register 0x010E, read-only: the heater's window sensor, 0 closed / 1 open.
@ SET_OPEN_WINDOW_DETECTION
Register 0x0106, read/write: open-window detection on (1) or off (0).
@ SET_TEMPERATURE
Register 0x0103, read/write: comfort setpoint, tenths of a degree.
@ TEMPERATURE_IN_FORCE
Register 0x0137, read-only: the temperature a towel dryer holds right now, tenths of a degree.
@ ECO_SETBACK
Register 0x0104, read-only: how far below the comfort setpoint a towel dryer's eco period heats,...
@ SET_MODE
Register 0x0100, read/write: operating mode (HeatingMode).
constexpr uint8_t HEATING_REGISTER_HIGH_BYTE
Payload byte at index 2: the high byte of the 16-bit register number, constant 0x01.
bool heating_function_is_readable(HeatingFunction fn)
Whether the register behind a function can be read.
TowelDryerMode
Modes of a towel dryer's mode register (HeatingFunction::TOWEL_MODE).
constexpr float HEATING_TEMP_MAX_C
Highest setpoint this codec will encode.
static constexpr float HEATING_TEMPERATURE_RANGE_MAX_C
See HEATING_TEMPERATURE_RANGE_MIN_C.
const char * heating_function_name(HeatingFunction fn)
Stable lowercase name for a heating function ("power_on", "set_temperature", ...).
bool heating_reply_echoes_register(const IoFrame &reply, uint8_t reg_hi, uint8_t reg_lo)
Is this frame a register reply that echoes a request for this register?
constexpr uint8_t HEATING_DIRECTION_SET
Payload byte at index 1 of a write ("set") request.
constexpr float HEATING_TEMP_MIN_C
Lowest setpoint this codec will encode.
constexpr uint8_t HEATING_NIGHT_LIGHT_BRIGHTNESS_MAX
Highest night light brightness (HeatingFunction::NIGHT_LIGHT_BRIGHTNESS): a percentage,...
size_t encode_heating_write(HeatingFunction fn, float value, uint8_t out[HEATING_PAYLOAD_MAX_SIZE])
Encode a write ("set") of one register into a CMD_WRITE_PRIVATE (0x20) payload.
static constexpr float HEATING_TEMPERATURE_RANGE_MIN_C
Default encoding range of a temperature main parameter, in degrees Celsius.
constexpr uint8_t HEATING_REGISTER_MODEL_NAME
Register 0x0119: the heater's model name, ASCII, not terminated ("ADELIS 2 DIGIT" on an Atlantic Adel...
HeatingMode
Operating modes of the mode register (HeatingFunction::SET_MODE).
@ PROG
Program mode; the device runs its own stored weekly schedule.
@ EXTERNAL_SETPOINT
Setpoint comes from an external controller.
@ MANUAL
Manual mode; follows the last written setpoint.
constexpr int16_t HEATING_SENSOR_FAULT_RAW
Measured value in a reading when the heater reports a sensor fault (raw -1).
constexpr uint8_t HEATING_PAYLOAD_PREFIX
Leading payload byte, common to every function.
size_t encode_heating_register_read(uint8_t reg_hi, uint8_t reg_lo, uint8_t out[HEATING_PAYLOAD_MAX_SIZE])
Encode a read ("get") of an arbitrary register into a CMD_WRITE_PRIVATE (0x20) payload.
bool heating_function_is_writable(HeatingFunction fn)
Whether the register behind a function can be written.
bool heating_function_register(HeatingFunction fn, uint8_t &register_low)
Low byte of the 0x01xx register behind a function.
HeatingTemporaryState
Temporary states of a towel dryer (HeatingFunction::TEMPORARY_STATE): a timed run on top of the mode,...
@ DRYING
Drying: full power for the drying duration.
size_t encode_heating_read(HeatingFunction fn, uint8_t out[HEATING_PAYLOAD_MAX_SIZE])
Encode a read ("get") of one register into a CMD_WRITE_PRIVATE (0x20) payload.
constexpr uint8_t HEATING_DIRECTION_GET
Payload byte at index 1 of a read ("get") request.
IO-Homecontrol 2W frame container: control bytes, IoFrame and (de)serialization.
What the hub has read from one heater so far.
int16_t window_open
0 closed / 1 open; -1 until read.
int16_t level
Low byte of the main parameter of a heater commanded with a prefixed value: a heating level,...
int16_t open_window_detection
1 detection on / 0 off; -1 until read.
int16_t value_of(HeatingFunction fn) const
The stored integer value of a register (a mode, a state, a flag, a percentage).
bool has(HeatingFunction fn) const
Has this register been read yet?
float setpoint_c
Comfort setpoint as the heater holds it; NaN until read.
float room_temperature_c
Measured room temperature; NaN until read or on a sensor fault.
int32_t main_parameter
The raw current main parameter of a heater commanded with an EXECUTE (a temperature,...
int16_t temporary_state
HeatingTemporaryState value; -1 until read.
bool clear(HeatingFunction fn)
Forget a register's value: it reads as "never read" again.
int16_t night_light
Night light 1 on / 0 off; -1 until read.
int16_t working_rate
Working rate, 0-100 %; -1 until read.
float temperature_of(HeatingFunction fn) const
The stored temperature of a register read in degrees.
float max_setpoint_c
Highest setpoint the heater accepts; NaN until read.
int16_t towel_mode
TowelDryerMode value; -1 until read.
int16_t mode
HeatingMode value; -1 until read.
int16_t night_light_brightness
Night light brightness, 0-100 %; -1 until read.
int16_t regulator
HeatingRegulatorState value; -1 until read.
float in_force_temperature_c
A towel dryer's temperature in force (register 0x0137); NaN until read.
float eco_setback_k
A towel dryer's eco setback (register 0x0104); NaN until read.
bool store(HeatingFunction fn, float value)
Fold one decoded register value into the readings.
Parsed IO‑Homecontrol frame (CTRL0/1 + addresses + command + data).
Definition proto_frame.h:93