Skip to content

Add Baichuan fallback for GetOsd/SetOsd - #183

Open
andrewvenson wants to merge 2 commits into
starkillerOG:mainfrom
andrewvenson:baichuan-set-osd
Open

Add Baichuan fallback for GetOsd/SetOsd#183
andrewvenson wants to merge 2 commits into
starkillerOG:mainfrom
andrewvenson:baichuan-set-osd

Conversation

@andrewvenson

Copy link
Copy Markdown

Summary

  • Adds a Baichuan implementation of GetOsd/SetOsd so Host.set_osd() also works on devices that are only reachable over the Baichuan protocol (bc_only=True, i.e. no HTTP(s) API available).
  • GetOsd now decodes the Baichuan XML response into the same _osd_settings[channel] shape the HTTP JSON API produces, so Host.set_osd() itself needed no changes — it works transparently regardless of which protocol is in use underneath.
  • Adds a SetOsd Baichuan command (cmd_id 45) that fetches the current OSD XML (cmd_id 44), patches only the fields being changed, and writes it back.

Position encoding

The HTTP JSON API expresses OSD position as a string ("Upper Left", "Bottom Center", etc, see validate_osd_pos), but Baichuan expresses it as raw topLeftX/topLeftY integers. There's no official documentation for this encoding, so I derived it empirically by cycling through all 6 HTTP positions and reading back the resulting Baichuan XML values:

Position topLeftX topLeftY
Upper Left 1 1
Upper Right 65536 1
Top Center 65537 1
Bottom Center 65537 65536
Lower Left 1 65536
Lower Right 65536 65536

Confirmed identical across two different device types:

  • Reolink E1 Pro (firmware v3.1.0.4417_2412122130)
  • Reolink Video Doorbell WiFi (firmware v3.0.0.4662_2508071282)

Usage

No API changes required — existing code works unmodified, including on bc_only hosts:

from reolink_aio.api import Host

host = Host(ip, username, password, bc_only=True)  # works the same with bc_only=False
await host.get_host_data()
await host.set_osd(0, namePos="Upper Left", datePos="Lower Right", enableWaterMark=True)

Testing

  • Verified end-to-end against both devices above with bc_only=True: enable/disable, name text, position, and watermark toggle all round-trip correctly and were cross-checked against the raw Baichuan XML readback.
  • black, isort, flake8, and pylint (10.00/10) all pass on the changed file; mypy reports no issues.

…ings map to Baichuan topLeftX/topLeftY via OSD_POS_HTTP_TO_BC, derived empirically by cycling all 6 HTTP OSD positions and reading back the resulting coordinates over Baichuan.
Populate _osd_settings from the Baichuan XML response and add a Baichuan SetOsd command so Host.set_osd() also works when bc_only=True (no HTTP(s)API available). OSD positions are exposed over Baichuan as raw topLeftX/topLeftY coordinates instead of the HTTP API's named positions ("Upper Left", "Bottom Center", etc), so OSD_POS_HTTP_TO_BC/ OSD_POS_BC_TO_HTTP translate between the two. The coordinate mapping was derived empirically by cycling all 6 HTTP OSD positions and reading back the resulting Baichuan coordinates, and confirmed to match across two different device types (Reolink E1 Pro, Reolink Video Doorbell Wifi).
@starkillerOG

Copy link
Copy Markdown
Owner

Why do you need this fallback?

@andrewvenson

andrewvenson commented Jul 15, 2026

Copy link
Copy Markdown
Author

Why do you need this fallback?

The hope is to limit the amount of attack vectors on my network. I would rather use the baicuan protocol to update settings on my cameras rather than temporarily opening up http/s ports to make changes.

Sometimes after power outages the osd settings are erased. I have a cron that targets this branch to set the osd on the cams on a daily basis.

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