Le besoin
Tout en sachant parfaitement que mes bricolages ne remplaceraient jamais un véritable système d’alarme, je voulais mettre en place quelque chose qui me prévienne lors de la détection d’un mouvement chez moi. Bien sur, le système devait être le plus automatisé possible, et facilement pilotable depuis un smartphone. Au niveau matériel, je disposai de mes serveurs, de caméras usb et d’une caméra IP.
Détection de mouvement
Premier gros soucis, je ne suis pas parvenu à faire fonctionner la foscam avec Zoneminder. (D’autres semblent pourtant y parvenir sans problèmes…) D’après les messages d’erreurs, les images jpeg qu’elle envoi sont corrompues. Une mise à jour du firmware n’a strictement rien changé. Heureusement que d’autre logiciels, à commencer par motion, sont plus tolérants, et parviennent à récupérer le flux vidéo (même si des warning en mode debug indiquent la aussi très clairement que la « syntaxe » des fichiers jpg n’est pas respecté).
Paramétrer motion pour qu’il utilise la caméra se fait sans difficulté :
netcam_url http://ip_fixe/videostream.cgi?user=LOGIN&pwd=PWD&resolution=32&rate=3
Pour connaître la liste des arguments possible et ainsi pouvoir régler la résolution et la fréquence de capture, je vous invite à aller lire ceci.
Le vrai soucis était plutôt le paramétrage lié à la détection de mouvement. La, je vous laisse le soin de lire la documentation de motion avec attention. En ce qui me concerne, j’ai du par exemple indiquer « minimum_motion_frames 15 », autrement dit, le soft ne considère qu’il y a un vrai mouvement qu’a partir de 15 images différentes. A une fréquence de 10 images par seconde, cela signifie qu’un mouvement ne sera détecté que si il dure plus d’une seconde et demi. Un paramétrage qui n’est pas optimal, mais qui permet de limiter le nombre d’alarmes inutiles (généralement du à une modification de la luminosité, et cela malgré l’utilisation d’un autre paramètre : lightswitch 100.
Un peu d’automatisation
Détecter les mouvements c’est fait. Assembler les images pour créer un fichier .mp4, motion sait aussi le faire en standard. Par contre, pour mettre à disposition la vidéo et envoyer un petit mail avec le bon lien, la un petit script de quelques lignes est nécessaire. Petit soucis, dans le fichier de configuration de motion, on ne peut donner qu’un seul argument au script que l’on appel. Pour passer plusieurs parametres (le numéro de la caméra, le nom du fichier etc) il faut donc ruser un peu en concaténant les arguments, avant de les ré-découper dans le script. Cela donne par exemple dans le fichier motion.conf
on_movie_end /etc/motion/scripts/movie_end "%t@%f"
Ici j’assemble %t et %f, en utilisant un @ comme séparateur. Dans le script, il suffit de ré-découper :
CAMERA=`echo $1 | cut -d'@' -f1` PATH_FILE=`echo $1 | cut -d'@' -f2`
Une fois les arguments récupérés, on fait bien ce que l’on veut (envoi de mail, upload des vidéos, mise à disposition sur un serveur web etc).
Motorisation
Il y a des gens qui n’ont pas confiance dans la sécurité de leur machine. Et malgré tout le soin et le sérieux que j’ai mis à sécuriser la solution (ajouts de reverse proxy https, etc), personne n’est totalement infaillible. Surtout, je peux comprendre qu’il n’est pas très agréable de se sentir observé 24h/24. Il fallait donc faire en sorte que la caméra se tourne lorsque le système de détection n’était pas opérationnel. Pour cela il suffit d’utiliser les « presets ». On commence par régler la caméra pour qu’elle regarde précisément la zone à surveiller, et on enregistre la position (position 1). Ensuite, on fait tourner la caméra pour qu’elle regarde totalement ailleurs (le plafond ou ce que vous voulez) et on enregistre une position 2. Pour passer d’une position à l’autre, il suffira alors d’une simple commande wget :
wget -q -O /dev/null "http://ip/decoder_control.cgi?command=31&user=X&pwd=PWD"
La encore, je vous renvoi à cette page. Les mouvements de la caméra sont donc très facilement scriptable (sur la FI8918W, le preset 0 est en fait le premier, le premier est le second etc).
Contrôle à distance
Il était facile, via la crontab, d’automatiser le système pour qu’il s’enclenche et se désactive à une heure donnée. Mais il faut aussi pouvoir piloter le tout à distance. Pour cela, un peu de php à été nécessaire. (Note : Je suis admin sys, pas développeur web… donc oui, c’est probablement TRES moche comme code et je suis ouvert à toutes les suggestions). Sur un serveur https correctement protégé, ajouter les deux pages suivantes :
La page d’index :
<html> <font size=7> <?php exec('ps -eaf | grep -v grep | grep motion',$sortie,$code_retour); if ( $code_retour == 0 ) { print "<p align=center> Surveillance ACTIVE </p>";} if ( $code_retour == 1 ) { print "<p align=center> Surveillance desactivee </p>";} ?> <form method="post" action="./traitement.php"> <p align="center"> <input type="submit" name="on" value="ON" style="height: 200px; width: 600px" /> </p> <p align="center"> <input type="submit" name="off" value="OFF" style="height: 200px; width: 600px"/> </p> </form> </font> </html>
La page de traitement du « formulaire » :
<html> <head> <meta http-equiv="refresh" content="3;url=index.php" /> </head> <font size=7> <?php error_reporting (E_ALL ^ E_NOTICE); if ( $_POST['on'] == "ON" ) { $cmd = "/etc/motion/scripts/goto_pos1" ; $id = shell_exec($cmd); sleep (17); $cmd = "sudo /etc/init.d/motion start" ; $id = shell_exec($cmd); } if ( $_POST['off'] == "OFF" ) { $cmd = "sudo /etc/init.d/motion stop" ; $id = shell_exec($cmd); sleep (4); $cmd = "/etc/motion/scripts/goto_pos2" ; $id = shell_exec($cmd); } ?> <p align=center>C'est fait !</p> </font> </html>
Pour que cela fonctionne, il faut que le serveur web ai le droit de lancer ou d’arrêter motion. Prenez bien soin de lui donner uniquement ce droit la. A propos de sécurité, si vous voyez la moindre faille dans ces deux bouts de code, merci de me le signaler 🙂
Conclusion
Lorsque j’ai montré ce bricolage à ma femme, en lui expliquant comment activer ou désactiver la surveillance à partir de son téléphone, elle l’a dit que j’étais fou. Mais… je crois qu’elle m’aime bien quand même 🙂 Il me reste quelques détails à peaufiner. Automatiser la purge des photos et de vidéos capturés par exemple. Et surtout mettre en place un système de synthèse vocale pour prévenir les intrus que leur tronche est déjà uploadée sur le net et qu’ils se sont trompés de maison… Cela fera, peut être, le sujet d’un autre billet.
shell_exec ? Non ? pas toi !
Alors comme je l’ai dit, je suis pas développeur moi. Et quand on tape « php exec », on voit que des fonctions qui font quasiment la même chose il en existe au moins 3 ou 4. Alors la comme ça, désolé, j’ai pris la première qui à tout de suite fait ce que je voulais. Si il faut que je remplace par autre chose, tu m’explique, et je corrige 🙂
Pour le reverse https t’utilise quel serveur? T’as essayé de creuser pour faire de l’authentification par certificat client? (cf. la page d’auth de Cacert ou starssl)?
J’ai tenté de faire ça avec nginx et j’ai pas trouvé, donc si ça t’intéresse et que tu trouves, je suis preneur 😀
Pour le serveur utilisé, c’est apache. (sachant qu’il tournait déjà sur le serveur, pourquoi en utiliser un autre…) Pour la mise en place des certificats clients, vu le contexte, c’est une excellente idée. Il faudra que je me penche sur la question un jour 🙂
C’est dommage de devoir transmettre le user & password de ta caméra en clair quand tu fais le wget… Pas moyen de faire autrement ?
Bonne remarque aussi 🙂 Malheureusement, pour le moment, je vois pas trop comment faire autrement. Le firmware de la caméra ne sait pas travailler directement en https. Sur mon réseau (filaire) je ne suis pas trop inquiet au niveau écoute. Par contre, ces informations apparaissent forcément (même brièvement) dans la liste des processus…
Une faille potentielle donc, mais que je ne vois vraiment pas comment éviter.
Tres Tres interessant.
Le sujet m’interesse mais je n’y connais rien en Php . Je en retraite et j’ai décroché depuis 10a. Est-ce que je pourrai par exemple utiliser plusieurs camera ip ? j’ai 15.000 m a surveiller ( en espagne )
Bravo
motion supporte en théorie un nombre illimité de caméra. Par contre, le cpu, qui doit évidement analyser chaque image reçue en temps réel, ne pourra surement pas surveiller plus de quelques caméras. De plus motion n’est pas vraiment adapté pour gérer un grand nombre de caméras (plus de 4 ou 5 quoi). Pour un parc important (plus de 10), mieux vaut se tourner vers un logiciel de surveillance vraiment fait pour ça, comme zoneminder.