Skip to content

Commit 4eaa6c7

Browse files
Merge pumpen-topics: TOP103 Pump_Duty_Max und TOP104 Water_Pump_Mode (3.10.0)
2 parents b8e1a4d + e96f7e3 commit 4eaa6c7

7 files changed

Lines changed: 179 additions & 104 deletions

File tree

‎MQTT-Topics.md‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ TOP99 | Quiet_Mode_Active | Quiet mode actually running (0=off, 1=on) - on/off o
128128
TOP100 | Powerful_Mode_Active | Powerful mode actually running (0=off, 1=on)
129129
TOP101 | Heat_Cool_SW_State | Actual heat/cool state of the unit (0=heat, 1=cool)
130130
TOP102 | External_SW_State | External switch state (0=off, 1=on)
131+
TOP103 | Pump_Duty_Max | Upper limit the water pump may modulate up to (duty) - the readback of SET15
132+
TOP104 | Water_Pump_Mode | Water pump mode (0=auto, 1=fix, 2=air purge) - the readback of SET14
131133

132134
### Actual states from byte 110 (TOP99 - TOP102, new in 3.7.0)
133135

@@ -304,6 +306,43 @@ zieht selbständig nach, aber ohne festen Versatz: 3,1 s hinter Stufe 1 auf der
304306
ersten Flanke, 40 ms auf der zweiten.*
305307

306308

309+
### Pump readback (TOP103, TOP104, new in 3.10.0)
310+
311+
Both are the missing readback for the two pump commands, and both byte
312+
positions were measured on the plant rather than taken from documentation
313+
(2026-08-19, raw bytes from the hex log, `test/byte_monitor.py`): the value was
314+
changed, the byte watched, the value put back.
315+
316+
Command | written | byte | raw value
317+
:--- | ---: | ---: | :---
318+
SET15 `WaterPumpSpeed` | 100 → 110 → 100 | 45 | `0x65` → `0x6F` → `0x65`
319+
SET14 `WaterPump` | 0 → 1 → 0 | 4, bits 3+4 | `b01` → `b10` → `b01`
320+
321+
**TOP103 is a duty limit, not a speed.** With the pump running, TOP92
322+
`Pump_Duty` followed the limit exactly - 100 gave duty 100 at 2300 rpm and
323+
11.95 l/min, 80 gave duty 80 at 1500 rpm and 6.93 l/min. The command name
324+
`WaterPumpSpeed` is misleading and stays as it is only for compatibility. The
325+
actual values remain TOP65 `Pump_Speed` and TOP92 `Pump_Duty`; TOP103 is the
326+
ceiling for the latter.
327+
328+
**TOP104 reports the effective state**, not the request: when the mode went to
329+
`Fix`, the pump really started (TOP65, TOP1 and TOP92 all followed). The third
330+
state `Air purge` (`b11`) is **not** measured - producing it would mean starting
331+
an air purge routine on an intact plant. That entry rests on
332+
`ProtocolByteDecrypt.md`, the same way the second state of TOP102 does.
333+
334+
*Deutsch: Beide sind die fehlende Rückmeldung zu den zwei Pumpenkommandos, und
335+
beide Byte-Positionen sind an der Anlage ausgemessen statt aus Unterlagen
336+
übernommen (2026-08-19, Rohbytes aus dem Hexlog mit `test/byte_monitor.py`):
337+
Wert verstellt, Byte beobachtet, zurückgestellt. **TOP103 ist eine
338+
Duty-Grenze, keine Drehzahl** - bei laufender Pumpe folgte TOP92 der Grenze
339+
exakt (100 → Duty 100 bei 2300 1/min, 80 → Duty 80 bei 1500 1/min). Der
340+
Kommandoname `WaterPumpSpeed` führt in die Irre und bleibt nur aus
341+
Kompatibilitätsgründen stehen. **TOP104 meldet den wirksamen Zustand**, nicht
342+
den Wunsch: Beim Umschalten auf `Fix` lief die Pumpe tatsächlich an. Der dritte
343+
Zustand `Air purge` ist NICHT gemessen - ihn herzustellen hieße, an einer
344+
intakten Anlage eine Entlüftungsroutine auszulösen.*
345+
307346
## Command Topics:
308347

309348
Published to `<prefix>/set/<Topic>`, e.g. `panasonic_heat_pump/set/Heatpump`.

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ keiner Zeit ein Leerwert (−128, −1) auf einem produktiven State-Topic.
555555

556556
## MQTT-Schnittstelle
557557

558-
90 State-Topics und 32 Set-Kommandos, Namen kompatibel zum Original-HeishaMon.
558+
92 State-Topics und 32 Set-Kommandos, Namen kompatibel zum Original-HeishaMon.
559559
Die vollständige Referenz mit Byte-Spalte und Wertebereichen steht in
560560
[`MQTT-Topics.md`](MQTT-Topics.md). Welches State-Topic ein Set-Kommando
561561
zurückliest — und welche vier Kommandos gar keine Rückmeldung haben —, steht in

‎SET-TOP-Zuordnung.md‎

Lines changed: 64 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# SET-TOP-Zuordnung
22

33
Welches State-Topic liest ein Set-Kommando zurück? Diese Datei beantwortet das
4-
für alle 32 Set-Kommandos und alle 90 State-Topics der Firmware 3.9.0 und hält
5-
fest, wo es kein Gegenstück gibt.
4+
für alle 32 Set-Kommandos und alle 92 State-Topics der Firmware 3.10.0 und
5+
hält fest, wo es kein Gegenstück gibt.
66

77
Wozu: Eine Steuerung, die schreibt, muss prüfen können, ob der Wert angekommen
88
ist. Die Wärmepumpe quittiert nichts — sie klemmt Werte außerhalb ihres
@@ -12,13 +12,13 @@ einzige Nachweis ist das Rücklesen des zugehörigen State-Topics. Wo diese
1212
Spalte leer bleibt, schreibt die Steuerung blind.
1313

1414
*In English: which state topic reads a set command back? This file maps all 32
15-
set commands and all 90 state topics of firmware 3.9.0 against each other and
15+
set commands and all 92 state topics of firmware 3.10.0 against each other and
1616
records where no counterpart exists. The heat pump acknowledges nothing and
1717
silently clamps out-of-range values, so reading the matching state topic back
1818
is the only proof a write arrived — where that column is empty, a controller
1919
writes blind. Tables are language-neutral; the notes are German.*
2020

21-
**Stand:** 2026-08-19, Firmware 3.9.0. Quelle sind ausschließlich die beiden
21+
**Stand:** 2026-08-19, Firmware 3.10.0. Quelle sind ausschließlich die beiden
2222
Tabellen im Code — `setCommands[]` in [`src/commands.cpp`](src/commands.cpp)
2323
und `stateTopics[]` in [`src/decode.cpp`](src/decode.cpp). Die Tabellen unten
2424
sind nicht von Hand gepflegt, sondern von
@@ -43,7 +43,7 @@ Byte 7).
4343
Zwei Eigenschaften des Protokolls tragen die ganze Auswertung:
4444

4545
* **Kommando- und Antworttelegramm benutzen dieselben Byte-Positionen.** Alle
46-
28 gefundenen Paare liegen auf identischer Position — Byte 38 schreibt die
46+
30 gefundenen Paare liegen auf identischer Position — Byte 38 schreibt die
4747
Heizanforderung und Byte 38 liest sie zurück, ohne eine einzige Ausnahme. Die
4848
Zuordnung ist damit nicht geraten, sondern abgelesen.
4949
* **Das Kommandotelegramm ist 110 Bytes lang** (`QUERYSIZE`, Indizes 0–109),
@@ -53,9 +53,9 @@ Zwei Eigenschaften des Protokolls tragen die ganze Auswertung:
5353

5454
Daraus ergibt sich die Zweiteilung des Telegramms: Bytes 4–106 tragen
5555
Einstellungen und spiegeln das Kommandotelegramm, ab Byte 110 kommen
56-
Ist-Zustände und Messwerte. Jedes der 28 Paare liegt unter Byte 110.
56+
Ist-Zustände und Messwerte. Jedes der 30 Paare liegt unter Byte 110.
5757

58-
## 1. Set-Kommandos mit Rückmeldung (28 von 32)
58+
## 1. Set-Kommandos mit Rückmeldung (30 von 32)
5959

6060
Die Spalte *Bits* zählt wie das Projekt: **Bit 1 ist das höchstwertige Bit**,
6161
`ganz` heißt, das Kommando belegt das volle Byte. *Art* sagt, ob das Topic
@@ -72,6 +72,8 @@ SET6 | `Z1CoolRequestTemperature` | 39 | ganz | TOP28 | `Z1_Cool_Request_Temp` |
7272
SET9 | `OperationMode` | 6 | ganz | TOP4 | `Operating_Mode_State` | teilweise ³
7373
SET10 | `ForceDHW` | 4 | 1+2 | TOP2 | `Force_DHW_State` | voll
7474
SET11 | `DHWTemp` | 42 | ganz | TOP9 | `DHW_Target_Temp` | voll
75+
SET14 | `WaterPump` | 4 | 3+4 | TOP104 | `Water_Pump_Mode` | voll ⁵
76+
SET15 | `WaterPumpSpeed` | 45 | ganz | TOP103 | `Pump_Duty_Max` | voll ⁵
7577
SET16 | `HeatDelta` | 84 | ganz | TOP23 | `Heat_Delta` | voll
7678
SET17 | `CoolDelta` | 94 | ganz | TOP24 | `Cool_Delta` | voll
7779
SET18 | `DHWHeatDelta` | 99 | ganz | TOP22 | `DHW_Heat_Delta` | voll
@@ -154,14 +156,52 @@ Als Regelgröße ist TOP101 `Heat_Cool_SW_State` zu nehmen.
154156
SET26 wird in Schritten zu 30 Minuten geschrieben, TOP98 meldet Minuten zurück:
155157
`TOP98 = SET26 × 30`. Ein Vergleich ohne diese Umrechnung schlägt fehl.
156158

157-
## 2. Set-Kommandos ohne Rückmeldung (4)
159+
### ⁵ Die zwei Pumpen-Rückmeldungen (neu in 3.10.0)
160+
161+
TOP103 und TOP104 sind die Rückmeldungen zu SET15 und SET14. Beide
162+
Byte-Positionen sind am 2026-08-19 an Stufe 1 im Hexlog ausgemessen worden statt
163+
aus Unterlagen übernommen — Wert verstellt, Rohbyte beobachtet, zurückgestellt
164+
([`test/byte_monitor.py`](test/byte_monitor.py)):
165+
166+
Kommando | geschrieben | Byte | Rohwert
167+
:--- | :--- | ---: | :---
168+
SET15 `WaterPumpSpeed` | 100 → 110 → 100 | 45 | `0x65` → `0x6F` → `0x65`
169+
SET14 `WaterPump` | 0 → 1 → 0 | 4, Bits 3+4 | `b01` → `b10` → `b01`
170+
171+
Zweite Kontrolle ganz ohne Schreibvorgang: Die beiden Stufen sind auf
172+
verschiedene Werte konfiguriert (100 und 125), und Byte 45 zeigte an Stufe 2
173+
entsprechend `0x7E`.
174+
175+
**TOP103 ist eine Duty-Grenze, keine Drehzahl.** Bei laufender Pumpe folgte
176+
TOP92 `Pump_Duty` der Grenze exakt:
177+
178+
Byte 45 als `X−1` | TOP92 `Pump_Duty` | TOP65 `Pump_Speed` | TOP1 `Pump_Flow`
179+
---: | ---: | ---: | ---:
180+
100 | **100** | 2300 1/min | 11,95 l/min
181+
80 | **80** | 1500 1/min | 6,93 l/min
182+
183+
Die Pumpe läuft im Handbetrieb also genau bis zur konfigurierten Obergrenze und
184+
nicht darüber. Der Kommandoname `WaterPumpSpeed` führt in die Irre und bleibt
185+
nur deshalb stehen, weil die Kaskadensteuerung darauf schreibt; die Ist-Werte
186+
sind weiter TOP65 und TOP92, TOP103 ist die Grenze zu TOP92.
187+
188+
**TOP104 meldet den wirksamen Zustand**, nicht den Wunsch: Beim Umschalten auf
189+
`Fix` lief die Pumpe tatsächlich an (TOP65, TOP1 und TOP92 zogen alle nach).
190+
Der dritte Zustand `Air purge` (`b11`) ist **nicht** gemessen — ihn herzustellen
191+
hieße, an einer intakten Anlage eine Entlüftungsroutine auszulösen. Er stützt
192+
sich auf `ProtocolByteDecrypt.md`, so wie der zweite Zustand von TOP102
193+
`External_SW_State`.
194+
195+
## 2. Set-Kommandos ohne Rückmeldung (2)
158196

159197
SET | Kommando | Byte | Bits | Lage
160198
:--- | :--- | ---: | :--- | :---
161199
SET12 | `ForceDefrost` | 8 | 7 | Byte 8 ist im Antworttelegramm unbelegt — kein Rücklesen möglich
162200
SET13 | `ForceSterilization` | 8 | 6 | dito
163-
SET14 | `WaterPump` | 4 | 3+4 | Antwortbyte am Gerät belegt (Auto und On) — **Lücke, direkt schließbar**, Abschnitt 4
164-
SET15 | `WaterPumpSpeed` | 45 | ganz | Antwortbyte am Gerät belegt — **Lücke, direkt schließbar**, Abschnitt 4
201+
202+
Byte 8 trägt im Antworttelegramm nichts — für diese beiden ist keine
203+
Rückmeldung möglich, das ist keine Lücke im Code. Die früher hier gelisteten
204+
SET14 und SET15 haben seit 3.10.0 ihr Rücklese-Topic, siehe Fußnote ⁵.
165205

166206
Für die beiden Force-Kommandos gibt es keinen Rückgabewert, wohl aber einen
167207
**Wirkungsnachweis**: Läuft die angestoßene Routine, meldet das ein
@@ -253,93 +293,13 @@ Kommandoname `WaterPumpSpeed` führt hier in die Irre, siehe Abschnitt 4.
253293

254294
## 4. Was sich schließen ließe
255295

256-
Nach Aufwand und Risiko geordnet. Die ersten beiden sind je eine Zeile in
257-
`decode.cpp` und am Gerät ausgemessen — sie ergänzen nur die Leseseite, am
258-
Schreibpfad ändert sich nichts. Erst der dritte Punkt fasst eine laufende
259-
Anlage an.
260-
261-
**1. Rücklesen für SET15 — `Pump_Duty_Max` auf Byte 45 (eine Zeile in
262-
`decode.cpp`).**
263-
264-
```c
265-
{103, 45, "Pump_Duty_Max", getIntMinus1, nullptr, Duty},
266-
```
267-
268-
Dazu `NUMBEROFTOPICS` um eins hoch; die Klartextliste `Duty` gibt es schon
269-
(TOP92). Kein Eingriff in den Schreibpfad. Zusammen mit Punkt 2 sind es zwei
270-
neue Zeilen und `NUMBEROFTOPICS` 92.
271-
272-
**Byte 45 ist am Gerät gemessen, nicht aus der Referenz übernommen**
273-
(2026-08-19, Rohbytes über den Hexlog mit
274-
[`test/byte_monitor.py`](test/byte_monitor.py)). Zwei Kontrollen: der Vergleich
275-
der beiden Stufen, die verschiedene Werte konfiguriert haben, und eine
276-
Änderung an Stufe 1 in beide Richtungen.
277-
278-
Messung | `set/WaterPumpSpeed` | Byte 45 roh | Byte 45 als `X−1` | Byte 95 als `X−128`
279-
:--- | ---: | ---: | ---: | ---:
280-
Stufe 1, Ausgangslage | 100 | `0x65` | **100** | 20
281-
Stufe 2, Ausgangslage | 125 | `0x7E` | **125** | 20
282-
Stufe 1, auf 110 gesetzt | 110 | `0x6F` | **110** | 20
283-
Stufe 1, zurück auf 100 | 100 | `0x65` | **100** | 20
284-
285-
Damit ist belegt: Byte 45 trägt den Wert, die Umrechnung ist `X−1`, und die
286-
Flanke folgt dem Kommando in beide Richtungen — beim Umschalten stand sie im
287-
selben Mitschnitt (ein Telegramm mit dem alten, die folgenden mit dem neuen
288-
Wert). Byte 95 blieb über alle vier Messungen unverändert bei 20 und ist die
289-
Heiz/Kühl-Umschalttemperatur TOP79.
290-
291-
**Der Wert ist ein Duty, keine Drehzahl** — und auch das ist gemessen, nicht
292-
geschlossen. Bei laufender Umwälzpumpe (Wärmepumpe stand, Pumpe über SET14 von
293-
Hand eingeschaltet) folgte TOP92 `Pump_Duty` der Grenze aus Byte 45 unmittelbar:
294-
295-
Byte 45 als `X−1` | TOP92 `Pump_Duty` | TOP65 `Pump_Speed` | TOP1 `Pump_Flow`
296-
---: | ---: | ---: | ---:
297-
100 | **100** | 2300 1/min | 11,95 l/min
298-
80 | **80** | 1500 1/min | 6,93 l/min
299-
300-
Die Pumpe läuft im Handbetrieb also genau bis zur konfigurierten Obergrenze und
301-
nicht darüber; Drehzahl und Durchfluss gehen mit. `Pump_Duty_Max` ist damit die
302-
Grenze zu TOP92, nicht dessen Ersatz — die Ist-Werte stehen weiter in TOP65 und
303-
TOP92. Der Kommandoname `WaterPumpSpeed` führt in die Irre; ob er auf
304-
`MaxPumpDuty` geändert wird, ist eine Entscheidung über die Kompatibilität der
305-
Topic-Namen und steht hier bewusst nicht offen, denn die Kaskadensteuerung
306-
schreibt heute auf den alten Namen.
307-
308-
Beim Nachschlagen in `ProtocolByteDecrypt.md`: Byte 45 trägt dort in der ersten
309-
Spalte die Nummer TOP95 — das ist die Topic-Nummer des Original-Projekts, keine
310-
Byte-Position.
311-
312-
**2. Rücklesen für SET14 — `Water_Pump_Mode` auf Byte 4 (eine Zeile in
313-
`decode.cpp`).**
314-
315-
```c
316-
{104, 4, "Water_Pump_Mode", getBit3and4, nullptr, WaterPumpMode},
317-
```
318-
319-
Dazu die Klartextliste `WaterPumpMode[] = {"Auto", "On", "Air purge", nullptr}`
320-
— sie deckt den Indexbereich `−1..2` des Dekodierers vollständig ab, wie es
321-
seit 3.9.0 für alle Listen gilt.
322-
323-
Am 2026-08-19 an Stufe 1 gemessen, bei stehender Wärmepumpe:
324-
325-
`set/WaterPump` | Byte 4 roh | Bits 3+4 | dekodiert | Pumpe
326-
---: | ---: | :--- | :--- | :---
327-
0 (Ausgangslage) | `0x55` | `01` | Auto | steht
328-
1 | `0x65` | `10` | **On** | läuft, 2300 1/min
329-
0 (zurück) | `0x55` | `01` | Auto | steht
330-
331-
Das Antwortbyte führt das Feld also, und der Wert `0x65` deckt sich mit der
332-
Referenz („Water pump on=65"). Dass die Pumpe dabei tatsächlich anlief, ist
333-
über TOP65, TOP92 und TOP1 belegt — das Bitfeld meldet keinen Wunsch, sondern
334-
den wirksamen Zustand.
335-
336-
**Ungemessen bleibt `Air purge`** (`b11`, laut Referenz `0x75`). Diesen Zustand
337-
zu erzeugen hieße, an einer intakten Anlage eine Entlüftungsroutine
338-
auszulösen — dafür gibt es keinen Anlass. Der Eintrag in der Klartextliste
339-
stützt sich auf die Referenz, so wie der zweite Zustand von TOP102
340-
`External_SW_State`, der an dieser Anlage ebenfalls nicht herstellbar ist.
296+
**Erledigt in 3.10.0:** die Rückmeldungen für SET14 und SET15 (TOP103
297+
`Pump_Duty_Max`, TOP104 `Water_Pump_Mode`) — je eine Zeile in `decode.cpp`,
298+
beide Byte-Positionen vorher am Gerät ausgemessen, Belege in Fußnote ⁵. Damit
299+
hat jedes Set-Kommando, für das es überhaupt ein Antwortbyte gibt, eine
300+
Rückmeldung. Offen bleibt:
341301

342-
**3. `Heating_Mode` / `Cooling_Mode` als Set-Kommando (Byte 28).**
302+
**1. `Heating_Mode` / `Cooling_Mode` als Set-Kommando (Byte 28).**
343303
Der größte praktische Gewinn. Heute muss beim Ausfall der Kaskadensteuerung
344304
jemand ans Bedienterminal und von Direkt- auf Kurvenbetrieb umschalten — die
345305
Kurvenwerte werden dafür schon vorgehalten (SET27–SET34). Mit einem Set-Kommando
@@ -349,14 +309,17 @@ mit TOP76/TOP81 bereits vorhanden, der Nachweis also gratis.
349309
Vorher zu klären, in dieser Reihenfolge:
350310

351311
* Nimmt die Wärmepumpe Byte 28 überhaupt an? Ein Schreibversuch mit
352-
anschließendem Rücklesen von TOP76 beantwortet das in einem Durchgang.
312+
anschließendem Rücklesen von TOP76 beantwortet das in einem Durchgang —
313+
dasselbe Vorgehen wie bei den Pumpen-Bytes, nur dass hier ein *Kommando*
314+
erprobt wird und nicht bloß eine Zuordnung.
353315
* Byte 28 trägt beide Modi (Heizen Bits 7+8, Kühlen Bits 5+6). Die Masken
354316
müssen bitgenau greifen, sonst schaltet ein Kühl-Kommando die Heizung mit um
355317
— genau der Fehler, den 3.1.0 beseitigt hat.
356-
* Ein Fehlversuch verstellt eine laufende Anlage. Nur bei stehender Anlage
357-
testen und den Ausgangswert vorher notieren.
318+
* **Ein Fehlversuch verstellt eine laufende Anlage.** Anders als bei den
319+
Pumpen-Messungen wird hier die Betriebsart der Heizung angefasst: nur bei
320+
stehender Anlage testen und den Ausgangswert vorher notieren.
358321

359-
**4. Der Rest aus Abschnitt 3a**, wenn ein konkreter Bedarf auftaucht. Jeder
322+
**2. Der Rest aus Abschnitt 3a**, wenn ein konkreter Bedarf auftaucht. Jeder
360323
dieser Werte ist eine Zeile in `setCommands[]`; die Arbeit steckt nicht im
361324
Code, sondern im Ausmessen des zulässigen Bereichs. Wie das geht und warum es
362325
nötig ist, steht in [`MQTT-Topics.md`](MQTT-Topics.md) — von den 21 Werten, die
@@ -395,7 +358,7 @@ Suche gilt als abgeschlossen, siehe [`MQTT-Topics.md`](MQTT-Topics.md).
395358
Am Gerät belegt sind die Kurven-Kommandos SET27–SET34 (Rücklesen an beiden
396359
Anlagen, 2026-08-10/11), SET3, SET4 und SET9 im laufenden Betrieb
397360
(2026-08-15/16) sowie SET14 auf Byte 4 und SET15 auf Byte 45, beide mit
398-
Änderung in beide Richtungen (2026-08-19, Abschnitt 4). Die übrigen Paare
361+
Änderung in beide Richtungen (2026-08-19, Fußnote ⁵). Die übrigen Paare
399362
stützen sich auf die identische
400363
Byte-Position, die bei jedem einzelnen der 28 Paare zutrifft. Wo Zweifel an
401364
einer Zuordnung bestehen, klärt sie [`test/byte_monitor.py`](test/byte_monitor.py)

‎src/decode.cpp‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ static const char *Percent[] = {"value", "&#37", nullptr};
5050
// vollstaendig gedeckt: b00 -> -1 -> leer, b01/b10/b11 -> 0/1/2 -> im Array.
5151
static const char *OffOnUnknown[] = {"Off", "On", "unknown", nullptr};
5252
static const char *HeatCoolActual[] = {"Heat", "Cool", "unknown", nullptr};
53+
// Betriebsart der Umwaelzpumpe (Byte 4, Bits 3+4). Drei Eintraege decken den
54+
// Indexbereich -1..2 von getBit3and4 vollstaendig ab. "Auto" und "Fix" sind am
55+
// 2026-08-19 an WP1 gemessen (Byte 4 wechselte 0x55 <-> 0x65, die Pumpe lief
56+
// dabei fix auf dem Max-Duty-Wert); "Air purge" stammt aus ProtocolByteDecrypt.md
57+
// und ist hier bewusst nicht nachgestellt worden - das haette an einer intakten
58+
// Anlage eine Entlueftungsroutine ausgeloest.
59+
static const char *WaterPumpMode[] = {"Auto", "Fix", "Air purge", nullptr};
5360

5461

5562
/*****************************************************************************/
@@ -168,6 +175,19 @@ const StateTopic stateTopics[NUMBEROFTOPICS] = {
168175
{100, 110, "Powerful_Mode_Active", getBit3and4, nullptr, OffOnUnknown},
169176
{101, 110, "Heat_Cool_SW_State", getBit5and6, nullptr, HeatCoolActual},
170177
{102, 110, "External_SW_State", getBit7and8, nullptr, OffOnUnknown},
178+
// Die beiden Ruecklesewerte zu SET15 und SET14 (3.10.0). Beide Bytes sind am
179+
// 2026-08-19 an WP1 ausgemessen worden, statt sie aus der Referenz zu
180+
// uebernehmen - Wert verstellt, Rohbyte im Hexlog beobachtet, zurueckgestellt:
181+
// Byte 45: set/WaterPumpSpeed 100 -> 110 -> 100 liess das Byte 0x65 -> 0x6F
182+
// -> 0x65 wandern; Stufe 2 zeigt mit 125 entsprechend 0x7E. Es ist die
183+
// MAX-DUTY-Grenze, keine Drehzahl: bei laufender Pumpe folgte TOP92
184+
// Pump_Duty der Grenze exakt (100 -> 100, 80 -> 80, Drehzahl 2300 -> 1500).
185+
// Deshalb Pump_Duty_Max und nicht der irrefuehrende Kommandoname.
186+
// Byte 4: set/WaterPump 0 -> 1 -> 0 liess die Bits 3+4 b01 -> b10 -> b01
187+
// wandern, die Pumpe lief dabei wirklich an (TOP65 2300 1/min, TOP1
188+
// 11,95 l/min). Das Feld meldet also den wirksamen Zustand.
189+
{103, 45, "Pump_Duty_Max", getIntMinus1, nullptr, Duty},
190+
{104, 4, "Water_Pump_Mode", getBit3and4, nullptr, WaterPumpMode},
171191
};
172192

173193
// Haelt NUMBEROFTOPICS (Array-Groesse von actual_data) und die Tabelle zusammen

‎src/decode.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// Anzahl der Zeilen in stateTopics[]. Wird als Array-Groesse gebraucht (siehe
88
// actual_data in HeishaMon.cpp) und muss deshalb eine Konstante sein - dass sie
99
// zur Tabelle passt, sichert ein static_assert in decode.cpp ab.
10-
constexpr unsigned int NUMBEROFTOPICS = 90;
10+
constexpr unsigned int NUMBEROFTOPICS = 92;
1111

1212
#define MAXVALUELEN 16 // longest payload value incl. terminator (e.g. "No error", "-123.75")
1313

0 commit comments

Comments
 (0)