// Command psttest probes PstRotatorAz's UDP tracking input to discover the wire // format it expects for the "DXLog.net" tracker. We don't have the spec, so this // sends a series of labelled candidate datagrams to the target and pauses between // each so you can watch PstRotatorAz and note which one it reacts to (the band // filter "Rotate Antenna only for the Selected Bands" changes, or the frequency // shows in the tracker box). // // Setup on the PstRotatorAz side: // - Tracker = DXLog.net // - Note the UDP port it listens on (commonly 12040) and this PC's IP // - In the tracker setup tick a couple of bands so the band filter is visible // // Usage: // // go run ./cmd/psttest 192.168.1.50:12040 # default 14025.5 kHz // go run ./cmd/psttest 192.168.1.50:12040 21074 # a specific kHz // go run ./cmd/psttest 192.168.1.50:12040 21074 3 # repeat each variant 3x // // Watch PstRotatorAz as it runs; when one variant makes it react, that's the // format — tell me the variant number and I'll wire it into OpsLog. package main import ( "fmt" "net" "os" "strconv" "time" ) type variant struct { name string // build returns the datagram for a given frequency in kHz. build func(khz float64) string } func main() { if len(os.Args) < 2 { fmt.Println("usage: psttest [freqKHz] [repeat]") fmt.Println("example: psttest 192.168.1.50:12040 3525.5") os.Exit(2) } target := os.Args[1] khz := 3525.5 if len(os.Args) >= 3 { if v, err := strconv.ParseFloat(os.Args[2], 64); err == nil { khz = v } } repeat := 1 if len(os.Args) >= 4 { if v, err := strconv.Atoi(os.Args[3]); err == nil && v > 0 { repeat = v } } hz := int64(khz*1000 + 0.5) tensHz := hz / 10 // N1MM/DXLog unit // Tag is confirmed. PstRotator strips the decimal point and // reads the digits, so pin down the exact unit: watch which one shows the real // frequency (3.5255 MHz), not 0.35255 / 0.003525 / 0.035255. variants := []variant{ {"FREQUENCY = Hz integer (expect 3.5255 MHz) ← prediction", func(k float64) string { return fmt.Sprintf("%d", hz) }}, {"FREQUENCY = tens-of-Hz (expect 0.35255 MHz)", func(k float64) string { return fmt.Sprintf("%d", tensHz) }}, {"FREQUENCY = kHz integer (expect 0.003525 MHz)", func(k float64) string { return fmt.Sprintf("%d", int64(k+0.5)) }}, {"FREQUENCY = kHz decimal (baseline: gave 0.035255 MHz)", func(k float64) string { return fmt.Sprintf("%.1f", k) }}, } conn, err := net.Dial("udp", target) if err != nil { fmt.Printf("dial %s: %v\n", target, err) os.Exit(1) } defer conn.Close() fmt.Printf("Sending %d variants to %s at %.1f kHz (%d Hz, %d tens-of-Hz), %dx each.\n\n", len(variants), target, khz, hz, tensHz, repeat) for i, v := range variants { msg := v.build(khz) fmt.Printf("── Variant %d: %s\n", i+1, v.name) fmt.Printf(" payload: %s\n", msg) for r := 0; r < repeat; r++ { if _, err := conn.Write([]byte(msg)); err != nil { fmt.Printf(" write error: %v\n", err) } time.Sleep(300 * time.Millisecond) } fmt.Printf(" → sent. Watch PstRotatorAz for ~4s…\n\n") time.Sleep(4 * time.Second) } fmt.Println("Done. Which variant number made PstRotatorAz react?") }