小智 AI 还能这么玩?接入萤石摄像头,告警抓图一气呵成!
本人玩各种AI硬件、具身智能、AI算法、模型训练、机器视觉等。欢迎合作!!!
小智AI接入萤石云摄像头:MQTT 实时告警 + 图片预览。让小智AI/ESP32 设备秒变智能安防终端——门口摄像头检测到有人出现时,屏幕自动弹出告警消息、播放提示音,还能下载并显示现场抓拍图片。
整体架构
萤石摄像头(门铃) │ ├─→ 萤石开放平台 ←─ 注册设备、开启告警推送 │ │ │ ├─→ 告警事件推送 → 消息回调服务 → 发布到 MQTT Broker │ │ │ │ │ ├─→ 飞书机器人 ←─ 手机端实时查看 │ │ │ │ │ └─→ 小智AI(ESP32) ←─ MQTT 订阅 │ │ │ │ │ ├─ 屏幕显示告警气泡 │ │ ├─ 播放提示音 │ │ └─ 下载并显示抓拍图片步骤一:门铃接入萤石开放平台
1. 注册萤石开放平台账号
访问 萤石开放平台,注册并登录开发者账号。
2. 添加设备
- 在萤石 APP 中确保门铃已联网并正常工作
- 在开放平台「我的资源」中添加设备,或扫描设备二维码完成绑定
3. 创建应用获取 AppKey / AppSecret
- 进入「我的应用」→ 创建应用
- 获取
AppKey和AppSecret,后续 API 调用需要用到
4. 开启告警推送
- 在「告警服务」中开启设备的移动侦测/门铃事件推送
- 配置告警推送地址为你的服务器回调 URL
步骤二:部署消息回调服务
萤石开放平台会将告警事件以 HTTP POST 方式推送到你的服务器,需要部署一个回调服务来接收并转发。
服务功能
萤石告警推送 → 回调服务解析 → 提取消息文本和图片URL │ ├─→ 发布到 MQTT Broker (qiongmu/mqtt/ys) └─→ 推送飞书机器人 webhook部署方式
- 服务器:任意 Linux 服务器(阿里云、腾讯云等)
- HTTPS:萤石回调要求 HTTPS,可用 Nginx 反向代理 + Let’s Encrypt 证书
- 保活:使用
systemd或supervisor管理进程
步骤三:接入飞书机器人
1. 创建飞书自定义机器人
- 打开飞书群聊 → 设置 → 群机器人 → 添加机器人 → 自定义机器人
- 获取 Webhook 地址
2. 配置回调服务
在上面的回调服务中配置FEISHU_WEBHOOK,告警消息会同时推送到飞书:
🚨 门口有人出现! 📷 抓拍: https://i.ys7.com/streamer/alarm/url/get?fileId=...3. 效果
- 手机端:飞书 APP 收到群消息推送,随时查看
- 带图片:点击链接可查看抓拍图片
- 可配合飞书自动化:设置特别关注、DND 时段等
步骤四:小智接入 MQTT 实现告警
设备端实现
在小智AI(ESP32-S3)上运行MqttListener,独立订阅 MQTT 告警主题:
// mqtt_listener.h - 独立 MQTT 客户端classMqttListener{// TLS 连接 emqxsl.cn:8883// 订阅 qiongmu/mqtt/ysstaticMqttListener&GetInstance();voidInitialize();voidStart();};在Application::Initialize()中初始化:
auto&mqtt_listener=MqttListener::GetInstance();mqtt_listener.SetMessageCallback([this](conststd::string&topic,conststd::string&payload){OnMqttMessage(payload);});mqtt_listener.Initialize();// 网络激活后启动mqtt_listener.Start();消息处理
MQTT 消息通过事件队列进入主事件循环:
MQTT 收到 → 入队 → MAIN_EVENT_MQTT_MESSAGE ↓ HandleMqttMessageEvent() ↓ ├── 解析 JSON → msg + pic ├── SetChatMessage("system", msg) → 显示气泡消息 ├── PlaySound(OGG_SUCCESS) → 播放提示音(3次) └── xTaskCreate() → 后台下载图片图片下载与显示
完整流程
HTTP GET → 跟随 302 重定向(最多3次) → 下载 JPEG ↓ jpeg_to_image() → 解码为 RGB565 ↓ 最近邻缩放至 320×320(保持宽高比) ↓ LvglAllocatedImage → SetPreviewImage() 显示重定向处理
萤石云图片 URL 返回 302 跳转到 AWS S3:
while(redirect_count<3){autohttp=Board::GetInstance().GetNetwork()->CreateHttp(3);http->SetKeepAlive(false);// 禁用连接复用http->Open("GET",current_url);if(status_code==302){std::string location=http->GetResponseHeader("Location");http->Close();current_url=location;redirect_count++;vTaskDelay(pdMS_TO_TICKS(200));continue;}// 下载并解码...}JPEG 解码 + 缩放
使用 ESP-IDF 自带的 JPEG 解码器(优先硬件加速),解码后缩放到 320×320:
// JPEG 解码uint8_t*rgb565=nullptr;esp_err_t err=jpeg_to_image(jpeg_data,content_length,&rgb565,&rgb_len,&img_width,&img_height,&img_stride);// 缩放到 320×320(保持宽高比)constintMAX_DIM=320;if(img_width>MAX_DIM||img_height>MAX_DIM){intscale_w=(img_width>img_height)?MAX_DIM:(MAX_DIM*img_width/img_height);intscale_h=(img_height>img_width)?MAX_DIM:(MAX_DIM*img_height/img_width);uint8_t*scaled=heap_caps_malloc(scale_w*scale_h*2,MALLOC_CAP_SPIRAM);downscale_rgb565((uint16_t*)rgb565,img_width,img_height,scaled,scale_w,scale_h);heap_caps_free(rgb565);// 立即释放原始大图}内存对比
| 原始分辨率 | 解码后 | 缩放后 |
|---|---|---|
| 1920×1080 | ~4MB | ~200KB |
| 1280×720 | ~1.8MB | ~112KB |
| 640×480 | ~600KB | ~150KB |
内存保护
ESP32 内存有限,下载前检查可用堆大小:
if(esp_get_free_heap_size()<80*1024){ESP_LOGW(TAG,"Skipping image download, low memory (%zu KB)",esp_get_free_heap_size()/1024);}else{xTaskCreate(...,"mqtt_img",4096*2,...);}消息气泡持久化
移除了所有SetChatMessage("system", "")空内容调用,让 MQTT 消息在聊天区永久显示,直到:
- 消息数量超过 MAX_MESSAGES(默认 20 条)自动挤掉最旧的
- 新对话开始时清除
最终效果
| 终端 | 效果 |
|---|---|
| 小智AI | 屏幕弹出告警气泡 + 提示音 + 抓拍图片 |
| 飞书APP | 随时随地查看门铃动态 |
后续计划
- 图片点击放大全屏查看
- 支持更多图片格式(PNG/WebP)
- MQTT 告警消息数量统计
- 语音播报告警内容
- 飞书机器人交互式按钮(静音时段、确认已处理等)
项目:xiaozhi-esp32
作者:qiongmu.tech
