Skip to content

Fix non-contiguous slots and slaves >= 32 in CCM15Device#16

Open
mephyu wants to merge 1 commit into
ocalvo:mainfrom
mephyu:fix-noncontiguous-slots
Open

Fix non-contiguous slots and slaves >= 32 in CCM15Device#16
mephyu wants to merge 1 commit into
ocalvo:mainfrom
mephyu:fix-noncontiguous-slots

Conversation

@mephyu

@mephyu mephyu commented Apr 23, 2026

Copy link
Copy Markdown

Two bugs in CCM15Device.py:

1. _fetch_data exits on the first empty slot.

for ac_name, ac_binary in data.items():
    if ac_binary == "-":
        break

A CCM15 is not guaranteed to have active units at slots 0..N. Tested against a production install with a0-a3 empty and a4-a21 populated (18 units): the loop exits at a0 and devices ends up empty. Downstream the Home Assistant integration loads as state: loaded with no entities and no error in the log, which is hard to diagnose.

Fix: continue on empty slots; derive ac_index from the XML key so devices is keyed by true slot number. Narrow try/except so a malformed payload can't crash the whole refresh.

2. async_set_state always writes the bitmask to ac0.

ac_id: int = 2**ac_index
url = ... + "&ac0=" + str(ac_id) + "&ac1=0" + ...

Slots 32-63 belong in ac1 per the controller's own cmd_aclist() in midea.js. 2**40 written to ac0 overflows silently and the command targets the wrong unit (or nothing).

Fix: split across ac0 (0-31) and ac1 (32-63).

Tests

Existing test_get_status_async used <ac1>/<ac2> tag names which do not match real CCM15 output (<a0>..<a63>). Fixed to use real names, added cases for non-contiguous slots and for slaves in the 32-63 range. All 8 tests pass locally.

Compatibility

No API change. Installs with contiguous slots starting at 0 see the same keying as before (ac_index from the key equals the previous counter value). Existing downstream code keeps working.

Verification

Live CCM15 (Midea OEM, 18 slaves at 4-21). Pre-patch: 0 devices decoded. Post-patch: 18 devices with correct ac_mode, fan_mode, temperature_setpoint, temperature, error_code. The >= 32 bitmask fix is by inspection against midea.js; I don't have hardware in that range.

_fetch_data exits on the first empty slot, so any CCM15 that does not
have its first active unit at slot 0 ends up returning an empty
CCM15DeviceState. Downstream the Home Assistant integration loads as
state: loaded but creates zero climate entities with no error.

async_set_state always writes the slave bitmask to ac0 and hard-codes
ac1=0. Slots 32-63 belong in ac1 per the controller's own cmd_aclist()
in midea.js; writing 2**40 into ac0 overflows silently.

Changes:

* _fetch_data: continue on empty slots; derive ac_index from the XML
  key so devices is keyed by real slot number. Narrow try/except so a
  malformed payload can't crash the whole refresh.
* async_set_state: split the bitmask across ac0 (0-31) and ac1 (32-63).
* tests: fix the existing test to use real <aN> tag names; add cases
  for non-contiguous slots and for slaves in the 32-63 range.

Verified on a live CCM15 with 18 slaves at 4-21. Pre-patch: 0 devices.
Post-patch: 18 devices with correct mode/fan/setpoint/temperature.
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.

1 participant