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  }