Hack caméra PTZ
Introduction
J’avais fait l’acquisition, il y a longtemps, d’une caméra-dôme PTZ (Pan-Tilt-Zoom) de surveillance, sur IP ethernet -pas WIFI-, placée à l’extérieur, à l’angle du toit pour un angle de vue maximal.

Problème : son interface de gestion est en Java, et je n’ai jamais eu l’intention de faire tourner du java sur mes PC.
Par chance, cette caméra possède un accès SSH.
J’ai donc entrepris d’investiguer son fonctionnement.
Fonctionnement interne
Sans la moindre surprise : c’est du Linux !
- parfeu iptables
- connexion SSH
- flux caméra rtsp (avec login/passwd)
- Pilotage PTZ sur DBus
- Commandes internes CGI, pour la partie http
HTTP
Au début, j’avais juste fait un hack en “auditant” les commandes passées par http sur le site
Bilan : la session est renégociée à chaque fois, ce qui fait que le temps de réaction est assez pénible.
SSH
Même chose : une commande passée individuellement, renégocie le login (ça reste une petite machine) → latence importante.
DBus
Il y a de quoi faire :
$ grep -E "<(interface|method|property|signal)" PTZ.Coordinator.xml
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<method name="Set">
<method name="GetAll">
<interface name="com.axis.PTZ.Coordinator">
<method name="Command">
<method name="UpdateStaticProperties">
<method name="GetStaticProperties">
<method name="RegisterDriver">
<method name="Queue">
<method name="GetDriverName">
<method name="GetSupportParameters">
<method name="SetDevicePreset">
<method name="RemovePresetNumber">
<method name="RemovePresetName">
<method name="UpdatePreset">
<method name="CreatePreset">
<method name="SetPresetNumber">
<method name="SetPresetName">
<method name="OsdMenu">
<method name="FieldAngles">
<method name="QueryZoomDelim">
<method name="QueryPosition">
<method name="QueryPresets">
<method name="QuerySpeed">
<method name="AreaZoom">
<method name="GetAuxiliary">
<method name="Auxiliary">
<method name="Image">
<method name="GotoHome">
<method name="GotoDevicePreset">
<method name="GotoPresetNumber">
<method name="GotoPresetName">
<method name="MoveLL">
<method name="MoveCmd">
<method name="Move">
<method name="MovePTZ">
<signal name="PtzStaticPropsUpdated">
<signal name="PtzParametersSetup">
<signal name="DriverUninstalled">
<signal name="DriverState">
<signal name="DriverCapabilities">
<signal name="SpeedControlEnable">
<signal name="DefaultSpeed">
<signal name="PtzPreset">
<signal name="PtzAction">
<signal name="PtzMoveEnabledChanged">
<signal name="PtzLockedChanged">
<signal name="PtzEnabledChanged">
<signal name="CamPort">
<signal name="TiltFlipped">
<signal name="PanFlipped">
<signal name="CtlQueueEnabled">
<property name="TiltFlipped" type="b" access="read"/>
<property name="PanFlipped" type="b" access="read"/>
<property name="DriverExtraCapabilities" type="i" access="read"/>
<property name="DriverMoveCapabilities" type="i" access="read"/>
<property name="Name" type="s" access="readwrite"/>
<property name="PTZEnabled" type="b" access="readwrite"/>
<property name="PTZLocked" type="b" access="readwrite"/>
<property name="CamPort" type="i" access="readwrite"/>
<property name="Various" type="s" access="write"/>
<property name="Support" type="s" access="write"/>
Méthode
Je créé donc une instance SSH persistante (avec échange de clés), à partir d’un petit script bash, appelé par mon appli Python/GTK :
#!/bin/sh
START_CMD='ssh -M -S ~/.ssh/cam_mux -fNT user@cam'
STOP_CMD='ssh -S ~/.ssh/cam_mux -O exit user@cam'
case "$1" in
start) eval $START_CMD ;;
stop) eval $STOP_CMD ;;
*) echo "usage: $0 [start|stop]"; exit 2 ;;
esac
Dans l’application :
cmd = f'ssh -S {self.ssh_socket} {self.user}@{self.host} \
dbus-send --system {command_line}'
Et voilà !
IA de détection
En ce qui concerne l’IA de détection, j’utilise tensorflow, avec le modèle très light :
ssd_mobilenet_v2_coco_quant_postprocess.tflite
à cette adresse :
https://github.com/google-coral/edgetpu/tree/master/test_data
Pour mon petit ordi, ça fait le taf, sans être trop gourmand en ressources (sur CPU -pas de GPU-)
Le Code
Aujourd’hui, j’ai au final une interface GTK de pilotage complet, avec IA de détection de présence et identification⁽¹⁾, tracking automatique, tours de garde, enregistrement automatique et alerte via un bot sur mobile avec snapshot (capture d’image).
Je ne fournis pas le code en Libre/public : c’est quand même un bricolage perso pas très propre -j’ai dû beaucoup tâtonner-, qui pourrait comporter des failles de sécurité. (voir Conclusion)
⁽¹⁾ Je ne fais pas pour l’heure de véritable contrôle d’identité automatisée (ça reste encore intrusif et peu légal). Uniquement de l’identification de formes : chat/chien/voiture/personne/…

y’a écrit “cat” - ‘faut que je change la couleur 😋 -
Conclusion
Évidemment la caméra d’origine ne faisait pas tout ça, et le modèle n’est même plus vendu, ni même mis à jour… Merci !
J’étais bon pour en acheter une autre, alors qu’elle fonctionne parfaitement et que j’ai pas les moyens !
Finalement, je me suis tout simplement retrouvé dans la même situation que Richard Stallman avec sa Xerox -histoire bien connue des Libristes : c’est la base de tout !-.
Et enfin, mon obligation morale tiendrait de fournir le code de mon hack, sous licence GNU/GPL. Il me faudra m’employer à le finaliser. (Nettoyage, sécurisation, documentation), et le poster en ligne.
NON : pas sur Github qui appartient à Micro$oft qui a donc là une mine de travail et d’idées gratuits, pour vous vendre ses produits -payés avec vos impôts- !