Initial import

This commit is contained in:
2026-02-14 15:59:31 +01:00
parent 05dcea3c2b
commit f1ecbfaf8d
19 changed files with 2675 additions and 0 deletions

106
protocol/aprs/address.go Normal file
View File

@@ -0,0 +1,106 @@
package aprs
import (
"errors"
"fmt"
"strings"
)
var (
ErrAddressInvalid = errors.New(`aprs: invalid address`)
)
type Address struct {
Call string `json:"call"`
SSID string `json:"ssid,omitempty"`
IsRepeated bool `json:"is_repeated,omitempty"`
}
func (a Address) EqualTo(b Address) bool {
return a.Call == b.Call && a.SSID == b.SSID
}
func (a Address) String() string {
var r = ""
if a.IsRepeated {
r = "*"
}
if a.SSID == "" {
return a.Call + r
}
return fmt.Sprintf("%s-%s%s", a.Call, a.SSID, r)
}
func (a Address) Secret() int16 {
var h = int16(0x73e2)
var c = a.Call
if len(c)%2 > 0 {
c += "\x00"
}
for i := 0; i < len(c); i += 2 {
h ^= int16(c[i]) << 8
h ^= int16(c[i+1])
}
return h & 0x7fff
}
func ParseAddress(s string) (Address, error) {
r := strings.HasSuffix(s, "*")
if r {
s = s[:len(s)-1]
}
p := strings.Split(s, "-")
if len(p) == 0 || len(p) > 2 {
return Address{}, ErrAddressInvalid
}
a := Address{Call: p[0], IsRepeated: r}
if len(p) == 2 {
a.SSID = p[1]
}
return a, nil
}
func MustParseAddress(s string) Address {
a, err := ParseAddress(s)
if err != nil {
panic(err)
}
return a
}
func IsQConstruct(call string) bool {
return len(call) == 3 && call[0] == 'q'
}
type Path []Address
func (p Path) String() string {
var s = make([]string, len(p))
for i, a := range p {
s[i] = a.String()
}
return strings.Join(s, ",")
}
func ParsePath(p string) (Path, error) {
ss := strings.Split(p, ",")
if len(ss) == 0 {
return nil, nil
}
var err error
as := make(Path, len(ss))
for i, s := range ss {
as[i], err = ParseAddress(s)
if err != nil {
return nil, err
}
}
return as, nil
}