new: gps module can use both serial and gpsd (based on pr #680 from @fheylis)

This commit is contained in:
Simone Margaritelli 2020-09-25 16:46:45 +02:00
parent a02f355926
commit 6f9f1954cb
3 changed files with 91 additions and 38 deletions

1
go.mod
View file

@ -26,6 +26,7 @@ require (
github.com/hashicorp/mdns v1.0.3
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b
github.com/jpillora/go-tld v1.0.0
github.com/koppacetic/go-gpsd v0.4.0
github.com/kr/binarydist v0.1.0 // indirect
github.com/malfunkt/iprange v0.9.0
github.com/mattn/go-colorable v0.1.7 // indirect

2
go.sum
View file

@ -93,6 +93,8 @@ github.com/jpillora/go-tld v0.0.0-20190202073305-f16ca3b7b383/go.mod h1:7H/4k+TV
github.com/jpillora/go-tld v1.0.0 h1:W0Wz3fYT9WCDNJXcXc58uV7sriLnVeELeOU5MP5X42M=
github.com/jpillora/go-tld v1.0.0/go.mod h1:kitBxOF//DR5FxYeIGw+etdiiTIq5S7bx0dwy1GUNAk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/koppacetic/go-gpsd v0.4.0 h1:/T3cRvi1ZsWbxCZPB9pPor0HjIw3HuD+MSvaxV5QqQ8=
github.com/koppacetic/go-gpsd v0.4.0/go.mod h1:mhcLuh9X++WHepbL3jEmEwnx1OkQDepZMihv12RO4qk=
github.com/kr/binarydist v0.1.0 h1:6kAoLA9FMMnNGSehX0s1PdjbEaACznAv/W219j2uvyo=
github.com/kr/binarydist v0.1.0/go.mod h1:DY7S//GCoz1BCd0B0EVrinCKAZN3pXe+MDaIZbXQVgM=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=

View file

@ -8,6 +8,7 @@ import (
"github.com/bettercap/bettercap/session"
"github.com/adrianmo/go-nmea"
"github.com/koppacetic/go-gpsd"
"github.com/tarm/serial"
"github.com/evilsocket/islazy/str"
@ -18,7 +19,16 @@ type GPS struct {
serialPort string
baudRate int
serial *serial.Port
gpsd *gpsd.Session
}
var ModeInfo = [4]string{
"NoValueSeen",
"NoFix",
"Mode2D",
"Mode3D",
}
func NewGPS(s *session.Session) *GPS {
@ -31,7 +41,7 @@ func NewGPS(s *session.Session) *GPS {
mod.AddParam(session.NewStringParameter("gps.device",
mod.serialPort,
"",
"Serial device of the GPS hardware."))
"Serial device of the GPS hardware or hostname:port for a GPSD instance."))
mod.AddParam(session.NewIntParameter("gps.baudrate",
fmt.Sprintf("%d", mod.baudRate),
@ -63,7 +73,7 @@ func (mod *GPS) Name() string {
}
func (mod *GPS) Description() string {
return "A module talking with GPS hardware on a serial interface."
return "A module talking with GPS hardware on a serial interface or via GPSD."
}
func (mod *GPS) Author() string {
@ -79,11 +89,17 @@ func (mod *GPS) Configure() (err error) {
return err
}
if mod.serialPort[0] == '/' || mod.serialPort[0] == '.' {
mod.Debug("connecting to serial port %s", mod.serialPort)
mod.serial, err = serial.OpenPort(&serial.Config{
Name: mod.serialPort,
Baud: mod.baudRate,
ReadTimeout: time.Second * 1,
})
} else {
mod.Debug("connecting to gpsd at %s", mod.serialPort)
mod.gpsd, err = gpsd.Dial(mod.serialPort)
}
return
}
@ -118,17 +134,7 @@ func (mod *GPS) Show() error {
return nil
}
func (mod *GPS) Start() error {
if err := mod.Configure(); err != nil {
return err
}
return mod.SetRunning(true, func() {
defer mod.serial.Close()
mod.Info("started on port %s ...", mod.serialPort)
for mod.Running() {
func (mod *GPS) readFromSerial() {
if line, err := mod.readLine(); err == nil {
if s, err := nmea.Parse(line); err == nil {
// http://aprs.gids.nl/nmea/#gga
@ -157,13 +163,57 @@ func (mod *GPS) Start() error {
} else if err != io.EOF {
mod.Warning("error while reading serial port: %s", err)
}
}
func (mod *GPS) runFromGPSD() {
mod.gpsd.Subscribe("TPV", func(r interface{}) {
report := r.(*gpsd.TPVReport)
mod.Session.GPS.Updated = report.Time
mod.Session.GPS.Latitude = report.Lat
mod.Session.GPS.Longitude = report.Lon
mod.Session.GPS.FixQuality = ModeInfo[report.Mode]
mod.Session.GPS.Altitude = report.Alt
})
mod.gpsd.Subscribe("SKY", func(r interface{}) {
report := r.(*gpsd.SKYReport)
mod.Session.GPS.NumSatellites = int64(len(report.Satellites))
mod.Session.GPS.HDOP = report.Hdop
//mod.Session.GPS.Separation = 0
})
mod.gpsd.Run()
}
func (mod *GPS) Start() error {
if err := mod.Configure(); err != nil {
return err
}
return mod.SetRunning(true, func() {
defer mod.serial.Close()
mod.Info("started on port %s ...", mod.serialPort)
if mod.serial != nil {
for mod.Running() {
mod.readFromSerial()
}
} else {
mod.runFromGPSD()
}
})
}
func (mod *GPS) Stop() error {
return mod.SetRunning(false, func() {
if mod.serial != nil {
// let the read fail and exit
mod.serial.Close()
} else {
if err := mod.gpsd.Close(); err != nil {
mod.Error("failed closing the connection to GPSD: %s", err)
}
}
})
}