Golang 实现从串口读取信息

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

你可能感兴趣的:(Golang 实现从串口读取信息)