Ostatnio aktywny 1 month ago

APRS-IS Send / Receive

aprs.go Surowy
1package main
2
3import (
4 "bufio"
5 "fmt"
6 "log"
7 "net"
8 "strings"
9 "time"
10)
11
12const server = "euro.aprs2.net"
13const port = 14580
14
15const softwareName = "goaprs"
16const softwareVersion = "0.1"
17
18const callsign = "PU2NVX"
19const passcode = "123456"
20const notifyMessage = "HUEBR"
21
22const SendInterval = time.Second * 60 * 5
23const ReconnectInterval = time.Minute * 30
24
25var myCoordinate = []float32{-23.640000,-46.650000}
26
27var lastCoordinateSent time.Time
28
29var loggedIn = false
30
31func Degrees2DMS(val float32) (deg int, min float32, n string) {
32 n = "+"
33 if val < 0 {
34 val = -val
35 n = "-"
36 }
37
38 deg = int(val)
39 val -= float32(deg)
40 val *= 60
41 min = val
42
43 return
44}
45
46func buildMessage(callsign, passcode, cmd string) string {
47 return fmt.Sprintf("user %s pass %s vers %s %s %s", callsign, passcode, softwareName, softwareVersion, cmd)
48}
49
50func parseAPRS(msg string, conn net.Conn) {
51 log.Printf("<- APRS: %s\n", msg)
52}
53
54func parseServer(msg string, conn net.Conn) {
55 log.Printf("<- SERVER: %s\n", msg)
56 if strings.Index(msg, "verified") > -1 {
57 log.Printf("-- Logged in as %s\n", callsign)
58
59 sendPosition(conn)
60 lastCoordinateSent = time.Now()
61
62 loggedIn = true
63 }
64}
65
66func parseMessage(msg string, conn net.Conn) {
67 if string(msg[0]) == "#" {
68 // Server Message
69 parseServer(msg[2:], conn)
70 return
71 }
72
73 parseAPRS(msg, conn)
74}
75
76func formatPosition() string {
77 lat := myCoordinate[0]
78 lon := myCoordinate[1]
79
80 latDeg, latMin, latV := Degrees2DMS(lat)
81 lonDeg, lonMin, lonV := Degrees2DMS(lon)
82
83 if latV == "-" {
84 latV = "S"
85 } else {
86 latV = "N"
87 }
88 if lonV == "-" {
89 lonV = "W"
90 } else {
91 lonV = "E"
92 }
93
94 return fmt.Sprintf("%02d%02.2f%s/%03d%02.2f%s-000/000/A=000000", latDeg, latMin, latV, lonDeg, lonMin, lonV)
95}
96
97func sendPosition(conn net.Conn) {
98 log.Println("-- Sending Position")
99 sendMessage(conn, buildMessage(callsign, passcode, "")) // First Line
100 sendMessage(conn, fmt.Sprintf("%s>APDR15,TCPIP*:=%s %s", callsign, formatPosition(), notifyMessage))
101}
102
103func sendMessage(conn net.Conn, msg string) {
104 log.Printf("-> %s\n" ,msg)
105 _, err := conn.Write([]byte(msg + "\n"))
106 if err != nil {
107 panic(err)
108 }
109}
110
111func connect() (net.Conn, *bufio.Reader) {
112 log.Printf("-- Connecting to %s:%d\n", server, port)
113 conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", server, port))
114
115 if err != nil {
116 panic(err)
117 }
118
119 reader := bufio.NewReader(conn)
120 time.Sleep(1 * time.Second)
121 line, _, err := reader.ReadLine()
122
123 if err != nil {
124 panic(err)
125 }
126 log.Printf("<- %s\n", string(line))
127
128 log.Println("-- Connected. Sending Login")
129
130 msg := buildMessage(callsign, passcode, fmt.Sprintf("filter r/%f/%f/%d", myCoordinate[0], myCoordinate[1], 50))
131 sendMessage(conn, msg)
132
133 if err != nil {
134 panic(err)
135 }
136
137 return conn, reader
138}
139
140func main() {
141 log.Printf("-- Restart Time: %s\n", ReconnectInterval)
142 log.Printf("-- Send Interval: %s\n", SendInterval)
143 connectTime := time.Now()
144 conn, reader := connect()
145
146 log.Println("-- Receiving messages")
147 for {
148 line, _, err := reader.ReadLine()
149 if err != nil {
150 panic(err)
151 }
152 parseMessage(string(line), conn)
153
154 if time.Since(lastCoordinateSent) > SendInterval && loggedIn {
155 sendPosition(conn)
156 lastCoordinateSent = time.Now()
157 }
158
159 if time.Since(connectTime) > ReconnectInterval {
160 log.Println("-- Reconnect time exceeded. Reconnecting")
161 _ = conn.Close()
162 conn, reader = connect()
163 connectTime = time.Now()
164 }
165 }
166}