radioreference

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package radioreference is a read-only client for RadioReference.com's SOAP web service, used by `gophertrunk hunt` to check whether a discovered trunked system already exists in RadioReference before an operator submits it. RadioReference has no public write API — new systems go through a manual web form reviewed by administrators — so this package never writes anything; it only reads, to avoid duplicate submissions.

Index

Constants

View Source
const DefaultEndpoint = "http://api.radioreference.com/soap2/"

DefaultEndpoint is the RadioReference SOAP web-service endpoint (v3.1).

Variables

View Source
var DefaultAppKey = ""

DefaultAppKey is the built-in RadioReference application key. It is injected at BUILD time via the linker, e.g.:

go build -ldflags "-X github.com/MattCheramie/GopherTrunk/internal/radioreference.DefaultAppKey=<key>"

(the Makefile wires this from the RR_APP_KEY environment variable, and the release workflow from the RR_APP_KEY Actions secret). It is intentionally empty in a bare `go build` / `go test` / `go run` and is never committed to source — a build without the key simply falls back to env/config, exactly as before this default existed.

View Source
var ErrNoCredentials = errors.New("radioreference: no API key configured")

ErrNoCredentials is returned by NewClient when no API key is configured, so callers can cleanly skip the (optional) duplicate check.

View Source
var ErrNoLogin = errors.New("radioreference: username and password are required to verify a subscription")

ErrNoLogin is returned by VerifyCredentials when the username or password is empty: with a built-in app key present, a "verify" can otherwise reach RR and come back with an opaque authorization fault instead of a clear local error.

Functions

func EffectiveAppKey added in v0.3.7

func EffectiveAppKey(explicit string) string

EffectiveAppKey resolves just the app key (explicit > env > built-in) for callers that don't have a full Auth in hand.

Types

type Account added in v0.3.7

type Account struct {
	Username string `json:"username,omitempty"`
	// Expires is the subscription expiry as RR reports it (left as the raw
	// string so the UI can display whatever format the service returns).
	Expires string `json:"expires,omitempty"`
	Premium bool   `json:"premium"`
}

Account is the subset of a RadioReference user account returned by the getUserData call. It is used to confirm that the supplied username/password are valid and that the membership carries an active (premium) subscription — the app key alone cannot prove premium access.

type Auth

type Auth struct {
	AppKey   string
	Username string
	Password string
	Version  string // defaults to "latest"
}

Auth carries the RadioReference web-service credentials.

func ResolveAuth added in v0.3.7

func ResolveAuth(a Auth) Auth

ResolveAuth fills an empty AppKey from the GOPHERTRUNK_RR_KEY environment variable and then the built-in DefaultAppKey, leaving an explicitly-supplied key (and the username/password) untouched. The resulting key precedence is: the value the caller already resolved (flag/config) > env > built-in. Every place that assembles an Auth should pass it through here so the built-in key flows everywhere uniformly.

type Candidate

type Candidate struct {
	WACN            uint32
	SystemID        uint16
	Name            string
	ControlChannels []uint32
}

Candidate is the discovered system's identifying fields, passed to MatchAgainst. It mirrors the parts of hunt.DiscoveredSystem relevant to duplicate detection without importing that package (avoiding a dependency cycle — the hunt CLI builds this from its DiscoveredSystem).

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a read-only RadioReference SOAP client. It is safe for sequential use; create one per hunt run.

func NewClient

func NewClient(auth Auth) (*Client, error)

NewClient builds a client. It returns ErrNoCredentials when auth.AppKey is empty so the hunt can degrade gracefully to "no duplicate check".

func (*Client) GetCountyInfo

func (c *Client) GetCountyInfo(ctx context.Context, ctid int) ([]System, error)

GetCountyInfo fetches the trunked systems registered in a RadioReference county (by ctid). Only the brief identity of each system is returned; call GetTrsDetails to enrich a candidate with its SYSID/WACN before matching.

func (*Client) GetCountyList added in v0.3.6

func (c *Client) GetCountyList(ctx context.Context, stid int) ([]GeoRef, error)

GetCountyList returns the counties in a state (ctid + name) via getStateInfo (the same call SearchByState walks), so the UI can offer a county dropdown after a state is chosen.

func (*Client) GetFullSystem added in v0.3.6

func (c *Client) GetFullSystem(ctx context.Context, sid int) (FullSystem, error)

GetFullSystem fetches a system's identity, sites, and talkgroups and returns an import-ready FullSystem with a mapped GopherTrunk protocol.

func (*Client) GetStateList added in v0.3.6

func (c *Client) GetStateList(ctx context.Context) ([]GeoRef, error)

GetStateList returns the states RadioReference knows (stid + name) for a name dropdown. Element names are matched tolerantly (the SOAP schema labels vary); an unrecognised response yields an empty list.

func (*Client) GetTrsDetails

func (c *Client) GetTrsDetails(ctx context.Context, sid int) (System, error)

GetTrsDetails fetches a single trunked system by RadioReference system id. The response is parsed namespace-agnostically (the RR WSDL wraps the return in method-specific elements that vary by SOAP style), pulling the leaf fields used for duplicate detection.

func (*Client) SearchByCounty added in v0.3.6

func (c *Client) SearchByCounty(ctx context.Context, ctid int) ([]SearchHit, error)

SearchByCounty lists the trunked systems registered in a RadioReference county (by ctid).

func (*Client) SearchByState added in v0.3.6

func (c *Client) SearchByState(ctx context.Context, stid int) ([]SearchHit, error)

SearchByState enumerates a state's counties (by stid) and aggregates the trunked systems registered in each. Duplicate systems (registered in multiple counties) are de-duplicated by SID.

func (*Client) SearchByZip added in v0.3.6

func (c *Client) SearchByZip(ctx context.Context, zip string) ([]SearchHit, error)

SearchByZip resolves a US ZIP code to its county, then lists the trunked systems registered in that county.

func (*Client) SetEndpoint

func (c *Client) SetEndpoint(url string)

SetEndpoint overrides the SOAP endpoint (used by tests).

func (*Client) SetHTTPClient

func (c *Client) SetHTTPClient(h *http.Client)

SetHTTPClient overrides the HTTP client (used by tests).

func (*Client) VerifyCredentials added in v0.3.7

func (c *Client) VerifyCredentials(ctx context.Context) (Account, error)

VerifyCredentials confirms the configured username/password against the RR account service (getUserData) and reports whether the account has an active (premium) subscription. A SOAP fault (bad login / expired membership) surfaces as an error so callers can show the message verbatim.

type FullSystem added in v0.3.6

type FullSystem struct {
	SID        int               `json:"sid"`
	Name       string            `json:"name"`
	Type       string            `json:"type"`             // e.g. "Project 25"
	Flavor     string            `json:"flavor,omitempty"` // e.g. "Phase II"
	Voice      string            `json:"voice,omitempty"`
	Protocol   string            `json:"protocol"` // mapped GopherTrunk protocol id
	SystemID   uint16            `json:"system_id,omitempty"`
	WACN       uint32            `json:"wacn,omitempty"`
	NAC        uint16            `json:"nac,omitempty"`
	City       string            `json:"city,omitempty"`
	County     string            `json:"county,omitempty"`
	State      string            `json:"state,omitempty"`
	Sites      []SiteDetail      `json:"sites"`
	Talkgroups []TalkgroupDetail `json:"talkgroups"`
}

FullSystem is the import-oriented projection of a RadioReference trunked system: identity plus its sites (with control-channel + voice frequencies) and talkgroups. It carries enough to fold into a config.SystemConfig (control channels collapse across sites, since the config schema is flat) and to write a talkgroup CSV sidecar.

type GeoRef added in v0.3.6

type GeoRef struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

GeoRef is a RadioReference geography entry (a state or county) used to back name-based pickers so operators don't have to know numeric ctid/stid.

type Hint

type Hint struct {
	SID        int
	Name       string
	Reason     string
	Confidence float64
}

Hint is a possible duplicate match between a discovered system and an existing RadioReference system.

func MatchAgainst

func MatchAgainst(c Candidate, existing []System) []Hint

MatchAgainst compares a discovered system against a list of existing RadioReference systems and returns ranked duplicate hints. The strongest signal is a WACN+SYSID match (a P25 system's globally-unique identity); failing that, an overlapping control-channel frequency; failing that, an exact (case-insensitive) name match. Systems that match nothing are omitted.

type SearchHit added in v0.3.6

type SearchHit struct {
	SID    int    `json:"sid"`
	Name   string `json:"name"`
	Type   string `json:"type"`
	County string `json:"county,omitempty"`
	State  string `json:"state,omitempty"`
}

SearchHit is a single trunked system returned by a geography search (zip / county / state). Enrich it with GetFullSystem before importing.

type SiteDetail added in v0.3.6

type SiteDetail struct {
	RFSS            int      `json:"rfss,omitempty"`
	SiteNumber      int      `json:"site_number,omitempty"`
	Description     string   `json:"description,omitempty"`
	County          string   `json:"county,omitempty"`
	ControlChannels []uint32 `json:"control_channels"`
	Frequencies     []uint32 `json:"frequencies"`
}

SiteDetail is one RF site of a trunked system. ControlChannels and Frequencies are in Hz.

type System

type System struct {
	SID      int    // RadioReference system id
	Name     string // system name (sName)
	Type     string // system type (sType), e.g. "Project 25 Phase II"
	SystemID uint16 // decoded SYSID (0 when unknown)
	WACN     uint32 // decoded WACN (0 when unknown)
	// ControlChannels are control-channel frequencies in Hz across the
	// system's sites (best-effort; may be empty if not fetched).
	ControlChannels []uint32
}

System is the subset of a RadioReference trunked-system record this package reads for duplicate detection.

type TalkgroupDetail added in v0.3.6

type TalkgroupDetail struct {
	Dec         uint32 `json:"dec"`
	AlphaTag    string `json:"alpha_tag,omitempty"`
	Description string `json:"description,omitempty"`
	Tag         string `json:"tag,omitempty"`
	Group       string `json:"group,omitempty"`
	Mode        string `json:"mode,omitempty"` // D / A / M
	Encrypted   bool   `json:"encrypted,omitempty"`
}

TalkgroupDetail is one talkgroup of a trunked system, shaped to match the columns trunking.TalkGroup loads from a Trunk Recorder–style CSV.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL