Перейти к содержанию

Старт прошивки на ядре

На этой странице вы создаёте проект прошивки, доводите ESP32 до состояния Online на портале и проверяете, что сетевая часть работает. Датчики и логику нагрева добавим на следующих шагах.

Подход построен на фасаде iDryer::Link. Вы описываете устройство одной структурой iDryer::Config, вызываете link.begin() и link.loop() — всё подключение к сети ядро делает само.

1. Подготовьте инструменты

Понадобится:

  • VS Code с расширением PlatformIO;
  • USB-кабель;
  • Wi-Fi-сеть 2.4 GHz (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 — транспорт ESP8266 из зависимостей espMqttClient:
; на 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). Саму idryer-core указывать в lib_deps не нужно — она лежит в 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. Прошейте

pio run -e cabinet -t upload

8. Откройте Serial Monitor

pio device monitor -b 115200

Пока у устройства нет 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 и привяжите устройство в приложении

  1. Подключите телефон к той сети Wi-Fi, в которой будет работать устройство (2.4 GHz), и войдите в приложение iDryer под своим аккаунтом портала.
  2. На главном экране нажмите Подключить новое устройство — откроется шаг Wi-Fi.
  3. Проверьте название сети (приложение подставляет его само, если включена геолокация), введите пароль и нажмите Подключить устройство. Приложение передаёт настройки до 90 секунд; когда устройство подключится к сети, появится Устройство подключено. Нажмите Далее.
  4. На шаге Привязка нажмите Привязать. Приложение найдёт устройство в сети, получит у портала одноразовый токен привязки, передаст его устройству и дождётся, пока портал подтвердит, что устройство вышло на связь.
  5. После Устройство привязано оно появится в списке устройств на портале и в приложении.

Если устройство уже в сети, сразу откройте шаг Привязка — нажмите его чип вверху окна.

Шаг Wi-Fi в приложении: имя сети и пароль Шаг Wi-Fi: приложение передаёт сеть устройству по воздуху.

Шаг привязки: приложение нашло устройство в сети Шаг Привязка: приложение нашло устройство в сети по его серийному номеру. Чужие устройства помечены как занятые.

Сообщение «устройство привязано» Готово: устройство привязано к аккаунту и сейчас появится в списке.

В логе видна привязка:

[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;
  • сеть так и не передаётся по воздуху — сделайте то же самое по USB через веб-установщик install.idryer.org;
  • на шаге Привязка приложение не нашло устройство — телефон и устройство должны быть в одной сети, и сеть не должна блокировать обнаружение устройств (гостевые сети часто блокируют);
  • устройство перезагружается — проверьте питание ESP32 (просадки напряжения при старте — частая причина сбросов);
  • сборка падает с ошибкой — спросите в сообществе: Telegram, Discord;
  • см. Ошибки питания и Ошибки контроллера.

Что дальше

Сетевая часть работает. Переходите к Датчикам: подключим SHT31 и термистор и увидим их данные на портале.