skylab: rework interface
This commit is contained in:
parent
96149ee38b
commit
2dceb3927e
93
broker.go
93
broker.go
|
@ -2,104 +2,29 @@ package gotelem
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/kschamplin/gotelem/skylab"
|
||||||
"golang.org/x/exp/slog"
|
"golang.org/x/exp/slog"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BrokerRequest struct {
|
|
||||||
Source string // the name of the sender
|
|
||||||
Msg Frame // the message to send
|
|
||||||
}
|
|
||||||
type BrokerClient struct {
|
|
||||||
Name string // the name of the client
|
|
||||||
Ch chan Frame // the channel to send frames to this client
|
|
||||||
}
|
|
||||||
type Broker struct {
|
|
||||||
subs map[string]chan Frame
|
|
||||||
|
|
||||||
publishCh chan BrokerRequest
|
|
||||||
|
|
||||||
subsCh chan BrokerClient
|
|
||||||
unsubCh chan BrokerClient
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Start runs the broker and sends messages to the subscribers (but not the sender)
|
|
||||||
func (b *Broker) Start() {
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case newClient := <-b.subsCh:
|
|
||||||
b.subs[newClient.Name] = newClient.Ch
|
|
||||||
case req := <-b.publishCh:
|
|
||||||
for name, ch := range b.subs {
|
|
||||||
if name == req.Source {
|
|
||||||
continue // don't send to ourselves.
|
|
||||||
}
|
|
||||||
// a kinda-inelegant non-blocking push.
|
|
||||||
// if we can't do it, we just drop it. this should ideally never happen.
|
|
||||||
select {
|
|
||||||
case ch <- req.Msg:
|
|
||||||
default:
|
|
||||||
fmt.Printf("we dropped a packet to dest %s", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case clientToRemove := <-b.unsubCh:
|
|
||||||
close(b.subs[clientToRemove.Name])
|
|
||||||
delete(b.subs, clientToRemove.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Broker) Publish(name string, msg Frame) {
|
|
||||||
breq := BrokerRequest{
|
|
||||||
Source: name,
|
|
||||||
Msg: msg,
|
|
||||||
}
|
|
||||||
b.publishCh <- breq
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Broker) Subscribe(name string) <-chan Frame {
|
|
||||||
ch := make(chan Frame, 3)
|
|
||||||
|
|
||||||
bc := BrokerClient{
|
|
||||||
Name: name,
|
|
||||||
Ch: ch,
|
|
||||||
}
|
|
||||||
b.subsCh <- bc
|
|
||||||
return ch
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Broker) Unsubscribe(name string) {
|
|
||||||
bc := BrokerClient{
|
|
||||||
Name: name,
|
|
||||||
}
|
|
||||||
b.unsubCh <- bc
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type JBroker struct {
|
type JBroker struct {
|
||||||
subs map[string] chan CANDumpEntry // contains the channel for each subsciber
|
subs map[string]chan skylab.BusEvent // contains the channel for each subsciber
|
||||||
|
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
bufsize int // size of chan buffer in elements.
|
bufsize int // size of chan buffer in elements.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func NewBroker(bufsize int, logger *slog.Logger) *JBroker {
|
func NewBroker(bufsize int, logger *slog.Logger) *JBroker {
|
||||||
return &JBroker{
|
return &JBroker{
|
||||||
subs: make(map[string]chan CANDumpEntry),
|
subs: make(map[string]chan skylab.BusEvent),
|
||||||
logger: logger,
|
logger: logger,
|
||||||
bufsize: bufsize,
|
bufsize: bufsize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *JBroker) Subscribe(name string) (ch chan CANDumpEntry, err error) {
|
func (b *JBroker) Subscribe(name string) (ch chan skylab.BusEvent, err error) {
|
||||||
// get rw lock.
|
// get rw lock.
|
||||||
b.lock.Lock()
|
b.lock.Lock()
|
||||||
defer b.lock.Unlock()
|
defer b.lock.Unlock()
|
||||||
|
@ -108,7 +33,7 @@ func (b *JBroker) Subscribe(name string) (ch chan CANDumpEntry, err error) {
|
||||||
return nil, errors.New("name already in use")
|
return nil, errors.New("name already in use")
|
||||||
}
|
}
|
||||||
b.logger.Info("new subscriber", "name", name)
|
b.logger.Info("new subscriber", "name", name)
|
||||||
ch = make(chan CANDumpEntry, b.bufsize)
|
ch = make(chan skylab.BusEvent, b.bufsize)
|
||||||
|
|
||||||
b.subs[name] = ch
|
b.subs[name] = ch
|
||||||
return
|
return
|
||||||
|
@ -121,7 +46,7 @@ func (b *JBroker) Unsubscribe(name string) {
|
||||||
delete(b.subs, name)
|
delete(b.subs, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *JBroker) Publish(sender string, message CANDumpEntry) {
|
func (b *JBroker) Publish(sender string, message skylab.BusEvent) {
|
||||||
b.lock.RLock()
|
b.lock.RLock()
|
||||||
defer b.lock.RUnlock()
|
defer b.lock.RUnlock()
|
||||||
for name, ch := range b.subs {
|
for name, ch := range b.subs {
|
||||||
|
|
|
@ -3,28 +3,26 @@ package cli
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
imgui "github.com/AllenDang/cimgui-go"
|
||||||
"github.com/kschamplin/gotelem"
|
"github.com/kschamplin/gotelem"
|
||||||
"github.com/kschamplin/gotelem/mprpc"
|
"github.com/kschamplin/gotelem/mprpc"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
imgui "github.com/AllenDang/cimgui-go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
subCmds = append(subCmds, clientCmd)
|
subCmds = append(subCmds, clientCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var clientCmd = &cli.Command{
|
var clientCmd = &cli.Command{
|
||||||
Name: "client",
|
Name: "client",
|
||||||
Aliases: []string{"c"},
|
Aliases: []string{"c"},
|
||||||
Usage: "interact with a gotelem server",
|
Usage: "interact with a gotelem server",
|
||||||
ArgsUsage: "[server url]",
|
ArgsUsage: "[server url]",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "gui",
|
Name: "gui",
|
||||||
Aliases: []string{"g"},
|
Aliases: []string{"g"},
|
||||||
Usage: "start a local TUI",
|
Usage: "start a local TUI",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Description: `
|
Description: `
|
||||||
|
@ -33,9 +31,8 @@ Connects to a gotelem server or relay. Can be used to
|
||||||
Action: client,
|
Action: client,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func loop() {
|
func loop() {
|
||||||
imgui.ShowDemoWindow()
|
imgui.ShowDemoWindow()
|
||||||
}
|
}
|
||||||
|
|
||||||
func client(ctx *cli.Context) error {
|
func client(ctx *cli.Context) error {
|
||||||
|
@ -45,13 +42,8 @@ func client(ctx *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// the client should connect to a TCP server and listen to packets.
|
// the client should connect to a TCP server and listen to packets.
|
||||||
func CANFrameHandler(f *gotelem.Frame) (*mprpc.RPCEmpty, error){
|
func CANFrameHandler(f *gotelem.Frame) (*mprpc.RPCEmpty, error) {
|
||||||
fmt.Printf("got frame, %v\n", f)
|
fmt.Printf("got frame, %v\n", f)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var initialRPCHandlers = map[string]mprpc.ServiceFunc{
|
|
||||||
"can": mprpc.MakeService(CANFrameHandler),
|
|
||||||
}
|
|
||||||
|
|
|
@ -37,11 +37,9 @@ var serveCmd = &cli.Command{
|
||||||
Action: serve,
|
Action: serve,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FIXME: naming
|
// FIXME: naming
|
||||||
// this is a server handler for i.e tcp socket, http server, socketCAN, xbee,
|
// this is a server handler for i.e tcp socket, http server, socketCAN, xbee,
|
||||||
// etc. we can register them in init() functions.
|
// etc. we can register them in init() functions.
|
||||||
type testThing func(cCtx *cli.Context, broker *gotelem.Broker, logger *slog.Logger) (err error)
|
|
||||||
|
|
||||||
type service interface {
|
type service interface {
|
||||||
fmt.Stringer
|
fmt.Stringer
|
||||||
|
@ -58,12 +56,6 @@ var serveThings = []service{
|
||||||
&rpcService{},
|
&rpcService{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func deriveLogger (oldLogger *slog.Logger, svc service) (newLogger *slog.Logger) {
|
|
||||||
newLogger = oldLogger.With("svc", svc.String())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func serve(cCtx *cli.Context) error {
|
func serve(cCtx *cli.Context) error {
|
||||||
// TODO: output both to stderr and a file.
|
// TODO: output both to stderr and a file.
|
||||||
logger := slog.New(slog.NewTextHandler(os.Stderr))
|
logger := slog.New(slog.NewTextHandler(os.Stderr))
|
||||||
|
@ -85,14 +77,11 @@ func serve(cCtx *cli.Context) error {
|
||||||
}(svc, logger)
|
}(svc, logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type rpcService struct {
|
type rpcService struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,8 +151,7 @@ func (c *CanLoggerService) String() string {
|
||||||
func (c *CanLoggerService) Status() {
|
func (c *CanLoggerService) Status() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *CanLoggerService) Start(cCtx *cli.Context, broker *gotelem.JBroker, l *slog.Logger) (err error) {
|
||||||
func (c *CanLoggerService) Start(cCtx *cli.Context, broker *gotelem.JBroker, l *slog.Logger) (err error) {
|
|
||||||
rxCh, err := broker.Subscribe("canDump")
|
rxCh, err := broker.Subscribe("canDump")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -171,7 +159,7 @@ func (c *CanLoggerService) Start(cCtx *cli.Context, broker *gotelem.JBroker, l
|
||||||
t := time.Now()
|
t := time.Now()
|
||||||
fname := fmt.Sprintf("candump_%d-%02d-%02dT%02d.%02d.%02d.txt",
|
fname := fmt.Sprintf("candump_%d-%02d-%02dT%02d.%02d.%02d.txt",
|
||||||
t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
|
t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
|
||||||
|
|
||||||
l.Info("logging to file", "filename", fname)
|
l.Info("logging to file", "filename", fname)
|
||||||
|
|
||||||
f, err := os.Create(fname)
|
f, err := os.Create(fname)
|
||||||
|
@ -194,7 +182,6 @@ func (c *CanLoggerService) Start(cCtx *cli.Context, broker *gotelem.JBroker, l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// XBeeService provides data over an Xbee device, either by serial or TCP
|
// XBeeService provides data over an Xbee device, either by serial or TCP
|
||||||
// based on the url provided in the xbee flag. see the description for details.
|
// based on the url provided in the xbee flag. see the description for details.
|
||||||
type XBeeService struct {
|
type XBeeService struct {
|
||||||
|
@ -207,7 +194,6 @@ func (x *XBeeService) String() string {
|
||||||
func (x *XBeeService) Status() {
|
func (x *XBeeService) Status() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (x *XBeeService) Start(cCtx *cli.Context, broker *gotelem.JBroker, logger *slog.Logger) (err error) {
|
func (x *XBeeService) Start(cCtx *cli.Context, broker *gotelem.JBroker, logger *slog.Logger) (err error) {
|
||||||
if cCtx.String("xbee") == "" {
|
if cCtx.String("xbee") == "" {
|
||||||
logger.Info("not using xbee")
|
logger.Info("not using xbee")
|
||||||
|
@ -245,7 +231,5 @@ func (x *XBeeService) Start(cCtx *cli.Context, broker *gotelem.JBroker, logger *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,10 @@ import (
|
||||||
// It is an example of the modular architecture of the command line and server stack.
|
// It is an example of the modular architecture of the command line and server stack.
|
||||||
|
|
||||||
var canDevFlag = &cli.StringFlag{
|
var canDevFlag = &cli.StringFlag{
|
||||||
Name: "can",
|
Name: "can",
|
||||||
Aliases: []string{"c"},
|
Aliases: []string{"c"},
|
||||||
Usage: "CAN device string",
|
Usage: "CAN device string",
|
||||||
EnvVars: []string{"CAN_DEVICE"},
|
EnvVars: []string{"CAN_DEVICE"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function sets up the `serve` flags and services that use socketCAN
|
// this function sets up the `serve` flags and services that use socketCAN
|
||||||
|
@ -37,10 +37,9 @@ func init() {
|
||||||
subCmds = append(subCmds, socketCANCmd)
|
subCmds = append(subCmds, socketCANCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type socketCANService struct {
|
type socketCANService struct {
|
||||||
name string
|
name string
|
||||||
sock socketcan.CanSocket
|
sock *socketcan.CanSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *socketCANService) Status() {
|
func (s *socketCANService) Status() {
|
||||||
|
@ -66,13 +65,13 @@ func (s *socketCANService) Start(cCtx *cli.Context, broker *gotelem.JBroker, log
|
||||||
go vcanTest(cCtx.String("can"))
|
go vcanTest(cCtx.String("can"))
|
||||||
}
|
}
|
||||||
|
|
||||||
sock, err := socketcan.NewCanSocket(cCtx.String("can"))
|
s.sock, err = socketcan.NewCanSocket(cCtx.String("can"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("error opening socket", "err", err)
|
logger.Error("error opening socket", "err", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer sock.Close()
|
defer s.sock.Close()
|
||||||
s.name = sock.Name()
|
s.name = s.sock.Name()
|
||||||
|
|
||||||
// connect to the broker
|
// connect to the broker
|
||||||
rxCh, err := broker.Subscribe("socketCAN")
|
rxCh, err := broker.Subscribe("socketCAN")
|
||||||
|
@ -81,13 +80,12 @@ func (s *socketCANService) Start(cCtx *cli.Context, broker *gotelem.JBroker, log
|
||||||
}
|
}
|
||||||
defer broker.Unsubscribe("socketCAN")
|
defer broker.Unsubscribe("socketCAN")
|
||||||
|
|
||||||
|
|
||||||
// make a channel to receive socketCAN frames.
|
// make a channel to receive socketCAN frames.
|
||||||
rxCan := make(chan gotelem.Frame)
|
rxCan := make(chan gotelem.Frame)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
pkt, err := sock.Recv()
|
pkt, err := s.sock.Recv()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn("error receiving CAN packet", "err", err)
|
logger.Warn("error receiving CAN packet", "err", err)
|
||||||
}
|
}
|
||||||
|
@ -99,13 +97,13 @@ func (s *socketCANService) Start(cCtx *cli.Context, broker *gotelem.JBroker, log
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case msg := <-rxCh:
|
case msg := <-rxCh:
|
||||||
|
|
||||||
id, d, _ := skylab.CanSend(msg.Data)
|
id, d, _ := skylab.ToCanFrame(msg.Data)
|
||||||
|
|
||||||
frame.Id = id
|
frame.Id = id
|
||||||
frame.Data = d
|
frame.Data = d
|
||||||
|
|
||||||
sock.Send(&frame)
|
s.sock.Send(&frame)
|
||||||
|
|
||||||
case msg := <-rxCan:
|
case msg := <-rxCan:
|
||||||
p, err := skylab.FromCanFrame(msg.Id, msg.Data)
|
p, err := skylab.FromCanFrame(msg.Id, msg.Data)
|
||||||
|
@ -113,10 +111,10 @@ func (s *socketCANService) Start(cCtx *cli.Context, broker *gotelem.JBroker, log
|
||||||
logger.Warn("error parsing can packet", "id", msg.Id)
|
logger.Warn("error parsing can packet", "id", msg.Id)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cde := gotelem.CANDumpEntry{
|
cde := skylab.BusEvent{
|
||||||
Timestamp: float64(time.Now().UnixNano()) / 1e9,
|
Timestamp: float64(time.Now().UnixNano()) / 1e9,
|
||||||
Id: uint64(msg.Id),
|
Id: uint64(msg.Id),
|
||||||
Data: p,
|
Data: p,
|
||||||
}
|
}
|
||||||
broker.Publish("socketCAN", cde)
|
broker.Publish("socketCAN", cde)
|
||||||
case <-cCtx.Done():
|
case <-cCtx.Done():
|
||||||
|
@ -161,14 +159,13 @@ func vcanTest(devname string) {
|
||||||
Id: 0.2,
|
Id: 0.2,
|
||||||
}
|
}
|
||||||
|
|
||||||
id, data, err := skylab.CanSend(&testPkt)
|
id, data, err := skylab.ToCanFrame(&testPkt)
|
||||||
testFrame := gotelem.Frame{
|
testFrame := gotelem.Frame{
|
||||||
Id: id,
|
Id: id,
|
||||||
Data: data,
|
Data: data,
|
||||||
Kind: gotelem.CanSFFFrame,
|
Kind: gotelem.CanSFFFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
slog.Info("sending test packet")
|
slog.Info("sending test packet")
|
||||||
sock.Send(&testFrame)
|
sock.Send(&testFrame)
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/kschamplin/gotelem"
|
|
||||||
"github.com/kschamplin/gotelem/skylab"
|
"github.com/kschamplin/gotelem/skylab"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
@ -92,7 +91,7 @@ func run(ctx *cli.Context) (err error) {
|
||||||
|
|
||||||
segments := strings.Split(dumpLine, " ")
|
segments := strings.Split(dumpLine, " ")
|
||||||
|
|
||||||
var cd gotelem.CANDumpEntry
|
var cd skylab.BusEvent
|
||||||
// this is cursed but easiest way to get a float from a string.
|
// this is cursed but easiest way to get a float from a string.
|
||||||
fmt.Sscanf(segments[0], "(%g)", &cd.Timestamp)
|
fmt.Sscanf(segments[0], "(%g)", &cd.Timestamp)
|
||||||
|
|
||||||
|
|
3
frame.go
3
frame.go
|
@ -6,7 +6,6 @@
|
||||||
// by writing "adapters" to various devices/formats (xbee, sqlite, network socket, socketcan)
|
// by writing "adapters" to various devices/formats (xbee, sqlite, network socket, socketcan)
|
||||||
package gotelem
|
package gotelem
|
||||||
|
|
||||||
|
|
||||||
// Frame represents a protocol-agnostic CAN frame. The Id can be standard or extended,
|
// Frame represents a protocol-agnostic CAN frame. The Id can be standard or extended,
|
||||||
// but if it is extended, the Kind should be EFF.
|
// but if it is extended, the Kind should be EFF.
|
||||||
type Frame struct {
|
type Frame struct {
|
||||||
|
@ -15,7 +14,6 @@ type Frame struct {
|
||||||
Kind Kind
|
Kind Kind
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate msgp
|
|
||||||
type CANFrame interface {
|
type CANFrame interface {
|
||||||
Id() uint32
|
Id() uint32
|
||||||
Data() []byte
|
Data() []byte
|
||||||
|
@ -58,4 +56,3 @@ type CanTransciever interface {
|
||||||
CanSink
|
CanSink
|
||||||
CanSource
|
CanSource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -20,4 +20,5 @@ require (
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/stretchr/testify v1.8.0 // indirect
|
github.com/stretchr/testify v1.8.0 // indirect
|
||||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,14 +18,13 @@ import (
|
||||||
// SkylabFile is a yaml file from skylab.
|
// SkylabFile is a yaml file from skylab.
|
||||||
type SkylabFile struct {
|
type SkylabFile struct {
|
||||||
Packets []PacketDef
|
Packets []PacketDef
|
||||||
Boards []BoardSpec
|
Boards []BoardSpec
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BoardSpec struct {
|
type BoardSpec struct {
|
||||||
Name string
|
Name string
|
||||||
Transmit []string
|
Transmit []string
|
||||||
Recieve []string
|
Recieve []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// data field.
|
// data field.
|
||||||
|
@ -80,8 +79,12 @@ var typeSizeMap = map[string]uint{
|
||||||
"bitfield": 1,
|
"bitfield": 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MapType(ctype string) string {
|
||||||
|
return typeMap[ctype]
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DataField) ToStructMember(parentName string) string {
|
func (d *DataField) ToStructMember(parentName string) string {
|
||||||
|
|
||||||
if d.Type == "bitfield" {
|
if d.Type == "bitfield" {
|
||||||
bfStructName := parentName + toCamelInitCase(d.Name, true)
|
bfStructName := parentName + toCamelInitCase(d.Name, true)
|
||||||
return toCamelInitCase(d.Name, true) + " " + bfStructName
|
return toCamelInitCase(d.Name, true) + " " + bfStructName
|
||||||
|
@ -96,32 +99,31 @@ func (d *DataField) MakeMarshal(offset int) string {
|
||||||
if d.Type == "uint8_t" || d.Type == "int8_t" {
|
if d.Type == "uint8_t" || d.Type == "int8_t" {
|
||||||
return fmt.Sprintf("b[%d] = p.%s", offset, fieldName)
|
return fmt.Sprintf("b[%d] = p.%s", offset, fieldName)
|
||||||
} else if d.Type == "bitfield" {
|
} else if d.Type == "bitfield" {
|
||||||
return fmt.Sprintf("b[%d] = p.%s.Marshal()", offset,fieldName)
|
return fmt.Sprintf("b[%d] = p.%s.MarshalByte()", offset, fieldName)
|
||||||
} else if d.Type == "float" {
|
} else if d.Type == "float" {
|
||||||
|
|
||||||
return fmt.Sprintf("float32ToBytes(b[%d:], p.%s, false)", offset, fieldName)
|
return fmt.Sprintf("float32ToBytes(b[%d:], p.%s, false)", offset, fieldName)
|
||||||
|
|
||||||
} else if t ,ok := typeMap[d.Type]; ok {
|
} else if t, ok := typeMap[d.Type]; ok {
|
||||||
// it's uint or int of some kind, use endian to write it.
|
// it's uint or int of some kind, use endian to write it.
|
||||||
if strings.HasPrefix(t, "i") {
|
if strings.HasPrefix(t, "i") {
|
||||||
// this means it's a signed integer.
|
// this means it's a signed integer.
|
||||||
// encoding/binary does not support putting signed ints, instead
|
// encoding/binary does not support putting signed ints, instead
|
||||||
// we should cast it to unsigned and then use the unsigned int functions.
|
// we should cast it to unsigned and then use the unsigned int functions.
|
||||||
return fmt.Sprintf("binary.LittleEndian.PutU%s(b[%d:], u%s(p.%s))", t, offset, t, fieldName)
|
return fmt.Sprintf("binary.LittleEndian.PutU%s(b[%d:], u%s(p.%s))", t, offset, t, fieldName)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("binary.LittleEndian.Put%s(b[%d:], p.%s)", toCamelInitCase(t, true), offset, fieldName)
|
return fmt.Sprintf("binary.LittleEndian.Put%s(b[%d:], p.%s)", toCamelInitCase(t, true), offset, fieldName)
|
||||||
}
|
}
|
||||||
return "panic(\"failed to do it\")\n"
|
return "panic(\"failed to do it\")\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (d *DataField) MakeUnmarshal(offset int) string {
|
func (d *DataField) MakeUnmarshal(offset int) string {
|
||||||
|
|
||||||
fieldName := toCamelInitCase(d.Name, true)
|
fieldName := toCamelInitCase(d.Name, true)
|
||||||
if d.Type == "uint8_t" || d.Type == "int8_t" {
|
if d.Type == "uint8_t" || d.Type == "int8_t" {
|
||||||
return fmt.Sprintf("p.%s = b[%d]", fieldName, offset)
|
return fmt.Sprintf("p.%s = b[%d]", fieldName, offset)
|
||||||
} else if d.Type == "bitfield" {
|
} else if d.Type == "bitfield" {
|
||||||
return fmt.Sprintf("p.%s.Unmarshal(b[%d])", fieldName, offset)
|
return fmt.Sprintf("p.%s.UnmarshalByte(b[%d])", fieldName, offset)
|
||||||
} else if d.Type == "float" {
|
} else if d.Type == "float" {
|
||||||
|
|
||||||
return fmt.Sprintf("p.%s = float32FromBytes(b[%d:], false)", fieldName, offset)
|
return fmt.Sprintf("p.%s = float32FromBytes(b[%d:], false)", fieldName, offset)
|
||||||
|
@ -134,14 +136,12 @@ func (d *DataField) MakeUnmarshal(offset int) string {
|
||||||
// encoding/binary does not support putting signed ints, instead
|
// encoding/binary does not support putting signed ints, instead
|
||||||
// we should cast it to unsigned and then use the unsigned int functions.
|
// we should cast it to unsigned and then use the unsigned int functions.
|
||||||
return fmt.Sprintf("p.%s = %s(binary.LittleEndian.U%s(b[%d:]))", fieldName, t, t, offset)
|
return fmt.Sprintf("p.%s = %s(binary.LittleEndian.U%s(b[%d:]))", fieldName, t, t, offset)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("p.%s = binary.LittleEndian.%s(b[%d:])", fieldName, toCamelInitCase(t, true), offset)
|
return fmt.Sprintf("p.%s = binary.LittleEndian.%s(b[%d:])", fieldName, toCamelInitCase(t, true), offset)
|
||||||
}
|
}
|
||||||
panic("unhandled type")
|
panic("unhandled type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func (p PacketDef) CalcSize() int {
|
func (p PacketDef) CalcSize() int {
|
||||||
// makes a function that returns the size of the code.
|
// makes a function that returns the size of the code.
|
||||||
|
|
||||||
|
@ -153,7 +153,6 @@ func (p PacketDef) CalcSize() int {
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (p PacketDef) MakeMarshal() string {
|
func (p PacketDef) MakeMarshal() string {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
|
|
||||||
|
@ -170,14 +169,12 @@ func (p PacketDef) MakeMarshal() string {
|
||||||
offset += int(typeSizeMap[val.Type])
|
offset += int(typeSizeMap[val.Type])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p PacketDef) MakeUnmarshal() string {
|
func (p PacketDef) MakeUnmarshal() string {
|
||||||
var buf strings.Builder
|
var buf strings.Builder
|
||||||
|
|
||||||
|
|
||||||
var offset int = 0
|
var offset int = 0
|
||||||
for _, val := range p.Data {
|
for _, val := range p.Data {
|
||||||
|
|
||||||
|
@ -190,7 +187,6 @@ func (p PacketDef) MakeUnmarshal() string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// stolen camelCaser code. initCase = true means CamelCase, false means camelCase
|
// stolen camelCaser code. initCase = true means CamelCase, false means camelCase
|
||||||
func toCamelInitCase(s string, initCase bool) string {
|
func toCamelInitCase(s string, initCase bool) string {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
|
@ -228,29 +224,28 @@ func toCamelInitCase(s string, initCase bool) string {
|
||||||
return n.String()
|
return n.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// N takes a start and stop value and returns a stream of
|
// N takes a start and stop value and returns a stream of
|
||||||
// [start, end), including the starting value but excluding the end value.
|
// [start, end), including the starting value but excluding the end value.
|
||||||
func N(start, end int) (stream chan int) {
|
func N(start, end int) (stream chan int) {
|
||||||
stream = make(chan int)
|
stream = make(chan int)
|
||||||
go func() {
|
go func() {
|
||||||
for i := start; i < end; i++ {
|
for i := start; i < end; i++ {
|
||||||
stream <- i
|
stream <- i
|
||||||
}
|
}
|
||||||
close(stream)
|
close(stream)
|
||||||
}()
|
}()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Nx takes a start, a quantity, and an offset and returns a stream
|
// Nx takes a start, a quantity, and an offset and returns a stream
|
||||||
// of `times` values which count from start and increment by `offset` each
|
// of `times` values which count from start and increment by `offset` each
|
||||||
// time.
|
// time.
|
||||||
func Nx (start, times, offset int) (elems []int) {
|
func Nx(start, times, offset int) (elems []int) {
|
||||||
elems = make([]int, times)
|
elems = make([]int, times)
|
||||||
for i := 0; i < times; i++ {
|
for i := 0; i < times; i++ {
|
||||||
elems[i] = start + offset * i
|
elems[i] = start + offset*i
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// dumb function for type conversion between uint32 to integer
|
// dumb function for type conversion between uint32 to integer
|
||||||
|
@ -259,10 +254,10 @@ func uint32ToInt(i uint32) (o int) {
|
||||||
return int(i)
|
return int(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// strJoin is a remapping of strings.Join so that we can use
|
// strJoin is a remapping of strings.Join so that we can use
|
||||||
// it in a pipeline.
|
// it in a pipeline.
|
||||||
// {{.Names | strJoin ", " }}
|
//
|
||||||
|
// {{.Names | strJoin ", " }}
|
||||||
func strJoin(delim string, elems []string) string {
|
func strJoin(delim string, elems []string) string {
|
||||||
return strings.Join(elems, delim)
|
return strings.Join(elems, delim)
|
||||||
}
|
}
|
||||||
|
@ -277,7 +272,6 @@ func mapf(format string, els []int) []string {
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// read path as the first arg, glob it for yamls, read each yaml into a skylabFile.
|
// read path as the first arg, glob it for yamls, read each yaml into a skylabFile.
|
||||||
// then take each skylab file, put all the packets into one big array.
|
// then take each skylab file, put all the packets into one big array.
|
||||||
|
@ -312,15 +306,16 @@ func main() {
|
||||||
v.Boards = append(v.Boards, newFile.Boards...)
|
v.Boards = append(v.Boards, newFile.Boards...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// we add any functions mapping we need here.
|
// we add any functions mapping we need here.
|
||||||
fnMap := template.FuncMap{
|
fnMap := template.FuncMap{
|
||||||
"camelCase": toCamelInitCase,
|
"camelCase": toCamelInitCase,
|
||||||
"Time": time.Now,
|
"Time": time.Now,
|
||||||
"N": N,
|
"N": N,
|
||||||
"Nx": Nx,
|
"Nx": Nx,
|
||||||
"int": uint32ToInt,
|
"int": uint32ToInt,
|
||||||
"strJoin": strJoin,
|
"strJoin": strJoin,
|
||||||
"mapf": mapf,
|
"mapf": mapf,
|
||||||
|
"maptype": MapType,
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpl, err := template.New("golang.go.tmpl").Funcs(fnMap).ParseGlob("templates/*.go.tmpl")
|
tmpl, err := template.New("golang.go.tmpl").Funcs(fnMap).ParseGlob("templates/*.go.tmpl")
|
||||||
|
@ -336,7 +331,6 @@ func main() {
|
||||||
}
|
}
|
||||||
err = tmpl.Execute(f, v)
|
err = tmpl.Execute(f, v)
|
||||||
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -354,4 +348,3 @@ func main() {
|
||||||
tests.Execute(testF, v)
|
tests.Execute(testF, v)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ type Sizer interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanSend takes a packet and makes CAN framing data.
|
// CanSend takes a packet and makes CAN framing data.
|
||||||
func CanSend(p Packet) (id uint32, data []byte, err error) {
|
func ToCanFrame(p Packet) (id uint32, data []byte, err error) {
|
||||||
|
|
||||||
id, err = p.CANId()
|
id, err = p.CANId()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -71,29 +71,86 @@ func CanSend(p Packet) (id uint32, data []byte, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- JSON encoding business ----
|
// ---- other wire encoding business ----
|
||||||
|
|
||||||
type JSONPacket struct {
|
// internal structure for partially decoding json object.
|
||||||
Id uint32
|
type jsonRawEvent struct {
|
||||||
Data json.RawMessage
|
Timestamp float64
|
||||||
|
Id uint32
|
||||||
|
Name string
|
||||||
|
Data json.RawMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToJson(p Packet) (*JSONPacket, error) {
|
// BusEvent is a timestamped Skylab packet designed to be serialized.
|
||||||
|
type BusEvent struct {
|
||||||
d, err := json.Marshal(p)
|
Timestamp float64 `json:"ts"`
|
||||||
|
Id uint64 `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Data Packet `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: handle Name field.
|
||||||
|
func (e *BusEvent) MarshalJSON() (b []byte, err error) {
|
||||||
|
// create the underlying raw event
|
||||||
|
j := &jsonRawEvent{
|
||||||
|
Timestamp: e.Timestamp,
|
||||||
|
Id: uint32(e.Id),
|
||||||
|
}
|
||||||
|
// now we use the magic Packet -> map[string]interface{} function
|
||||||
|
j.Data, err = json.Marshal(e.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := p.CANId()
|
return json.Marshal(j)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *BusEvent) UnmarshalJSON(b []byte) error {
|
||||||
|
var jRaw *jsonRawEvent
|
||||||
|
|
||||||
|
err := json.Unmarshal(b, jRaw)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Timestamp = jRaw.Timestamp
|
||||||
|
e.Id = uint64(jRaw.Id)
|
||||||
|
e.Data, err = FromJson(jRaw.Id, jRaw.Data)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: handle name field.
|
||||||
|
func (e *BusEvent) MarshalMsg(b []byte) ([]byte, error) {
|
||||||
|
|
||||||
|
// we need to send the bytes as a []byte instead of
|
||||||
|
// an object like the JSON one (lose self-documenting)
|
||||||
|
data, err := e.Data.MarshalPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
rawEv := &msgpRawEvent{
|
||||||
|
Timestamp: e.Timestamp,
|
||||||
|
Id: uint32(e.Id),
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
|
||||||
jp := &JSONPacket{Id: id, Data: d}
|
return rawEv.MarshalMsg(b)
|
||||||
|
}
|
||||||
|
|
||||||
return jp, nil
|
func (e *BusEvent) UnmarshalMsg(b []byte) ([]byte, error) {
|
||||||
|
rawEv := &msgpRawEvent{}
|
||||||
|
remain, err := rawEv.UnmarshalMsg(b)
|
||||||
|
if err != nil {
|
||||||
|
return remain, err
|
||||||
|
}
|
||||||
|
e.Timestamp = rawEv.Timestamp
|
||||||
|
e.Id = uint64(rawEv.Id)
|
||||||
|
e.Data, err = FromCanFrame(rawEv.Id, rawEv.Data)
|
||||||
|
|
||||||
|
return remain, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to be able to parse the JSON as well. this is done using the
|
// we need to be able to parse the JSON as well. this is done using the
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
18
skylab/skylab_msgp.go
Normal file
18
skylab/skylab_msgp.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package skylab
|
||||||
|
|
||||||
|
//go:generate msgp -unexported
|
||||||
|
|
||||||
|
// internal structure for handling
|
||||||
|
type msgpRawEvent struct {
|
||||||
|
Timestamp float64 `msg:"ts"`
|
||||||
|
Id uint32 `msg:"id"`
|
||||||
|
Data []byte `msg:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// internal structure to represent a raw can packet over the network.
|
||||||
|
// this is what's sent over the solar car to lead xbee connection
|
||||||
|
// for brevity while still having some robustness.
|
||||||
|
type msgpRawPacket struct {
|
||||||
|
Id uint32 `msg:"id"`
|
||||||
|
Data []byte `msg:"data"`
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package gotelem
|
package skylab
|
||||||
|
|
||||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// DecodeMsg implements msgp.Decodable
|
// DecodeMsg implements msgp.Decodable
|
||||||
func (z *CanFilter) DecodeMsg(dc *msgp.Reader) (err error) {
|
func (z *msgpRawEvent) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||||
var field []byte
|
var field []byte
|
||||||
_ = field
|
_ = field
|
||||||
var zb0001 uint32
|
var zb0001 uint32
|
||||||
|
@ -24,181 +24,24 @@ func (z *CanFilter) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch msgp.UnsafeString(field) {
|
switch msgp.UnsafeString(field) {
|
||||||
case "Id":
|
case "ts":
|
||||||
|
z.Timestamp, err = dc.ReadFloat64()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Timestamp")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "id":
|
||||||
z.Id, err = dc.ReadUint32()
|
z.Id, err = dc.ReadUint32()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = msgp.WrapError(err, "Id")
|
err = msgp.WrapError(err, "Id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case "Mask":
|
case "data":
|
||||||
z.Mask, err = dc.ReadUint32()
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Mask")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case "Inverted":
|
|
||||||
z.Inverted, err = dc.ReadBool()
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Inverted")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err = dc.Skip()
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// EncodeMsg implements msgp.Encodable
|
|
||||||
func (z CanFilter) EncodeMsg(en *msgp.Writer) (err error) {
|
|
||||||
// map header, size 3
|
|
||||||
// write "Id"
|
|
||||||
err = en.Append(0x83, 0xa2, 0x49, 0x64)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = en.WriteUint32(z.Id)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Id")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// write "Mask"
|
|
||||||
err = en.Append(0xa4, 0x4d, 0x61, 0x73, 0x6b)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = en.WriteUint32(z.Mask)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Mask")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// write "Inverted"
|
|
||||||
err = en.Append(0xa8, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = en.WriteBool(z.Inverted)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Inverted")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalMsg implements msgp.Marshaler
|
|
||||||
func (z CanFilter) MarshalMsg(b []byte) (o []byte, err error) {
|
|
||||||
o = msgp.Require(b, z.Msgsize())
|
|
||||||
// map header, size 3
|
|
||||||
// string "Id"
|
|
||||||
o = append(o, 0x83, 0xa2, 0x49, 0x64)
|
|
||||||
o = msgp.AppendUint32(o, z.Id)
|
|
||||||
// string "Mask"
|
|
||||||
o = append(o, 0xa4, 0x4d, 0x61, 0x73, 0x6b)
|
|
||||||
o = msgp.AppendUint32(o, z.Mask)
|
|
||||||
// string "Inverted"
|
|
||||||
o = append(o, 0xa8, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x65, 0x64)
|
|
||||||
o = msgp.AppendBool(o, z.Inverted)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalMsg implements msgp.Unmarshaler
|
|
||||||
func (z *CanFilter) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
|
||||||
var field []byte
|
|
||||||
_ = field
|
|
||||||
var zb0001 uint32
|
|
||||||
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for zb0001 > 0 {
|
|
||||||
zb0001--
|
|
||||||
field, bts, err = msgp.ReadMapKeyZC(bts)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch msgp.UnsafeString(field) {
|
|
||||||
case "Id":
|
|
||||||
z.Id, bts, err = msgp.ReadUint32Bytes(bts)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Id")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case "Mask":
|
|
||||||
z.Mask, bts, err = msgp.ReadUint32Bytes(bts)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Mask")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case "Inverted":
|
|
||||||
z.Inverted, bts, err = msgp.ReadBoolBytes(bts)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Inverted")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
bts, err = msgp.Skip(bts)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
o = bts
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
|
||||||
func (z CanFilter) Msgsize() (s int) {
|
|
||||||
s = 1 + 3 + msgp.Uint32Size + 5 + msgp.Uint32Size + 9 + msgp.BoolSize
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeMsg implements msgp.Decodable
|
|
||||||
func (z *Frame) DecodeMsg(dc *msgp.Reader) (err error) {
|
|
||||||
var field []byte
|
|
||||||
_ = field
|
|
||||||
var zb0001 uint32
|
|
||||||
zb0001, err = dc.ReadMapHeader()
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for zb0001 > 0 {
|
|
||||||
zb0001--
|
|
||||||
field, err = dc.ReadMapKeyPtr()
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch msgp.UnsafeString(field) {
|
|
||||||
case "Id":
|
|
||||||
z.Id, err = dc.ReadUint32()
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Id")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case "Data":
|
|
||||||
z.Data, err = dc.ReadBytes(z.Data)
|
z.Data, err = dc.ReadBytes(z.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = msgp.WrapError(err, "Data")
|
err = msgp.WrapError(err, "Data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case "Kind":
|
|
||||||
{
|
|
||||||
var zb0002 uint8
|
|
||||||
zb0002, err = dc.ReadUint8()
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Kind")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.Kind = Kind(zb0002)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
err = dc.Skip()
|
err = dc.Skip()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -211,10 +54,20 @@ func (z *Frame) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeMsg implements msgp.Encodable
|
// EncodeMsg implements msgp.Encodable
|
||||||
func (z *Frame) EncodeMsg(en *msgp.Writer) (err error) {
|
func (z *msgpRawEvent) EncodeMsg(en *msgp.Writer) (err error) {
|
||||||
// map header, size 3
|
// map header, size 3
|
||||||
// write "Id"
|
// write "ts"
|
||||||
err = en.Append(0x83, 0xa2, 0x49, 0x64)
|
err = en.Append(0x83, 0xa2, 0x74, 0x73)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = en.WriteFloat64(z.Timestamp)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Timestamp")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// write "id"
|
||||||
|
err = en.Append(0xa2, 0x69, 0x64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -223,8 +76,8 @@ func (z *Frame) EncodeMsg(en *msgp.Writer) (err error) {
|
||||||
err = msgp.WrapError(err, "Id")
|
err = msgp.WrapError(err, "Id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// write "Data"
|
// write "data"
|
||||||
err = en.Append(0xa4, 0x44, 0x61, 0x74, 0x61)
|
err = en.Append(0xa4, 0x64, 0x61, 0x74, 0x61)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -233,37 +86,27 @@ func (z *Frame) EncodeMsg(en *msgp.Writer) (err error) {
|
||||||
err = msgp.WrapError(err, "Data")
|
err = msgp.WrapError(err, "Data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// write "Kind"
|
|
||||||
err = en.Append(0xa4, 0x4b, 0x69, 0x6e, 0x64)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = en.WriteUint8(uint8(z.Kind))
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Kind")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalMsg implements msgp.Marshaler
|
// MarshalMsg implements msgp.Marshaler
|
||||||
func (z *Frame) MarshalMsg(b []byte) (o []byte, err error) {
|
func (z *msgpRawEvent) MarshalMsg(b []byte) (o []byte, err error) {
|
||||||
o = msgp.Require(b, z.Msgsize())
|
o = msgp.Require(b, z.Msgsize())
|
||||||
// map header, size 3
|
// map header, size 3
|
||||||
// string "Id"
|
// string "ts"
|
||||||
o = append(o, 0x83, 0xa2, 0x49, 0x64)
|
o = append(o, 0x83, 0xa2, 0x74, 0x73)
|
||||||
|
o = msgp.AppendFloat64(o, z.Timestamp)
|
||||||
|
// string "id"
|
||||||
|
o = append(o, 0xa2, 0x69, 0x64)
|
||||||
o = msgp.AppendUint32(o, z.Id)
|
o = msgp.AppendUint32(o, z.Id)
|
||||||
// string "Data"
|
// string "data"
|
||||||
o = append(o, 0xa4, 0x44, 0x61, 0x74, 0x61)
|
o = append(o, 0xa4, 0x64, 0x61, 0x74, 0x61)
|
||||||
o = msgp.AppendBytes(o, z.Data)
|
o = msgp.AppendBytes(o, z.Data)
|
||||||
// string "Kind"
|
|
||||||
o = append(o, 0xa4, 0x4b, 0x69, 0x6e, 0x64)
|
|
||||||
o = msgp.AppendUint8(o, uint8(z.Kind))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalMsg implements msgp.Unmarshaler
|
// UnmarshalMsg implements msgp.Unmarshaler
|
||||||
func (z *Frame) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
func (z *msgpRawEvent) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||||
var field []byte
|
var field []byte
|
||||||
_ = field
|
_ = field
|
||||||
var zb0001 uint32
|
var zb0001 uint32
|
||||||
|
@ -280,28 +123,24 @@ func (z *Frame) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch msgp.UnsafeString(field) {
|
switch msgp.UnsafeString(field) {
|
||||||
case "Id":
|
case "ts":
|
||||||
|
z.Timestamp, bts, err = msgp.ReadFloat64Bytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Timestamp")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "id":
|
||||||
z.Id, bts, err = msgp.ReadUint32Bytes(bts)
|
z.Id, bts, err = msgp.ReadUint32Bytes(bts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = msgp.WrapError(err, "Id")
|
err = msgp.WrapError(err, "Id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case "Data":
|
case "data":
|
||||||
z.Data, bts, err = msgp.ReadBytesBytes(bts, z.Data)
|
z.Data, bts, err = msgp.ReadBytesBytes(bts, z.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = msgp.WrapError(err, "Data")
|
err = msgp.WrapError(err, "Data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case "Kind":
|
|
||||||
{
|
|
||||||
var zb0002 uint8
|
|
||||||
zb0002, bts, err = msgp.ReadUint8Bytes(bts)
|
|
||||||
if err != nil {
|
|
||||||
err = msgp.WrapError(err, "Kind")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
z.Kind = Kind(zb0002)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
bts, err = msgp.Skip(bts)
|
bts, err = msgp.Skip(bts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -315,59 +154,135 @@ func (z *Frame) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||||
func (z *Frame) Msgsize() (s int) {
|
func (z *msgpRawEvent) Msgsize() (s int) {
|
||||||
s = 1 + 3 + msgp.Uint32Size + 5 + msgp.BytesPrefixSize + len(z.Data) + 5 + msgp.Uint8Size
|
s = 1 + 3 + msgp.Float64Size + 3 + msgp.Uint32Size + 5 + msgp.BytesPrefixSize + len(z.Data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeMsg implements msgp.Decodable
|
// DecodeMsg implements msgp.Decodable
|
||||||
func (z *Kind) DecodeMsg(dc *msgp.Reader) (err error) {
|
func (z *msgpRawPacket) DecodeMsg(dc *msgp.Reader) (err error) {
|
||||||
{
|
var field []byte
|
||||||
var zb0001 uint8
|
_ = field
|
||||||
zb0001, err = dc.ReadUint8()
|
var zb0001 uint32
|
||||||
|
zb0001, err = dc.ReadMapHeader()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for zb0001 > 0 {
|
||||||
|
zb0001--
|
||||||
|
field, err = dc.ReadMapKeyPtr()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = msgp.WrapError(err)
|
err = msgp.WrapError(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
(*z) = Kind(zb0001)
|
switch msgp.UnsafeString(field) {
|
||||||
|
case "id":
|
||||||
|
z.Id, err = dc.ReadUint32()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "data":
|
||||||
|
z.Data, err = dc.ReadBytes(z.Data)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Data")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = dc.Skip()
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncodeMsg implements msgp.Encodable
|
// EncodeMsg implements msgp.Encodable
|
||||||
func (z Kind) EncodeMsg(en *msgp.Writer) (err error) {
|
func (z *msgpRawPacket) EncodeMsg(en *msgp.Writer) (err error) {
|
||||||
err = en.WriteUint8(uint8(z))
|
// map header, size 2
|
||||||
|
// write "id"
|
||||||
|
err = en.Append(0x82, 0xa2, 0x69, 0x64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = msgp.WrapError(err)
|
return
|
||||||
|
}
|
||||||
|
err = en.WriteUint32(z.Id)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// write "data"
|
||||||
|
err = en.Append(0xa4, 0x64, 0x61, 0x74, 0x61)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = en.WriteBytes(z.Data)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalMsg implements msgp.Marshaler
|
// MarshalMsg implements msgp.Marshaler
|
||||||
func (z Kind) MarshalMsg(b []byte) (o []byte, err error) {
|
func (z *msgpRawPacket) MarshalMsg(b []byte) (o []byte, err error) {
|
||||||
o = msgp.Require(b, z.Msgsize())
|
o = msgp.Require(b, z.Msgsize())
|
||||||
o = msgp.AppendUint8(o, uint8(z))
|
// map header, size 2
|
||||||
|
// string "id"
|
||||||
|
o = append(o, 0x82, 0xa2, 0x69, 0x64)
|
||||||
|
o = msgp.AppendUint32(o, z.Id)
|
||||||
|
// string "data"
|
||||||
|
o = append(o, 0xa4, 0x64, 0x61, 0x74, 0x61)
|
||||||
|
o = msgp.AppendBytes(o, z.Data)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalMsg implements msgp.Unmarshaler
|
// UnmarshalMsg implements msgp.Unmarshaler
|
||||||
func (z *Kind) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
func (z *msgpRawPacket) UnmarshalMsg(bts []byte) (o []byte, err error) {
|
||||||
{
|
var field []byte
|
||||||
var zb0001 uint8
|
_ = field
|
||||||
zb0001, bts, err = msgp.ReadUint8Bytes(bts)
|
var zb0001 uint32
|
||||||
|
zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for zb0001 > 0 {
|
||||||
|
zb0001--
|
||||||
|
field, bts, err = msgp.ReadMapKeyZC(bts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = msgp.WrapError(err)
|
err = msgp.WrapError(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
(*z) = Kind(zb0001)
|
switch msgp.UnsafeString(field) {
|
||||||
|
case "id":
|
||||||
|
z.Id, bts, err = msgp.ReadUint32Bytes(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Id")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case "data":
|
||||||
|
z.Data, bts, err = msgp.ReadBytesBytes(bts, z.Data)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err, "Data")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
bts, err = msgp.Skip(bts)
|
||||||
|
if err != nil {
|
||||||
|
err = msgp.WrapError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
o = bts
|
o = bts
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
|
||||||
func (z Kind) Msgsize() (s int) {
|
func (z *msgpRawPacket) Msgsize() (s int) {
|
||||||
s = msgp.Uint8Size
|
s = 1 + 3 + msgp.Uint32Size + 5 + msgp.BytesPrefixSize + len(z.Data)
|
||||||
return
|
return
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package gotelem
|
package skylab
|
||||||
|
|
||||||
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ import (
|
||||||
"github.com/tinylib/msgp/msgp"
|
"github.com/tinylib/msgp/msgp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMarshalUnmarshalCanFilter(t *testing.T) {
|
func TestMarshalUnmarshalmsgpRawEvent(t *testing.T) {
|
||||||
v := CanFilter{}
|
v := msgpRawEvent{}
|
||||||
bts, err := v.MarshalMsg(nil)
|
bts, err := v.MarshalMsg(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -32,8 +32,8 @@ func TestMarshalUnmarshalCanFilter(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMarshalMsgCanFilter(b *testing.B) {
|
func BenchmarkMarshalMsgmsgpRawEvent(b *testing.B) {
|
||||||
v := CanFilter{}
|
v := msgpRawEvent{}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
@ -41,8 +41,8 @@ func BenchmarkMarshalMsgCanFilter(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAppendMsgCanFilter(b *testing.B) {
|
func BenchmarkAppendMsgmsgpRawEvent(b *testing.B) {
|
||||||
v := CanFilter{}
|
v := msgpRawEvent{}
|
||||||
bts := make([]byte, 0, v.Msgsize())
|
bts := make([]byte, 0, v.Msgsize())
|
||||||
bts, _ = v.MarshalMsg(bts[0:0])
|
bts, _ = v.MarshalMsg(bts[0:0])
|
||||||
b.SetBytes(int64(len(bts)))
|
b.SetBytes(int64(len(bts)))
|
||||||
|
@ -53,8 +53,8 @@ func BenchmarkAppendMsgCanFilter(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkUnmarshalCanFilter(b *testing.B) {
|
func BenchmarkUnmarshalmsgpRawEvent(b *testing.B) {
|
||||||
v := CanFilter{}
|
v := msgpRawEvent{}
|
||||||
bts, _ := v.MarshalMsg(nil)
|
bts, _ := v.MarshalMsg(nil)
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.SetBytes(int64(len(bts)))
|
b.SetBytes(int64(len(bts)))
|
||||||
|
@ -67,17 +67,17 @@ func BenchmarkUnmarshalCanFilter(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncodeDecodeCanFilter(t *testing.T) {
|
func TestEncodeDecodemsgpRawEvent(t *testing.T) {
|
||||||
v := CanFilter{}
|
v := msgpRawEvent{}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
msgp.Encode(&buf, &v)
|
msgp.Encode(&buf, &v)
|
||||||
|
|
||||||
m := v.Msgsize()
|
m := v.Msgsize()
|
||||||
if buf.Len() > m {
|
if buf.Len() > m {
|
||||||
t.Log("WARNING: TestEncodeDecodeCanFilter Msgsize() is inaccurate")
|
t.Log("WARNING: TestEncodeDecodemsgpRawEvent Msgsize() is inaccurate")
|
||||||
}
|
}
|
||||||
|
|
||||||
vn := CanFilter{}
|
vn := msgpRawEvent{}
|
||||||
err := msgp.Decode(&buf, &vn)
|
err := msgp.Decode(&buf, &vn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -91,8 +91,8 @@ func TestEncodeDecodeCanFilter(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkEncodeCanFilter(b *testing.B) {
|
func BenchmarkEncodemsgpRawEvent(b *testing.B) {
|
||||||
v := CanFilter{}
|
v := msgpRawEvent{}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
msgp.Encode(&buf, &v)
|
msgp.Encode(&buf, &v)
|
||||||
b.SetBytes(int64(buf.Len()))
|
b.SetBytes(int64(buf.Len()))
|
||||||
|
@ -105,8 +105,8 @@ func BenchmarkEncodeCanFilter(b *testing.B) {
|
||||||
en.Flush()
|
en.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkDecodeCanFilter(b *testing.B) {
|
func BenchmarkDecodemsgpRawEvent(b *testing.B) {
|
||||||
v := CanFilter{}
|
v := msgpRawEvent{}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
msgp.Encode(&buf, &v)
|
msgp.Encode(&buf, &v)
|
||||||
b.SetBytes(int64(buf.Len()))
|
b.SetBytes(int64(buf.Len()))
|
||||||
|
@ -122,8 +122,8 @@ func BenchmarkDecodeCanFilter(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarshalUnmarshalFrame(t *testing.T) {
|
func TestMarshalUnmarshalmsgpRawPacket(t *testing.T) {
|
||||||
v := Frame{}
|
v := msgpRawPacket{}
|
||||||
bts, err := v.MarshalMsg(nil)
|
bts, err := v.MarshalMsg(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -145,8 +145,8 @@ func TestMarshalUnmarshalFrame(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMarshalMsgFrame(b *testing.B) {
|
func BenchmarkMarshalMsgmsgpRawPacket(b *testing.B) {
|
||||||
v := Frame{}
|
v := msgpRawPacket{}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
@ -154,8 +154,8 @@ func BenchmarkMarshalMsgFrame(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAppendMsgFrame(b *testing.B) {
|
func BenchmarkAppendMsgmsgpRawPacket(b *testing.B) {
|
||||||
v := Frame{}
|
v := msgpRawPacket{}
|
||||||
bts := make([]byte, 0, v.Msgsize())
|
bts := make([]byte, 0, v.Msgsize())
|
||||||
bts, _ = v.MarshalMsg(bts[0:0])
|
bts, _ = v.MarshalMsg(bts[0:0])
|
||||||
b.SetBytes(int64(len(bts)))
|
b.SetBytes(int64(len(bts)))
|
||||||
|
@ -166,8 +166,8 @@ func BenchmarkAppendMsgFrame(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkUnmarshalFrame(b *testing.B) {
|
func BenchmarkUnmarshalmsgpRawPacket(b *testing.B) {
|
||||||
v := Frame{}
|
v := msgpRawPacket{}
|
||||||
bts, _ := v.MarshalMsg(nil)
|
bts, _ := v.MarshalMsg(nil)
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.SetBytes(int64(len(bts)))
|
b.SetBytes(int64(len(bts)))
|
||||||
|
@ -180,17 +180,17 @@ func BenchmarkUnmarshalFrame(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncodeDecodeFrame(t *testing.T) {
|
func TestEncodeDecodemsgpRawPacket(t *testing.T) {
|
||||||
v := Frame{}
|
v := msgpRawPacket{}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
msgp.Encode(&buf, &v)
|
msgp.Encode(&buf, &v)
|
||||||
|
|
||||||
m := v.Msgsize()
|
m := v.Msgsize()
|
||||||
if buf.Len() > m {
|
if buf.Len() > m {
|
||||||
t.Log("WARNING: TestEncodeDecodeFrame Msgsize() is inaccurate")
|
t.Log("WARNING: TestEncodeDecodemsgpRawPacket Msgsize() is inaccurate")
|
||||||
}
|
}
|
||||||
|
|
||||||
vn := Frame{}
|
vn := msgpRawPacket{}
|
||||||
err := msgp.Decode(&buf, &vn)
|
err := msgp.Decode(&buf, &vn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -204,8 +204,8 @@ func TestEncodeDecodeFrame(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkEncodeFrame(b *testing.B) {
|
func BenchmarkEncodemsgpRawPacket(b *testing.B) {
|
||||||
v := Frame{}
|
v := msgpRawPacket{}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
msgp.Encode(&buf, &v)
|
msgp.Encode(&buf, &v)
|
||||||
b.SetBytes(int64(buf.Len()))
|
b.SetBytes(int64(buf.Len()))
|
||||||
|
@ -218,8 +218,8 @@ func BenchmarkEncodeFrame(b *testing.B) {
|
||||||
en.Flush()
|
en.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkDecodeFrame(b *testing.B) {
|
func BenchmarkDecodemsgpRawPacket(b *testing.B) {
|
||||||
v := Frame{}
|
v := msgpRawPacket{}
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
msgp.Encode(&buf, &v)
|
msgp.Encode(&buf, &v)
|
||||||
b.SetBytes(int64(buf.Len()))
|
b.SetBytes(int64(buf.Len()))
|
|
@ -11,7 +11,7 @@ type {{$bfname}} struct {
|
||||||
{{- end}}
|
{{- end}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *{{$bfname}}) Marshal() byte {
|
func (p *{{$bfname}}) MarshalByte() byte {
|
||||||
var b byte
|
var b byte
|
||||||
{{- range $idx, $el := .Bits}}
|
{{- range $idx, $el := .Bits}}
|
||||||
{{- $bitName := camelCase $el.Name true}}
|
{{- $bitName := camelCase $el.Name true}}
|
||||||
|
@ -22,7 +22,7 @@ func (p *{{$bfname}}) Marshal() byte {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *{{$bfname}}) Unmarshal(b byte) {
|
func (p *{{$bfname}}) UnmarshalByte(b byte) {
|
||||||
{{- range $idx, $el := .Bits}}
|
{{- range $idx, $el := .Bits}}
|
||||||
{{- $bitName := camelCase $el.Name true }}
|
{{- $bitName := camelCase $el.Name true }}
|
||||||
p.{{$bitName}} = (b & (1 << {{ $idx }})) != 0
|
p.{{$bitName}} = (b & (1 << {{ $idx }})) != 0
|
||||||
|
@ -114,7 +114,7 @@ var idMap = map[uint32]bool{
|
||||||
// If the CAN ID is unknown, it will return an error.
|
// If the CAN ID is unknown, it will return an error.
|
||||||
func FromCanFrame(id uint32, data []byte) (Packet, error) {
|
func FromCanFrame(id uint32, data []byte) (Packet, error) {
|
||||||
if !idMap[id] {
|
if !idMap[id] {
|
||||||
return nil, errors.New("Unknown Id")
|
return nil, errors.New("unknown id")
|
||||||
}
|
}
|
||||||
switch id {
|
switch id {
|
||||||
{{- range $p := .Packets }}
|
{{- range $p := .Packets }}
|
||||||
|
@ -133,34 +133,32 @@ func FromCanFrame(id uint32, data []byte) (Packet, error) {
|
||||||
{{- end}}
|
{{- end}}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("failed to match Id, something is really wrong!")
|
return nil, errors.New("failed to match Id, something is really wrong")
|
||||||
}
|
}
|
||||||
|
|
||||||
func FromJson (raw []byte) (Packet, error) {
|
|
||||||
// attempt to parse the JSON to a JSONPacket
|
func FromJson (id uint32, raw []byte) (Packet, error) {
|
||||||
jp := &JSONPacket{}
|
if !idMap[id] {
|
||||||
err := json.Unmarshal(raw, jp)
|
return nil, errors.New("unknown id")
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
switch jp.Id {
|
switch id {
|
||||||
{{- range $p := .Packets }}
|
{{- range $p := .Packets }}
|
||||||
{{- if $p.Repeat }}
|
{{- if $p.Repeat }}
|
||||||
case {{ Nx (int $p.Id) $p.Repeat $p.Offset | mapf "0x%X" | strJoin ", " -}}:
|
case {{ Nx (int $p.Id) $p.Repeat $p.Offset | mapf "0x%X" | strJoin ", " -}}:
|
||||||
var res = &{{camelCase $p.Name true}}{}
|
var res = &{{camelCase $p.Name true}}{}
|
||||||
err := json.Unmarshal(jp.Data, res)
|
err := json.Unmarshal(raw, res)
|
||||||
res.Idx = jp.Id - {{ $p.Id | printf "0x%X" }}
|
res.Idx = id - {{ $p.Id | printf "0x%X" }}
|
||||||
return res, err
|
return res, err
|
||||||
{{- else }}
|
{{- else }}
|
||||||
case {{ $p.Id | printf "0x%X" }}:
|
case {{ $p.Id | printf "0x%X" }}:
|
||||||
var res = &{{camelCase $p.Name true}}{}
|
var res = &{{camelCase $p.Name true}}{}
|
||||||
err := json.Unmarshal(jp.Data, res)
|
err := json.Unmarshal(raw, res)
|
||||||
return res, err
|
return res, err
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("aaa")
|
return nil, errors.New("failed to match id")
|
||||||
}
|
}
|
||||||
|
|
||||||
{{range .Packets -}}
|
{{range .Packets -}}
|
||||||
|
|
|
@ -23,17 +23,14 @@ func TestMarshalUnmarshal{{$structName}}(t *testing.T) {
|
||||||
func TestJSON{{$structName}}(t *testing.T) {
|
func TestJSON{{$structName}}(t *testing.T) {
|
||||||
|
|
||||||
v := &{{$structName}}{}
|
v := &{{$structName}}{}
|
||||||
jp, err := ToJson(v)
|
|
||||||
|
rawData, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rawData, err := json.Marshal(jp)
|
id, _ := v.CANId()
|
||||||
if err != nil {
|
p, err := FromJson(id, rawData)
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := FromJson(rawData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
package gotelem
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kschamplin/gotelem/skylab"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CanWriter
|
|
||||||
type CanWriter struct {
|
|
||||||
output *os.File
|
|
||||||
cd CANDumpEntry
|
|
||||||
jsonBuf []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// send writes the frame to the file.
|
|
||||||
func (cw *CanWriter) Send(f *Frame) (err error) {
|
|
||||||
cw.cd.Timestamp = float64(time.Now().Unix())
|
|
||||||
|
|
||||||
cw.cd.Id = uint64(f.Id)
|
|
||||||
|
|
||||||
cw.cd.Data, err = skylab.FromCanFrame(f.Id, f.Data)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
out, err := json.Marshal(cw.cd)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Fprintln(cw.output, string(out))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cw *CanWriter) Close() error {
|
|
||||||
return cw.output.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func OpenCanWriter(name string) (*CanWriter, error) {
|
|
||||||
f, err := os.Create(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cw := &CanWriter{
|
|
||||||
output: f,
|
|
||||||
}
|
|
||||||
return cw, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CANDumpEntry struct {
|
|
||||||
Timestamp float64 `json:"ts"`
|
|
||||||
Id uint64 `json:"id"`
|
|
||||||
Data skylab.Packet `json:"data"`
|
|
||||||
}
|
|
Loading…
Reference in a new issue