Initial commit — Serveur Lucas SmartEye

API réception alertes chute (SmartEye/YOLO), analyse IA (Gemini 2.5 Flash),
gestion alertes avec escalade (watchdog), notifications Firebase,
dashboard web, documentation MkDocs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Debian
2026-03-14 21:26:06 +01:00
commit 24dbc7cd6a
64 changed files with 9677 additions and 0 deletions

140
api.php Executable file
View File

@@ -0,0 +1,140 @@
<?php
header("Content-Type: application/json");
header("Access-Control-Allow-Origin: *");
// --- 1. CHARGEMENT CONFIGURATION ---
$json_file = 'database.json';
if (!file_exists($json_file)) {
http_response_code(500);
die(json_encode(["status" => "error", "message" => "Base de données introuvable"]));
}
$db = json_decode(file_get_contents($json_file), true);
// Données reçues
$client_input = $_POST['client_id'] ?? '';
$token_input = $_POST['token'] ?? '';
// --- 2. IDENTIFICATION & SÉCURITÉ ---
$client_index = -1;
$current_client = null;
if (isset($db['clients'])) {
foreach ($db['clients'] as $index => $c) {
if (strcasecmp($c['name'], $client_input) == 0 && $c['token'] === $token_input) {
$client_index = $index;
$current_client = $c;
break;
}
}
}
if ($client_index === -1) {
http_response_code(403);
die(json_encode(["status" => "error", "message" => "Authentification échouée"]));
}
// --- 3. TRAITEMENT IMAGE ---
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
// Dossier spécifique
$upload_dir = 'clients/' . $current_client['name'] . '/';
if (!is_dir($upload_dir)) mkdir($upload_dir, 0775, true);
$filename = "alerte_" . date("Ymd_His") . ".jpg";
$target_file = $upload_dir . $filename;
if (move_uploaded_file($_FILES['image']['tmp_name'], $target_file)) {
// --- 4. APPEL IA & AUTOMATISATION ---
// On reconstruit l'URL publique
$public_url = "https://lucas.unigest.fr/" . $target_file;
// SÉCURITÉ AJOUTÉE : "cd " . __DIR__
// On force le serveur à se mettre dans le bon dossier pour trouver admin_key.json
// Champs caméra envoyés par SmartEye
$env_camera_id = escapeshellarg($_POST['camera_id'] ?? '');
$env_rtsp_url = escapeshellarg($_POST['rtsp_url'] ?? '');
$env_audio_ws = escapeshellarg($_POST['audio_ws'] ?? 'ws://57.128.74.87:8800');
$env_camera_map = escapeshellarg($_POST['camera_map'] ?? '{}');
$env_client_id = escapeshellarg($current_client['name']);
$safe_cmd = "cd " . __DIR__ . " && "
. "LUCAS_CLIENT_ID={$env_client_id} "
. "SMARTEYE_CAMERA_ID={$env_camera_id} "
. "SMARTEYE_RTSP_URL={$env_rtsp_url} "
. "SMARTEYE_AUDIO_WS={$env_audio_ws} "
. "SMARTEYE_CAMERA_MAP={$env_camera_map} "
. "python3 analyze.py " . escapeshellarg($target_file) . " 2>>/tmp/lucas_python_stderr.log";
// C'EST ICI QUE TOUT SE JOUE :
// 1. PHP lance Python.
// 2. Python analyse l'image.
// 3. Si Urgence -> Python envoie la notif Firebase au téléphone.
// 4. Python renvoie le résultat JSON à PHP.
$output = shell_exec($safe_cmd);
$resultat_ia = json_decode($output, true);
// --- GESTION DES RÉSULTATS ---
if (!$resultat_ia) {
// Si le JSON est cassé (crash Python), on force l'urgence par sécurité
$est_urgence = true;
$message_ia = "⚠️ Erreur technique IA. Analyse visuelle requise.";
// Optionnel : On logue l'erreur brute pour déboguer plus tard
file_put_contents("error_python.log", date("Y-m-d H:i:s") . " - " . $output . PHP_EOL, FILE_APPEND);
} else {
$est_urgence = $resultat_ia['urgence'] ?? false;
$message_ia = $resultat_ia['message'] ?? "Analyse terminée";
}
// --- 5. MISE A JOUR BASE DE DONNÉES ---
$db['clients'][$client_index]['alerte'] = $est_urgence;
$db['clients'][$client_index]['last_update'] = date("d/m/Y H:i:s");
$db['clients'][$client_index]['message'] = $message_ia;
file_put_contents($json_file, json_encode($db, JSON_PRETTY_PRINT));
// --- 5b. ARCHIVAGE JSON ---
$history_data = [
"urgence" => $est_urgence,
"message" => $message_ia,
"timestamp" => date("Y-m-d H:i:s")
];
file_put_contents($target_file . ".json", json_encode($history_data));
// --- 6. LOG SMS (Optionnel : Backup SMS si urgence) ---
if ($est_urgence) {
$contacts = $current_client['contacts'] ?? [];
$sms_body = "🚨 ALERTE CHUTE : " . $current_client['name']; // Message court pour SMS
foreach ($contacts as $contact) {
if (!empty($contact['phone'])) {
envoyer_sms_reel($contact['phone'], $sms_body);
}
}
}
echo json_encode([
"status" => "success",
"client" => $current_client['name'],
"ia_result" => $resultat_ia
]);
} else {
http_response_code(500);
echo json_encode(["status" => "error", "message" => "Erreur écriture fichier"]);
}
} else {
http_response_code(400);
echo json_encode(["status" => "error", "message" => "Pas d'image reçue"]);
}
function envoyer_sms_reel($numero, $message) {
// Nettoyage sommaire
$numero = str_replace([' ', '.', '-'], '', $numero);
// Appel du gestionnaire SMS (séparé)
$cmd = "python3 sms_manager.py " . escapeshellarg($numero) . " " . escapeshellarg($message) . " > /dev/null 2>&1 &";
shell_exec($cmd);
}
?>