208 lines
7.9 KiB
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);
|
|
}
|