- 🔴 P1 — Bug / broken functionality
- 🟠 P2 — Important improvement
- 🔵 P3 — Nice to have
- ⚪ P4 — Research / exploration
- 🔴 Room-specific cleaning still needs on-device verification —
clean_rooms_miot()now preloadssiid 4 piid 10clean-extend-dataand then calls officialsiid 2 aiid 3, but actual X20+ hardware behavior still needs confirmation after this sequence change. (Updated 2026-04-08) - 🔴 FIXED:
set_fan_speed()was writing to siid 2 piid 2 (device fault, read-only!) instead of piid 3 (mode/fan). This means everyxiao speed setcommand was attempting to write a fault code. Alsostatus()was mapping piid 2 (fault) →fan_speeddisplay, causing garbage values. Fixed 2026-03-31. - 🔴 FIXED:
set_water_level()was writing to siid 18 piid 1 (mop-life-level, READ-ONLY %) instead of siid 4 piid 5 (mop-mode, 1=Low, 2=Medium, 3=High). Every water level command was corrupting mop consumable tracking. Alsowater_level()returned a stub string instead of reading from the device. Fixed 2026-04-02. - 🔴 FIXED:
status()mapped state 13 → "In Dock" but official MIoT spec says 13 = "Charging Completed". Fixed 2026-04-02.
- ⚪ Map extraction — MITM Mi Home app traffic to find decryption key for cloud map data
- ⚪ Room IDs verification — map room IDs to actual room names from Mi Home app
- ⚪ clean-logs (siid 12) corrected from official miot-spec.org JSON (2026-04-07):
- piid 1 =
first-clean-time(unix timestamp) — NOTlast-clean-time - piid 2 =
total-clean-time(minutes) - piid 3 =
total-clean-times(count) - piid 4 =
total-clean-area - Implication: current cloud API/spec does not expose a dedicated
last-clean-datefield for c102gl via siid 12; any real per-run history likely needs app/cloud log endpoints or map/log filenames from siid 4 piid 9.
- piid 1 =
- ⚪ vacuum-extend (siid 4) — fully mapped from official miot-spec.org JSON (2026-04-02):
- piid 4 = cleaning-mode (0=Quiet, 1=Standard, 2=Medium, 3=Strong) — READ-ONLY mirror of fan mode
- piid 5 = mop-mode / water level (1=Low, 2=Medium, 3=High) — WRITABLE ✅ Now implemented
- piid 6 = waterbox-status (0=No, 1=Yes) — reads whether water box is attached
- piid 7 = task-status (uint8 0-255) — unknown semantics
- piid 10 = clean-extend-data (string, write-only) — likely the room cleaning JSON param!
- piid 11 = break-point-restart (0=Off, 1=On) — resume after charging — writable
- piid 12 = carpet-press (0=Off, 1=On) — carpet boost — writable
- piid 16 = clean-rags-tip (0-120 minutes) — mop wash reminder — writable
- piid 17 = keep-sweeper-time (int32 minutes) — unknown
- piid 18 = faults (string) — extended fault string
- piid 27 = child-lock (0=Off, 1=On) — writable
- piid 34 = smart-wash-switch (0=Off, 1=On) — smart mop wash
- piid 36 = carpet-escape (1=Escape, 2=Auto) — carpet avoidance mode
- ⚪ Room cleaning deep dive: Official spec:
siid 2 aiid 3 = start-room-sweep, in=[piid 4 (Room IDs string)]. The piid 4 (room-ids) hasaccess: []meaning NO standalone read/write — it only works as an action param. Next step: testclean_rooms_miot()with piid 4 value as comma-separated string like "3,8,7,6". Also tryclean-extend-data(siid 4 piid 10) as alternative path — write JSON before calling start-sweep. - ⚪ Room cleaning research update (2026-04-08):
- Official spec page for
xiaomi.vacuum.c102glstill points tosiid 2 aiid 3(start-room-sweep) with room IDs passed aspiid 4string. hass-xiaomi-miotREADME example shows Dreame/Xiaomi custom room cleaning viasiid 4 aiid 1with paramspiid 1 = 18andpiid 10 = clean-extend-data, whereclean-extend-datais JSON underselects.dreame-vacuumissue #910 logs show theselectsrows encode at least room id, repeat count, fan mode, water mode, and explicit order: e.g.[[1,1,3,1,1],[3,1,3,1,2], ...].openHABmiio binding docs list bothvacuum-start-room-sweepandvacuum-extend-start-cleanactions forxiaomi.vacuum.c102gl, which supports the idea that both paths exist on X20+.- Community reports still describe
code=0/ accepted actions that do nothing, so success responses alone are not proof of movement.
- Official spec page for
- ⚪ X20+ / c102gl community notes (2026-04-10):
hass-xiaomi-miotissue#2767reports X20+ room-cleaning action (siid 2 aiid 3) still returning accepted responses while not actually starting room jobs for some users; reinforces thatcode=0is not enough without on-device movement verification.python-miioissue#2071tracks new X20 Max model gaps (xiaomi.vacuum.d109gl) and timeout/auth pain in HA stacks; X20 family support is still uneven across ecosystem tools.- Xiaomi Cloud Map Extractor issue
#697continues to show cloud login/session fragility (captcha/2FA/token churn), supporting our token-refresh-first strategy. - No clear Valetudo support signal for
xiaomi.vacuum.c102glturned up in this pass; keep this as watch-only research, not an actionable integration path yet.
- ⚪ Dashboard diagnostics UX research (2026-04-21):
home-assistant/frontenduses native HTML<details>/<summary>for dense system-information and repair diagnostics blocks, which keeps advanced data accessible without overwhelming the default view.openhab/openhab-webuidocuments accordion lists specifically for collapsible technical sections, reinforcing that diagnostics/debug data should be progressively disclosed rather than always expanded.- For xiao, the lowest-risk ship is to collapse the three verbose lower panels (Audio, Clean Log Raw, All Properties) by default while preserving their existing live data and DOM ids.
- ⚪ Session blocker (2026-04-08):
- This sandbox allows editing tracked files but denies writes inside
.git/.git add/git commitfailed withfatal: Unable to create '.git/index.lock': Operation not permitted, so this session could not create the requested local commit.
- This sandbox allows editing tracked files but denies writes inside
- ⚪ Test-suite findings (2026-04-09):
- Full
pytest tests/ -vcurrently still has 8 unrelated failures intests/test_cloud_vacuum.py. - Failing areas: status parsing / fan-speed decoding regressions, plus missing
total_clean_duration_displayinclean_history(). - These pre-existing failures are outside the token-refresh scope and should be handled as a separate bugfix pass.
- Full
- ⚪ Local UDP fallback — periodically check if vacuum becomes reachable locally
- ⚪ Valetudo compatibility — monitor if X20+ (c102gl) gets rooting support
- ⚪ Home Assistant integration — MQTT or REST sensor for HA
- ⚪ Notification system — Telegram alerts for cleaning complete, errors, consumable low
- ⚪ Energy estimation — track cleaning time × estimated wattage for power consumption
- ⚪ Floor plan editor — manual room layout in dashboard (drag & drop)
- ⚪ vacuum-extend service (siid 4) — investigate writable properties found in official spec:
- piid 5 = mop-mode (1=Low, 2=Medium, 3=High) — actual water level control!
- piid 11 = break-point-restart (0=Close, 1=Open) — resume after charging
- piid 12 = carpet-press (0=Close, 1=Open) — carpet boost
- piid 27 = child-lock (0=Close, 1=Open)
- piid 16 = clean-rags-tip (minutes, 0-120) — mop wash reminder interval
- ⚪ vacuum-extend piid 10 (clean-extend-data, write-only string) — this is likely the room cleaning param! Format: probably JSON with segments, fan level, water level. Worth testing with clean_rooms_miot().
Sources: Valetudo, python-miio, hass-xiaomi-miot, r/Xiaomi, r/homeassistant
- Zone cleaning with coordinates
- Virtual walls / no-go zones
- Carpet detection behavior
- Multi-floor map support
- Cleaning history heatmap
- Custom voice packs
- OTA firmware management
- ✅ Smart wash switch toggle — added first-class CLI support for
xiao settings smart-washplus cloud-service helpers for the X20+vacuum-extendsmart-wash-switchboolean (siid 4 piid 34), and included it in the dashboard settings snapshot API for programmatic consumers. Added TDD regression coverage for both the cloud property reads/writes and the new CLI command before implementation. Research notes: the local MIoT mapping already identifiedpiid 34as writable, the officialhome.miot-spec.com/spec/xiaomi.vacuum.c102glpage still exposes it undervacuum-extend, and adjacent ecosystem threads (al-one/hass-xiaomi-miot#2767,openhab/openhab-addons#17796) continue to reinforce that X20+ support remains cloud-centric, making another spec-backed boolean toggle a safer unattended release than room-cleaning experiments. (2026-04-26) - 🔜 Next planned item: Clean rags tip interval — expose
siid 4 piid 16(clean-rags-tip, 0-120 minutes) as a validated base-station maintenance setting once we lock down the safest CLI shape and value validation. (Planned 2026-04-26) - ✅ Advanced vacuum-extend settings toggles — added first-class CLI support for
xiao settings resume-after-charge,xiao settings carpet-boost, andxiao settings child-lock, all backed by the official X20+ MIoTvacuum-extendbooleans (siid 4 piid 11/12/27). Added TDD regression coverage for both the cloud property reads/writes and the new CLI commands before implementing the feature. Research notes: the local MIoT mapping already identified these three properties as writable booleans, the officialhome.miot-spec.com/spec/xiaomi.vacuum.c102glpage still exposes them undervacuum-extend, and adjacent ecosystem threads (al-one/hass-xiaomi-miot#2767,openhab/openhab-addons#17796) continue to show X20+ users relying on cloud-only MIoT paths, which made CLI exposure of stable spec-backed toggles a safer unattended ship than more experimental room-cleaning work. (2026-04-25) - 🔜 Next planned item: Clean rags tip interval — expose
siid 4 piid 16(clean-rags-tip, 0-120 minutes) as a validated base-station maintenance setting once we lock down the safest CLI shape and value validation. (Planned 2026-04-26) - ✅ Sweep type decoding cleanup — removed the stale dashboard
sweep_typewording and now surfacedry_left_time_minexplicitly as dry-time-left in both Mission Control and CLI rich status output, including a drying-specific status tag. Added TDD regression coverage for the dashboard copy and formatter label before implementing the fix. Research notes: the officialmiot-spec.orgJSON forxiaomi.vacuum.c102glconfirmssiid 2 piid 5isdry-left-timein minutes,hass-xiaomi-miotexamples continue to useclean-extend-datafor room cleaning instead of any sweep-type property, andopenhabstill exposesvacuum-start-room-sweepplusvacuum-extend-start-clean, which reinforced that our old sweep-type label was legacy/spec drift rather than a real X20+ field. Also corrected the dashboard's lingering state-13 label toCharging Completedfor consistency with the already-fixed backend mapping. (2026-04-24) - ✅ Dashboard dark/light theme toggle — Mission Control now keeps the current dark glassmorphism default, but adds an explicit light theme switch in the header and persists the user's choice in local storage so daytime use is less fatiguing without re-theming every visit. Added TDD regression coverage for the toggle markup and persistence hook. Research notes: the local README already positions Mission Control as a day-to-day dashboard surface, MDN's
prefers-color-schemeguidance reinforced shipping named light/dark themes instead of ad-hoc color overrides, andhome-assistant/frontendpersistsselectedThemein browser storage with defensive fallbacks, which informed our saved-preference approach and storage guards. (2026-04-23) - ✅ CLI schedule default view + compact cadence labels —
xiao schedulenow shows the parsed schedule table directly without requiring the extralistsubcommand, and schedule cadence text now compacts common masks toEvery day,Weekdays,Weekends, andOne timefor faster scanning. Added TDD regression coverage for both the parser labels and the root CLI behavior. Research notes: local README/docs already positioned schedule viewing as a primary CLI workflow, and Home Assistant's schedule model explicitly treats weekdays as first-class recurrence data rather than a raw bitmask, which reinforced shipping human-readable cadence labels instead of the previous verbose day list. (2026-04-22) - ✅ Dashboard diagnostics cleanup — collapsed the lower-noise Audio, Clean Log (Raw), and All Properties panels by default using native
<details>/<summary>sections, while keeping the same content and live refresh hooks once expanded. Added a regression test that failed before the markup change and now locks the collapsed-by-default contract. (2026-04-21) - ✅ CLI rooms rename command — added
xiao rooms rename <id> <name>as a first-class command (same underlying behavior as alias set) so room naming flows are more discoverable. Added TDD regression test (TestCLIRooms::test_rooms_rename) that failed before command implementation and passes now. (2026-04-10) - ✅ Device list token auto-refresh —
XiaomiCloud.get_devices()now catchesTokenExpiredError, refreshes cloud tokens via browser CDP helper, and retries once before surfacing the error. This closes the remaining gap where setup/device listing could still fail on expired Xiaomi cloud sessions even though RPC/property helpers already retried. Added regression tests for both refresh-success and refresh-failure paths. (2026-04-09) - ✅ Room cleaning reliability improvement —
clean_rooms_miot()now preloadsvacuum-extendclean-extend-data(siid 4 piid 10) using aselectspayload derived from room order, repeat count, current fan mode, and current water mode, then calls the officialsiid 2 aiid 3room-sweep action. CLIxiao clean --room ... --repeat Nnow forwardsrepeatinto that MIoT path instead of silently dropping it. Added regression tests. Hardware verification still pending. (2026-04-08) - ✅ Clean history / first-clean-time mapping fix —
siid 12 piid 1was incorrectly treated aslast-clean-time, which madelast_clean_datestale/misleading. Official MIoT spec confirms siid 12 isclean-logs: piid 1 =first-clean-time, piid 2 =total-clean-time, piid 3 =total-clean-times, piid 4 =total-clean-area. Updatedclean_history(),last_clean(), and history scan output to exposefirst_clean_dateand correct aggregate totals instead of fake last-run fields. Added regression tests. (2026-04-07) - ✅ Water level MIoT property bug fix —
set_water_level()was writing to siid 18 piid 1 (mop-life-level, READ-ONLY %) instead of siid 4 piid 5 (mop-mode, writable). Official MIoT spec confirms: siid 4 piid 5 =mop-mode(1=Low, 2=Medium, 3=High). Also fixedwater_level()to actually read from the device instead of returning stub string. Added 7 new tests. (2026-04-02) - ✅ Status 13 corrected —
status()mapped state 13 → "In Dock" but official MIoT spec says 13 = "Charging Completed". Fixed with test. (2026-04-02) - ✅ MIOT_SPEC extended — Added mop-mode, break-point-restart, carpet-press, child-lock, clean-rags-tip, clean-extend-data to MIOT_SPEC dict. Updated module comments to reflect siid 4 = vacuum-extend (not clean-log). (2026-04-02)
- ✅ Fan speed MIoT property bug fix —
set_fan_speed()was writing to siid 2 piid 2 (device fault, read-only!). Official MIoT spec confirms: piid 2 = fault, piid 3 = mode/fan speed (0=Silent, 1=Basic, 2=Strong, 3=Full Speed). Fixed read and write paths. Added 5 new tests confirming correct piid usage. (2026-03-31) - ✅ Status fan_speed parsing corrected — was mapping piid 2 (fault code) to fan speed display. Now correctly reads piid 3 for fan speed and stores piid 2 as
fault_code. (2026-03-31) - ✅ MIOT_SPEC corrected —
fan_levelnow points to piid 3,fault_codeadded for piid 2,dry_left_timeadded for piid 5 (was wrongly calledsweep_type). (2026-03-31) - ✅ Dashboard history section: fixed "--" for zero/falsy values — added
total_clean_duration_displayfield toclean_history()(e.g. "2h 10min"), fixed JS to use??null-coalescing so0shows as0not--, fixed total-time label (was incorrectly appendinghto a minutes value). - ✅ Cloud mode control (all basic actions)
- ✅ Mission Control dashboard (glassmorphism, real-time)
- ✅ Water Tank Alert detection (state 21) + auto-reset
- ✅ Water tank level estimator (area-based)
- ✅ Mop consumable tracking + reset
- ✅ Network info in dashboard (IP, WiFi, RSSI, MAC)
- ✅ All 4 consumable resets (main brush, side brush, filter, mop)
- ✅ Full MIoT property scan (39 properties documented)
- ✅ Schedule parser with room names
- ✅ Base station controls (wash, dry, dust, eject)
- ✅ Fan speed / water level / volume / DND settings
- ✅ Token refresh via browser CDP