station: Identify devices by MAC OUI vendor lookup

Embed the IEEE OUI registry (~1MB pre-processed text file) and resolve
the vendor for every station MAC. Locally administered MACs (U/L bit
set, used by iOS/Android private addresses and virtual interfaces) are
skipped so we don't return spurious matches against randomized prefixes.

The vendor name shows up in the device card as a secondary line, and
falls back to the title position when no DHCP hostname is available —
"Apple" with the IP and MAC is far more useful than "Sans nom".

The lookup table loads lazily (sync.Once) on the first call so the
~40k-entry parse only runs when the station discovery code is exercised.
This commit is contained in:
nemunaire 2026-05-01 22:32:57 +08:00
commit 70140bc289
10 changed files with 39518 additions and 3 deletions

View file

@ -403,14 +403,16 @@ function displayDevices(devices) {
const displayName = device.name && device.name.trim() !== ''
? device.name
: 'Sans nom';
: (device.vendor ? device.vendor : 'Sans nom');
const showVendor = device.vendor && device.vendor !== displayName;
const metrics = buildDeviceMetrics(device);
deviceCard.innerHTML = `
${getDeviceIcon(device.type)}
<div class="device-name">${escapeHtml(displayName)}</div>
<div class="device-type">${escapeHtml(formatDeviceType(device.type))}</div>
${showVendor ? `<div class="device-vendor">${escapeHtml(device.vendor)}</div>` : ''}
<div class="device-info">
<div>${escapeHtml(device.ip || '—')}</div>
<div class="device-mac">${escapeHtml(device.mac)}</div>

View file

@ -553,7 +553,16 @@ body {
color: var(--text-tertiary);
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 0.125rem;
}
.device-vendor {
font-size: 0.75rem;
color: var(--text-secondary);
margin-bottom: 0.375rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.device-info {