onu: info/stats sub-tab with CPE lease health + OUI vendor
Adds an ONU info page and splits the ONU tab into two sub-tabs (Info / stats, Fleet & upgrade). The ONU tab now lands on Info; campaign/verify keep the Fleet sub-tab lit. ONU info page (#view-onu-info): master-detail over the already-loaded fleet (search + status filter, no new bulk fetch). Per-ONU detail shows identity, link/optical + FEC (read from the merged ONU-STATE), firmware, and a CPE card. CPE (customer router): - McmsClient.getCpe — GET /api/cpe/onu/<id>/ (unversioned, [status,doc] tuple). - src/cpe.js (pure, shared): summarizeCpe + leaseHealth. Renewal rule — <50% of the lease remaining => "renewal overdue" (amber), past end => expired. v4 expiry = DHCP "Remove Time"; v6 spans Last Success -> Preferred Lifetime (T1 midpoint), with Prefix Delegation surfaced. - api:getOnuCpe (main.js + web/server.js, exposed in both bridges). OUI vendor (src/oui.js, pure, shared): lazy fetch of the IEEE oui.csv, prefix->org map, cached in memory ~30 days + best-effort to disk (PFW_CACHE_DIR / temp; PrivateTmp makes /tmp writable). Resolved server-side in getOnuCpe; every failure degrades to "unknown OUI". CPE itself is not TTL-cached (lease must be live); only the OUI list is. Dashboard abnormal Rx/Tx rows are now clickable -> deep-link to that ONU's info page (showListModal gained per-item onClick). Docs: CLAUDE.md §17 + IPC table + intro; README. Verified: node --check; cpe.js/oui.js unit-tested (15/15: lease ok/warn/ expired/unknown + 50% boundary, v6 prefix parse, OUI quoted-CSV parse + lookup); ONU info page + CPE card rendered offscreen over HTTP. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
5e3d9271a8
commit
55e95ed467
12 changed files with 677 additions and 7 deletions
|
|
@ -13,7 +13,7 @@
|
|||
<div class="brand">PON Fleet Upgrader</div>
|
||||
<nav id="tabs" class="tabs hidden">
|
||||
<button class="tab" data-tab="dashboard" data-view="#view-dashboard">Dashboard</button>
|
||||
<button class="tab" data-tab="onu" data-view="#view-fleet">ONU</button>
|
||||
<button class="tab" data-tab="onu" data-view="#view-onu-info">ONU</button>
|
||||
<button class="tab" data-tab="olt" data-view="#view-olts">OLT</button>
|
||||
</nav>
|
||||
<div class="session" id="session-label">Not connected</div>
|
||||
|
|
@ -66,9 +66,47 @@
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ================= ONU info / stats view ================= -->
|
||||
<section id="view-onu-info" class="view hidden">
|
||||
<div class="panel-left">
|
||||
<nav class="subtabs">
|
||||
<button class="subtab" data-subview="#view-onu-info">Info / stats</button>
|
||||
<button class="subtab" data-subview="#view-fleet">Fleet & upgrade</button>
|
||||
</nav>
|
||||
<h2>Find ONU</h2>
|
||||
<label>Search (name / address / serial)
|
||||
<input id="onu-info-search" type="search" placeholder="e.g. ORKANGER or GNXS05…" />
|
||||
</label>
|
||||
<label>Registration status
|
||||
<select id="onu-info-status">
|
||||
<option value="">Any</option>
|
||||
<option value="__down__">Down (Dereg / Dying Gasp / Disabled)</option>
|
||||
<option value="Registered">Registered</option>
|
||||
<option value="Deregistered">Deregistered</option>
|
||||
<option value="Dying Gasp">Dying Gasp</option>
|
||||
<option value="Disabled">Disabled</option>
|
||||
<option value="__unknown__">Unknown (no OLT state)</option>
|
||||
</select>
|
||||
</label>
|
||||
<button id="onu-info-load" class="primary">Load fleet</button>
|
||||
<p class="muted small" id="onu-info-status-line">Load the fleet, then pick an ONU.</p>
|
||||
<div class="onu-info-list" id="onu-info-list"></div>
|
||||
</div>
|
||||
|
||||
<div class="panel-main">
|
||||
<div id="onu-info-detail" class="onu-detail">
|
||||
<p class="muted">Select an ONU on the left to see its stats and the CPE (customer router) behind it.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ================= Fleet view ================= -->
|
||||
<section id="view-fleet" class="view hidden">
|
||||
<div class="panel-left">
|
||||
<nav class="subtabs">
|
||||
<button class="subtab" data-subview="#view-onu-info">Info / stats</button>
|
||||
<button class="subtab" data-subview="#view-fleet">Fleet & upgrade</button>
|
||||
</nav>
|
||||
<h2>Filters</h2>
|
||||
<label>Name / address contains
|
||||
<input id="filter-text" type="search" placeholder="e.g. ORKANGER" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue