github.com/simpleiot/simpleiot@v0.18.3/gps/gps.go (about) 1 package gps 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "strings" 8 "time" 9 10 nmea "github.com/adrianmo/go-nmea" 11 "github.com/jacobsa/go-serial/serial" 12 "github.com/simpleiot/simpleiot/data" 13 ) 14 15 // Gps represent a GPS receiver 16 type Gps struct { 17 portName string 18 baud uint 19 c chan data.GpsPos 20 debug bool 21 stop bool 22 port io.ReadWriteCloser 23 } 24 25 // NewGps is used to create a new Gps type 26 func NewGps(portName string, baud uint, c chan data.GpsPos) *Gps { 27 return &Gps{ 28 portName: portName, 29 baud: baud, 30 c: c, 31 } 32 } 33 34 // SetDebug can be used to turn debugging on and off 35 func (gps *Gps) SetDebug(d bool) { 36 gps.debug = d 37 } 38 39 // Stop can be used to stop the GPS acquisition and close port 40 func (gps *Gps) Stop() { 41 gps.port.Close() 42 gps.stop = true 43 } 44 45 // Start is used to start reading the GPS, and data will be sent back 46 // through the handler 47 func (gps *Gps) Start() { 48 gps.stop = false 49 go func() { 50 options := serial.OpenOptions{ 51 PortName: gps.portName, 52 BaudRate: gps.baud, 53 DataBits: 8, 54 StopBits: 1, 55 MinimumReadSize: 1, 56 InterCharacterTimeout: 0, 57 } 58 for { 59 var err error 60 gps.port, err = serial.Open(options) 61 62 if err != nil { 63 if gps.debug { 64 fmt.Println("failed to open port: ", options.PortName) 65 } 66 // delay a bit before trying to open port again 67 time.Sleep(10 * time.Second) 68 continue 69 } 70 71 fmt.Println("GPS port opened: ", options.PortName) 72 reader := bufio.NewReader(gps.port) 73 74 for { 75 if gps.stop { 76 fmt.Println("Closing GPS") 77 return 78 } 79 80 line, err := reader.ReadString('\n') 81 82 if gps.debug { 83 fmt.Println(line) 84 } 85 86 if err != nil { 87 fmt.Println("Error reading gps, closing: ", err) 88 break 89 } 90 91 s, err := nmea.Parse(strings.TrimSpace(line)) 92 if err == nil { 93 if s.DataType() == nmea.TypeGGA { 94 m := s.(nmea.GGA) 95 ret := data.GpsPos{ 96 Lat: m.Latitude, 97 Long: m.Longitude, 98 Fix: m.FixQuality, 99 NumSat: m.NumSatellites, 100 } 101 102 gps.c <- ret 103 } 104 } else { 105 if gps.debug { 106 fmt.Println("Error parsing GPS data: ", err) 107 } 108 } 109 } 110 111 gps.port.Close() 112 if gps.stop { 113 fmt.Println("Closing GPS") 114 return 115 } 116 117 // delay a bit before trying to open port again 118 time.Sleep(10 * time.Second) 119 } 120 }() 121 }