Videosorveglianza con Raspberry Pi – Parte settima

closeQuesto articolo è stato pubblicato 9 anni 9 mesi 2 giorni giorni fa quindi alcuni contenuti o informazioni presenti in esso potrebbero non essere più validi.

Per chi si fosse perso le puntate precedenti: Parte prima, Parte seconda, Parte terza, Parte Quarta, Parte quinta, Parte sesta

Ed eccoci qui al cuore del sistema. Perché lasciato per ultimo? Così abbiamo tutti i pezzetti di contorno per farlo funzionare.

Torniamo alle specifiche. Il sistema va controllato via DM, ogni DM un comando, ad ogni comando un’azione, dopo l’esecuzione dell’azione il sistema risponderà con cosa ha fatto. Se il comando non è riconosciuto un DM manderà la lista di tutti i comandi utilizzabili.

Ecco i comandi che ho implementato:

  • motionon: se il sistema non è attivo lo attiva, se è già attivo lo comunica
  • motionoff: se il sistema è attivo lo spegne, se non è attivo lo comunica
  • motionstatus: risponde con lo stato del sistema (attivo o no)
  • click: scatta un’istantanea, come quella oraria, e la twitta
  • cancellatutto: abilita la rimozione di tutti i tweet
  • ippubblico: voglio sapere che indirizzo IP pubblico ha il router

Ecco il codice del file “cerca_dm.py”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python2.7
import tweepy
import sys
import datetime
import time
import string
import subprocess
import os
import requests
import json
 
# qualche costante
file_di_log = "/home/pi/tweepy/controllo_movimento.log" # file di log del sistema di controllo
file_semaforo_cancella = "/home/pi/tweepy/cancella_tutti_tweet" #file creato per autorizzare la cancellazione dei tweet
utente_dm = "iltuoutente" # utente a cui mandare i DM (magari poi saranno gestibili diversi utenti)
 
# Autenticazione su Twitter
consumer_key = 'xxx'
consumer_secret = 'xxx'
access_token = 'xxx'
access_token_secret = 'xxx'
 
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
 
api = tweepy.API(auth)
 
# apro il file di log in append
log = open (file_di_log, "a")
 
# memorizzo il timestamp attuale (cosi' lo metto nei tweet ed evito il blocco dei doppioni)
ts = time.time()
st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
 
# recupero l'ultimo DM ricevuto
dm_comando = api.direct_messages(count=1)
 
# memorizzo una stringa vuota in ultimo_dm, nel caso in cui non si trovino DM
ultimo_dm = " "
 
# imposto id_ultimo_dm a zero, se non si trovano DM, lo uso per non mandare DM a fine pagina
id_ultimo_dm = 0
 
# memorizzo il testo del tweet recuperato
for directmessage in dm_comando:
    # converto la stringa tutta in minuscolo, per non avere problemi con le iniziali maiuscole dei vari client
    ultimo_dm = directmessage.text.lower()
    id_ultimo_dm = directmessage.id
    luogo_ultimo_dm = directmessage.sender.location
    data_ultimo_dm = directmessage.created_at
    # scrivo il log della richiesta
    log.write(st + " - DM di comando: " + ultimo_dm + " (" + str(id_ultimo_dm) + ") - da " + luogo_ultimo_dm + " \n")
    # elimino il DM
    api.destroy_direct_message(id_ultimo_dm)
    log.write(st + " - cancellato il DM di comando con id " + str(id_ultimo_dm) + " \n")
 
# controllo se il processo 'motion' e' attivo o no
processname = 'motion'
tmp = os.popen("ps -Af").read()
proccount = tmp.count(processname)
 
# l'ultimo DM contiene l'ashtag motionoff? (voglio spegnere il sistema)
if string.find(ultimo_dm, "motionoff") != -1:
    # se il processo 'motion' e' attivo lo uccido e avviso che e' disattivato
    if proccount != 0:
        os.system("pkill motion")
        log.write(st + " - Ucciso motion" + " \n")
        api.send_direct_message(utente_dm,text="Motion disattivato - " + st)
    else:
        api.send_direct_message(utente_dm,text="Motion era gia' disattivato - " + st)
 
# l'ultimo DM contiene l'ashtag motionon? (voglio accendere il sistema)
elif string.find(ultimo_dm, "motionon") != -1:
    # se il processo 'motion' non e' attivo lo avvio e avviso che e' attivato
    if proccount == 0:
        os.system("/home/pi/motion-mmal/motion")
        log.write(st + " - avviato motion \n")
        api.send_direct_message(utente_dm,text="Motion attivato - " + st)
    else:
        api.send_direct_message(utente_dm,text="Motion era gia' attivo - " + st)
 
# l'ultimo DM contiene l'ashtag motionstatus? (voglio sapere se il sistema e' attivo o no)
elif string.find(ultimo_dm, "motionstatus") != -1:
    # se il processo non c'e' twitto che e' disattivato
    if proccount == 0:
        api.send_direct_message(utente_dm,text="Stato motion: NON ATTIVO - " + st)
        log.write(st + " - controllo stato motion: NON attivo \n")
    # se il processo c'e' twitto che e' attivo
    else:
        api.send_direct_message(utente_dm,text="Stato motion: ATTIVO - " + st)
        log.write(st + " - controllo statio motion: attivo \n")
 
# l'ultimo DM contiene il comando cancellatutto? (voglio cancellare tutti i tweet dell'account)
elif string.find(ultimo_dm, "cancellatutto") != -1:
    #creo il file di semaforo
    semaforo = open (file_semaforo_cancella, "a")
    semaforo.write("cancella")
    log.write(st + " - creato il semaforo per la cancellazione\n")
    api.send_direct_message(utente_dm,text="Procedura rimozione tweet impostata, esecuzione entro 1h - " + st)
 
# l'ultimo DM contiene il comando ippubblico (voglio sapere qual e' l'indirizzo IP pubblico)
elif string.find(ultimo_dm, "ippubblico") != -1:
    req = requests.get("http://httpbin.org/ip")
    if req.status_code == 200:
        text = json.loads(req.text)
        ip = text['origin']
 
    api.send_direct_message(utente_dm,text="Indirizzo IP pubblico: " + ip + " - " + st)
    log.write(st + " - IP pubblico di questo momento " + ip + " \n")
 
# l'ultimo DM contiene il comando click (voglio scattare una foto)
elif string.find(ultimo_dm, "click") != -1:
    # se motion e' attivo la videocamera e' impegnata, devo quindi prima spegnerlo
    if proccount != 0:
        os.system("pkill motion")
        log.write(st + " - ucciso motion per foto \n")
        time.sleep(5)
        os.system("raspistill -w 1600 -h 1200 -t 1 -o /home/pi/Pictures/SingoloClick.jpg")
        log.write(st + " - scattata la foto \n")
        time.sleep(15)
        os.system("/home/pi/motion-mmal/motion")
        log.write(st + " - avviato motion dopo foto \n")
    else:
        os.system("raspistill -w 1600 -h 1200 -t 1 -o /home/pi/Pictures/SingoloClick.jpg")
        log.write(st + " - scattata la foto con motion non attivo \n")
 
    api.update_with_media("/home/pi/Pictures/SingoloClick.jpg", utente_dm + " Istantanea del " + st)
    log.write(st + " - mandato tweet con istantanea \n")
    os.system("rm /home/pi/Pictures/SingoloClick.jpg")
    log.write(st + " - rimossa istantanea \n")
 
#se nessun comando e' stato riconosciuto
else:
    if id_ultimo_dm != 0:
        api.send_direct_message(utente_dm,text="Comandi utilizzabili: motionon, motionstatus, motionoff, cancellatutto, ippubblico, click - " + st)
        log.write(st + " - comando non riconosciuto: " + ultimo_dm + " \n")
 
# chiudo il file di log
log.close()

Tutti commenti sono nel codice, la procedura è semplice, cerco nell’ultimo DM ricevuto il comando, se lo trovo eseguo l’azione, rimuovo l’ultimo DM ricevuto per non eseguire continuamente l’ultima azione richiesta. Per ogni azione eseguita viene registrata una riga nel file di log, compresi i dati del DM ricevuto e la posizione geografica del mittente (se abilitata dal client da cui si sta mandando il DM)

Questo programma va eseguito ogni minuto, si deve mettere di nuovo mano al crontab aggiungendo

1
2
#controllo di motion tramite DM di twitter (una volta ogni minuto)
*/1 * * * * python /home/pi/tweepy/cerca_dm.py >/dev/null 2>&1

Attenzione che Twitter ha una frequenza massima di interrogazioni su DM, se dovete fare prove a mano lanciando il programma dalla riga di comando, interrompete il servizio del crontab o commentate quest’ultima riga anteponendo il “#” al comando. Se non lo fate vi troverete bloccati per superamento del limite di interrogazioni.

Concludendo

Ce l’abbiamo fatta! abbiamo un sistema di controllo di una zona fatto completamente da noi, completamente personalizzabile e gestibile da twitter! Ovviamente il codice è un po’ scritto da me, un po’ scopiazzato qua e là per Internet, potrebbero esserci errori e sicuramente potrebbe essere ottimizzato, vale la regola della licenza GNU, viene fornito così com’è e non potrò mai essere ritenuto responsabile di eventuali danni che questo progetto potrebbe arrecarvi.

Ovviamente se avete idee, miglioramenti, correzione di errori, sarò lieto di ascoltarli ed eventualmente implementarli tra le pagine del blog e sul dispositivo che ho a casa.

Altre idee?

Ho pubblicato questa guida per condividerla con chi è alle prime armi con il Raspberry (come me), ma sopratutto perché magari i lettori potrebbero proporre modifiche, aggiunte, nuove funzioni, tutto allo scopo di migliorare il progetto.

Problemi riscontrati ed evoluzioni

Il progetto non è esente da difetti e sicuramente potrebbe avere evoluzioni interessanti, magari ci farò altri post, man mano che mi vengono idee. Ovviamente se avete qualche idea non fatevi problemi a postarla qui sotto nei commenti!

Ecco qui alcuni pensieri che ho fatto

  • Salvare tutti i file in un disco collegato via USB, per non consumare la scheda SD e poter tenere un archivio
  • Fare in modo di avere un server web per poter accedere dall’esterno all’archivio delle immagini
  • Utilizzare il GPIO del Raspberry per attivare un qualche dispositivo esterno in caso di rilevazione di movimento

E qui alcuni problemi che mi sono passati per le mani

  • Pare che la WiFi, dopo che non accedo via SSH per un po’ di tempo, smetta di funzionare per metà, tutto il sistema funziona, ma non riesco più a collegarmici. Non so se è colpa del router, indago
  • La videocamera è eccellente di giorno, ma pessima di notte, serve quella IR con illuminatore apposito (dovrei riuscire a procurarmelo prima delle vacanze)
  • Ci sono ancora troppi falsi movimenti rilevati, devo trovare un modo per filtrarli
  • Il LED rosso della videocamera resta acceso durante lo stato attivo, è da coprire con un pezzo di nastro nero
  • Se va via la corrente ed il vs router è in po’ troppo lento ad avere la connessione è necessario ritardare l’invio del DM di riattivazione al reboot. Comunque ogni tanto lo perdo
  • Qualcosa non torna con il comando “pkill” per ammazzare motion, ogni tanto il processo non viene terminato, pertanto ne parte un altro e così via a catena. Questo riempie RAM, CPU e pianta il sistema che va riavviato. Ci sto lavorando

Ed infine… ecco un banalissimo avatar che ho impostato sul mio account Twitter per il controllo, l’uovo era davvero brutto…

Avatar Motion Twitter

 

28 pensieri riguardo “Videosorveglianza con Raspberry Pi – Parte settima”

  1. Complimenti per la guida, molto utile. Volevo farti una domanda. Sai se è possibile fare lo zoom in tempo reale? Quello che vorrei fare è zoommare la parte interessata e scattare una foto.

    Grazie 10000000000

    Ciao

  2. Complimenti per il lavoro svolto.
    è possibile collegare più di una telecamera ? Se sì, hai già avuto esperienze di questo tipo e che modifiche sono necessarie.
    grazie 1000.

  3. Ciao Francesco,
    con più telecamere non ho mai provato, ma so che Motion lo gestisce (IP e USB), devi fare un file di configurazione per ognuna con un file principale per le opzioni in comune.
    Su Raspberry non so se ce la fai, con solo una la CPU è parecchio sotto stress, magari con la nuova scheda Pi 2 B

  4. Ciao Francesco,
    volevo chiederti come mai quando eseguo questo ultimo file, mi esegue sempre l’ultimo DM inviato, pur avendolo eliminato (credo) con “api.destroy_direct_message(id_ultimo_dm)”
    Grazie e complimenti!

  5. Ciao Vincenzo,
    per capire se hai rimosso il DM puoi mettere un try e capire se c’è un’eccezione durante l’operazione, oppure puoi memorizzare in un file l’ID in modo che quando lo controlli, se l’ID che becchi è lo stesso di prima non fai alcuna elaborazione.
    Spero di essere stato di aiuto! 🙂

  6. Ciao Francesco, ottimo lavoro, sto realizzando anche io un sistema di sorveglianza così, sapresti come fare su una ip cam che espone solo un protocollo rtsp motion non lo supporta

  7. Ciao Luca, io ho usato una IP camera di Foscam, cercando un po’ di documentazione ho trovato il link esatto per andare a prendere lo streaming video, secondo me c’è anche nella tua (ma sicuramente Google può darti una risposta più precisa)

  8. Ciao Francesco, Google non riesce ad aiutarmi e credo che non ha un indirizzo x stream HTTP la ipCam si chiama ONVIF JA-B1080 c’è solo lo stream RTSP ma troppo pesante x raspberry pi 2 B, occupa solo lui quasi il 100% della CPU, stavo pensando a farlo funzionare con protocollo FTP ma non so come, puoi aiutarmi? ho la porta 21 aperta, conosco l’ip ma non conosco l’indirizzo FTP://

  9. Ciao Francesco, ho scoperto questa guida dopo aver fatto i primi passi con Motion.
    Complimenti.
    Ti vorrei chiedere qualcosa

    1)
    [code]on_[evento]
    on_event_end rm /home/pi/Pictures/*.jpg
    on_picture_save python /home/pi/tweepy/tweet.py %f [/code]

    se volessi che memorizzi queste immagini e basta devo togliere il comando rm alla seconda linea?

    2) se volessi memorizzare il filmato che si ha dopo il movimento percepito dalla webcam, che cosa dovrei impostare?

    3) quando tu scrivi queste cose non capisco che devo fare:
    “”
    Bene, abbiamo il file configurato. Ma dove lo mettiamo? Il file si deve chiamare “motion.conf” e deve stare nella cartella “/home/pi/.motion”. Commentate le righe relative agli eventi “on_[qualcosa]” anteponendo un “;” o un “#”, e impostate l’opzione “daemon” a “off”, salvate il file ed eseguite il programma “/home/pi/motion-mmal/motion”

    “”
    il file motion.conf a me è nella cartella /etc/motion
    Perchè lo devo spostare?

  10. Ciao Vittorio,
    vediamo se riesco a rispondere ai tuoi quesiti!

    1. Sì, se togli il comando rm lui non cancella tutti i JPG dalla cartella dove salva le immagini
    2. per il filmato la procedura è complessa, devi compilare e installare il modulo FFMPEG (aspettati parecchio tempo di compilazione) poi devi andare a lavorare con i parametri della sezione “FFMPEG related options” nel file di configurazione
    3. l’ho spostato perché ho sbattuto parecchio il naso su questa cosa, se lo lasciavo nella /etc/motion qualcosa non funzionava, poi, non ricordo bene dove, ho trovato indicazione di spostarlo lì

    Spero di essere stato di aiuto

    Grazie dei complimenti 🙂

  11. Ciao Francesco
    grazie per la risposta.
    Hai mai configurato motion per l’utilizzo di due webcam? io ci sto sopra da un po’ e non ci riesco. Potresti controllare i miei file di configurazione?

  12. Ciao Vittorio,
    il mio tempo non mi permette di controllare il codice altrui, mi spiace. Posso dirti che via USB non l’ho mai usata, ma ne ho una attiva via IP, nel mio file di configurazione, per accedere ho queste impostazioni


    netcam_url value http://[indirizzo_IP_camera]/videostream.cgi
    netcam_userpass [utente]:[password]

    La mia era una Foscam, per avere il link dello streaming di altre camere devi cercare sulla documentazione della camera che usi tu

  13. Ciao Francesco, scusa il ritardo della risposta.
    Ci sono riuscito alla fine a mettere due webcam in funzione, anche se ora devo mettere qualche impostazioni per far salvare le foto o i video. Intanto se mi collego dal cell riesco a vedere entrambe le webcam in real-time.
    Se vuoi, ti posso mandare in qualche modo la mia guida per settare due webcam

    Quindi per quanto riguarda le webcam ip, quelle due che hai postato sono le uniche impostazioni da settare?
    quando dici utente e password io che ci devo mettere?
    immagina che non ho creato nessun altro utente, e che lavoro in /home/pi.

  14. Ciao Vittorio,
    sono contento che tua sia riuscito! Ma quindi attivi motion su 2 videocamere contemporaneamente sul Raspberry? E il processore tiene? Il mio, con solo una è già molto carico.
    Per il salvataggio delle immagini ti consiglio di usare un HD esterno, la memoria SD si usura con tante scritture. Se vuoi un repository esterno puoi fare un FTP ogni tanto o usare iSync che permette di usare Google Drive ul raspberry.

    Come credenziali devi mettere quelle che usi per collegarti alla camera IP, quando al usi

  15. Ciao Francesco, ti rispondo sempre tardi perchè non mi arriva nessuna notifica via mail nonostante spunto ogni volta le due caselle qui sotto…..e me ne dimentico.
    Per quanto riguarda il processore, e la temperatura, non vedo grossi problemi: ho installato un programma che mi permette tramite internet di monitorare sia il lavoro della CPU che la sua temperatura. Ho visto che c’è ampio margine: potrei utilizzare almeno altre due webcam. Quale è una temperatura preoccupante per il raspberry?

    Vorrei fare il repository esterno con FTP, ma non ne sono in grado. Se hai una guida, ne sarei felice. Cosa è iSync??

    forse allora non ho camere IP: non metto nulla per vederle: vado per esempio su mozilla e metto l’indirizzo ip del raspberry che ho settato e poi ” :porta_della_webcam “

  16. Ciao Vittorio,
    per depositare le immagini su un server FTP ti serve un PC sempre acceso con un programma che faccia da server FTP, puoi usare vsftp su Linux o Filezilla Server su Windows. Al termine di un evento, invece di fare “rm [nomefile]” puoi invocare uno script FTP che faccia l’upload della foto per poi cancellarla dal raspberry.
    Non credo che la scheda patisca il surriscaldamento, è progettata bene, per surriscardarla devi iniziare a fare operazioni di overclock, ma vendono dei dissipatori da montare sul chip nel caso in cui tu lo voglia fare. La mia CPU, se faccio un “top” con motion attivo su una sola camera è al 60-70%, tu usi una Pi o una Pi2?

    Mi spiace per le mail, è una cosa con cui sto combattendo da mesi, alcune partono, altre no…

  17. Ciao Francesco
    ora come ora vorrei capire come e dove mettere il percorso, dove salvare le immagini e le riprese con motion. (Non so se lo avevi scritto in questa guida, ora non ricordo).

    Quello del server, ci sto ragionando e ricercando guide semplici in giro

    Io ho una scehda raspberry con 1 gb di ram. Mi sembra che sia la Pi2.

    Oggi mi è arrivata l’email di come passare con un nuovo portatile da win7 a win 8
    ciao ciao

  18. Ciao Vittorio,
    queste attività sono di uno spettro più ampio rispetto a Raspberry, dovresti studiarti come funziona linux in generale, i mount su dischi esterni o come fare un server FTP. Buon Lavoro!

  19. Complimenti per questa guida, molto completa ed esauriente.
    Leggendo questo articolo mi è venuta un’idea… per attivare un illuminatore IR si potrebbe usare anche un GPIO che lo accenda ad una certa ora oppure che legga lo stato di un crepuscolare collegato su un altro gpio

  20. Grazie Daniele!
    Io ho risolto con un illuminatore IR trovato in una fiera con sensore crepuscolare integrato, quando diventa buio lui accende il fascio IR. Tra alimentatore e illuminatore credo di aver speso circa 20€ (ma si tratta di un po’ di tempo fa, non ricordo esattamente la spesa)

    Per il tuo progetto c’è una parte interessante di studio di elettronica.
    1. il GPIO non ha la corrente nè la tensione sufficiente per accendere un illuminatore almeno decente, devi giocare con un relè o un transistor
    2. il crepuscolare è analogico, il GPIO del raspberry è solo digitale, devi fare un circuito in mezzo che converta la soglia minima di luce in 1 o 0

    Magari ti ho dato lo spunto per elaborare un tuo sistema automatizzato

    Ciao!

  21. Ciao Enrico,
    grazie del tuo contributo, trovo motionEye davvero interessante!
    Ha solo il difetto che per poterlo gestire devi aprire una porta dall’esterno verso il Raspberry PI, la soluzione con Telegram non apre porte verso l’esterno, ma è oggettivamente un po’ più scomoda 🙂 la proverò sicuramente!

    Ciao!

  22. Ciao Francesco sono Mario, il ragazzo che aveva chiesto il tuo aiuto per la versione evoluta con Telegram ! Se ti può interessare ho trovato un modo per evitare di utilizzare il nastro adesivo nero sul led rosso della camera basta eseguire da terminale:
    sudo nano /boot/config.txt ed aggiungere al fine del file di configurazione
    disable_camera_led=1 .
    Spero possa essere utile a qualcuno. Saluti!

  23. Ciao Mario,
    grazie! avevo provato, ma pare che a seconda del modello di telecamera, questa funzione non sia “ascoltata” dal sistema, infatti con il mio non funziona, se ha te ha funzionato, meglio, è una cosa fastidiosa a volte 🙂

  24. bel lavoro,
    stavo pensando ad un modo piu “automatico” per attivare e disattivare la videosorveglianza.
    che ne pensi, ammesso che sia fattibile, far verificare al raspi se nella lan sono connessi altri dispositivi esempio smatphone e nel caso positivo non serve la video sorveglianza perche significa che siamo in casa….. e viceversa. immagino che dovremo filtrare altre eventuali device che potremmo avere in casa.

  25. Ciao Andrea,
    grazie del commento e dei complimenti! Avevo già pensato a questa cosa, ma i cellulari (iPhone soprattutto), quando sono in standby disattivano la connettività WiFi e per le notifiche usano il 3G, quindi l’ho esclusa dopo un test di mezz’ora. Se hai un dispositivo che porti sempre con te e che sai che mantiene la wifi sempre attiva basta che tu imposti una reservation sul DHCP del tuo router in modo che assegni sempre lo stesso indirizzo al dispositivo e che regolarmente fai un PING su quell’IP, se è in rete allora disattivi l’antifurto.
    Ci sono due problemi:
    1- attento al delay di connettività, magari la tua WiFi si prende poco oltre la porta di casa e quindi rischi di entrare prima che il dispositivo venga trovato in rete
    2- devi essere assolutamente certo che la tua rete sia inaccessibile e che nessun altro abbia quell’IP, se no va tutto a pallino.

    Ciao!

Nota importante, da leggere prima di commentare

Questo è un blog scritto per passione, non fornisco quindi risposte di tipo professionale, se avete bisogno di un aiuto tecnico rivolgetevi ad un professionista di fiducia, non offendetevi se mi astengo dal rispondere. Vi ringrazio per la comprensione.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.