diff --git a/main.go b/main.go index 635e7d6..b86dda3 100644 --- a/main.go +++ b/main.go @@ -40,10 +40,10 @@ type Config struct { ChannelKeys []string // Statistics configuration - StatsInterval time.Duration - CacheSize int - CacheRetention time.Duration - VerboseLogging bool + StatsInterval time.Duration + CacheSize int + CacheRetention time.Duration + VerboseLogging bool } // getEnv retrieves an environment variable with the given prefix or returns the default value diff --git a/mqtt/broker.go b/mqtt/broker.go index c628078..83bcd55 100644 --- a/mqtt/broker.go +++ b/mqtt/broker.go @@ -30,11 +30,11 @@ var typePriority = map[pb.PortNum]int{ pb.PortNum_TEXT_MESSAGE_COMPRESSED_APP: 5, pb.PortNum_NEIGHBORINFO_APP: 4, // rare; protect from eviction pb.PortNum_TRACEROUTE_APP: 3, - pb.PortNum_POSITION_APP: 3, - pb.PortNum_NODEINFO_APP: 2, // frequent; lower priority - pb.PortNum_TELEMETRY_APP: 2, - pb.PortNum_ROUTING_APP: 2, - pb.PortNum_MAP_REPORT_APP: 2, + pb.PortNum_POSITION_APP: 3, + pb.PortNum_NODEINFO_APP: 2, // frequent; lower priority + pb.PortNum_TELEMETRY_APP: 2, + pb.PortNum_ROUTING_APP: 2, + pb.PortNum_MAP_REPORT_APP: 2, } // defaultTypePriority applies to any port type not listed above. diff --git a/mqtt/broker_test.go b/mqtt/broker_test.go index 6babda5..73f71ff 100644 --- a/mqtt/broker_test.go +++ b/mqtt/broker_test.go @@ -60,10 +60,10 @@ func TestNodeAwareCacheBasicOrdering(t *testing.T) { func TestPressureEvictsOldestOfLowestPriority(t *testing.T) { c := NewNodeAwareCache(3, time.Hour) - c.Add(pkt(1, 1, pb.PortNum_NODEINFO_APP)) // priority 2 - c.Add(pkt(2, 1, pb.PortNum_NEIGHBORINFO_APP)) // priority 4 - c.Add(pkt(3, 1, pb.PortNum_NODEINFO_APP)) // priority 2 — at cap - c.Add(pkt(4, 1, pb.PortNum_NODEINFO_APP)) // pressure: evicts oldest pri=2 (ID 1) + c.Add(pkt(1, 1, pb.PortNum_NODEINFO_APP)) // priority 2 + c.Add(pkt(2, 1, pb.PortNum_NEIGHBORINFO_APP)) // priority 4 + c.Add(pkt(3, 1, pb.PortNum_NODEINFO_APP)) // priority 2 — at cap + c.Add(pkt(4, 1, pb.PortNum_NODEINFO_APP)) // pressure: evicts oldest pri=2 (ID 1) got := c.GetAll() if len(got) != 3 { diff --git a/web/src/routes/map.tsx b/web/src/routes/map.tsx index 28e1469..a3d315e 100644 --- a/web/src/routes/map.tsx +++ b/web/src/routes/map.tsx @@ -26,15 +26,15 @@ function MapPage() { return (
-
+
- -
+ +
diff --git a/web/src/store/slices/topologySlice.ts b/web/src/store/slices/topologySlice.ts index 4a68218..50b0fa9 100644 --- a/web/src/store/slices/topologySlice.ts +++ b/web/src/store/slices/topologySlice.ts @@ -156,6 +156,8 @@ function processTopology( for (let i = 0; i < forwardPath.length - 1; i++) { const cap = Math.min(snrTowards.length, forwardPath.length - 1); const snr = i < cap ? snrTowards[i] / 4 : undefined; + // SNR of exactly 0 indicates an MQTT-bridged hop + const hopViaMqtt = snr === 0 || !!data.viaMqtt; upsertObservation( state, forwardPath[i], // sender @@ -163,7 +165,7 @@ function processTopology( snr, undefined, "traceroute", - !!data.viaMqtt, + hopViaMqtt, timestamp, hopCount ); @@ -176,6 +178,8 @@ function processTopology( for (let i = 0; i < returnPath.length - 1; i++) { const cap = Math.min(snrBack.length, returnPath.length - 1); const snr = i < cap ? snrBack[i] / 4 : undefined; + // SNR of exactly 0 indicates an MQTT-bridged hop + const hopViaMqtt = snr === 0 || !!data.viaMqtt; upsertObservation( state, returnPath[i], @@ -183,7 +187,7 @@ function processTopology( snr, undefined, "traceroute", - !!data.viaMqtt, + hopViaMqtt, timestamp, hopCount ); diff --git a/web/src/test/setup.ts b/web/src/test/setup.ts index 572681e..fe190bc 100644 --- a/web/src/test/setup.ts +++ b/web/src/test/setup.ts @@ -1,6 +1,14 @@ import '@testing-library/jest-dom'; import { vi } from 'vitest'; +// Mock URL.createObjectURL (required by maplibre-gl worker setup) +if (typeof window.URL.createObjectURL === 'undefined') { + window.URL.createObjectURL = vi.fn(() => ''); +} +if (typeof window.URL.revokeObjectURL === 'undefined') { + window.URL.revokeObjectURL = vi.fn(); +} + // Mock for window.matchMedia Object.defineProperty(window, 'matchMedia', { writable: true,