stratux/ry835ai.go

181 wiersze
3.5 KiB
Go
Czysty Zwykły widok Historia

package main
import (
"fmt"
"github.com/tarm/serial"
"time"
"strings"
"strconv"
)
type GPSData struct {
lastFixSinceMidnightUTC uint32
lat float32
lng float32
quality uint8
satellites uint16
accuracy float32 // Meters.
alt float32 // Feet.
alt_accuracy float32
lastFixLocalTime time.Time
trueCourse uint16
groundSpeed uint16
lastGroundTrackTime time.Time
}
var serialConfig *serial.Config
var serialPort *serial.Port
func initGPSSerialReader() bool {
serialConfig = &serial.Config{Name: "/dev/ttyACM0", Baud: 9600}
p, err := serial.OpenPort(serialConfig)
if err != nil {
fmt.Printf("serial port err: %s\n", err.Error())
return false
}
serialPort = p
return true
}
func processNMEALine(l string) bool {
x := strings.Split(l, ",")
if x[0] == "$GNVTG" { // Ground track information.
if len(x) < 10 {
return false
}
trueCourse := uint16(0)
if len(x[1]) > 0 {
tc, err := strconv.ParseFloat(x[1], 32)
if err != nil {
return false
}
trueCourse = uint16(tc)
} else {
// No movement.
myGPS.trueCourse = 0
myGPS.groundSpeed = 0
myGPS.lastGroundTrackTime = time.Time{}
return true
}
groundSpeed, err := strconv.ParseFloat(x[5], 32) // Knots.
if err != nil {
return false
}
myGPS.trueCourse = uint16(trueCourse)
myGPS.groundSpeed = uint16(groundSpeed)
myGPS.lastGroundTrackTime = time.Now()
} else if x[0] == "$GNGGA" { // GPS fix.
if len(x) < 15 {
return false
}
var fix GPSData
fix = myGPS
// Timestamp.
if len(x[1]) < 9 {
return false
}
hr, err1 := strconv.Atoi(x[1][0:2])
min, err2 := strconv.Atoi(x[1][2:4])
sec, err3 := strconv.Atoi(x[1][4:6])
if err1 != nil || err2 != nil || err3 != nil {
return false
}
fix.lastFixSinceMidnightUTC = uint32((hr * 60 * 60) + (min * 60) + sec)
// Latitude.
if len(x[2]) < 10 {
return false
}
hr, err1 = strconv.Atoi(x[2][0:2])
minf, err2 := strconv.ParseFloat(x[2][2:10], 32)
if err1 != nil || err2 != nil {
return false
}
fix.lat = float32(hr) + float32(minf / 60.0)
if x[3] == "S" { // South = negative.
fix.lat = -fix.lat
}
// Longitude.
if len(x[4]) < 11 {
return false
}
hr, err1 = strconv.Atoi(x[4][0:3])
minf, err2 = strconv.ParseFloat(x[4][3:11], 32)
if err1 != nil || err2 != nil {
return false
}
fix.lng = float32(hr) + float32(minf / 60.0)
if x[5] == "W" { // West = negative.
fix.lng = -fix.lng
}
// Quality indicator.
q, err1 := strconv.Atoi(x[6])
if err1 != nil {
return false
}
fix.quality = uint8(q)
// Satellites.
sat, err1 := strconv.Atoi(x[7])
if err1 != nil {
return false
}
fix.satellites = uint16(sat)
// Accuracy.
hdop, err1 := strconv.ParseFloat(x[8], 32)
if err1 != nil {
return false
}
fix.accuracy = float32(hdop * 5.0) //FIXME: 5 meters ~ 1.0 HDOP?
// Altitude.
alt, err1 := strconv.ParseFloat(x[9], 32)
if err1 != nil {
return false
}
fix.alt = float32(alt * 3.28084) // Covnert to feet.
//TODO: Altitude accuracy.
fix.alt_accuracy = 0
// Timestamp.
fix.lastFixLocalTime = time.Now()
myGPS = fix
}
return true
}
func gpsSerialReader() {
defer serialPort.Close()
for {
buf := make([]byte, 1024)
n, err := serialPort.Read(buf)
if err != nil {
fmt.Printf("gps unit read error: %s\n", err.Error())
return
}
s := string(buf[:n])
x := strings.Split(s, "\n")
for _, l := range x {
processNMEALine(l)
}
}
}
func gpsReader() {
if initGPSSerialReader() {
gpsSerialReader()
}
}