Skip to content

feat(camera): answer the robot's fwapi/createca TURN request for live video (#18) - #144

Merged
Lash-L merged 2 commits into
Python-roborock:mainfrom
cptntrps:feat/camera-turn-createca
Oct 12, 2026
Merged

Lash-L merged 2 commits into
Python-roborock:mainfrom
cptntrps:feat/camera-turn-createca

Conversation

@cptntrps

@cptntrps cptntrps commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Follows up on #18, where @Lash-L invited a PR after we both reached the same conclusion from the firmware.

What this does

When the app requests a camera preview, the firmware fetches a TURN/STUN configuration from a fwapi endpoint (.../fwapi/createca) before starting the WebRTC session. With no handler the request fell through to the catchall, so the robot never got TURN credentials and start_camera_preview returned -10012 / request turnserver failed.

This adds a routes/fw/createca.py handler that answers with a plain-JSON TURN credential body, driven by a new optional [turn] config section.

Behaviour / safety

  • Off by default. With [turn].enabled = false (the default) the request still falls through to the catchall, so there is no behaviour change for anyone not running a TURN server.
  • The response carries both the legacy user/pwd names (in data) and the ICE-style username/credential names (in result), so either firmware parser is satisfied.

Region requirement

As you noted in #18, the firmware derives the fwapi host from region[:15] + "iot.roborock.com", so the camera needs an onboarding region of 14 characters or fewer plus a trailing / for the createca host to resolve to the server. This is documented in docs/camera.md; the onboarding UI/CLI warning you mentioned is a natural companion on your side.

Verification

Verified end to end on a Saros 10R (roborock.vacuum.a144, FCC/US firmware): with coturn configured the robot completes the WebRTC handshake and a go2rtc roborock:// consumer receives frames. The createca shape and the region-host rule look like general firmware behaviour; the two-key activation needed to arm the camera is model-specific and documented.

Changes

  • config.py: [turn] section (enabled/host/port/username/password/realm/ttl)
  • routes/fw/createca.py + registration in endpoint_rules.py
  • ServerContext: TURN fields (default off)
  • docs/camera.md, known_limitations.md, config.example.toml
  • tests/test_fw_createca.py (payload shape, path variants, disabled fallback)

Full suite: 298 passed locally.

Happy to adjust naming/placement or split anything out.

@Lash-L

Lash-L commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Hey @cptntrps This looks good to me! I'm going to merge it in and will do some work on top of it

I will make it work with the HA addon, update onboarding, and make some other small tweaks.

TYSM!

… video (Python-roborock#18)

When the app requests a camera preview, the firmware fetches a TURN/STUN config
from a fwapi endpoint before starting the WebRTC session. The host is derived from
the onboarding region as region[:15] + "iot.roborock.com", so a short region
resolves it to this server. Without a handler the request hit the catchall and the
robot returned -10012 / "request turnserver failed".

This adds a routes/fw/createca.py handler that answers with a plain-JSON TURN
credential body (both legacy user/pwd and ICE username/credential aliases), driven
by a new optional [turn] config section. With [turn].enabled = false (the default)
the request still falls through to the catchall, so there is no behaviour change
for anyone not running a TURN server.

Verified end to end on a Saros 10R (roborock.vacuum.a144): with coturn configured,
the robot completes the WebRTC handshake and a go2rtc roborock:// consumer receives
frames. The createca shape and the region-host rule look like general firmware
behaviour; the two-key activation needed to arm the camera is model-specific and
documented in docs/camera.md.

- config: [turn] section (enabled/host/port/username/password/realm/ttl)
- route: routes/fw/createca.py + registration in endpoint_rules.py
- context: TURN fields on ServerContext (default off)
- docs: docs/camera.md; known_limitations updated; config.example.toml
- tests: tests/test_fw_createca.py (payload shape, path variants, disabled fallback)
@cptntrps

Copy link
Copy Markdown
Contributor Author

Thanks a lot @Lash-L, I'm really happy to contribute to this project!

One small request before you merge: the commit on this PR has a placeholder author email (user@example.com) from a misconfigured git identity on my side. GitHub links that email to an unrelated account, so the merged commit would be credited to someone else instead of me.

Is it OK if I force-push the branch with only the author fixed (to cptntrps)? The code and file tree stay identical, it's just one commit with a new author. If you'd rather not deal with a force-push, adding Co-authored-by: cptntrps <50712262+cptntrps@users.noreply.github.com> on the squash merge works for me too.

I'll wait for your OK before I push anything.

@Lash-L

Lash-L commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Yes, that is fine! @cptntrps Thanks for asking

@cptntrps
cptntrps force-pushed the feat/camera-turn-createca branch from 9086b9b to 0f1df07 Compare October 10, 2026 18:16
@Lash-L
Lash-L merged commit 095c7c8 into Python-roborock:main Oct 12, 2026
1 check passed
Lash-L added a commit that referenced this pull request Oct 12, 2026
- Keep package and add-on versions at 1.2.1 and leave the unused beta add-on
  untouched; version bumps and image publishing belong in a release PR.
- Drop the never-released HA turn_enabled option and show turn_mode
  (default disabled) in the add-on options. config.toml still reads the
  [turn] enabled = true form from #144 as external mode.
- Lowercase turn.mode before choosing the provided-mode username default.
- createca docstring and known limitations now describe the model-specific
  bootstrap host (a144 country_domain, a87 token.r) instead of a single rule.
- Remove stray blank lines and a placeholder-free f-string.
Lash-L added a commit that referenced this pull request Oct 12, 2026
* feat(turn): add Home Assistant add-on TURN options and onboarding region notices

* fix(ha,gui): avoid reserving unused turn ports in addon and wire camera_domain in web ui

* fix(onboarding,addon): validate camera domain hostname format and expose turn_ttl in addon schema

* fix(onboarding): warn when 15-character region lacks trailing slash for camera bootstrap

* feat(camera): provide TURN relay and validate model-specific bootstrap

* style: remove trailing blank lines in camera configuration

* chore(camera): drop release bumps and tidy TURN follow-ups from #144

- Keep package and add-on versions at 1.2.1 and leave the unused beta add-on
  untouched; version bumps and image publishing belong in a release PR.
- Drop the never-released HA turn_enabled option and show turn_mode
  (default disabled) in the add-on options. config.toml still reads the
  [turn] enabled = true form from #144 as external mode.
- Lowercase turn.mode before choosing the provided-mode username default.
- createca docstring and known limitations now describe the model-specific
  bootstrap host (a144 country_domain, a87 token.r) instead of a single rule.
- Remove stray blank lines and a placeholder-free f-string.
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