mirror of
https://github.com/henrygd/beszel.git
synced 2026-09-27 03:47:47 +02:00
store compact RSSI stats and skip real-time collection
Stats.WiFi is now map[string]int8 (json "wf") holding only available RSSI readings; SSID and unavailable signals stay in Info.WiFi. Averages are rounded to whole dBm. Wi-Fi is collected only on the default 60s interval; real-time requests reuse the last snapshot to avoid spawning osascript / dumping the BSS cache every second.
This commit is contained in:
@@ -268,7 +268,13 @@ func (a *Agent) getSystemStats(cacheTimeMs uint16) system.Stats {
|
||||
}
|
||||
}
|
||||
|
||||
systemStats.WiFi = wifi.Collect()
|
||||
// Wi-Fi collection spawns a process on macOS and dumps the BSS cache on
|
||||
// Linux, so only refresh on the default interval. Real-time requests reuse
|
||||
// the last snapshot.
|
||||
if cacheTimeMs == defaultDataCacheTimeMs {
|
||||
a.systemInfo.WiFi = wifi.Collect()
|
||||
}
|
||||
systemStats.WiFi = wifi.Signals(a.systemInfo.WiFi)
|
||||
|
||||
// update system info
|
||||
a.systemInfo.ConnectionType = a.connectionManager.ConnectionType
|
||||
@@ -277,7 +283,6 @@ func (a *Agent) getSystemStats(cacheTimeMs uint16) system.Stats {
|
||||
a.systemInfo.MemPct = systemStats.MemPct
|
||||
a.systemInfo.DiskPct = systemStats.DiskPct
|
||||
a.systemInfo.Battery = systemStats.Battery
|
||||
a.systemInfo.WiFi = systemStats.WiFi
|
||||
a.systemInfo.Uptime, _ = getUptime()
|
||||
a.systemInfo.BandwidthBytes = systemStats.Bandwidth[0] + systemStats.Bandwidth[1]
|
||||
a.systemInfo.Threads = a.systemDetails.Threads
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# Connected Wi-Fi signal
|
||||
|
||||
Each fresh stats poll reports a snapshot of connected station interfaces in
|
||||
`stats.wifi` and `info.wifi`. Map keys identify interfaces, not networks. `s` is
|
||||
optional SSID metadata; `r` is nullable native RSSI in dBm. Quality percentages
|
||||
are never converted to dBm. An associated interface without an accessible RSSI
|
||||
still appears with an unavailable signal. No scans or network changes occur.
|
||||
Each default-interval poll reports a snapshot of connected station interfaces
|
||||
in `info.wifi`. Map keys identify interfaces, not networks. `s` is optional SSID
|
||||
metadata; `r` is nullable native RSSI in dBm. Quality percentages are never
|
||||
converted to dBm. An associated interface without an accessible RSSI still
|
||||
appears with an unavailable signal. No scans or network changes occur.
|
||||
`stats.wf` stores only available RSSI values (integer dBm) keyed by interface.
|
||||
Real-time requests reuse the last snapshot instead of collecting again.
|
||||
|
||||
The hub panel gates exclusively on current `systems.info.wifi` and system `up`
|
||||
status, independently of the selected historical period. Empty/null snapshots
|
||||
clear it. Historical averages use only available readings per interface; gaps
|
||||
are not zero signal. Interface colors and keys remain stable on reconnect.
|
||||
SSID in an aggregate is the latest observed metadata, not a separate series.
|
||||
|
||||
## Platforms
|
||||
|
||||
@@ -39,7 +40,7 @@ SSID in an aggregate is the latest observed metadata, not a separate series.
|
||||
- FreeBSD and other platforms: unsupported, empty snapshot. No approximation
|
||||
from ifconfig quality and no stale data retained.
|
||||
|
||||
Collectors retry each fresh poll, allowing interfaces and capabilities to appear
|
||||
Collectors retry each default-interval poll, allowing interfaces and capabilities to appear
|
||||
without an agent restart. Standard agent response caching still applies. Existing
|
||||
hub record JSON storage requires no database schema migration. Older agents
|
||||
without the field keep the panel hidden. Native macOS/Windows runtime checks and
|
||||
|
||||
@@ -4,6 +4,7 @@ package wifi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
@@ -38,3 +39,19 @@ func Collect() map[string]system.WiFi {
|
||||
defer cancel()
|
||||
return collect(ctx)
|
||||
}
|
||||
|
||||
// Signals reduces a snapshot to the RSSI values stored in stats history.
|
||||
// Interfaces without an available reading are omitted.
|
||||
func Signals(snapshot map[string]system.WiFi) map[string]int8 {
|
||||
var signals map[string]int8
|
||||
for id, reading := range snapshot {
|
||||
if reading.Signal == nil {
|
||||
continue
|
||||
}
|
||||
if signals == nil {
|
||||
signals = make(map[string]int8, len(snapshot))
|
||||
}
|
||||
signals[id] = int8(max(math.Round(*reading.Signal), math.MinInt8))
|
||||
}
|
||||
return signals
|
||||
}
|
||||
|
||||
@@ -33,3 +33,25 @@ func TestSSIDWireSafety(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignals(t *testing.T) {
|
||||
strong, weak, rounded := -40.0, -200.0, -52.6
|
||||
got := Signals(map[string]system.WiFi{
|
||||
"wlan0": {SSID: "home", Signal: &strong},
|
||||
"wlan1": {Signal: &weak},
|
||||
"wlan2": {Signal: &rounded},
|
||||
"wlan3": {SSID: "no rssi"},
|
||||
})
|
||||
want := map[string]int8{"wlan0": -40, "wlan1": -128, "wlan2": -53}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("got %v, want %v", got, want)
|
||||
}
|
||||
for id, signal := range want {
|
||||
if got[id] != signal {
|
||||
t.Fatalf("got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
if Signals(map[string]system.WiFi{"wlan0": {}}) != nil || Signals(nil) != nil {
|
||||
t.Fatal("expected nil without available readings")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user