跳过导航,直接进入主要内容跳过导航,直接进入主要内容跳过导航,直接进入主要内容

MQTT 集成

MiBee NVR 支持 MQTT 触发录制与状态发布,用于智能家居自动化和事件驱动录制。接收 MQTT 消息可以启动/停止摄像头录制;开启状态发布后,健康告警与录像事件也会推送到 MQTT。没有 MQTT 代理、只有 HTTP 的场景可以改用 Webhook 触发。

概述

  • 协议: MQTT (Message Queuing Telemetry Transport)
  • 触发(订阅): {prefix}/trigger/{camera_id}
  • 状态(发布): {prefix}/health/{camera_id}、{prefix}/event/{topic}(见状态发布)
  • 触发负载: 包含 action 字段的 JSON
  • 触发操作: record, stop, snapshot(快照落盘并发布 camera.snapshot 事件)
  • 自动重连: 内置指数退避重连;代理在 NVR 启动时尚不可达也会持续重试(1s→5s→10s→60s 分层退避),不要求代理先于 NVR 启动

配置

基本设置

mqtt:
  enabled: true
  broker: "tcp://192.168.1.100:1883"
  client_id: "mibee-nvr"
  topic: "mibee"
  username: "mqtt_user"
  password: "mqtt_password"

配置选项

字段 必需 类型 默认值 描述
enabled 是 bool false 启用 MQTT 客户端
broker 是 string - MQTT 代理地址(如 tcp://192.168.1.100:1883)
client_id 是 string - MQTT 连接的唯一客户端 ID
topic 是 string - 主题前缀(如 mibee),实际订阅 {topic}/trigger/+
username 否 string - MQTT 用户名(如果代理需要认证)
password 否 string - MQTT 密码(可经 mibee-nvr encrypt-config 加密存储)
status_events 否 bool false 将录像/摄像头事件转发到 {topic}/event/<topic>(见状态发布)

完整配置示例

mqtt:
  enabled: true
  broker: "tcp://mqtt.example.com:1883"
  client_id: "mibee-nvr-home"
  topic: "home/security"
  username: "smart_home_user"
  password: "secure_password_123"
  status_events: true

使用方法

MQTT 消息

触发录制

启动指定摄像头(等价于页面的「启动」按钮):连接相机并开始取流。

{
  "action": "record"
}

注意:实际是否落盘仍由该摄像头的「启用录制」开关(recording_enabled)决定——开关关闭时为仅直播模式(取流、预览、健康监控正常,不写录像段)。对关闭录制的相机,record 触发的效果是拉起直播流而非开始写盘。

限时强制录制(duration,#660)

不受「启用录制」开关限制的限时录制窗口——窗口期内写盘录像,到期自动收尾当前段并回到仅直播模式。适合「平时仅直播、事件时录一段」的场景(如 Home Assistant 移动触发):

{
  "action": "record",
  "duration": "60s"
}
  • duration 支持 Go 时长格式("30s"、"5m");无效或非正值按缺省处理(回退为普通 record,并打 WARN 日志)
  • 相机未运行时先按 record 语义启动取流,再开启窗口;运行中的相机原地续窗(重复触发取更晚的到期时间,与音频/像素触发的 hold 语义一致)
  • 支持 H.264/H.265、MJPEG、HTTP-JPEG 相机;推送接入型(SRT/RTMP ingest 等)不支持,会返回明确错误

主题: home/security/trigger/front-door
消息: {"action": "record"}

主题: home/security/trigger/backyard
消息: {"action": "record"}

停止录制

停止录制特定摄像头:

{
  "action": "stop"
}

主题: home/security/trigger/front-door
消息: {"action": "stop"}

触发快照

从特定摄像头拍摄一张快照并落盘(#656):

{
  "action": "snapshot"
}

捕获按能力依次尝试:JPEG 系摄像头(HTTP-JPEG/MJPEG)直接取录像器最新帧;H.264/H.265 摄像头经一次性 StreamHub 订阅(缓存 IDR 立即回放,无需等待下个 GOP)后由可选 FFmpeg 解码为 JPEG,FFmpeg 缺失时回退到摄像头配置的 snapshot_url(携带摄像头凭据)。快照以原子写(临时文件 → 重命名)保存到 {存储根目录}/snapshots/{camera_id}/{时间戳}.jpg,成功后发布 camera.snapshot 事件(见下方事件转发表)。

主题: home/security/trigger/front-door
消息: {"action": "snapshot"}

状态发布

NVR 会将以下状态发布到 MQTT(均需 mqtt.enabled: true):

健康告警 — {prefix}/health/{camera_id}

门控:mqtt.enabled: true 且 health.alerts.mqtt: true。摄像头断连、码流冻结、连接恢复等健康事件会发布到该主题,负载为健康事件 JSON:

{
  "id": "evt-123",
  "camera_id": "front-door",
  "event_type": "connection_lost",
  "status": "warning",
  "message": "no frames for 30s",
  "created_at": "2026-09-01T12:00:00Z"
}

同一事件的重复告警受 health.alerts.cooldown(默认 5m)抑制;持续异常会升级为 error,恢复类事件(connection_restored、freeze_recovered)永不升级。

事件转发 — {prefix}/event/{topic}

门控:mqtt.enabled: true 且 mqtt.status_events: true。以下事件总线主题会被原样转发(负载为对应事件的 JSON):

事件主题 MQTT 主题 负载要点
segment.completed {prefix}/event/segment.completed camera_id、file_path、format、encoding、started_at、ended_at、file_size、recording_id
camera.added {prefix}/event/camera.added camera_id、name、endpoint、source
camera.quality {prefix}/event/camera.quality camera_id、from、to、reason
storage.health.changed {prefix}/event/storage.health.changed camera_id、previous_state、current_state、message
camera.snapshot {prefix}/event/camera.snapshot camera_id、file_path(相对存储根目录)、timestamp、trigger

高频主题(如 AI 检测)刻意不在转发白名单内。消息 QoS 1、不保留(retain=false);代理缓慢时事件会被丢弃(事件总线满即丢,不阻塞录制)。

集成示例

Home Assistant

# Home Assistant MQTT 自动化
- alias: 检测到运动 - 前门
  trigger:
    - platform: mqtt
      topic: "zigbee2mqtt/front-door-motion/occupancy"
      payload: "ON"
  action:
    - service: mqtt.publish
      data:
        topic: "home/security/trigger/front-door"
        payload: '{"action": "record"}'
        retain: false

Node-RED

// Node-RED 流示例
[
  {"id": "1", "type": "mqtt in", "topic": "zigbee2mqtt/occupancy/+", "z": "2"},
  {"id": "2", "type": "switch", "name": "运动检测", "property": "payload", "propertyType": "msg", "rules": [{"t": "eq", "v": "ON"}], "checkall": "true", "outputs": 1},
  {"id": "3", "type": "function", "name": "获取摄像头 ID", "func": "const camera = msg.topic.split('/')[1]; msg.camera = camera; return msg;", "outputs": 1},
  {"id": "4", "type": "function", "name": "构建 MQTT 消息", "func": "msg.topic = `home/security/trigger/${msg.camera}`; msg.payload = '{\"action\": \"record\"}'; return msg;", "outputs": 1},
  {"id": "5", "type": "mqtt out", "topic": "home/security/trigger/+", "qos": "0", "retain": "false"}
]

ESP8266/ESP32

// ESP8266 运动检测示例
#include <PubSubClient.h>
#include <WiFi.h>

const char* mqtt_server = "192.168.1.100";
const char* topic_prefix = "home/security";

void setup() {
  pinMode(D1, INPUT); // PIR 传感器引脚
  WiFi.begin("your_ssid", "password");
  
  client.setServer(mqtt_server, 1883);
}

void loop() {
  if (digitalRead(D1) == HIGH) {
    // 检测到运动,触发录制
    String payload = "{\"action\": \"record\"}";
    String topic = String(topic_prefix) + "/trigger/front-door";
    client.publish(topic.c_str(), payload.c_str());
    delay(30000); // 等待 30 秒后下次触发
  }
  delay(1000);
}

Python 脚本

# Python MQTT 发布器示例
import paho.mqtt.client as mqtt
import json
import time

def on_connect(client, userdata, flags, rc):
    print("已连接到 MQTT 代理")

client = mqtt.Client("mibee-nvr-trigger")
client.username_pw_set("mqtt_user", "mqtt_password")
client.connect("192.168.1.100", 1883)

# 从 Python 触发录制
def trigger_recording(camera_id, action="record"):
    topic = f"home/security/trigger/{camera_id}"
    payload = json.dumps({"action": action})
    client.publish(topic, payload)
    print(f"触发 {camera_id} 的 {action}")

# 使用示例
trigger_recording("front-door", "record")
time.sleep(30)  # 录制 30 秒
trigger_recording("front-door", "stop")

监控

系统日志

检查 MQTT 连接状态和消息:

# 查看系统日志
journalctl -u mibee-nvr -f | grep mqtt

# Docker 日志
docker logs -f mibee-nvr | grep mqtt

健康检查

验证 MQTT 客户端状态:

curl -u admin:password http://localhost:9090/api/system/health

在响应中查找 "mqtt": {"status": "ok"}。

错误处理

常见问题

连接失败

WARN: mqtt connection failed: connection refused

解决方案:检查代理 URL,确保代理正在运行 调试:使用 mosquitto_pub -h 192.168.1.100 -t test -m hello 进行测试

认证失败

WARN: mqtt authentication failed

解决方案:验证配置中的用户名和密码 调试:使用凭据测试:mosquitto_pub -u user -P pass -h broker -t test -m hello

消息未处理

WARN: invalid mqtt message payload format

解决方案:确保 JSON 负载包含 action 字段 调试:使用 JSON 验证器验证负载

高级配置

多个主题

mqtt:
  broker_url: "tcp://192.168.1.100:1883"
  client_id: "mibee-nvr"
  topic_prefix: "security"

多个摄像头可以在同一个代理上被触发:

security/trigger/camera1
security/trigger/camera2
security/trigger/camera3

代理安全

mqtt:
  broker_url: "ssl://mqtt.example.com:8883"
  client_id: "mibee-nvr"
  topic_prefix: "home/security"
  username: "secure_user"
  password: "complex_password"
  # SSL 需要 正确配置证书
  ca_cert: "/path/to/ca.crt"
  client_cert: "/path/to/client.crt"
  client_key: "/path/to/client.key"

与其他系统集成

Zigbee2MQTT

# Zigbee2MQTT 集成
mqtt:
  broker_url: "tcp://192.168.1.100:1883"
  client_id: "mibee-nvr"
  topic_prefix: "zigbee2mqtt"

# 从运动传感器触发摄像头

Home Assistant 自动化

# 门铃触发的 Home Assistant 自动化录制
- alias: 门铃录制
  trigger:
    - platform: mqtt
      topic: "zigbee2mqtt/doorbell/bell_pressed"
      payload: "ON"
  action:
    - service: mqtt.publish
      data:
        topic: "zigbee2mqtt/trigger/doorbell"
        payload: '{"action": "record", "duration": 60}'
        retain: false

最佳实践

  1. 主题组织:使用有意义的前缀来组织不同区域
  2. 负载验证:在 JSON 负载中始终包含 action 字段
  3. 连接可靠性:配置代理用于自动重连
  4. 错误处理:在客户端应用程序中实现重试逻辑
  5. 消息保留:在代理上使用适当的消息保留策略
  6. 安全性:为生产部署使用强密码和 SSL/TLS

故障排除

连接问题

  1. 验证代理是否可达:

    ping 192.168.1.100
    nc -zv 192.168.1.100 1883
    
  2. 手动测试 MQTT 连接:

    mosquitto_sub -h 192.168.1.100 -t "test" -u user -P pass
    mosquitto_pub -h 192.168.1.100 -t "test" -m "hello" -u user -P pass
    

消息传递问题

  1. 检查日志中的处理错误:

    journalctl -u mibee-nvr -f | grep mqtt
    
  2. 验证主题匹配:

    # 测试主题匹配
    echo '{"action": "record"}' | mosquitto_pub -h 192.168.1.100 -t "security/trigger/camera1" -u user -P pass
    

配置验证

验证配置文件:

./mibee-nvr -config mibee-nvr.yaml --validate

调试模式

启用调试日志:

mqtt:
  broker_url: "tcp://192.168.1.100:1883"
  client_id: "mibee-nvr"
  topic_prefix: "home/security"

observability:
  log_level: "debug"
页面已加载完成,可访问性功能已启用
页面已加载完成,可访问性功能已启用
页面已加载完成,可访问性功能已启用