Origin
Companion issue to eman/esphome-alpha-hwr#43, filed against this repo because the same bug exists here — the ESPHome component is a line-for-line port of this client's ControlService (its source comments cite this file's line numbers directly), so it inherited the bug rather than introducing it.
Problem
start() and set_mode() never send the pump's actual/desired setpoint. They call _send_control_request(mode_val, start=True) with no setpoint, which falls back to _MODE_SUFFIX_MAP's default suffix bytes. Every mode's default suffix except DHW and Temperature Range is the same 4 bytes, bytes([0x45, 0x65, 0x70, 0x00]), which decodes as a big-endian IEEE‑754 float to exactly 3671.0:
>>> import struct
>>> struct.unpack(">f", bytes([0x45, 0x65, 0x70, 0x00]))[0]
3671.0
So calling start() (or set_mode(), which also calls _send_control_request(mode_val, start=True) with no setpoint) always commands the pump to run at 3671 RPM/3671 Pa-equivalent/etc, regardless of any setpoint previously written via set_constant_speed()/set_constant_pressure()/set_constant_flow().
Evidence
src/alpha_hwr/services/control.py:185-208 — start() calls self._send_control_request(mode_val, start=True), no setpoint arg.
src/alpha_hwr/services/control.py:347-368 — set_mode() likewise calls self._send_control_request(mode_val, start=True) with no setpoint.
src/alpha_hwr/services/control.py:235-286 — _send_control_request(): when setpoint is None, uses self._MODE_SUFFIX_MAP.get(mode_byte, bytes([0x45, 0x65, 0x70, 0x00])) (line 267-269).
src/alpha_hwr/services/control.py:146-165 — _MODE_BYTE_MAP/_MODE_SUFFIX_MAP: every mode except DHW (0x19) and Temperature Range (0x1B) shares the identical default suffix bytes([0x45, 0x65, 0x70, 0x00]) = 3671.0.
- Cross-repo bench confirmation: esphome-alpha-hwr#23 reports the pump running at ~3671 RPM whenever "Pump Enabled" is turned on, which is this exact code path (ported verbatim into
control_service.cpp's CLASS10_CONTROL_MAP).
- The same issue report also independently confirms a working alternative: GENIbus Class 3
START/STOP commands ([0x03, 0x81, 0x06] / [0x03, 0x81, 0x05]) turn the pump on/off without touching the setpoint at all, respecting whatever setpoint is already stored on the pump. This repo's own Register enum already has the relevant GENIbus command IDs defined but unused: src/alpha_hwr/constants.py:88-94 (STOP = 0x0305, AUTO = 0x0306, REMOTE = 0x0307), annotated # Class 3 Commands (not used in BLE captures).
Suggested fix
Either:
- Have
start() look up/track the current setpoint for the active mode and pass it explicitly to _send_control_request() instead of relying on the default suffix, or
- Switch
start()/stop() to the Class 3 START/STOP commands (command IDs 0x06/0x05), which don't require a setpoint at all and let the pump use whatever is already stored — this also avoids the enable-forces-a-value problem tracked in the companion force-enable issue.
References
Origin
Companion issue to eman/esphome-alpha-hwr#43, filed against this repo because the same bug exists here — the ESPHome component is a line-for-line port of this client's
ControlService(its source comments cite this file's line numbers directly), so it inherited the bug rather than introducing it.Problem
start()andset_mode()never send the pump's actual/desired setpoint. They call_send_control_request(mode_val, start=True)with nosetpoint, which falls back to_MODE_SUFFIX_MAP's default suffix bytes. Every mode's default suffix except DHW and Temperature Range is the same 4 bytes,bytes([0x45, 0x65, 0x70, 0x00]), which decodes as a big-endian IEEE‑754 float to exactly 3671.0:So calling
start()(orset_mode(), which also calls_send_control_request(mode_val, start=True)with no setpoint) always commands the pump to run at 3671 RPM/3671 Pa-equivalent/etc, regardless of any setpoint previously written viaset_constant_speed()/set_constant_pressure()/set_constant_flow().Evidence
src/alpha_hwr/services/control.py:185-208—start()callsself._send_control_request(mode_val, start=True), nosetpointarg.src/alpha_hwr/services/control.py:347-368—set_mode()likewise callsself._send_control_request(mode_val, start=True)with no setpoint.src/alpha_hwr/services/control.py:235-286—_send_control_request(): whensetpoint is None, usesself._MODE_SUFFIX_MAP.get(mode_byte, bytes([0x45, 0x65, 0x70, 0x00]))(line 267-269).src/alpha_hwr/services/control.py:146-165—_MODE_BYTE_MAP/_MODE_SUFFIX_MAP: every mode except DHW (0x19) and Temperature Range (0x1B) shares the identical default suffixbytes([0x45, 0x65, 0x70, 0x00])= 3671.0.control_service.cpp'sCLASS10_CONTROL_MAP).START/STOPcommands ([0x03, 0x81, 0x06]/[0x03, 0x81, 0x05]) turn the pump on/off without touching the setpoint at all, respecting whatever setpoint is already stored on the pump. This repo's ownRegisterenum already has the relevant GENIbus command IDs defined but unused:src/alpha_hwr/constants.py:88-94(STOP = 0x0305,AUTO = 0x0306,REMOTE = 0x0307), annotated# Class 3 Commands (not used in BLE captures).Suggested fix
Either:
start()look up/track the current setpoint for the active mode and pass it explicitly to_send_control_request()instead of relying on the default suffix, orstart()/stop()to the Class 3START/STOPcommands (command IDs0x06/0x05), which don't require a setpoint at all and let the pump use whatever is already stored — this also avoids the enable-forces-a-value problem tracked in the companion force-enable issue.References