138 lines
6.6 KiB
PHP
138 lines
6.6 KiB
PHP
<?php
|
|
session_start();
|
|
if (empty($_SESSION['loggedin'])) { header('Location: index.php'); exit; }
|
|
|
|
define('PMX_API', 'http://192.168.10.106:8765/?key=esp_api_xupas_2025');
|
|
|
|
function pmx_get(): array {
|
|
$ch = curl_init(PMX_API.'&action=list');
|
|
curl_setopt_array($ch,[CURLOPT_RETURNTRANSFER=>true,CURLOPT_TIMEOUT=>8]);
|
|
$r = json_decode(curl_exec($ch),true); curl_close($ch);
|
|
return $r['devices'] ?? [];
|
|
}
|
|
|
|
function pmx_post(array $data): array {
|
|
$ch = curl_init(PMX_API);
|
|
curl_setopt_array($ch,[CURLOPT_RETURNTRANSFER=>true,CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>http_build_query($data),CURLOPT_TIMEOUT=>8]);
|
|
$r = json_decode(curl_exec($ch),true); curl_close($ch);
|
|
return $r ?? [];
|
|
}
|
|
|
|
$notice = ''; $error = '';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$uid = preg_replace('/[^0-9A-Fa-f]/', '', $_POST['uid'] ?? '');
|
|
if (!$uid) { $error = 'UID inválido.'; }
|
|
else {
|
|
$res = pmx_post($_POST);
|
|
if (!empty($res['ok'])) $notice = "[{$uid}] {$_POST['action']} OK";
|
|
else $error = $res['error'] ?? 'Erro';
|
|
}
|
|
$qs = $notice ? '?ok='.urlencode($notice) : ($error ? '?err='.urlencode($error) : '');
|
|
header("Location: esp_devices.php$qs"); exit;
|
|
}
|
|
|
|
if (isset($_GET['ok'])) $notice = htmlspecialchars($_GET['ok']);
|
|
if (isset($_GET['err'])) $error = htmlspecialchars($_GET['err']);
|
|
|
|
$devices = pmx_get();
|
|
function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES); }
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="pt">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>ESP Devices — Proxmox</title>
|
|
<style>
|
|
* { box-sizing:border-box; margin:0; padding:0; }
|
|
body { background:#0d1117; color:#e6edf3; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif; font-size:14px; }
|
|
.header { background:#161b22; border-bottom:1px solid #21262d; padding:14px 24px; display:flex; align-items:center; gap:16px; }
|
|
.header a { color:#58a6ff; text-decoration:none; font-size:13px; }
|
|
.header h1 { font-size:16px; font-weight:600; flex:1; }
|
|
.wrap { max-width:1200px; margin:0 auto; padding:24px; }
|
|
.flash-ok { background:#0d4f2a; color:#3fb950; padding:10px 16px; border-radius:6px; margin-bottom:16px; }
|
|
.flash-err { background:#4f1010; color:#da3633; padding:10px 16px; border-radius:6px; margin-bottom:16px; }
|
|
table { width:100%; border-collapse:collapse; font-size:13px; }
|
|
th { background:#1e2733; padding:10px 12px; text-align:left; color:#aaa; font-weight:normal; }
|
|
td { padding:9px 12px; border-bottom:1px solid #1e2733; vertical-align:middle; }
|
|
tr:hover td { background:#111822; }
|
|
.badge { display:inline-block; padding:2px 8px; border-radius:4px; font-size:11px; }
|
|
.badge-ok { background:#0d4f2a; color:#3fb950; }
|
|
.badge-block { background:#4f1010; color:#da3633; }
|
|
.btn { display:inline-block; padding:4px 9px; border-radius:4px; border:none; cursor:pointer; font-size:12px; }
|
|
.btn:hover { filter:brightness(1.3); }
|
|
.btn-green { background:#1a4a1a; color:#3fb950; }
|
|
.btn-red { background:#4f1010; color:#da3633; }
|
|
.btn-grey { background:#2a2a2a; color:#ccc; }
|
|
.btn-blue { background:#0d2a4f; color:#58a6ff; }
|
|
.btn-orange { background:#4f3210; color:#d29922; }
|
|
.btn-purple { background:#2d1a4f; color:#bc8cff; }
|
|
.uid { font-family:monospace; }
|
|
.ago { color:#666; font-size:11px; }
|
|
form { display:inline; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="header">
|
|
<a href="index.php">← Painel</a>
|
|
<h1>ESP Devices <span style="color:#bc8cff;font-size:13px;font-weight:400">— Proxmox broker</span></h1>
|
|
<span style="color:#666;font-size:12px"><?= count($devices) ?> dispositivos</span>
|
|
</div>
|
|
<div class="wrap">
|
|
|
|
<?php if ($notice): ?><div class="flash-ok"><?= $notice ?></div><?php endif; ?>
|
|
<?php if ($error): ?><div class="flash-err"><?= $error ?></div><?php endif; ?>
|
|
|
|
<?php if (!$devices): ?>
|
|
<p style="color:#666;margin-top:20px">Sem dispositivos ou erro a ligar ao broker Proxmox.</p>
|
|
<?php else: ?>
|
|
<table>
|
|
<thead><tr><th>UID</th><th>Broker atual</th><th>Estado</th><th>Último contacto</th><th>Heap</th><th>RSSI</th><th>Ações</th></tr></thead>
|
|
<tbody>
|
|
<?php foreach ($devices as $d):
|
|
$uid = $d['uid'];
|
|
$blocked= (bool)$d['blocked'];
|
|
$broker = $d['current_broker'] ?? '—';
|
|
$last = $d['last_seen'] ?? '-';
|
|
$ago = '-';
|
|
if ($last && $last !== '-') {
|
|
$diff = time() - strtotime($last);
|
|
if ($diff < 60) $ago = $diff.'s atrás';
|
|
else if ($diff < 3600) $ago = round($diff/60).'min atrás';
|
|
else $ago = round($diff/3600).'h atrás';
|
|
}
|
|
?>
|
|
<tr>
|
|
<td><span class="uid"><?= h($uid) ?></span></td>
|
|
<td style="font-size:12px;color:var(--muted,#8b949e)"><?= h($broker) ?></td>
|
|
<td><?php if ($blocked): ?>
|
|
<span class="badge badge-block">bloqueado</span>
|
|
<?php else: ?>
|
|
<span class="badge badge-ok">aprovado</span>
|
|
<?php endif; ?></td>
|
|
<td><?= h($last) ?><br><span class="ago"><?= $ago ?></span></td>
|
|
<td style="color:#666;font-size:12px"><?= $d['heap'] ? number_format((int)$d['heap']) : '—' ?></td>
|
|
<td style="color:#666;font-size:12px"><?= $d['rssi'] ? $d['rssi'].' dBm' : '—' ?></td>
|
|
<td style="white-space:nowrap">
|
|
<?php if ($blocked): ?>
|
|
<form method="post"><input type="hidden" name="uid" value="<?= h($uid) ?>"><input type="hidden" name="action" value="approve"><button class="btn btn-green">Aprovar</button></form>
|
|
<?php else: ?>
|
|
<form method="post"><input type="hidden" name="uid" value="<?= h($uid) ?>"><input type="hidden" name="action" value="block"><button class="btn btn-red">Bloquear</button></form>
|
|
<?php endif; ?>
|
|
<?php foreach ([['REBOOT','btn-orange','Reboot'],['STATUS','btn-grey','Status'],['SWITCH_PRIMARY','btn-blue','→Main'],['REJOIN','btn-grey','Rejoin']] as [$c,$cl,$lb]): ?>
|
|
<form method="post"><input type="hidden" name="uid" value="<?= h($uid) ?>"><input type="hidden" name="action" value="cmd"><input type="hidden" name="cmd" value="<?= $c ?>"><button class="btn <?= $cl ?>"><?= $lb ?></button></form>
|
|
<?php endforeach; ?>
|
|
<form method="post"><input type="hidden" name="uid" value="<?= h($uid) ?>"><input type="hidden" name="action" value="switch_pair"><input type="hidden" name="pair" value="0"><button class="btn btn-blue">→xpto</button></form>
|
|
<form method="post"><input type="hidden" name="uid" value="<?= h($uid) ?>"><input type="hidden" name="action" value="switch_pair"><input type="hidden" name="pair" value="1"><button class="btn btn-purple">→xupas</button></form>
|
|
<form method="post" onsubmit="return confirm('Remover?')"><input type="hidden" name="uid" value="<?= h($uid) ?>"><input type="hidden" name="action" value="delete"><button class="btn btn-red">✕</button></form>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|
|
</div>
|
|
</body>
|
|
</html>
|