93 lines
3.3 KiB
Go
93 lines
3.3 KiB
Go
// 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 <ip:port> [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 <Freq> unit
|
|
|
|
// Tag <PST><FREQUENCY> 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("<PST><FREQUENCY>%d</FREQUENCY></PST>", hz) }},
|
|
{"FREQUENCY = tens-of-Hz (expect 0.35255 MHz)", func(k float64) string { return fmt.Sprintf("<PST><FREQUENCY>%d</FREQUENCY></PST>", tensHz) }},
|
|
{"FREQUENCY = kHz integer (expect 0.003525 MHz)", func(k float64) string { return fmt.Sprintf("<PST><FREQUENCY>%d</FREQUENCY></PST>", int64(k+0.5)) }},
|
|
{"FREQUENCY = kHz decimal (baseline: gave 0.035255 MHz)", func(k float64) string { return fmt.Sprintf("<PST><FREQUENCY>%.1f</FREQUENCY></PST>", 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?")
|
|
}
|