Files
ha_xiaomi_home/custom_components
zealllot bf38d93068
Some checks failed
Tests / check-rule-format (push) Has been cancelled
Validate / validate-hassfest (push) Has been cancelled
Validate / validate-hacs (push) Has been cancelled
Validate / validate-lint (push) Has been cancelled
Validate / validate-setup (push) Has been cancelled
fix(mips): return None instead of raising when getDevList times out (#1793)
`MipsLocalClient.get_dev_list_async()` raises `MIoTMipsError` when the
central hub gateway does not answer in time, but both of its callers in
`miot_client.py` are written to handle a `None` return:

    gw_list = await mips.get_dev_list_async(payload=json.dumps(payload))
    if gw_list is None:
        ...
        return

Because the coroutine raises instead, those `None` branches are dead code
and the exception escapes as an unretrieved task exception.

The consequence is severe for `__refresh_gw_devices_with_group_id_async()`,
which is the only place that populates `_device_list_gateway` in full (it
runs when the local mips connection comes up, and queries every device with
no `filter`). One unreachable device is enough to time out the whole query,
and when it does:

  - `_device_list_gateway` stays empty, so every device keeps `gw_state`
    False;
  - the retry in the `gw_list is None` branch never runs, so it never
    recovers.

`__check_device_state()` is `cloud or gateway or lan`, so with the gateway
path silently dead the cloud becomes the only source of truth. The next
time the cloud MQTT connection drops, every device is marked offline at
once, even though the central hub gateway is connected and healthy the
whole time.

Observed on a 256-device / 2697-entity setup: an unplugged rice cooker
(8 entities, permanently unavailable) caused 18 of 30 such exceptions over
four days. Each cloud MQTT `Connection reset by peer` then took all 2643
gateway-backed entities offline until the cloud reconnected.

Returning `None` makes the existing caller logic work as written: the
failure is logged and, for the full refresh, retried until it succeeds.
`MIoTMipsError` remains in use elsewhere in the file, and the return type
is widened to `Optional[dict[str, dict]]` on the abstract method and on
`MipsCloudClient` to match.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-24 13:06:18 +08:00
..