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
- Variables
- func EffectiveAppKey(explicit string) string
- type Account
- type Auth
- type Candidate
- type Client
- func (c *Client) GetCountyInfo(ctx context.Context, ctid int) ([]System, error)
- func (c *Client) GetCountyList(ctx context.Context, stid int) ([]GeoRef, error)
- func (c *Client) GetFullSystem(ctx context.Context, sid int) (FullSystem, error)
- func (c *Client) GetStateList(ctx context.Context) ([]GeoRef, error)
- func (c *Client) GetTrsDetails(ctx context.Context, sid int) (System, error)
- func (c *Client) SearchByCounty(ctx context.Context, ctid int) ([]SearchHit, error)
- func (c *Client) SearchByState(ctx context.Context, stid int) ([]SearchHit, error)
- func (c *Client) SearchByZip(ctx context.Context, zip string) ([]SearchHit, error)
- func (c *Client) SetEndpoint(url string)
- func (c *Client) SetHTTPClient(h *http.Client)
- func (c *Client) VerifyCredentials(ctx context.Context) (Account, error)
- type FullSystem
- type GeoRef
- type Hint
- type SearchHit
- type SiteDetail
- type System
- type TalkgroupDetail
Constants ¶
const DefaultEndpoint = "http://api.radioreference.com/soap2/"
DefaultEndpoint is the RadioReference SOAP web-service endpoint (v3.1).
Variables ¶
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.
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.
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
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
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 ¶
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 ¶
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 ¶
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
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
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
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 ¶
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
SearchByCounty lists the trunked systems registered in a RadioReference county (by ctid).
func (*Client) SearchByState ¶ added in v0.3.6
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
SearchByZip resolves a US ZIP code to its county, then lists the trunked systems registered in that county.
func (*Client) SetEndpoint ¶
SetEndpoint overrides the SOAP endpoint (used by tests).
func (*Client) SetHTTPClient ¶
SetHTTPClient overrides the HTTP client (used by tests).
func (*Client) VerifyCredentials ¶ added in v0.3.7
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
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 ¶
Hint is a possible duplicate match between a discovered system and an existing RadioReference system.
func MatchAgainst ¶
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.