159 lines
5.0 KiB
Go
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
|
|
}
|