Cloud API vs ONVIF/RTSP
For cameras behind bad uplink, ONVIF/RTSP on LAN (if you're on-site) beats cloud relay. For remote-only access, vendor cloud OpenAPI is the practical path: you get signed live URLs, cloud playback index, and push alarms. HA can consume MQTT from your bridge while the frontend plays HLS via a custom card or generic camera entity fed by a refreshed URL.
Don't put appSecret in configuration.yaml. Run a small bridge on your NAS/RPi that holds credentials, calls listDeviceDetailsByPage, bindDeviceLive, and setMessageCallback, then exposes MQTT + a REST sensor for the current play URL.
Install path
Place a custom integration under config/custom_components/vendor_camera/ (or HACS if you publish it). The integration should only store app_id and point to your bridge; secrets live in secrets.yaml:
# secrets.yaml
vendor_camera_app_id: YOUR_APP_ID
vendor_bridge_url: http://192.168.1.10:8123/api/vendor
vendor_bridge_token: !secret bridge_bearer
# configuration.yaml
vendor_camera:
app_id: !secret vendor_camera_app_id
bridge_url: !secret vendor_bridge_url
token: !secret vendor_bridge_token
Entities
camera.porch— stream URL updated every 8 minutes from bridge (stream_type: subon weak links)binary_sensor.porch_motion— MQTTcamera/alarm/DEVICE_IDpayloadtype=motionsensor.porch_stream_expires— optional countdown for debugging
MQTT topics
camera/alarm/# QoS 1, JSON payload from vendor callback
camera/status/DEVICE_ID online|offline (debounced 90s)
Automation — motion to light + notify
automation:
- alias: Porch motion at night
trigger:
- platform: mqtt
topic: camera/alarm/DEVICE_ID
condition:
- condition: template
value_template: "{{ trigger.payload_json.type == 'motion' }}"
- condition: sun
after: sunset
action:
- service: light.turn_on
target:
entity_id: light.porch
data:
brightness_pct: 80
- service: notify.mobile_app
data:
message: "Porch motion (cloud alarm)"
Weak-network video in HA
If your frontend card uses HLS.js (e.g. some custom cards), destroy the HLS instance when leaving the view—otherwise the next load keeps stale buffer state and looks like "HA is broken on Wi-Fi." Prefer sub-stream from the bridge when needApInfo or RSSI reports weak signal.
We run bridge-side policy: first bind streamType: 1; only upshift after 5 minutes without stall events logged from the app.
Pitfall specific to HA
Lovelace picture-glance / generic camera with a static URL rots when the cloud URL expires—use a template camera or an integration that refreshes the URL on a timer (expireTime - 60s). Otherwise users blame HA Wi-Fi when the stream 403s mid-session.