mirror of
https://github.com/henrygd/beszel.git
synced 2026-09-28 20:37:48 +02:00
feat: monitor connected Wi-Fi signal per interface (#2367)
This commit is contained in:
28
internal/site/src/lib/wifi.test.ts
Normal file
28
internal/site/src/lib/wifi.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import { connectedWiFi, strongestWiFiSignal, wifiColor } from "./wifi"
|
||||
import type { SystemInfo } from "@/types"
|
||||
|
||||
const system = (wifi?: SystemInfo["wifi"], status: "up" | "down" = "up") => ({ status, info: { wifi } as SystemInfo })
|
||||
|
||||
test("current state gates panel, not retained history", () => {
|
||||
expect(connectedWiFi(system())).toEqual([])
|
||||
expect(connectedWiFi(system(null))).toEqual([])
|
||||
expect(connectedWiFi(system({}))).toEqual([])
|
||||
expect(connectedWiFi(system({ wlan0: { r: -50 } }, "down"))).toEqual([])
|
||||
expect(connectedWiFi(system({ wlan0: { r: -50 } }))).toHaveLength(1)
|
||||
expect(connectedWiFi(system({}))).toHaveLength(0)
|
||||
expect(connectedWiFi(system({ wlan0: { s: "new", r: -60 } }))[0][0]).toBe("wlan0")
|
||||
})
|
||||
|
||||
test("multiple interfaces retain independent stable identities and colors", () => {
|
||||
const connections = connectedWiFi(system({ wlan1: { s: "same" }, wlan0: { s: "same", r: -40 } }))
|
||||
expect(connections.map(([id]) => id)).toEqual(["wlan0", "wlan1"])
|
||||
expect(wifiColor(connections[0][0])).toBe(wifiColor("wlan0"))
|
||||
expect(wifiColor("wlan0")).not.toBe(wifiColor("wlan1"))
|
||||
})
|
||||
|
||||
test("strongestWiFiSignal returns the strongest current native RSSI", () => {
|
||||
expect(strongestWiFiSignal(system({ wlan0: { r: -63 }, wlan1: { r: -48 }, wlan2: {} }))).toBe(-48)
|
||||
expect(strongestWiFiSignal(system({ wlan0: {} }))).toBeUndefined()
|
||||
expect(strongestWiFiSignal(system({ wlan0: { r: -48 } }, "down"))).toBeUndefined()
|
||||
})
|
||||
20
internal/site/src/lib/wifi.ts
Normal file
20
internal/site/src/lib/wifi.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { SystemRecord, WiFi } from "@/types"
|
||||
|
||||
// Current system info is independent of the selected historical chart window.
|
||||
// No fallback to history: missing data, disconnect and offline all hide the panel.
|
||||
export function connectedWiFi(system: Pick<SystemRecord, "status" | "info">): [string, WiFi][] {
|
||||
return system.status === "up" ? Object.entries(system.info?.wifi ?? {}).sort(([a], [b]) => a.localeCompare(b)) : []
|
||||
}
|
||||
|
||||
export function strongestWiFiSignal(system: Pick<SystemRecord, "status" | "info">): number | undefined {
|
||||
const signals = connectedWiFi(system)
|
||||
.map(([, wifi]) => wifi.r)
|
||||
.filter((signal): signal is number => signal !== undefined && Number.isFinite(signal))
|
||||
return signals.length ? Math.max(...signals) : undefined
|
||||
}
|
||||
|
||||
export function wifiColor(id: string): string {
|
||||
let hash = 0
|
||||
for (const char of id) hash = (Math.imul(hash, 31) + char.charCodeAt(0)) | 0
|
||||
return `hsl(${(hash >>> 0) % 360}, 65%, 52%)`
|
||||
}
|
||||
Reference in New Issue
Block a user