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); }