Zum Inhalt

Neues Produkt auf Basis von idryer-core hinzufügen

Diese Anleitung ist für neue Produkte auf Basis von idryer-core: Filamenttrockner, Heizblock, Beleuchtung, Sensor oder anderes Modul. Sie zeigt, was in der Bibliothek bleibt und was in den konkreten Produktcode gehört.

Eine praktische Checkliste zum Erstellen eines neuen Geräts auf der Basis von idryer-core.

Zwei Szenarien:

  • Minimal — MQTT + Cloud nur. Ausreichend für die meisten einfachen Geräte.
  • Erweitert — MQTT + lokaler WS-Zugriff über LAN. Für Geräte, die lokalen Zugriff ohne die Cloud benötigen.

Szenario 1: Minimales MQTT-only-Gerät

Minimales Set: WiFi, MQTT, Cloud State Machine, ein Profil.

Referenz: examples/minimal_mqtt_only/

1. Implementieren Sie IProfile

// src/mydevice/my_profile.h
#include <profiles/IProfile.h>

class MyProfile : public idryer::IProfile {
public:
    void onOnline() override;
    void loop() override;
    void getConfig(JsonDocument& out) override;
    bool applyConfig(int id, int val) override;
    void buildInfoJson(char* buf, size_t len) const override;
};

2. Montieren Sie die Composition Root

#include <idryer_core.h>

static idryer::ArduinoWifiStore       s_wifiStore;
static idryer::ArduinoWifiManager     s_wifi;
static idryer::ArduinoCredentialStore s_credentials;
static idryer::ArduinoHttpClient      s_http;

static idryer::cloud::HttpApi           s_api(&s_http, IDRYER_API_BASE);
static idryer::MqttClient               s_mqtt;
static idryer::cloud::CloudStateMachine s_cloud(&s_wifi, &s_credentials, &s_api, &s_mqtt);
static idryer::ActionDispatcher         s_dispatcher;

static MyProfile             s_profile;
static idryer::IdryerRuntime s_runtime(&s_cloud, &s_dispatcher, &s_profile, &s_mqtt);

3. Registrieren Sie den Command Handler und starten Sie

static void handleCommand(const char* cmd, JsonObjectConst data) {
    const char* action = data["action"] | "";
    if (strcmp(cmd, "get_config") == 0 ||
        (strcmp(cmd, "invoke") == 0 && strcmp(action, "device.getConfig") == 0))
    {
        StaticJsonDocument<256> doc;
        s_profile.getConfig(doc);
        s_mqtt.publishConfig(doc);
        return;
    }
    if (strcmp(cmd, "invoke") == 0) { s_dispatcher.handleInvoke(data); return; }
    if (strcmp(cmd, "set") == 0)    { s_dispatcher.handleSet(data);    return; }
}

void setup() {
    Serial.begin(115200);
    idryer::hal::initArduinoHal(&Serial);
    // ... load WiFi credentials, seedSerialFromMac ...
    s_runtime.setCommandHandler(handleCommand);
    s_runtime.begin();
}

void loop() {
    s_runtime.loop();
}

Szenario 2: MQTT + Local WS Gerät

Erweitert Minimal. Fügt LocalAccess (LAN WebSocket + mDNS) und DevicePublisher hinzu — ein dünner Wrapper zum Veröffentlichen auf beiden Transporte in einem Aufruf.

Referenz: examples/mqtt_with_local_ws/

Zusätzliche Objekte

#include <local_access/local_access.h>
#include <local_access/device_publisher.h>

static idryer::LocalAccess     s_local;
static idryer::DevicePublisher s_pub(&s_mqtt, &s_local);

Command Handler — einer für beide Transporte

static void handleCommand(const char* cmd, JsonObjectConst data) {
    const char* action = data["action"] | "";
    if (strcmp(cmd, "get_config") == 0 ||
        (strcmp(cmd, "invoke") == 0 && strcmp(action, "device.getConfig") == 0))
    {
        StaticJsonDocument<256> doc;
        s_profile.getConfig(doc);
        s_pub.publishConfig(doc);   // → MQTT + WS
        return;
    }
    if (strcmp(cmd, "invoke") == 0) { s_dispatcher.handleInvoke(data); return; }
    if (strcmp(cmd, "set") == 0)    { s_dispatcher.handleSet(data);    return; }
}

Initialisierung in setup()

s_credentials.seedSerialFromMac();
{
    idryer::DeviceIdentity identity;
    s_credentials.load(identity);
    s_local.initMdns(identity.serialNumber);   // mDNS before WS starts
    s_local.begin(identity.serialNumber, identity.token);
    s_local.setCommandSink(handleCommand);     // same handler
    s_local.setTokenRefreshCallback([]() {
        idryer::DeviceIdentity id;
        s_credentials.load(id);
        s_local.updateToken(id.token);
    });
}
s_runtime.setCommandHandler(handleCommand);
s_runtime.begin();

loop()

void loop() {
    s_runtime.loop();
    s_local.loop();
    // product logic — sensors, telemetry via s_pub
}