diff --git a/main/gen_gdl90.go b/main/gen_gdl90.go index 0fb6751f..aaa790f5 100755 --- a/main/gen_gdl90.go +++ b/main/gen_gdl90.go @@ -984,6 +984,7 @@ type settings struct { ES_Enabled bool Ping_Enabled bool GPS_Enabled bool + GpsdAddress string NetworkOutputs []networkConnection SerialOutputs map[string]serialConnection AHRS_Enabled bool @@ -1046,6 +1047,7 @@ func defaultSettings() { globalSettings.UAT_Enabled = true globalSettings.ES_Enabled = true globalSettings.GPS_Enabled = true + globalSettings.GpsdAddress = "localhost:2947" //FIXME: Need to change format below. globalSettings.NetworkOutputs = []networkConnection{ {Conn: nil, Ip: "", Port: 4000, Capability: NETWORK_GDL90_STANDARD | NETWORK_AHRS_GDL90}, diff --git a/main/gpsd.go b/main/gpsd.go index fc6f0255..bd402a5a 100644 --- a/main/gpsd.go +++ b/main/gpsd.go @@ -6,8 +6,13 @@ import ( "log" "math" "sync" + "time" ) +// Channel to disconnect current gpsd connection +var killGpsd chan struct{} +var gps *gpsd.Session + // Determine type of satellite based on PRN number. func satelliteType(prnId int) uint8 { // TODO: Galileo @@ -53,7 +58,9 @@ func isSbasInSolution() bool { func processDEVICES(r interface{}) { devices := r.(*gpsd.DEVICESReport) - log.Printf("DEVICES (%d)", len(devices.Devices)) + if globalSettings.DEBUG { + log.Printf("DEVICES (%d)", len(devices.Devices)) + } for _, dev := range devices.Devices { log.Printf(" %s %s %x %s %s %i %s %s %i %s %s %i %d %d", dev.Path, @@ -78,7 +85,9 @@ func processDEVICES(r interface{}) { func processTPV(r interface{}) { tpv := r.(*gpsd.TPVReport) - log.Printf("TPV", tpv.Device, tpv.Mode, tpv.Time, tpv.Tag) + if globalSettings.DEBUG { + log.Printf("TPV", tpv.Device, tpv.Mode, tpv.Time, tpv.Tag) + } mySituation.mu_GPS.Lock() satelliteMutex.Lock() @@ -128,7 +137,9 @@ func processTPV(r interface{}) { func processSKY(r interface{}) { sky := r.(*gpsd.SKYReport) - log.Printf("SKY", sky.Device, sky.Tag) + if globalSettings.DEBUG { + log.Printf("SKY", sky.Device, sky.Tag) + } mySituation.mu_GPS.Lock() satelliteMutex.Lock() @@ -171,7 +182,9 @@ func processSKY(r interface{}) { func processATT(r interface{}) { att := r.(*gpsd.ATTReport) - log.Printf("ATT", att.Device, att.Tag, att.Pitch, att.Roll, att.Heading) + if globalSettings.DEBUG { + log.Printf("ATT", att.Device, att.Tag, att.Pitch, att.Roll, att.Heading) + } mySituation.mu_GPS.Lock() @@ -196,18 +209,61 @@ func initGpsd() { satelliteMutex = &sync.Mutex{} Satellites = make(map[string]SatelliteInfo) - var gps *gpsd.Session - var err error + killGpsd = make(chan struct{}) - if gps, err = gpsd.Dial(gpsd.DefaultAddress); err != nil { - log.Printf("Failed to connect to gpsd: %s", err) + if globalSettings.GPS_Enabled { + connectGpsd(globalSettings.GpsdAddress) + } +} + +// Main interface for enabling and changing the gpsd connection +// Calling will block until previous connection disconnects +// If address is zero value, it connects to gpsd on the local machine +func connectGpsd(address string) { + // kill existing monitor goroutine if it exists + if gps != nil { + disconnectGpsd() } - gps.AddFilter("DEVICES", processDEVICES) - gps.AddFilter("TPV", processTPV) - gps.AddFilter("SKY", processSKY) - gps.AddFilter("ATT", processATT) + if address == "" { + address = gpsd.DefaultAddress + } - gps.SendCommand("DEVICES") - gps.Watch() + go func() { + for { + var err error + if gps, err = gpsd.Dial(address); err != nil { + log.Printf("Failed to connect to gpsd: %s", err) + time.Sleep(time.Second) + continue + } + + log.Printf("Gpsd %s Connected.", address) + + gps.AddFilter("DEVICES", processDEVICES) + gps.AddFilter("TPV", processTPV) + gps.AddFilter("SKY", processSKY) + gps.AddFilter("ATT", processATT) + + reconnect := gps.Watch() + + select { + case <-killGpsd: + log.Printf("Gpsd %s disconnecting", address) + gps.Close() + gps = nil + return + case <-reconnect: + log.Printf("Gpsd %s disconnected. Reconnecting..", address) + time.Sleep(time.Second) + } + } + }() +} + +// Disconnect from gpsd +// Blocks until connection is disconnected and all goroutines are stopped +func disconnectGpsd() { + log.Printf("Stopping gpsd session") + killGpsd <- struct{}{} } diff --git a/main/managementinterface.go b/main/managementinterface.go index 290a10b3..5b3ebf2d 100644 --- a/main/managementinterface.go +++ b/main/managementinterface.go @@ -218,6 +218,12 @@ func handleSettingsSetRequest(w http.ResponseWriter, r *http.Request) { case "Ping_Enabled": globalSettings.Ping_Enabled = val.(bool) case "GPS_Enabled": + switch { + case val.(bool) == true && globalSettings.GPS_Enabled == false: + connectGpsd(globalSettings.GpsdAddress) + case val.(bool) == false && globalSettings.GPS_Enabled == true: + disconnectGpsd() + } globalSettings.GPS_Enabled = val.(bool) case "AHRS_Enabled": globalSettings.AHRS_Enabled = val.(bool)