kopia lustrzana https://github.com/cyoung/stratux
Add emergency status to traffic msgs; additional UAT statistics; cleanup
rodzic
950c0594bf
commit
318e883db5
141
main/traffic.go
141
main/traffic.go
|
@ -97,6 +97,7 @@ type TrafficInfo struct {
|
||||||
Speed_valid bool // set when speed report received.
|
Speed_valid bool // set when speed report received.
|
||||||
Vvel int16 // feet per minute
|
Vvel int16 // feet per minute
|
||||||
Timestamp time.Time // timestamp of traffic message, UTC
|
Timestamp time.Time // timestamp of traffic message, UTC
|
||||||
|
PriorityStatus uint8 // Emergency or priority code as defined in GDL90 spec, DO-260B (Type 28 msg) and DO-282B
|
||||||
|
|
||||||
// Parameters starting at 'Age' are calculated from last message receipt on each call of sendTrafficUpdates().
|
// Parameters starting at 'Age' are calculated from last message receipt on each call of sendTrafficUpdates().
|
||||||
// Mode S transmits position and track in separate messages, and altitude can also be
|
// Mode S transmits position and track in separate messages, and altitude can also be
|
||||||
|
@ -348,6 +349,9 @@ func makeTrafficReportMsg(ti TrafficInfo) []byte {
|
||||||
msg[19+i] = c
|
msg[19+i] = c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//msg[27] is priority / emergency status per GDL90 spec (DO260B and DO282B are same codes)
|
||||||
|
msg[27] = ti.PriorityStatus << 4
|
||||||
|
|
||||||
return prepareMessage(msg)
|
return prepareMessage(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,68 +398,107 @@ func parseDownlinkReport(s string, signalLevel int) {
|
||||||
|
|
||||||
// Extract parameters from Mode Status elements, if available.
|
// Extract parameters from Mode Status elements, if available.
|
||||||
if msg_type == 1 || msg_type == 3 {
|
if msg_type == 1 || msg_type == 3 {
|
||||||
|
|
||||||
// Determine UAT message version. This is needed for some capability decoding and is useful for debugging.
|
// Determine UAT message version. This is needed for some capability decoding and is useful for debugging.
|
||||||
uat_version = (frame[23] >> 2) % 0x08
|
uat_version = (frame[23] >> 2) & 0x07
|
||||||
//log.Printf("%06X: UAT version %v\n",icao_addr,uat_version)
|
|
||||||
|
|
||||||
// Extract emitter category.
|
// Extract emitter category.
|
||||||
if msg_type == 1 || msg_type == 3 {
|
|
||||||
v := (uint16(frame[17]) << 8) | (uint16(frame[18]))
|
|
||||||
ti.Emitter_category = uint8((v / 1600) % 40)
|
|
||||||
|
|
||||||
// Decode callsign or Flight Plan ID (i.e. squawk code)
|
v := (uint16(frame[17]) << 8) | (uint16(frame[18]))
|
||||||
// If the CSID bit (byte 27, bit 7) is set to 1, all eight characters
|
ti.Emitter_category = uint8((v / 1600) % 40)
|
||||||
// encoded in bytes 18-23 represent callsign.
|
|
||||||
// If the CSID bit is set to 0, the first four characters encoded in bytes 18-23
|
|
||||||
// represent the Mode A squawk code.
|
|
||||||
|
|
||||||
csid := (frame[26] >> 1) & 0x01
|
// Decode callsign or Flight Plan ID (i.e. squawk code)
|
||||||
|
// If the CSID bit (byte 27, bit 7) is set to 1, all eight characters
|
||||||
|
// encoded in bytes 18-23 represent callsign.
|
||||||
|
// If the CSID bit is set to 0, the first four characters encoded in bytes 18-23
|
||||||
|
// represent the Mode A squawk code.
|
||||||
|
|
||||||
if csid == 1 { // decode as callsign
|
csid := (frame[26] >> 1) & 0x01
|
||||||
//log.Printf("CSID == 1. Decoding callsign.\n")
|
|
||||||
base40_alphabet := string("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ..")
|
|
||||||
tail := ""
|
|
||||||
|
|
||||||
v := (uint16(frame[17]) << 8) | uint16(frame[18])
|
if csid == 1 { // decode as callsign
|
||||||
tail += string(base40_alphabet[(v/40)%40])
|
base40_alphabet := string("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ..")
|
||||||
tail += string(base40_alphabet[v%40])
|
tail := ""
|
||||||
v = (uint16(frame[19]) << 8) | uint16(frame[20])
|
|
||||||
tail += string(base40_alphabet[(v/1600)%40])
|
|
||||||
tail += string(base40_alphabet[(v/40)%40])
|
|
||||||
tail += string(base40_alphabet[v%40])
|
|
||||||
v = (uint16(frame[21]) << 8) | uint16(frame[22])
|
|
||||||
tail += string(base40_alphabet[(v/1600)%40])
|
|
||||||
tail += string(base40_alphabet[(v/40)%40])
|
|
||||||
tail += string(base40_alphabet[v%40])
|
|
||||||
tail = strings.Trim(tail, " ")
|
|
||||||
ti.Tail = tail
|
|
||||||
//log.Printf("Callsign decoded as %s\n",tail)
|
|
||||||
|
|
||||||
} else if uat_version >= 2 { // decode as Mode 3/A code, if UAT version is at least 2
|
v := (uint16(frame[17]) << 8) | uint16(frame[18])
|
||||||
//log.Printf("CSID == 0. Decoding Mode 3/A code.\n")
|
tail += string(base40_alphabet[(v/40)%40])
|
||||||
v := (uint16(frame[17]) << 8) | uint16(frame[18])
|
tail += string(base40_alphabet[v%40])
|
||||||
squawk_a := (v / 40) % 40
|
v = (uint16(frame[19]) << 8) | uint16(frame[20])
|
||||||
squawk_b := v % 40
|
tail += string(base40_alphabet[(v/1600)%40])
|
||||||
v = (uint16(frame[19]) << 8) | uint16(frame[20])
|
tail += string(base40_alphabet[(v/40)%40])
|
||||||
squawk_c := (v / 1600) % 40
|
tail += string(base40_alphabet[v%40])
|
||||||
squawk_d := (v / 40) % 40
|
v = (uint16(frame[21]) << 8) | uint16(frame[22])
|
||||||
squawk := 1000*squawk_a + 100*squawk_b + 10*squawk_c + squawk_d
|
tail += string(base40_alphabet[(v/1600)%40])
|
||||||
ti.Squawk = int(squawk)
|
tail += string(base40_alphabet[(v/40)%40])
|
||||||
//log.Printf("Mode 3/A decoded as %d\n",squawk)
|
tail += string(base40_alphabet[v%40])
|
||||||
}
|
tail = strings.Trim(tail, " ")
|
||||||
|
ti.Tail = tail
|
||||||
|
|
||||||
|
} else if uat_version >= 2 { // decode as Mode 3/A code, if UAT version is at least 2
|
||||||
|
v := (uint16(frame[17]) << 8) | uint16(frame[18])
|
||||||
|
squawk_a := (v / 40) % 40
|
||||||
|
squawk_b := v % 40
|
||||||
|
v = (uint16(frame[19]) << 8) | uint16(frame[20])
|
||||||
|
squawk_c := (v / 1600) % 40
|
||||||
|
squawk_d := (v / 40) % 40
|
||||||
|
squawk := 1000*squawk_a + 100*squawk_b + 10*squawk_c + squawk_d
|
||||||
|
ti.Squawk = int(squawk)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
ti.NACp = int((frame[25] >> 4) & 0x0F)
|
||||||
|
ti.PriorityStatus = (frame[23] >> 5) & 0x07
|
||||||
|
|
||||||
// OK.
|
// Following section is future-use for debugging and / or additional status info on UAT traffic. Message parsing needs testing.
|
||||||
// fmt.Printf("%d, %d, %06X\n", msg_type, ti.Addr_type, ti.Icao_addr)
|
/*
|
||||||
|
//declaration for mode status flags -- parse for debug logging
|
||||||
|
var status_sil byte
|
||||||
|
//var status_transmit_mso byte
|
||||||
|
var status_sda byte
|
||||||
|
//var status_nacv byte
|
||||||
|
//var status_nicbaro byte
|
||||||
|
//var status_sil_supp byte
|
||||||
|
//var status_geom_vert_acc byte
|
||||||
|
//var status_sa_flag byte
|
||||||
|
var capability_uat_in bool
|
||||||
|
var capability_1090_in bool
|
||||||
|
//var capability_tcas bool
|
||||||
|
//var capability_cdti bool
|
||||||
|
//var opmode_tcas_active bool
|
||||||
|
//var opmode_ident_active bool
|
||||||
|
//var opmode_rec_atc_serv bool
|
||||||
|
|
||||||
|
// these are present in v1 and v2 messages
|
||||||
|
status_sil = frame[23] & 0x03
|
||||||
|
//status_transmit_mso = frame[24] >> 2
|
||||||
|
//status_nacv = (frame[25] >> 1) & 0x07
|
||||||
|
//status_nicbaro = frame[25] & 0x01
|
||||||
|
|
||||||
|
// other status and capability bits are different between v1 and v2
|
||||||
|
if uat_version == 2 {
|
||||||
|
status_sda = frame[24] & 0x03
|
||||||
|
capability_uat_in = (frame[26] >> 7) != 0
|
||||||
|
capability_1090_in = ((frame[26] >> 6) & 0x01) != 0
|
||||||
|
//capability_tcas = ((frame[26] >> 5) & 0x01) != 0
|
||||||
|
//opmode_tcas_active = ((frame[26] >> 4) & 0x01) != 0
|
||||||
|
//opmode_ident_active = ((frame[26] >> 3) & 0x01) != 0
|
||||||
|
//opmode_rec_atc_serv = ((frame[26] >> 2) & 0x01) != 0
|
||||||
|
//status_sil_supp = frame[26] & 0x01
|
||||||
|
//status_geom_vert_acc = (frame[27] >> 6) & 0x03
|
||||||
|
//status_sa_flag = (frame[27] >> 5) & 0x01
|
||||||
|
|
||||||
|
} else if uat_version == 1 {
|
||||||
|
//capability_cdti = (frame[26] >> 7) != 0
|
||||||
|
//capability_tcas = ((frame[26] >> 6) & 0x01) != 0
|
||||||
|
//opmode_tcas_active = ((frame[26] >> 5) & 0x01) != 0
|
||||||
|
//opmode_ident_active = ((frame[26] >> 4) & 0x01) != 0
|
||||||
|
//opmode_rec_atc_serv = ((frame[26] >> 3) & 0x01) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Additional UAT mode status for %06X: Version = %d; SIL = %d; SDA = %d; 978 In = %v; 1090 In = %v\n",icao_addr,uat_version,status_sil,status_sda,capability_uat_in,capability_1090_in)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
ti.NIC = int(frame[11] & 0x0F)
|
ti.NIC = int(frame[11] & 0x0F)
|
||||||
|
|
||||||
if (msg_type == 1) || (msg_type == 3) { // Since NACp is passed with normal UATreports, no need to use our ES hack.
|
|
||||||
ti.NACp = int((frame[25] >> 4) & 0x0F)
|
|
||||||
}
|
|
||||||
|
|
||||||
var power float64
|
var power float64
|
||||||
if signalLevel > 0 {
|
if signalLevel > 0 {
|
||||||
power = 20 * (math.Log10(float64(signalLevel) / 1000)) // reported amplitude is 0-1000. Normalize to max = 1 and do amplitude dB calculation (20 dB per decade)
|
power = 20 * (math.Log10(float64(signalLevel) / 1000)) // reported amplitude is 0-1000. Normalize to max = 1 and do amplitude dB calculation (20 dB per decade)
|
||||||
|
@ -625,7 +668,6 @@ func parseDownlinkReport(s string, signalLevel int) {
|
||||||
ti.Last_speed = stratuxClock.Time
|
ti.Last_speed = stratuxClock.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
//OK.
|
|
||||||
// fmt.Printf("ns_vel %d, ew_vel %d, track %d, speed_valid %t, speed %d, vvel_geo %t, vvel %d\n", ns_vel, ew_vel, track, speed_valid, speed, vvel_geo, vvel)
|
// fmt.Printf("ns_vel %d, ew_vel %d, track %d, speed_valid %t, speed %d, vvel_geo %t, vvel %d\n", ns_vel, ew_vel, track, speed_valid, speed, vvel_geo, vvel)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -639,7 +681,6 @@ func parseDownlinkReport(s string, signalLevel int) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//OK.
|
|
||||||
// fmt.Printf("tisb_site_id %d, utc_coupled %t\n", tisb_site_id, utc_coupled)
|
// fmt.Printf("tisb_site_id %d, utc_coupled %t\n", tisb_site_id, utc_coupled)
|
||||||
|
|
||||||
ti.Timestamp = time.Now()
|
ti.Timestamp = time.Now()
|
||||||
|
|
Ładowanie…
Reference in New Issue