🎯 重点更新
本版本对齐 seeed-esp32s3-cam 实现,统一端口架构和 ONVIF 协议标准,NVR 现在可以发现并预览视频。
✨ 新功能
📺 MJPEG 独立流媒体服务器 (Port 81)
MJPEG 推流从 esp_http_server handler 重构为独立 TCP 服务器(端口 81),对齐 seeed-esp32s3-cam 架构:
- 长连接推流不再阻塞端口 80 的 Web API / UI
- 独立 FreeRTOS 任务 pinned to Core 1,最多 2 个并发客户端
SO_RCVTIMEO超时防止半开连接内存泄漏- 预览页
preview.html自动指向http://host:81/stream
📡 ONVIF 协议对齐 (NVR 兼容)
| SOAP 方法 | 变更 |
|---|---|
GetStreamUri |
rtsp://ip:8554/stream(假 RTSP)→ http://ip:81/stream(真实 MJPEG) |
GetSystemDateAndTime |
新增 — NVR 发现握手必需 |
| HTTP-directed Probe | 新增 — 支持 HTTP POST 方式的 WS-Discovery |
| WS-Discovery Hello | 新增 — 启动时 + 每 30 秒主动多播通告 |
💻 AT 指令接口 (UART0)
新增 20 条 AT 指令,支持串口配置 WiFi、查看系统信息、控制摄像头:
AT+CWJAP=<ssid>,<pass> — 设置 WiFi
AT+CWJAP2=<ssid>,<pass> — 设置备用 WiFi
AT+CIFSR — 查询 IP 地址
AT+CFGGET=<field> — 读取配置项
AT+CFGSET=<field>,<value> — 修改配置项
AT+SAVE — 保存到 NVS
AT+RST / AT+RESTORE — 重启 / 恢复出厂
AT+CWLAP — 扫描 WiFi
AT+HEAP / AT+UPTIME / AT+TEMP — 系统信息
...
🧠 内存自适应启动
无 PSRAM 板子上,运动检测在 heap < 30KB 时自动跳过,优先保障 NVR 推流:
if (free_heap < 30000) {
ESP_LOGW(TAG, "Motion detection skipped (NVR/streaming mode)");
} else {
motion_detect_start();
}🐛 Bug 修复
| 问题 | 根因 | 修复 |
|---|---|---|
| ONVIF 启动崩溃 (Guru Meditation) | onvif_discovery_task 栈溢出(4KB 栈 + 4KB 局部缓冲区) |
缓冲区移至堆 (malloc) |
| 运行数小时后设备无响应 | MJPEG recv() 无超时,半开连接泄漏 4KB/次 |
添加 SO_RCVTIMEO 5 秒超时 |
| 运动检测抢占摄像头 | 与推流争抢相机互斥锁,malloc(19KB) 失败 |
heap < 30KB 自动跳过 |
| WiFi 连接不稳定 | set_ps() 在 wifi_start() 前调用被忽略 |
移到 start() 之后 |
| 配置并发访问崩溃 | AT 任务 + httpd 并发读写配置 | config_get_copy() + mutex |
📐 端口架构
Port 80 → Web UI + REST API + ONVIF SOAP + WebSocket
Port 81 → MJPEG Stream (独立 TCP 服务器)
Port 3702/UDP → WS-Discovery (Probe + Hello)
📦 升级须知
- 刷固件:
idf.py -p /dev/ttyACM0 flash - 刷 SPIFFS(Web UI 文件,必须单独刷):
python $IDF_PATH/components/spiffs/spiffsgen.py 0x3CE000 main/web_ui build/spiffs.bin python -m esptool --chip esp32s3 -p /dev/ttyACM0 -b 460800 write_flash 0x392000 build/spiffs.bin - 启用 ONVIF(如需 NVR 对接):通过 Web 配置页或
AT+CFGSET=onvif_enabled,1+AT+SAVE - NVR 对接:NVR 和摄像头需在同一子网,NVR 需支持 MJPEG over HTTP 格式
Full Changelog: v0.2.2...v0.3.0