Skip to content

Fix battery scaling and fan step, add airflow-percentage register - #6

Open
madsvonqualen wants to merge 1 commit into
JonasPed:masterfrom
madsvonqualen:fix-battery-and-fan-step-registers
Open

Fix battery scaling and fan step, add airflow-percentage register#6
madsvonqualen wants to merge 1 commit into
JonasPed:masterfrom
madsvonqualen:fix-battery-and-fan-step-registers

Conversation

@madsvonqualen

Copy link
Copy Markdown

Fix battery scaling and fan step, add airflow-percentage register

Three related read-decoding fixes, all verified against a live Danfoss Air CCM
(Danfoss Air A2, HW rev. 18.15, SW rev. 2.48).

1. Battery is a raw 0–100 byte, not a 0–255 value

battery_percent (0x01 04 03 0f) was decoded via _read_percent, i.e.
raw * 100 / 255. The register already reports a percentage directly, so a full
battery pack (raw 100) was reported as ≈39 %. Fixed by reading it as a
plain byte.

Confirmed by measuring the Air Dial's 4×AAA pack:

Pack voltage Raw byte Old (×100/255) New (raw)
6.48 V (fresh, 4×1.62 V) 100 39.22 100
5.36 V (depleted) 44 17.25 44

2. fan_step is the stored manual step (1–10), not step×10

The 0.3.0 "fan step in percent" change multiplied the step register
(0x01 04 15 61) by 10 to approximate airflow. But the step is a 1–10 value,
and the real airflow percentage lives in a separate register
(0x00 04 17 81). On the live unit, step 5 coincides with an airflow of
54 % — and 5 × 10 = 50 ≠ 54, so the ×10 was only an approximation.

fan_step now returns the raw manual step, and…

3. New fan_speed_percent register

…the actual airflow percentage is exposed as fan_speed_percent
(0x00 04 17 81, a raw 0–100 byte). Both values are now available and correct,
serving both the default use case and the one from #5.

Live verification

read_all() from the patched client against the CCM:

battery_percent   = 100        (was 39.22)
fan_step          = 5          (was 50)
fan_speed_percent = 54         (new)
humidity          = 61.18      (unchanged: still rescaled)
roomTemperature   = 23.85      (unchanged)
supply_fan_speed  = 1644 / exhaust_fan_speed = 1976
bypass = True / automatic_bypass = True / operation_mode = demand

Tests

Adds tests/test_danfossclient.py — 16 cases covering the changed decoding
(battery raw, fan_step raw, fan_speed_percent) and guarding the unchanged paths
(humidity/filter still rescaled, temperatures in centidegrees, bypass truthiness,
automatic_bypass inversion). All pass on Python 3.14 / pytest 9.

Compatibility note

battery_percent and fan_step now return corrected values, so downstream
consumers that compensated for the old scaling (e.g. multiplying fan_step back
down, or treating battery as 0–39) should drop those workarounds. Would you be
able to cut a release (e.g. 0.4.0) once merged? The Home Assistant integration
will then bump to it.

Battery (0x01 04 03 0f) is a plain 0-100 byte, not a 0-255 value: it was
rescaled by 100/255, so a full pack read ~39% instead of 100%. Read it
directly instead.

fan_step (0x01 04 15 61) is the stored manual step (1-10). The 0.3.0
"fan step in percent" change multiplied it by 10 to approximate airflow,
but the real airflow percentage is a separate register (0x00 04 17 81).
Expose that as fan_speed_percent and return the raw manual step for
fan_step, so both values are available and correct.

Verified against a live Danfoss Air CCM: battery 100 (raw) vs 39.22
(rescaled); fan_step 5 while airflow reads 54% (5*10=50 != 54, confirming
the *10 was an approximation). Adds unit tests for the decoding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@JonasPed

JonasPed commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Thanks for the PR. I will however not sit in front of a computer for the next couple of weeks. I will look at it when I am at a computer again.

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