esp/api/estado.php

157 lines
4.9 KiB
PHP

<?php
$expectedToken = (string) envv('ORQUESTA_TOKEN', 'f797bca7be69276299a9931373551ae6');
$providedToken = $_SERVER['HTTP_X_ESP_DISPOSITIVOS_TOKEN'] ?? '';
if (!hash_equals($expectedToken, (string) $providedToken)) {
json_error('Token inv\xC3\xA1lido', 401);
}
$dispositivosFile = __DIR__ . '/../data/dispositivos.json';
$puertosFile = __DIR__ . '/../data/puertos.json';
if (!file_exists($dispositivosFile) || !is_readable($dispositivosFile)) {
json_error('Archivo de dispositivos no disponible', 500);
}
$rawDispositivos = @file_get_contents($dispositivosFile);
if ($rawDispositivos === false) {
json_error('No se pudo leer dispositivos.json', 500);
}
$dispositivosData = json_decode($rawDispositivos, true);
if (json_last_error() !== JSON_ERROR_NONE || !is_array($dispositivosData)) {
json_error('dispositivos.json inv\xC3\xA1lido', 500);
}
$puertosData = [];
if (file_exists($puertosFile) && is_readable($puertosFile)) {
$rawPuertos = @file_get_contents($puertosFile);
if ($rawPuertos !== false) {
$decodedPuertos = json_decode($rawPuertos, true);
if (is_array($decodedPuertos)) {
$puertosData = $decodedPuertos;
}
}
}
$estadosRealtime = [];
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$mensajes = $redis->hGetAll('mqtt:mensajes');
foreach ($mensajes as $topic => $datosJson) {
$datos = json_decode($datosJson, true);
if (!is_array($datos) || !array_key_exists('payload', $datos)) {
continue;
}
$parts = explode('/', (string) $topic);
if (count($parts) < 3 || $parts[0] !== 'dispositivo') {
continue;
}
$chipid = $parts[1];
$tipo = $parts[2];
$subtipo = $parts[3] ?? null;
$payload = $datos['payload'];
if (!isset($estadosRealtime[$chipid])) {
$estadosRealtime[$chipid] = [
'estado' => 'offline',
'ip' => null,
'pines' => [],
];
}
switch ($tipo) {
case 'state':
$estado = strtolower(trim((string) $payload));
$estadosRealtime[$chipid]['estado'] = ($estado === 'online') ? 'online' : 'offline';
break;
case 'ip':
$estadosRealtime[$chipid]['ip'] = trim((string) $payload);
break;
case 'valores':
if ($subtipo !== null) {
$pinEstado = null;
$decodedPayload = json_decode((string) $payload, true);
if (is_array($decodedPayload) && isset($decodedPayload['valor'])) {
$pinEstado = $decodedPayload['valor'];
} else {
$pinEstado = $payload;
}
$estadosRealtime[$chipid]['pines'][$subtipo] = strtoupper(trim((string) $pinEstado));
}
break;
case 'comando':
$decodedPayload = json_decode((string) $payload, true);
if (is_array($decodedPayload) && isset($decodedPayload['alias'], $decodedPayload['valor'])) {
$alias = (string) $decodedPayload['alias'];
$valor = strtoupper(trim((string) $decodedPayload['valor']));
$estadosRealtime[$chipid]['pines'][$alias] = $valor;
}
break;
}
}
} catch (Throwable $e) {
// Si Redis no est\xC3\xA1 disponible, devolvemos igualmente la estructura base.
}
$response = ['dispositivos' => []];
foreach ($dispositivosData as $dispositivo) {
if (!is_array($dispositivo)) {
continue;
}
$chipid = $dispositivo['chipid'] ?? null;
if (!$chipid) {
continue;
}
$estadoRealtime = $estadosRealtime[$chipid] ?? [
'estado' => 'offline',
'ip' => null,
'pines' => [],
];
if (($estadoRealtime['estado'] ?? 'offline') !== 'online') {
continue;
}
$puertosDispositivo = $puertosData[$chipid] ?? [];
$pines = [];
foreach ($puertosDispositivo as $alias => $configPin) {
if ($alias === 'update' || !is_array($configPin)) {
continue;
}
$pines[$alias] = [
'modo' => $configPin['modo'] ?? null,
'estado' => $estadoRealtime['pines'][$alias] ?? null,
];
}
$response['dispositivos'][] = [
'chipid' => (string) $chipid,
'tag' => $dispositivo['tag'] ?? null,
'nombre' => $dispositivo['nombre'] ?? null,
'modelo' => $dispositivo['nombre'] ?? null,
'ciudad' => $dispositivo['ciudad'] ?? null,
'sector' => $dispositivo['sector'] ?? null,
'estado' => $estadoRealtime['estado'],
'ip' => $estadoRealtime['ip'],
'firmware' => $dispositivo['firmware'] ?? null,
'pines' => $pines,
];
}
echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
exit;