Suite à l'article de Sebsauvage sur PhoneTrack + NextCloud, j'étais bien embêté. Je trouvais l'idée sympa et utile, mais vu que je viens d'arrêter Nextcloud pour diverses raisons, je me suis sentis "frustré" (façon de parler).
Mais comme il le dit si bien :
Il est à noter que vous pouvez utiliser l'application PhoneTrack sans NextCloud : Vous pouvez lui demander d'envoyer les coordoonées GPS par HTTP (GET ou POST) à l'URL de votre choix (vous pouvez donc très bien développer votre propre application pour réceptionner les positions GPS).
C'est donc ce que je me suis attelé à faire, même s'il ne s'agit pas d'une application en fait ^^
Ci-dessous, j'explique comment j'ai fait, et ça commence déjà par avoir son nom de domaine à soit bien entendu.
Attention, ce n'est sûrement pas le plus propre possible, mais ça fonctionne. Si vous avez des suggestions...
Commencer par installer sur le smartphone l'appli phonetrack.
Niveau réglages, cocher les paramètres que vous voulez, puis créer un "log job personnalisé" en cliquant sur le "+" en bas de l'écran. En url mettez ceci :
http://votre_ndd/time=;%TIMESTAMP;=;bidulelat=;%LAT;=;%LON;
- autant de points-virgules pour être sûr de bien avoir les séparations lors de la récupération des infos ;
- le "bidulelat" pour avoir une expression à peu près unique que l'on recherchera dans le fichier de log ;
Dans votre index.php (ou toute autre page), saisir les lignes suivantes :
<!--<tbody>-->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8">
<link rel="SHORTCUT ICON" href="img.png">
<title>Géolocalisation_smartphone</title>
</head>
<div style="text-align: left;" id="header"><a class="nom_du_site"><b>Géolocalisation_smartphone</b></a>
<body>
<?php
echo "<br>";
?>
<?php
$emplacement = '/emplacement/ou/seront/stockes/vos/coordonnees/';
//recherche uniquement de fichiers "CSV"
$files = scandir($emplacement);
$csvFiles = array_filter($files, function ($file) {
return pathinfo($file, PATHINFO_EXTENSION) === 'csv';
});
if (empty($csvFiles)) {
echo 'Aucun fichier CSV trouvé dans cet emplacement.';
} else {
$selectedFile = isset($_GET['file']) ? $_GET['file'] : '';
$selectedLine = isset($_GET['line']) ? $_GET['line'] : 0;
if (empty($selectedFile) || !in_array($selectedFile, $csvFiles)) {
echo '<form method="get" action="">';
echo 'Choisir un fichier CSV : ';
echo '<select name="file">';
foreach ($csvFiles as $file) {
echo '<option value="' . $file . '">' . $file . '</option>';
}
echo '</select>';
echo '<input type="submit" value="Sélectionner">';
echo '</form>';
} else {
//echo 'Fichier sélectionné : ' . $selectedFile;
// Autres traitements à effectuer avec le fichier sélectionné
// Lecture du fichier CSV
$fileContent = file_get_contents($emplacement . $selectedFile);
$lines = explode("\n", $fileContent);
if (!is_numeric($selectedLine) || $selectedLine < 0 || $selectedLine >= count($lines)) {
$selectedLine = 0;
}
// Affichage du formulaire de sélection de ligne
echo '<form method="get" action="">';
echo 'Sélectionner un autre fichier CSV : ';
echo '<select name="file">';
foreach ($csvFiles as $file) {
$selected = ($file === $selectedFile) ? 'selected' : '';
echo '<option value="' . $file . '" ' . $selected . '>' . $file . '</option>';
}
echo '</select>';
echo '<br>';
echo 'Sélectionner une ligne à afficher : ';
echo '<select name="line" onchange="this.form.submit()">';
foreach ($lines as $index => $line) {
$selected = ($index == $selectedLine) ? 'selected' : '';
$columns = explode(';', $line);
$time = $columns[0];
echo '<option value="' . $index . '" ' . $selected . '>' . $time . '</option>';
}
echo '</select>';
echo '</form>';
// Affichage du tableau avec la ligne sélectionnée
echo '<table>';
$line = $lines[$selectedLine];
$columns = explode(';', $line);
$time = $columns[0];
$latitude = $columns[1];
$longitude = $columns[2];
//echo '<tr>';
//echo '<td>' . $time . '</td>';
//echo '<td>' . $latitude . '</td>';
//echo '<td>' . $longitude . '</td>';
//echo '</tr>';
echo "<br>";
echo $time . '<br>';
echo $latitude . '</br>';
echo $longitude . '</br>';
//echo '</tr>';
echo '</table>';
// Utilisation des valeurs dans le code JavaScript
echo '<script>';
echo 'var lat = ' . $latitude . ';';
echo 'var lon = ' . $longitude . ';';
echo '</script>';
}
}
?>
<br>
<head>
<meta charset="utf-8">
<!-- Nous chargeons les fichiers CDN de Leaflet. Le CSS AVANT le JS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<style type="text/css">
#map{ /* la carte DOIT avoir une hauteur sinon elle n'apparaît pas */
height:400px;
}
</style>
<title>Carte</title>
</head>
<body>
<div id="map">
<!-- Ici s'affichera la carte -->
</div>
<!-- Fichiers Javascript -->
<script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script>
<script type="text/javascript">
// On initialise la latitude et la longitude de Paris (centre de la carte)
console.log('Latitude:', lat);
console.log('Longitude:', lon);
var macarte = null;
// Fonction d'initialisation de la carte
function initMap() {
// Créer l'objet "macarte" et l'insèrer dans l'élément HTML qui a l'ID "map"
macarte = L.map('map').setView([lat, lon], 11);
// Leaflet ne récupère pas les cartes (tuiles) sur un serveur par défaut. Nous devons lui préciser où nous souhaitons les récupérer. Ici, openstreetmap.fr
L.tileLayer('https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', {
// Il est toujours bien de laisser le lien vers la source des données
attribution: 'données © <a href="//osm.org/copyright">OpenStreetMap</a>/ODbL - rendu <a href="//openstreetmap.fr">OSM France</a>',
minZoom: 15,
maxZoom: 20
}).addTo(macarte);
// Nous ajoutons un marqueur
var marker = L.marker([lat, lon]).addTo(macarte);
}
window.onload = function(){
// Fonction d'initialisation qui s'exécute lorsque le DOM est chargé
initMap();
};
</script>
</body>
</body>
</div>
</html>
Avec juste ce code, la page n'affiche rien hormis un bouton pour la sélection d'un fichier, et pour cause, le serveur n'a pas encore récupéré les données 🤪
Il faudra créer 2 scripts sur le serveur pour ça.
Le 1er :
nano /emplacement/script_surveillance_log.sh
#!/bin/bash
# Chemin du fichier de journal Apache
access_log="/var/log/apache2/access.log"
# Chemin du fichier de destination pour les lignes extraites
coordonnees_brutes="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_brutes.txt"
# chemin du fichier après suppression des doublons
input_file_1="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_uniq_1.txt"
# Chemin du fichier de sortie après suppression des %
output_file_1="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_uniq_2.txt"
# chemin du fichier avec les dates propres
output_file_2="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_dates_propres.txt"
# chemin du fichier contenant toutes les dates présentes dans le fichier de log
fichier_sortie_1="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_all_dates.csv"
# chemin du fichier ne contenant que les coordonnées du jour mais parfois avec des doublons
fichier_sortie_2="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_du_jour.txt"
# chemin du fichier ne contenant que les coordonnées du jour sans doublons
fichier_sortie_3="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_du_jour_uniq.txt"
# chemin fichier de sortie du jour
fichier_du_jour="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_aujourd-hui.csv"
# Fonction pour extraire les lignes du fichier de log, supprimer les doublons puis les %
recup_lignes() {
# Recherche des lignes contenant le motif spécifié (par exemple, "bidulelat=;")
sudo grep "bidulelat=;" "$access_log" | cut -d";" -f 2,5,7 >> "$coordonnees_brutes"
# suppression des doublons :
sudo cat "$coordonnees_brutes" | sort | uniq > "$input_file_1"
# suppression des lignes contenant %
# Utilise sed pour supprimer les lignes contenant le caractère '%'
sed '/%/d' "$input_file_1" > "$output_file_1"
}
# Surveille en continu le fichier de journal
tail -f "$access_log" | while read -r line; do
# Affichez la ligne en cours pour vérification (optionnel)
echo "$line"
# Appelez la fonction pour extraire les lignes appropriées
recup_lignes
# Lecture du fichier TXT
while IFS=';' read -r timestamp col2 col3
do
# Conversion du timestamp en format lisible
date_propre=$(date -d @$timestamp)
# Ajout des données modifiées à un nouveau fichier CSV
echo "$date_propre;$col2;$col3" >> "$output_file_2"
done < "$output_file_1"
# RE-suppression des doublons (au cas ou...)
# et envois du résultat vers un fichier CSV avec toutes les dates du fichier de log
sudo cat "$output_file_2" | sort | uniq > "$fichier_sortie_1"
# Remplacer la date du jour qui ressemeble à 'jeu. 20 juil. 2023'
# par la date de la veille au format spécifique
date_veille=$(date -d "yesterday" +"%a %e %b %Y")
# Utiliser grep avec une expression régulière pour enlever les lignes
# qui correspondent exactement à la date de la veille au début de la ligne
grep -vE "^$date_veille" "$output_file_2" > "$fichier_sortie_2"
# suppression des doublons (oui encore au cas ou) :
sudo cat "$fichier_sortie_2" | sort | uniq > "$fichier_sortie_3"
# passage du fichier TXT en fichier CSV
sudo cp "$fichier_sortie_3" "$fichier_du_jour"
done
Et on rends ce script exécutable
chmod +x /emplacement/script_surveillance_log.sh
Le 2nd qui permettra de créer un fichier par date afin de rendre plus facile la recherche pour la géolocalisation
chmod +x /emplacement/script_archivage.sh
#!/bin/bash
annee=$(date +%Y)
mois=$(date +%m)
jour=$(date +%d)
jour=$[$jour-1]
date=$annee-$mois-$jour
# chemin fichier d'entrée
fichier_du_jour="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_aujourd-hui.csv"
fichier_tmp_1="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_tmp_1.csv"
fichier_tmp_2="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_tmp_2.csv"
fichier_tmp_3="/emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_tmp_3.csv"
sudo cp "$fichier_du_jour" "fichier_tmp_1"
# création de la variable qui définie la date de la veille
date_veille=$(date -d "yesterday" +"%a %e %b %Y")
# ici on ne garde que la date de la veille
grep -E "^$date_veille" "$fichier_tmp_1" > "$fichier_tmp_2"
# suppression des doublons :
sudo cat "$tmp_file_2" | sort | uniq > "$ichier_tmp_3"
sudo mv "$ichier_tmp_3" /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees-$date.csv
# suppression des fichiers afin de repartir à zéro
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_brutes.txt
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_uniq_1.txt
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_uniq_2.txt
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_dates_propres.txt
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_all_dates.csv
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_du_jour.txt
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_du_jour_uniq.txt
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_aujourd-hui.csv
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_tmp_1.csv
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_tmp_2.csv
sudo rm -f /emplacement/ou/seront/stockes/vos/coordonnees/coordonnees_tmp_3.csv
Et on rends (biensûr aussi ^^) ce script exécutable
chmod +x /emplacement/script_archivage.sh
On peut mettre tout ça dans
crontab -e
# au démarrage, surveillance du fichier de log apache2 pour extraire les coordonnées GPS du smartphone
@reboot sudo /emplacement/script_surveillance_log.sh
# tous les jours à 0h01, sauvegarde des coordonnée GPS du smartphone de la veille
01 0 * * * sudo /emplacement/script_archivage.sh
On peut ainsi avoir l'emplacement de téléphone à l'heure que l'on souhaite.
Biensur, ceci ne doit pas être utilisé à des fins d'espionnage ou de tracking d'un appareil sans le consentement du propriétaire du dît appareil.
Perso, c'est sur le meins en cas de pertes, ou s'il m'arrive quelque chose lors d'une rando (j'ai fournit le lien aux personnes suseptible d'en avoir besoin)
Je n'ai pas "créé" tout ces codes, je me suis largement inspiré de ce que j'ai pu "sous-tiret" ça et là...
À bientôt.
o/