add string type enums and retry config
Publish / release (push) Successful in 1m23s

This commit is contained in:
2026-06-23 22:35:26 -04:00
parent 9b0e05d477
commit 9e94696363
6 changed files with 266 additions and 23 deletions
+12 -12
View File
@@ -32,7 +32,7 @@ type Aircraft struct {
// indicates a non-ICAO address (TIS-B).
Hex string `json:"hex"`
// Type is the message source/type, e.g. "adsb_icao", "mode_s", "mlat".
Type string `json:"type"`
Type MessageType `json:"type"`
// Flight is the callsign. readsb space-pads it; use Callsign for a trimmed value.
Flight string `json:"flight,omitempty"`
// Registration (r) and aircraft type (t) come from an optional database.
@@ -61,9 +61,9 @@ type Aircraft struct {
// Squawk is the Mode A code as 4 octal digits.
Squawk string `json:"squawk,omitempty"`
// Emergency is the emergency/priority status; "none" when not declared.
Emergency string `json:"emergency,omitempty"`
Emergency EmergencyStatus `json:"emergency,omitempty"`
// Category is the emitter category, e.g. "A0".."A7", "B0".. (see README-json).
Category string `json:"category,omitempty"`
Category EmitterCategory `json:"category,omitempty"`
// Lat/Lon are the last known position in decimal degrees.
Lat float64 `json:"lat,omitempty"`
@@ -89,14 +89,14 @@ type Aircraft struct {
NavModes []string `json:"nav_modes,omitempty"`
// ADS-B version and quality/accuracy indicators.
Version int `json:"version,omitempty"`
NICBaro int `json:"nic_baro,omitempty"`
NACP int `json:"nac_p,omitempty"`
NACV int `json:"nac_v,omitempty"`
SIL int `json:"sil,omitempty"`
SILType string `json:"sil_type,omitempty"`
GVA int `json:"gva,omitempty"`
SDA int `json:"sda,omitempty"`
Version int `json:"version,omitempty"`
NICBaro int `json:"nic_baro,omitempty"`
NACP int `json:"nac_p,omitempty"`
NACV int `json:"nac_v,omitempty"`
SIL int `json:"sil,omitempty"`
SILType SILType `json:"sil_type,omitempty"`
GVA int `json:"gva,omitempty"`
SDA int `json:"sda,omitempty"`
// Alert and special position identification flags.
Alert int `json:"alert,omitempty"`
@@ -133,7 +133,7 @@ func (a Aircraft) HasPosition() bool { return a.Lat != 0 || a.Lon != 0 }
// InEmergency reports whether a non-routine emergency/priority code is set.
func (a Aircraft) InEmergency() bool {
return a.Emergency != "" && a.Emergency != "none"
return a.Emergency != "" && a.Emergency != EmergencyNone
}
// SeenFor returns the time since the last message was received.
+96
View File
@@ -0,0 +1,96 @@
package readsb
// MessageType is the source/type of an aircraft's data (the "type" field). It is
// a named string so callers can compare against typed constants; it decodes from
// and encodes to JSON exactly like a plain string. readsb lists these values in
// descending order of trustworthiness in README-json.md.
type MessageType string
const (
TypeADSBICAO MessageType = "adsb_icao" // Mode S/ADS-B transponder, ICAO address
TypeADSBICAONT MessageType = "adsb_icao_nt" // ADS-B non-transponder emitter, ICAO address
TypeADSRICAO MessageType = "adsr_icao" // ADS-B rebroadcast (e.g. UAT), ICAO address
TypeTISBICAO MessageType = "tisb_icao" // TIS-B about a non-ADS-B target, ICAO address
TypeADSC MessageType = "adsc" // ADS-C via satellite downlink
TypeMLAT MessageType = "mlat" // position from multilateration
TypeOther MessageType = "other" // miscellaneous Basestation/SBS data
TypeModeS MessageType = "mode_s" // Mode S only, no position
TypeADSBOther MessageType = "adsb_other" // ADS-B transponder, non-ICAO address
TypeADSROther MessageType = "adsr_other" // ADS-B rebroadcast, non-ICAO address
TypeTISBOther MessageType = "tisb_other" // TIS-B about a non-ADS-B target, non-ICAO address
TypeTISBTrackfile MessageType = "tisb_trackfile" // TIS-B keyed by track/file id (radar)
)
// EmitterCategory is the ADS-B emitter category (the "category" field): a class
// letter A-D and a digit 0-7. The A0/B0/C0/D0 codes mean "no category info"; the
// remaining D codes and a few others are reserved. Decodes/encodes as a string.
type EmitterCategory string
const (
CatNoInfo EmitterCategory = "A0" // also B0/C0/D0: no category information
CatLight EmitterCategory = "A1" // < 15,500 lb
CatSmall EmitterCategory = "A2" // 15,500-75,000 lb
CatLarge EmitterCategory = "A3" // 75,000-300,000 lb
CatHighVortex EmitterCategory = "A4" // high-vortex large, e.g. B757
CatHeavy EmitterCategory = "A5" // > 300,000 lb
CatHighPerf EmitterCategory = "A6" // > 5g and > 400 kt
CatRotorcraft EmitterCategory = "A7"
CatGlider EmitterCategory = "B1" // glider / sailplane
CatLighterThanAir EmitterCategory = "B2"
CatParachutist EmitterCategory = "B3" // parachutist / skydiver
CatUltralight EmitterCategory = "B4" // ultralight / hang-glider / paraglider
CatUAV EmitterCategory = "B6" // unmanned aerial vehicle
CatSpace EmitterCategory = "B7" // space / transatmospheric vehicle
CatSurfaceEmergency EmitterCategory = "C1" // surface vehicle, emergency
CatSurfaceService EmitterCategory = "C2" // surface vehicle, service
CatPointObstacle EmitterCategory = "C3" // point obstacle (incl. tethered balloons)
CatClusterObstacle EmitterCategory = "C4"
CatLineObstacle EmitterCategory = "C5"
)
// catDescriptions maps every defined emitter code (including reserved ones) to a
// human label. Codes absent from the map are undefined.
var catDescriptions = map[EmitterCategory]string{
"A0": "no information", "A1": "light", "A2": "small", "A3": "large",
"A4": "high-vortex large", "A5": "heavy", "A6": "high performance", "A7": "rotorcraft",
"B0": "no information", "B1": "glider/sailplane", "B2": "lighter-than-air",
"B3": "parachutist", "B4": "ultralight", "B5": "reserved",
"B6": "unmanned aerial vehicle", "B7": "space/transatmospheric",
"C0": "no information", "C1": "surface emergency vehicle", "C2": "surface service vehicle",
"C3": "point obstacle", "C4": "cluster obstacle", "C5": "line obstacle",
"C6": "reserved", "C7": "reserved",
"D0": "no information", "D1": "reserved", "D2": "reserved", "D3": "reserved",
"D4": "reserved", "D5": "reserved", "D6": "reserved", "D7": "reserved",
}
// Description returns the human-readable label for the emitter category, or ""
// if the code is not a defined A0-D7 value.
func (c EmitterCategory) Description() string { return catDescriptions[c] }
// EmergencyStatus is the emergency/priority status (the "emergency" field).
// EmergencyNone means no emergency is declared. Decodes/encodes as a string.
type EmergencyStatus string
const (
EmergencyNone EmergencyStatus = "none"
EmergencyGeneral EmergencyStatus = "general"
EmergencyLifeguard EmergencyStatus = "lifeguard" // medical/lifeguard flight
EmergencyMinFuel EmergencyStatus = "minfuel" // minimum fuel
EmergencyNoRadio EmergencyStatus = "nordo" // no radio communication
EmergencyUnlawful EmergencyStatus = "unlawful" // unlawful interference
EmergencyDowned EmergencyStatus = "downed" // downed aircraft
EmergencyReserved EmergencyStatus = "reserved"
)
// SILType describes how the SIL (source integrity level) probability is scaled
// (the "sil_type" field): per flight hour or per sample. Decodes/encodes as a string.
type SILType string
const (
SILUnknown SILType = "unknown"
SILPerHour SILType = "perhour"
SILPerSample SILType = "persample"
)
+17 -8
View File
@@ -66,16 +66,16 @@ func WithSquawk(codes ...string) AircraftFilter {
return func(a *Aircraft) bool { return set[strings.ToLower(a.Squawk)] }
}
// WithCategory keeps aircraft of any of the given emitter categories (e.g. "A3").
func WithCategory(cats ...string) AircraftFilter {
set := lowerSet(nil, cats, "")
return func(a *Aircraft) bool { return set[strings.ToLower(a.Category)] }
// WithCategory keeps aircraft of any of the given emitter categories (e.g. CatLarge).
func WithCategory(cats ...EmitterCategory) AircraftFilter {
set := lowerSet(nil, strs(cats), "")
return func(a *Aircraft) bool { return set[strings.ToLower(string(a.Category))] }
}
// WithType keeps aircraft of any of the given source types (e.g. "adsb_icao", "mlat").
func WithType(types ...string) AircraftFilter {
set := lowerSet(nil, types, "")
return func(a *Aircraft) bool { return set[strings.ToLower(a.Type)] }
// WithType keeps aircraft of any of the given source types (e.g. TypeADSBICAO, TypeMLAT).
func WithType(types ...MessageType) AircraftFilter {
set := lowerSet(nil, strs(types), "")
return func(a *Aircraft) bool { return set[strings.ToLower(string(a.Type))] }
}
// InEmergency keeps only aircraft squawking a non-routine emergency/priority code.
@@ -138,6 +138,15 @@ func Any(filters ...AircraftFilter) AircraftFilter {
// lowerSet builds a lowercased lookup set, optionally pre-processing each value
// with trim(value, cut) when trim is non-nil.
// strs widens a slice of any string-kind type to []string for the set helpers.
func strs[T ~string](in []T) []string {
out := make([]string, len(in))
for i, v := range in {
out[i] = string(v)
}
return out
}
func lowerSet(trim func(string, string) string, values []string, cut string) map[string]bool {
set := make(map[string]bool, len(values))
for _, v := range values {