Pokażę tutaj jak wygląda tworzenie strony WWW dla dowolnego urządzenia IoT na wieloplatformowym firmware OpenBeken, chociaż to samo podejście oferować będzie również kompatybilność z Tasmotą (zgodność wysyłanych komend oraz zwracanego formatu JSON). Stronę do kontroli urządzenia napiszemy w HTML i Javascripcie, zahostujemy ją na samym urządzeniu IoT w systemie plików LittleFS a komunikacja tej strony z samą podstawą obsługi urządzenia odbędzie się poprzez Ajax i interfejs REST, co oznacza, że strona też będzie się odświeżać bez przeładowywania.
Podstawa interfejsu REST OpenBeken/Tasmota
OpenBeken ma interfejs REST zgodny z podstawą Tasmoty, co oznacza, że składania komend i zwracanych danych jest w dużej mierze taka sama.
Samą komendę wysyłamy przez HTTP GET, przykładowo:
http://192.168.0.201/cm?cmnd=POWER%20ON
Jest to komenda POWER z argumentem ON, czyli np. włączenie przekaźnika bądź zapalenie lampki.
Wtedy urządzenie zwraca JSON:
Kod: JSON
Komendy i zwracane JSON znajdują się w dokumentacji Tasmoty. Warto też zajrzeć do dokumentacji OBK, która jest bieżąco rozwijana.
https://github.com/openshwprojects/OpenBK7231T_App/blob/main/docs/README.md
Informacje o urządzeniu można pobrać poprzez wysłanie komendy bez argumentu - np. samego POWER.
Podstawa HTML, Javascript, JSON
Ten temat zakłada, że czytelnik ma podstawową wiedzę o wspomnianych w tym akapicie tematach. HTML (wraz z CSS) pozwala stworzyć wygląd strony, jej kontrolki, i tak dalej, Javascript pozwala je odpowiednio oskryptować - przechwycić zdarzenia od użytkownika a potem wysyłać i odbierać odpowiednio dane. Javascript tutaj przetwarza dane w połączeniu z Ajax, czyli strona nie jest przeładowywana cała, tylko sam Javascript w tle wysyła dane, odbiera i aktualizuje tylko wybrane kontrolki. Z kolei JSON to format w którym są odbierane dane, pozwala on na tekstową reprezentację obiektów (z parami klucz/wartość), tablic, itd.
W tej tematyce polecam m. in. kurs W3:
https://www.w3schools.com/html/
https://www.w3schools.com/js/
https://www.w3schools.com/js/js_ajax_intro.asp
https://www.w3schools.com/js/js_json_intro.asp
System plików LittleFS na OpenBeken
System plików LittleFS dostępny jest z poziomu panelu Web App, czyli panelu który sam pobierany jest z Githuba a z urządzeniem IoT komunikuje się już sam w sobie przez interfejs REST. Oczywiście, nie znaczy to też że bez internetu nie dostaniecie się na ten panel - jak chcecie, to można jego źródła zahostować u siebie w sieci i po prostu zmienić ich adres w konfiguracji OBK.
Otwieramy Web Panel:
Otwieramy zakładkę LittleFS:
Oto interfejs systemu plików:
Create tworzy nowy plik, List odświeża ich listę.
Tu możemy tworzyć autoexec.bat (który wykonywany jest na początku), dowolne inne skrypty dla komendy startScript, oraz właśnie pliki HTML i skrypty.
Możemy również przeciągnąć istniejące pliki na pole
Hello World OBK
Utworzymy podstawowy dokument - Create File, hello.html:
Możemy tam wkleić cokolwiek - chociażby bazowy dokument HTML:
Kod: HTML, XML
W ten sposób (po zapisaniu) będzie on dostępny pod ściezką:
http://192.168.0.201/api/lfs/hello.html
Oto nasz pierwszy dokument HTML zahostowany (w tym przypadku) na lampce LED 12W!
Interfejs REST - najprostszy przycisk
Interfejs REST OBK jest w dużej mierze zgodny z Tasmotą. Wszystkie te komendy POWER, STATUS, są podobnie zaimplementowane.
Spróbujmy zatem zrobić kontrolę POWER (stanu on/off) lampki.
Dla ułatwienia podpiąłem tutaj styl bootstrap.
Na początek - gotowy przykład i rezultat:
Kod: HTML, XML
Kopia kodu: https://github.com/openshwprojects/OpenBekenRESTDemo/blob/main/examples/Generic_Power.html
Powyższa strona to SPA (Single Page Application), najprostsza z możliwych na OBK, demonstrojąca użycie komendy POWER Tasmoty do kontroli stanu LED.
Strona ta robi zasadniczo dwie rzeczy:
- po załadowaniu okienka wysyła puste POWER (bez argumentu) do urządzenia, by pobrać bieżacy stan zasilania LED
- po kliknięciu przycisku próbuje przełaczyć stan LED na przeciwny
Kolor przycisku odzwierciedla stan LED:
Ten fragment:
let baseURL = "http://192.168.0.210";
Pozwala mi ją uruchamiać na Windowsie, czyli zasadniczo z dowolnego miejsca, bo ustawia on IP urządzenia. Przy wrzucaniu na LittleFS urządzenia, ta zmienna powinna być pustym napisem.
Zapytanie REST po HTTP GET wykonuje ten fragment:
Kod: Javascript
Zgodnie z dokumentacją Tasmoty, POWER bez argumentu zwróci tylko bieżący stan, a z argumentem (ON, OFF lub Toggle) go zmieni.
Można to przetestować w przeglądarce:
Ten fragment odświeża stan LED po załadowaniu strony:
Kod: Javascript
Poniższy fragment to funkcja pomocnicza zmieniająca kolor/styl przycisku:
Kod: Javascript
A poniżej mamy sam przycisk - wraz z podpiętym wywołaniem API z argumentem TOGGLE (tutaj z dodatkową spacją):
Kod: HTML, XML
Pasek do kontroli jasności
Idąc tym tropem możemy dodać obsługę ściemniacza. Najpierw potrzebny będzie slider:
Kod: HTML, XML
Potem trzeba jeszcze jakoś odebrać jako początkowy stan oraz obsłużyć jego zmianę.
Event zmiany dodaje się tak:
Kod: Javascript
Funkcji sendCmnd jeszcze nie ma, ale to jest przerobiona sendPower tak by brała dowolną komendę. To dlatego, że dla kontoli jasności LED można skorzystać z komendy Dimmer.
Oto cały kod:
Kod: HTML, XML
Kopia kodu: https://github.com/openshwprojects/OpenBekenR...mo/blob/main/examples/LED_PowerAndDimmer.html
Rezultat:
Zarówno przycisk, jak i pasek działają. I to nawet z Tasmotą! Tylko wtedy trzeba HTML zapisać na dysku, a OBK ma swój mini-hosting w LittleFS.
Zmiana koloru
Dla wyboru koloru też istnieje specjalna kontrolka w HTML5:
Kod: HTML, XML
Równie łatwo można złapać zdarzenie jej zmiany:
Kod: Javascript
W tym przypadku użyłem komendy z OBK w celu ułatwienia sobie pracy, led_basecolor_rgb zwraca kolor w postaci zgodnej z HTML.
Tak wygląda zaktualizowane zdarzenie 'change':
Kod: Javascript
Dodatkowo zmodyfikowałem funkcję wysyłającą komendę tak, by przed użyciem pól z odpowiedzi sprawdzała, czy one istnieją:
Kod: Javascript
Rezultat:
Poglądowo - skrypt jest tutaj:
https://github.com/openshwprojects/OpenBekenR.../blob/main/examples/LED_PowerDimmerColor.html
Temperatura światła
Analogicznie można obsługiwać temperaturę bieli. Jest ona dostępna w produktach CW oraz RGBCW. Czasem też jest emulowana diodami RGB (+diodą ciepłej bieli), ale o tym innym razem.
Wystarczy komenda CT, która też jest zgodna z Tasmotą.
Oto strona po dodaniu drugiego paska:
Dodany HTML:
Kod: HTML, XML
Javascript (wysyłanie zmiany):
Kod: Javascript
Javascript (odbiór stanu, fragment do wklejenia do bloku then):
Kod: Javascript
Warto zwrócić uwagę na to, że dzięki strukturze JSON Tasmoty, wystarczy jeden blok do odebrania różnych wartości takich jak CT czy tam POWER.
Poglądowo - skrypt jest tutaj:
https://github.com/openshwprojects/OpenBekenR...examples/LED_PowerDimmerColorTemperature.html
Kanały OpenBeken
OpenBeken wprowadza nieco odmienny od Tasmoty koncept, tzw. kanały, które tak naprawdę są zmiennymi ogólnego przeznaczenia i pozwalają na łączenie razem różnych peryferiów i skryptów. Kanał może zawierać wszystko, od stanu przekaźnika (1 lub 0), poprzez PWM (od 0 do 100), aż do np. wartości odczytanej z ADC lub po prostu nawet zwykły licznik zdarzeń (np. jak chcemy by po N zdarzeniach system podejmował jakąś akcję).
Dostęp do kanałów OpenBeken dostępny jest m. in. przez komendę:
http://127.0.0.1/cm?cmnd=Ch1%20100
Podstawowa składania to Ch, potem bez spacji indeks kanału oraz. ew. jego wartość jeśli chcemy go ustawić a nie tylko odczytać. Analogicznie do Tasmoty.
Wspierany jest też zapis w stylu Ch+4, gdzie + oznacza, że chcemy do wartości kanału coś dodać.
OBK zwraca wtedy taki JSON:
Kod: JSON
Obecność kanałów w pakiecie determinuje to, czy są one używane - np. zmapowanie kanału na przekaźnik lub na ADC (lub ustawienie mu typu) powoduje, że kanał pojawia się w tych używanych.
Bardzo ważne jest też wspomnieć o kompatybilności z TuyaMCU. W OpenBeken można zmapować dowolną zmienną TuyaMCU na kanał, nawet taką, której typ nie był przewidziany w trakcie tworzenia software (przykładowo, nie wiem, poziom pyłków w powietrzu czy stężenie gazu) a potem poprzez interfejs REST przekazać dalej do przetwarzania.
Oprócz tego dostępne są nieco starsze komendy, które zwracają wartość w postaci tekstu:
- SetChannel [indeks] [wartość] - ustawia kanał na daną wartość i zwraca bieżącą wartość
- AddChannel [indeks] [wartość] - dodaje wartość do kanału i zwraca bieżącą wartość
- GetChannel [indeks] - po prostu zwraca bieżącą wartość
Ale ogólnie lepiej używać wspólnej komendy Ch*, o której już wspominałem.
W oparciu o dostęp do kanałów wykonałem dla zabawy kontroler frytkownicy:
źródło umieszczem na Githubie: https://github.com/openshwprojects/OpenBekenRESTDemo/blob/main/examples/TuyaMCU_AirFryer.html
Pobieranie informacji o urządzeniu, o sensorach, pomiarach energii elektrycznej
OpenBeken również wspiera komendy STATUS w stylu Tasmoty, czyli można pobrać przez nie opis JSON całego stanu urządzenia. Przykładowo, dla urządzenia z BL0942 (pomiar energii elektrycznej) możemy uzyskać:
Kod: JSON
Analogicznie dla wielu innych czujników, zarówno w Tasmocie, jak i w OpenBeken, np. cała rodzina DHT (DHT11 i podobne), itd. też w JSON publikuje swoje wyniki.
A czy można w drugą stronę?
Cała prezentacja opierała się na założeniu, że to urządzenie IoT jest mini serwerem i odpowiada na żądanie GET, ale czy można zrobić to na odwrót?
Tak składa się, że w OpenBeken jest komenda SendGET, która również wspiera podstawianie zmiennych (kanałów), więc nic nie stoi na przeszkodzie by w timerze lub w zdarzeniu onChange raportować pomiary z urządzenia do zewnętrznego serwera (nawet takiego na hostingu HTTP w sieci). Ale o tym już innym razem.
Podsumowanie
Z tej krótkiej zabawy można wyciągnąć następujące wnioski:
- zarówno dla Tasmoty, jak i dla OpenBeken, można łatwo napisać prostę stronkę do sterowania danym urządzeniem
- można ją zahostować np. na samym OpenBeken w systemie plików LittleFS, ale też można ją zostawić jako dokument HTML choćby na naszym komputerze, albo na dowolnym hostingu HTTP (np. na Raspberry)
- taka strona może mieć dowolny styl i dowolny interfejs, w CSS można zrobić naprawdę wszystko
- interfejs REST zasadniczo daje dostęp do wszystkiego, więc możliwe jest utworzenie naprawdę dowolnych kontrolerów do każdego zastosowania
- OpenBeken oferuje również prosty język skryptowy, więc można nawet na stronie umieścić pola dla tworzenia automatyzacji, np. można konfigurować czas włączenia zraszaczy a potem realizować ich obsługę już na samym OBK (firmware wspiera pobieranie czasu z NTP oraz wspiera zdarzenia ustawiane na daną godzinnę danego dnia)
Możliwości są naprawdę bardzo duże. Poza kontrolą pojedynczego urządzenia zasadniczo można też by zrobić jedną stronkę zbiorczą dla wielu urządzeń, czyli zasadniczo taki własny DIY Home Assistant.
Zatem czy są jakieś minusy?
Jednym z minusów może być natura samego Javascriptu i tego, że taka stronka tylko działa jeśli mamy ją otwartą w przeglądarce, czyli np. ładnego zapisu pomiarów poboru mocy z BL0942 do wykresu na tym nie zrobimy, no chyba, że chcemy mieć tylko wykres z czasu kiedy mamy otwartą stronę internetową. Przy okazji dodam, że informacje między sesjami można by trzymać po stronie przeglądarki w cookies, ale to już co innego...
Mimo wszystko uważam, że możliwości i tak są duże. Wkrótce postaram zaprezentować się bardziej praktyczny przykład takiej strony, ale to już w innym temacie.
Fajne? Ranking DIY Pomogłem? Kup mi kawę.