Modes & presets¶
Almost everything confusing about this integration follows from one fact:
The appliance holds a set of modes, not one mode
ApplianceModes is a bitfield. Boost, away, advance, frost protection and several
others are independent bits, and more than one can be set at the same time. Home
Assistant's preset_mode is a single string, so it can only ever show one of them.
That mismatch is why #163 needed a decompiler to diagnose: the integration asked for boost, the appliance engaged advance, and the dashboard had no way to say so.
What the appliance reports¶
The full bitfield, as recovered from the official app. The integration reads four of these and ignores the rest.
| Bit | Value | Mode | Used by the integration |
|---|---|---|---|
| 0 | 1 | TIMER_MODE — following the schedule |
Implicitly, as "not overridden" |
| 1 | 2 | BOOST |
Boost active sensor, boost preset |
| 2 | 4 | AWAY |
Away active sensor, away preset |
| 3 | 8 | HOLIDAY |
No |
| 4 | 16 | ADVANCE |
Advance active sensor, dimplex.set_advance |
| 5 | 32 | FROST_PROTECT |
Frost protection sensor, HVAC off |
| 6 | 64 | ECO |
Decoded by the Operating mode sensor — see the bit-64 probe |
| 7 | 128 | MANUAL — holding one target, ignoring the schedule |
Operating mode sensor, manual option of the Operating mode select |
| 8 | 256 | HYGIENE — hot water cylinder anti-legionella cycle |
No |
| 9 | 512 | STANDALONE |
No |
| 10 | 1024 | SAFE_MODE |
No |
| 11 | 2048 | SHUTDOWN |
No |
| 12 | 4096 | COMMS |
No |
| 13 | 8192 | NORMAL |
No |
| 14 | 16384 | STANDBY |
No |
Before 4.1.0 these values were wrong
Earlier releases assumed boost was bit 16 and away bit 32. Those are in fact
ADVANCE and FROST_PROTECT. Asking for boost engaged advance; asking for away engaged
frost protection and pinned the heater to 7 °C. Both were corrected in 4.1.0 against
the values above.
How it maps into Home Assistant¶
flowchart LR
subgraph AP["Appliance — ApplianceModes bitfield"]
direction TB
B["BOOST (2)"]
A["AWAY (4)"]
AD["ADVANCE (16)"]
F["FROST_PROTECT (32)"]
end
subgraph ES["Separate setting"]
E["EcoStartEnabled"]
end
subgraph HA["Home Assistant"]
direction TB
HM["hvac_mode<br/>heat / off"]
PM["preset_mode<br/>one value only"]
BS["4 diagnostic sensors<br/>one per bit"]
end
F --> HM
B --> PM
A --> PM
E --> PM
B --> BS
A --> BS
AD --> BS
F --> BS
AD -. "not represented<br/>in preset_mode" .-> PM
The four diagnostic sensors are the lossless view. preset_mode is the convenient one.
Why preset_mode can disagree with reality¶
The entity resolves the bitfield to a single preset in a fixed order, and stops at the first match:
- Frost protection engaged → no preset, and
hvac_modeisoff. The live bitfield is authoritative: a cached off-like timer schedule no longer forcesoffwhile the appliance reports a live mode. The schedule is only consulted when the appliance reports no modes at all. BOOSTset →boostAWAYset →awayEcoStartEnabled→eco- Otherwise →
comfort
So an appliance holding both boost and away reports boost, and one holding advance
reports comfort — because advance has no preset of its own. Neither is a bug in the
reporting; there is simply nowhere for the second value to go.
Automate on the diagnostic sensors, not on preset_mode, whenever you care about a
specific mode:
Setting a preset clears the others¶
Home Assistant treats a preset as a single mutually exclusive state, so selecting one engages exactly what that preset owns and clears the rest.
| Preset | Engages | Clears |
|---|---|---|
comfort |
nothing — follow the schedule | boost, away, EcoStart |
boost |
boost | away, EcoStart |
away |
away | boost, EcoStart |
eco |
EcoStart | boost, away |
Clearing happens before engaging, so the appliance never briefly holds two conflicting modes.
Before 4.1.0 each preset only added its own state. Switching from away to eco enabled
EcoStart but left away engaged, and because the resolution order above puts away ahead of
EcoStart, the entity kept reporting away and nothing appeared to happen — that was
#173.
Presets are also gated by appliance capability: one your appliance does not support is not
offered in preset_modes and is skipped rather than sent blindly.
Temperature range per mode¶
The ranges genuinely differ, and only one is exposed as a climate limit.
| Mode | Range | Notes |
|---|---|---|
| Normal setpoint | 7–30 °C | The climate entity's min_temp / max_temp |
| Boost | 7–30 °C | Believed the same; the app's picker offers it |
| Away | 7–18 °C | Genuinely lower. Higher values are clamped with a log warning |
| Advance | 7–30 °C | Or omit it and use the schedule's own target |
| Frost protection | fixed 7 °C | Not settable |
Away is the one that surprises people: 18 is the ceiling in the official app's Away picker too, and the cloud silently reduces anything higher. See #174.
The non-Away ranges are inferred, not confirmed
7–30 °C for boost, advance and manual comes from reading the official app, not from testing each one. Since Away turned out to be an exception, the others are not fully trustworthy either. dimplex-controller-py#98 tracks re-reading each mode's range from the app.
Which modes stack¶
- Frost protection wins over everything. It is the app's "off", and while it is engaged
the integration reports
hvac_mode: offand no preset, whatever else is set. - Boost and away can both be set at the appliance. The integration will not put them there — presets clear each other — but a change made in the official app can, and the diagnostic sensors will show it.
- Advance stacks with anything. It affects the next schedule period, so it coexists with whatever is happening now.
- EcoStart is orthogonal. It is a separate boolean, not a bit in this field, so it can be on alongside any mode.
Timer modes are a different field¶
TimerMode is a small enum, not part of the bitfield, and it says how the appliance treats
its schedule:
| Value | Mode | Meaning |
|---|---|---|
| 0 | USER_TIMER |
Follow the weekly programme — the normal state |
| 1 | MANUAL |
Hold one target, ignore the programme |
| 2 | FROST_PROTECTION |
The 7 °C floor |
| 3 | OFF |
Off |
The integration exposes this as the diagnostic Schedule sensor. An off-like
TimerMode (2 or 3) counts as "off" for hvac_mode only when the appliance
reports no live modes at all — with a bitfield present, the bits win, so a
heater the app shows as Manual is heat even while its cached schedule still
says frost. Turning a heater back on restores USER_TIMER, but only for
appliances that report no live mode bits: rewriting the schedule over a live
Manual hold is what kept converting Manual heaters to user timers.
The sensor always shows the active profile's periods, but periods refresh on a fifteen-minute cadence (plus immediately after a profile change or a Home Assistant-side edit). Editing the same profile's periods in the official app can therefore take up to fifteen minutes to appear here — the state name updates on the next status poll, while the period list waits out the cache.
The bit-64 probe¶
QRAD firmware 28 reports ApplianceModes: 64 (ECO) while the official app
shows the heater as Manual, with the setpoint behaving as a manual hold.
The library maps 64 to ECO and 128 to MANUAL, and the integration follows
the library rather than special-casing 64 in code: the Operating mode
sensor reports the raw integer and the flag names faithfully, and the
operating-mode select maps only 128 to manual.
If you can test what bit 64 actually drives on real hardware — whether it heats like Manual, follows a schedule, or does something else — that result belongs here and in #273, and only then should the mapping change.
"Off" is frost protection¶
There is no off mode. Turning a Dimplex appliance off, in the official app or here, engages frost protection at 7 °C — an anti-freeze floor that stops rooms and pipework freezing.
So after climate.turn_off the entity reports a 7 °C target, hvac_mode: off and
hvac_action: off. That is correct. Full detail in
why "off" reports 7 °C.
The eco preset is not Eco mode¶
Two different things share the name, and the integration uses only one of them.
EcoStartEnabled |
ECO (bit 64) |
|
|---|---|---|
| What | A pre-heat setting | An appliance mode |
| Does | Learns the room's warm-up time and starts early so target is met on time | Unknown — never tested |
| Exposed as | The eco preset, the EcoStart switch, dimplex.set_eco_start |
The Operating mode sensor (read-only) |
The eco preset drives EcoStart. The cloud's separate Eco mode bit is read but never
written: the operating-mode select deliberately does not offer it, because its behaviour
on real hardware has not been established — see the bit-64 probe.
This ambiguity is worth knowing about precisely because the new mode sensors sit next to a
preset called eco that has nothing to do with the ECO bit.
Seeing the real state¶
Four ways, in increasing detail:
- The Operating mode sensor — the live bitfield decoded to flag names, with the raw integer alongside. The lossless view that never guesses.
- The four diagnostic binary sensors — boost, away, frost protection, advance. Disabled by default; enable them in the entity registry.
- A diagnostics download — decodes
ApplianceModesinto mode names, so you do not have to do the arithmetic. See diagnostics & bug reports. - The raw value —
ApplianceModesappears in diagnostics as an integer.8198isBOOST | AWAY | NORMAL(2 + 4 + 8192)… which is exactly the sort of sum nobody should have to do by hand, hence the decoding above.
Next¶
- Temperature & schedules — how a setpoint write reaches the appliance
- Actions — boost, away and advance with their fields
- Entities — the diagnostic mode sensors
- Automations — triggering on the real mode