Composition Root¶
Продукт создаёт все объекты библиотеки в main.cpp как статические переменные и передаёт зависимости через конструкторы. Нет фабрик, нет глобального реестра — только явная сборка.
Порядок создания объектов¶
Зависимости строятся снизу вверх: сначала платформенный слой, потом облачный стек, потом рантайм.
// 1. Платформенный слой
idryer::ArduinoWifiStore s_wifiStore; // NVS: SSID/password
idryer::ArduinoWifiManager s_wifi; // управление WiFi
idryer::ArduinoCredentialStore s_credentials; // NVS: serial/token/deviceId
idryer::ArduinoHttpClient s_http; // TLS HTTP для provisioning
// 2. Облачный стек TODO: описание назначения
idryer::cloud::HttpApi s_api(&s_http, IDRYER_API_BASE);
idryer::MqttClient s_mqtt;
idryer::cloud::CloudStateMachine s_cloud(&s_wifi, &s_credentials, &s_api, &s_mqtt);
idryer::ActionDispatcher s_dispatcher;
// 3. Профиль продукта (реализует IProfile) — product code, не библиотека
LedStripProfile s_profile(&s_executor);
// 4. Рантайм — связывает всё
idryer::IdryerRuntime s_runtime(&s_cloud, &s_dispatcher, &s_profile, &s_mqtt);
Что делает setup()¶
void setup() {
// HAL: логи идут в /dev/null пока Improv владеет Serial
idryer::hal::initArduinoHal(nullptr);
// Восстановить сохранённые WiFi-credentials
char ssid[64], pass[64];
if (s_wifiStore.load(ssid, sizeof(ssid), pass, sizeof(pass))) {
s_wifi.begin(ssid, pass);
}
// Сгенерировать serial из MAC если ещё нет
s_credentials.seedSerialFromMac();
// Зарегистрировать обработчики команд
s_dispatcher.setInvokeHandler(onInvoke, nullptr);
s_dispatcher.setSetCallback(onSetCommand, nullptr);
// Опционально: реакция на переходы стейт-машины
s_cloud.setStateChangeCallback([](auto prev, auto, void*) {
if (prev == idryer::cloud::CloudState::WifiConnecting)
configTime(0, 0, "pool.ntp.org", "time.google.com");
}, nullptr);
// Автоматический claiming для standalone-устройств
s_cloud.setUnclaimedCallback([](void*) {
s_cloud.requestClaim();
}, nullptr);
// Запустить рантайм
s_runtime.begin();
}
void loop() {
s_runtime.loop(); // CloudStateMachine + IProfile::loop()
// ... продуктовая логика (сенсоры, телеметрия)
}
Правила сборки¶
- Все объекты библиотеки — статические (
static). Никакихnewиmallocдля объектов верхнего уровня. runtime.begin()вызывается последним вsetup(), после того как все обработчики зарегистрированы.runtime.loop()вызывается первым вloop().- Продуктовые объекты (сенсоры, телеметрия) создаются отдельно и подключаются к
s_mqttнапрямую — рантайм о них не знает.
Пример: Storage Link¶
Полный composition root Storage Link — src/main.cpp в репозитории
iDryer-Storage (опубликован отдельно).
Слои устройства в порядке сборки:
| Слой | Объекты | Источник |
|---|---|---|
| Платформа | s_wifiStore, s_wifi, s_credentials, s_http |
idryer-core |
| Облако | s_api, s_mqtt, s_cloud, s_dispatcher |
idryer-core |
| Устройство | s_executor, s_profile |
src/storage/led_strip/ |
| Рантайм | s_runtime |
idryer-core |
| Сенсоры | s_sensor, s_telemetry |
src/storage/sensors/, src/storage/telemetry/ |