MiBee 开源项目实践系列
引言
本文记录用 ESP01 + DHT11 搭建一个温湿度监控的过程,涵盖硬件连接、代码实现和功能验证。ESP01 作为一款低成本、低功耗的 Wi-Fi 模块,适合作为采集节点。
硬件准备
- ESP01 主板:核心控制模块,负责数据采集和网络通信。

- DHT 温湿度传感器:用于测量环境的温度和湿度。

- 杜邦线:用于连接 ESP01 和 DHT 传感器。
将 DHT 传感器的 VCC 引脚连接到 ESP01 的 3.3V 引脚,GND 引脚连接到 GND,数据引脚连接到 ESP01 的指定引脚(代码中为 DHTPIN)。
起因
我在市区不同地方有几个局域网,相互之间大概隔了 10 公里左右。为了让这几个网络能互通,我用 NetBird、ZeroTier、Cloudflare Tunnel 这类工具搭了一套跨地域的虚拟局域网。
起因
家里养了几只鹦鹉,白天上班的时候没人在家,想随时看看它们在干嘛。需求说起来简单:能实时看画面、能录像存下来、最好还能自动备份到 NAS 上。市面上的摄像头要么价格不便宜,要么要装各种 APP 注册账号绑手机号,隐私方面心里没底——我就是想看看鸟,不想把视频传到别人的服务器上。
家里有好几个摄像头,几台小米,一些自己用 ESP32 搭的,还有多台树莓派 CSI 摄像头。之前一直在用一些云存储方案,但总觉得不放心:厂商绑定、依赖网络、费用还不少。索性自己动手,写了个 NVR 系统,就叫 MiBeeNvr。
起因
之前用 ESP32-S3 做了个监控摄像头,效果还行。后来翻抽屉发现还有一块 AI-Thinker 的 ESP32-CAM 开发板——就是那种十几块钱、自带 OV2640 摄像头和 TF 卡槽的经典板子。手上有就不用浪费,再做一个吧:ai-thinker-esp32-cam。
上一篇文章介绍了 MiBeeNvr 的基本功能和设计思路,距离 v0.1.0 发布也就一周时间,v0.2.0 紧跟着就出来了。这次更新内容不少,15 个新特性,有些是我自己需要的,有些是来自社区反馈的。
家里有小米摄像头?想把录像存到自己手里,不靠云存储?
作为一个家里装了几个小米摄像头的用户,我一直有个烦恼:每次想看门口的录像,都得先登录小米云,加载半天还经常转圈。而且云存储按天收费,一个月下来也不是小数目。有时候换摄像头,之前的录像就全没了,想想都觉得可惜。
v0.2.0 发布之后又折腾了不少,这次 v0.3.x 带来了几个重量级更新:小米摄像头内置支持、归档录像功能、多协议流媒体架构(WebRTC/HTTP-FLV/RTMP/SRT/LL-HLS),以及一大波安全加固。从外部依赖到内置实现、从单协议到全协议支持的架构演进过程,比我想象的要曲折得多。
之前 MiBeeNvr 录的 MP4 文件只有视频轨,播放时是静音的。v0.4.0 补上了这个功能 —— 音频录制。同时新增了更实用的 摄像头健康监控和自动恢复。
录像有声音了
每个摄像头都可以单独开启音频录制:
v0.3.1 发布之后又肝了 196 个提交。v0.4.0 是一个功能密度很高的版本:音频录制管线、多层健康监控引擎、HLS/LL-HLS 播放稳定性优化、UI 大改版。完整更新列表见 GitHub Release Notes。
做运维出身,后来转开发,维护的项目越来越多。各种中间件、数据库、监控组件……每次升级版本都是一场体力活:去官网找下载链接、比对版本号、手动下载到内网、再分发到各台机器。以前写了一堆 Shell 脚本定期拉取最新版本到局域网,能用但不好用——脚本散落在各处,加新软件得手写解析逻辑,出错了也没什么日志可查。
v0.4.0 发布不到一周,又肝了 31 个提交。v0.5.0 是一个功能密度很高的版本:ONVIF 全协议支持(Device/Media/PTZ/Imaging/Event 五大服务全覆盖)、硬件转码(H.265 → H.264)、录制器重连优化。127 个文件变更,+24,509 / -730 行。完整更新列表见 GitHub Release Notes。
做工作室运维,最头疼的从来不是某个具体问题,而是设备多起来之后的「不知道」。
不知道哪个设备还活着,不知道它上面跑了什么服务,不知道网络里什么时候多了台新机器,不知道某个端口是不是还开着——这种「不知道」积累到最后就是故障。
MiBeeNvr 连续跑了几周录像后,存储最先告急。单路 1080p 摄像头每天要写几十 GB,30 天留存一件 1TB 硬盘就没了大半。社区里不少朋友反馈了同样的问题,讨论中延时摄影和转码保存的方案呼声最高——画面大部分时间静止,用 timelapse 压缩后同样时长只需要 5% 的空间。
同期发布的 MiBeeNvr v0.6.0 带来了延时摄影、视频转码、ONVIF 增强等大功能,光靠单元测试远远不够,必须在真实摄像头环境下跑完整流程。为了给这个版本提供靠谱的测试机器,6 月 5 日同一天更新了三个摄像头项目——既是给 NVR 提供测试环境,也顺手解决了一些嵌入式开发中比较典型的工程问题。
v0.6.0 把延时摄影管道搭起来之后,社区反馈很快就指出了几个硬伤:JPEG 序列要吃掉太多存储、H.265 摄像头生成的延时片段播放不了、双摄小米设备只能抓到主镜头、偶尔还会出现 H.265 HLS 直接 panic 的崩溃。这些都不是边缘场景——双摄 CW500 和室外摄像头 4 在国内出货量很大,H.265 已经是中高端摄像头的事实标准。v0.7.0 的主线就是围绕这些反馈展开的。
在 MiBee NVR 项目里要把摄像头画面推到国内某直播平台,候选方案有三个:直接调 FFmpeg、用纯 Go 的 gortmplib、用 go2rtc。三个都能「推 RTMP」,但实际对接国内直播平台时表现差异巨大——有的秒断、有的几秒后断、有的稳如老狗。这篇从源码层面把三者拆开对比,并梳理对接国内 FMS 兼容平台时的坑和解法。
v0.1.0 发布的时候我写了一句:它能回答「网络上有哪些设备、它们是什么、它们之间什么关系」。但说实话,v0.1.0 只答好了前半句——而且只限于 center 所在的那一个 LAN。
工作室的真实场景是:办公室一个网段、机房一个网段、家里跑测试机又一个网段。center 坐在办公室,机房的摄像头它根本看不见。要让 center 去扫机房,得跨子网穿透,要么开 SNMP 路由转发,要么干脆把 center 搬过去——两个都不优雅。
9 路摄像头挂在 Banana Pi M5 上跑了大半年,从 v0.6 开始累积的工程债到了不得不还的时候。/api/cameras 接口在 9 个录制器全部启动的过程中要卡 14.9 秒——不是遍历慢,是 cm.mu RWMutex 在阻塞,任何读操作都进不来。ONVIF 摄像头添加还得手动填 IP,家里装了 CW500、DS-2CD2047G2 这类设备之后,每多一台就要开一次终端,不可持续。FFmpeg 作为 NVR 唯一的第三方二进制依赖,每次部署都要确认装没装,树莓派上还要操心硬件编码器版本。更扎心的是,Xiaomi 的那几个旧设备——Dafang、Xiaofang、Aqara G2——因为走了 TUTK 协议,一直没法接入。这些问题都不是新技术挑战,是工程债,v0.9 一次性还了。
上一篇讲了 v0.2.0 有什么。这篇讲为什么这么设计——分布式一致性是这个版本最重的部分,几个看似随意的决定背后都有具体的取舍。
要解决的问题很明确:center 只能看见自己所在的 LAN,但用户有多个 LAN。把 center 扔到每个网段不现实,于是有了 mibee-agent——一个只做「扫本地 + 报 center」的二进制。但 agent 一上,立刻带出一串协议问题:怎么上报、怎么对账、怎么判定掉线、怎么不把 center 写爆。下面逐个拆。
接手一个不熟悉的局域网,第一件事是搞清楚里面有什么——办公室、机房、家里几个网段混接,没人留下文档,交换机上连着一堆没人叫得出名字的 MAC。MiBeeSteward 就是干这件事的:扫一遍网络,告诉你有哪些设备、它们是什么、它们之间怎么连的。
上一篇讲了 v0.3.0 有什么。这篇讲为什么——本版有三个看似随意、背后有具体工程取舍的决定:Docker 网络模式如何决定 scanner 的探测保真度、TLS 证书链采集为什么能用一个核心覆盖 8 个协议、L2 拓扑为什么需要三个 MIB 才拼得起来。逐个拆。