Hardware + Software - framework pod IoT z arduino dla ESP8266 oraz ESP32

7

Cześć,

Od kilku lat dłubię sobie frameworka internetu rzeczy, który napędza mi w domu całe rozwiązania typu smarthome. Ostatnimi czasy zbudowałem bramkę do Zigbee, która też napędzana jest owym frameworkiem.

Na początku wspierałem ESP8266, potem też ESP32. Pod spodem jest Arduino core a całość działa w oparciu o PlatformIO. Dążę do eliminacji Arduino, jednak w przypadku ESP8266 to bardzo trudne zadanie, bo będzie wymagać przygotowania własnej paczki platformy (to co jest w rejestrach to średniowieczne wersje ~1.5, a ostatnia to 3.4).

Funkcje

  • zdecydowałem na wstępie, że chciałbym pójść w kierunku kompzycji, realizowanej na wzór... Unity3D
  • głównym obiektem jest rotator aplikacji, który tworzony jest na starcie aplikacji
  • rotator posiada listę aplikacji, które są instancjonowane i wykonywane do końca - po zakończeniu aplikacji wstaje następna a na koniec się to zapętla
  • zwykle oprogramowanie urządzenia składa się z aplikacji funkcjonalnej (zachowanie urządzenia) oraz konfiguracyjnej (własny access point)
  • mając wskaźnik do aplikacji możemy wyszukiwać komponenty po typie i w łatwy sposób unikać sztywnych referencji
  • komponenty można dodawać i usuwać w trakcie działania aplikacji a stosując mechanizm lock i weak_ptr pisać stabilny i bezpieczny kod

Komponenty

Poza samym szkieletem, użytkownik może korzystać z komponentów wewnętrznych, jak i swoich własnych. Wśród komponentów wewnętrznych, mamy takie jak:

  • portal urządzenia po HTTP w sieci lokalnej, z terminalem, statusem a także możliwością aktualizacji oprogramowania
  • komponent połączenia MQTT
  • komponenty konfiguracji (dostawcy oraz nadrzędny)
  • komponent wysyłający statystyki urządzenia (RSSI, IP i inne)
  • komponent realizujący różne funkcje przycisku RESET

Moje urządzenia

Na bazie frameworka zbudowałem kilka swoich urządzeń, niektóre są open source:

Fragmenty kodu

/*
    Budowanie listy komponentów, inicjalizacja aplikacji.
*/
bool EnergyMonitorApp::init()
{
    /* Add WiFi connector component. */
    addComponent<ksf::comps::ksWifiConnector>(apps::config::EnergyMonitorConfig::emonDeviceName);

    /* Add MQTT components. */
    auto mqttWp{addComponent<ksf::comps::ksMqttConnector>()};
    addComponent<ksf::comps::ksDevStatMqttReporter>();

    /* Add LED indicator components. */
    statusLedWp = addComponent<ksf::comps::ksLed>(STATUS_LED_PIN);
    eventLedWp = addComponent<ksf::comps::ksLed>(EVENT_LED_PIN);

    /* Create Device Portal component. */
    addComponent<ksf::comps::ksDevicePortal>();

    /* Add sensor component. */
    auto sensorCompWp{addComponent<components::EnergySensor>(ANA_PIN)};

    /* Setup reset button. */
    addComponent<ksf::comps::ksResetButton>(CFG_PUSH_PIN, LOW);

    /* Bind MQTT connect/disconnect events for LED status. */
    if (auto mqttSp{mqttWp.lock()})
    {
        mqttSp->onConnected->registerEvent(connEventHandleSp, std::bind(&EnergyMonitorApp::onMqttConnected, this));
        mqttSp->onDisconnected->registerEvent(disEventHandleSp, std::bind(&EnergyMonitorApp::onMqttDisconnected, this));
    }

    /* Set event LED. */
    if (auto sensorCompSp{sensorCompWp.lock()})
        sensorCompSp->setEventLed(eventLedWp);

    /* Start blinking status LED. */
    if (auto statusLedSp{statusLedWp.lock()})
        statusLedSp->setBlinking(500);

    return true;
}
/*
    Etap post-inicjalizacji. To miejsce w którym można wyszukiwać komponenty w aplikacji.
    Dzięki temu możemy wyszukać np. komponent MQTT i zarejestrować callback reagujący na zdarzenie.
*/
bool AudioPlay::postInit(ksf::ksApplication* app)
{
    using namespace std::placeholders;

    if (mqttWp = app->findComponent<ksf::comps::ksMqttConnector>(); auto mqttSp{mqttWp.lock()})
    {
        mqttSp->onDeviceMessage->registerEvent(msgEventHandleSp, std::bind(&AudioPlay::onMqttDevMessage, this, _1, _2));
        mqttSp->onConnected->registerEvent(connEventHandleSp, std::bind(&AudioPlay::onMqttConnected, this));
    }

    return true;
}
/*
    Obsługa wiadomości TTS. Najpierw parsujemy a potem dodajemy do playlisty efekt dźwiękowy, po którym
    zostanie odtworzona wiadomość głosowa. Podobnie jak zapowiadanie pociągu na stacji PKP :)
*/
void AudioPlay::onMqttDevMessage(const std::string_view& topic, const std::string_view& payload)
{
    if (payload.empty())
        return;

    std::string_view flashFileName;

    if (topic == PSTR("info"))
        flashFileName = PSTR("/info.mp3");
    else if (topic == PSTR("alarm"))
        flashFileName = PSTR("/alarm.mp3");
    else 
        return;

    std::string_view languagePayload;
    std::string_view textPayload;

    if (payload.size() > 3 && payload[2] == ':')
    {
        languagePayload = payload.substr(0, 2);
        textPayload = payload.substr(3);
    }
    else 
    {
        languagePayload =  PSTR("en");
        textPayload = payload;
    }
    
    if (!flashFileName.empty())
        enqueueAudioCommand<PlayFromFlashCommand>(std::string(flashFileName));
    
    enqueueAudioCommand<TextToSpeechCommand>(std::string(textPayload), std::string(languagePayload));
}

Galeria

screenshot-20240412224901.png
screenshot-20240412224739.png
screenshot-20240412230645.png

Linki

Dajcie znać, co sądzicie 😀

1

Wielki szacun, kawał dobrej roboty 😀

Pytanie - jakie masz plany odnośnie tych swoich projektów? Na razie sobie robisz dla własnej satysfakcji, ale potem jakoś puścisz to w świat? Wiem - jest to udostępnione, ale to tak bardziej na zasadzie że podzieliłeś się tym, co masz, a nie jakiś OSS projekt z tego powstał. Czy planujesz to dalej rozwijać? Skorzystać z pomocy innych ludzi w tworzeniu kolejnych wersji?

I (tylko proszę - nie odbierz tego jako złośliwości czy szydery) - po co wrzuciłeś? W sensie - bardziej się pochwalić, czy oczekujesz na feedback/ocenę? Bo w sumie napisałeś trochę o projekcie, ale nie zaznaczyłeś, czego od nas oczekujesz ;)

Pytanie - czemu pisałeś wszystko samodzielnie, zamiast skorzystać z różnych (zarówno gotowych, jak i otwartych/darmowych) istniejących rozwiązań? Żadne Ci nie pasowało, czy po prostu chciałeś to zrobić dla siebie po swojemu? Nie jest to zarzut, sam też bym wolał tak zrobić (jakbym miał czas i wystarczające moce przerobowe), po prostu - chciałbym zrozumieć, co Ci chodziło po głowie (ponownie zaznaczam - nie jest to żadna szydera ani złośliwość).

No i najważniejsza sprawa - witam na forum. Super jest zobaczyć tutaj nowego użytkownika z pasją, wiedzą i doświadczeniem, a nie kolejnego trolla, który wpada, żeby pisać o polityce, wojnie i szczepionkach. Potrzeba więcej takich ludzi, jak Ty. Mam nadzieję, że powyższy post nie będzie Twoim ostatnim. Zwłaszcza, że widać, że masz dużą wiedzę - więc fajnie, jakbyś się zaangażował, zwłaszcza w działach Embedded oraz https://4programmers.net/Forum/C_i_C++ (oczywiście - niczego nie narzucam, to tylko taka sugestia).

Pytanie - to jest tylko Twoje hobby, a zawodowo zajmujesz się czymś innym, czy w pracy też masz styk z elektroniką/programowaniem?

1

@cerrato rozwijam hobbystycznie, oczekuję oceny, być może i adaptacji do projektów użytkowników. Po prostu chciałbym bibliotekę promować. Do tego trzeba zbudować bazę, zacząć dyskusje no i też zebrać feedback. Tego właśnie oczekuję 🙂

Bibliotekę zbudowałem dlatego, że w sumie nie było ciekawych rozwiązań. Gdy zaczynałem to popularna była usługa Blynk ale działało to topornie. Dzisiaj est ESPHome ale nadal nie zrobię na nim obsługi wszystkich urządzeń. Jedno z nich to moduł nadzorczy kotła grzewczego. Proces obróbki ramek CAN jest dość wymagający i nie sposób to ogarnąć bez kodu.

Dzięki za miłe słowa. Zawodowo też programowanie ale już bez elektroniki. W zasadzie w branży od ponad 10 lat. Wcześniej game development (Unreal Engine) a teraz można powiedzieć okolice backendu / low level stuff.

1 użytkowników online, w tym zalogowanych: 0, gości: 1