Pokazywanie postów oznaczonych etykietą linux. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą linux. Pokaż wszystkie posty

poniedziałek, 7 kwietnia 2014

Inteligentny dom oparty na OpenHab - wstęp

OpenHab to oprogramowanie dzięki któremu możemy połączyć urządzenia domowe oparte na różnych technologiach i protokołach w jeden sprawnie działający system inteligentnego budynku.
Główną częścią OpenHab jest tzw. OpenHab Runtime. Jest to aplikacja webowa napisana w całości w Javie, działająca pod kontrolą serwera Jetty.

OpenHab Runtime działa w oparciu o zestaw plików konfiguracyjnych. Są to niestety pliki tekstowe, brak jest jakichkolwiek narzędzi do graficznej konfiguracji. Autorzy zapewnili jednak narzędzie o nazwie OpenHabDesigner bazujące na Eclipse IDE, które zapewni nam podświetlanie błędów, oraz kolorowanie i uzupełnianie składni plików konfiguracyjnych co jest dość dużą pomocą. Dodatkowo dość czytelne przykłady i nie najgorsza dokumentacja sprawiają że konfigurowanie nie jest takie straszne.

Dostępne są również aplikacje na iOS oraz na Androida pozwalające na sterowanie automatyką z poziomu telefonu lub tabletu.

Całość wydana jest na licencji Eclipse Public Licence, co oznacza że mamy pełny dostęp do kodu źródłowego.

Generalnie w instalacjach inteligentnych budynków dużym problemem jest niezgodność protokołów transmisji pomiędzy dostawcami poszczególnych rozwiązań. Mamy chociażby standardy KNX, z-Wave, Fritz i wiele innych.
Gdy zdecydujemy się na jedno z rozwiązań stajemy się na stałe przywiązani do jednej firmy, która zwykle każe sobie słono płacić za każde dodatkowe elementy.

OpenHab jest próbą rozwiązania tego problemu.
Spójrzmy najpierw na architekturę (schemat pobrany ze strony http://www.openhab.org/)

Jak widać na schemacie, podstawowym elementem systemu jest szyna zdarzeń (Event Bus). która jak sama nazwa wskazuje zarządza zdarzeniami zachodzącymi w systemie.
Generalnie wyróżnić należy dwa typy zdarzeń: commands - czyli komendy wydawane przez użytkownika (lub inne źródła), oraz state change czyli zdarzenie zmiany statusu danego elementu systemu.

Tworząc własną konfigurację przygotowujemy tzw. Sitemap'ę czyli plik w którym opisujemy interfejs użytkownika. Co ciekawe interfejs ten wygląda później identycznie na wszystkich urządzeniach - w przeglądarce, na telefonie lub tablecie.
Dodatkowo definiujemy listę elementów (items) kontrolujących nasz system. Mogą to być przełączniki, suwaki, pola tekstowe wyświetlające stan elementów systemu - na przykład temperaturę w pomieszczeniu i kilka innych. Dla każdego z tych elementów w konfiguracji określamy sposób komunikacji z odpowiednim urządzeniem (binding) - czy to będzie KNX, połączenie szeregowe, bluetooth, czy też połączenie TCP. Obecnie dostępnych jest kilkadziesiąt różnych protokołów. Istnieje również możliwość dopisywania nowych, dostosowanych do własnych potrzeb. Każdy z elementów ma zdefiniowane komendy sterujące (np dla elementu typu Switch komendy to ON oraz OFF). W konfiguracji umieścić należy dodatkowo mapowanie poleceń wysyłanych lub odbieranych z urządzenia zewnętrznego na odpowiednie komendy elementu OpenHab.

System daje nam  dużą dowolność jeśli chodzi o sposób zapisu zdarzeń  w systemie. Może być to proste logowanie w pliku tekstowym, ale też zapisywanie stanu czujników w bazie danych, oraz generowanie wykresów na podstawie wyników.

Możliwości konfiguracji OpenHab'a są na prawdę olbrzymie. Myślę że warto zapoznać się z konfiguracją demo którą można uruchomić bez instalowania aplikacji u siebie.

Ja dopiero zaczynam poznawać jego możliwości i w miarę postępów postaram się opisać tutaj moje doświadczenia. W pierwszej części pojawi się komunikacja z Arduino za pomocą TCP, która niestety nie okazała się bezproblemowa.

niedziela, 6 kwietnia 2014

Arduino - sterowanie przekaźnikiem za pomocą przełącznika lub przez sieć



Opisane w poniższym wpisie elementy możesz zakupić na aliexpres. Poniższe linki to linki afiliacyjne. Skorzystanie z nich Ciebie nic dodatkowo nie kosztuje a ja otrzymam niewielką prowizję która wspomoże rozwój tego bloga. Dzięki!

Przekaźnik: http://ali.pub/2hk8br
Klon Arduino mega: http://ali.pub/2hk94c
Ethernet shield: http://ali.pub/2hk97n

poprzednim wpisie opisałem mój pomysł na stosunkowo wygodne podłączenie do arduino przekaźników oraz przełączników. Tym razem pokażę jak takie połączenie można wykorzystać w praktyce. Jak pewnie zauważyliście na zdjęciach, dołączyłem do mojego arduino ethernet shield dzięki któremu będzie możliwe sterowanie urządzeniami za pośrednictwem sieci ethernet.

Przykład który pokażę pozwala na załączenie lub wyłączenie przekaźnika za pomocą przycisku dzwonkowego, lub za pomocą pakietu TCP o odpowiedniej treści.
Jeśli będziemy potrafili załączyć przekaźnik pakietem TCP, będziemy mogli sterować nim z poziomu dowolnego urządzenia - z komputera, telefonu, tabletu...

Przypuśćmy że chcemy sterować przekaźnikiem załączającym oświetlenie LED w salonie.

Program sterujący dla przejrzystości podzieliłem na 3 pliki:

1. _01_homeController.ino
Jest to główny plik zawierający funkcję inicjującą oraz pętlę główną
2.  _02_salon_led.ino
W tym pliku zawarta jest obsługa przycisku oraz przekaźnika
3. _03_network.ino
W tym pliku zawarta jest obsługa połączenia sieciowego
Wydaje mi się że kod jest dość przejrzysty i czytelny. Nie będę zatem opisywał go linia po linii.

Zwróćcie uwagę na nazewnictwo plików które zastosowałem. Arduino IDE sortuje zakładki w projekcie w sposób alfabetyczny. Na początku nazwałem pliki

salon_led.ino
network.ino

zakładka z plikiem network.ino ustawiła się przed zakładką salon_led.ino

otrzymywałem wtedy błąd "SALON_LED_REMOTE_COMMAND was not declared in this scope" w linii 55'tej pliku network.ino.
Nie pomaga tutaj żadne include'owanie plików. Jedyne co pomogło to przeorganizowanie zakładek. Dziwne... Ale tak jest :).
Podłączony układ wygląda następująco:

Działanie całego układu najlepiej zobrazuje poniższy film:

Komunikację sieciową z Arduino trochę ławiej byłoby zrobić za pomocą pakietów UDP, chciałem jednak żeby ten wpis był wstępem do sterowania urządzeniami poprzez OpenHab a niestety natrafiłem na problemy z połączeniem OpenHab i Arduino za pośrednictwem UDP.

poniedziałek, 21 października 2013

Raspberry Pi i strumieniowanie video

Na potrzeby projektu Zabawka dla Sierściucha, którego koncepcję opisałem w jednym z poprzednich wpisów potrzebuję strumieniowania video w czasie rzeczywistym, dodatkowo w postaci którą można w prosty sposób osadzić na stronie WWW i to bez użycia flash'a.

Pytałem Wujka Google co wie na ten temat, ale okazało się że spektrum możliwości niestety nie jest zbyt szerokie. Zależało mi żeby rozwiązanie działało w miarę płynnie, nie miało dużych opóźnień no i oczywiście żeby dało się je uruchomić na Raspberry Pi.

Chyba najsensowniejsze rozwiązanie które znalazłem to MJPG-streamer.
W uproszczeniu można napisać, że pobiera on z kamery statyczne obrazy i kopiuje je do pamięci. Wtyczki wyjściowe potrafią przesłać te obrazy do przeglądarki tworząc animację. Potrafi wykorzystać sprzętową kompresję wbudowaną w kamery. Dzięki temu nie zużywa dużo pamięci ani mocy procesora.

Nie mam dedykowanej kamery do Raspberry Pi, więc wykorzystałem zwykłą najtańszą kamerę USB, przechwytującą video z rozdzielczością do 640x480. Rozwiązanie jest na tyle uniwersalne że później można wymienić kamerę na lepszą :)

Jako że Raspberry Pi oparte jest o architekturę ARM, w większości przypadków programy które nie są zawarte w dystrybucji którą zainstalowaliśmy nie mają dedykowanych pakietów. Pozostaje zatem zbudowanie ich ze źródeł. Na szczęście nie stanowi to większego problemu.

Na RPI zainstalowałem dystrybucję Raspbian, która bazuje na Debianie. W tym przypadku kompilacja będzie wymagała następujących kroków (zakładam że użytkownik zalogowany jest np na koncie "pi" - lub dowolnym innym bez uprawnień administratora):

Na początek musimy zainstalować wymagane zależności. Zrobimy to następującymi poleceniami:

sudo apt-get install subversion 
sudo apt-get install libv4l-dev 
sudo apt-get install libjpeg8-dev 
sudo apt-get install imagemagick

Następnie pobieramy kod źródłowy mjpeg-streamer'a bezpośrednio z repozytorium SVN:

svn checkout svn://svn.code.sf.net/p/mjpg-streamer/code/ mjpg-streamer-code 

Przechodzimy do katalogu w którym znajdują się pobrane źródła:

cd mjpg-streamer-code/mjpg-streamer 

i kompilujemy:

make USE_LIBV4L2=true clean all 

po miejmy nadzieję poprawnej kompilacji, trzeba zainstalować zbudowaną aplikację w systemie:

sudo make DESTDIR=/usr install 

tworzymy katalog dla obrazów:

sudo mkdir /var/www/mjpg_streamer
sudo chmod a+rw /var/www/mjpg_streamer

W tym momencie możemy już przetestować czy strumieniowanie działa.
Odpalamy polecenie:

mjpg_streamer -i "/usr/lib/input_uvc.so -d /dev/video0 -r 320x240 -f 15 -y" -o "/usr/lib/output_http.so -p 8090 -w /var/www/mjpg_streamer" 

które oznacza mniej więcej tyle, że rozpoczynamy strumieniowanie obrazu z urządzenia /dev/video0 (kamera usb) o rozdzielczości 320x240, z framerate 15 FPS używając kodeka YUYV (opcja -y), na porcie 8090 wykorzystując folder /var/www/mjpeg_streamer

W przypadku mojej kamery opcja -y była niezbędna -  kamera nie wspierała dekodowania MJPEG. W przypadku lepszych kamer powinno zadziałać bez tej opcji - co generalnie jest rozwiązaniem lepszym, ponieważ dekodowanie MJPEG jest podobno wydajniejsze od YUYV.

Żeby przetestować działanie strumienia trzeba spreparować sobie plik html w takiej postaci:

<html><body>
<img src="http://IP_RASPBERRY_PI:8090?action=stream">
</body></html>

I otworzyć go w przeglądarce. Okienko powinno zawierać obraz z kamery.

Gdy już mamy działający strumień, możemy przekonfigurować system aby strumieniowanie uruchamiało się automatycznie przy starcie.

W tym celu tworzymy plik stream.sh:

 sudo nano /usr/bin/stream.sh 

i dodajemy do niego polecenie uruchamiające strumień, czyli ponownie:

mjpg_streamer -i "/usr/lib/input_uvc.so -d /dev/video0 -r 320x240 -f 15 -y" -o "/usr/lib/output_http.so -p 8090 -w /var/www/mjpg_streamer" 


i zapisujemy plik. Nadajemy mu uprawnienia wykonywalne:

 sudo chmod a+x /usr/bin/stream.sh

i tworzymy dowiązanie symboliczne w /etc/init.d

 sudo ln -s /usr/bin/stream.sh /etc/init.d/stream.sh

Dodajemy utworzony skrypt do automatycznego startu poleceniem:

 sudo update-rc.d stream.sh defaults 94 6

W tym momencie po restarcie systemu strumień powinien być automatycznie dostępny.
Docelowo w projekcie to Raspberry ma serwować stronę WWW z obrazem wideo. Dlatego musimy zainstalować na malince Apache + PHP.

Wystarczy polecenie:
 sudo apt-get install php5 

Serwer Apache jest w zależnościach PHP więc zainstaluje się automatycznie.

Chcemy aby nasza strona docelowo była generowana dynamicznie, zatem zamieniamy statyczny plik index.html:

sudo rm /var/www/index.html

na plik /var/www/index.php o następującej zawartości:

Odpalenie w przeglądarce adresu:
http://IP_RASPBERRY_PI

powinno wyświetlić serwowane przez Malinkę wideo.

Z wstępnych testów wynika że przy strumieniowaniu przez WIFI obraz w rozdzielczości 320x240 przy 15 FPS działa praktycznie bez żadnych opóźnień. Strumień 640x480 przy 15FPS ma około 2-3 sekundy opóźnienia - co w praktyce może okazać się akceptowalnym wynikiem. Nie badałem jeszcze skąd te opóźnienia. Przyczyn może być kilka - wolne WIFI, słaba kamera bez obsługi MJPEG...
W każdym razie obciążenie CPU w Raspberry Pi jest praktycznie niezauważalne.

Jeśli macie lepsze propozycje przesyłania strumienia, chętnie się o nich dowiem - temat jest ciągle otwarty :)