gpsprot

package
v0.0.0-...-f5f1695 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const GLOUnknown uint8 = 0 // with GLONASS FDMA, it is possible to be tracking a satellite but not know its PRN
View Source
const MaxSpareGLONASS = 8

There are 24 operational GLONASS satellites with slot numbers 1 to 24. But there can be others that are spares or in testing. See https://glonass-iac.ru/en/sostavOG which is referenced by https://files.igs.org/pub/resource/working_groups/multi_gnss/Metadata_SINEX_1.10.pdf So it is possible to have satellite numbers for GLONASS > 24. Maximum number of spares there has ever been is 3. NMEA allows up to 8 which would imply a total of 32 slots. This matches the use of 5 bits for slot number in the GLONASS ICD, so it seems like a sensible upper limit.

Variables

View Source
var ErrNotHandled = errors.New("sentence not handled")

ErrNotHandled is returned by ExtSentenceHandler.HandleSentence when the handler does not recognize the sentence.

Functions

func DispatchMsgs

func DispatchMsgs(msgs []Msg, h MsgHandler, tRead time.Time)

DispatchMsgs dispatches each message to the handler.

func IsValidPacket

func IsValidPacket(pf PacketFormat, buf []byte) bool

IsValidPacket says whether the given buffer is a valid packet in the given PacketFormat. It uses only the Next method on PacketFormat. It does not validate the checksum.

func SetAllMsgHandlers

func SetAllMsgHandlers(pps map[Tag]PacketProcessor, handler MsgHandler)

SetAllMsgHandlers sets handler on every PacketProcessor in the map.

func SetMsgsPriority

func SetMsgsPriority(msgs []Msg, pri MsgPriority)

SetMsgsPriority sets priority on all PVMsg messages in the slice.

Types

type Accuracy

type Accuracy struct {
	Pos         opt.Val[Length] `json:"pos,omitzero"`         // 3D position accuracy
	Hor         opt.Val[Length] `json:"hor,omitzero"`         // horizontal position accuracy
	Vert        opt.Val[Length] `json:"vert,omitzero"`        // vertical position accuracy
	Speed       opt.Val[Speed]  `json:"speed,omitzero"`       // 3D speed accuracy
	GroundSpeed opt.Val[Speed]  `json:"groundSpeed,omitzero"` // 2D ground speed accuracy
	Course      opt.Val[Angle]  `json:"course,omitzero"`      // course/heading accuracy
}

Accuracy holds estimated accuracy of the navigation solution. Fields are opt.Val because different protocols provide different subsets. Accuracy may be synthesized from multiple messages within an epoch.

func (*Accuracy) Fill

func (a *Accuracy) Fill(other *Accuracy)

Fill sets any unset fields in a from the corresponding fields in other.

type AltChecksumPacketFormat

type AltChecksumPacketFormat interface {
	PacketFormat
	// ComputeChecksum computes an alternate checksum for the given packet
	// Precondition: the packet must be valid according to Next()
	ComputeAltChecksum(pkt []byte) []byte
}

AltChecksumPacketFormat provides an alternate method for computing the checksum, which can be used to work around firmware quirks. For examplem, on the Unicore UM980, the checksum for NMEA-like packets used for configuration responses computes the checksum over the packet including the leading $ (normal NMEA checksums exclude the $). ComputeAltChecksum in this case can detect when it might be one of these packets and return the checksum including the leading $.

type Angle

type Angle int64

Angle represents an angle in nanodegrees.

const (
	Nanodegrees  Angle = 1
	Microdegrees Angle = 1000 * Nanodegrees
	Millidegrees Angle = 1000 * Microdegrees
	Degrees      Angle = 1000 * Millidegrees
)

func DegreesFromFloat

func DegreesFromFloat(f float64) Angle

DegreesFromFloat creates an Angle from a float64 value in degrees.

func ParseAngle

func ParseAngle(s string) (Angle, error)

ParseAngle parses a string as an angle in degrees.

func (Angle) Degrees

func (a Angle) Degrees() float64

Degrees returns the angle in degrees as a float64.

func (Angle) MarshalJSON

func (a Angle) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (Angle) MarshalText

func (a Angle) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (Angle) String

func (a Angle) String() string

func (*Angle) UnmarshalJSON

func (a *Angle) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

func (*Angle) UnmarshalText

func (a *Angle) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type AuxSrc

type AuxSrc uint8

AuxSrc is a bitmask of additional data sources that contributed to the navigation solution. GNSS contribution is implicit when FixLevel indicates a GNSS-based fix.

const (
	AuxSrcDR  AuxSrc = 1 << iota // dead reckoning (e.g. wheel ticks, motion model)
	AuxSrcINS                    // inertial navigation system
)

func (AuxSrc) Items

func (a AuxSrc) Items() []string

Items returns the names of the set bits as a string slice.

func (AuxSrc) MarshalJSON

func (a AuxSrc) MarshalJSON() ([]byte, error)

func (AuxSrc) String

func (a AuxSrc) String() string

type Band

type Band uint16
const (
	BandL1      Band = Band((1 << sigIndexL1Legacy) | (1 << sigIndexL1Modern) | (1 << sigIndexL1Augment)) // 1575.42 - 1609 MHz, 1559-1610
	BandL2      Band = Band((1 << sigIndexL2Legacy) | (1 << sigIndexL2Modern))                            // 1227.60 - 1252 MHz, 1215-1252
	BandL5      Band = Band((1 << sigIndexL5) | (1 << sigIndexL5Augment))                                 // 1176.45 MHz, 1164-1210
	BandE5b     Band = Band((1 << sigIndexE5b) | (1 << sigIndexE5bAugment))                               // 1202.025 - 1207.14 MHz, 1164-1210
	BandE6      Band = Band((1 << sigIndexE6) | (1 << sigIndexE6Augment))                                 // 1268.52 - 1278.75 MHz, 1260-1300
	BandAll     Band = Band((1 << sigIndexCount) - 1)
	BandAugment Band = Band((1 << sigIndexL1Augment) | (1 << sigIndexL5Augment) | (1 << sigIndexE5bAugment) | (1 << sigIndexE6Augment)) // 1559-1610, 1164-1210, 1260-1300
)

E5b and L5 could be considered the same band: you can | them together to represent this I prefer to keep L5 for just 1176.45 MHz, and then use E5b (for lack of a better name) for the rest

func (Band) SignalSet

func (b Band) SignalSet(gs ...GNSS) SignalSet

SignalSet returns the set of signals for a given GNSS in the Band.

type ConfigAction

type ConfigAction struct {
	Type     ConfigActionType
	Index    int       // Request index for Send actions
	Packet   []byte    // Packet to send for SendRequest action
	Speed    int       // Speed change after send (0 if none)
	Deadline time.Time // Deadline for WaitUntil actions
	Error    error     // Error details for Error action
}

ConfigAction represents an action the client should take during configuration.

type ConfigActionType

type ConfigActionType int

ConfigActionType specifies the type of action the client should take.

const (
	// ConfigActionSendRequest means the client should send a configuration packet.
	ConfigActionSendRequest ConfigActionType = iota

	// ConfigActionWaitUntil means the client should wait until the specified deadline.
	ConfigActionWaitUntil

	// ConfigActionError means a configuration error occurred.
	ConfigActionError
)

type ConfigDirector

type ConfigDirector struct {
	ErrorCount int // Number of ConfigActionError actions yielded
	// contains filtered or unexported fields
}

ConfigDirector coordinates configuration operations by providing high-level actions to clients. It wraps a Configurator to provide: - Automatic retry management - Request windowing for efficient batching - Simplified client interface via ConfigAction instructions - Protocol-independent orchestration logic

The same ConfigDirector can be used by both production code (gpscfg) and test code (replayer), ensuring consistent behavior and eliminating duplicate logic.

func NewConfigDirector

func NewConfigDirector(cfgtor Configurator, maxRetries int) *ConfigDirector

NewConfigDirector creates a new ConfigDirector for the given Configurator. maxRetries specifies the maximum number of retry attempts for timed-out requests.

func (*ConfigDirector) Actions

func (cd *ConfigDirector) Actions() iter.Seq[ConfigAction]

Actions returns an iterator over configuration actions. The iterator yields ConfigAction instructions that the client should execute. The iterator ends when configuration is complete or fatally fails.

The ConfigDirector manages an "active window" of requests to enable efficient batching and retry handling. It examines request states and determines the next action without executing the actions itself.

func (*ConfigDirector) AdvanceTimeTo

func (cd *ConfigDirector) AdvanceTimeTo(t time.Time)

AdvanceTimeTo updates the ConfigDirector's current time and automatically processes timeouts. This method should be called by clients to update the director's time reference. Time cannot go backwards - this will panic if t is before the current time.

func (*ConfigDirector) ValidPacketReceived

func (cd *ConfigDirector) ValidPacketReceived(t time.Time)

ValidPacketReceived should be called when a packet with valid checksum is received. It notifies requests that may be able to use this as confirmation of a speed change.

type ConfigOptions

type ConfigOptions struct {
	Socket     bool                  // connected via socket, skip serial detection
	ForceProbe bool                  // force probe even when no config changes needed
	Save       SaveType              // what to save to non-volatile memory
	Reset      ResetType             // what kind of reset to perform
	PVTMsg     PVTMsgFlags           // messages relating to Position, Velocity, and Time
	NMEAMsg    opt.Val[NMEAMsgFlags] `json:",omitzero"`
	RTCMMsg    opt.Val[RTCMMsgFlags] `json:",omitzero"` // RTCM 3.x messages
	SatsMsg    opt.Val[SatsMsgFlags] `json:",omitzero"`
	RawMsg     opt.Val[RawMsgFlags]  `json:",omitzero"`
	Survey     Survey
	SetStatic  bool         // ensure receiver is in static mode without changing existing fixed position
	BaudRate   uint32       // serial port baud rate, 0 means do not change
	TimeAssist TimeEstimate // provide time assistance to the receiver
	OSNMA      OSNMAOptions // options for OSNMA authentication
}

func (*ConfigOptions) EnablesMsgs

func (o *ConfigOptions) EnablesMsgs() bool

func (ConfigOptions) NoOp

func (o ConfigOptions) NoOp() bool

func (*ConfigOptions) SetsMsgs

func (o *ConfigOptions) SetsMsgs() bool

type ConfigProps

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

ConfigProps represents a collection configuration properties

func (*ConfigProps) CopyFrom

func (cp *ConfigProps) CopyFrom(other *ConfigProps)

CopyFrom copies the properties in other to this ConfigProps. Properties that are not set in other are unchanged in cp.

func (*ConfigProps) GetAntennaCableDelay

func (cp *ConfigProps) GetAntennaCableDelay() (time.Duration, bool)

GetAntennaCableDelay returns the antennaCableDelay value and whether it's set

func (*ConfigProps) GetMinElevation

func (cp *ConfigProps) GetMinElevation() (Angle, bool)

GetMinElevation returns the minElevation value and whether it's set

func (*ConfigProps) GetMode

func (cp *ConfigProps) GetMode() (Mode, bool)

GetMode returns the mode value and whether it's set

func (*ConfigProps) GetNavMsgAuth

func (cp *ConfigProps) GetNavMsgAuth() (NavMsgAuth, bool)

GetNavMsgAuth returns the navMsgAuth value and whether it's set

func (*ConfigProps) GetRTCMBaseID

func (cp *ConfigProps) GetRTCMBaseID() (uint16, bool)

GetRTCMBaseID returns the rtcmBaseID value and whether it's set

func (*ConfigProps) GetSignalsEnabled

func (cp *ConfigProps) GetSignalsEnabled() (SignalSet, bool)

GetSignalsEnabled returns the signalsEnabled value and whether it's set

func (*ConfigProps) GetTimeGNSS

func (cp *ConfigProps) GetTimeGNSS() (GNSS, bool)

GetTimeGNSS returns the timeGNSS value and whether it's set

func (*ConfigProps) GetTimePulse

func (cp *ConfigProps) GetTimePulse() (TimePulse, bool)

GetTimePulse returns the entire TimePulse struct and whether all TimePulse properties are set

func (*ConfigProps) GetTimePulseAlignToGNSS

func (cp *ConfigProps) GetTimePulseAlignToGNSS() (bool, bool)

GetTimePulseAlignToGNSS returns the timePulseAlignToGNSS value and whether it's set

func (*ConfigProps) GetTimePulseOnlyWhenLocked

func (cp *ConfigProps) GetTimePulseOnlyWhenLocked() (bool, bool)

GetTimePulseOnlyWhenLocked returns the timePulseOnlyWhenLocked value and whether it's set

func (*ConfigProps) GetTimePulsePeriod

func (cp *ConfigProps) GetTimePulsePeriod() (time.Duration, bool)

GetTimePulsePeriod returns the timePulsePeriod value and whether it's set

func (*ConfigProps) GetTimePulsePolarityRising

func (cp *ConfigProps) GetTimePulsePolarityRising() (bool, bool)

GetTimePulsePolarityRising returns the timePulsePolarityRising value and whether it's set

func (*ConfigProps) GetTimePulseWidth

func (cp *ConfigProps) GetTimePulseWidth() (time.Duration, bool)

GetTimePulseWidth returns the timePulseWidth value and whether it's set

func (*ConfigProps) Inconsistent

func (cp *ConfigProps) Inconsistent(other *ConfigProps) *ConfigProps

Inconsistent returns a ConfigProps with entries in other that are inconsistent with this one. An entry is inconsistent if it exists in both ConfigProps but has different values.

func (*ConfigProps) IsEmpty

func (cp *ConfigProps) IsEmpty() bool

IsEmpty returns true if no properties are set

func (*ConfigProps) MarshalJSON

func (cp *ConfigProps) MarshalJSON() ([]byte, error)

MarshalJSON marshals the config properties to JSON

func (*ConfigProps) MarshalText

func (cp *ConfigProps) MarshalText() ([]byte, error)

MarshalText marshals the config properties to text

func (*ConfigProps) Missing

func (cp *ConfigProps) Missing(other *ConfigProps) *ConfigProps

Missing returns a ConfigProps with entries from other that are missing from this one. An entry is missing if it exists in other but not in this ConfigProps.

func (*ConfigProps) SetAntennaCableDelay

func (cp *ConfigProps) SetAntennaCableDelay(val time.Duration)

SetAntennaCableDelay sets the antennaCableDelay value

func (*ConfigProps) SetMinElevation

func (cp *ConfigProps) SetMinElevation(val Angle)

SetMinElevation sets the minElevation value

func (*ConfigProps) SetMode

func (cp *ConfigProps) SetMode(val Mode)

SetMode sets the mode value

func (*ConfigProps) SetNavMsgAuth

func (cp *ConfigProps) SetNavMsgAuth(val NavMsgAuth)

SetNavMsgAuth sets the navMsgAuth value

func (*ConfigProps) SetPPS

func (cp *ConfigProps) SetPPS(width time.Duration)

SetPPS configures the properties for a pulse-per-second output

func (*ConfigProps) SetRTCMBaseID

func (cp *ConfigProps) SetRTCMBaseID(val uint16)

SetRTCMBaseID sets the rtcmBaseID value

func (*ConfigProps) SetSignalsEnabled

func (cp *ConfigProps) SetSignalsEnabled(val SignalSet)

SetSignalsEnabled sets the signalsEnabled value

func (*ConfigProps) SetTimeGNSS

func (cp *ConfigProps) SetTimeGNSS(val GNSS)

SetTimeGNSS sets the timeGNSS value

func (*ConfigProps) SetTimePulse

func (cp *ConfigProps) SetTimePulse(tp TimePulse)

SetTimePulse sets all timePulse properties at once

func (*ConfigProps) SetTimePulseAlignToGNSS

func (cp *ConfigProps) SetTimePulseAlignToGNSS(val bool)

SetTimePulseAlignToGNSS sets the timePulseAlignToGNSS value

func (*ConfigProps) SetTimePulseOnlyWhenLocked

func (cp *ConfigProps) SetTimePulseOnlyWhenLocked(val bool)

SetTimePulseOnlyWhenLocked sets the timePulseOnlyWhenLocked value

func (*ConfigProps) SetTimePulsePeriod

func (cp *ConfigProps) SetTimePulsePeriod(val time.Duration)

SetTimePulsePeriod sets the timePulsePeriod value

func (*ConfigProps) SetTimePulsePolarityRising

func (cp *ConfigProps) SetTimePulsePolarityRising(val bool)

SetTimePulsePolarityRising sets the timePulsePolarityRising value

func (*ConfigProps) SetTimePulseWidth

func (cp *ConfigProps) SetTimePulseWidth(val time.Duration)

SetTimePulseWidth sets the timePulseWidth value

func (*ConfigProps) SetsAny

func (cp *ConfigProps) SetsAny(props ...PropIDs) bool

SetsAny returns true if any of the specified properties are set in the ConfigProps

func (*ConfigProps) String

func (cp *ConfigProps) String() string

String returns a string representation of the configuration

func (*ConfigProps) UnmarshalJSON

func (cp *ConfigProps) UnmarshalJSON(data []byte) error

UnmarshalJSON deserializes a JSON map into ConfigProps. Each key present in the map calls the corresponding setter. Keys absent from the map leave properties unchanged.

type ConfigProtocol

type ConfigProtocol interface {
	NativeMsgHandler

	// ProbePacket returns a packet to be sent to the GPS receiver for probing.
	ProbePacket() []byte

	// ProbeOK returns true when a message has been received indicating the GPS receiver is responding.
	ProbeOK() bool

	// Configure creates a Configurator for the given configuration target.
	// The returned Configurator will receive packets via NativeMsg calls on this ConfigProtocol.
	Configure(target *ConfigTarget) (Configurator, error)
}

ConfigProtocol manages the processing and generation of packets for a GPS receiver, replacing the old PacketExchanger interface with improved multi-format support.

Methods do not send or receive packets themselves. ConfigProtocol embeds NativeMsgHandler to process protocol-specific messages directly.

type ConfigRequest

type ConfigRequest interface {
	// GetPacket returns the packet bytes for this request.
	// Precondition: request state is ConfigRequestReadyToSend, ConfigRequestMayResend, or ConfigRequestFailed
	// The returned packet is ready to transmit to the GPS receiver without modification.
	// For ConfigRequestMayResend and ConfigRequestFailed states, this is useful for error reporting.
	GetPacket() []byte

	// GetSpeedChangeAfter returns the new baud rate to configure after sending this request.
	// Precondition: request state is ConfigRequestReadyToSend, ConfigRequestMayResend, or ConfigRequestFailed
	// Returns 0 if no speed change is required.
	// Speed changes are protocol-specific operations that must be handled by the client
	// after the packet is sent but before waiting for acknowledgment.
	GetSpeedChangeAfter() int

	// GetState returns the current state of this request.
	// This is the primary method for tracking configuration progress.
	GetState() ConfigRequestState

	// GetDeadline returns the absolute time by which response packets are expected.
	// Precondition: request state is ConfigRequestAwaitingResponse, ConfigRequestMaybeComplete, or ConfigRequestPausing
	// The returned time is non-zero and includes monotonic time for accurate timeout comparisons.
	// For ConfigRequestAwaitingResponse: deadline for receiving first/only response (based on SetSentTime timestamp)
	// For ConfigRequestMaybeComplete: deadline for receiving next response in burst (based on last response time + idle period)
	// For ConfigRequestPausing: deadline for when pause completes and GPS receiver is ready for next command
	GetDeadline() time.Time

	// GetError returns the error details for a failed request.
	// Precondition: request state is ConfigRequestFailed
	// Error details may include protocol-specific failure reasons, NACK codes, or timeout information.
	// The caller should use this error for logging, user feedback, or determining recovery strategies.
	GetError() error

	// SetSentTime records when the request packet was transmitted to the GPS receiver.
	// Precondition: request state is ConfigRequestReadyToSend or ConfigRequestMayResend
	// State transitions:
	//   - ConfigRequestReadyToSend → ConfigRequestAwaitingResponse (if response expected)
	//   - ConfigRequestReadyToSend → ConfigRequestSucceeded (if no response expected)
	//   - ConfigRequestMayResend → ConfigRequestAwaitingResponse (retry)
	// The timestamp is used for timeout calculations and protocol timing requirements.
	SetSentTime(tSent time.Time)

	// SetDeadlinePassed notifies that the response deadline has passed.
	// Precondition: request state is ConfigRequestAwaitingResponse, ConfigRequestMaybeComplete, or ConfigRequestPausing
	// State transitions:
	//   - ConfigRequestAwaitingResponse → ConfigRequestMayResend (timeout, can retry)
	//   - ConfigRequestMaybeComplete → ConfigRequestSucceeded (idle period over, no more responses expected)
	//   - ConfigRequestPausing → ConfigRequestSucceeded (pause duration elapsed, ready for next request)
	// The client should call this when GetDeadline() time has passed.
	SetDeadlinePassed()

	// SetWontResend marks a request as permanently failed because the client decides not to retry.
	// Precondition: request state is ConfigRequestMayResend
	// State transitions:
	//   - ConfigRequestMayResend → ConfigRequestFailed
	// This should be called when the client decides not to retry a timed-out request,
	// typically after reaching a maximum retry count.
	SetWontResend()

	// MaybeSpeedChangeSucceeded notifies the request that a valid packet was received at the given time.
	// Precondition: request state is ConfigRequestAwaitingResponse
	// State transitions:
	//   - ConfigRequestAwaitingResponse → ConfigRequestSucceeded (if conditions met)
	// The request will check if it's a speed change awaiting ACK and if sufficient time has passed
	// since sending to treat this as confirmation of success.
	MaybeSpeedChangeSucceeded(validPacketTime time.Time)
}

ConfigRequest represents a configuration request with state-based lifecycle management. Each request encapsulates both the request data and its execution state.

State Transitions: - Client-initiated transitions occur via Set* method calls - Automatic transitions occur from packet processing within the Configurator - See ConfigRequestState documentation for detailed state semantics

Automatic state transitions from packet processing:

  • ConfigRequestAwaitingResponse → ConfigRequestMaybeComplete (first of multiple responses received)
  • ConfigRequestAwaitingResponse → ConfigRequestSucceeded (complete response received)
  • ConfigRequestAwaitingResponse → ConfigRequestPausing (acknowledgment received, pause required)
  • ConfigRequestAwaitingResponse → ConfigRequestFailed (negative acknowledgment received)

All precondition failures result in panics. All Get* methods are side-effect free.

type ConfigRequestState

type ConfigRequestState int

ConfigRequestState represents the current state of a configuration request. States are either actionable (client can/should take action) or not: - Actionable: ReadyToSend, AwaitingResponse, MaybeComplete, Pausing, MayResend - Not actionable: NotReady, Succeeded, Failed, Skipped

const (
	// ConfigRequestNotReady means this request cannot be sent yet because
	// some earlier requests are not yet in the Succeeded state.
	// GenerateRequests may transition requests from this state to ReadyToSend.
	ConfigRequestNotReady ConfigRequestState = iota

	// ConfigRequestReadyToSend means this request is ready to be sent to the GPS receiver.
	ConfigRequestReadyToSend

	// ConfigRequestAwaitingResponse means the request has been sent and the Configurator
	// is expecting to receive one or more packets in response from the receiver.
	ConfigRequestAwaitingResponse

	// ConfigRequestMaybeComplete means the request has received at least one response packet
	// and may be waiting for more. This state is used for queries that can produce multiple
	// response packets where the total number is not known in advance. The request will
	// transition to Succeeded when the response deadline passes without new responses.
	ConfigRequestMaybeComplete

	// ConfigRequestPausing means the request received its acknowledgment/response and is
	// waiting for a protocol-specified pause duration before the next request can be sent.
	ConfigRequestPausing

	// ConfigRequestSucceeded means the request completed successfully.
	// This is a terminal state - the request will never transition to another state.
	ConfigRequestSucceeded

	// ConfigRequestMayResend means the request timed out waiting for a response and is
	// eligible for retry. The client must decide whether to retry (via SetSentTime)
	// or abandon (via SetWontResend).
	ConfigRequestMayResend

	// ConfigRequestFailed means the request was sent but did not succeed and cannot be retried.
	// This is a terminal state - the request will never transition to another state.
	ConfigRequestFailed

	// ConfigRequestSkipped means this request was skipped because an earlier request did not succeed.
	// GenerateRequests may transition requests from this state to ReadyToSend.
	// This is a terminal state - the request will never transition to another state.
	ConfigRequestSkipped
)

type ConfigTarget

type ConfigTarget struct {
	Props ConfigProps
	Get   PropIDs // Bitmask of properties to retrieve
	Opts  ConfigOptions
}

ConfigTarget represents configuration target settings

func NewConfigTarget

func NewConfigTarget() *ConfigTarget

func (*ConfigTarget) NoOp

func (ct *ConfigTarget) NoOp() bool

NoOp says whether the target is a no-op, except possibly for detecting the receiver

func (*ConfigTarget) UsesAny

func (ct *ConfigTarget) UsesAny(props ...PropIDs) bool

type Configurator

type Configurator interface {
	// ConfigProps returns the current configuration of the GPS receiver.
	// Should be called after configuration completes to see what was achieved.
	ConfigProps() *ConfigProps

	// ReceiverInfo returns static information about the GPS receiver.
	ReceiverInfo() *ReceiverInfo

	// GenerateRequests attempts to generate more requests, potentially increasing the slice size.
	// This is the only method that can increase the slice size.
	// May also change states of existing requests (see ConfigRequestState documentation).
	// Generation is lazy - it may generate only some requests if later requests depend on earlier results.
	// After successful return, either some request will be actionable or GetRequestCount will return complete=true.
	// Should be called when the client needs more requests than are currently available.
	// Returns an error if request generation fails.
	GenerateRequests() error

	// GetRequestCount returns the current number of requests and whether the slice is complete.
	// When bool is true, the slice count will never increase.
	// When bool is false, the slice count may increase after calling GenerateRequests().
	GetRequestCount() (count int, complete bool)

	// Request returns the ConfigRequest at the given index.
	// Precondition: index < count from GetRequestCount()
	// Panics if index is out of bounds.
	Request(index int) ConfigRequest
}

Configurator manages the generation and interpretation of configuration-related packets.

The Configurator maintains a slice of ConfigRequest instances, each with its own state. It can generate additional requests lazily and modify existing request states. It processes incoming packets to automatically update request states. Configurators are time-agnostic: they never call time.Now() or track wall clock time. All time progression happens through client method calls, ensuring deterministic testability.

type CorrKind

type CorrKind uint16

CorrKind is a bitmask of assertions about corrections applied in the navigation solution. The zero value means "no correction assertions".

The Corr* bits are not necessarily orthogonal; they are related by a partial order. When you assert a more specific fact, you must also assert the more general facts it implies.

Partial order definition: A <= B means asserting A implies asserting B.

Ordering (immediate implications):

CorrOSR <= CorrUsed
CorrSSR <= CorrUsed
CorrRTCM <= CorrUsed
CorrPartialDualFreq <= CorrOSR
CorrFullDualFreq <= CorrPartialDualFreq
CorrSBAS <= CorrSSR
CorrCLAS <= CorrSSR
CorrSPARTN <= CorrSSR
CorrPPP <= CorrSSR
CorrPPPRTK <= CorrPPP
CorrPPPConverging <= CorrPPP
CorrPPPConverged <= CorrPPP
CorrPPPHAS <= CorrPPP
CorrPPPMDC <= CorrPPP
CorrPPPB2b <= CorrPPP
const (
	// CorrUsed asserts that external corrections are applied.
	CorrUsed CorrKind = 1 << iota

	// CorrOSR asserts observation-space (OSR) corrections: base/network
	// referenced, such as RTK or network RTK. CorrOSR <= CorrUsed.
	CorrOSR

	// CorrSSR asserts state-space (SSR) corrections: wide-area/broadcast
	// not tied to a local base station, such as SBAS, PPP, CLAS, SPARTN.
	// CorrSSR <= CorrUsed.
	CorrSSR

	// CorrRTCM asserts that corrections being applied are delivered/packaged as RTCM.
	// CorrRTCM <= CorrUsed.
	CorrRTCM

	// CorrPartialDualFreq asserts an OSR solution using partial dual-frequency
	// ambiguity resolution (e.g. wide-lane). CorrPartialDualFreq <= CorrOSR.
	CorrPartialDualFreq

	// CorrFullDualFreq asserts an OSR solution using full dual-frequency
	// ambiguity resolution (e.g. narrow-lane, ionosphere-free).
	// CorrFullDualFreq <= CorrPartialDualFreq.
	CorrFullDualFreq

	// CorrSBAS asserts SSR corrections from SBAS. CorrSBAS <= CorrSSR.
	CorrSBAS

	// CorrCLAS asserts SSR corrections from CLAS. CorrCLAS <= CorrSSR.
	CorrCLAS

	// CorrSPARTN asserts SSR corrections from SPARTN. CorrSPARTN <= CorrSSR.
	CorrSPARTN

	// CorrPPP asserts SSR corrections from a PPP-class service (standalone
	// absolute solution with convergence). CorrPPP <= CorrSSR.
	CorrPPP

	// CorrPPPRTK asserts PPP-RTK/SSR-RTK corrections enabling rapid
	// ambiguity resolution. CorrPPPRTK <= CorrPPP.
	CorrPPPRTK

	// CorrPPPConverging asserts a PPP solution that is still converging.
	// CorrPPPConverging <= CorrPPP.
	CorrPPPConverging

	// CorrPPPConverged asserts a converged PPP solution.
	// CorrPPPConverged <= CorrPPP.
	CorrPPPConverged

	// CorrPPPHAS asserts PPP corrections from Galileo HAS.
	// CorrPPPHAS <= CorrPPP.
	CorrPPPHAS

	// CorrPPPMDC asserts PPP corrections from QZSS MADOCA.
	// CorrPPPMDC <= CorrPPP.
	CorrPPPMDC

	// CorrPPPB2b asserts PPP corrections from BeiDou B2b.
	// CorrPPPB2b <= CorrPPP.
	CorrPPPB2b
)

func (CorrKind) Expand

func (c CorrKind) Expand() CorrKind

Close returns c with all implied bits set according to the partial order. For example, CorrSBAS.Expand() returns CorrSBAS|CorrSSR|CorrUsed.

func (CorrKind) MarshalJSON

func (c CorrKind) MarshalJSON() ([]byte, error)

func (CorrKind) String

func (c CorrKind) String() string

func (*CorrKind) UnmarshalJSON

func (c *CorrKind) UnmarshalJSON(data []byte) error

type DOP

type DOP struct {
	Geom opt.Val[float64] `json:"geom,omitzero"` // geometric DOP
	Pos  opt.Val[float64] `json:"pos,omitzero"`  // position (3D) DOP
	Hor  opt.Val[float64] `json:"hor,omitzero"`  // horizontal DOP
	Vert opt.Val[float64] `json:"vert,omitzero"` // vertical DOP
	Time opt.Val[float64] `json:"time,omitzero"` // time DOP
}

DOP holds dilution of precision values for the navigation solution. Fields are opt.Val because different protocols provide different subsets. DOP may be synthesized from multiple messages within an epoch (e.g. UBX-NAV-DOP provides all five, while NMEA GSA provides only PDOP/HDOP/VDOP).

func (*DOP) Fill

func (d *DOP) Fill(other *DOP)

Fill sets any unset fields in d from the corresponding fields in other.

type DefaultHandler

type DefaultHandler struct{}

func (*DefaultHandler) LeapSecond

func (h *DefaultHandler) LeapSecond(msg *LeapSecondMsg, tRead time.Time)

func (*DefaultHandler) NavEpoch

func (h *DefaultHandler) NavEpoch(msg *NavEpochMsg, tRead time.Time)

func (*DefaultHandler) PosECEF

func (h *DefaultHandler) PosECEF(msg *PosECEFMsg, tRead time.Time)

func (*DefaultHandler) PosGeo

func (h *DefaultHandler) PosGeo(msg *PosGeoMsg, tRead time.Time)

func (*DefaultHandler) Satellites

func (h *DefaultHandler) Satellites(msg *SatellitesMsg, tRead time.Time)

func (*DefaultHandler) Survey

func (h *DefaultHandler) Survey(msg *SurveyMsg, tRead time.Time)

func (*DefaultHandler) Time

func (h *DefaultHandler) Time(msg *TimeMsg, tRead time.Time)

func (*DefaultHandler) VelECEF

func (h *DefaultHandler) VelECEF(msg *VelECEFMsg, tRead time.Time)

func (*DefaultHandler) VelGeo

func (h *DefaultHandler) VelGeo(msg *VelGeoMsg, tRead time.Time)

type DefaultPacketProcessor

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

DefaultPacketProcessor provides default implementations of PacketProcessor methods

func (*DefaultPacketProcessor) GetNativeMsgHandler

func (p *DefaultPacketProcessor) GetNativeMsgHandler() NativeMsgHandler

GetNativeMsgHandler returns the current native message handler

func (*DefaultPacketProcessor) Idle

func (p *DefaultPacketProcessor) Idle(tRead time.Time)

Idle provides a default implementation that does nothing

func (*DefaultPacketProcessor) NativeOnly

func (p *DefaultPacketProcessor) NativeOnly() bool

NativeOnly returns false by default since most protocols provide timing/positioning

func (*DefaultPacketProcessor) ProcessPacket

func (p *DefaultPacketProcessor) ProcessPacket(data string, tRead time.Time) error

ProcessPacket provides a default implementation that does nothing and returns nil

func (*DefaultPacketProcessor) SetMsgHandler

func (p *DefaultPacketProcessor) SetMsgHandler(handler MsgHandler)

SetMsgHandler does nothing in the default implementation.

func (*DefaultPacketProcessor) SetNativeMsgHandler

func (p *DefaultPacketProcessor) SetNativeMsgHandler(handler NativeMsgHandler)

SetNativeMsgHandler sets the native message handler

type Duration

type Duration time.Duration

Duration represents a duration that serialises as decimal seconds.

const (
	Nanosecond  Duration = Duration(time.Nanosecond)
	Microsecond Duration = Duration(time.Microsecond)
	Millisecond Duration = Duration(time.Millisecond)
	Second      Duration = Duration(time.Second)
)

func ParseDuration

func ParseDuration(s string) (Duration, error)

ParseDuration parses a string as a duration in seconds.

func Seconds

func Seconds(f float64) Duration

Seconds creates a Duration from a float64 value in seconds.

func (Duration) MarshalJSON

func (d Duration) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (Duration) MarshalText

func (d Duration) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (Duration) Seconds

func (d Duration) Seconds() float64

Seconds returns the duration in seconds as a float64.

func (Duration) String

func (d Duration) String() string

func (*Duration) UnmarshalJSON

func (d *Duration) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

func (*Duration) UnmarshalText

func (d *Duration) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type EpochFlusher

type EpochFlusher interface {
	FlushNavEpoch(tRead time.Time) (*NavEpochMsg, MsgPriority, MsgHandler)
}

EpochFlusher is implemented by PacketProcessors that participate in epoch coordination. The manager calls FlushNavEpoch when an epoch boundary is detected. The processor returns its accumulated NavEpochMsg (or nil if it has nothing to contribute), a MsgPriority indicating the protocol band, and its MsgHandler for emission.

type FixLevel

type FixLevel uint8

FixLevel is the primary ordered axis describing GNSS contribution to the navigation solution, ordered by increasing quality. FixLevelCode and above describe how the position/time solution is computed. The zero value means "not provided" or "not applicable".

const (
	// FixLevelNone indicates that no valid GNSS solution is available.
	FixLevelNone FixLevel = iota + 1

	// FixLevelNotMeasured indicates that the receiver reports a position that
	// is not based on any measurement (e.g. manual input or simulated). No
	// component of the PVT solution is being computed from observations.
	// CorrKind and SolutionDim do not apply.
	FixLevelNotMeasured

	// FixLevelDoppler indicates a velocity-only solution derived from Doppler
	// measurements, without a valid position/time solution.
	FixLevelDoppler

	// FixLevelCode indicates an uncorrected code-based GNSS solution
	// (e.g. standalone SPS or single point positioning).
	FixLevelCode

	// FixLevelCodeCorrected indicates a code-based GNSS solution with
	// corrections applied (e.g. DGPS or SBAS). This improves accuracy but
	// remains limited by code measurement precision.
	FixLevelCodeCorrected

	// FixLevelCarrierFloat indicates a carrier-phase-based solution with
	// ambiguities estimated as float (non-integer) values. This includes
	// RTK float and classical PPP solutions prior to ambiguity fixing.
	FixLevelCarrierFloat

	// FixLevelCarrierFixed indicates a carrier-phase-based solution with
	// integer ambiguities resolved and constrained. This includes RTK fixed
	// and PPP-AR/PPP-RTK solutions.
	FixLevelCarrierFixed
)

func (FixLevel) MarshalJSON

func (f FixLevel) MarshalJSON() ([]byte, error)

func (FixLevel) MarshalText

func (f FixLevel) MarshalText() ([]byte, error)

func (FixLevel) String

func (f FixLevel) String() string

func (*FixLevel) UnmarshalText

func (f *FixLevel) UnmarshalText(text []byte) error

type GNSS

type GNSS uint8
const (
	GPS      GNSS = iota + 1 // GPS (USA)
	GAL                      // Galileo (Europe)
	BDS                      // BeiDou (China)
	GLO                      // GLONASS (Russia)
	QZSS                     // QZSS (Japan)
	NAVIC                    // NavIC (India)
	SBAS                     // Satellite-Based Augmentation System (e.g. WAAS, EGNOS, GAGAN, MSAS)
	GNSSLast GNSS = SBAS
)

Constants for GNSS type. Zero value means invalid/unknown/unspecified. The major GNSS systems are first. SBAS is an augmentation system, and not a standalone GNSS system.

func ParseGNSS

func ParseGNSS(s string) (GNSS, error)

ParseGNSS parses a GNSS name string into a GNSS value.

func (GNSS) IsMajor

func (g GNSS) IsMajor() bool

IsMajor returns true if the GNSS is one of the four major systems (GPS, Galileo, BeiDou, GLONASS).

func (GNSS) IsValid

func (g GNSS) IsValid() bool

IsValid returns true if the GNSS value is a known system.

func (GNSS) IsValidSVNum

func (g GNSS) IsValidSVNum(num int) bool

IsValidSVNum checks if the given SV number is valid for the GNSS type. Numbers are as in RINEX 3.04.

func (GNSS) MarshalJSON

func (g GNSS) MarshalJSON() ([]byte, error)

func (GNSS) MarshalText

func (g GNSS) MarshalText() ([]byte, error)

func (GNSS) SVIDPrefix

func (g GNSS) SVIDPrefix() string

SVIDPrefix returns the single-letter prefix used in SVID string representation.

func (GNSS) String

func (i GNSS) String() string

func (*GNSS) UnmarshalText

func (gp *GNSS) UnmarshalText(text []byte) error

type GNSSSet

type GNSSSet uint32

GNSSSet is a set of GNSS values. It is comparable.

const MajorGNSSSet GNSSSet = 1<<GPS | 1<<GAL | 1<<BDS | 1<<GLO

func GNSSSetOf

func GNSSSetOf(gs ...GNSS) GNSSSet

func (GNSSSet) Contains

func (s GNSSSet) Contains(g GNSS) bool

func (GNSSSet) Items

func (s GNSSSet) Items() []GNSS

func (GNSSSet) MarshalJSON

func (s GNSSSet) MarshalJSON() ([]byte, error)

func (GNSSSet) String

func (s GNSSSet) String() string

String returns a comma-separated list of the GNSS names in the set. Returns "(none)" if the set is empty.

type LeapSecondMsg

type LeapSecondMsg struct {
	ptime.LeapSecond
	GNSS GNSS `json:"gnss,omitempty"` // the GNSS that is the source of this leap second
}

func (*LeapSecondMsg) Dispatch

func (m *LeapSecondMsg) Dispatch(h MsgHandler, t time.Time)

func (*LeapSecondMsg) UpdateLeapSecond

func (msg *LeapSecondMsg) UpdateLeapSecond(target *ptime.LeapSecond) bool

UpdateLeapSecond updates the target leap second if this message contains newer information Returns true if the target was updated

type Length

type Length int64

Length represents a length in micrometers.

const (
	Micrometer Length = 1
	Millimeter Length = 1000 * Micrometer
	Centimeter Length = 10 * Millimeter
	Meter      Length = 100 * Centimeter
)

func Meters

func Meters(f float64) Length

Meters creates a Length from a float64 value in meters.

func ParseLength

func ParseLength(s string) (Length, error)

ParseLength parses a string as a length in meters.

func (Length) MarshalJSON

func (l Length) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (Length) MarshalText

func (l Length) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (Length) Meters

func (l Length) Meters() float64

Meters returns the length in meters as a float64.

func (Length) String

func (l Length) String() string

func (*Length) UnmarshalJSON

func (l *Length) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

func (*Length) UnmarshalText

func (l *Length) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type LookAngles

type LookAngles struct {
	Azimuth   int16 `json:"azimuth"`   // in degrees, 0 to 360
	Elevation int8  `json:"elevation"` // in degrees, -
}

type Mode

type Mode struct {
	Static       bool     // true if receiver should assume antenna position does not move
	PosType      PosType  // which coordinate system to use for fixed position
	FixedPosECEF Point3D  // ECEF coordinates (when PosType == PosTypeECEF)
	FixedPosLLH  [2]Angle // Latitude and Longitude (when PosType == PosTypeLLH)
	Height       Length   // Height (when PosType == PosTypeLLH)
	FixedPosAcc  Length   // accuracy of fixed position
}

func (Mode) IsZero

func (m Mode) IsZero() bool

type Msg

type Msg interface {
	Dispatch(MsgHandler, time.Time)
}

Msg is implemented by all protocol-agnostic message types.

type MsgHandler

type MsgHandler interface {
	Time(msg *TimeMsg, tRead time.Time)
	PosGeo(msg *PosGeoMsg, tRead time.Time)
	PosECEF(msg *PosECEFMsg, tRead time.Time)
	VelGeo(msg *VelGeoMsg, tRead time.Time)
	VelECEF(msg *VelECEFMsg, tRead time.Time)
	LeapSecond(msg *LeapSecondMsg, tRead time.Time)
	Survey(msg *SurveyMsg, tRead time.Time)
	Satellites(msg *SatellitesMsg, tRead time.Time)
	NavEpoch(msg *NavEpochMsg, tRead time.Time)
}

type MsgPriority

type MsgPriority uint8

MsgPriority indicates the trustworthiness of a message's fields for priority-based merging within a navigation epoch.

const (
	PriGenericLow  MsgPriority = iota + 1 // NMEA, basic sentence
	PriGenericHigh                        // NMEA, richer sentence (e.g. GGA over RMC)
	PriVendorLow                          // vendor binary, standard message
	PriVendorHigh                         // vendor binary, high-precision message
)

type MultiHandler

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

func NewMultiHandler

func NewMultiHandler(handlers ...MsgHandler) *MultiHandler

func (*MultiHandler) Handlers

func (h *MultiHandler) Handlers() iter.Seq[MsgHandler]

Handlers returns an iterator over the message handlers

func (*MultiHandler) LeapSecond

func (h *MultiHandler) LeapSecond(msg *LeapSecondMsg, tRead time.Time)

func (*MultiHandler) NavEpoch

func (h *MultiHandler) NavEpoch(msg *NavEpochMsg, tRead time.Time)

func (*MultiHandler) PosECEF

func (h *MultiHandler) PosECEF(msg *PosECEFMsg, tRead time.Time)

func (*MultiHandler) PosGeo

func (h *MultiHandler) PosGeo(msg *PosGeoMsg, tRead time.Time)

func (*MultiHandler) Satellites

func (h *MultiHandler) Satellites(msg *SatellitesMsg, tRead time.Time)

func (*MultiHandler) Survey

func (h *MultiHandler) Survey(msg *SurveyMsg, tRead time.Time)

func (*MultiHandler) Time

func (h *MultiHandler) Time(msg *TimeMsg, tRead time.Time)

func (*MultiHandler) VelECEF

func (h *MultiHandler) VelECEF(msg *VelECEFMsg, tRead time.Time)

func (*MultiHandler) VelGeo

func (h *MultiHandler) VelGeo(msg *VelGeoMsg, tRead time.Time)

type MultiNativeMsgHandler

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

MultiNativeMsgHandler fans out NativeMsg calls to multiple handlers

func NewMultiNativeMsgHandler

func NewMultiNativeMsgHandler(handlers ...NativeMsgHandler) *MultiNativeMsgHandler

func (*MultiNativeMsgHandler) NativeMsg

func (m *MultiNativeMsgHandler) NativeMsg(tag Tag, msgID string, msg any, tRead time.Time) error

func (*MultiNativeMsgHandler) Reset

func (m *MultiNativeMsgHandler) Reset(handlers ...NativeMsgHandler)

type NMEAMsgFlags

type NMEAMsgFlags uint16
const (
	NMEAMsgRMC NMEAMsgFlags = 1 << iota
	NMEAMsgGGA
	NMEAMsgGSA
	NMEAMsgGSV
	NMEAMsgZDA
	NMEAMsgVTG
	NMEAMsgGLL
	NMEAMsgOther NMEAMsgFlags = 1 << 15 // other unspecified NMEA messages
	// may have flags like NMEA version or rate in the future
	NMEAMsgNone NMEAMsgFlags = 0
	NMEAMsgAny  NMEAMsgFlags = NMEAMsgRMC | NMEAMsgGGA | NMEAMsgGSA | NMEAMsgGSV | NMEAMsgZDA | NMEAMsgVTG | NMEAMsgGLL | NMEAMsgOther // any message (not flag)
)

type NMEAPacketProcessor

type NMEAPacketProcessor interface {
	PacketProcessor
	// SetSVNumbering sets the satellite numbering scheme for NMEA.
	// The ranges must be non-overlapping and in increasing order of MinID/MaxID.
	SetSVNumbering([]NMEASVNumberingRange)
}

type NMEASVNumberingRange

type NMEASVNumberingRange struct {
	MinID    uint16
	MaxID    uint16
	MinNum   uint8
	GNSS     GNSS
	SignalID SignalID
}

type NativeMsgHandler

type NativeMsgHandler interface {
	// NativeMsg processes a protocol-specific message.
	// tag: identifies the protocol (e.g., UBX, NMEA).
	// msgID: identifies the message type within the protocol (e.g., UBX-NAV-PVT, NMEA-GGA).
	// msg: the protocol-specific message object.
	// tRead: timestamp when the message was received.
	NativeMsg(tag Tag, msgID string, msg any, tRead time.Time) error
}

NativeMsgHandler handles protocol-specific messages that don't map to standard messages.

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

NavEpochManager coordinates navigation epoch handling across multiple protocol processors. Each PacketProcessor receives a reference to the shared manager in its constructor instead of directly calling MsgHandler.NavEpoch.

func NewNavEpochManager

func NewNavEpochManager() *NavEpochManager

NewNavEpochManager creates a new NavEpochManager.

func (m *NavEpochManager) EndOfEpoch(tRead time.Time)

EndOfEpoch is called by a processor that received an explicit end-of-epoch signal (e.g. UBX NAV-EOE, Quectel PQTMEOE). These messages mark the end of the epoch for all protocols on the receiver, so all active processors are flushed unconditionally.

func (m *NavEpochManager) EpochStarted(f EpochFlusher, tRead time.Time)

EpochStarted is called by a processor when it detects the start of a new epoch. If the caller is already in the active set, the manager flushes all active processors and emits the merged NavEpochMsg. The caller is then added to the (possibly cleared) active set.

type NavEpochMsg struct {
	// FixLevel is the primary GNSS solution mode, ordered by increasing
	// quality (None < Doppler < Code < CodeCorrected <
	// CarrierFloat < CarrierFixed).
	FixLevel FixLevel `json:"fixLevel,omitzero"`
	// SolutionDim is the dimensionality of the position/time solution
	// (2D, 3D, time-only). Unset when FixLevel < FixLevelCode.
	SolutionDim SolutionDim `json:"solutionDim,omitzero"`
	// Correction is a bitmask of assertions about corrections applied.
	// Meaningful when FixLevel >= FixLevelCodeCorrected.
	Correction CorrKind `json:"correction,omitzero"`
	// AuxSrc is a bitmask of additional sources (DR, INS) that contributed
	// to the solution. GNSS is implicit when FixLevel indicates a fix.
	AuxSrc AuxSrc `json:"auxSrc,omitzero"`
	// Acc holds estimated position, velocity, and course accuracy.
	Acc Accuracy `json:"acc,omitzero"`
	// DOP holds dilution of precision values (GDOP, PDOP, HDOP, VDOP, TDOP).
	DOP DOP `json:"dop,omitzero"`
	// DiffAge is the age of the differential corrections applied to the
	// current solution. Unset when no corrections are in use or the
	// protocol doesn't report it.
	DiffAge opt.Val[Duration] `json:"diffAge,omitzero"`
	// RTCMRefBaseID is the RTCM reference station ID (DF003, 0-4095) of
	// the base station whose corrections are applied to this solution.
	// Distinct from the RTCMBaseID config property, which is this
	// receiver's own base ID for RTCM output.
	RTCMRefBaseID opt.Val[uint16] `json:"rtcmRefBaseID,omitzero"`
	// NumSVUsed is the number of satellites used in the solution.
	NumSVUsed opt.Val[uint16] `json:"numSVUsed,omitzero"`
	// NumSVTracked is the number of satellites tracked by the receiver.
	NumSVTracked opt.Val[uint16] `json:"numSVTracked,omitzero"`
	// NumSVInView is the number of satellites in view of the receiver.
	NumSVInView opt.Val[uint16] `json:"numSVInView,omitzero"`
	// SignalsUsed is the set of GNSS signals used in the solution.
	SignalsUsed SignalSet `json:"signalsUsed,omitzero"`
	// Tag identifies the protocol source (e.g. UBX, NMEA, Unicore).
	Tag Tag `json:"tag,omitzero"`
	// StartTime is when the first message in this epoch was read.
	StartTime time.Time `json:"startTime"`
}

NavEpochMsg is emitted once at the end of each navigation epoch, after all time/position/velocity messages for that epoch have been dispatched. GNSS is the implicit baseline source when FixLevel indicates a GNSS-based fix. AuxSrc captures additional sources (e.g. DR/INS). The zero value of each field means "not provided" or "not applicable". CorrKind is a bitmask (not an enum) and its bits are related by a partial order (see CorrKind docs).

func MergeNavEpoch

func MergeNavEpoch(msgs ...*NavEpochMsg) *NavEpochMsg

MergeNavEpoch merges multiple NavEpochMsg values. Priority is implicit in argument order: the first non-nil message wins for scalar fields (Tag, FixLevel, SolutionDim); optional fields use fill-if-unset semantics; bitmask fields (Correction, AuxSrc, SignalsUsed) are unioned; StartTime is the earliest. The first non-nil argument is mutated and returned.

type NavMsgAuth byte
const (
	NavMsgAuthNone NavMsgAuth = iota // no authentication
	NavMsgAuthOSNMA
)

type OSNMAOptions

type OSNMAOptions struct {
	MerkleTreeRoot [32]byte // all zeros means not set
}

type PVMsg

type PVMsg interface {
	Msg
	SetPriority(MsgPriority)
}

PVMsg is implemented by position/velocity message types that participate in per-epoch accumulation with priority-based merging.

type PVMsgAccum

type PVMsgAccum struct {
	DefaultHandler
	PVMsgBundle
}

PVMsgAccum accumulates the best position/velocity message of each kind within a navigation epoch. It implements MsgHandler for the four PV methods, merging incoming messages by priority. NavEpoch clears the accumulated bundle.

func (*PVMsgAccum) NavEpoch

func (a *PVMsgAccum) NavEpoch(_ *NavEpochMsg, _ time.Time)

NavEpoch clears the accumulated bundle, preparing for the next epoch.

func (*PVMsgAccum) PosECEF

func (a *PVMsgAccum) PosECEF(msg *PosECEFMsg, _ time.Time)

func (*PVMsgAccum) PosGeo

func (a *PVMsgAccum) PosGeo(msg *PosGeoMsg, _ time.Time)

func (*PVMsgAccum) VelECEF

func (a *PVMsgAccum) VelECEF(msg *VelECEFMsg, _ time.Time)

func (*PVMsgAccum) VelGeo

func (a *PVMsgAccum) VelGeo(msg *VelGeoMsg, _ time.Time)

type PVMsgBundle

type PVMsgBundle struct {
	PosGeo  opt.Val[PosGeoMsg]  `json:"posGeo,omitzero"`
	PosECEF opt.Val[PosECEFMsg] `json:"posECEF,omitzero"`
	VelGeo  opt.Val[VelGeoMsg]  `json:"velGeo,omitzero"`
	VelECEF opt.Val[VelECEFMsg] `json:"velECEF,omitzero"`
}

PVMsgBundle holds the accumulated position/velocity messages for a single navigation epoch.

func (*PVMsgBundle) FillDerived

func (b *PVMsgBundle) FillDerived()

FillDerived fills in missing fields using cross-frame derivation.

type PVTMsgFlags

type PVTMsgFlags uint16

PVTMsgFlags says what messages relating to Position, Velocity, and Time are wanted. The PVTMsgOff option says to turn off PVT messages that are not enabled. This makes PVTMsgFlags different from the other message flags, where the equivalent of PVTMsgOff semantics is always applied. A zero value means no specific PVT message configuration is requested.

const (
	PVTMsgPos            PVTMsgFlags = 1 << iota // position
	PVTMsgVel                                    // velocity
	PVTMsgTime                                   // time of navigation solution
	PVTMsgTimePulse                              // time of time pulse
	PVTMsgLeapSecond                             // date of most recently announced leap second
	PVTMsgSurvey                                 // survey-in progress
	PVTMsgTAI                                    // want time in TAI not UTC (option)
	PVTMsgECEF                                   // want position in ECEF coordinates (option)
	PVTMsgTimePulseAfter                         // ensure there is a time message following the time pulse (option)
	PVTMsgQuality                                // solution quality messages (fix level, corrections, DOPs)
	PVTMsgEpoch                                  // end-of-epoch messages (NavEpochMsg)
	PVTMsgOff                                    // turn off any unneeded PVT messages (option)
)

func (*PVTMsgFlags) Get

func (f *PVTMsgFlags) Get() PVTMsgFlags

Get returns the PVT message flags value

func (*PVTMsgFlags) IsSet

func (f *PVTMsgFlags) IsSet() bool

IsSet returns true if any PVT message flags are set

func (*PVTMsgFlags) IsZero

func (f *PVTMsgFlags) IsZero() bool

IsZero returns true if no PVT message flags are set

func (*PVTMsgFlags) Set

func (f *PVTMsgFlags) Set(v PVTMsgFlags)

Set sets the PVT message flags value

type PacketFormat

type PacketFormat interface {
	// Tag returns the protocol-specific packet kind
	Tag() Tag

	// Next takes the current state, buffer, index, and packet length, and returns the next state
	// buf is the buffer containing the packet data
	// nextScanIndex is the index of the byte to process
	// packetLen is the length of the packet so far, not including the one at nextScanIndex
	Next(state ScanState, buf []byte, nextScanIndex, packetLen int) ScanState

	// IsFinal determines if the given state represents a complete packet
	IsFinal(state ScanState) bool

	// MsgID returns a human readable ID of the packet
	// Precondition: the packet must be valid according to Next()
	MsgID(pkt []byte) string

	// ExtractChecksum extracts the checksum from the packet
	// Precondition: the packet must be valid according to Next()
	ExtractChecksum(pkt []byte) []byte

	// ComputeChecksum computes the checksum for the given packet
	// Precondition: the packet must be valid according to Next()
	ComputeChecksum(pkt []byte) []byte

	// RescanOnBadChecksum determines if the scanner should rescan on a bad checksum
	// starting with the byte after the first byte of the packet with the bad checksum
	// prevPktValid indicates if the previous packet was valid
	RescanOnBadChecksum(prevPktValid bool, pkt []byte) bool
}

PacketFormat defines the interface for protocol-specific packet format handling PacketFormat is immutable

type PacketProcessor

type PacketProcessor interface {
	// ProcessPacket processes a packet's data and returns a string with the type of the packet and an error
	ProcessPacket(data string, tRead time.Time) (string, error)

	// No data has been received for a period of time (usually 0.1s).
	// tRead is the end of the period.
	// There is no implication that data is received immediately after this.
	Idle(tRead time.Time)

	// SetMsgHandler sets the handler for protocol-agnostic messages
	SetMsgHandler(handler MsgHandler)

	// SetNativeMsgHandler sets the handler for protocol-specific messages
	SetNativeMsgHandler(handler NativeMsgHandler)

	// GetNativeMsgHandler returns the current protocol message handler
	GetNativeMsgHandler() NativeMsgHandler

	// NativeOnly returns true if this processor only generates native messages
	// and never produces protocol-agnostic messages like TimeMsg or SatellitesMsg.
	// This is typically true for protocols that provide correction data rather
	// than positioning solutions (e.g., RTCM).
	NativeOnly() bool
}

PacketProcessor processes packets of a specific protocol.

Callers must call SetMsgHandler with a non-nil handler before calling ProcessPacket or Idle.

type Point3D

type Point3D [3]Length

Point3D represents a 3D point with Length coordinates.

func ParsePoint3D

func ParsePoint3D(s string) (Point3D, error)

ParsePoint3D parses a string as three comma-separated coordinates in meters.

func (Point3D) IsZero

func (p Point3D) IsZero() bool

func (Point3D) String

func (p Point3D) String() string

type PosECEFMsg

type PosECEFMsg struct {
	Pos         Point3D     `json:"pos"` // ECEF X, Y, Z
	Priority    MsgPriority `json:"-"`
	Tag         Tag         `json:"tag"`
	NativeMsgID string      `json:"nativeMsgID"`
}

PosECEFMsg is an Earth-Centered, Earth-Fixed position.

func (*PosECEFMsg) Dispatch

func (m *PosECEFMsg) Dispatch(h MsgHandler, t time.Time)

func (*PosECEFMsg) Merge

func (m *PosECEFMsg) Merge(other *PosECEFMsg)

Merge incorporates fields from other into m based on priority.

func (*PosECEFMsg) SetPriority

func (m *PosECEFMsg) SetPriority(pri MsgPriority)

type PosGeoMsg

type PosGeoMsg struct {
	LatLon      [2]Angle        `json:"latLon"`             // [lat, lon]; lat positive north, lon positive east
	Height      opt.Val[Length] `json:"height,omitzero"`    // above WGS-84 ellipsoid
	HeightMSL   opt.Val[Length] `json:"heightMSL,omitzero"` // above mean sea level
	Priority    MsgPriority     `json:"-"`
	Tag         Tag             `json:"tag"`
	NativeMsgID string          `json:"nativeMsgID"`
}

PosGeoMsg is a geodetic position (latitude, longitude, height above WGS-84 ellipsoid).

func (*PosGeoMsg) Dispatch

func (m *PosGeoMsg) Dispatch(h MsgHandler, t time.Time)

func (*PosGeoMsg) Merge

func (m *PosGeoMsg) Merge(other *PosGeoMsg)

Merge incorporates fields from other into m based on priority. Higher priority overwrites everything. Equal priority fills only missing optional fields (first-wins). Lower priority does nothing.

func (*PosGeoMsg) SetPriority

func (m *PosGeoMsg) SetPriority(pri MsgPriority)

SetPriority implements PVMsg for the four position/velocity types.

type PosType

type PosType byte
const (
	PosTypeNone PosType = iota
	PosTypeECEF
	PosTypeLLH
)

type PropIDs

type PropIDs uint32

PropIDs represents a set of configuration property names

const (
	PropIDSignalsEnabled PropIDs = 1 << iota
	PropIDTimeGNSS
	// eventually the individual time pulse properties will be combined into a single property
	PropIDTimePulseWidth
	PropIDTimePulsePeriod
	PropIDTimePulseAlignToGNSS
	PropIDTimePulseOnlyWhenLocked
	PropIDTimePulsePolarityRising
	PropIDMode
	PropIDAntennaCableDelay
	PropIDNavMsgAuth
	PropIDRTCMBaseID
	PropIDMinElevation
	PropIDTimePulse PropIDs = PropIDTimePulseWidth | PropIDTimePulsePeriod |
		PropIDTimePulseAlignToGNSS | PropIDTimePulseOnlyWhenLocked | PropIDTimePulsePolarityRising
)

func (PropIDs) MarshalJSON

func (p PropIDs) MarshalJSON() ([]byte, error)

MarshalJSON marshals PropIDs as a JSON array of property name strings.

func (PropIDs) String

func (p PropIDs) String() string

String returns a human-readable representation of the PropIDs flags

func (*PropIDs) UnmarshalJSON

func (p *PropIDs) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshals PropIDs from a JSON array of property name strings.

type RTCMMsgFlags

type RTCMMsgFlags uint16
const (
	RTCMMsgMSM4 RTCMMsgFlags = 1 << iota // MSM4 for all enabled GNSS

	RTCMMsgMSM7                         // MSM7 for all enabled GNSS
	RTCMMsgARP                          // RTCM message 1005
	RTCMMsgLax                          // Do the best we can on enabling RTCM messages
	RTCMMsgOther RTCMMsgFlags = 1 << 15 // other unspecified RTCM messages
	// may have flags for rate
	RTCMMsgNone RTCMMsgFlags = 0
	RTCMMsgAuto RTCMMsgFlags = RTCMMsgMSM4 | RTCMMsgARP | RTCMMsgLax                 // enable intelligently
	RTCMMsgAny  RTCMMsgFlags = RTCMMsgMSM4 | RTCMMsgMSM7 | RTCMMsgARP | RTCMMsgOther // any message (not flag)
)

type RawMsgFlags

type RawMsgFlags uint8
const (
	RawMsgObs     RawMsgFlags = 1 << iota // Raw observation messages (for RINEX)
	RawMsgNavData                         // Raw navigation date e.g. subframes for GPS
	RawMsgNone    RawMsgFlags = 0
	RawMsgAny     RawMsgFlags = RawMsgObs | RawMsgNavData // any message (not flag)
)

type ReceiverInfo

type ReceiverInfo struct {
	Vendor         string      `json:"vendor"`        // receiver vendor (e.g., "u-blox")
	Firmware       string      `json:"firmware"`      // information about firmware; for u-blox, format would be e.g. "TIM 2.20 PROTVER 18.00"
	Hardware       string      `json:"hardware"`      // information about hardware; for u-blox, this is the model (e.g., "ZED-F9T")
	SupportedGNSS  GNSSSet     `json:"supportedGNSS"` // supported GNSS constellations
	VendorSpecific interface{} `json:"-"`             // vendor-specific information, excluded from JSON
}

ReceiverInfo provides static information about the GPS receiver.

type ResetType

type ResetType uint8
const (
	ResetNone    ResetType = iota
	ResetReload            // reload the configuration from non-volatile memory without a reset/start (if possible)
	ResetCold              // restore configuration from non-volatile memory and perform a cold start
	ResetFactory           // restore non-volatile memory to factory defaults and then ResetCold
)

type SVID

type SVID struct {
	GNSS GNSS
	// Num is a number identifying the SV within a specific GNSS.
	// Numbering is the same as in RINEX 3.04.
	// For GPS, GAL, BDS, NAVIC, this is the PRN (pseudo-random noise) number.
	// For GLONASS, this is the orbital slot number.
	// For SBAS, this is the PRN number minus 100.
	// For QZSS, this is the PRN number minus 192.
	// This gives two-digit, non-zero numbers.
	// In addition, this can be GLOUnknown, when the GNSS is GLONASS
	Num uint8
}

SVID is an identifier of a space vehicle (satellite).

func (SVID) IsValid

func (sv SVID) IsValid() bool

IsValid checks if the SVID has a valid Num for its GNSS type

func (SVID) IsZero

func (sv SVID) IsZero() bool

func (SVID) MarshalJSON

func (sv SVID) MarshalJSON() ([]byte, error)

func (SVID) String

func (sv SVID) String() string

type SVInfo

type SVInfo struct {
	ID         SVID         `json:"id"`
	LookAngles *LookAngles  `json:"lookAngles,omitempty"` // look angle of the satellite
	Signals    []SignalInfo `json:"signals"`              // signals being transmitted by a satellite
	Used       bool         `json:"used,omitempty"`       // true if the satellite is used in the navigation solution
}

type SatelliteUsedValidity

type SatelliteUsedValidity int
const (
	SatelliteUsedInvalid SatelliteUsedValidity = iota // Used is not specified in both SVInfo and SignalInfo
	SatelliteUsedSV                                   // Used is specified in SVInfo, but not in SignalInfo
	SatelliteUsedSignal                               // Used is specified in SignalInfo and in SVInfo
)

type SatellitesMsg

type SatellitesMsg struct {
	Tag          Tag                   `json:"tag,omitempty"`
	NativeMsgID  string                `json:"nativeMsgID,omitempty"`
	SVs          []SVInfo              `json:"info"`                   // satellites being tracked
	UsedValidity SatelliteUsedValidity `json:"usedValidity,omitempty"` // says whether Used fields in SVInfo and SignalInfo are valid
}

func (*SatellitesMsg) Dispatch

func (m *SatellitesMsg) Dispatch(h MsgHandler, t time.Time)

type SatsMsgFlags

type SatsMsgFlags uint8
const (
	SatsMsgSat    SatsMsgFlags = 1 << iota // position of SVs
	SatsMsgSignal                          // signal strength of each signal from each SV
	SatsMsgNone   SatsMsgFlags = 0
	SatsMsgAny    SatsMsgFlags = SatsMsgSat | SatsMsgSignal // any message (not flag)
)

type SaveType

type SaveType uint8
const (
	SaveNone    SaveType = iota
	SaveMinimal          // save the minimum to save the configuration changes specified in ConfigTarget
	SaveAll              // save the current configuration
)

type ScanState

type ScanState uint32

ScanState represents the state of a packet scanner

const (
	ScanStateSync ScanState = 0 // Always 0, the initial state looking for packet start
)

Constants for scan states

type Signal

type Signal int

Signal represents a signal that be enabled in a GNSS receiver. The signal identies both the GNSS constellation and the signal.

const (
	// GPS signals
	SigGPSL1CA Signal = sigBaseGPS + sigIndexL1Legacy // L1 C/A (1575.42 MHz)
	SigGPSL1C  Signal = sigBaseGPS + sigIndexL1Modern // L1C (1575.42 MHz)
	SigGPSL2P  Signal = sigBaseGPS + sigIndexL2Legacy // L2P(Y) (1227.60 MHz)
	SigGPSL2C  Signal = sigBaseGPS + sigIndexL2Modern // L2C (1227.60 MHz)
	SigGPSL5   Signal = sigBaseGPS + sigIndexL5       // L5 (1176.45 MHz)

	// GLONASS signals
	SigGLOL1   Signal = sigBaseGLO + sigIndexL1Legacy // G1 (1598–1609 MHz)
	SigGLOL1OC Signal = sigBaseGLO + sigIndexL1Modern // L1OC (1600.995 MHz)
	SigGLOL2   Signal = sigBaseGLO + sigIndexL2Legacy // G2 (1243–1252 MHz)
	SigGLOL2OC Signal = sigBaseGLO + sigIndexL2Modern // L2OC (1248.06 MHz)
	SigGLOL3   Signal = sigBaseGLO + sigIndexE5b      // G3 (1202.025 MHz)

	// Galileo signals
	SigGALE1  Signal = sigBaseGAL + sigIndexL1Modern  // E1 (1575.42 MHz)
	SigGALE5a Signal = sigBaseGAL + sigIndexL5        // E5a (1176.45 MHz)
	SigGALE5b Signal = sigBaseGAL + sigIndexE5b       // E5b (1207.14 MHz)
	SigGALE6  Signal = sigBaseGAL + sigIndexE6Augment // E6 (1278.75 MHz)

	// BeiDou signals
	SigBDSB1I Signal = sigBaseBDS + sigIndexL1Legacy   // B1I (1561.098 MHz)
	SigBDSB1C Signal = sigBaseBDS + sigIndexL1Modern   // B1C (1575.42 MHz)
	SigBDSB2I Signal = sigBaseBDS + sigIndexE5b        // B2I (1207.14 MHz)
	SigBDSB2b Signal = sigBaseBDS + sigIndexE5bAugment // B2b (1207.14 MHz)
	SigBDSB2a Signal = sigBaseBDS + sigIndexL5         // B2a (1176.45 MHz)
	SigBDSB3I Signal = sigBaseBDS + sigIndexE6         // B3I (1268.52 MHz)

	// QZSS signals
	SigQZSSL1CA Signal = sigBaseQZSS + sigIndexL1Legacy  // L1 C/A (1575.42 MHz)
	SigQZSSL1C  Signal = sigBaseQZSS + sigIndexL1Modern  // L1C (1575.42 MHz)
	SigQZSSL1S  Signal = sigBaseQZSS + sigIndexL1Augment // L1S (1575.42 MHz)
	SigQZSSL2C  Signal = sigBaseQZSS + sigIndexL2Modern  // L2C (1227.60 MHz)
	SigQZSSL5   Signal = sigBaseQZSS + sigIndexL5        // L5 (1176.45 MHz)
	SigQZSSL5S  Signal = sigBaseQZSS + sigIndexL5Augment // L5 (1176.45 MHz)
	SigQZSSL6   Signal = sigBaseQZSS + sigIndexE6Augment // L6 (1278.75 MHz)

	// NavIC signals
	SigNAVICL1 Signal = sigBaseNAVIC + sigIndexL1Modern // L1 (1575.42 MHz)
	SigNAVICL5 Signal = sigBaseNAVIC + sigIndexL5       // L5 (1176.45 MHz)

	// SBAS signals
	SigSBASL1CA Signal = sigBaseGPS + sigIndexL1Augment // L1 C/A (1575.42 MHz)
	SigSBASL5   Signal = sigBaseGPS + sigIndexL5Augment // L5 (1176.45 MHz)
)

func (Signal) GNSS

func (sig Signal) GNSS() GNSS

func (Signal) String

func (sig Signal) String() string

type SignalID

type SignalID string

SignalID is a human-readable string that distinguishes the signals transmitted by a satellite. The SignalID does not identify the GNSS constellation. It distinguishes signals that are transmitted separately, and have independent signal levels. There may be separate SignalIDs for the components of a Signal.

const (
	SigIDInvalid SignalID = "" // Invalid SignalID
	// GPS SignalID constants
	SigIDGPSL1CA SignalID = "L1 C/A"
	SigIDGPSL1PY SignalID = "L1 P(Y)" // restricted
	SigIDGPSL1M  SignalID = "L1M"     // restricted
	SigIDGPSL1C  SignalID = "L1C"
	SigIDGPSL2P  SignalID = "L2P"   // restricted
	SigIDGPSL2CM SignalID = "L2C-M" // L2C data
	SigIDGPSL2CL SignalID = "L2C-L" // L2C pilot
	SigIDGPSL5I  SignalID = "L5-I"  // L5 data
	SigIDGPSL5Q  SignalID = "L5-Q"  // L5 pilot
	SigIDGPSL1CD SignalID = "L1C-D" // L1C data
	SigIDGPSL1CP SignalID = "L1C-P" // L1C pilot

	// GLONASS SignalID constants
	SigIDGLOL1  SignalID = "L1"   // friendlier name for L1 C/A
	SigIDGLOL1P SignalID = "L1P"  // restricted
	SigIDGLOL2  SignalID = "L2"   // friendlier name for L2 C/A
	SigIDGLOL2P SignalID = "L2P"  // restricted
	SigIDGLOL3I SignalID = "L3-I" // L3 data
	SigIDGLOL3Q SignalID = "L3-Q" // L3 pilot

	// Galileo SignalID constants
	SigIDGALE5a SignalID = "E5a"
	SigIDGALE5b SignalID = "E5b"
	SigIDGALE5  SignalID = "E5"   // combo of E5a and E5b
	SigIDGALE6A SignalID = "E6-A" // restricted
	SigIDGALE6  SignalID = "E6"   // combo of E6-B and E6-C, sometimes called E6BC
	SigIDGALE1A SignalID = "E1-A" // restricted
	SigIDGALE1  SignalID = "E1"   // combo of E1-B plus E1-C, sometimes called E1-B/C or E1BC
	// Constants for Galileo components
	SigIDGALE1C  SignalID = "E1-C"  // E1 pilot
	SigIDGALE1B  SignalID = "E1-B"  // E1 data
	SigIDGALE5aI SignalID = "E5a-I" // E5a data
	SigIDGALE5aQ SignalID = "E5a-Q" // E5a pilot
	SigIDGALE5bI SignalID = "E5b-I" // E5b  data
	SigIDGALE5bQ SignalID = "E5b-Q" // E5b pilot
	SigIDGALE6B  SignalID = "E6-B"  // E6 data
	SigIDGALE6C  SignalID = "E6-C"  // E6 pilot

	// BeiDou SignalID constants
	SigIDBDSB1I  SignalID = "B1I"
	SigIDBDSB1Q  SignalID = "B1Q" // restricted
	SigIDBDSB1C  SignalID = "B1C"
	SigIDBDSB1A  SignalID = "B1A"   // restricted
	SigIDBDSB2a  SignalID = "B2a"   // NMEA calls it B2-a
	SigIDBDSB2b  SignalID = "B2b"   // NMEA calls it B2-b
	SigIDBDSB2ab SignalID = "B2a+b" // u-blox tracks these together
	SigIDBDSB3I  SignalID = "B3I"
	SigIDBDSB3Q  SignalID = "B3Q" // restricted
	SigIDBDSB3A  SignalID = "B3A" // restricted
	SigIDBDSB2I  SignalID = "B2I"
	SigIDBDSB2Q  SignalID = "B2Q" // restricted
	// Constants for BeiDou formats/components
	SigIDBDSB1ID1 SignalID = "B1I-D1" // B1I D1 format
	SigIDBDSB1ID2 SignalID = "B1I-D2" // B1I D2 format
	SigIDBDSB2ID1 SignalID = "B2I-D1" // B2I D1 format
	SigIDBDSB2ID2 SignalID = "B2I-D2" // B2I D2 format
	SigIDBDSB3ID1 SignalID = "B3I-D1" // B3I D1 format
	SigIDBDSB3ID2 SignalID = "B3I-D2" // B3I D2 format
	SigIDBDSB1CP  SignalID = "B1C-P"  // B1C pilot
	SigIDBDSB1CD  SignalID = "B1C-D"  // B1C data
	SigIDBDSB2aP  SignalID = "B2a-P"  // B2a pilot
	SigIDBDSB2aD  SignalID = "B2a-D"  // B2a data
	SigIDBDSB2bI  SignalID = "B2b-I"  // B2b data

	// QZSS SignalID constants
	SigIDQZSSL1CA SignalID = "L1 C/A"
	SigIDQZSSL1CD SignalID = "L1C (D)" // L1C data
	SigIDQZSSL1CP SignalID = "L1C (P)" // L1C pilot
	SigIDQZSSL1S  SignalID = "L1S"
	SigIDQZSSL2CM SignalID = "L2C-M"  // L2C data
	SigIDQZSSL2CL SignalID = "L2C-L"  // L2C pilot
	SigIDQZSSL5I  SignalID = "L5-I"   // L5 data
	SigIDQZSSL5Q  SignalID = "L5-Q"   // L5 pilot
	SigIDQZSSL6   SignalID = "L6"     // friendlier name for L6D
	SigIDQZSSL6E  SignalID = "L6E"    // restricted
	SigIDQZSSL1CB SignalID = "L1 C/B" // replacement for L1 C/A

	// NavIC SignalID constants
	SigIDNAVICL5   SignalID = "L5"    // friendlier name for L5-SPS
	SigIDNAVICS    SignalID = "S"     // friendlier name for S-SPS
	SigIDNAVICL5RS SignalID = "L5-RS" // restricted
	SigIDNAVICSRS  SignalID = "S-RS"  // restricted
	SigIDNAVICL1   SignalID = "L1"    // friendlier name for L1-SPS
	SigIDNAVICL5I  SignalID = "L5-I"  // L5 data
	SigIDNAVICL5Q  SignalID = "L5-Q"  // L5 pilot
)

SignalID constants

type SignalInfo

type SignalInfo struct {
	ID   SignalID `json:"id,omitempty"`   // human-readable label of the signal e.g. "L5"
	CN0  uint8    `json:"cn0"`            // C/NO signal to noise ratio
	Used bool     `json:"used,omitempty"` // true if the signal is used in the navigation solution
}

SignalInfo contains information about a single signal transmitted by a satellite.

type SignalSet

type SignalSet uint64

SignalSet is a bitmask representing a set of GNSS signals. SignalSet makes it convenient to manipulate sets of signals based on GNSS and band. The Signal type gives the index of the signal in the set. The idea is that the 64 bits are divided into 6 groups of 11 bits each, where there is a group for each GNSS constellation, and the 11 bits is a Band bitmask. The 2-bit overflow does not matter since the last constellation is NAVIC, which does not use all bits in the Band bitmask.

const (
	SigSetGPS   SignalSet = (1 << SigGPSL1CA) | (1 << SigGPSL1C) | (1 << SigGPSL2P) | (1 << SigGPSL2C) | (1 << SigGPSL5)
	SigSetGLO   SignalSet = (1 << SigGLOL1) | (1 << SigGLOL1OC) | (1 << SigGLOL2) | (1 << SigGLOL2OC) | (1 << SigGLOL3)
	SigSetGAL   SignalSet = (1 << SigGALE1) | (1 << SigGALE5a) | (1 << SigGALE5b) | (1 << SigGALE6)
	SigSetBDS   SignalSet = (1 << SigBDSB1I) | (1 << SigBDSB1C) | (1 << SigBDSB2I) | (1 << SigBDSB2b) | (1 << SigBDSB2a) | (1 << SigBDSB3I)
	SigSetQZSS  SignalSet = (1 << SigQZSSL1CA) | (1 << SigQZSSL1C) | (1 << SigQZSSL1S) | (1 << SigQZSSL2C) | (1 << SigQZSSL5) | (1 << SigQZSSL5S) | (1 << SigQZSSL6)
	SigSetNAVIC SignalSet = (1 << SigNAVICL1) | (1 << SigNAVICL5)
	SigSetSBAS  SignalSet = (1 << SigSBASL1CA) | (1 << SigSBASL5)
)

Signal sets for each GNSS constellation

const (
	SigSetMajor   SignalSet = SigSetGPS | SigSetGLO | SigSetGAL | SigSetBDS // signals for major GNSS constellations
	SigSetAugment SignalSet = SigSetSBAS | (1 << SigGALE6) | (1 << SigBDSB2b) | (1 << SigQZSSL1S) | (1 << SigQZSSL5S) | (1 << SigQZSSL6)
	SigSetAll     SignalSet = SigSetGPS | SigSetGLO | SigSetGAL | SigSetBDS | SigSetQZSS | SigSetNAVIC | SigSetSBAS
)

func ParseSignalMap

func ParseSignalMap(m map[string][]string) (SignalSet, error)

ParseSignalMap parses a map from GNSS constellation name to signal name list into a SignalSet.

func SignalSetOf

func SignalSetOf(sig ...Signal) SignalSet

SignalSetOf creates a SignalSet from a list of signals.

func (SignalSet) Contains

func (ss SignalSet) Contains(sig Signal) bool

func (SignalSet) GNSSSet

func (ss SignalSet) GNSSSet() GNSSSet

GNSSSet returns the set of GNSS constellations that have at least one enabled signal.

func (SignalSet) GNSSSignalMap

func (ss SignalSet) GNSSSignalMap() map[string][]string

GNSSSignalMap returns the signal set as a map from GNSS constellation name to signal name list.

func (SignalSet) IsZero

func (ss SignalSet) IsZero() bool

IsZero returns true when the signal set is empty.

func (SignalSet) MarshalJSON

func (ss SignalSet) MarshalJSON() ([]byte, error)

MarshalJSON marshals the signal set as a JSON object mapping GNSS constellation names to signal name arrays.

func (SignalSet) Signals

func (ss SignalSet) Signals() func(yield func(Signal) bool)

Signals returns an iterator that yields each signal in the SignalSet.

func (SignalSet) String

func (ss SignalSet) String() string

String returns a human-readable representation of the SignalSet in the form "GPS[L1,L5],GAL[E1,E5b]" This leaves " C/A" off the end of the signal name to keep things short.

func (*SignalSet) UnmarshalJSON

func (ss *SignalSet) UnmarshalJSON(data []byte) error

UnmarshalJSON unmarshals a JSON object mapping GNSS constellation names to signal name arrays into a SignalSet.

type SolutionDim

type SolutionDim uint8

SolutionDim describes dimensionality for a GNSS position/time solution. It is only meaningful when FixLevel >= FixLevelCode. The zero value means "not provided" or "not applicable".

const (
	// SolutionDim2D indicates a two-dimensional solution where height is fixed
	// or constrained and only horizontal position is solved.
	SolutionDim2D SolutionDim = iota + 1

	// SolutionDim3D indicates a full three-dimensional solution where
	// position and clock bias are fully estimated.
	SolutionDim3D

	// SolutionDimTimeOnly indicates a solution where only time (and possibly
	// clock bias) is solved, without a valid position.
	SolutionDimTimeOnly
)

func (SolutionDim) MarshalJSON

func (d SolutionDim) MarshalJSON() ([]byte, error)

func (SolutionDim) MarshalText

func (d SolutionDim) MarshalText() ([]byte, error)

func (SolutionDim) String

func (d SolutionDim) String() string

func (*SolutionDim) UnmarshalText

func (d *SolutionDim) UnmarshalText(text []byte) error

type Speed

type Speed int64

Speed represents a speed in micrometers per second.

const (
	MicrometerPerSecond Speed = 1
	MillimeterPerSecond Speed = 1000 * MicrometerPerSecond
	CentimeterPerSecond Speed = 10 * MillimeterPerSecond
	MeterPerSecond      Speed = 100 * CentimeterPerSecond
)

func MetersPerSecondFromFloat

func MetersPerSecondFromFloat(f float64) Speed

MetersPerSecondFromFloat creates a Speed from a float64 value in meters per second.

func (Speed) MarshalJSON

func (s Speed) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (Speed) MarshalText

func (s Speed) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler.

func (Speed) MetersPerSecond

func (s Speed) MetersPerSecond() float64

MetersPerSecond returns the speed in meters per second as a float64.

func (Speed) String

func (s Speed) String() string

func (*Speed) UnmarshalJSON

func (sp *Speed) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

func (*Speed) UnmarshalText

func (sp *Speed) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler.

type Survey

type Survey struct {
	Flags    SurveyFlags   // control survey behavior
	MinDur   time.Duration // survey should run at least this long
	AccLimit Length        // survey should run until this accuracy is achieved
}

Survey specifies the parameters for performing a survey-in.

type SurveyFlags

type SurveyFlags int
const (
	SurveyAgain SurveyFlags = 1 << iota // do a survey even if we have done one already
)

type SurveyMsg

type SurveyMsg struct {
	Position   Point3D  `json:"position,omitzero"`
	Accuracy   Length   `json:"accuracy"`
	ObsCount   uint32   `json:"obsCount"`
	ObsTime    Duration `json:"obsTime"`
	Valid      bool     `json:"valid"`
	InProgress bool     `json:"inProgress"`
}

func (*SurveyMsg) Dispatch

func (m *SurveyMsg) Dispatch(h MsgHandler, t time.Time)

type Tag

type Tag string

Tag identifies the kind of packet

const EmptyTag Tag = ""

func (Tag) IsZero

func (t Tag) IsZero() bool

type TimeEstimate

type TimeEstimate struct {
	EstimatedTime  time.Time             // the estimated wall-clock time
	TimeOfEstimate time.Time             // the monotonic time at which the estimate was made
	Accuracy       time.Duration         // the accuracy of the estimate
	LeapSecond     ptime.LeapSecondState // leap second information, if known
	Trusted        bool                  // whether the estimate is trusted
}

TimeEstimate represents an estimate of the current UTC time that can be provided to the GPS receiver. An EstimatedTime of zero means that no estimate is available. If TimeOfEstimate is non-zero, the EstimatedTime to be sent to the GPS receiver will be adjusted by the elapsed time between the time at which the estimate is sent and TimeOfEstimate. If TimeOfEstimate is zero, then the EstimatedTime is sent as-is, which is useful for testing purposes. For a system time generated by time.Now(), EstimatedTime and TimeOfEstimate will be the same. If EstimatedTime is non-zero, then the Accuracy must also be non-zero.

type TimeMode

type TimeMode byte
const (
	TimeModeDisabled TimeMode = iota + 1
	TimeModeSurvey
	TimeModeFixed
)

type TimeModeSet

type TimeModeSet byte
const (
	TimeModeNone TimeModeSet = 0
	TimeModeAny  TimeModeSet = 1<<TimeModeDisabled | 1<<TimeModeSurvey | 1<<TimeModeFixed
)

func TimeModeFlags

func TimeModeFlags(ms ...TimeMode) TimeModeSet

func (TimeModeSet) Contains

func (m TimeModeSet) Contains(t TimeMode) bool

type TimeMsg

type TimeMsg struct {
	TAITime     ptime.Time     `json:"taiTime,omitempty"`
	UTCTime     *ptime.UTCTime `json:"utcTime,omitempty"`
	Accuracy    time.Duration  `json:"accuracy,omitempty"`
	UTCOffset   uint8          `json:"utcOffset,omitempty"`
	PulseOffset *float64       `json:"pulseOffset,omitempty"` // the true time of the top of second is the time of the pulse plus the PulseOffset
	GNSS        GNSS           `json:"gnss,omitempty"`
	Ref         TimeRef        `json:"ref,omitempty"`
	Tag         Tag            `json:"tag,omitempty"`
	NativeMsgID string         `json:"nativeMsgID,omitempty"`
}

func (*TimeMsg) ComputeTAITime

func (msg *TimeMsg) ComputeTAITime(ls ptime.LeapSecond) (ptime.Time, bool)

ComputeTAITime computes the TAI time from this message, using the leap second for UTC conversion if needed

func (*TimeMsg) Dispatch

func (m *TimeMsg) Dispatch(h MsgHandler, t time.Time)

type TimePulse

type TimePulse struct {
	Width          time.Duration // width of 0 means disabled
	Period         time.Duration
	AlignToGNSS    bool
	OnlyWhenLocked bool
	PolarityRising bool
}

TimePulse represents the time pulse configuration settings

type TimeRef

type TimeRef int
const (
	NavSolution TimeRef = iota // a message provding part of the result of a navigation solution (e.g. UBX-NAV-TIMEGPS)
	PrePulse                   // a message that is emitted before a pulse (e.g. UBX-TIM-TP)
	PostPulse                  // a message that is emitted immediately after a pulse (e.g. UBX-TIM-TOS)
)

func (TimeRef) String

func (i TimeRef) String() string

type TimeTicker

type TimeTicker struct {
	DefaultHandler
	// contains filtered or unexported fields
}

TimeTicker produces one filled-in TimeMsg per navigation epoch. It stores the first non-PrePulse TimeMsg each epoch, fills in derived fields (TAITime, UTCTime, UTCOffset), and forwards the result immediately to a downstream MsgHandler. NavEpoch resets the state for the next epoch.

func NewTimeTicker

func NewTimeTicker(h MsgHandler, ls ptime.LeapSecond) *TimeTicker

NewTimeTicker creates a TimeTicker that forwards filled TimeMsgs to h.

func (*TimeTicker) LeapSecond

func (t *TimeTicker) LeapSecond(msg *LeapSecondMsg, _ time.Time)

LeapSecond updates the stored leap second.

func (*TimeTicker) NavEpoch

func (t *TimeTicker) NavEpoch(_ *NavEpochMsg, _ time.Time)

NavEpoch clears the stored TimeMsg, preparing for the next epoch.

func (*TimeTicker) SetLeapSecond

func (t *TimeTicker) SetLeapSecond(ls ptime.LeapSecond)

SetLeapSecond replaces the stored leap second.

func (*TimeTicker) Time

func (t *TimeTicker) Time(msg *TimeMsg, tRead time.Time)

Time filters, fills, and forwards one TimeMsg per epoch.

type VelECEFMsg

type VelECEFMsg struct {
	Vel         [3]Speed    `json:"vel"` // ECEF VX, VY, VZ
	Priority    MsgPriority `json:"-"`
	Tag         Tag         `json:"tag"`
	NativeMsgID string      `json:"nativeMsgID"`
}

VelECEFMsg is velocity in the ECEF frame.

func (*VelECEFMsg) Dispatch

func (m *VelECEFMsg) Dispatch(h MsgHandler, t time.Time)

func (*VelECEFMsg) Merge

func (m *VelECEFMsg) Merge(other *VelECEFMsg)

Merge incorporates fields from other into m based on priority.

func (*VelECEFMsg) SetPriority

func (m *VelECEFMsg) SetPriority(pri MsgPriority)

type VelGeoMsg

type VelGeoMsg struct {
	VelNED      opt.Val[[3]Speed] `json:"velNED,omitzero"`      // north, east, down
	GroundSpeed opt.Val[Speed]    `json:"groundSpeed,omitzero"` // 2D ground speed
	Speed3D     opt.Val[Speed]    `json:"speed3D,omitzero"`     // 3D speed
	Course      opt.Val[Angle]    `json:"course,omitzero"`      // course over ground, true north
	Priority    MsgPriority       `json:"-"`
	Tag         Tag               `json:"tag"`
	NativeMsgID string            `json:"nativeMsgID"`
}

VelGeoMsg is velocity in the local geodetic frame.

func (*VelGeoMsg) Dispatch

func (m *VelGeoMsg) Dispatch(h MsgHandler, t time.Time)

func (*VelGeoMsg) Merge

func (m *VelGeoMsg) Merge(other *VelGeoMsg)

Merge incorporates fields from other into m based on priority.

func (*VelGeoMsg) SetPriority

func (m *VelGeoMsg) SetPriority(pri MsgPriority)

Jump to

Keyboard shortcuts

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