gyrogpsc/serial_ubx/serial.go

125 lines
3.0 KiB
Go

package serial_ubx
import (
"errors"
"fmt"
"git.timovolkmann.de/gyrogpsc/ublox"
"go.bug.st/serial"
"log"
"time"
)
type Measurement struct {
//Timestamp int64 `json:"timestamp"`
Timestamp time.Time `json:"timestamp"`
Position [3]int32 `json:"position"` // Latitude, Longitude, Height
Orientation [3]int32 `json:"orientation"` // Pitch, Roll, Heading
}
type ubxReceiver struct {
decoder *ublox.Decoder
currentMeas Measurement
}
func Setup(portname string) (*ubxReceiver, error) {
mode := &serial.Mode{
BaudRate: 115200,
}
port, err := serial.Open(portname, mode)
if err != nil {
return nil, err
}
return &ubxReceiver{
decoder: ublox.NewDecoder(port),
}, nil
}
func (u *ubxReceiver) Next() (ublox.Message, error) {
return u.decoder.Decode()
}
var (
errNotImplemented = errors.New("message not implemented")
)
// TODO: additional callback with adjustable timing
func (u *ubxReceiver) NextMeasurement() (*Measurement, error) {
msg, err := u.decoder.Decode()
if err != nil {
return nil, err
}
//t := time.Time{}
switch v := msg.(type) {
case *ublox.NavPvt:
t, err := time.Parse(time.RFC3339Nano, formatTime(v.Year_y, v.Month_month, v.Day_d, v.Hour_h, v.Min_min, v.Sec_s, v.Nano_ns))
if err != nil {
log.Println(err)
}
//u.currentMeas.Timestamp = t.UnixNano()
u.currentMeas.Timestamp = t
u.currentMeas.Position[0] = v.Lat_dege7
u.currentMeas.Position[1] = v.Lon_dege7
u.currentMeas.Position[2] = v.Height_mm
//fmt.Printf("%T %v\n", *v, *v)
case *ublox.HnrPvt:
t, err := time.Parse(time.RFC3339Nano, formatTime(v.Year_y, v.Month_month, v.Day_d, v.Hour_h, v.Min_min, v.Sec_s, v.Nano_ns))
if err != nil {
log.Println(err)
}
u.currentMeas.Timestamp = t
u.currentMeas.Position[0] = v.Lat_dege7
u.currentMeas.Position[1] = v.Lon_dege7
u.currentMeas.Position[2] = v.Height_mm
//fmt.Printf("%T %v\n", *v, *v)
case *ublox.NavAtt:
u.currentMeas.Orientation[0] = v.Pitch_deg
u.currentMeas.Orientation[1] = v.Roll_deg
u.currentMeas.Orientation[2] = v.Heading_deg
//fmt.Printf("%T %v\n", *v, *v)
//case *ublox.RawMessage:
// //fmt.Printf("%T %v\n\n", *v, *v)
default:
return nil, errNotImplemented
}
m := u.currentMeas
return &m, nil
}
func formatTime(Year_y uint16, Month_month byte, Day_d byte, Hour_h byte, Min_min byte, Sec_s byte, Nano_ns int32) string {
//Nano_ns *= 1e+3
if Nano_ns < 0 {
Nano_ns += int32(time.Second)
if Sec_s > 0 {
Sec_s--
} else if Min_min > 0 {
Sec_s = 59
Min_min--
} else if Hour_h > 0 {
Sec_s = 59
Min_min = 59
Hour_h--
} else if Day_d > 1 {
Sec_s = 59
Min_min = 59
Hour_h = 23
Day_d--
} // TODO: more cases for exact behavior! good for now...
}
//fmt.Printf("%04d-%02d-%02dT%02d:%02d:%02d.%09dZ00:00\n", Year_y, Month_month, Day_d, Hour_h, Min_min, Sec_s, Nano_ns )
return fmt.Sprintf("%04d-%02d-%02dT%02d:%02d:%02d.%09dZ", Year_y, Month_month, Day_d, Hour_h, Min_min, Sec_s, Nano_ns)
}
func (u *ubxReceiver) Printloop() {
for {
meas, err := u.NextMeasurement()
if err != nil {
continue
}
fmt.Println(meas)
}
}