传感器与遥测¶
本章过滤器开始测量空气并上报数据到云。关键技巧是**遥测中的自定义字段**:生态系统字典对VOC一无所知,但核心允许向遥测添加任何字段。
1. 传感器库¶
在platformio.ini的lib_deps中添加:
2. 读取SGP40¶
在src/main.cpp中(引脚来自接线图):
#include <Wire.h>
#include <Adafruit_SGP40.h>
static Adafruit_SGP40 s_sgp;
static int32_t g_vocIndex = -1; // -1 = 还没有数据
static void initVocSensor() {
Wire.begin(/*SDA=*/8, /*SCL=*/9);
if (!s_sgp.begin()) {
Serial.println("[VOC] SGP40 not found, check wiring");
}
}
static void readVocSensor() {
// measureVocIndex() 自己处理传感器的内部补偿。
// 指数:~100 = 普通空气,更高 = 更脏(最高500)。
g_vocIndex = s_sgp.measureVocIndex();
}
在setup()中调用initVocSensor()放在s_link.begin()后,readVocSensor()在loop()中每秒调用一次(用millis计时器,不用delay!):
static uint32_t s_lastReadMs = 0;
void loop() {
s_link.loop();
uint32_t now = millis();
if (now - s_lastReadMs >= 1000) {
s_lastReadMs = now;
readVocSensor();
}
}
loop中不要用delay()
s_link.loop()必须经常调用 —— Wi-Fi、MQTT和来自门户的命令都依赖它。delay(1000)会冻结所有这些。只用millis计时器。
3. 遥测中的自定义字段¶
每telemetryPeriodMs,核心自动收集遥测JSON消息并发送到云。对于我们的设备(一个单元,从字典中只有风机),核心收集这样的消息:
结构说明:
units—— 单元(干燥腔)数组。商业iDryer干燥机最多有四个独立腔室,所以遥测始终是数组,即使只有一个腔室;units[0]—— 第一个(也是我们唯一的)单元:我们在Config中指定了unitsCount = 1;fanStatus—— 字典字段,来自hasFan = true;rssi、uptime—— Wi-Fi信号强度和运行时间,核心总是添加。
这条消息中没有VOC —— 核心不知道我们的传感器。但在发送前,核心给你的代码一个机会在消息中添加自定义字段。为此你注册一个**回调**(callback,"回调函数")—— 一个函数,你把它交给核心,核心自己在每次发布时调用它,把收集的JSON(参数doc就是它)传入。
在setup()中:
s_link.onTelemetryPublish([](JsonObject doc) {
// doc —— 核心收集的遥测消息(见上面的JSON)。
// 我们向第一个单元添加自己的vocIndex字段。
if (g_vocIndex >= 0) {
doc["units"][0]["vocIndex"] = g_vocIndex;
}
});
doc["units"][0]["vocIndex"] = g_vocIndex;这一行读作:"在消息doc中取数组units,其中的元素0(我们唯一的单元),写入字段vocIndex"。字段名你自己起——在下一章中你要引用它来在卡片上显示这个值。
如果你看到"hook"这个词
在核心源代码中这个回调叫做PublishHook —— "hook"("钩子")意思相同:库给你"挂接"函数的地方。这些术语可互换;在本文档中我们说"回调"。
Lambda与为什么它是"空的"
构造[](JsonObject doc) { ... }叫做**lambda** —— 无名函数,写在使用地点,避免单独定义并取名。
开头的方括号 —— "捕获列表":列出函数带走的本地变量。核心规则:括号总是空的([])—— lambda不捕获任何东西,不带任何状态(这叫"无状态"或*stateless*)。
技术原因:带捕获的lambda需要动态内存分配,而ESP32上频繁分配会碎片化堆,最坏情况下会让Wi-Fi崩溃。所以核心只接受简单函数。
实际结果:回调需要的所有东西存放在**全局**变量中 —— 像我们的g_vocIndex。这个规则对所有idryer-core回调都适用。
风机状态用字典方式发布 —— 当你打开/关闭时写入核心字段(逻辑在第7章):
4. 检查¶
烧入固件后,在MQTT设备流中(或Serial日志中)遥测看起来像这样:
{
"units": [ { "unitId": "U1", "fanStatus": false, "vocIndex": 103 } ],
"rssi": -52,
"uptime": 120
}
vocIndex —— 你自己的字段,随着字典的fanStatus一起上云。门户已经接收并保存它,但还不知道怎么用:下一章告诉它。
对传感器呼气或靠近记号笔 —— 指数应该在几秒内明显上升。