The store shipped without its main source. Locators came only from this station's own WSJT-X decodes, which is what the whole MQTT discussion was about. PSK Reporter now feeds it through a new OnGrid callback, fired before any geographic filtering: what the store wants is "which square is this callsign in", and that is true whoever happened to hear the report. The subscription filters on the RECEIVER's square, a level the v2 topic exposes. Measured on the live feed: the four opening bands unfiltered are 83 messages a second, of which roughly one in a hundred survived the NearKm test that already existed here — the rest was received, TLS-decrypted, JSON-parsed and discarded. One ring of squares is 0.2 to 1.2 a second. By square rather than by DXCC, which was the obvious alternative: one country measured 1.2 messages a second (OH) against 72.5 (K) on a single band, because a DXCC can be a continent. By square the same measurement is 0.2 to 1.2, so the load follows distance — what the feed is actually about — and is the same for every operator. Grid chasing subscribes with the "+" band wildcard, so one subscription per square covers every band instead of one per band per square. The store gains a source column (decode | mqtt), migrated in place on an existing file.
50 lines
1.3 KiB
Go
50 lines
1.3 KiB
Go
package geo
|
|
|
|
import "testing"
|
|
|
|
// The squares the PSK Reporter feed is filtered on. A wrong ring means either
|
|
// receiving the world again or hearing nothing.
|
|
func TestNeighbourGrids(t *testing.T) {
|
|
// JN36 is around 46.5N 5.5E.
|
|
lat, lon, ok := GridToLatLon("JN36")
|
|
if !ok {
|
|
t.Fatal("JN36 did not resolve")
|
|
}
|
|
if got := LatLonToGrid(lat, lon); got != "JN36" {
|
|
t.Fatalf("round trip gave %q, want JN36", got)
|
|
}
|
|
|
|
ring := NeighbourGrids(lat, lon, 1)
|
|
if len(ring) != 9 {
|
|
t.Errorf("ring 1 has %d squares, want 9: %v", len(ring), ring)
|
|
}
|
|
found := false
|
|
for _, g := range ring {
|
|
if g == "JN36" {
|
|
found = true
|
|
}
|
|
if len(g) != 4 {
|
|
t.Errorf("not a 4-character square: %q", g)
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("the operator's own square is missing from %v", ring)
|
|
}
|
|
if n := len(NeighbourGrids(lat, lon, 0)); n != 1 {
|
|
t.Errorf("ring 0 has %d squares, want just the operator's", n)
|
|
}
|
|
if n := len(NeighbourGrids(lat, lon, 2)); n != 25 {
|
|
t.Errorf("ring 2 has %d squares, want 25", n)
|
|
}
|
|
}
|
|
|
|
// Near a pole a step north has nowhere to go; it must be dropped, not wrapped
|
|
// onto a square on the far side of the world.
|
|
func TestNeighbourGridsNearThePole(t *testing.T) {
|
|
for _, g := range NeighbourGrids(89.5, 25, 1) {
|
|
if len(g) != 4 {
|
|
t.Errorf("bad square near the pole: %q", g)
|
|
}
|
|
}
|
|
}
|