Jakiś czas temu opisywałem prosty system monitoringu oparty o kamerę Edimax IC3030. Do tej pory zapisywałem (i wysyłałem dalej) obraz z kamery wyłącznie po wykryciu ruchu. Z czasem zacząłem się zastanawiać, czy nie rozszerzyć monitoringu o ciągłą rejestrację. Założyłem, że dobrze byłoby zapisywać obrazy z kamery co kilka sekund i gromadzić je na ukrytym nośniku w domu (oczywiście obsługiwanym przez router z OpenWRT). Tutaj w szczegóły nie będę się wdawał z wiadomych względów.
Tak się składa, że obecnie jest ku temu świetna okazja, bo napędy flash mocno ostatnio staniały. Obecnie pendrive o pojemności 16GB z dożywotnią gwarancją można kupić za 40 zł. Można się co prawda zastanawiać czy pamięć flash nadaje się do praktycznie ciągłego zapisu, ze względu na trwałość, ale myślę, że przy odpowiedniej minimalizacji ilości zapisów w tym samym miejscu nada się świetnie. Trzeba to sprawdzić w praktyce, a w razie problemów producent ręczy przecież gwarancją (dożywotnią, więc chyba jest pewien swego)·
Zacznijmy od prostych obliczeń. Przeciętny jpg z kamery o rozdzielczości 1.3 Mpix zajmuje 100KB (dla uproszczenia obliczeń). Zapisując obraz co 3 sekundy zużywamy około 2MB miejsca na minutę, czyli 120MB na godzinę. 16GB powinno więc wystarczyć na ponad 5 dni – całkiem nieźle.
Trzeba więc kupić pendrive i zastanowić się jak zminimalizować jego zużycie. Skoro pojemność klucza USB wystarczy na 5 dni, więc trzeba zadbać, żeby plik był zapisywany w danym miejscu pamięci właśnie co 5 dni. Zapewni to bardzo długie życie wrażliwym na zapisy kościom. To żaden problem, wszak zapisywać będziemy cyklicznie – najpierw zapełnimy dysk, potem zaczniemy usuwać najstarsze pliki, w ich miejsce wstawiając nowsze i tak „w kółko”. I na tym można by zakończyć rozważania nie przejmując się żywotnością sprzętu zupełnie, gdyby nie dwa drobiazgi – tablica alokacji i dziennik systemu plików. O ile z drugim bardzo łatwo sobie poradzić wybierając system plików bez tzw. journalingu, o tyle tablica alokacji w każdym systemie plików jest niezbędna (i obawiam się, że nawet dynamiczna struktura niewiele tu by pomogła).
Jak nie spróbujemy, to się nie dowiemy w praktyce jaka będzie trwałość pendrive i czy jest się czym przejmować. Wiemy jednak, że system plików ma być bez journalingu – naturalnym wyborem dla OpenWRT będzie więc ext2. Jak zminimalizować obciążenie tablicy alokacji? Zapis do niej odbywa się za każdym razem gdy tworzymy, modyfikujemy lub usuwamy plik i tutaj niewiele można zrobić. Ale czy tylko? W uniksach jednym z atrybutów pliku (przechowywanym w ext2 oczywiście na poziomie inoda, czyli w tablicy alokacji) jest czas ostatniego dostępu. Czyli modyfikacja tablicy inodów odbywa się nie tylko przy zapisie pliku, ale także przy każdym dostępie do niego (w tym odczycie, nawet jeżeli odbywa się z cache filesystemu). O ile w przypadku plików nie będziemy mieli z tym problemu, bo pliki będziemy odczytywać sporadycznie, to problemem mogą być katalogi. Szczęśliwie istnieje możliwość wyłączenia zapisu czasu dostępu, w przypadku katalogów i ext2 zrobimy to dodając opcję do mountowania systemu plików – nodiratime. Oczywiście w specyficznych przypadkach mogłoby to zakłócić pracę programów opierających się na tym atrybucie, na naszym pendrive będą operować jednak wyłącznie skrypty od monitoringu.
Przygotowujemy więc pendrive tworząc na nim partycję, a następnie formatując ją w systmie plików ext2 i dla wygody nadając jej etykietę „pendrive” (przez mkfs -t ext2 -L pendrive) – oczywiście korzystając z komputera z Linuksem lub bezpośrednio z OpenWRT po zainstalowaniu odpowiednich pakietów. Kolejnym krokiem będzie dodanie do pliku konfiguracyjnego /etc/config/fstab sekcji:
config mount option target /mnt/monitor option device label option label pendrive option fstype ext2 option options rw,sync,nodiratime option enabled 1 option enabled_fsck 1 option is_rootfs 0
Co zapewni nam, że pamięć USB zostanie automatycznie zamountowana przy starcie systemu w katalogu /mnt/monitor (rzecz jasna jeżeli taki katalog utworzymy).
Jak zapisywać pliki z kamery? IC3030 udostępnia nam aktualny obraz w postaci pliku jpg przez wbudowanych serwer www (trzeba tylko uaktywnić tę opcję i wybrać nazwę pliku – domyślnie snapshot.jpg). Pliki najlepiej będzie zapisywać w wielu katalogach, żeby nie było sytuacji, w której mamy kilkadziesiąt bądź kilkaset tysięcy plików w jednym folderze, bo po pierwsze ciężko się na nich wtedy operuje, a po drugie router w takich sytuacjach ma czasami problemy (wiem z praktyki). Można więc przyjąć, że katalog będzie zawierał obrazy z jednej godziny. Skrypt musi więc tworzyć odpowiednie katalogi i zapisywać do nich obrazy pobrane z serwera www. Dobrze byłoby, żeby łatwo można było ustalić katalog z najstarszymi plikami bez zagłębiania się się w daty modyfikacji – po nazwie katalogu.
Pliki będziemy zapisywać co około 3 sekundy do czasu aż pendrive się nie zapełni (oczywiście trzeba zostawić jakiś margines, żeby zachować ciągłość operacji). Zakładamy, że będzie on dedykowany tylko do monitoringu, nic więcej tam nie będzie zapisywane. Raz w ciągu minuty skrypt będzie sprawdzał ile zostało jeszcze wolnego miejsca i jeżeli mniej niż zakładany margines – uruchomiony zostanie skrypt usuwający jeden lub kilka najstarszych katalogów (czyli godzin zapisu).
To tyle założeń, pora przejść do realizacji. Skrypt będzie uruchamiany co minutę z crona i będzie wykonywał około 20 zdjęć. Wpisujemy więc do crona linię:
* * * * * /usr/scripts/getsnapshot &
Znak & na końcu gwarantuje nam, że kolejna instancja skryptu uruchomi się nawet jeżeli poprzednia jeszcze się nie zakończyła. Oczywiście w skrypcie wprowadzone zostanie proste zabezpieczenie, które spowoduje, że pierwszy ze skryptów zaprzestanie działania gdy upłynie minuta (aby dwa skrypty nie zapisywały obrazów w tym samym czasie). Zabezpieczy to przed sytuacją, gdy przez opóźnienia w pobieraniu obrazów skrypt zakończył by się np. 5 sekund po pełnej minucie, a kolejny wywołany byłby dopiero za 55 sekund, co spowodowałoby prawie minutową lukę w monitoringu.
Cały skrypt wygląda następująco:
#!/bin/ash CAMURL=http://192.168.0.125/snapshot.jpg DATA_PART=/mnt/monitor DATA_DIR=/mnt/monitor/data MINFREE=50 SUBDIR=`date +%Y%m%d%H` MOUNTED=`df -m | grep $DATA_PART | wc -l` FREE=`df -m /mnt/monitor | tail -1 | awk '{ print $4 }'` ACTMIN=`date +%M` if [ "$MOUNTED" -lt "1" ] then echo "Data partition not mounted" exit; fi if [ "$FREE" -lt "$MINFREE" ] then /usr/scripts/removeoldsnapshots & fi if [ ! -d $DATA_DIR/$SUBDIR ]; then mkdir $DATA_DIR/$SUBDIR fi for i in `seq 1 20` do if [ "`date +%M`" -ne "$ACTMIN" ] then exit else wget $CAMURL -O $DATA_DIR/$SUBDIR/`date +%Y%m%d%H%M%S`.jpg sleep 3 fi done
Parametry, które należy zmodyfikować są na początku:
CAMURL – URL, pod którym kamera udostępnia aktualny obraz
DATA_PART – katalog, którym podmountowany powinien być pendrive
DATA_DIR – katalog, którym będą podkatalogi z plikami monitoringu
MINFREE – ilość wolnego miejsca, poniżej której uruchamiana będzie procedura usuwania starych plików
Dodatkowo potrzebny będzie skrypt do usuwania starych katalogów (/usr/scripts/removeoldsnapshots, wywoływany pierwszym programie). Parametr NUM_DIRS określa ile godzin monitoringu ma zostać usunięte za jednym wywołaniem skryptu.
#!/bin/ash DATA_DIR=/mnt/monitor/data NUM_DIRS=2 for i in `seq 1 $NUM_DIRS` do DIR_TO_REMOVE=`ls $DATA_DIR | head -1` DIR_LENGTH=`echo $DIR_TO_REMOVE | wc -c` if [ "$DIR_LENGTH" -gt "4" ] then rm $DATA_DIR/$DIR_TO_REMOVE/*.jpg rmdir $DATA_DIR/$DIR_TO_REMOVE/ fi done
Skrypt został skonstruowany tak, żeby łatwo było wymienić pendrive na inny , także o innej pojemności (w szczególności na dysk twardy). Praktyka pokaże, czy pendrive będzie wystarczająco trwały do tego zastosowania. Póki co jestem jednak dobrej myśli, tym bardziej, że ceny pamięci flash nieustająco spadają. Co więcej na rynku pojawiły się także miniaturowe, energooszczędne routery ze złączem USB, które łatwo ukryć i dedykować do rejestracji obrazów z monitoringu. Za wyborem pamięci flash jako nośnika przemawia w tej chwili cena, a także właśnie możliwość oszczędności energii.
Coś mi wcięło komentarz… W skrócie: czy jeśli wprowadzisz rejestracje „ciągłą” czyli zdjęcia co 3 sek to nadal korzystasz z wykrywaniu ruchu czy to już jest wtedy zbędne?
Jak najbardziej prowadzę obie formy monitoringu równolegle. Po wykryciu ruchu nadal wysyłam zdjęcia na bezpieczny zewnętrzny serwer, natomiast monitoring ciągły gromadzi więcej danych, ale znajduje się w mniej dostępnym miejscu, bo w domu (natomiast dzięki wifi może on być np. u sąsiadów, co wydaje się być świetnym pomysłem przy zabudowie szeregowej).
Ok ale tak ogólnie to czemu miałby służyć taki ciągły monitoring skoro ruch i tak rejestrujesz… Zmiany pogody? 🙂
Choćby po to, że algorytmy wykrywania ruchu bywają zawodne, a jak widomo jak coś może zawieść, to zawiedzie kiedy jest potrzebne… Poza tym może być kiedyś sytuacja, gdy będę chciał przeanalizować dokładnie jakieś zdarzenie i fotki zarejestrowane przy wykrywaniu ruchu mogą nie być wystarczające.
Nie warto? Może i nie, ale wiele nie kosztuje, a kiedyś może się przydać.
W sumie racja… co dwa zabezpieczenia to nie jedno 🙂
Osobiście bym to jednak trochę modyfikował.
1) Przy cenach rzędu 40zł/16GB (podlinkuj z ciekawości, bo bym sam sobie kupił). Jednak bym poszedł w kierunku 2 pamięci, równocześnie zapisywanych. Bo jak padnie jeden, to drugi zawsze będzie działał.
2) Nie jestem linxowscem, więc nie rozumiem twojego kodu. Ale ja bym jeszcze zmienił nazwę pliku na coś typu RRRRMMDD-GGMMSS.jpg, zresztą katalog bym też podobnie nazwał RRRMMDD.
3) Z tego co pamiętam, posiadasz kilka routerów, to odnośnie pkt.1 chyba bym to zrobił równocześnie na dwóch urządzeniach. Mniejsze szanse iż złodziej oba znajdzie.
ad.3. Jak napisałem, o szczegółach nie chciałbym pisać 🙂
ad.2. Pliki są nazywane właśnie RRRRMMDDGGMMSS.jpg a katalogi w porównaniu z Twoją propozycją mają jeszcze godzinę na końcu (żeby łatwo kasować godzinami a nie dniami)
A fakt, zapomniałem iż to jest jeszcze godzina (bo dużo plików).
Jak sytuacja z pendrivem? Działa wszystko? Bo sam się zastanawiam nad podobnym rozwiązaniem i zapisywaniem plików na pendrive. Bawię się obecnie w monitoring za pomocą starego laptopa i kamerki usb ale dysk jest dość głośny i szkoda mi go bo w razie jak padnie to już raczej nie do kupienia.
Póki co cały czas działa.
Fajny blog (inspirujący), gratulacje.
Trzy grosze ode mnie – ostatnio badałem sprawę pamięci Flash i systemów plików. Okazuje się, że jest całkiem spora grupa FSów dedykowanych dla tego rodzaju pamięci, które radzą sobie z wszelkimi ich bolączkami: http://en.wikipedia.org/wiki/Flash_file_system . Tak więc Zamiast ext2 i bólu głowy o żywotność pendrive’a mógłbyś spróbować któregoś z dedykowanych FSów (aczkolwiek nie wiem jak wygląda możliwość ich użycia z OpenWRT).
Planuję zrobić monitoring u siebie w domu. Chciałbym zapytać o dwie rzeczy:
1. Czy cała ta koncepcja zadziała z kamerą D-link DCS-932L i ruterem TP-Link MR3420?
2. Czy aby zwiększyć ilość kamer wystarczy dodać kilka linijek do skryptu (url’e/nazwy katalogow zapisu zaczynające się np. cam1, cam2 itp.)?
Pozdrawiam