Skip to content

fix(scenes): return List<SceneOrder> from GET /user/scene/order - #211

Merged
Lash-L merged 1 commit into
Python-roborock:mainfrom
SmarthomeElektroniker:fix/scene-order-objects
Oct 30, 2026
Merged

Lash-L merged 1 commit into
Python-roborock:mainfrom
SmarthomeElektroniker:fix/scene-order-objects

Conversation

@SmarthomeElektroniker

Copy link
Copy Markdown
Contributor

Related: #189 (same finding on iOS 4.74, reported by mbrunno together with POST persistence)

Problem

The Android app (ISceneApi) reads the scene order as

GET user/scene/order?homeId=…[&duids=…]
→ ApiReturn<List<SceneOrder>>
SceneOrder = {"duid": String, "sceneIds": List<Long>}

Both ISceneApi methods on this path (with and without duids) use this return type. The server returned a flat list of scene ids:

{"success": true, "code": 200, "msg": "success", "data": [101, 102]}

The app fails with Expected start of the object '{', but had '['.

This is also the shape the cloud returns. import_web_inventory_from_cloud.py stores the cloud's /user/scene/order result verbatim, and an imported inventory contains

"scene_order": [{"duid": "<duid>", "sceneIds": [101, 102, 103]}]

scene_order() passes each entry through as_int(), which turns a dict into 0. So the imported order was silently ignored. create_scene and delete_scene dropped the dict entries whenever they rewrote the order.

Fix

  • scene_order_by_device() groups the ordered ids per device, and the route returns the cloud shape.
  • _flatten_stored_scene_order() reads both stored shapes (cloud objects and a flat id list). It is used by scene_order(), create_scene and delete_scene.
  • The duids filter and the homeId check work as before.

Contract fixture

tests/contracts/fixtures/ios_app_init_v4_59_02_anonymized.json expected the flat list for get_scene_order. I changed it to the object form. The fixture's expected responses look like server output: for example, post_app_info returns {"stored": true, …}, which is not a cloud response. Its seed scene_order is also a reduced flat list. #189 reports that iOS 4.74 ignores the flat list and falls back to the default order, and that the cloud returns [{"duid", "sceneIds"}]. Please double-check this with an iOS device if you can. I only have Android.

Tests

tests/test_scene_order.py

  • grouping per device, preserving the stored order
  • reading the cloud object form from the inventory
  • duids filter, foreign homeId gives []
  • delete_scene keeps the remaining order when the stored order is in cloud form

Full suite: passing, with the updated contract fixture.

Live check (Oct 2026): verified together with the other fixes of this series (all based on current main) against the Android app 4.60.06 and a real Q7 Max (roborock.vacuum.a38). The app called /user/scene/order and showed the scene tiles in the stored (cloud-imported) order, which the previous code had silently dropped. No errors. iOS not tested.

Overlap with #189

#189 proposes the same GET shape and dual-format reading, plus a POST /user/scene/order rule that persists the order. If you prefer that patch, this PR can be closed. The Android evidence above still applies to it. Alternatively, this PR is the smaller GET-only subset, and the POST part can follow on top of it.

🤖 Generated with Claude Code

The Android app (ISceneApi, GET user/scene/order with homeId and optional
duids) expects ApiReturn<List<SceneOrder>> with

    SceneOrder = {"duid": String, "sceneIds": List<Long>}

The server returned a flat list of scene ids, which fails in the app with
"Expected start of the object '{', but had '['".

This is also the shape the cloud returns: the cloud import stores the cloud
response verbatim, so imported inventories hold
[{"duid": ..., "sceneIds": [...]}]. scene_order() ignored those dict entries
(as_int(dict) == 0), and create/delete dropped them when rewriting the order.

- group the ordered scene ids per device in the route response
- read both the cloud object form and the flat form of the stored order
- update the iOS contract fixture's expected get_scene_order response

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Lash-L

Lash-L commented Oct 30, 2026

Copy link
Copy Markdown
Contributor

Looks correct, TY!

@Lash-L
Lash-L merged commit b376d0f into Python-roborock:main Oct 30, 2026
3 checks passed
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