Golang实现对串口的操作的库:https://github.com/huin/goserial
以环天BU353 路测USB GPS为例,该GPS模块的主要参数:http://jn.goepe.com/apollo/show_product1.php?id=2164028&uid=zhaogis
GPS模块的驱动安装
驱动程序可以去官网下载,下载地址:
http://usglobalsat.com/s-24-support-drivers.aspx
备用下载地址:http://usglobalsat.com/s-172-bu-353-s4-support.aspx
GPS模块的应用程序设计
实现读取并解析GPS信息的代码如下:
package model
import (
// "fmt"
// "infrastructure/log"
// "io"
"math"
"strconv"
"strings"
"time"
"infrastructure/github.com/serial"
)
type GpsInfo struct {
Longitude string
Latitude string
LonDirection string
LatDirection string
LongitudeRadian float64
LatitudeRadian float64
IsGpsNormal bool
}
type ComObject struct {
ComName string
Baudrate int
// Com io.ReadWriteCloser
Com *serial.SerialPort
IsComNormal bool
CloseChan chan bool
}
var (
ComName = "COM3"
ComObj = &ComObject{ComName: ComName, Baudrate: 4800, IsComNormal: false, CloseChan: make(chan bool, 1)}
GpsObj = &GpsInfo{IsGpsNormal: false}
BsGpsObj = &GpsInfo{IsGpsNormal: true, LonDirection: "E", LongitudeRadian: 116.63, LatDirection: "N", LatitudeRadian: 40.32}
UeBsDistance float64 = 0
directionMap = map[string]string{
"N": "北纬",
"S": "南纬",
"E": "东经",
"W": "西经",
}
)
func StartGpsModule() {
ComObj.ComName = ComName
if true == ComObj.GetPortName() {
ComName = ComObj.ComName
}
for {
if true == ComObj.IsComNormal {
<-ComObj.CloseChan
ComObj.IsComNormal = false
GpsObj.IsGpsNormal = false
continue
}
time.Sleep(time.Second * 5)
if false == ComObj.GetPortName() {
continue
}
err := ComObj.OpenCom()
if nil != err {
GpsObj.IsGpsNormal = false
continue
} else {
ComObj.IsComNormal = true
}
go ComObj.ReceiveFromCom()
}
}
func (this *ComObject) GetPortName() bool {
ports, err := serial.GetPortsList()
if nil != err || 0 == len(ports) {
return false
}
this.ComName = ports[0]
return true
// for _, port := range ports {
// fmt.Printf("Found port: %v\n", port)
// }
}
func (this *ComObject) OpenCom() (err error) {
mode := &serial.Mode{
BaudRate: 4800,
DataBits: 8,
Parity: serial.PARITY_NONE,
StopBits: serial.STOPBITS_ONE,
}
s, err := serial.OpenPort(this.ComName, mode)
if nil != err {
// log.Error("pkg: model, func: OpenCom, method: goserial.OpenPort, errInfo:", err)
return
}
this.Com = s
return nil
}
func (this *ComObject) Close() {
this.Com.Close()
this.CloseChan <- true
}
func (this *ComObject) ReceiveFromCom() {
defer this.Close()
buf := make([]byte, 512)
for {
time.Sleep(time.Second)
n, err := this.Com.Read(buf[0:])
if nil != err {
// log.Error("pkg: model, func: ReceiveFromCom, method: this.Com.Read, errInfo:", err)
return
}
parseGpsInfo(string(buf[:n]))
// fmt.Println("parseRst:", GpsObj)
}
}
func parseGpsInfo(gpsInfo string) {
var parseSuccessfulFlag bool = false
strLineSlice := strings.Split(gpsInfo, "\n")
if 0 == len(strLineSlice) {
GpsObj.IsGpsNormal = false
return
}
for _, oneLine := range strLineSlice {
if 0 == len(oneLine) {
continue
}
if '$' != oneLine[0] {
continue
}
if !strings.Contains(oneLine, "*") {
continue
}
if !strings.Contains(oneLine, "N") && !strings.Contains(oneLine, "S") {
continue
}
if !strings.Contains(oneLine, "E") && !strings.Contains(oneLine, "W") {
continue
}
if strings.Contains(oneLine, "GPGGA") {
if false == parseLongitudeAndLatitudeFromGpgga(oneLine) {
continue
}
parseSuccessfulFlag = true
break
}
if strings.Contains(oneLine, "GPRMC") {
if false == parseLongitudeAndLatitudeFromGprmc(oneLine) {
continue
}
parseSuccessfulFlag = true
break
}
}
if true == parseSuccessfulFlag {
GpsObj.IsGpsNormal = true
UeBsDistance = CalcDistByLongitudeLantitude(*GpsObj, *BsGpsObj)
} else {
GpsObj.IsGpsNormal = false
UeBsDistance = 0
}
}
func parseLongitudeAndLatitudeFromGpgga(gpggaInfo string) bool {
strSlice := strings.Split(gpggaInfo, ",")
if 3 > len(strSlice[2]) || 4 > len(strSlice[4]) {
return false
}
GpsObj.LatDirection = strSlice[3]
GpsObj.LonDirection = strSlice[5]
GpsObj.Latitude = directionMap[strSlice[3]] + strSlice[2][:2] + "度" + strSlice[2][2:] + "分"
GpsObj.Longitude = directionMap[strSlice[5]] + strSlice[4][:3] + "度" + strSlice[4][3:] + "分"
tmpIntPartLat, _ := strconv.ParseFloat(strSlice[2][:2], 32)
tmpDecimalPartLat, _ := strconv.ParseFloat(strSlice[2][2:], 32)
GpsObj.LatitudeRadian = tmpIntPartLat + tmpDecimalPartLat/60
tmpIntPartLon, _ := strconv.ParseFloat(strSlice[4][:3], 32)
tmpDecimalPartLon, _ := strconv.ParseFloat(strSlice[4][3:], 32)
GpsObj.LongitudeRadian = tmpIntPartLon + tmpDecimalPartLon/60
return true
}
func parseLongitudeAndLatitudeFromGprmc(gprmcInfo string) bool {
strSlice := strings.Split(gprmcInfo, ",")
if 3 > len(strSlice[3]) || 4 > len(strSlice[5]) {
return false
}
GpsObj.LatDirection = strSlice[4]
GpsObj.LonDirection = strSlice[6]
GpsObj.Latitude = directionMap[strSlice[4]] + strSlice[3][:2] + "度" + strSlice[3][2:] + "分"
GpsObj.Longitude = directionMap[strSlice[6]] + strSlice[5][:3] + "度" + strSlice[5][3:] + "分"
tmpIntPartLat, _ := strconv.ParseFloat(strSlice[3][:2], 32)
tmpDecimalPartLat, _ := strconv.ParseFloat(strSlice[3][2:], 32)
GpsObj.LatitudeRadian = tmpIntPartLat + tmpDecimalPartLat/60
tmpIntPartLon, _ := strconv.ParseFloat(strSlice[5][:3], 32)
tmpDecimalPartLon, _ := strconv.ParseFloat(strSlice[5][3:], 32)
GpsObj.LongitudeRadian = tmpIntPartLon + tmpDecimalPartLon/60
return true
}
func CalcDistByLongitudeLantitude(gpsPointA, gpsPointB GpsInfo) (distance float64) {
if false == gpsPointA.IsGpsNormal || false == gpsPointB.IsGpsNormal {
return 0
}
lonA, latA := getFormatedLongitudeLantitude(gpsPointA)
lonB, latB := getFormatedLongitudeLantitude(gpsPointB)
c := math.Sin(latA*math.Pi/180)*math.Sin(latB*math.Pi/180)*math.Cos((lonA-lonB)*math.Pi/180) + math.Cos(latA*math.Pi/180)*math.Cos(latB*math.Pi/180)
distance = 6371004 * math.Acos(c)
return
}
func getFormatedLongitudeLantitude(gpsPoint GpsInfo) (lon, lat float64) {
if "E" == gpsPoint.LonDirection {
lon = gpsPoint.LongitudeRadian
} else {
lon = 0 - gpsPoint.LongitudeRadian
}
if "N" == gpsPoint.LatDirection {
lat = 90 - gpsPoint.LatitudeRadian
} else {
lat = 90 + gpsPoint.LatitudeRadian
}
return
}
可参考:http://studygolang.com/articles/302