HubScreen – nowe funkcje i optymalizacja działania

Wstęp

Z racji, że ekran z projektu HubScreen posiadał dużo potencjału, który marnował się niewykorzystany, postanowiłem znaleźć dodatkowe zastosowania. Zostały one przedstawione poniżej.

Uniwersalna bramka ZigBee

Żeby znaleźć jakieś nowe zastosowanie dla działającego przez 24h/dobę Raspberry postanowiłem zbudować sobie uniwersalną bramkę ZigBee w oparciu o układ CC2531 i oprogramowanie Zigbee2Mqtt.

Wszystko zaczęło się od potrzeby posiadania termometru na balkonie, ale jak wiemy mamy XXI wiek, więc to nie mógł być taki zwykły termometr 😉 W tym celu zakupiłem układ sniffera ZigBee CC2531 na Aliexpress za ok. 15 zł i czujnik Xiaomi Aqara WSDCGQ11LM za 67 zł.

Układ CC2531 normalnie jest wykorzystywany jako sniffer ZigBee (przetestowany na sterownikach wykorzystywanych w pracy 😉 ), ale po zmianie firmware według tej instrukcji staje się uniwersalną bramką ZigBee. Problemem podczas prób uruchomienia Zigbee2Mqtt był fakt, że usługa chciała wystartować dopiero po zainstalowaniu Node.js w wersji 11.15.0.

Do wymiany firmware chciałem wykorzystać płytkę Raspberry Pi 4B, ale niestety przy próbie odczytania wersji firmware z układu CC2531 otrzymywałem odpowiedź ID = 0000 lub ID = ffff. Niedawno czytałem, że podobno ma pomagać aktualizacja biblioteki wiringPi, ale w moim przypadku z problemem sobie poradziłem poprzez zmianę płytki na Raspberry Pi 3B (RPi 3B).

Ze względu na wcześniejsze pomiary obciążenia Raspberry Pi Zero (RPi Zero) postanowiłem wymienić je na wspomniane przed chwilą Raspberry Pi 3B, które dzięki zwiększonej wydajności miało poradzić sobie z obsługą projektu HubScreen i nowym zadaniem bycia bramką ZigBee. Na początku nie wyglądało, żeby miały występować jakieś problemy, ale po kilku dniach pracy okazało się, że nie jest tak kolorowo:

  • procesor RPi osiągał temperaturę minimum 60°C niezależnie od obciążenia (aż radiator zaczął spływać z procesora; próbowałem nawet obniżać częstotliwość, ale niczego to nie zmieniało),
  • pobór energii zwiększył się 10-krotnie w porównaniu do tego co było przy RPi Zero.

Problemy wynikały zapewne z moich studenckich czasów, gdzie RPi 3B nie miało zbyt łatwego życia. Dlatego musiałem wrócić do RPi Zero i opracować rozwiązanie dla zbyt małej mocy obliczeniowej – a o nim już poniżej.

Zdalny pulpit

Z racji uruchomienia w ostatnim czasie domowego serwera najlepszym sposobem zmniejszenia obciążenia byłoby przeniesienie zadań wymagających dużej mocy obliczeniowej na platformę bardziej do nich przystosowaną.

I taką „platformą” został domowy serwer z systemem Windows Server 2019. Różnicę w obciążeniu widać na poniższym zrzucie ekranu (trzeba pamiętać, że RPi Zero obsługuje teraz dodatkowe zadanie pod postacią bramki ZigBee).

Obciążenie Raspberry Pi Zero przy nowym podejściu

Do obsługi projektu utworzyłem nowego użytkownika, który podczas logowania otwiera przeglądarkę internetową ze stroną hostowaną na RPi Zero. Dzięki temu, gdy RPi ma awarię albo po prostu jest wyłączone, nie jest zużywany transfer danych potrzebny do ciągłego odświeżania informacji wyświetlanych na Ekranie.

Zdalny pulpit uruchamiam w systemie Linux dzięki aplikacji Remmina (dobrze mi się tego używało za czasów zabawy z Ubuntu). Skrypt uruchamiający aplikację jest uruchamiany automatycznie przy starcie RPi Zero. Dzięki temu z punktu widzenia użytkownika działanie jest dokładnie takie samo jak w przypadku wcześniejszego rozwiązania, ale za to widać znaczną różnicę w szybkości działania (chociażby po cyfrowym zegarze z sekundnikiem generowanym przez skrypt JavaScript).

Dodatkowo wykorzystałem Harmonogram zadań systemu Windows w celu wyłączania procesu przeglądarki w nocy i ponownego uruchamiania rano (kolejny sposób na oszczędność transferu).

Klasyczne problemy z Windowsem

Niestety wiele dni pracy Ekranu ze zdalnym pulpitem doprowadziło do obserwacji, że po kilku godzinach okno przeglądarki internetowej traci focus i nie mogę zmieniać kart przeglądarki za pomocą skrótu klawiaturowego Alt + Tab bez dodatkowego kliknięcia na któryś element strony internetowej. Czasami Remmina się po prostu wyłączała bez podania żadnego powodu.

Przyczyną było tracenie połączenia sesji RDP lub występowanie dużych opóźnień w połączeniu pomiędzy RPi Zero a serwerem. Problem postanowiłem rozwiązać na kilku płaszczyznach:

  • poprzez przywracanie focus’a przy logowaniu do konta użytkownika (np. gdy Remmina rozłączała się ze zdalnym pulpitem i przy ponownym łączeniu kolejny raz logowała do konta Windows’a):
Do przywrócenia focus’a wykorzystuję skrypt sendKeys, a jego uruchomienia dokonuję z wygodnego graficznego narzędzia Task Scheduler (Harmonogram zadań), które pozwala reagować na zdarzenie, którym jest zalogowanie do systemowego konta
  • poprzez automatyczne zabijanie i ponowne uruchamianie aplikacji Remmina w przypadku problemów z działaniem – w tym celu wykorzystałem program supervise (wchodzący w skład pakietu daemontools), który nadzoruje pracę uruchamianych przez niego procesów. Nie mogłem skorzystać z narzędzia systemctl w Debianie ze względu na uruchamianie zdalnego pulpitu w warstwie graficznej do której to narzędzie nie sięga.
  • poprzez usprawnienie domowej sieci komputerowej:

Ekran projektu HubScreen i router znajdują się w dwóch skrajnych miejscach mieszkania, a samo Raspberry ma antenę na płycie PCB, więc taki układ nie może sprawnie działać. W tym celu postanowiłem dokonać odpowiednich pomiarów, aby dowiedzieć się jaki ma to wpływ na opóźnienia oraz samą dostępność Raspberry w mojej sieci komputerowej. W tym celu pewnego sobotniego dnia postanowiłem zainstalować serwer Zabbix’a na moim Windows Serwerze (uroki posiadania komputera włączonego 24h/dobę oraz Docker’a, który pozwala na błyskawiczne uruchomienie dowolnego oprogramowania) i odpowiedniego agenta na RPi. Następnie przystąpiłem do pomiarów (a właściwie to Zabbix):

Opóźnienie (ping) pomiędzy serwerem a Ekranem
Dostępność Ekranu w sieci

Pomiary były dokonywane co 10 sekund, aby dało się także normalnie korzystać z domowej sieci.

Na powyższych wykresach dotyczących kilku dni pomiarów możemy odczytać następujące wartości:

  • Średnie opóźnienie (ping): 20,32 ms
  • Maksymalne opóźnienie (ping): 523,5 ms
  • Średnia dostępność Ekranu w sieci: 98,2 %

Trzeba było to w jakiś sposób usprawnić (szczególnie ten wykres dostępności). Pierwszy pomysł na jaki wpadłem to zastosowanie repeatera WiFi. Niestety klasyczny podłączany do zwykłego gniazdka w ścianie nie wchodził w grę ze względu na niekorzystne ułożenie gniazdek w mieszkaniu. Dlatego wpadłem na genialny pomysł: repeater pod sufitem jako LED’owa żarówka! W salonie akurat znajduje się kinket z idealnym widokiem na router znajdujący się na drugim końcu mieszkania. Niestety takie inteligentne żarówki wymagają zasilania 24h/dobę, więc musiałbym wymienić co najmniej dwie. I tutaj znalazłem idealny zestaw: żarówka z repeaterem WiFi i żarówka z głośnikiem bluetooth JBL’a. No idealny zestaw do mojego budowanego inteligentnego mieszkania. Na szczęście tuż przed kliknięciem przycisku „Kup” postanowiłem zasięgnąć rady ludzi z Reddita. Tam uświadomiono mnie o jeszcze jednej ważnej rzeczy: może zasięg WiFi się zwiększy, ale to wszystko kosztem opóźnień. Zasugerowano mi zbudowanie sobie sieci PLC (PowerLine Communication), która pozwala na komunikację poprzez przewody elektryczne. I to był strzał w dziesiątkę. Na Allegro za 255 zł udało mi się kupić zestaw do takiego zastosowania z routerem WiFi. Dzięki PLC opóźnienia w sieci z jednego końca mieszkania do drugiego są naprawdę minimalne, mogę sobie w końcu swobodnie korzystać z Internetu na balkonie i dodatkowo mogę grać w gry na telewizorze transmitując obraz z domowego komputera poprzez sieć (opóźnienia są naprawdę bardzo niskie).

Nowy układ sieci przedstawiłem poniżej:

A tutaj pomiary dla nowej konfiguracji:

Opóźnienie (ping) pomiędzy serwerem a Ekranem po dodaniu nowego Access Point’a
Dostępność Ekranu w sieci po dodaniu nowego Access Point’a

Na powyższych wykresach dotyczących kilku dni pomiarów po dodaniu nowego Access Point’a możemy odczytać następujące wartości:

  • Średnie opóźnienie (ping): 12,29 ms
  • Maksymalne opóźnienie (ping): 366,4 ms
  • Średnia dostępność Ekranu w sieci: 99,98 %

Teraz poziom dostępności jest na znacznie lepszym poziomie co można odczuć podczas codziennego korzystania z Ekranu 😉

Domoticz

Z racji, że w domu zaczęły pojawiać się pierwsze czujniki ZigBee to trzeba było gdzieś przechować generowane pomiary. I tak, kierując się poradami oraz doświadczeniami z pracy, poszedłem w kierunku systemu Domoticz.

Całkiem przyjemny system. Prosta konfiguracja. Szybkie działanie. Interfejs aplikacji w postaci strony WWW. Bez problemu udało się połączyć z Zigbee2MQTT. Na dodatek Domoticz posiada REST API, które pozwoliło mi na podłączenie czujnika DHT-11 czy czujnika ruchu odczytywanego przez RPi. Napisałem również aplikację, która na podstawie pingowania przez Bluetooth smartphone’ów decyduje czy w domu jest któryś z mieszkańców i modyfikuje zachowanie HubScreen’a, a historię statusów archiwizuje w bazie danych Domoticza. Dodatkowo udało się połączyć Domoticza z systemem Casambi (za pomocą autorskiej aplikacji Casambi2Domoticz napisanej w .NET Core) co pozwoliło na prezentację danych z czujnika powietrza Casambi.

Ale nie ma róży bez kolców. Jeśli chodzi o wady to Domoticz robi wrażenie przestarzałej aplikacji. Niedobór ciekawych pluginów, mało wodotrysków w interfejsie, brak prostej zmiany motywu itd. Potrzebowałem czegoś więcej.

Ostatnio ze względu na projekt prowadzony w pracy pojawiły się u mnie nowe doświadczenia z alternatywą dla Domoticza czyli Home Assistant’em, więc powoli przygotowuję się psychicznie na przeprowadzkę do nowego systemu „Inteligentnego mieszkania” 😉

Podsumowanie

Przedstawiona powyżej konfiguracja nie przetrwała próby czasu… Ale o tym w innym wpisie 😉 Najważniejsze, że to co wtedy się nauczyłem to moje 🙂

HubScreen – podsumowanie projektu

Wstęp

Projekt HubScreen, pozwalający na szybkie poranne sprawdzenie prognozy pogody oraz drogi do pracy, zakończony 🙂

Po tygodniach prac i zmian udało się uzyskać efekt widoczny na poniższych zdjęciach:

Ekran podczas normalnej pracy
Czego normalnie nie widać 😉

Zmiany względem pierwotnego planu

Ekran miał wisieć w przedpokoju – niestety ilość elementów przyklejona na gorąco nie pozwala na powieszenie w dedykowanym miejscu. Konieczne będzie wykonanie obudowy na drukarce 3D jak już się którejś dorobię 😉

Oszczędzanie energii miało działać w oparciu o czujkę PIR – niestety z racji umieszczenia ekranu w salonie niemożliwym było wykorzystanie czujki PIR, bo byłaby aktywowana przez każdą przebywającą tam osobę. Z tego powodu postanowiłem zamienić czujkę na przycisk, który umieściłem w kartoniku. Dzięki temu ekran uruchamia się po wciśnięciu przycisku (kiedyś popracuję nad estetyką tego rozwiązania) i wyłącza się po minucie bezczynności (możliwe to było poprzez włączanie i wyłączanie wyjścia HDMI za pomocą narzędzia vcgencmd i manipulacji parametru display_power – szczegóły w kodzie źródłowym aplikacji PIRScreenControl).

Miała zostać wykorzystana przeglądarka Chromium – okazało się, że wydajność RPi Zero WH jest daleka od oczekiwań i w przypadku przeglądarki Chromium cała strona ulegała zawieszeniu po pewnym czasie działania. Dodatkowo opracowałem aplikację, która na podstawie stanu wyjścia HDMI minimalizowała lub maksymalizowała okno przeglądarki Chromium (w opraciu o xdotool), a skrypty JS strony WWW zatrzymywały lub wznawiały odświeżanie iframe’ów w zależności od stanu okna, ale niestety taka operacja była bardziej wymagająca dla RPi niż nicnierobienie. Ostatecznie po uruchomieniu systemu otwieram stronę WWW w trybie pełnoekranowym przeglądarki surf i pomimo opóźnienia (bazując na wyświetlanym zegarze w JS) kilku sekund całość działa w sposób akceptowalny. Gdybym mógł dograć do przeglądarki uBlock’a to zapewne działałoby to lepiej, ale nie widziałem takiej możliwości, więc muszę poczekać aż wgram sobie Pi-hole’a na domowy router.

Typowe zużycie zasobów podczas pracy ekranu

Dodatkową energooszczędność (i zabezpieczenie przed awaryjną elektroniką z Chin 😉 ) uzyskuję dzięki inteligentnemu gniazdku, które o północy się wyłącza i włącza z rana, gdy przychodzi pora do wstawania.

A więc jak to ostatecznie działa?

RPi po uruchomieniu systemu wyłącza wyjście HDMI (a więc przy okazji ekran LCD) oraz otwiera przeglądarkę internetową ze stroną internetową znajdującą się na lokalnym serwerze Apache. W ramach tej strony wyświetlane są 3 elementy:

  • Prognoza pogody Google – iframe z wyszukiwarką Google dla hasła „pogoda Gdańsk”. Po wszystkim iframe jest odpowiednio manipulowany, aby wyświetlać na ekranie tylko prognozę pogody.
  • Trasę dojazdu Google Mapy – iframe z Mapą Google wytyczającą najszybszą trasę pomiędzy dwoma punktami. Darmowy iframe można uzyskać poprzez wyznaczenie trasy w zwykłych Mapach Google, wyświetlenie szczegółów jednej z dostępnych tras, a następnie wybranie opcji umieszczania mapy w postaci iframe’a.
  • Godziny odjazdów z wybranego przystanku autobusowego – tabela generowana dzięki projektowi ztmGdanskDepartureBoardParser.

Do włączenia ekranu wykorzystywany jest zwykły przycisk monostabilny NO, którego stan jest odczytywany dzięki przerwaniom pochodzących z biblioteki wiringPi.

Podczas bardzo prostych pomiarów okazało się, że dziennie ekran zużywa ok. 60-70 MB transferu internetowego i 0.01-0.02 kW energii (chociaż wartość jest tak niska, że nie wiem czy nie jest to błąd pomiaru).

Wykorzystany sprzęt i poniesione koszty

  • Ekran LCD Samsung LTN156AT01-U01 – bezpłatnie (z elektrośmieci po starym laptopie)
  • Kontroler ekranu LCD – ~75 zł (Aliexpress)
  • Raspberry Pi Zero WH – 59,90 zł (Botland)
  • Przewód miniHDMI <-> HDMI – 19,90 zł (Komputronik)
  • Zasilacz 12 V 5 A 60 W – 19,50 zł (Allegro)
  • Przetwornica step-down LM2596 3,2-35V 3A Arduino – 3,79 zł (Allegro)
  • Radiatory – ~1,83 zł (Aliexpress)

RAZEM: ~179,92 zł

Kody źródłowe i opracowane pliki

Kody źródłowe i opracowane pliki

PIRScreenControl

Wnioski

  • Raspberry Pi Zero ZH nie nadaje się do pracy z GUI i stronami WWW bazującymi na skryptach JavaScript – do mojego zastosowania RPi działało „na styk”, ale z rozbudową projektu mogą w przyszłości być problemy. Zapewne wystarczyłoby opracowanie aplikacji przetwarzających i/lub prezentujących w prostszy sposób potrzebne informacje, ale wtedy potrzebowałbym chmury Google, a to już nie byłoby darmowe jak w obecnej postaci 😉
  • Układ SMD LM317 w obudowie TO-252, który podebrałem z dawnego robota Minisumo nie nadaje się do zasilania RPi (zamiana 12 V DC na 5 V DC) ze względu na problemy z oddawaniem ciepła (nawet z radiatorem) – niby problemów z działaniem nie było, ale temperatura pracy na zbyt długo nie pozwoliłaby mi się nacieszyć projektem, więc LM317 zamieniłem na LM2596.

Projekt chciałbym w przyszłości rozbudować o obsługę czujników temperatury i otwartych okien na WiFi/BT, ale pewnie trzeba będzie wszystko zacząć od wymiany RPi na mocniejszą wersję.

HubScreen – część wizualna zrobiona

Udało się opracować część programistyczną: stronę WWW wyświetlającą pogodę, trasę dojazdu do pracy i estymowane czasy odjazdów z wybranego przystanku komunikacji miejskiej (wszystko oparte na HTML’u i JavaScipt’ie) oraz usługę (opracowaną w C++ i wykorzystującą wiringPi) odpowiedzialną za włączanie i wyłączanie portu HDMI w zależności od stanu czujki ruchu (kod źródłowy znajduje się tutaj).

Teraz pozostało tylko zadbać o odpowiednie zasilanie (dawny robot minisumo postanowił zostać dawcą), wszystko połączyć i złożyć w jedną całość – szykuje się pracowity weekend 😉

HubScreen – sprzęt skompletowany

Chińczyk mnie zawiódł i udało się skompletować sprzęt ?

Klasycznie nie mogło obejść się bez problemów i okazało się, że zasilacz 12 V/3 A jest niewystarczający dla kontrolera ekranu LCD i musiałem szybko zamówić jakiś mocniejszy model, więc skończyło się na 12 V/5 A (tutaj też to działa bez szału, ale działa).

Do zestawu brakuje jeszcze jakiegoś zasilania dla Raspberry, ale pewnie spróbuję zrobić je we własnym zakresie projektując przekształtnik buck, który obniży napięcie 12 V, dostarczane do ekranu LCD, do 5 V.

Teraz pozostało już tylko programować. Wymyśliłem sobie, że na Raspberry będę uruchamiał klasyczne GUI, gdzie po uruchomieniu systemu RaspiOS uruchomi się moja aplikacja napisana w języku C++. Do opracowania interfejsu planowałem wykorzystać biblioteki programistyczne Qt. Powodem była ich znajomość, wieloplatformowość i łatwość łączenia z językiem C++, a ten dodatkowo pozwoliłby mi na łatwą interakcję z systemem Linux oraz warstwą sprzętową mojego Raspberry. Niestety okazało się, że przykłady dla najnowszej wersji Qt (v.5.15.1) dotyczące Qt Webengine nie działają bezpośrednio po zainstalowaniu wymaganych bibliotek i IDE, więc aby uniknąć kolejnych i zapewne jeszcze większych problemów odpuściłem sobie ten pomysł.

I dlatego ostatecznie wykorzystam serwer WWW Apache, który wraz z napisanymi aplikacjami wykorzystującymi CGI oraz skryptami JS będzie realizował zaplanowane zadanie – w przypadku pracy magisterskiej takie połączenie na płytce BeagleBone Black zdało egzamin, więc wierzę, że i w tym przypadku tak będzie 🙂

HubScreen – pierwszy opis

W poszukiwaniu pomysłu na nowy projekt postanowiłem znaleźć rozwiązanie na jeden z ostatnio trapiących mnie problemów – mianowicie, z racji rozpoczęcia prawdziwie dorosłego życia, każdego ranka muszę sprawdzać parę rzeczy przed wyjściem do pracy jak np. prognozę pogody, co tam nowego na świecie przez noc się zadziało, czy komunikacja miejska w Gdańsku jeździ bez żadnych problemów, itd.

Dodatkowo od niedawna zostałem kierowcą z prawdziwego zdarzenia, a to powoduje, że muszę również uwzględniać drogę dojazdu do pracy – a mam je dwie 😉 Błędny wybór może kosztować mnie wiele minut jak nie godzin stania w korku (uroki tunelu pod Martwą Wisłą).

Do tej pory radziłem sobie za pomocą swojego smartphone’a, ale sprawdzanie tego wszystkiego zajmowało trochę czasu i wymagało przeklikiwania się przez kilka aplikacji.

Dlatego, z racji posiadania dwóch popsutych laptopów Toshiba L500D-149 z czasów studiów, stwierdziłem, że te wszystkie informacje najlepiej byłoby wyświetlać na jednym ekranie, a takowe posiadałem w moich popsutych laptopach (miały uszkodzony mostek północny, więc ekrany powinny być w porządku).

I wtedy powstała następująca koncepcja: do ekranu z popsutego laptopa podłączam jakiś kompaktowy układ scalony, który poprzez WiFi pobiera potrzebne informacje i wyświetla je na ekranie, gdy czujka ruchu wykryje obecność (dodatkowy warunek, żeby działało to maksymalnie bezobsługowo, a dodatkowo energooszczędnie).

Jeśli chodzi o rzeczywisty sprzęt do zaplanowałem to w ten sposób: ekran Samsung LTN156AT01-U01 poprzez odpowiedni kontroler z HDMI podłączam do Raspberry Pi Zero WH (wyświetlanie informacji będzie w formie strony WWW lub pobawię się z nowym .NET Core/.NET Framework 5.0), które otrzymuje polecenie załączenia ekranu po odebraniu sygnału o obecności z czujki PIR.

Zobaczymy czy taka koncepcja ma sens – na razie kompletuje sprzęt 🙂