env2metric 把正和清源空气质量检测仪B39变成一台可以长期运行的网络传感器:ESP32-S3 开发板通过 USB 读取检测仪数据,再通过 OpenTelemetry 的 OTLP/HTTP 协议将空气质量指标上报到兼容的可观测平台,当前以 OneUptime 为主要接入示例。
在可观测平台配置 Dashboard 后,可以查看 PM2.5、CO2、甲醛、VOC、温度和湿度的当前值、历史趋势及空气质量参考线。
OneUptime 是一个开源的监控与可观测性平台,支持指标、日志、链路追踪、告警和事件管理,可以自行部署,也可以使用官方托管服务。部署和使用说明见 官方文档。
在本项目中,OneUptime 负责接收和存储 ESP32-S3 通过 OTLP/HTTP 上报的空气质量指标,并通过 Metrics 和 Dashboard 展示当前值与历史趋势。使用前需要准备一个可从设备所在 Wi-Fi 访问的 OneUptime 实例,在其中创建项目并获取 Telemetry Ingestion Key;本仓库还提供创建配套 Dashboard 的脚本。
固件发送的是 OTLP/HTTP JSON 格式的指标(Metrics)数据,通过 HTTP POST 上报,Content-Type 为 application/json。其他平台提供兼容的指标接收端点时,可以修改 CONFIG_ENV2METRIC_OTLP_METRICS_URL 和 CONFIG_ENV2METRIC_OTLP_HEADERS,填写其完整接收地址和认证请求头,再重新编译固件。使用 HTTPS 时,设备还需信任接收端的证书。协议细节见 OTLP/HTTP 规范。
如果目标平台仅接受 OTLP/gRPC、OTLP/HTTP 二进制 Protobuf 或其他协议,可以先将指标发送到启用了 OTLP/HTTP 接收端的 OpenTelemetry Collector,再配置对应的导出器转发到目标平台。
数据上报兼容不代表看板配置通用。本仓库保留了 OneUptime 和 SigNoz 的看板相关文件,其他平台需要按其查询和展示方式另外配置 Dashboard;具体接入效果仍需在目标平台验证。
本项目已经在下面这套硬件上完成验证:
- 正和清源空气质量检测仪 B39
- YN038 ESP32-S3 开发板
- 一根自行购买的 USB 数据线,用于连接电脑与开发板的 CH340 下载/调试接口
- 一根自行购买的 USB 数据线,用于连接开发板的 USB Host 接口与空气质量检测仪
还需要:
- 一个 2.4 GHz Wi-Fi 网络
- 一个可从该 Wi-Fi 访问的指标接收端点:OneUptime、其他兼容平台或 OpenTelemetry Collector
- 一台用于编译和刷机的 macOS 或 Linux 电脑
- 将空气质量检测仪接到 YN038 的 USB Host 接口。
- 将 YN038 的 CH340 下载/调试接口接到电脑。
- 确认检测仪已经通电。
开发板刷入固件后不再依赖电脑运行。电脑只在首次刷机或查看串口日志时需要连接。
根据检测仪厂商针对 VOC 传感器基线漂移的维护建议,固件会在检测仪每连续连接 7 天(7×24 小时)后,通过 USB DTR/RTS 控制线重启检测仪,ESP32-S3 网关自身继续运行。重启期间暂时停止采集,随后清空残留数据和序号记录并恢复读取;重启后的数据序号可以重新从小值开始。
周期使用单调时钟计时,不受校时或时区影响;检测仪断开重连或 ESP32-S3 重启后重新计时。复位后仍在线的 USB 连接会直接复用,避免因重新打开串口再次触发重启。USB 复位请求失败时记录 warning,不立即补发;若连接保持在线,下一次尝试在 7 天后。电脑直连和 ESP32-S3 USB Host 实测中,检测仪均在重启约 30 秒后恢复输出;开发板端已验证能够自动恢复采集和上报。
项目使用 ESP-IDF v5.5.4,与依赖锁文件及已完成的实机验证版本一致。下面是 macOS/Linux 的隔离安装方式,不会替换系统编译器:
mkdir -p ~/esp
cd ~/esp
git clone --recursive --branch v5.5.4 https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh all每次打开新的终端后激活 ESP-IDF:
. "$HOME/esp/esp-idf/export.sh"以下以 OneUptime 为例。回到 env2metric 仓库根目录,创建只在本机使用的配置文件:
cp firmware/esp32s3/sdkconfig.defaults.local.example \
firmware/esp32s3/sdkconfig.defaults.local编辑 firmware/esp32s3/sdkconfig.defaults.local:
CONFIG_ENV2METRIC_WIFI_SSID="your-wifi-name"
CONFIG_ENV2METRIC_WIFI_PASSWORD="your-wifi-password"
CONFIG_ENV2METRIC_OTLP_METRICS_URL="https://your-oneuptime-host/otlp/v1/metrics"
CONFIG_ENV2METRIC_OTLP_HEADERS="x-oneuptime-token=your-oneuptime-telemetry-ingestion-key"
CONFIG_ENV2METRIC_OTLP_HEADERS 与 OTEL_EXPORTER_OTLP_HEADERS 使用相同的 名称=值 格式,支持用逗号分隔多个 Header。OneUptime 的 Telemetry Ingestion Key 应填写为 x-oneuptime-token=<key>;本地 SigNoz 不需要鉴权时可留空。该文件包含 Wi-Fi 密码和遥测密钥,已经被 Git 忽略,不要提交它。
自托管 OneUptime 时,地址通常是 https://your-oneuptime-host/otlp/v1/metrics。请让 ESP32 信任该 HTTPS 证书;如暂时使用内网 HTTP,应使用对应的 http:// 地址。
使用 ESP-IDF 官方组件管理器自动获取 LED 和 USB Host 依赖。首次构建需要联网访问 ESP Component Registry;组件版本由 idf_component.yml 和已提交的 dependencies.lock 固定,下载目录 managed_components/ 不需要提交。
unset IDF_COMPONENT_MANAGER
idf.py -C firmware/esp32s3 set-target esp32s3
idf.py -C firmware/esp32s3 buildset-target 仅在首次构建或切换芯片时执行;后续修改代码后直接运行 build。
GitHub Actions 会在推送代码、提交 PR 或手动触发时运行序号校验和定期重启回归测试,并使用 ESP-IDF v5.5.4 和示例配置编译 ESP32-S3 固件,同时检查依赖锁文件是否发生变化。结果可在仓库的 Actions 页面查看,工作流见 .github/workflows/firmware.yml。构建使用占位凭据,不需要配置 GitHub Secrets;实际使用时仍需填写自己的 Wi-Fi 和上报平台配置并重新编译。
先找到开发板串口。macOS 通常是 /dev/cu.usbserial-*,Linux 通常是 /dev/ttyUSB*。
idf.py -C firmware/esp32s3 \
-p /dev/cu.usbserial-xxxx flash monitor把端口替换成实际设备。退出日志监视器使用 Ctrl+]。
启动成功后,固件会依次连接 Wi-Fi、同步时间、等待检测仪数据并上传指标。以 OneUptime 为例,Metrics 中出现 env2metric.air.* 指标,就表示整条链路已经跑通;其他平台应在对应的指标查询界面确认数据已接收。
服务端暂时不可用不会导致设备卡死或程序退出。一次数据上传失败后,固件会继续读取并上报后续数据。
| 灯光 | 含义 |
|---|---|
| 蓝色快闪 | Wi-Fi 未连接或正在重连 |
| 黄色快闪 | 等待空气质量检测仪 |
| 白色短亮 0.5 秒 | 开始上传有效数据或上传成功时各短亮一次 |
| 橙色短亮 0.5 秒 | 本次上传失败,固件将继续运行 |
| 黄色短亮 0.5 秒 | 本次数据解析或校验失败,跳过该样本并继续读取 |
| 红色常亮 | 启动发生致命错误 |
脚本会创建一个包含六个当前值面板和七个趋势图的 OneUptime Dashboard。它使用 OneUptime API Key,区别于设备上报所用的 Telemetry Ingestion Key。
./scripts/create_oneuptime_dashboard.sh脚本会依次询问 OneUptime 地址、API Key 和 Project ID;API Key 输入时不会回显。也可预先设置同名的 ONEUPTIME_BASE_URL、ONEUPTIME_API_KEY、ONEUPTIME_PROJECT_ID 环境变量,适合自动化运行。同一项目中已有同名 Dashboard 时,脚本会先删除它再创建,API Key 因而需要 Dashboard 的创建与删除权限。
| 指标名 | 含义 | 单位 |
|---|---|---|
env2metric.air.particle_0_3um |
0.3 微米以上颗粒数 | pcs/0.1L |
env2metric.air.pm25 |
PM2.5 | µg/m³ |
env2metric.air.hcho |
甲醛 | µg/m³ |
env2metric.air.co2 |
二氧化碳 | ppm |
env2metric.air.temperature |
温度 | °C |
env2metric.air.humidity |
相对湿度 | % |
env2metric.air.voc |
VOC | ppm |
env2metric.air.sequence |
检测仪输出序号 | 1 |
检测仪输出的 VOC 原始值按 ppb 解析,上传时换算为 ppm:
1 ppm = 1000 ppb
固件会过滤明显异常的样本。例如 CO2 低于 300 ppm 时,日志会打印该组完整数据,但不会上传。
甲醛、VOC 和 CO2 使用五档颜色展示:绿色为优、蓝色为良、黄色为轻度污染、橙色为中度污染、红色为重度污染。
| 指标 | 优 | 良 | 轻度污染 | 中度污染 | 重度污染 |
|---|---|---|---|---|---|
甲醛 (µg/m³) |
0-80 |
80-120 |
120-200 |
200-400 |
400-800 |
VOC (ppm) |
<0.22 |
<0.44 |
<0.88 |
<1.76 |
<2.64 |
CO2 (ppm) |
<700 |
<1000 |
<1500 |
<2000 |
<3000 |
PM2.5 当前标注的参考限值为 50 µg/m³。温度舒适区间为 18-25.5 °C,湿度舒适区间为 40-60%。
env2metric/
firmware/esp32s3/ # YN038 ESP32-S3 固件
dashboards/ # SigNoz Dashboard 模板(保留供旧部署使用)
scripts/ # SigNoz 和 OneUptime Dashboard 创建脚本
设备协议参数、固件配置和开发说明见 firmware/esp32s3/README.md。
本项目以源码公开、限非商业使用的方式分享,不属于 OSI 定义的开源软件。各部分分别适用以下许可证,不是对同一内容提供任选许可:
| 内容 | 许可证 |
|---|---|
| 原创固件、脚本、测试、Dashboard 配置及构建配置 | PolyForm Noncommercial 1.0.0 |
| 原创外壳设计(SCAD、STL、图片)及项目文档 | CC BY-NC-SA 4.0 |
| 第三方组件 | 保留各自的许可证及版权声明 |
外壳和文档的作者署名为 frederic (@fr0der1c),项目为 env2metric。分享时须保留署名、项目来源和许可证链接,并说明修改;分享改编版本时须遵守相同方式共享条款。
非商业用途不等同于免费提供,具体许可范围以完整条款为准。Espressif USB 组件继续使用其 Apache-2.0 许可证,项目的非商业限制不适用于这些第三方组件本身。完整许可范围见 LICENSE。