在核心上启动固件¶
在本页中,你创建固件项目,使 ESP32 在门户网站上达到在线状态,并检查网络部分是否有效。在下一步中添加传感器和加热逻辑。
该方法基于 iDryer::Link 外观。你用一个 iDryer::Config 结构描述设备,调用 link.begin() 和 link.loop() — 核心库自己处理所有网络连接。
1. 准备工具¶
你需要:
- VS Code 与 PlatformIO 扩展;
- USB 电缆;
2.4 GHzWi-Fi 网络(ESP32 不适用于仅5 GHz网络);- 一部装有 iDryer 应用(App Store、Google Play)并已登录 iDryer 门户账户的智能手机:设备通过它获得 Wi-Fi 网络并绑定到账户;
- 核心库 idryer-core;
- 本章的现成项目 — 教程仓库中的 example/09-cabinet:传感器驱动以及后面建议复制的其他文件都从那里取。
什么是控制器固件以及它如何进入板——刷入控制器。
2. 创建项目¶
在 PlatformIO 中,项目是具有固定结构的文件夹。创建项目文件夹(例如 my-cabinet)并在 VS Code 中打开它。里面应该有这些文件:
my-cabinet/
├── platformio.ini # 构建设置(步骤 4 中填写)
├── lib/
│ └── idryer-core/ # 核心库(符号链接或副本)
└── src/
└── main.cpp # 设备代码:Config + setup() + loop()
下面的所有代码片段都放在这些文件中——每个步骤都指定了文件的位置。如果没有的话,手动创建 include/、lib/ 和 src/ 文件夹。
将 idryer-core 库放在 lib/ 中 — PlatformIO 自动在那里查找库。最简单的方法是对下载的库创建符号链接:
git clone https://github.com/pavluchenkor/idryer-core.git ~/idryer-core
ln -s ~/idryer-core lib/idryer-core
也可以不用符号链接,直接把库文件夹复制到 lib/idryer-core — 效果一样。
这也是菜单生成所需的(第 6 章)—— 钩子在 lib/idryer-core/ 内查找生成器。
3. Wi-Fi 和绑定不写在代码里¶
固件中既没有网络密码,也没有账户数据。首次启动时设备没有 Wi-Fi,会等待配置:iDryer 应用通过无线方式(ESPTouch)发送配置,然后用一次性绑定令牌把设备绑定到你的账户。这些都由核心库在 s_link.begin() 和 s_link.loop() 中完成,你只需在应用中完成步骤——见第 9 节。
网络是怎么进到设备里的。 没有保存网络的板子在监听空中信号,就像一台还没调到电台的收音机。手机这时把网络名称和密码"敲"到空气里 — 差不多像莫尔斯电码,只不过用的是 Wi-Fi 数据包。板子收到这段发送后连上网络,此后每次上电都自己接入。为此不需要额外的引脚和导线:用的是板子自带的天线,只要还没有网络就自动开启,最长持续 90 秒。
如果无线方式没成功,还有有线的办法:网页安装程序 install.idryer.org 通过 USB 把网络和绑定令牌传给板子 — 和应用做的事一样,只是走电缆。普通地重启板子也有帮助:重启后它会重新等待配置。
4. 配置 platformio.ini¶
填充项目根目录中的 platformio.ini:
[env:cabinet]
platform = espressif32
framework = arduino
board = esp32-c3-devkitm-1
; 核心库的依赖(MQTT、ArduinoJson、WebSockets、Improv)
; 会自动从 lib/idryer-core/library.json 引入。
; ESPAsyncTCP 是 espMqttClient 依赖中的 ESP8266 传输层:
; 它在 ESP32 上无法编译,必须排除。
lib_ignore = ESPAsyncTCP
build_flags =
-DIDRYER_API_BASE='"https://portal.idryer.org/api"'
-DMQTT_BROKER='"mqtt.idryer.org"'
-DMQTT_PORT=8883
-DMQTT_USE_TLS=1
将 board 替换为你的板(例如 esp32-s3-devkitc-1)。不需要在 lib_deps 中指定 idryer-core — 它在 lib/ 中(步骤 2)。
这些行的作用
无需列出核心库的依赖:PlatformIO 会从 lib/idryer-core/library.json 获取。lib_ignore = ESPAsyncTCP 是必需的——没有它,构建会在 ESPAsyncTCP.cpp 处失败。MQTT_BROKER 和 MQTT_PORT 标志也是必需的——没有它们核心库无法编译('MQTT_BROKER' was not declared)。
5. 在 Config 中描述设备¶
接下来的一切都发生在一个文件中 — src/main.cpp。打开它并记录本步骤和后续步骤的代码。
iDryer::Config 是设备的护照。has* 标志告诉门户网站设备有什么,并确定发布了哪些遥测字段。
对于加热柜,在 src/main.cpp 的开头
#include <iDryer.h>
static const iDryer::Config CFG = {
.deviceType = iDryer::DeviceType::Unknown, // 自制设备:卡片由清单生成
.unitsCount = 1,
.telemetryPeriodMs = 5000,
.statusPeriodMs = 10000,
.hardwareVersion = "1.0",
.firmwareVersion = "0.1.0",
.model = "DIY Storage Cabinet",
};
static iDryer::Link s_link(CFG);
has* 标志是与门户网站的合约
没有相应的 false 标志的遥测字段不会被发布。例如,如果没有 hasAirHumidity = true,湿度不会进入云端,即使你在代码中写入它。只包括设备中物理存在的内容。
组件和标志的列表——系统组成。
6. 最小主程序¶
在相同的文件中,在 Config 块之后添加 setup() 和 loop() 函数。对于首次启动,已经足够启动链接并在 loop() 中运行它:
void setup() {
Serial.begin(115200);
s_link.begin();
// 设备在门户上被解绑:清除密钥,等待重新绑定。
s_link.onCommand("revoke", [](JsonObjectConst) { s_link.handleRevoke(); });
}
void loop() {
s_link.loop();
}
s_link.begin() 会启动 Wi-Fi、绑定以及与门户的连接。当设备从账户解绑时,门户会发来 revoke 命令:handleRevoke() 清除设备密钥,设备随后等待重新绑定。传感器在传感器一步中添加。
本章后 src/main.cpp 的完整版本¶
将上面的两个块放在一个文件中 — 这是此步骤中的整个 src/main.cpp:
#include <iDryer.h>
static const iDryer::Config CFG = {
.deviceType = iDryer::DeviceType::Unknown, // 自制设备:卡片由清单生成
.unitsCount = 1,
.telemetryPeriodMs = 5000,
.statusPeriodMs = 10000,
.hardwareVersion = "1.0",
.firmwareVersion = "0.1.0",
.model = "DIY Storage Cabinet",
};
static iDryer::Link s_link(CFG);
void setup() {
Serial.begin(115200);
s_link.begin();
// 设备在门户上被解绑:清除密钥,等待重新绑定。
s_link.onCommand("revoke", [](JsonObjectConst) { s_link.handleRevoke(); });
}
void loop() {
s_link.loop();
}
前一章展示了**要添加什么**以及**更改后的完整 src/main.cpp**,这样你总能看到完整的画面,而不是分散的片段。
7. 刷入固件¶
8. 打开串口监视器¶
在设备连上 Wi-Fi 之前,日志不会输出:核心库把串口留给网页安装程序(Improv)。Wi-Fi 一连上,日志就会开启。对于尚未绑定的设备,日志最后是这样的:
[BOOT] WiFi ok, logs enabled
[INFO ] CLOUD: WiFi connected, IP: 192.168.1.42, RSSI: -55 dBm, …
…
[INFO ] CLOUD: binding-v3: no secret — awaiting pairing token (SETUP)
最后一行正是这一步需要的:网络有了,绑定密钥还没有,设备在等待应用发来的令牌。保持监视器打开,转到应用。
9. 在应用中连接 Wi-Fi 并绑定设备¶
- 把手机连接到设备将要使用的 Wi-Fi 网络(
2.4 GHz),并用门户账户登录 iDryer 应用。 - 在首页点击 连接新设备——打开 Wi-Fi 步骤。
- 核对网络名称(开启定位时应用会自动填写),输入密码并点击 连接设备。应用最多发送 90 秒;设备加入网络后显示 设备已连接。点击 下一步。
- 在 绑定 步骤中点击 绑定。应用在网络中找到设备,从门户获取一次性绑定令牌并交给设备,然后等待门户确认设备已上线。
- 显示 设备已绑定 后,设备会出现在门户和应用的设备列表中。
如果设备已经在网络中,可以直接打开 绑定 步骤——点击窗口顶部的对应标签。
在 绑定 步骤中:应用按序列号在网络中找到了设备。别人的设备标记为已占用。
日志中可以看到绑定过程:
[INFO ] CLOUD: binding-v3: pairing token received (… chars)
[INFO ] CLOUD: binding-v3: activating with pairing token (serial=DEVICE_… mcu=-)
[INFO ] CLOUD: binding-v3: activated, deviceId=… -> Ready
…
[INFO ] MQTT: Connected! …
检查结果¶
此时设备应在门户上显示为 Online。还没有传感器数据——这是正常的:Config 还没有声明任何传感器,卡片也就没什么可显示的。
门户上的设备:名称、Idle 状态、连接图标。没有读数——它们会在下一章出现。
Device DEVICE_… 是出厂名称。用名称旁边的铅笔图标给设备改名:后面的示例中它叫 "Storage cabinet"。
如果出了问题:
- 应用没有等到设备加入网络——检查密码以及网络是否为
2.4 GHz;密码错误时设备会重新等待配置,请重启板子并重复 Wi-Fi 步骤; - 网络始终传不过去——用网页安装程序 install.idryer.org 通过 USB 做同样的事;
- 在 绑定 步骤中应用没有找到设备——手机和设备必须在同一网络中,且网络不能阻止设备发现(访客网络常常会阻止);
- 设备反复重启——检查 ESP32 的供电(启动时的电压跌落是复位的常见原因);
- 构建报错——到社区里问:Telegram、Discord;
- 参见供电错误和控制器错误。
接下来¶
网络部分工作正常。转到传感器:连接 SHT31 和温度计并在门户网站上查看它们的数据。

