跳转到内容

reolink(摄像头)

Reolink 的门铃 / 摄像头走局域网 HTTP API + ONVIF 事件订阅,不经云端。接一台只要 地址和一组账号密码。

[[device]]
name = "doorbell"
adapter = "reolink"
host = "192.168.52.70"
user = "admin"
password = "${REOLINK_PASSWORD}"

host 只写地址,不带 scheme 也不带路径——内部会拼成 http://<host>/...,写成 http://192.168.52.70 就成了 http://http://...

adapter 订阅一次 ONVIF 事件后就持续拉取消息流,值是设备自己送上来的——没有「问」这个 动作。所以它名下的实体 poll_tier 是空的,poll_ms 这类字段在这里不存在,rha status 里看到的时间戳反映的是最后一次事件而不是最后一次轮询。

断连、HTTP 错误、鉴权失败都会让这台设备整体重启并用同一组凭据重新订阅。一台掉线不会 拖垮其余摄像头——监督粒度是一台设备一个

门铃固定暴露两个实体,都是 kind = "trigger"瞬时信号

实体 什么时候上报
<设备名>.pressed 门铃被按下
<设备名>.motion 侦测到移动

瞬时信号实体没有持续状态,平时读不到任何值。规则里只能用 fired 监听它,不能用 changed;对它写条件谓词永远不成立(无值一律算 false),而 rha check 不会拦这一 条——想「按了门铃就通知」,只有下面这一种写法:

[[rule]]
name = "doorbell_pressed"
trigger = { entity = "doorbell.pressed", fired = true }
[rule.action.notify]
url = "https://ntfy.sh/rha-demo"
message = "有人按门铃"

fired = falsefired = true 行为完全一样(只看键写没写、不看值),想临时关掉规则 请把整条规则注释掉。

摄像头的快照端点能作为 llm 动作的 snapshot 输入,让模型带图决策。两个前提别忘: 摄像头在内网,默认被 [notify] 的 SSRF 闸拒掉(要么开 allow_private_networks,要么把 host 加进 allowed_hosts);而 reolink 的快照 URL 需要登录才能拿到 token、且会过期, 直接把它写进配置不能长期工作

字段类型默认说明
host*string

相机地址, 会被直接拼进 http://{host}/onvif/event_service。所以这里只写裸的 IP 或主机名, 需要时带端口(192.168.52.70192.168.52.70:8000), 不要带 http:// 前缀, 也不要带末尾路径 —— 带了会拼出 http://http://… 这种非法 URL, 订阅第一步就失败, 而错误信息说的是 URL 解析, 不会提示你多写了前缀。

协议写死是明文 HTTP: 只认 https 的相机连不上, 且凭据以 HTTP Basic(base64, 等同 明文)过网 —— 这条链路只适合放在可信内网。

password*string
Secret

敏感值。建议写成 ${ENV} 由环境变量插值, 不要把明文提交进配置文件。该值绝不进日志与 trace。

user*string

相机本机的账号, 不是 Reolink App 的云账号: 本 adapter 的请求全部直发相机 地址, 全程不碰云端。

它和 password 以 HTTP Basic 发出, 订阅那一次和之后每一次 PullMessages 都带。 凭据不对没有单独的处理路径: 相机回 4xx → 设备任务返回 Err → supervise 退避重启 → 再用同一套凭据重试。表现是日志里反复的 subscribe: 错误 + 门铃/移动事件一直 不来, 不会有一条"密码错了"的明确提示, 所以事件收不到时先核这两行。

鉴权只实现了 Basic: 若相机要求 WS-Security UsernameToken 摘要认证, 订阅同样会 失败(见 crate::io::run_one_camera 的说明)。