Application de Splunk pour la sécurité… routière !
Introduction
Splunk est un logiciel de recherche, de suivi et d'analyse de données machines permettant d’aider les organisations à découvrir, extraire et exploiter tout le potentiel caché de leurs données. En tant que tel, ses champs d’application sont quasi-infinis dans la mesure où chacune de nos actions peut aujourd’hui générer une information à analyser.
Je propose donc de prouver cela par un exemple concret d'application de Splunk dans un domaine bien particulier : l’analyse de comportements humains.
Constat : Une rue à faible visibilité, d'une largeur insuffisante pour permettre à deux voitures de se croiser, sans aucun trottoir pour les résidents qui sortent de leur domicile, une vitesse limitée à 30 km/h, et pourtant de nombreux automobilistes roulent beaucoup trop vite et commettent à l'évidence des infractions à répétition.
Action : Demande faite à la commune pour mettre en œuvre les mesures de sécurité adéquates.
Résultats : Après plus d'un an, toujours aucune action mise en œuvre.
Idée : Si les personnes décisionnaires ne prennent aucune mesure correctrice, c'est qu'elles n'ont pas les éléments prouvant leur nécessité, et que rien ne les contraint à le faire ou à le traiter en priorité.
Pour faire avancer la situation, l'idéal serait donc que j'arrive à mesurer et analyser moi-même la situation pour l'exposer de manière plus factuelle qu'un simple constat du type « on trouve que les voitures roulent vite dans cette rue ».
La seule preuve concrète et respectueuse du règlement général sur la protection des données à caractère personnel serait de mesurer la vitesse des véhicules sans identification de ces derniers ni de leurs conducteur(rice)s pour quantifier et exposer de manière factuelle le comportement déviant de certains automobilistes.
Concept
L’objectif est le suivant : générer les données relatives à la vitesse des véhicules afin de pouvoir la collecter et l’exploiter dans Splunk. La condition sine qua non est donc d’arriver à la mesurer de façon simple, peu onéreuse, et sans avoir à disposition un radar des forces de l’ordre.
Comme chacun le sait, la vitesse est la grandeur définie par le temps mis à accomplir une action (dans le cas présent : parcourir une certaine distance). Par chance, j’ai à ma disposition un environnement idéal : deux fenêtres en rez-de-chaussée orientées dans le même sens, positionnées sur un même mur directement adjacent à la rue, à la même hauteur, et à une distance de plusieurs mètres l’une de l’autre.
- Cette distance étant fixe et mesurable, il suffit donc de chronométrer le temps mis à la parcourir afin d’en déterminer la vitesse au même titre qu’un radar tronçon :
-
Inconvénients :
-
Ce système ne permet que de calculer la vitesse moyenne sur cette portion. Cependant, elle peut être considérée comme étant quasi égale à la vitesse instantanée étant donné la faible distance parcourue.
-
RGPD oblige (pour mieux comprendre les principes de la protection des données personnelles, voici un autre article de notre blog : https://www.algosecure.fr/actualites/article/rgpd-conservation-donnees-personnelles), je ne pourrai pas non plus utiliser de caméras, donc je ne pourrai pas garantir à 100% que deux de détections correspondent bien à un même véhicule, ni même d’ailleurs que ce soit bien un véhicule.
Acceptés : L’objectif n’est pas de fabriquer un radar parfait et homologué. La priorité est pour moi d’avoir de la donnée à exploiter rapidement et simplement, même si celle-ci est une estimation. La précision pourra toujours être améliorée dans un second temps si nécessaire.
-
-
Avantages :
-
Simple, sous réserve d’arriver à chronométrer le temps de parcours
-
En fonction de l’ordre chronologique des détections, je pourrai en déduire le sens de circulation afin de prendre en compte ce paramètre dans mes statistiques. L’une des hypothèses que je souhaiterais valider est la suivante : les véhicules roulent plus rapidement et commettent davantage d’excès de vitesse en entrant dans le village qu’en y sortant. Cela pour une raison simple : la topologie de la rue offre une meilleure et plus longue visibilité dans ce sens-là. Si je peux prouver qu’un sens particulier de circulation est plus sujette aux excès de vitesse qu’une autre, alors cela permettrait d’aider les personnes décisionnaires à faire des choix plus pertinents quant aux moyens à mettre en œuvre pour améliorer cette situation de manière plus efficace.
-
Pour mesurer le temps parcouru, il faudrait donc détecter de manière automatique lorsqu’un véhicule passe deux points de référence (ici mes deux fenêtres). Une solution offre pour cela un très bon compromis entre simplicité, coût et efficacité : les capteurs.
Aucun besoin de déporter le calcul ailleurs que dans Splunk : j’ai uniquement besoin que mes deux points de référence m’indiquent le moment exact auquel ils détectent un mouvement et que je récupère cette donnée.
- Si je parviens à avoir ces valeurs de temps, alors je pourrais en déduire la durée.
- Ayant déjà la distance qui est fixe, j’en déduirai la vitesse, dont l’unité de mesure la plus pertinente sera le nombre de mètres par seconde.
- Il me suffira ensuite de la convertir en kilomètres par heure grâce au calcul suivant : il y a mille mètres dans un kilomètre et trois mille six cents secondes dans une heure donc $1$ m/s = $(1/1000) / (1/3600)$ = $3600 / 1000$ = $3,6$ km/h.
- J’aurais alors l’heure et la vitesse des véhicules dans Splunk, et je n’aurai plus qu’à l’exploiter.
Le système de détection
Les contraintes
Il me faut gérer moi-même les détections et leurs envois vers Splunk en horodatant l’information transmise.
- Ainsi, peu importe le temps que met cette donnée à être reçue : c’est l’heure indiquée au sein de l’information qui fera foi et non celle de réception de cette dernière.
Les deux points de mesure étant éloignés l’un de l’autre de plusieurs mètres, il me faut donc deux systèmes de détection indépendants et parvenir à ce qu’ils soient synchronisés au niveau temporel.
Enfin, je souhaite travailler sur une solution open-source pour des raisons de budget et pour donner à chacun la possibilité de reprendre et améliorer cette solution.
Le matériel
Mon serveur Splunk étant déjà en place, configuré, et en fonctionnement, ce point-là est déjà réglé et le choix du matériel va se porter uniquement sur le système de détection des véhicules.
Étant donné que j'ai décidé d'utiliser des capteurs, les composants open-source qui me permettront de les gérer en autonomie, de manière peu onéreuse, tout en me laissant une complète liberté au niveau du code exécuté sont les cartes Arduino.
- L'objectif étant que la donnée soit collectée dans Splunk, il faut donc qu'elle transite sur le réseau jusqu'à mon serveur.
- Bien qu'il soit possible d'utiliser une liaison filaire avec un câble RJ45 pour la communication depuis un Arduino via un composant spécifique (Shield Ethernet), je n'ai pas vraiment envie d'acheter et d'installer des mètres de câbles entre mes chambres et mon bureau.
- Je vais par conséquent privilégier une connexion sans fil avec des cartes qui prendront en charge directement ce mode de communication : des Arduino R4 Wifi.
Au niveau de la connectique, je possède déjà des fils de connexion nécessaires pour pouvoir relier les capteurs aux cartes.
Au niveau des capteurs, mon choix se porte sur le modèle infrarouge HC-SR501 :
Principales caractéristiques :
- Gamme de détection : 110 degrés
- Détection de la distance : jusqu'à 7 mètres
- Temps de blocage : 2,5s par défaut
- Possibilité de réglage de la sensibilité et de la temporisation
Il suffit donc de connecter le capteur à la carte Arduino comme suit :
Broche capteur | Broche Arduino |
---|---|
VCC | 5V |
OUT | D2 (au choix) |
GND | GND |
Le code Arduino
Contrainte n°1: le temps
La première chose essentielle qu'il a fallu déterminer est la manière de synchroniser les deux cartes Arduino au niveau temporel. En effet, de base les cartes n'ont aucune connaissance de l'heure qu'il est. La seule composante temporelle en leur possession est le nombre de millisecondes écoulées depuis qu’elles ont commencé à exécuter le programme en cours, qui est réinitialisé après environ 50 jours (cette valeur peut être récupérée via la fonction millis()).
Problème : il est impossible de faire démarrer les deux cartes en même temps à la milliseconde près donc cette valeur est inutilisable.
Solution : Les cartes étant connectées au réseau Wifi, elles peuvent donc avoir accès à Internet.
- Il existe un protocole bien connu permettant de synchroniser l'horloge locale des machines via le réseau : le protocole NTP (Network Time Protocol).
- Mes cartes pourront ainsi récupérer et transmettre cette heure qui sera toujours correcte, même si nous vivons dans un pays qui change d'heure deux fois par an.
- Il me reste donc à trouver le moyen de faire interroger un même serveur NTP par mes cartes pour qu'elles se synchronisent avec celui-ci à la même heure.
- Heureusement, les Arduino fonctionnant sous code open-source, des librairies existent généralement pour chaque besoin dont celui-ci avec la librairie
ezTime
.
Contrainte n°2 : l'envoi des données à Splunk
Les cartes Arduino ne possèdent pas de système d'exploitation et donc ne peuvent pas accueillir un agent Splunk déjà packagé.
- Par chance, il existe de nombreuses autres méthodes de collecte dans Splunk.
- L'une de ses méthodes déjà éprouvée dans mon contexte professionnel est l'utilisation du HEC (HTTP Event Collector), qui permet d’envoyer les données à une instance Splunk via le protocole HTTP/HTTPS.
- Il me reste donc à trouver le moyen de faire envoyer par mes cartes les données reçues des capteurs dans des paquets HTTP à destination de mon serveur Splunk qui sera préalablement configuré pour les collecter et les indexer correctement.
- Exceptionnellement, je ne sécuriserai pas le flux via HTTPS car je ne transmets aucune donnée sensible et je travaille dans un cadre personnel.
Contrainte n°3 : l'identification des capteurs
Afin de pouvoir analyser la durée et l'ordre des détections, il me faut identifier de manière fiable et unique le capteur qui communique ses données. Il est possible de spécifier manuellement la valeur de la métadonnée « host » identifiant la source de la donnée dans Splunk mais je souhaite avoir un code unique quel que soit mon capteur et utiliser une seule entrée de données pour toutes mes cartes Arduino.
- La solution choisie consiste à utiliser le dernier octet de l'adresse IP retournée par mon serveur DHCP aux cartes.
- Je sais en effet que mon réseau Wifi utilise un masque en /24 fournissant ainsi jusqu’à 254 IP potentielles disponibles entre les adresses X.X.X.1 et X.X.X.254. Le dernier octet sera donc toujours unique.
- Il me suffit de faire attribuer une adresse statique à chacune de mes cartes par mon serveur DHCP pour garantir qu'elles ne changeront jamais même après redémarrage, puis de récupérer et d’utiliser le dernier octet attribué pour forger un nom unique à chaque carte.
Algorithmie et structure du code :
Toute création de code nécessite au préalable deux choses :
- Connaître la structure du programme pour le langage utilisé
- Réfléchir à l'algorithmie nécessaire pour répondre au besoin
La structure d’un code Arduino reprend beaucoup d'éléments communs à d'autres langages plus complexes :
- Importation des libraires (facultatif si non utilisées)
- Création des variables et constantes globales (facultatif)
- Fonctions (facultatif)
- Partie "Setup" :
- Identifiée par la fonction setup()
- Exécutée directement après le démarrage de la carte
- Exécutée une seule et unique fois
- Utilisée pour initialiser les variables, les modes des broches de la carte et commencer à utiliser les librairies
- Partie "Loop"
- Identifiée par la fonction loop()
- Exécutée directement après la partie setup()
- Exécutée en boucle infinie
- Utilisée pour réaliser les principales opérations de l'application
L'algorithmie envisagé pour mon besoin en fonction de cette structure sera donc le suivant :
-
Importation des librairies nécessaires pour la connexion Wifi, la synchronisation NTP, et les envois HTTP
-
Création des variables et constantes globales nécessaires
-
Partie Setup avec :
- Connexion à mon réseau Wifi
- Récupération du dernier octet de l'adresse IP pour forger le nom de la carte
- Initialisation de l'heure et de la fréquence de mise à jour NTP
- Initialisation de la broche 2 de la carte pour lire les données du capteur
-
Partie Loop avec :
- Lecture des données du capteur
- Si un mouvement est détecté : forger et envoyer la donnée à Splunk puis réinitialiser le capteur et attendre qu'il revienne à son état initial
- Sinon ne rien faire
Voici donc le code finalement utilisé par chacune des cartes Arduino :
// Importation des librairies
// NTP
#include <ezTime.h>
// Connexion Wifi
#include <WiFi.h>
// Envoi des paquets HTTP
#include <ArduinoHttpClient.h>
// Fichier dédié contenant mes données sensibles (SSID, clé Wifi, adresse IP de mon serveur Splunk, et token d’authentification vers ce dernier)
#include "arduino_secrets.h"
// Paramètres Wifi récupérés depuis le fichier arduino_secrets.h
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
// Paramètres de connexion à Splunk récupérés depuis le fichier arduino_secrets.h
char splunkindexer[] = SPLUNK_IDX;
char collectorToken[] = SPLUNK_TOK;
int port = 8088;
// Initialisation des variables qui me seront nécessaires par la suite
// Pour la connexion Wifi
WiFiClient wifi;
int status = WL_IDLE_STATUS;
// Pour le NTP
Timezone France;
// Pour la connexion à Splunk
HttpClient client = HttpClient(wifi, splunkindexer, port);
// Pour la broche et les états du capteur
int sensorPin = 2;
int sensorState = LOW;
int sensorValue = 0;
// Pour les éléments à transmettre à Splunk
String date;
String eventData;
String host;
// Fonction utilisée pour les envois vers Splunk
void splunkpost(String collectorToken,String PostData, String Host)
{
// Affichage des données à envoyer
Serial.println(PostData);
// Inclusion des évènements à envoyer dans le paquet HTTP
String postData = "{ \"event\": \"" + PostData + "\"}";
// Authentification via token
String tokenValue="Splunk " + collectorToken;
// Initialisation du client
client.beginRequest();
// Définition de l’URL à contacter pour les envois en HTTP POST
client.post("/services/collector/event");
// Définition des différents en-têtes du paquet HTTP
client.sendHeader("Content-Type", "application/application/json");
client.sendHeader("Content-Length", postData.length());
client.sendHeader("Host", Host);
client.sendHeader("Authorization", tokenValue);
// Inclusion des données
client.beginBody();
client.print(postData);
// Fin de transmission de la requête
client.endRequest();
// Lecture et affichage du code retour et du corps de la réponse
int statusCode = client.responseStatusCode();
String response = client.responseBody();
Serial.print("POST Status code: ");
Serial.println(statusCode);
Serial.print("POST Response: ");
Serial.println(response);
}
// Partie setup
void setup() {
// Définition du débit de données en bits par seconde (baud) pour la transmission de données sur le moniteur série de la carte.
Serial.begin(9600);
// Connexion Wifi avec affichage des informations en série
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to Network named: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
}
// Récupération et affichage de l’adresse IP allouée
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// Utilisation du dernier octet pour paramétrer le nom d’host unique
host="sensor"+String(ip[3]);
// Paramétrage du serveur NTP à contacter, de la fréquence des synchronisation et affichage des évènements de synchronisations
setServer("ntp.unice.fr");
setInterval(60);
waitForSync();
setDebug(INFO);
// Paramétrage de la timezone, essentielle pour avoir l’heure correcte
France.setLocation("Europe/Paris");
// Paramétrage de la broche du capteur en mode entrée et envoi des premières données à Splunk pour valider la communication initiale
pinMode(sensorPin, INPUT);
eventData="Initializing System...";
splunkpost(collectorToken,eventData,host);
// Pause de 5s pour laisser le temps au capteur de s’initialiser
delay(5000);
}
// Partie loop
void loop() {
// Synchronisation NTP de manière récurrente à la fréquence définie
events();
// Lecture de la valeur du capteur
sensorValue = digitalRead(sensorPin);
// Si le capteur a détecté un mouvement
if (sensorValue == HIGH) {
// Si le capteur n’avait rien détecté avant
if (sensorState == LOW) {
// On forge la donnée à envoyer avec la date en millisecondes
eventData=France.dateTime("d-m-Y H:i:s.v") + " - Motion detected !";
// On transmet la donnée grâce à la fonction créée
splunkpost(collectorToken,eventData,host);
// On positionne l’état du capteur comme étant en détection
sensorState = HIGH;
// On attend 1s pour un début de temporisation
delay(1000);
}
}
// Si la variable d’état du capteur est en détection
if (sensorState == HIGH) {
// On attend encore 1s
delay(1000);
// On positionne sont état en mode non-détection pour faire la lecture suivante
sensorState = LOW;
}
}
La collecte dans Splunk
L'ensemble de la configuration d'un serveur Splunk étant déjà documentée sur le site de l’éditeur, je me contenterai uniquement d'indiquer la configuration nécessaire à l'entrée des données de mes cartes Arduino :
- Un index pour réceptionner, compartimenter et stocker les données Arduino que je vais pouvoir interroger :
- Une entrée HTTP Event Collector avec un token d’authentification pour recevoir les données transmises par les Arduino sur un port bien spécifique (TCP 8088 par défaut) et les stocker dans l’index précédemment créé :
Les résultats
Sur la carte
Une fois le code téléversé sur la carte, voici les données qui s’affiche sur le moniteur série (avec génération d’un mouvement devant le capteur) :
A chaque mouvement qui survient au niveau du capteur j'ai donc l'heure et la notification transmise à Splunk avec un code retour HTTP 200 (OK).
Dans Splunk
En cherchant dans l’index sur la période concernée, je retrouve bien les données de mes deux cartes identifiées de manière unique (les logs ci-dessous sont évidemment différents de ceux précédemment affichés sur le moniteur série de la carte Arduino) :
J'ai donc bien les données générées par mes capteurs, transmises par mes cartes Arduino, reçues et stockées dans mon serveur Splunk. Il reste à les exploiter et les analyser mais avant cela, un problème doit au préalable être résolu.
Adaptations des capteurs
Les premiers tests réalisés étaient concluants en environnement intérieur mais en les réalisant en conditions réelles dans la rue, j'ai constaté un taux élevé de faux positifs avec des détections sans qu'aucun véhicule ne soit présent. La raison est la suivante : les capteurs de mouvements infrarouges fonctionnent avec un large faisceau de détection (110 degrés pour ce modèle de capteurs).
- Dans mon salon, il n'y avait aucun mouvement autres que ceux que je déclenchais moi-même pour mes tests de fonctionnement.
- Dans la rue, il en est tout autrement : le vent qui fait bouger les feuilles, un oiseau qui se pose sur un muret, un sac en plastique qui virevolte de manière poétique... Les mouvements sont divers et variés et chacun d'entre eux est détecté par mes capteurs.
- Si je souhaite limiter ce phénomène pour me concentrer sur les mouvements qui m'intéressent alors il faut que je bride moi-même le faisceau de détection des capteurs, afin que seule une zone limitée soit surveillée.
Malheureusement, je ne peux pas réduire l'angle du faisceau au niveau du capteur comme la portée et la temporisation qui sont modifiables à l'aide d'un tournevis sur de petits potentiomètres.
- Je vais donc devoir obstruer les capteurs assez finement pour limiter le faisceau dans une zone restreinte.
- Contrainte : il faut que cette obstruction soit strictement identique entre mes deux capteurs pour éviter toute différence de comportement entre eux.
J'ai donc improvisé avec les éléments à ma disposition :
- Deux petites boîtes de conserve vides et identiques
- Des morceaux d'un même carton
- Quatre trombones identiques
- De la patafix
- Un marteau et quelques clous
L'idée à partir de ces éléments :
- Enfermer mes capteurs au fond des boîtes de conserves
- Les fixer avec des trombones dépliés faisant office de fils de fer, en prévoyant également d'autres trous pour faire passer les fils de connectiques vers la carte Arduino
- Découper des cercles de cartons du même diamètre que les boîtes
- Les évider d'un petit trou
- Scotcher ces derniers pour obstruer les ouvertures
Le tout devant rester immobile, je complète avec deux petits couvercles d'emballages identiques pour servir de supports stables sur lesquels sont scotchées les boîtes.
Le résultat :
Merci à Angus de m’avoir appris qu’il existait toujours une solution étonnante pour résoudre un problème !
Après les avoir installés sur les bords de fenêtre, les détections ont directement été plus pertinentes : plus aucune détection de mouvements parasites et uniquement ceux d'objets qui passent exactement en face des capteurs (même si cela inclut d'autres éléments que les véhicules, par exemple les piétons, mais je traiterai ces faux-positifs dans mes calculs au sein de Splunk).
Exploitation des données
Une fois les données dans Splunk, et leurs champs extraits (même si dans le cas présent je n'ai pas eu à réaliser cette étape puisque seuls l'heure de l'évènement et l'identité de la carte source m'étaient nécessaires), elles peuvent être exploitées, manipulées, mises en forme, et enrichies grâce au langage de requêtage de Splunk : le SPL (Search Processing Language).
Ce langage étant documenté sur le site de l'éditeur, je me contenterai d'exposer progressivement l'élaboration de la requête pour illustrer comment, par différentes étapes successives, nous partons de données brutes pour arriver à des données mises en forme dans Splunk :
- J’interroge l’index concerné sur la période qui m’intéresse :
- Je m’occupe dès maintenant de définir quel capteur se trouve à quelle position :
- Je regroupe les évènements par paquets de deux, en partant du principe :
- Qu’il y a 2 secondes maximum de pause entre les passages de véhicules (car temporisation paramétrée dans le code des cartes Arduino entre chaque mesure)
- Qu’il y a un délai de 1s maximum entre chaque évènement d’un même bloc (car si un élément met plus d’une seconde à parcourir la distance entre les deux fenêtres, cela correspond à une vitesse inférieure à 12km/h, ce qui est certainement un faux-positif car aucune voiture ne roule aussi lentement dans la rue)
- Gros avantage de cette commande : elle calcule directement la durée entre l’évènement le plus ancien et le plus récent du bloc
- Je ne conserve que les blocs avec deux capteurs différents au cas où :
- Je commence à générer un tableau avec les données qui m’intéressent :
- Je renseigne la distance entre les capteurs, et je commence mes calculs : en fonction de l’ordre des capteurs, j’en déduis la direction, et en fonction de la durée, j’en déduis la vitesse en m/s que je convertis ensuite en km/h :
- Je conserve les vitesses plausibles entre 15 et 75 km/h et retire 5 km/h à la valeur calculée pour inclure la même marge d’erreur que les radars homologués :
- Je me renseigne sur le site www.service-public.fr et identifie les éléments suivants en fonction du niveau d’infraction :
- Je sais donc que dans mon contexte, les amendes seront uniquement de 135€ quel que soit le niveau d’infraction, et le nombre de points en fonction des différents seuils d’excès de vitesse
- J’exclus le dernier cas de 50 km/h et plus car celui-ci ne fait pas partie des valeurs plausibles dans mon contexte
- Je paramètre donc ces éléments en fonction de la vitesse mesurée, en sachant que la limite est de 30 km/h :
- Je ne conserve que les champs qui me sont utiles pour l’analyse :
De plusieurs simples logs de détection de mouvement, nous nous retrouvons donc avec :
- L'heure du passage devant les deux capteurs
- La vitesse en km/h mesurée et abaissée pour concorder avec le fonctionnement des radars homologués
- La direction de passage de l'objet
- Le niveau d'infraction en cas de vitesse supérieure à 30 km/h
- L'amende correspondant à l'infraction
- Le nombre de points retirés correspondant à l'infraction
- La suppression d'un maximum de faux-positifs en ne gardant que les vitesses plausibles et pouvant correspondre à celle d'un véhicule dans mon contexte
Il ne reste donc plus que la dernière étape de traitement, celle qui permet de mettre en évidence la valeur de la donnée et de la rendre accessible à tous : le dashboarding !
Dashboard et analyse
De la même manière que le langage SPL, l'idée n'est pas de montrer l'ensemble de la configuration d'un tableau de bord sur Splunk mais comment il est possible, à partir d'une donnée technique, d'arriver à un résultat beaucoup plus visuel, accessible et interprétable par tous.
Voici donc les différents éléments du dashboard créé, volontairement séparés pour une meilleure lisibilité, et sur une période d'analyse représentative de 24h consécutives :
Les données parlent d’elles-mêmes :
- Un tiers d’excès de vitesse (malgré avoir retiré 5 km/h aux mesures)
- Plus de 27 k€ d’amendes et presque 170 retraits de points sur cette journée
- Les plus grandes infractions sont généralement commises dans la matinée, aux alentours de midi (pauses déjeuner), et en fin d’après-midi (retours du travail)
La majorité des infractions sont situées entre 5 et 19 km/h au-dessus de la vitesse autorisée (donc une vitesse entre 35 et 49 km/h).
La vitesse moyenne est proche de la limite autorisée.
Mais le 90ème percentile est plus de 10 km/h au-dessus, ce qui signifie qu’une personne sur dix roule à plus de 42 km/h.
L’écart type est de 11 km/h, ce qui correspond à la dispersion des données autour de la valeur moyenne : cela permet de mettre en évidence les différences de comportements entre les automobilistes. Un faible écart-type indiquerait qu’une grande partie roulent à une vitesse proche de la valeur moyenne (28 km/h pour cette journée). Plus l’écart-type augmente, plus les valeurs sont au contraire dispersées.
Il y a légèrement plus de sorties du village que d’entrées.
Le nombre d’entrées augmente brusquement en fin d’après-midi (certainement dû aux retours du travail) tandis que les sorties sont davantage étalées dans le temps.
Malgré le nombre de passages plus élevés en sortie du village, plus de 76% des infractions sont faites dans le sens inverse, et ce quelle que soit l’heure.
Les infractions en entrée du village sont à un niveau d’excès de vitesse largement supérieur à celui du sens inverse.
Cela confirme mon hypothèse concernant la topologie de la rue qui incite davantage à ces comportements déviants dans ce sens-là de circulation.
Conclusion
La création de ce projet m'a permis de valider plusieurs hypothèses concernant le comportement des automobilistes et leurs causes associées.
Les objectifs que je m’étais fixés étaient notamment :
- De parvenir, à mon niveau et avec les moyens à ma disposition, à répondre par moi-même à ce besoin d'analyse.
- De prouver qu'il n'y a que l'imagination qui bride les champs d'application de Splunk tant qu'il est possible de lui donner de la donnée à exploiter.
J’ai rempli le premier objectif, et j’ose espérer avoir également réussi à remplir le second pour celles et ceux qui auront eu le courage de me lire jusqu’ici 😊 !
Happy Splunking !
Axes d’amélioration
Comme tout projet, celui-ci n'est pas parfait... Pas au niveau de Splunk (évidemment), qui effectue très bien son travail de collecte et d'exploitation des données, mais au niveau du système de détection encore au stade de bricolage et qui comporte des défauts non négligeables :
La précision temporelle
Le plus important d'entre eux et la synchronisation du temps entre les cartes Arduino. En effet, malgré avoir tenté de résoudre cela au maximum, n'importe quelle machine se désynchronise perpétuellement de quelques millisecondes, même en interrogeant un serveur NTP toutes les minutes. Cela n'est d'ordinaire pas impactant, mais dans le cas présent, le moindre décalage a d'énormes impacts sur mes mesures.
Exemple :
A 50 km/h, qui correspond à 13,9 m/s, le temps de parcours de ma distance de 3,4m est de $3.4/13.9$ = environ $245$ ms.
- Si mes cartes sont désynchronisées de 50 ms l'une de l'autre, je relèverai une durée pouvant être de $195$ms ou $295$ms en fonction du sens de désynchronisation.
- A $195$ms, mon résultat de calcul de vitesse serait donc de $17,4$ m/s = $63$ km/h, contre $11,5$ m/s = environ $41$ km/h à $295$ms, les deux versus une vitesse réelle de 50 km/h.
Autant dire que je ne peux en l'état actuel malheureusement pas garantir la fiabilité de mes mesures car elles comportent une marge d'erreur beaucoup trop importante.
- Elles reflètent tout au plus une tendance qui ne peut pas être interprétée comme des valeurs avérées d'un radar homologué.
Solutions :
-
Diminuer les impacts de décalage du temps en augmentant la distance parcourue.
- Mais cela ne résoudra pas le problème de désynchronisation des cartes, et en augmentant la distance, la vitesse moyenne sera de moins en moins proche de la vitesse instantanée
- Dans tous les cas cette solution est impossible dans mon cas car mon environnement ne permet pas de disposer de davantage de distance
-
Modifier le système en le rendant synchrone via deux capteurs reliés à une seule et même carte.
- Meilleure solution car peu importe la désynchronisation de la carte avec le serveur NTP, les deux capteurs utiliseraient une seule et unique base temporelle pour leurs détections.
- De plus, cela permettrait de déléguer tout le travail de calcul et de tri des faux-positifs à la carte Arduino au niveau de son propre code :
- Si je vois une détection d'un capteur, alors j'attends le deuxième.
- Si le deuxième ne voit rien, alors c'est un faux positif, j'ignore et je recommence.
- Si le deuxième détecte aussi un mouvement je calcule la durée exacte entre les deux et je la transmets à Splunk, voire je vérifie si c'est une valeur plausible avant de l'envoyer.
La donnée arriverait donc déjà épurée dans Splunk, et sa volumétrie serait divisée par deux étant donné qu'il ne recevrait plus que les durées déjà calculées et non les détections de mouvement de chaque capteur.
- La distance étant variable en fonction de la manière dont sont positionnés les capteurs, elle resterait modifiable au sein de la requête Splunk pour s'adapter à chaque contexte sans avoir à changer systématiquement le code de l'Arduino.
Malheureusement cette solution ne peut pas non plus être mise en œuvre en l'état dans mon contexte. J'ai en effet de nombreux murs et un couloir qui impliqueraient de tirer des mètres de fils électriques depuis mes capteurs pour pouvoir les relier à une même carte.
- De plus, je ne peux pas non plus envisager de connecter mes capteurs à une carte positionnée entre les deux depuis l'extérieur car le tout serait à la vue de tous sans aucune protection et à la merci des intempéries.
Si jamais je change d'environnement de mesure alors je pourrai envisager la mise en œuvre de cette version améliorée du système de détection.
La précision des capteurs
Utilisant des capteurs infrarouges que j'ai volontairement obstrués pour limiter la plage de détection, celle-ci est forcément imparfaite. J'ai notamment constaté que certains véhicules roulaient si rapidement que les capteurs n'avaient pas le temps de détecter leur passage.
De même, les capteurs possèdent une temporisation que j'ai limitée à 2 secondes entre chaque mesure, donc un mouvement survenant moins de 2 secondes après un autre ne sera pas détecté.
- Les résultats ne sont donc pas complètement exhaustifs en termes de détections
Solution : Utiliser des capteurs beaucoup plus précis et réactifs, tels que des capteurs lasers avec réflecteurs.
- Malheureusement impossible à mettre en œuvre dans mon environnement actuel.
La qualité du matériel
D'autres axes d'amélioration sont évidents au niveau de la finition du système de détection, qui reste fait de bric et de broc pour mes tests sans même avoir soudé les fils avec mes cartes Arduino.
Un produit propre, robuste et étanche serait tout de même plus présentable que des boîtes de conserves avec des fils reliés jusqu'à une carte elle-même branchée à une rallonge électrique...
Sources
- Comment construire un détecteur de vitesse de voiture avec Arduino : https://www.moussasoft.com/comment-construire-detecteur-de-vitesse-arduino/
- Comment utiliser le capteur de mouvement PIR HC-sr501 avec l’Arduino : https://idehack.com/comment-utiliser-le-capteur-de-mouvement-pir-hc-sr501-avec-larduino/
- How to use HC-SR501 PIR Motion Sensor with Arduino : https://www.makerguides.com/hc-sr501-arduino-tutorial/
- ARDUINO et pile 9V : NON ! : https://forum.arduino.cc/t/arduino-et-pile-9v-non/700342
- ezTime, an Arduino library for all of time : https://github.com/ropg/ezTime
- Arduino, Meet Splunk : https://medium.com/hackernoon/arduino-meet-splunk-81f32e252f9c
- Vitesse au volant : https://www.service-public.fr/particuliers/vosdroits/F19460
À propos : Le blog d'AlgoSecure est un espace sur lequel notre équipe toute entière peut s'exprimer. Notre personnel marketing et commercial vous donne des informations sur la vie et l'évolution de notre société spécialisée en sécurité sur Lyon. Nos consultants techniques, entre deux tests d'intrusion ou analyses de risque, vous donnent leur avis ainsi que des détails techniques sur l'exploitation d'une faille de sécurité informatique. Ils vous expliqueront également comment sécuriser votre système d'informations ou vos usages informatiques particuliers, avec autant de méthodologie et de pédagogie que possible. Vous souhaitez retrouver sur ce blog des informations spécifiques sur certains sujets techniques ? N'hésitez pas à nous en faire part via notre formulaire de contact, nous lirons vos idées avec attention. Laissez-vous guider par nos rédacteurs : Alexandre, Amine, Antonin, Arnaud, Benjamin, Damien, Enzo, Eugénie, Fabien, Françoise, Gilles, Jean-Charles, Jean-Philippe, Jonathan, Joël, Joëlie, Julien, Jéromine, Ludovic, Lyse, Nancy, Natacha, Nicolas, Pierre, PierreG, Sébastien, Tristan, Yann, et bonne visite !