esp/api/api_dispositivos.php

208 lines
7.9 KiB
PHP

<?php
// Consolidated dispositivos API: handles get_dispositivos, add_dispositivo, delete_dispositivo
// Expects $route from api/index.php and bootstrap loaded (json_success/json_error available)
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('log_errors', 1);
$file = __DIR__ . '/../data/dispositivos.json';
switch ($route) {
case 'get_dispositivos': {
if (!file_exists($file)) json_error('Archivo no encontrado', 500);
if (!is_readable($file)) json_error('Archivo no legible', 500);
$raw = @file_get_contents($file);
if ($raw === false) json_error('Error al leer archivo', 500);
$dispositivos = json_decode($raw, true);
if (json_last_error() !== JSON_ERROR_NONE) json_error('JSON inválido', 500);
if (!is_array($dispositivos)) $dispositivos = [];
$resultado = [];
$realtime = [];
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379, 1.0);
$mensajes = $redis->hGetAll('mqtt:mensajes');
foreach ($mensajes as $topic => $datosJson) {
$datos = json_decode((string) $datosJson, true);
if (!is_array($datos) || !array_key_exists('payload', $datos)) continue;
$parts = explode('/', trim((string) $topic, '/'));
$deviceIndex = array_search('dispositivo', $parts, true);
if ($deviceIndex === false || count($parts) < $deviceIndex + 3) continue;
$chipid = strtoupper((string) $parts[$deviceIndex + 1]);
$tipo = $parts[$deviceIndex + 2] ?? null;
$subtipo = $parts[$deviceIndex + 3] ?? null;
$payload = $datos['payload'];
if (!isset($realtime[$chipid])) {
$realtime[$chipid] = ['online' => false, 'ip' => null, 'pines' => []];
}
if ($tipo === 'state') {
$estado = strtolower(trim((string) $payload));
$realtime[$chipid]['online'] = in_array($estado, ['online', 'connected', 'available', '1', 'true', 'on'], true);
} elseif ($tipo === 'ip') {
$realtime[$chipid]['ip'] = trim((string) $payload);
} elseif (($tipo === 'valores' || $tipo === 'pin') && $subtipo !== null) {
$decodedPayload = json_decode((string) $payload, true);
$valor = is_array($decodedPayload) && array_key_exists('valor', $decodedPayload)
? $decodedPayload['valor']
: $payload;
$realtime[$chipid]['pines'][$subtipo] = strtoupper(trim((string) $valor));
}
}
} catch (Throwable $e) {
$realtime = [];
}
foreach ($dispositivos as $disp) {
// Eliminar IP persistida: ahora se sirve en vivo por MQTT WebSocket
if (isset($disp['ip'])) {
unset($disp['ip']);
}
$chipid = $disp['chipid'] ?? null;
if ($chipid) {
$chipKey = strtoupper((string) $chipid);
if (isset($realtime[$chipKey])) {
$disp['online'] = $realtime[$chipKey]['online'];
$disp['ip'] = $realtime[$chipKey]['ip'];
$disp['pines'] = $realtime[$chipKey]['pines'];
} else {
$disp['online'] = false;
}
$resultado[$chipid] = $disp;
}
}
header('Content-Type: application/json');
echo json_encode($resultado);
break;
}
case 'edit_dispositivo': {
try {
$input = json_decode(file_get_contents('php://input'), true);
if (json_last_error() !== JSON_ERROR_NONE || !isset($input['chipid'])) {
throw new Exception('JSON inválido o chipid faltante');
}
$chipid = $input['chipid'];
if (!file_exists($file)) throw new Exception('Archivo no encontrado');
$contenido = file_get_contents($file);
$dispositivos = json_decode($contenido, true) ?: [];
$index = array_search($chipid, array_column($dispositivos, 'chipid'));
if ($index === false) throw new Exception("Dispositivo $chipid no encontrado");
foreach ($input as $k => $v) {
if ($k !== 'chipid') $dispositivos[$index][$k] = $v;
}
if (!file_put_contents($file, json_encode($dispositivos, JSON_PRETTY_PRINT))) {
throw new Exception('Error al guardar el archivo');
}
json_success(true);
} catch (Exception $e) {
json_error('Error: ' . $e->getMessage(), 500);
}
break;
}
case 'add_dispositivo': {
$data = json_decode(file_get_contents('php://input'), true);
if (!isset($data['chipid'], $data['tag'], $data['nombre'], $data['ciudad'], $data['sector'])) {
json_error('Faltan datos', 400);
}
$dispositivos = [];
if (file_exists($file)) {
$dispositivos = json_decode(file_get_contents($file), true) ?: [];
}
foreach ($dispositivos as $d) {
if ($d['chipid'] === $data['chipid']) {
json_error('El chipid ya existe', 400);
}
}
$nuevo = [
'id_disp' => count($dispositivos) + 1,
'chipid' => $data['chipid'],
'tag' => $data['tag'],
'nombre' => $data['nombre'],
'ciudad' => $data['ciudad'],
'sector' => $data['sector']
];
$dispositivos[] = $nuevo;
if (file_put_contents($file, json_encode($dispositivos, JSON_PRETTY_PRINT))) {
json_success(true);
} else {
json_error('Error al guardar el dispositivo', 500);
}
break;
}
case 'delete_dispositivo': {
$input = json_decode(file_get_contents('php://input'), true);
$chipid = $input['chipid'] ?? '';
if (!$chipid) json_error('ChipID no proporcionado', 400);
if (!file_exists($file)) json_error('Archivo no encontrado', 500);
$dispositivos = json_decode(file_get_contents($file), true);
if (!is_array($dispositivos)) json_error('JSON inválido', 500);
$nuevaLista = array_filter($dispositivos, fn($d) => $d['chipid'] !== $chipid);
if (count($nuevaLista) === count($dispositivos)) json_error('Dispositivo no encontrado', 404);
$nuevaLista = array_values($nuevaLista);
foreach ($nuevaLista as $i => &$d) { $d['id_disp'] = $i + 1; }
$backup_dir = __DIR__ . '/../backups';
if (!is_dir($backup_dir)) mkdir($backup_dir, 0755, true);
$fecha = date('Ymd_His');
$backupFile = $backup_dir . "/dispositivos_backup_$fecha.json";
@copy($file, $backupFile);
if (file_put_contents($file, json_encode($nuevaLista, JSON_PRETTY_PRINT))) {
json_success(['backup' => $backupFile]);
} else {
json_error('No se pudo guardar el archivo', 500);
}
break;
}
case 'update_dispositivo': {
$datosRecibidos = json_decode(file_get_contents('php://input'), true);
if (!is_array($datosRecibidos)) json_error('Entrada inválida', 400);
$dispositivosData = [];
if (file_exists($file)) {
$dispositivosData = json_decode(file_get_contents($file), true);
if (!is_array($dispositivosData)) $dispositivosData = [];
}
foreach ($datosRecibidos as $chipid => $data) {
$dispositivosData[$chipid] = $data;
}
if (file_put_contents($file, json_encode($dispositivosData, JSON_PRETTY_PRINT))) {
json_success(['success' => true]);
} else {
json_error('No se pudo guardar dispositivos.json', 500);
}
break;
}
default:
json_error('Ruta no soportada en api_dispositivos', 404);
}