<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sentinel · Cloud & Devices</title>
<link rel="stylesheet" href="/static/css/operations-v59.css?v=701">
<link rel="stylesheet" href="/static/css/cloud-v7.css?v=701">
</head>
<body data-page="cloud">
<div class="ops-shell">
  <aside class="ops-sidebar">
    <a class="ops-brand" href="/"><div class="brand-mark">S</div><div><strong>Sentinel</strong><span>Equipment Intelligence</span></div></a>
    <nav class="ops-nav">
      <a href="/"><span class="nav-glyph">⌁</span>Dashboard</a>
      <a href="/equipment-overview"><span class="nav-glyph">▣</span>Equipment</a>
      <a href="/cloud" class="active"><span class="nav-glyph">☁</span>Cloud & Devices</a>
      <a href="/alarms"><span class="nav-glyph">!</span>Alarms</a>
      <a href="/alarm-blocking"><span class="nav-glyph">◫</span>Alarm blocking</a>
      <a href="/trends"><span class="nav-glyph">↗</span>Trends</a>
      <a href="/reports"><span class="nav-glyph">▤</span>Reports</a>
      <div class="nav-divider"></div><span class="nav-section">Administration</span>
      <a href="/organization"><span class="nav-glyph">⌘</span>Organization units</a>
      <a href="/users"><span class="nav-glyph">♙</span>Users</a>
      <a href="/audit"><span class="nav-glyph">≡</span>Audit log</a>
      <a href="/administration"><span class="nav-glyph">⚙</span>Advanced configuration</a>
    </nav>
    <div class="sidebar-foot"><span class="online-dot"></span><div><strong>Sentinel online</strong><span>V7 Cloud + Edge</span></div></div>
  </aside>
  <section class="ops-workspace">
    <header class="ops-header"><div><h1>Cloud & Device Connectivity</h1><span>Central heartbeat, Device availability and Edge synchronization</span></div><div class="header-actions"><span class="header-site">LCSB</span><span class="header-user">Sentinel Admin</span><div class="avatar">S</div></div></header>
    <main class="ops-main">
      <section class="metric-strip cloud-metrics">
        <article><span>Registered Devices</span><strong>{{ stats.devices }}</strong><small>known Edge nodes</small></article>
        <article class="good"><span>Online</span><strong>{{ stats.online }}</strong><small>heartbeat received</small></article>
        <article class="alarm"><span>Offline</span><strong>{{ stats.offline }}</strong><small>after {{ heartbeat_grace_seconds }} s grace</small></article>
        <article class="predictive"><span>Cloud measurements</span><strong>{{ stats.synced_measurements }}</strong><small>synchronized records</small></article>
      </section>
      <article class="ops-card">
        <div class="card-title"><div><h2>Device fleet</h2><span>Edge nodes and connectivity status</span></div><input id="device-filter" class="cloud-filter" placeholder="Search device, equipment, site…"></div>
        {% if devices %}<div class="cloud-table-wrap"><table class="cloud-table"><thead><tr><th>Status</th><th>Equipment</th><th>Device</th><th>Site</th><th>Edge version</th><th>Last heartbeat</th><th>Interval</th></tr></thead><tbody>{% for d in devices %}<tr class="device-row" data-search="{{ d.equipment_id }} {{ d.device_id }} {{ d.site_code or '' }} {{ d.display_name or '' }}"><td><span class="status-dot {{ 'online' if d.online else 'offline' }}"></span>{{ 'ONLINE' if d.online else 'OFFLINE' }}</td><td><a href="/equipment/{{ d.equipment_id }}">{{ d.equipment_id }}</a></td><td>{{ d.device_id }}</td><td>{{ d.site_code or '—' }}</td><td>{{ d.edge_version or '—' }}</td><td>{{ d.last_heartbeat_at or 'Never' }}</td><td>{{ d.heartbeat_interval_seconds }} s</td></tr>{% endfor %}</tbody></table></div>{% else %}<div class="empty-state">No Cloud Device registered yet. The Edge agent will appear here after its first registration.</div>{% endif %}
      </article>
      <article class="ops-card"><div class="card-title"><div><h2>Connectivity event history</h2><span>DEVICE_REGISTERED · DEVICE_OFFLINE · DEVICE_ONLINE</span></div></div>{% if events %}<div class="cloud-table-wrap"><table class="cloud-table"><thead><tr><th>Time</th><th>Event</th><th>Equipment</th><th>Device</th><th>Detail</th></tr></thead><tbody>{% for e in events %}<tr><td>{{ e.occurred_at }}</td><td><strong>{{ e.event_type }}</strong></td><td>{{ e.equipment_id or '—' }}</td><td>{{ e.device_id }}</td><td>{{ e.detail }}</td></tr>{% endfor %}</tbody></table></div>{% else %}<div class="empty-state">No connectivity event yet.</div>{% endif %}</article>
      <div class="predictive-callout cloud-note"><span>Power-loss policy</span><strong>No internal UPS required.</strong> Missing heartbeat triggers Device Offline after the grace period. Edge buffering applies only while the Pi remains powered.</div>
    </main>
  </section>
</div>
<script>const f=document.getElementById('device-filter');f?.addEventListener('input',()=>{const q=f.value.toLowerCase();document.querySelectorAll('.device-row').forEach(r=>r.hidden=!r.dataset.search.toLowerCase().includes(q));});</script>
</body></html>
