Arlo Videosorveglianza, basta con i falsi allarmi

Da quasi 2 anni uso con molta soddisfazione i sistemi Arlo per la videosorveglianza della mia casa.
Per chi non lo conoscesse, Arlo di Netgear, offre un sistema di domotica completa, che va dalle telecamere, alle sirene, dai campanelli alle telecamere per bambini.

Il topic di questo post e’ un tema che probabilmente sta molto a cuore a tutti i possessori di questo tipo di tecnologie (non solo di Arlo): la gestione dei falsi allarmi!
Se avete un sistema di videosorveglianza sapete sicuramente bene che, prima di chiamare la polizia all’arrivo di una notifica di allarme, e’ bene controllare prima la registrazione che lo ha generato, dato che al 99%, la causa non sara’ un tentativo di effrazione.

Stanco di questa situazione (tra l’altro, avendo un cane, vi posso garantire che i falsi allarmi sono all’ordine del giorno), mi sono provato ad inventare qualcosa costruendo un “lego” con tutte le tecnologie esistenti ad oggi.

Quello che volevo realizzare era un sistema che riuscisse, autonomamente, a filtrare i video con persone, da quelli con cani a quelli con automobili fino ad arrivare a video dovuti semplicemente al cambiamento di fattori meteorologici (vento, temporali….)

L’idea si puo’ riassumere in questo piccola ascii art:

sistema arlo casalingo
-> cloud arlo
-> API arlo
-> cloud privato
-> acquisizione video apena registrato
-> ImageAI applicato al video
-> inserimento su db influxdb
-> grafana per statistiche e allarmi
-> eventuale notifica in caso di rilevazione

Sembra complesso ma nella realta’ non lo e’ per niente, sopratutto perche’ persone intorno al mondo come noi, hanno gia’ creato piccoli pezzettini di codice che fanno tutto quello che ci servira’!

Mettiamoci all’opera!

Di cosa abbiamo bisogno?

La cosa fondamentale di cui abbiamo bisogno e’ un SERVER linux (che puo’ essere anche il vostro pc di casa o il vostro raspberry, fino ad arrivare ad una VPS in cloud).
Su di esso dobbiamo installare tutti i vari pacchetti python (hah giusto, ho basato tutto su python) che ci aiuteranno a raggiungere il nostro obiettivo ovvero:
1) python3 (almeno versione 3.5)
2) tensorflow 1.4.0 o successivo
3) opencv
4) keras
5) imageai
6) arlo python library

Sintentizzando, bastera’ lanciare questi comandi:

pip3 install -U tensorflow keras opencv-python arlo
pip3 install imageai --upgrade

Fatto questo il nostro ambiente sara’ operativo, ora sporchiamoci le mani con un po’ di codice!

from influxdb import InfluxDBClient
import os
import re
import datetime
import calendar
import warnings
import logging
from imageai.Detection import VideoObjectDetection
import os
from arlo import Arlo
import pytz
tz = pytz.timezone('Europe/Rome')
from datetime import timedelta, date
import sys
### Variables 
influxhost = "$INFLUXHOST"              #CHANGEME
influxport = "$INFLUXPORT"              #CHANGEME
influxuser = "$INFLUXUSER"              #CHANGEME
influxpassword = "$INFLUXPASSWORD"      #CHANGEME
influxdbname = "$DBARLO"                #CHANGEME
USERNAME = '$ARLOUSERNAME'              #CHANGEME
PASSWORD = '$ARLOPASSWORD'              #CHANGEME
videoinfo = None
datevideo = datetime.datetime.now()
fluxdb = InfluxDBClient(influxhost, influxport, influxuser, influxpassword, influxdbname)

prima di tutto andiamo a includere tutti i moduli che ci serviranno e andiamo a definire (ricordatevi di cambiare i valori) tutte le variabili che ci serviranno piu’ avanti.

def forSeconds(output_arrays, count_arrays, average_output_count):
        global datevideo
        global videoinfo
        try:
                count=0
                for i in average_output_count:
                        count+=1
                        json_body = [
                        {
                                "measurement": "motion",
                                "time": datevideo,
                                "tags": { "camera": videoinfo['deviceId'], "objects": "yes"  },
                                "fields": {
                                        i: "1",
                                        "videoid": videoinfo['uniqueId']
                                }
                        }]
                       fluxdb.write_points(json_body)
                if(count==0):
                        json_body = [
                        {
                                "measurement": "motion",
                                "time": datevideo,
                                "tags": { "camera": videoinfo['deviceId'], "objects": "no"  },
                                "fields": {
                                        "videoid": videoinfo['uniqueId']
                                }
                        }]
                        fluxdb.write_points(json_body)
    except Exception as e:
            print(e)

questa funzione sara’ il vero e proprio cuore di tutto, verra’ chiamata automaticamente ad ogni fine video, e aggiungera’ al db influx i dati raccolti. Ovviamente siete liberi di fargli fare quello che volete!

execution_path = os.getcwd()
fluxdb.create_database(influxdbname)
detector = VideoObjectDetection()
detector.setModelTypeAsTinyYOLOv3()
detector.setModelPath( os.path.join(execution_path , "yolo-tiny.h5"))
detector.loadModel(detection_speed="flash")

qui creiamo il db e istruiamo ImageAI a come operare una volta chiamato

try:
        arlo = Arlo(USERNAME, PASSWORD)
        today = (date.today()-timedelta(days=0)).strftime("%Y%m%d")
        library = arlo.GetLibrary(today, today)
        for recording in library:
                videoinfo = recording
                datevideo = datetime.datetime.fromtimestamp(int(recording['name'])//1000, pytz.timezone("UTC")).strftime('%Y-%m-%d %H:%M:%S')
                videofilename = datetime.datetime.fromtimestamp(int(recording['name'])//1000).strftime('%Y-%m-%d %H-%M-%S') + ' ' + recording['uniqueId'] + '.mp4'

andiamo ad iterare su tutti i video della giornata salvati dalle nostre telecamere Arlo

            if(os.path.isfile('videos/'+videofilename)==False):
                    stream = arlo.StreamRecording(recording['presignedContentUrl'])
                    with open('videos/'+videofilename, 'wb') as f:
                            for chunk in stream:
                                    f.write(chunk)
                            f.close()
                    print('Downloaded video '+videofilename+' from '+recording['createdDate']+'.')

salviamo il video

                    print(os.path.join(execution_path , 'videos/'+videofilename))
                    detections = detector.detectObjectsFromVideo(input_file_path=os.path.join(execution_path , 'videos/'+videofilename), frames_per_second=25, minimum_percentage_probability=50, save_detected_video=False, video_complete_function=forSeconds )

lanciamo ImageAI

except Exception as e:
    print(e)

e ovviamente gestiamo le eccezioni

Ecco tutto! Vi avevo detto che sarebbe stato semplice!
Al termine di questo script il vostro db influx verra’ riempito con gli oggetti riconosciuti comprensivi di data e ora.
Ovviamente voi potreste anche non voler usare un db ma farvi mandare semplicemente una mail con lo screenshot che ha generato il trigger.
Insomma l’integrazione di ImageAI con Arlo apre veramente ad un sacco di implementazioni!

Vi lascio qui sotto un po’ di link utili che mi sono serviti alla realizzazione di questo script, oltre che allo script stesso per intero!

Progetto GitHub: https://github.com/cagnulein/ArloAI

https://towardsdatascience.com/object-detection-with-10-lines-of-code-d6cb4d86f606
https://github.com/OlafenwaMoses/ImageAI
https://github.com/jeffreydwalter/arlo
https://github.com/tensorflow/tensorflow/issues/19584
https://github.com/yaroslavvb/tensorflow-community-wheels/issues/103
https://github.com/matcom/ml/releases/tag/tf-no-avx
https://github.com/OlafenwaMoses/ImageAI/releases/tag/1.0/

Ovviamente tutto cio’ sarebbe gia’ fattibile spendendo circa 1,5 euro al mese per telecamera con Arlo, ma questa e’ tutta un’altra storia…

Opentherm, questo sconosciuto [work in progress…]

Complice il periodo delle vacanze, ho iniziato a guardarmi intorno per trovare una soluzione ad uno dei tanti problemi irrisolti dell’universo: “come posso accendere e spegnere la caldaia da remoto”? 😀

Definiamo prima il mio scenario attuale: io abito in una casa su 2 piani con riscaldamento a pavimento. Ogni stanza presenza un termostato “scemo” (ovvero un classico on/off) che apre/chiude un’elettrovalvola nel circuito di riscaldamento. In sostanza, la caldaia, una Viessmann Vitodens 111, non ha nessuna idea della loro esistenza.

La mia idea era quella di collegare $qualcosa alla caldaia, e gestire da remoto almeno la sua accensione/spegnimento in caso di assenza da casa per più di un paio di giorni.

Ovviamente l’appetito vien mangiando, e mentre cercavo le possibili soluzioni mi sono detto: “ma perchè non trovare qualcosa che possa non solo accenderla, ma anche configurarla e addirittura anche leggerne i valori correnti”!

E da qui mi si è aperto un mondo 🙂

In prima battuta mi sono messo a leggere il manuale della mia caldaia: subito ho visto la presenza di 2 pin per il dialogo con “Opentherm”. Opentherm ho scoperto essere uno “standard” (ancora crediamo a babbo natale? :D) per il riscaldamento e la climatizzazione.

manuale della mia Vitodens. In particolare notare il connettore OT e mi dovrò ricordare di togliere il jumper “D” se presente

In parallelo, il consiglio del mio installatore è stato quello di installare il Tado. Tado offre una soluzione abbastanza plug & play, ma purtroppo non calza a pennello con quello che devo fare: infatti è molto limitato per quello che riguarda le API e sopratutto ha senso se tutti i termostati in casa fossero dei “Tadi”. In ogni caso, per parlare in Opentherm, è necessario un Extension KIT da collegare alla caldaia. Il kit quindi al completo sarebbe composto da 1 Termostato, 1 Gateway (per la connessione LAN) e l’Extension Kit per l’OT.

esempi di collegamenti con Tado, ringrazio Massimo per lo schema 🙂

Ho dato un’occhiata anche a Nest ma si è rivelato essere peggio di Tado: limitato e poco documentato.

Finalmente, dopo qualche ora di ricerca mi imbatto in un progetto tutto open source (sia ad hw che a sw): Opentherm Gateway.

Questa scheda, interamente progettata da uno smanettone come noi, permette di parlare tramite PIC con una caldaia Opentherm (qui la lista di compatibilità) e riportare via wifi i dati ad un dispositivo esterno (raspberry?).

Ovviamente me ne sono subito innamorato: tra l’altro è presente anche una colorità comunità.

Parlando di questa scheda, un utente del forum, mi ha fatto notare che esiste una soluzione chiamata Toon: in sostanza è un piccolo pannello touchscreen con una scheda di estensione chiamata “ketelmodule” che permette sia di agire come termostato che come scheda OT. E’ rootabile, e si può installare pure VNC. Bisogna però trovarli usati perchè di base vengono venduti da un provider elettrico olandese in abbonamento. Una strada un po’ troppo arzigoggolata per i miei gusti. Mi ha inoltre inviato un link dove poterli cercare usati.

Il costo è di circa 100€ (potete risparmiare qualcosa se avete già alimentatore 24V, se avete voglia di saldare o se avete già un cavo USB-TTL).

Riepilogando ecco cosa offre il mercato:

TadoNestOpentherm GatewayToon
Spegnimento/Accensione Caldaia da RemotoXXXX
Collegamento OpenthermXXXX
Possibilità di impostare temperatura acqua sanitariXXO (non so)
Possibilità di impostare temperatura mandata riscaldamentoXO (non so)
Soluzione professionaleXXO (nì)
OpensourceX
Controllo remotoXXX ma se accompagnato da un device esterno tipo raspberry piX
PrezzoCirca 300€249€Circa 100€50€ circa, dipende dalle offerte