From aafcd4892c3bf9fb303582369180e94392cc1531 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Wed, 30 Sep 2015 13:36:31 -0400 Subject: [PATCH 1/5] NIC & NACp from @AvSquirrel. --- main/gen_gdl90.go | 13 +++++++++++-- main/ry835ai.go | 26 ++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index 75777086..c427a65d 100644 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -211,7 +211,7 @@ func makeOwnshipReport() bool { msg[12] = msg[12] | 0x0B // "Airborne" + "True Heading" } - msg[13] = 0xBB // NIC and NACp. + msg[13] = byte(0x80 | (mySituation.NACp & 0x0F)) //Set NIC = 8 and use NACp from ry835ai.go. gdSpeed := uint16(0) // 1kt resolution. if isGPSGroundTrackValid() { @@ -239,6 +239,15 @@ func makeOwnshipReport() bool { msg[18] = 0x01 // "Light (ICAO) < 15,500 lbs" + // Create callsign "Stratux". + msg[19] = 0x53 + msg[20] = 0x74 + msg[21] = 0x72 + msg[22] = 0x61 + msg[23] = 0x74 + msg[24] = 0x75 + msg[25] = 0x78 + sendGDL90(prepareMessage(msg), false) return true } @@ -737,7 +746,7 @@ func printStats() { log.Printf("stats [up since: %s]\n", humanize.Time(timeStarted)) log.Printf(" - CPUTemp=%.02f deg C, MemStats.Alloc=%s, MemStats.Sys=%s, totalNetworkMessagesSent=%s\n", globalStatus.CPUTemp, humanize.Bytes(uint64(memstats.Alloc)), humanize.Bytes(uint64(memstats.Sys)), humanize.Comma(int64(totalNetworkMessagesSent))) log.Printf(" - UAT/min %s/%s [maxSS=%.02f%%], ES/min %s/%s\n", humanize.Comma(int64(globalStatus.UAT_messages_last_minute)), humanize.Comma(int64(globalStatus.UAT_messages_max)), float64(maxSignalStrength)/10.0, humanize.Comma(int64(globalStatus.ES_messages_last_minute)), humanize.Comma(int64(globalStatus.ES_messages_max))) - log.Printf(" - Total traffic targets tracked=%s, last GPS fix: %s\n", humanize.Comma(int64(len(seenTraffic))), humanize.Time(mySituation.LastFixLocalTime)) + log.Printf(" - Total traffic targets tracked=%s, last GPS fix: %s, GPS solution type: %d, NACp: %d, est accuracy %.02f m\n", humanize.Comma(int64(len(seenTraffic))), humanize.Time(mySituation.LastFixLocalTime), mySituation.quality, mySituation.NACp, mySituation.Accuracy) } } diff --git a/main/ry835ai.go b/main/ry835ai.go index 334c1ca2..d58d2d68 100644 --- a/main/ry835ai.go +++ b/main/ry835ai.go @@ -31,6 +31,7 @@ type SituationData struct { quality uint8 Satellites uint16 Accuracy float32 // Meters. + NACp uint8 // NACp categories are defined in AC 20-165A Alt float32 // Feet. alt_accuracy float32 LastFixLocalTime time.Time @@ -266,7 +267,7 @@ func processNMEALine(l string) bool { if err1 != nil { return false } - mySituation.quality = uint8(q) + mySituation.quality = uint8(q) // 1 = 3D GPS; 2 = DGPS (SBAS /WAAS) // Satellites. sat, err1 := strconv.Atoi(x[7]) @@ -280,7 +281,28 @@ func processNMEALine(l string) bool { if err1 != nil { return false } - mySituation.Accuracy = float32(hdop * 5.0) //FIXME: 5 meters ~ 1.0 HDOP? + if mySituation.quality == 2 { + mySituation.Accuracy = float32(hdop * 4.0) //Estimate for WAAS / DGPS solution + } else { + mySituation.Accuracy = float32(hdop * 8.0) //Estimate for 3D non-WAAS solution + } + + // NACp estimate. + if mySituation.Accuracy < 3 { + mySituation.NACp = 11 + } else if mySituation.Accuracy < 10 { + mySituation.NACp = 10 + } else if mySituation.Accuracy < 30 { + mySituation.NACp = 9 + } else if mySituation.Accuracy < 92.6 { + mySituation.NACp = 8 + } else if mySituation.Accuracy < 185.2 { + mySituation.NACp = 7 + } else if mySituation.Accuracy < 555.6 { + mySituation.NACp = 6 + } else { + mySituation.NACp = 0 + } // Altitude. alt, err1 := strconv.ParseFloat(x[9], 32) From 2661c865609c3b9465417f502277acba1cf2c7fe Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Wed, 30 Sep 2015 18:52:52 -0400 Subject: [PATCH 2/5] Skip traffic targets on websocket with no valid position. --- main/managementinterface.go | 3 +++ main/traffic.go | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/main/managementinterface.go b/main/managementinterface.go index 8332ce21..4343ff08 100644 --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -43,6 +43,9 @@ func handleWeatherWS(conn *websocket.Conn) { func handleTrafficWS(conn *websocket.Conn) { trafficMutex.Lock() for _, traf := range traffic { + if !traf.Position_valid { // Don't send unless a valid position exists. + continue + } trafficJSON, _ := json.Marshal(&traf) conn.Write(trafficJSON) } diff --git a/main/traffic.go b/main/traffic.go index 3448d590..f646352f 100644 --- a/main/traffic.go +++ b/main/traffic.go @@ -96,7 +96,9 @@ func sendTrafficUpdates() { // Send update to attached client. func registerTrafficUpdate(ti TrafficInfo) { - trafficUpdate <- ti + if ti.Position_valid { // Don't send unless a valid position exists. + trafficUpdate <- ti + } } func makeTrafficReport(ti TrafficInfo) { From baae410a3f2beb607b2a4c008139e0266bc9f4b8 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Wed, 30 Sep 2015 21:06:38 -0400 Subject: [PATCH 3/5] Stratux heartbeat. --- main/gen_gdl90.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index c427a65d..f897ca88 100644 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -273,6 +273,33 @@ func makeOwnshipGeometricAltitudeReport() bool { return true } +/* + + "Stratux" GDL90 message. + + Message ID 0xCC. + Byte1: p p p p p p GPS AHRS + First 6 bytes are protocol version codes. + Protocol 1: GPS on/off | AHRS on/off. +*/ + +func makeStratuxHeartbeat() []byte { + msg := make([]byte, 2) + msg[0] = 0xCC // Message type "Stratux". + msg[1] = 0 + if isGPSValid() { + msg[1] = 0x02 + } + if isAHRSValid() { + msg[1] = msg[1] | 0x01 + } + + protocolVers := int8(1) + msg[1] = msg[1] | byte(protocolVers << 2) + + return prepareMessage(msg) +} + func makeHeartbeat() []byte { msg := make([]byte, 7) // See p.10. @@ -321,6 +348,7 @@ func heartBeatSender() { select { case <-timer.C: sendGDL90(makeHeartbeat(), false) + sendGDL90(makeStratuxHeartbeat(), false) // sendGDL90(makeTrafficReport()) makeOwnshipReport() makeOwnshipGeometricAltitudeReport() From c842cbe59529d5c777574d6c541ca7e7483c1b89 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Thu, 1 Oct 2015 16:10:35 -0400 Subject: [PATCH 4/5] Traffic source tracking. --- main/traffic.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/main/traffic.go b/main/traffic.go index f646352f..7d093570 100644 --- a/main/traffic.go +++ b/main/traffic.go @@ -48,6 +48,11 @@ AUXSV: */ +const ( + TRAFFIC_SOURCE_1090ES = 1 + TRAFFIC_SOURCE_UAT = 2 +) + type TrafficInfo struct { Icao_addr uint32 addr_type uint8 @@ -68,7 +73,8 @@ type TrafficInfo struct { Tail string - Last_seen time.Time + Last_seen time.Time + Last_source uint8 } var traffic map[uint32]TrafficInfo @@ -328,6 +334,7 @@ func parseDownlinkReport(s string) { //OK. // fmt.Printf("tisb_site_id %d, utc_coupled %t\n", tisb_site_id, utc_coupled) + ti.Last_source = TRAFFIC_SOURCE_UAT ti.Last_seen = time.Now() // Parse tail number, if available. @@ -499,6 +506,7 @@ func esListen() { } // Update "last seen" (any type of message, as long as the ICAO addr can be parsed). + ti.Last_source = TRAFFIC_SOURCE_1090ES ti.Last_seen = time.Now() ti.addr_type = 0 //FIXME: ADS-B with ICAO address. Not recognized by ForeFlight. From 6ba4009f1ba129f2f6edd332003e782618e19ff4 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Thu, 1 Oct 2015 16:21:41 -0400 Subject: [PATCH 5/5] Rename /control to /status (JS). --- web/plates/js/status.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/plates/js/status.js b/web/plates/js/status.js index a10b832c..7e50eaff 100755 --- a/web/plates/js/status.js +++ b/web/plates/js/status.js @@ -11,8 +11,8 @@ function StatusCtrl($rootScope, $scope, $state, $http) { return; // we are getting called once after clicking away from the status page if (($scope.socket === undefined) || ($scope.socket === null)) { - // socket = new WebSocket('ws://' + window.location.hostname + '/control'); - socket = new WebSocket('ws://' + URL_HOST_BASE + '/control'); + // socket = new WebSocket('ws://' + window.location.hostname + '/status'); + socket = new WebSocket('ws://' + URL_HOST_BASE + '/status'); $scope.socket = socket; // store socket in scope for enter/exit usage } @@ -104,4 +104,4 @@ function StatusCtrl($rootScope, $scope, $state, $http) { // Status Controller tasks setHardwareVisibility(); connect($scope); // connect - opens a socket and listens for messages -}; \ No newline at end of file +};