如何新增基於 idryer-core 的新產品¶
當你在 idryer-core 上開發新產品(線材烘乾機、加熱模組、照明、感測器或其他模組)時,請使用本指南。它說明核心庫替你完成了什麼,以及產品程式碼需要補充什麼。
一個可以完整編譯的範例是 Build-Your-Own-iDryer 文件中的加熱儲料櫃(example/09-cabinet):它涵蓋了本頁的全部內容。
產品的基礎¶
產品透過一個物件與核心庫互動——外觀類別 iDryer::Link(<iDryer.h>)。在 s_link.begin() 和 s_link.loop() 中,核心庫會:
- 以無線方式(ESPTouch)從 iDryer 應用程式、或透過 USB(Improv)從網頁安裝程式取得 Wi-Fi 網路,並保持連線;
- 把裝置綁定到帳戶:等待一次性綁定權杖——來自應用程式(經區域網路)或來自序列埠(
PAIR_TOKEN:<token>)——並在門戶上換取永久金鑰; - 連接 MQTT,並依
Config中的週期發布telemetry和status; - 在區域網路中廣播自己(mDNS
_idryer._tcp),並透過 WebSocket 接收應用程式的指令; - 發布裝置卡片的 card 清單。
更底層的類別(IdryerRuntime、CloudStateMachine、LocalAccess 等)是核心庫的內部實作:綁定權杖只有在 iDryer::Link 內部才會傳到雲端部分。請在外觀類別之上建立產品。
1. 專案¶
idryer-core 放在 lib/idryer-core/(複製或符號連結);PlatformIO 從它的 library.json 取得核心庫的相依套件。最小的 platformio.ini:
[env:my-device]
platform = espressif32
framework = arduino
board = esp32-c3-devkitm-1
; 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
沒有 lib_ignore = ESPAsyncTCP,建置會在 ESPAsyncTCP.cpp 處失敗;沒有 MQTT_BROKER 和 MQTT_PORT,核心庫無法編譯。
2. 最小韌體¶
#include <iDryer.h>
static const iDryer::Config CFG = {
.deviceType = iDryer::DeviceType::Unknown, // 不是 iDryer 產品:卡片來自清單
.unitsCount = 1,
.hasAirTemp = true,
.hasAirHumidity = true,
.hardwareVersion = "1.0",
.firmwareVersion = "0.1.0",
.model = "My Device",
};
static iDryer::Link s_link(CFG);
void setup() {
s_link.begin();
// 裝置在門戶上被解除綁定:清除金鑰,等待重新綁定。
s_link.onCommand("revoke", [](JsonObjectConst) { s_link.handleRevoke(); });
}
void loop() {
s_link.loop();
s_link.telemetry.airTempC[0] = readTemp(); // 你的感測器函式
s_link.telemetry.airHumidityPct[0] = readHumidity();
}
s_link.begin() 啟動 Wi-Fi、綁定、MQTT 和本機存取;s_link.loop() 必須一直執行,不能使用 delay()。當裝置從帳戶解除綁定時,門戶會送來 revoke 指令:handleRevoke() 清除金鑰,裝置等待新的綁定權杖。
3. Wi-Fi 和綁定——不寫在程式碼裡¶
韌體中既沒有網路密碼,也沒有帳戶資料。使用者在 iDryer 應用程式中連接裝置:连接新设备 → Wi-Fi 步驟(應用程式透過 ESPTouch 傳送網路)→ 绑定 步驟(應用程式透過 mDNS 找到裝置,從門戶取得一次性權杖並交給裝置;裝置自己在門戶上啟用權杖)。在 Wi-Fi 連上之前,序列埠不會輸出:核心庫把它留給網頁安裝程式(Improv)。
分步說明和預期日誌——Build-Your-Own-iDryer,「在核心庫上啟動韌體」一章。
4. 資料:遙測和狀態¶
Config中的has*旗標決定哪些詞彙欄位進入遙測、卡片上出現哪些儲存格。- 把值寫入
s_link.telemetry(airTempC、airHumidityPct、heaterTempC、heaterPower01、fanOn、servoOpen)和s_link.status(mode、targetTempC、durationS、elapsedS);核心庫依Config中的週期發布它們,s_link.publishStatusNow()會立即傳送狀態。 - 自訂欄位——透過
s_link.onTelemetryPublish(),顯示到卡片上——透過s_link.card().sensor();見裝置卡片。
5. 設定:選單¶
設定在 src/menu/menu.yaml 中描述;產生器 menu_gen.py 由此產生 C++ 程式碼、NVS 儲存和選單 JSON(作為協定的選單)。產品程式碼:
- 在
s_link.begin()之前載入選單:menu.initDefaults()、menu.loadFromNVS()、menu_sync_state_to_cache(); - 用
menu_buildFullJson()和s_link.devicePublisher()->publishConfigRaw()發布選單——在上線時以及收到get_config指令時; - 用
menu_apply_by_bind()套用set指令(值、NVS 和快取一次完成),然後重新發布選單。
完整程式碼——Build-Your-Own-iDryer,「來自 YAML 的選單」一章。
6. 裝置卡片¶
卡片顯示什麼、啟動哪些操作,用 s_link.card() 宣告——裝置卡片:card 清單。
7. 合約¶
當你新增新主題或修改負載時:
- 更新
contracts/mqtt_contract.yaml; - 執行
contracts/regen.sh並提交產生的檔案。
雙晶片裝置¶
對於透過 UART 與獨立控制器(例如 RP2040)協作的 ESP32,核心庫提供 UART 橋接 idryer_uart.h;可執行的參考實作是 idryer-link 韌體。