Documentation
¶
Overview ¶
Package webapi is graywolf's REST management API.
@title Graywolf Management API @version 1.0 @description REST API for graywolf configuration and control. @BasePath /api @schemes http
@securityDefinitions.apikey CookieAuth @in header @name Cookie @description Session cookie issued by POST /api/auth/login. @description Swagger 2.0 lacks a native `in: cookie` apiKey @description location, so the spec models the same credential @description as a `Cookie:` request header. Browsers send this @description automatically once the session cookie is set; the @description session cookie is named `graywolf_session`.
Tag-group ordering is applied post-generation by pkg/webapi/docs/cmd/tagify — swag v1.16.x silently drops package- level `@tag.name`/`@tag.description` directives, and swag v2 (RC5) still drops them plus mangles POST/PUT bodies in OpenAPI 3.1 mode, so we stay on v1.16.x and inject the `tags:` array ourselves.
Index ¶
- Constants
- func RegisterIgate(srv *Server, mux *http.ServeMux, toggle func(bool) error, ...)
- func RegisterPackets(srv *Server, mux *http.ServeMux, log *packetlog.Log, ...)
- func RegisterPosition(srv *Server, mux *http.ServeMux, pos *gps.StationPos)
- func RegisterReleaseNotes(srv *Server, mux *http.ServeMux, version string, auth *webauth.AuthStore)
- func RegisterStations(srv *Server, mux *http.ServeMux, cache StationCache)
- func RegisterStationsAutocomplete(srv *Server, mux *http.ServeMux, store MessagesStore, ...)
- func RegisterVersion(srv *Server, mux *http.ServeMux)
- func StripAPIPrefix(path string) (string, bool)
- type ActionsService
- type ChannelReferrersResponse
- type Config
- type IgateSimulationResponse
- type IgateToggleRequest
- type MessagesService
- type MessagesStore
- type PositionDTO
- type Server
- func (s *Server) MessagesReload() <-chan struct{}
- func (s *Server) RegisterRoutes(mux *http.ServeMux)
- func (s *Server) ServeTilesPMTiles(w http.ResponseWriter, r *http.Request)
- func (s *Server) SetAX25Manager(m *ax25conn.Manager)
- func (s *Server) SetActionsService(svc ActionsService)
- func (s *Server) SetAgwReload(ch chan struct{})
- func (s *Server) SetBeaconReload(ch chan struct{})
- func (s *Server) SetBeaconSendNow(fn func(ctx context.Context, id uint32) error)
- func (s *Server) SetDigipeaterReload(ch chan struct{})
- func (s *Server) SetGPSReload(ch chan struct{})
- func (s *Server) SetIgateReload(ch chan struct{})
- func (s *Server) SetIgateStatusFn(fn func() *igate.Status)
- func (s *Server) SetMessagesBotDirectory(dir messages.BotDirectory)
- func (s *Server) SetMessagesReload(ch chan struct{})
- func (s *Server) SetMessagesService(svc MessagesService)
- func (s *Server) SetMessagesStore(store MessagesStore)
- func (s *Server) SetPacketLog(l *packetlog.Log)
- func (s *Server) SetPositionLogReload(ch chan struct{})
- func (s *Server) SetRemoteActions(svc *remoteactions.Service)
- func (s *Server) SetSmartBeaconReload(ch chan struct{})
- func (s *Server) SetTxBackendReload(ch chan struct{})
- func (s *Server) SetUpdatesChecker(c *updatescheck.Checker)
- func (s *Server) UpdatesReloadCh() <-chan struct{}
- type StationCache
- type StationDTO
- type StationPosDTO
- type StatusChannel
- type StatusDTO
- type StatusIgateDTO
- type VersionResponse
- type WeatherDTO
Constants ¶
const DefaultAutocompleteLimit = 25
DefaultAutocompleteLimit is the cap applied when no explicit limit is supplied. Big enough to cover the bot list + a reasonable station-history tail without overwhelming the combobox UI.
Variables ¶
This section is empty.
Functions ¶
func RegisterIgate ¶
func RegisterIgate(srv *Server, mux *http.ServeMux, toggle func(bool) error, status func() *igate.Status)
RegisterIgate installs /api/igate (GET status) and /api/igate/simulation (POST toggle) on mux using Go 1.22+ method-scoped patterns. Both callbacks may be nil, in which case the endpoints return 503. RegisterRoutes intentionally omits /api/igate so this helper owns the path.
Signature shape (mux second) is shared with every out-of-band RegisterXxx in this package — see RegisterPackets, RegisterPosition, RegisterStations. Keep callers consistent.
Operation IDs in the swag annotation blocks below are frozen against constants in pkg/webapi/docs/op_ids.go; `make docs-lint` enforces the correspondence.
func RegisterPackets ¶
func RegisterPackets(srv *Server, mux *http.ServeMux, log *packetlog.Log, posCache gps.PositionCache)
RegisterPackets installs a GET /api/packets handler backed by the supplied packetlog.Log. Server.RegisterRoutes intentionally omits /api/packets so this helper can own the route without triggering a net/http ServeMux duplicate-pattern panic.
Signature shape (mux second) is shared with every out-of-band RegisterXxx in this package — see RegisterPosition, RegisterIgate, RegisterStations. Keep callers consistent.
Operation IDs in the swag annotation blocks below are frozen against constants in pkg/webapi/docs/op_ids.go; `make docs-lint` enforces the correspondence.
func RegisterPosition ¶
func RegisterPosition(srv *Server, mux *http.ServeMux, pos *gps.StationPos)
RegisterPosition installs GET /api/position on the Server's mux using a Go 1.22+ method-scoped pattern.
Signature shape (mux second) is shared with every out-of-band RegisterXxx in this package — see RegisterPackets, RegisterIgate, RegisterStations. Keep callers consistent.
Operation IDs in the swag annotation blocks below are frozen against constants in pkg/webapi/docs/op_ids.go; `make docs-lint` enforces the correspondence.
func RegisterReleaseNotes ¶
RegisterReleaseNotes installs the three release-notes endpoints on apiMux. All three require authentication (apiMux is behind RequireAuth via wiring.go).
- GET /api/release-notes — every note
- GET /api/release-notes/unseen — caller's unseen subset
- POST /api/release-notes/ack — server-authoritative ack
version is the running build version (webapi.Config.Version); auth is the auth store used both for the ack write and for reading the caller's current LastSeenReleaseVersion.
Signature shape (srv, mux, deps...) matches the other out-of-band registrars (RegisterVersion, RegisterPackets, …).
Operation IDs are frozen in pkg/webapi/docs/op_ids.go; docs-lint enforces the correspondence.
func RegisterStations ¶
func RegisterStations(srv *Server, mux *http.ServeMux, cache StationCache)
RegisterStations installs GET /api/stations backed by a StationCache using a Go 1.22+ method-scoped pattern.
Signature shape (mux second) is shared with every out-of-band RegisterXxx in this package — see RegisterPackets, RegisterPosition, RegisterIgate. Keep callers consistent.
Operation IDs in the swag annotation blocks below are frozen against constants in pkg/webapi/docs/op_ids.go; `make docs-lint` enforces the correspondence.
func RegisterStationsAutocomplete ¶
func RegisterStationsAutocomplete( srv *Server, mux *http.ServeMux, store MessagesStore, cache stationcache.StationStore, )
RegisterStationsAutocomplete installs GET /api/stations/autocomplete. Server.RegisterRoutes intentionally omits this route so the wiring layer can register it only after all three sources (bot directory, station cache, messages store) are constructed.
The autocomplete merges three sources in priority order:
- Bot directory (DefaultBotDirectory or server override)
- Station cache hits
- Message history (peers we've previously exchanged messages with)
When the operator hasn't typed anything, the bot group is rendered in full and the station section is capped at emptyInputStationCap most-recent entries. When a prefix is supplied, all three sources contribute matches (case-insensitive prefix) up to the overall limit.
Ranking after merge:
- source=="bot" ahead of everything (always first group)
- source=="cache" (or cache+history) ahead of history-only
- within each group: last_heard DESC
func RegisterVersion ¶
RegisterVersion installs GET /api/version on mux. It is a public endpoint — wiring.go mounts it on the outer mux, not the RequireAuth-wrapped apiMux, because the web UI reads the version before the user is authenticated to decide which screens to show.
Signature shape (srv, mux, deps...) is shared with every out-of-band RegisterXxx in this package — see RegisterIgate, RegisterPackets, RegisterPosition, RegisterStations. The version string itself is sourced from webapi.Config.Version, propagated from cmd-level build flags through pkg/app/wiring.go.
Operation IDs in the swag annotation block below are frozen against constants in pkg/webapi/docs/op_ids.go; `make docs-lint` enforces the correspondence.
func StripAPIPrefix ¶
StripAPIPrefix is a tiny helper for tests and middleware that need to know whether a URL belongs to this package.
Types ¶
type ActionsService ¶ added in v0.13.0
type ActionsService interface {
ReloadListeners(ctx context.Context) error
TestFire(ctx context.Context, a *configstore.Action, args []actions.KeyValue) (actions.Result, uint)
}
ActionsService is the narrow surface the webapi handlers consume from pkg/actions.Service. Listener-addressee mutations call ReloadListeners; the test-fire endpoint calls TestFire.
type ChannelReferrersResponse ¶
type ChannelReferrersResponse struct {
Error string `json:"error,omitempty"`
Referrers []configstore.Referrer `json:"referrers"`
}
ChannelReferrersResponse is the body returned by GET /api/channels/{id}/referrers and by DELETE /api/channels/{id} when referrers exist and cascade is not requested (409 Conflict). The Error field is populated only on the 409 path so the wire shape stays stable between the two endpoints.
type Config ¶
type Config struct {
Store *configstore.Store
Bridge *modembridge.Bridge
KissManager *kiss.Manager
KissCtx context.Context // parent context for dynamically started KISS servers
Logger *slog.Logger
HistoryDBPath string // path to history database, from -history-db flag
Version string // build-time version string reported by GET /api/version
// MapsAuth is the registration client used by
// POST /api/preferences/maps/register. Optional; NewServer
// defaults to a client pointed at mapsauth.DefaultBaseURL when
// nil so production wiring doesn't need to set it explicitly.
// Tests inject a client pointed at an httptest.Server.
MapsAuth *mapsauth.Client
// MapsCache is the PMTiles download/cache manager. Optional —
// the /api/maps/downloads handlers and ServeTilesPMTiles return
// 503 when nil so wiring can defer construction until the cache
// directory is known. Tests inject a Manager pointed at a temp
// dir + httptest upstream.
MapsCache *mapscache.Manager
// Catalog is the download-catalog fetcher. Optional — the
// /api/maps/catalog handler and slug-validation paths return 503
// when nil. Tests inject a Cache pointed at an httptest upstream.
Catalog *mapscatalog.Cache
}
Config bundles the dependencies for NewServer.
type IgateSimulationResponse ¶
type IgateSimulationResponse struct {
SimulationMode bool `json:"simulation_mode"`
}
IgateSimulationResponse is the success body returned by POST /api/igate/simulation. It mirrors the toggled value so clients can confirm the requested state was applied.
type IgateToggleRequest ¶
type IgateToggleRequest struct {
Enabled bool `json:"enabled"`
}
IgateToggleRequest is the POST body for /api/igate/simulation.
type MessagesService ¶
type MessagesService interface {
SendMessage(ctx context.Context, req messages.SendMessageRequest) (*configstore.Message, error)
Resend(ctx context.Context, id uint64) (messages.SendResult, error)
SoftDelete(ctx context.Context, id uint64) error
SoftDeleteThread(ctx context.Context, kind, key string) (int, error)
MarkRead(ctx context.Context, id uint64) error
MarkUnread(ctx context.Context, id uint64) error
ReloadTacticalCallsigns(ctx context.Context) error
ReloadPreferences(ctx context.Context) error
EventHub() *messages.EventHub
}
MessagesService is the narrow surface the webapi handlers consume from pkg/messages.*Service. Kept as an interface so tests can inject a fake and so the webapi package doesn't drag in the router / retry goroutines at import time.
type MessagesStore ¶
type MessagesStore interface {
List(ctx context.Context, f messages.Filter) ([]configstore.Message, string, error)
GetByID(ctx context.Context, id uint64) (*configstore.Message, error)
ConversationRollup(ctx context.Context, limit int) ([]messages.ConversationSummary, error)
ListParticipants(ctx context.Context, tacticalKey string, within time.Duration) ([]messages.Participant, time.Duration, error)
QueryMessageHistoryByPeer(ctx context.Context, prefix string, limit int) ([]messages.MessageHistoryEntry, error)
}
MessagesStore is the narrow read surface the handlers consume for pure queries (list, get, conversations, participants). Wiring passes a *messages.Store directly; tests may swap.
type PositionDTO ¶
type PositionDTO struct {
Valid bool `json:"valid"`
Source string `json:"source"` // "gps", "fixed", or "none"
Latitude float64 `json:"lat,omitempty"`
Longitude float64 `json:"lon,omitempty"`
Altitude float64 `json:"alt_m,omitempty"`
HasAlt bool `json:"has_alt,omitempty"`
Speed float64 `json:"speed_kt,omitempty"`
Heading float64 `json:"heading_deg,omitempty"`
HasCourse bool `json:"has_course,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
}
PositionDTO is the JSON shape returned by GET /api/position.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server routes /api/* requests. It does not own the underlying listener; cmd/graywolf composes it into its main mux.
func NewServer ¶
NewServer constructs a Server. Store is required; Logger defaults to slog.Default().
func (*Server) MessagesReload ¶
func (s *Server) MessagesReload() <-chan struct{}
MessagesReload returns the messages reload channel for wiring's drainer goroutine. Safe to call before SetMessagesReload; nil is returned and the drainer becomes a no-op until the channel is installed.
func (*Server) RegisterRoutes ¶
RegisterRoutes installs the /api/* handlers on mux. Each resource owns its own routes via a registerX method so this stays a short dispatch list.
Out-of-band endpoints are installed by separate helpers that cmd/graywolf calls explicitly after RegisterRoutes:
/api/igate — webapi.RegisterIgate (status + simulation)
/api/packets — webapi.RegisterPackets
/api/position — webapi.RegisterPosition
/api/version — webapi.RegisterVersion (public; mounted on
the outer mux, not the RequireAuth-wrapped
apiMux)
Invariant — apiMux is the sole handler for /api/* on the outer mux (see pkg/app/wiring.go: mux.Handle("/api/", webauth.RequireAuth(apiMux))). Nothing bolts routes onto the outer mux under /api/; everything goes through the mux passed to RegisterRoutes (and to the RegisterXxx out-of-band helpers). Any middleware placed in front of apiMux (today: webauth.RequireAuth) MUST pass through the response status code and all headers — in particular the `Allow` header that Go 1.22's per-mux method-pattern routing generates on a 405 — unchanged. The handler-split work in later phases relies on that 405-with-Allow contract reaching the client; violating it breaks OpenAPI-derived clients that use method-not-allowed as a routing signal.
func (*Server) ServeTilesPMTiles ¶
func (s *Server) ServeTilesPMTiles(w http.ResponseWriter, r *http.Request)
ServeTilesPMTiles is mounted on the OUTER mux (under RequireAuth) in pkg/app/wiring.go because it lives at /tiles/..., outside /api/... http.ServeFile honors the Range header natively, which PMTiles relies on for efficient sub-range fetches of the index + tile blobs.
Catalog membership is intentionally NOT checked here: the slug grammar plus a successful filesystem lookup form the closed set. Otherwise an outage of the maps Worker (catalog endpoint) would brick already-downloaded local archives, which is a regression vs. the previous static-allowlist design.
func (*Server) SetAX25Manager ¶ added in v0.12.4
SetAX25Manager installs the ax25conn session manager wiring constructs. Until this is called the /api/ax25/terminal WebSocket handler returns 503 so an ordering bug in wiring fails loud rather than letting the operator open a session that has nowhere to go.
func (*Server) SetActionsService ¶ added in v0.13.0
func (s *Server) SetActionsService(svc ActionsService)
SetActionsService installs the running Actions subsystem so the listener-addressee handlers can signal a reload after mutations and the test-fire handler can dispatch through the runtime path. Nil until pkg/app wiring sets it; mutating listener handlers skip the reload signal when nil.
func (*Server) SetAgwReload ¶
func (s *Server) SetAgwReload(ch chan struct{})
SetAgwReload installs the channel signalled after a successful AGW config write. Wiring (pkg/app) is expected to drain this channel and restart the AGW TCP server so new ListenAddr / callsign / enabled state takes effect without a graywolf restart.
func (*Server) SetBeaconReload ¶
func (s *Server) SetBeaconReload(ch chan struct{})
SetBeaconReload installs the channel signalled when beacon config is created, updated, or deleted.
func (*Server) SetBeaconSendNow ¶
SetBeaconSendNow installs the callback used by POST /api/beacons/{id}/send to trigger an immediate one-shot transmission of a beacon.
func (*Server) SetDigipeaterReload ¶
func (s *Server) SetDigipeaterReload(ch chan struct{})
SetDigipeaterReload installs the channel signalled after successful digipeater config/rule writes. main.go drains it from a dedicated goroutine that pushes updated state into the running digipeater engine (enabled flag, mycall, dedup window, rules), so changes take effect without a restart. The channel is expected to be buffered (size 1) so signals coalesce under rapid edits.
func (*Server) SetGPSReload ¶
func (s *Server) SetGPSReload(ch chan struct{})
SetGPSReload installs the channel signalled when GPS config is saved.
func (*Server) SetIgateReload ¶
func (s *Server) SetIgateReload(ch chan struct{})
SetIgateReload installs the channel signalled after successful igate config or filter writes, so the running igate can pick up changes without a restart.
func (*Server) SetIgateStatusFn ¶
SetIgateStatusFn installs the function used by /api/status to report igate counters. The callback should return nil when the iGate is currently disabled so the aggregate status omits the field rather than embedding a deceptive Connected=false snapshot.
func (*Server) SetMessagesBotDirectory ¶
func (s *Server) SetMessagesBotDirectory(dir messages.BotDirectory)
SetMessagesBotDirectory overrides the bot directory used by the stations autocomplete endpoint. Useful for tests; production leaves it unset so the package default (messages.DefaultBotDirectory) wins.
func (*Server) SetMessagesReload ¶
func (s *Server) SetMessagesReload(ch chan struct{})
SetMessagesReload installs the channel signalled after a successful messages preferences or tactical-callsign mutation. Wiring (pkg/app) drains this channel and calls Service.ReloadPreferences + Service.ReloadTacticalCallsigns so the router / sender pick up the new snapshot. Buffer size 1 + coalesced non-blocking sends keep rapid edits from stacking. The handlers also call the service's reload methods inline where the new value must be visible before the request returns (e.g. immediately after registering a new tactical label so the next compose classifies it as tactical).
func (*Server) SetMessagesService ¶
func (s *Server) SetMessagesService(svc MessagesService)
SetMessagesService installs the messages service Phase 5 wiring constructed. Until this is called, the messages handlers return 503. The service is optional so tests that don't exercise the messages surface can omit it entirely.
func (*Server) SetMessagesStore ¶
func (s *Server) SetMessagesStore(store MessagesStore)
SetMessagesStore installs the message repository used by pure read handlers (list, get, conversations, participants). When nil the read handlers return 503. Wiring passes a *messages.Store directly.
func (*Server) SetPacketLog ¶ added in v0.12.4
SetPacketLog installs the shared packet ring buffer so the AX.25 terminal raw-tail mode can fan out live decodes. Until this is set the bridge surfaces a typed `raw_tail_unsupported` error envelope.
func (*Server) SetPositionLogReload ¶
func (s *Server) SetPositionLogReload(ch chan struct{})
SetPositionLogReload installs the channel signalled after successful position log config writes.
func (*Server) SetRemoteActions ¶ added in v0.13.0
func (s *Server) SetRemoteActions(svc *remoteactions.Service)
SetRemoteActions installs the outbound-Actions service. Nil disables the /api/remote-actions/* endpoints (they return 503).
func (*Server) SetSmartBeaconReload ¶
func (s *Server) SetSmartBeaconReload(ch chan struct{})
SetSmartBeaconReload installs the channel signalled after a successful PUT /api/smart-beacon. Wiring (pkg/app) is expected to drain this channel and re-run the beacon reload pipeline so new curve parameters take effect without a graywolf restart. Buffer size 1 + coalesced non-blocking sends keep rapid edits from stacking.
func (*Server) SetTxBackendReload ¶
func (s *Server) SetTxBackendReload(ch chan struct{})
SetTxBackendReload installs the channel the Phase 3 dispatcher's watcher drains. Nudged by handlers (and by notifyBridgeReload) on every config change that might alter channel-backing membership so the dispatcher's atomic snapshot re-publishes.
func (*Server) SetUpdatesChecker ¶
func (s *Server) SetUpdatesChecker(c *updatescheck.Checker)
SetUpdatesChecker installs the updates checker post-construction. Called by pkg/app wiring once the checker has been built with the running version and configstore handle. Safe to call before the server starts serving; not safe to call after. Until this is called, GET /api/updates/status returns a synthesized "pending" response rather than panicking.
func (*Server) UpdatesReloadCh ¶
func (s *Server) UpdatesReloadCh() <-chan struct{}
UpdatesReloadCh exposes the updates reload channel to wiring so the checker goroutine can receive on it. The channel itself is owned by the Server (created in NewServer, buffer size 1) so its lifetime matches the request handlers that send on it.
type StationCache ¶
type StationCache interface {
stationcache.StationStore
Gen() uint64
}
StationCache extends StationStore with the generation counter for ETag support.
type StationDTO ¶
type StationDTO struct {
// Callsign is the station or object name (APRS callsign-SSID for stations, object/item name otherwise).
Callsign string `json:"callsign"`
// IsObject is true for APRS objects and items; false for regular stations.
IsObject bool `json:"is_object,omitempty"`
// SymbolTable is the APRS symbol table character ("/" primary, "\\" alternate, or an overlay char).
SymbolTable string `json:"symbol_table"`
// SymbolCode is the APRS symbol code character within the selected table.
SymbolCode string `json:"symbol_code"`
// Positions is the station's position history, newest first; static stations have exactly one entry.
Positions []StationPosDTO `json:"positions"`
// LastHeard is the UTC RFC3339 timestamp of the most recent packet from this station.
LastHeard time.Time `json:"last_heard"`
// Direction indicates the source of the most recent packet: "RX" (heard on air), "TX" (sent by us), or "IS" (APRS-IS).
Direction string `json:"direction"`
// Via is the callsign of the last digipeater in the most recent packet's H-bit path; empty for direct packets.
Via string `json:"via,omitempty"`
// Path is the raw AX.25 digipeater path from the most recent packet (entries with trailing "*" have the H-bit set).
Path []string `json:"path,omitempty"`
// PathPositions lists [lat, lon] pairs resolved for H-bit digipeaters in Path; zero pair when position is unknown.
PathPositions [][2]float64 `json:"path_positions,omitempty"`
// Hops is the APRS digipeater hop count (number of H-bit entries in Path).
Hops int `json:"hops,omitempty"`
// Channel is the graywolf channel ID that received the most recent packet.
Channel uint32 `json:"channel"`
// Comment is the free-form comment field from the most recent packet.
Comment string `json:"comment"`
// Weather is optional weather telemetry; present only when include=weather is requested and the station reports weather.
Weather *WeatherDTO `json:"weather,omitempty"`
}
StationDTO is one station's wire format for the map.
type StationPosDTO ¶
type StationPosDTO struct {
// Lat is the reported latitude in decimal degrees (WGS84, north positive).
Lat float64 `json:"lat"`
// Lon is the reported longitude in decimal degrees (WGS84, east positive).
Lon float64 `json:"lon"`
// Alt is the reported altitude in meters above mean sea level; omitted when not reported.
Alt float64 `json:"alt_m,omitempty"`
// HasAlt is true when the originating packet reported an altitude.
HasAlt bool `json:"has_alt,omitempty"`
// Speed is the reported ground speed in knots; omitted when not reported.
Speed float64 `json:"speed_kt,omitempty"`
// Course is the reported course over ground in degrees true (0-359); omitted when not reported.
Course *int `json:"course,omitempty"`
// Via is the callsign of the last digipeater (H-bit) that forwarded this position packet; empty for direct.
Via string `json:"via,omitempty"`
// Path is the AX.25 digipeater path recorded with this position fix.
Path []string `json:"path,omitempty"`
// PathPositions lists [lat, lon] pairs resolved for H-bit digipeaters in Path; zero pair when position is unknown.
PathPositions [][2]float64 `json:"path_positions,omitempty"`
// Hops is the APRS digipeater hop count (number of H-bit entries in Path) for this fix.
Hops int `json:"hops,omitempty"`
// Direction indicates the source of this position packet: "RX", "TX", or "IS".
Direction string `json:"direction,omitempty"`
// Channel is the graywolf channel ID that received this position packet.
Channel uint32 `json:"channel,omitempty"`
// Comment is the free-form comment field from this position packet.
Comment string `json:"comment,omitempty"`
// Timestamp is the UTC RFC3339 time the position was received.
Timestamp time.Time `json:"timestamp"`
}
StationPosDTO is a single position fix in the station wire format. Per-position metadata captures the packet context at the time this position was reported (path, via, direction, etc.).
type StatusChannel ¶
type StatusChannel struct {
ID uint32 `json:"id"`
Name string `json:"name"`
ModemType string `json:"modem_type"`
BitRate uint32 `json:"bit_rate"`
RxFrames uint64 `json:"rx_frames"`
RxBadFCS uint64 `json:"rx_bad_fcs"`
TxFrames uint64 `json:"tx_frames"`
DcdState bool `json:"dcd_state"`
AudioPeak float32 `json:"audio_peak"`
InputDeviceID uint32 `json:"input_device_id"`
DevicePeakDBFS float32 `json:"device_peak_dbfs"`
DeviceRmsDBFS float32 `json:"device_rms_dbfs"`
DeviceClipping bool `json:"device_clipping"`
}
StatusChannel pairs a channel config with its live stats.
type StatusDTO ¶
type StatusDTO struct {
// UptimeSeconds is the server process uptime in whole seconds.
UptimeSeconds int64 `json:"uptime_seconds"`
// Channels is the per-channel live status snapshot (frame counters, audio levels).
Channels []StatusChannel `json:"channels"`
// Igate is the current iGate session state; omitted when no iGate is configured.
Igate *StatusIgateDTO `json:"igate,omitempty"`
}
StatusDTO is the JSON shape returned by GET /api/status.
type StatusIgateDTO ¶
type StatusIgateDTO struct {
// Connected is true while an APRS-IS session is established.
Connected bool `json:"connected"`
// Server is the APRS-IS host:port currently in use (or last attempted).
Server string `json:"server"`
// Callsign is the login callsign-SSID presented to APRS-IS.
Callsign string `json:"callsign"`
// SimulationMode is true when RF->IS uploads are suppressed for testing.
SimulationMode bool `json:"simulation_mode"`
// LastConnected is the UTC RFC3339 timestamp of the most recent successful IS login; omitted if never connected.
LastConnected time.Time `json:"last_connected,omitempty"`
// Gated is the cumulative count of RF packets forwarded to APRS-IS.
Gated uint64 `json:"rf_to_is_gated"`
// Downlinked is the cumulative count of IS packets transmitted on RF.
Downlinked uint64 `json:"is_to_rf_gated"`
// Filtered is the cumulative count of packets dropped by the filter engine.
Filtered uint64 `json:"packets_filtered"`
// DroppedOffline is the cumulative count of RF packets dropped because the IS session was offline.
DroppedOffline uint64 `json:"rf_to_is_dropped"`
}
StatusIgateDTO mirrors igate.Status as an explicit local type so the generated OpenAPI spec does not cross-reference the igate package. This keeps client codegen (e.g. progenitor) from emitting awkward Option<Box<_>> wrappers around an external schema. The JSON wire shape is identical to igate.Status.
type VersionResponse ¶
type VersionResponse struct {
Version string `json:"version"`
// Platform is runtime.GOOS of the server process — "windows", "linux",
// "darwin", etc. The UI uses it to surface platform-specific guidance
// (e.g. the Windows app-volume warning on the Audio Devices page).
Platform string `json:"platform"`
}
VersionResponse is the JSON shape returned by GET /api/version.
type WeatherDTO ¶
type WeatherDTO struct {
// Temperature is the ambient temperature in degrees Fahrenheit; nil when not reported.
Temperature *float64 `json:"temp_f,omitempty"`
// WindSpeed is the sustained wind speed in miles per hour; nil when not reported.
WindSpeed *float64 `json:"wind_mph,omitempty"`
// WindDir is the wind direction in degrees true (0-359); nil when not reported.
WindDir *int `json:"wind_dir,omitempty"`
// WindGust is the peak wind gust in miles per hour; nil when not reported.
WindGust *float64 `json:"gust_mph,omitempty"`
// Humidity is the relative humidity in percent (0-100); nil when not reported.
Humidity *int `json:"humidity,omitempty"`
// Pressure is the barometric pressure in millibars; nil when not reported.
Pressure *float64 `json:"pressure_mb,omitempty"`
// Rain1h is rainfall in the last hour in inches; nil when not reported.
Rain1h *float64 `json:"rain_1h_in,omitempty"`
// Rain24h is rainfall in the last 24 hours in inches; nil when not reported.
Rain24h *float64 `json:"rain_24h_in,omitempty"`
// Snow24h is snowfall in the last 24 hours in inches; nil when not reported.
Snow24h *float64 `json:"snow_24h_in,omitempty"`
// Luminosity is solar radiation in watts per square meter; nil when not reported.
Luminosity *int `json:"luminosity_wm2,omitempty"`
}
WeatherDTO carries optional weather fields as pointers (nil = not reported).
Source Files
¶
- action_invocations.go
- action_listeners.go
- action_test_fire.go
- actions.go
- agw.go
- audio_devices.go
- ax25_profiles.go
- ax25_terminal.go
- ax25_terminal_config.go
- ax25_transcripts.go
- beacons.go
- catalog.go
- catalog_lookup.go
- channels.go
- digipeater.go
- downloads.go
- errors.go
- gps.go
- handlers.go
- igate.go
- igate_config.go
- kiss.go
- maps.go
- messages.go
- messages_config.go
- otp_credentials.go
- packets.go
- position.go
- position_log.go
- ptt.go
- ptt_test_rigctld.go
- release_notes.go
- remote_actions_creds.go
- remote_actions_macros.go
- remote_actions_otp.go
- remote_actions_test_helpers.go
- server.go
- slug.go
- smart_beacon.go
- station_config.go
- stations.go
- stations_autocomplete.go
- status.go
- tacticals.go
- theme.go
- tx_timing.go
- units.go
- updates.go
- version.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package docs holds the frozen operation-ID registry for the webapi package's OpenAPI spec.
|
Package docs holds the frozen operation-ID registry for the webapi package's OpenAPI spec. |
|
cmd/idlint
command
idlint walks pkg/webapi and pkg/webauth, extracts every @ID value appearing in a top-level function's doc comment (via the Go AST — including `/* */` block comments which a plain grep would miss), and asserts that each value is declared as a string constant in pkg/webapi/docs/op_ids.go.
|
idlint walks pkg/webapi and pkg/webauth, extracts every @ID value appearing in a top-level function's doc comment (via the Go AST — including `/* */` block comments which a plain grep would miss), and asserts that each value is declared as a string constant in pkg/webapi/docs/op_ids.go. |
|
cmd/tagify
command
tagify injects a top-level `tags:` array into the swag-generated OpenAPI 2.0 spec so Swagger UI and downstream generators can render tag groups in a deliberate, curated order instead of alphabetical.
|
tagify injects a top-level `tags:` array into the swag-generated OpenAPI 2.0 spec so Swagger UI and downstream generators can render tag groups in a deliberate, curated order instead of alphabetical. |
|
Package dto: actions resource shapes.
|
Package dto: actions resource shapes. |