Files
ham/protocol/adsb/fields/bds05.go
maze 32f6c38c13
Some checks failed
Run tests / test (1.25) (push) Failing after 15s
Run tests / test (stable) (push) Failing after 17s
Fixed code smells
2026-02-22 21:14:58 +01:00

159 lines
5.0 KiB
Go

package fields
// SurveillanceStatus is the surveillance status
//
// Specified in Doc 9871 / A.2.3.2.6
type SurveillanceStatus byte
const (
SSNoCondition SurveillanceStatus = iota // No aircraft category information
SSPermanentAlert // Permanent alert (emergency condition)
SSTemporaryAlert // Temporary alert (change in Mode A identity code other than emergency condition)
SSSPICondition // SPI condition
)
// AltitudeSource is the type of source of the Altitude: Barometric or GNSS.
type AltitudeSource byte
const (
AltitudeBarometric AltitudeSource = iota // Altitude is barometric altitude
AltitudeGNSS // Altitude is GNSS height (HAE)
)
// AltitudeReportMethod defines how the altitude is reported.
type AltitudeReportMethod byte
const (
AltitudeReport100FootIncrements AltitudeReportMethod = iota // 100-foot increments
AltitudeReport25FootIncrements // 25-foot increments
)
// CompactPositionReportingFormat is the CPR (Compact Position Reporting) format definition
//
// Specified in Doc 9871 / A.2.3.3.3
type CompactPositionReportingFormat byte
const (
CPRFormatEven CompactPositionReportingFormat = iota // Even format coding
CPRFormatOdd // Odd format coding
)
func ParseCompactPositioningReportFormat(data []byte) CompactPositionReportingFormat {
bits := (data[2] & 0x04) >> 2
return CompactPositionReportingFormat(bits)
}
func ParseAltitude(data []byte) (altitude int32, source AltitudeSource, method AltitudeReportMethod, err error) {
source = AltitudeBarometric
if format := (data[0] & 0xF8) >> 3; 20 <= format && format <= 22 {
source = AltitudeGNSS
}
// Altitude code is a 12 bits fields, so read a uint16
// bit | 8 9 10 11 12 13 14 15| 16 17 18 19 20 21 22 23 |
// message | x x x x x x x x| x x x x _ _ _ _ |
// 100 foot |C1 A1 C2 A2 C4 A4 B1 Q| B2 D2 B4 D4 _ _ _ _ |
// Get the Q bit
if qBit := (data[1] & 0x01) != 0; qBit {
// If the Q bit equals 1, the 11-bit field represented by bits 8 to 14 and 16 to 18
n := uint16(0)
n |= uint16(data[1]&0xFE) << 3
n |= uint16(data[2]&0xF0) >> 4
return 25*int32(n) - 1000, source, AltitudeReport25FootIncrements, nil
}
// Otherwise, altitude is reported in 100 foot increments
c1 := (data[1] & 0x80) != 0
a1 := (data[1] & 0x40) != 0
c2 := (data[1] & 0x20) != 0
a2 := (data[1] & 0x10) != 0
c4 := (data[1] & 0x08) != 0
a4 := (data[1] & 0x04) != 0
b1 := (data[1] & 0x02) != 0
b2 := (data[2] & 0x80) != 0
d2 := (data[2] & 0x40) != 0
b4 := (data[2] & 0x20) != 0
d4 := (data[2] & 0x10) != 0
if altitude, err = GillhamToAltitude(false, d2, d4, a1, a2, a4, b1, b2, b4, c1, c2, c4); err != nil {
return
}
return
}
// MovementStatus is the status of the Movement information
type MovementStatus int
const (
// MSNoInformation indicates no information
MSNoInformation MovementStatus = 0 // No information
MSAircraftStopped MovementStatus = 1 // The aircraft is stopped
MSAboveMaximum MovementStatus = 124 // The Movement is above the maximum
MSReservedDecelerating MovementStatus = 125 // Reserved
MSReservedAccelerating MovementStatus = 126 // Reserved
MSReservedBackingUp MovementStatus = 127 // Reserved
)
func ParseMovementStatus(data []byte) (float64, MovementStatus) {
bits := (data[0]&0x07)<<4 + (data[1]&0xF0)>>4
status := MovementStatus(bits)
return status.Speed(), status
}
// Speed in knots.
func (status MovementStatus) Speed() float64 {
if status == 0 || status == 1 || status > 124 {
return 0
} else if 2 <= status && status <= 8 {
return 0.125 + float64(status-2)*0.125
} else if 9 <= status && status <= 12 {
return 1 + float64(status-9)*0.25
} else if 13 <= status && status <= 38 {
return 2 + float64(status-13)*0.5
} else if 39 <= status && status <= 93 {
return 15 + float64(status-39)*1.0
} else if 94 <= status && status <= 108 {
return 70 + float64(status-94)*2.0
} else if 109 <= status && status <= 123 {
return 100 + float64(status-109)*5.0
}
// Movement max
return 175
}
// EncodedLatitude is the encoded latitude
//
// Specified in Doc 9871 / C.2.6
type EncodedLatitude uint32
func ParseEncodedLatitude(data []byte) EncodedLatitude {
return EncodedLatitude((data[2]&0x02)>>1)<<16 |
EncodedLatitude((data[2]&0x01)<<7+(data[3]&0xFE)>>1)<<8 |
EncodedLatitude((data[3]&0x01)<<7+(data[4]&0xFE)>>1)
}
// EncodedLongitude is the encoded longitude
//
// Specified in Doc 9871 / C.2.6
type EncodedLongitude uint32
func ParseEncodedLongitude(data []byte) EncodedLongitude {
return EncodedLongitude(data[4]&0x01)<<16 |
EncodedLongitude(data[5])<<8 |
EncodedLongitude(data[6])
}
func ParseGroundTrackStatus(data []byte) (track float64, status bool) {
status = (data[1] & 0x08) != 0
allBits := (uint16(data[1]&0x07)<<8 | uint16(data[2]&0xF0)) >> 4
track = float64(allBits) * 360.0 / 128.0
return
}
func ParseTimeSynchronizedToUTC(data []byte) bool {
return ((data[2] & 0x08) >> 3) != 0
}