Skip to content

Obstacle photos on Saros 20 Neo (a296): photo_name is None (36-byte records) and type: 0 full photo is not reassembled #991

Open

Description

@Killekon

Device: Roborock Saros 20 Neo (roborock.vacuum.a296), firmware 02.29.56. Home Assistant 2026.10.2 with python-roborock 7.12.0 and vacuum-map-parser-roborock 0.1.5. Local server (local_roborock_server), MQTT path.

1. photo_name is always None
map_data.obstacles_with_photo lists the obstacles correctly (x, y, type, description, confidence), but details.photo_name is None. That means ObstaclePhotoTrait.get_photo() cannot be used with parsed map data.

In the raw map, block type 15 on this model has 36-byte records:

  • bytes 0-2 x, 2-4 y (uint16 LE)
  • 4-6 type
  • 12-28 photo id as null-padded ASCII (e.g. 002OP8DjMLKGBRnX)

The map parser only reads photo_name when obstacle_size == 28 (RoborockMapDataParser._parse_obstacles() in vacuum-map-parser-roborock, not python-roborock itself), so this part may belong in https://github.com/PiotrMachowski/Python-package-vacuum-map-parser-roborock. I can open an issue there if you prefer. Reading rec[12:28].split(b"\x00")[0] gives ids that get_photo accepts. All 12/12 photos were returned.

2. type: 0 (full 640×480 frame) times out
get_photo with {"img_id": ..., "type": 0} makes the robot send a protocol 300 frame (ROBOROCK header: request id at 8-12, header size 16-18, gzip payload size 20-24, 65 232 bytes here), followed by a raw protocol-301 continuation frame (29 109 bytes) without the ROBOROCK prefix.

create_blob_response_decoder() only handles a single 301 frame. The request therefore times out, even though the data arrives. Concatenating the 300 frame and its continuation(s) until header_size + payload_size bytes are collected, then gunzipping, gives the usual block list. Block 3 is a 640×480 JPEG (about 94 kB).

type: 1 (285×285 crop, single 301 frame) works as implemented. Other types return an RPC error: type: 2 → {"code": -10007, "message": "not support"}, type: 3 → {"code": -10005, "message": "type is incorrect"}.

ioBroker.roborock (src/lib/PhotoManager.ts) handles the 300 + raw-stream case, for reference.

Workaround used: a wrapper around create_blob_response_decoder that buffers 300 + continuation frames, plus own parsing of block 15 for the ids. I can share it or test a fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions