diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index dedd01bb..7a03d31f 100644 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -459,8 +459,8 @@ func makeSXHeartbeat() []byte { // Number of GPS satellites locked. msg[16] = byte(globalStatus.GPS_satellites_locked) - //FIXME: Number of satellites connected. ?? - msg[17] = 0xFF + // Number of satellites tracked + msg[17] = byte(globalStatus.GPS_satellites_tracked) // Summarize number of UAT and 1090ES traffic targets for reports that follow. var uat_traffic_targets uint16 @@ -703,10 +703,13 @@ func cpuTempMonitor() { func updateStatus() { if isGPSValid() { globalStatus.GPS_satellites_locked = mySituation.Satellites + globalStatus.GPS_satellites_tracked = mySituation.SatellitesTracked if mySituation.quality == 2 { - globalStatus.GPS_solution = "DGPS (WAAS)" + globalStatus.GPS_solution = "DGPS (SBAS / WAAS)" } else if mySituation.quality == 1 { globalStatus.GPS_solution = "3D GPS" + } else if mySituation.quality == 6 { + globalStatus.GPS_solution = "Dead Reckoning" } else { globalStatus.GPS_solution = "N/A" } @@ -985,6 +988,7 @@ type status struct { ES_messages_last_minute uint ES_messages_max uint GPS_satellites_locked uint16 + GPS_satellites_tracked uint16 GPS_connected bool GPS_solution string RY835AI_connected bool @@ -1107,7 +1111,8 @@ func printStats() { 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, Total traffic targets tracked=%s", 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)), humanize.Comma(int64(len(seenTraffic)))) if globalSettings.GPS_Enabled { - log.Printf(" - Last GPS fix: %s, GPS solution type: %d, NACp: %d, est accuracy %.02f m\n", humanize.Time(mySituation.LastFixLocalTime), mySituation.quality, mySituation.NACp, mySituation.Accuracy) + log.Printf(" - Last GPS fix: %s, GPS solution type: %d using %v satellites (%v tracked), NACp: %d, est accuracy %.02f m\n", humanize.Time(mySituation.LastFixLocalTime), mySituation.quality, mySituation.Satellites, mySituation.SatellitesTracked, mySituation.NACp, mySituation.Accuracy) + log.Printf(" - GPS vertical velocity: %.02f ft/sec; GPS vertical accuracy: %v m\n", mySituation.GPSVertVel, mySituation.AccuracyVert) } } } diff --git a/main/ry835ai.go b/main/ry835ai.go index 62745360..a7bd72b2 100644 --- a/main/ry835ai.go +++ b/main/ry835ai.go @@ -29,12 +29,13 @@ type SituationData struct { Lat float32 Lng float32 quality uint8 - Satellites uint16 + Satellites uint16 // satellites used in solution + SatellitesTracked uint16 // satellites tracked Accuracy float32 // Meters. NACp uint8 // NACp categories are defined in AC 20-165A Alt float32 // Feet. - alt_accuracy float32 - vertVelGPS float32 // GPS vertical velocity, feet per second + AccuracyVert float32 + GPSVertVel float32 // GPS vertical velocity, feet per second LastFixLocalTime time.Time TrueCourse uint16 GroundSpeed uint16 @@ -106,6 +107,8 @@ func initGPSSerial() bool { device = "/dev/ttyAMA0" } log.Printf("Using %s for GPS\n", device) + + /* Developer option -- allow "hot" configuration of GPS (assume it comes up at 115.2 kpbs on reboot) serialConfig = &serial.Config{Name: device, Baud: 115200} p, err := serial.OpenPort(serialConfig) if err != nil { @@ -150,10 +153,11 @@ func initGPSSerial() bool { p.Write(makeUBXCFG(0x06, 0x00, 20, cfg1)) p.Close() } + */ // Open port at 9600 baud for config. serialConfig = &serial.Config{Name: device, Baud: 9600} - p, err = serial.OpenPort(serialConfig) + p, err := serial.OpenPort(serialConfig) if err != nil { log.Printf("serial port err: %s\n", err.Error()) return false @@ -174,7 +178,7 @@ func initGPSSerial() bool { p.Write(makeUBXCFG(0x06, 0x24, 36, nav)) - // GNSS configuration CFG-GNSS, p. 125 + // GNSS configuration CFG-GNSS for ublox 7 higher, p. 125 (v8) // cfgGnss := []byte{0x00, 0x20, 0x20, 0x05} gps := []byte{0x00, 0x08, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01} @@ -189,16 +193,16 @@ func initGPSSerial() bool { cfgGnss = append(cfgGnss, glonass...) p.Write(makeUBXCFG(0x06, 0x3E, uint16(len(cfgGnss)), cfgGnss)) - // SBAS configuration + // SBAS configuration for ublox 6 and higher p.Write(makeUBXCFG(0x06, 0x16, 8, []byte{0x01, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00})) - // Message output configuration + // Message output configuration -- disable standard NMEA messages // Msg DDC UART1 UART2 USB I2C Res p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})) // GGA p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})) // GLL p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})) // GSA p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})) // GSV - p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x04, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x01})) // RMC + p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})) // RMC p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01})) // VGT p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})) // GRS p.Write(makeUBXCFG(0x06, 0x01, 8, []byte{0xF0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})) // GST @@ -229,7 +233,7 @@ func initGPSSerial() bool { cfg[7] = 0x00 // Baud rate. Little endian order. - bdrt := uint32(115200) + bdrt := uint32(38400) cfg[11] = byte((bdrt >> 24) & 0xFF) cfg[10] = byte((bdrt >> 16) & 0xFF) cfg[9] = byte((bdrt >> 8) & 0xFF) @@ -252,8 +256,8 @@ func initGPSSerial() bool { p.Write(makeUBXCFG(0x06, 0x00, 20, cfg)) p.Close() - // Re-open port at 115200 baud so we can read messages - serialConfig = &serial.Config{Name: device, Baud: 115200} + // Re-open port at 38400 baud so we can read messages + serialConfig = &serial.Config{Name: device, Baud: 38400} p, err = serial.OpenPort(serialConfig) if err != nil { log.Printf("serial port err: %s\n", err.Error()) @@ -422,7 +426,7 @@ func processNMEALine(l string) bool { if err != nil { return false } - mySituation.alt_accuracy = float32(vAcc) + mySituation.AccuracyVert = float32(vAcc) // field 11 = groundspeed, km/h @@ -462,7 +466,7 @@ func processNMEALine(l string) bool { if err != nil { return false } - mySituation.vertVelGPS = float32(vv*3.28084) // convert to ft/sec + mySituation.GPSVertVel = float32(vv*-3.28084) // convert to ft/sec; positive = up @@ -478,10 +482,60 @@ func processNMEALine(l string) bool { mySituation.LastFixLocalTime = time.Now() - } // else if 03 or 04 message -- TODO + } else if (x[1] == "03") { // satellite status message + + // field 2 = number of satellites tracked + satTracked, err := strconv.Atoi(x[2]) + if err != nil { + return false + } + mySituation.SatellitesTracked = uint16(satTracked) + + // fields 3-8 are repeated block + /* + for i:= 0; i < satTracked; i++ { + x[3+6*i] // sv number + x[4+6*i] // status [ U | e | - ] for used / ephemeris / not used + x[5+6*i] // azimuth, deg, 0-359 + x[6+6*i] // elevation, deg, 0-90 + x[7+6*i] // signal strength dB-Hz + x[8+6*i] // lock time, sec, 0-64 + */ + } else if (x[1] == "04") { // clock message + // field 2 is UTC time + if len(x[2]) < 9 { + return false + } + hr, err1 := strconv.Atoi(x[2][0:2]) + min, err2 := strconv.Atoi(x[2][2:4]) + sec, err3 := strconv.Atoi(x[2][4:6]) + if err1 != nil || err2 != nil || err3 != nil { + return false + } + mySituation.lastFixSinceMidnightUTC = uint32((hr * 60 * 60) + (min * 60) + sec) + + // field 3 is date + + if len(x[3]) == 6 { + // Date of Fix, i.e 191115 = 19 November 2015 UTC field 9 + gpsTimeStr := fmt.Sprintf("%s %d:%d:%d", x[3], hr, min, sec) + gpsTime, err := time.Parse("020106 15:04:05", gpsTimeStr) + if err == nil { + if time.Since(gpsTime) > 10*time.Minute { + log.Printf("setting system time to: %s\n", gpsTime) + setStr := gpsTime.Format("20060102 15:04:05") + if err := exec.Command("date", "-s", setStr).Run(); err != nil { + log.Printf("Set Date failure: %s error\n", err) + } + } + } + } + } + + // otherwise look for NMEA standard messages and process them } else if (x[0] == "GNVTG") || (x[0] == "GPVTG") { // Ground track information. mySituation.mu_GPS.Lock() defer mySituation.mu_GPS.Unlock() @@ -615,7 +669,7 @@ func processNMEALine(l string) bool { mySituation.Alt = float32(alt * 3.28084) // Convert to feet. //TODO: Altitude accuracy. - mySituation.alt_accuracy = 0 + mySituation.AccuracyVert = 0 // Timestamp. mySituation.LastFixLocalTime = time.Now() diff --git a/web/plates/gps.html b/web/plates/gps.html index d8c5f4ab..92c76865 100755 --- a/web/plates/gps.html +++ b/web/plates/gps.html @@ -18,10 +18,10 @@
Location: Track: -
+
- {{gps_lat}}, {{gps_lon}} ± {{gps_accuracy}} m - {{gps_track}}° @ {{gps_speed}}KTS @ {{gps_alt}} ft + {{gps_lat}}, {{gps_lon}} ± {{gps_accuracy}} m
{{gps_alt}} ± {{gps_vert_accuracy}} ft @ {{gps_vert_speed}} ft/min
+ {{gps_track}}° @ {{gps_speed}} KTS
@@ -63,4 +63,4 @@ ---> \ No newline at end of file +--> diff --git a/web/plates/js/gps.js b/web/plates/js/gps.js index 3dc35262..ee05c401 100755 --- a/web/plates/js/gps.js +++ b/web/plates/js/gps.js @@ -60,18 +60,22 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) { /* not currently used $scope.gps_satellites = status.Satellites; */ - $scope.gps_accuracy = Math.round(status.Accuracy); + $scope.gps_accuracy = status.Accuracy.toFixed(1); + $scope.gps_vert_accuracy = (status.AccuracyVert*3.2808).toFixed(1); // accuracy is in meters, need to display in ft + // NACp should be an integer value in the range of 0 .. 11 // var accuracies = ["≥ 10 NM", "< 10 NM", "< 4 NM", "< 2 NM", "< 1 NM", "< 0.5 NM", "< 0.3 NM", "< 0.1 NM", "< 100 m", "< 30 m", "< 10 m", "< 3 m"]; // $scope.gps_accuracy = accuracies[status.NACp]; // "LastFixLocalTime":"2015-10-11T16:47:03.523085162Z" - $scope.gps_lat = status.Lat.toPrecision(6); // result is string - $scope.gps_lon = status.Lng.toPrecision(6); // result is string + $scope.gps_lat = status.Lat.toFixed(5); // result is string + $scope.gps_lon = status.Lng.toFixed(5); // result is string $scope.gps_alt = Math.round(status.Alt); $scope.gps_track = status.TrueCourse; $scope.gps_speed = status.GroundSpeed; + $scope.gps_vert_speed = status.GPSVertVel.toFixed(1); + // "LastGroundTrackTime":"0001-01-01T00:00:00Z" /* not currently used @@ -103,9 +107,9 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) { }; var updateStatus = $interval(function () { - // refresh GPS/AHRS status once each second (aka polling) + // refresh GPS/AHRS status once each half second (aka polling) getStatus(); - }, (1 * 1000), 0, false); + }, (1 * 500), 0, false); $state.get('gps').onEnter = function () { // everything gets handled correctly by the controller @@ -122,4 +126,4 @@ function GPSCtrl($rootScope, $scope, $state, $http, $interval) { ahrs.init(); ahrs.orientation(0, 0, 0); -}; \ No newline at end of file +}; diff --git a/web/plates/js/status.js b/web/plates/js/status.js index 842331d9..5cee43c8 100755 --- a/web/plates/js/status.js +++ b/web/plates/js/status.js @@ -49,6 +49,7 @@ function StatusCtrl($rootScope, $scope, $state, $http, $interval) { $scope.ES_messages_last_minute = status.ES_messages_last_minute; $scope.ES_messages_max = status.ES_messages_max; $scope.GPS_satellites_locked = status.GPS_satellites_locked; + $scope.GPS_satellites_tracked = status.GPS_satellites_tracked; $scope.GPS_solution = status.GPS_solution; $scope.RY835AI_connected = status.RY835AI_connected; diff --git a/web/plates/status.html b/web/plates/status.html index d1a03c07..734097f5 100755 --- a/web/plates/status.html +++ b/web/plates/status.html @@ -62,7 +62,7 @@
- {{GPS_satellites_locked}} + {{GPS_satellites_locked}} used; {{GPS_satellites_tracked}} tracked