Add Starlink status lines for the physical gateway pane (closes #3)
check / check (push) Failing after 1s

When the non-VPN physical gateway is a Starlink dish, two lines are shown
under that pane: state, uptime, obstruction and alert count; then pop-ping
latency and drop rate with downlink/uplink throughput. They turn red when
the dish is not connected or an alert is active.

Detection is a TCP connect to the dish's fixed endpoint 192.168.100.1:9200,
bound to the physical interface the same way the latency probes bind. Until
a dish answers nothing is drawn and no status is fetched, so an absent dish
adds no noise. Status comes from the dish's local get_status gRPC call.

Detection and the fetch sit behind a small Client interface; the loop and
the pure Render function are tested with a fake, no dish and no network.

Model: opus-4-8
This commit is contained in:
2026-09-21 22:51:45 +00:00
parent 486a47397c
commit e3ef4f2f48
15 changed files with 1535 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
package starlink_test
import (
"testing"
"time"
"git.eeqj.de/sneak/rtnetmon/internal/starlink"
)
func TestRender(t *testing.T) {
t.Parallel()
connected := starlink.Status{
State: "CONNECTED",
Uptime: 3*24*time.Hour + 4*time.Hour + 12*time.Minute,
ObstructionPct: 0.1,
Alerts: 0,
PopPingMs: 34,
PopPingDropPct: 0.0,
DownlinkMbps: 145.3,
UplinkMbps: 12.1,
}
tests := []struct {
name string
status starlink.Status
wantLine1 string
wantLine2 string
wantAlert bool
}{
{
name: "connected, no alert",
status: connected,
wantLine1: "Starlink: CONNECTED uptime 3d 4h 12m obstruction 0.1% alerts 0",
wantLine2: " pop ping 34ms / drop 0.0% down 145.3Mbps / up 12.1Mbps",
wantAlert: false,
},
{
name: "searching is an alert",
status: starlink.Status{
State: "SEARCHING",
Uptime: 0,
},
wantLine1: "Starlink: SEARCHING uptime 0d 0h 0m obstruction 0.0% alerts 0",
wantLine2: " pop ping 0ms / drop 0.0% down 0.0Mbps / up 0.0Mbps",
wantAlert: true,
},
{
name: "connected but alerts active",
status: starlink.Status{
State: "CONNECTED",
Uptime: 90 * time.Minute,
Alerts: 2,
},
wantLine1: "Starlink: CONNECTED uptime 0d 1h 30m obstruction 0.0% alerts 2",
wantLine2: " pop ping 0ms / drop 0.0% down 0.0Mbps / up 0.0Mbps",
wantAlert: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
line1, line2, alert := starlink.Render(tt.status)
if line1 != tt.wantLine1 {
t.Errorf("line1 = %q, want %q", line1, tt.wantLine1)
}
if line2 != tt.wantLine2 {
t.Errorf("line2 = %q, want %q", line2, tt.wantLine2)
}
if alert != tt.wantAlert {
t.Errorf("alert = %v, want %v", alert, tt.wantAlert)
}
})
}
}