move tihngs

This commit is contained in:
saji 2023-04-20 15:26:29 -05:00
parent ba288f2959
commit c7cda9db7a
16 changed files with 1408 additions and 74 deletions

View file

@ -1,11 +1,69 @@
package cmd package cmd
import ( import (
"fmt"
"net"
"time"
"github.com/kschamplin/gotelem/internal/gotelem"
"github.com/tinylib/msgp/msgp"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
) )
const xbeeCategory = "XBee settings"
var serveCmd = &cli.Command{ var serveCmd = &cli.Command{
Name: "serve", Name: "serve",
Aliases: []string{"server", "s"}, Aliases: []string{"server", "s"},
Usage: "Start a telemetry server", Usage: "Start a telemetry server",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "xbee", Aliases: []string{"x"}, Usage: "Find and connect to an XBee"},
},
Action: func(ctx *cli.Context) error {
serve()
return nil
},
}
type session struct {
conn net.Conn
send chan gotelem.Body
recv chan gotelem.Body
quit chan bool
}
func serve() {
ln, err := net.Listen("tcp", ":8082")
if err != nil {
fmt.Printf("Error listening: %v\n", err)
}
fmt.Printf("Listening on :8082\n")
for {
conn, err := ln.Accept()
if err != nil {
fmt.Printf("error accepting: %v\n", err)
}
go handleCon(conn)
}
}
func handleCon(conn net.Conn) {
// reader := msgp.NewReader(conn)
writer := msgp.NewWriter(conn)
for {
// data := telemnet.StatusBody{
// BatteryPct: 1.2,
// ErrCode: 0,
// }
// data.EncodeMsg(writer)
data := gotelem.StatusBody{
BatteryPct: 1.2,
ErrCode: 0,
}
data.EncodeMsg(writer)
writer.Flush()
time.Sleep(1 * time.Second)
}
} }

4
go.mod
View file

@ -9,6 +9,10 @@ require (
require ( require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/philhofer/fwd v1.1.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/tools v0.8.0 // indirect
) )

38
go.sum
View file

@ -1,10 +1,48 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw= github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw=
github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View file

@ -29,3 +29,8 @@ type CanSink interface {
type CanSource interface { type CanSource interface {
Recv() (*Frame, error) Recv() (*Frame, error)
} }
type CanTransciever interface {
CanSink
CanSource
}

View file

@ -0,0 +1,26 @@
// Code generated by "stringer -output=frame_kind.go -type Kind"; DO NOT EDIT.
package can
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[SFF-0]
_ = x[EFF-1]
_ = x[RTR-2]
_ = x[ERR-3]
}
const _Kind_name = "SFFEFFRTRERR"
var _Kind_index = [...]uint8{0, 3, 6, 9, 12}
func (i Kind) String() string {
if i >= Kind(len(_Kind_index)-1) {
return "Kind(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Kind_name[_Kind_index[i]:_Kind_index[i+1]]
}

View file

@ -0,0 +1,21 @@
package db
import (
"database/sql"
"github.com/kschamplin/gotelem/internal/can"
)
// this file implements a CAN adapter for the sqlite db.
type CanDB struct {
Db *sql.DB
}
func (cdb *CanDB) Send(_ *can.Frame) error {
panic("not implemented") // TODO: Implement
}
func (cdb *CanDB) Recv() (*can.Frame, error) {
panic("not implemented") // TODO: Implement
}

View file

@ -0,0 +1,60 @@
package gotelem
import (
"github.com/tinylib/msgp/msgp"
)
// a body is a thing that can get a type, which we put in the header.
// we use the header to store metadata too
type Body interface {
GetType() string
msgp.Marshaler
}
//go:generate msgp
type Data struct {
Header map[string]string `msg:"header"`
Body msgp.Raw `msg:"body"`
}
type CanBody struct {
Id uint32 `msg:"id"`
Payload []byte `msg:"data"`
Source string `msg:"src"`
}
func (*CanBody) GetType() string {
return "canp"
}
// A status contains information about the running application.
// mainly internal battery percentage.
type StatusBody struct {
BatteryPct float32 `msg:"batt"`
ErrCode int16 `msg:"err"` // 0 is good.
}
func (*StatusBody) GetType() string {
return "status"
}
// takes anything that has a GetType() string method and packs it up.
func NewData(body Body) (*Data, error) {
data := &Data{}
data.Header["type"] = body.GetType()
// add other metadata here.
data.Header["ver"] = "0.0.1"
data.Header["test"] = "mesg"
rawBody, err := body.MarshalMsg(nil)
if err != nil {
return nil, err
}
data.Body = rawBody
return data, nil
}

View file

@ -0,0 +1,491 @@
package gotelem
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
import (
"github.com/tinylib/msgp/msgp"
)
// DecodeMsg implements msgp.Decodable
func (z *CanBody) 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.Payload, err = dc.ReadBytes(z.Payload)
if err != nil {
err = msgp.WrapError(err, "Payload")
return
}
case "src":
z.Source, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Source")
return
}
default:
err = dc.Skip()
if err != nil {
err = msgp.WrapError(err)
return
}
}
}
return
}
// EncodeMsg implements msgp.Encodable
func (z *CanBody) EncodeMsg(en *msgp.Writer) (err error) {
// map header, size 3
// write "id"
err = en.Append(0x83, 0xa2, 0x69, 0x64)
if err != nil {
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.Payload)
if err != nil {
err = msgp.WrapError(err, "Payload")
return
}
// write "src"
err = en.Append(0xa3, 0x73, 0x72, 0x63)
if err != nil {
return
}
err = en.WriteString(z.Source)
if err != nil {
err = msgp.WrapError(err, "Source")
return
}
return
}
// MarshalMsg implements msgp.Marshaler
func (z *CanBody) MarshalMsg(b []byte) (o []byte, err error) {
o = msgp.Require(b, z.Msgsize())
// map header, size 3
// string "id"
o = append(o, 0x83, 0xa2, 0x69, 0x64)
o = msgp.AppendUint32(o, z.Id)
// string "data"
o = append(o, 0xa4, 0x64, 0x61, 0x74, 0x61)
o = msgp.AppendBytes(o, z.Payload)
// string "src"
o = append(o, 0xa3, 0x73, 0x72, 0x63)
o = msgp.AppendString(o, z.Source)
return
}
// UnmarshalMsg implements msgp.Unmarshaler
func (z *CanBody) 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 "data":
z.Payload, bts, err = msgp.ReadBytesBytes(bts, z.Payload)
if err != nil {
err = msgp.WrapError(err, "Payload")
return
}
case "src":
z.Source, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Source")
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 *CanBody) Msgsize() (s int) {
s = 1 + 3 + msgp.Uint32Size + 5 + msgp.BytesPrefixSize + len(z.Payload) + 4 + msgp.StringPrefixSize + len(z.Source)
return
}
// DecodeMsg implements msgp.Decodable
func (z *Data) 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 "header":
var zb0002 uint32
zb0002, err = dc.ReadMapHeader()
if err != nil {
err = msgp.WrapError(err, "Header")
return
}
if z.Header == nil {
z.Header = make(map[string]string, zb0002)
} else if len(z.Header) > 0 {
for key := range z.Header {
delete(z.Header, key)
}
}
for zb0002 > 0 {
zb0002--
var za0001 string
var za0002 string
za0001, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Header")
return
}
za0002, err = dc.ReadString()
if err != nil {
err = msgp.WrapError(err, "Header", za0001)
return
}
z.Header[za0001] = za0002
}
case "body":
err = z.Body.DecodeMsg(dc)
if err != nil {
err = msgp.WrapError(err, "Body")
return
}
default:
err = dc.Skip()
if err != nil {
err = msgp.WrapError(err)
return
}
}
}
return
}
// EncodeMsg implements msgp.Encodable
func (z *Data) EncodeMsg(en *msgp.Writer) (err error) {
// map header, size 2
// write "header"
err = en.Append(0x82, 0xa6, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72)
if err != nil {
return
}
err = en.WriteMapHeader(uint32(len(z.Header)))
if err != nil {
err = msgp.WrapError(err, "Header")
return
}
for za0001, za0002 := range z.Header {
err = en.WriteString(za0001)
if err != nil {
err = msgp.WrapError(err, "Header")
return
}
err = en.WriteString(za0002)
if err != nil {
err = msgp.WrapError(err, "Header", za0001)
return
}
}
// write "body"
err = en.Append(0xa4, 0x62, 0x6f, 0x64, 0x79)
if err != nil {
return
}
err = z.Body.EncodeMsg(en)
if err != nil {
err = msgp.WrapError(err, "Body")
return
}
return
}
// MarshalMsg implements msgp.Marshaler
func (z *Data) MarshalMsg(b []byte) (o []byte, err error) {
o = msgp.Require(b, z.Msgsize())
// map header, size 2
// string "header"
o = append(o, 0x82, 0xa6, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72)
o = msgp.AppendMapHeader(o, uint32(len(z.Header)))
for za0001, za0002 := range z.Header {
o = msgp.AppendString(o, za0001)
o = msgp.AppendString(o, za0002)
}
// string "body"
o = append(o, 0xa4, 0x62, 0x6f, 0x64, 0x79)
o, err = z.Body.MarshalMsg(o)
if err != nil {
err = msgp.WrapError(err, "Body")
return
}
return
}
// UnmarshalMsg implements msgp.Unmarshaler
func (z *Data) 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 "header":
var zb0002 uint32
zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Header")
return
}
if z.Header == nil {
z.Header = make(map[string]string, zb0002)
} else if len(z.Header) > 0 {
for key := range z.Header {
delete(z.Header, key)
}
}
for zb0002 > 0 {
var za0001 string
var za0002 string
zb0002--
za0001, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Header")
return
}
za0002, bts, err = msgp.ReadStringBytes(bts)
if err != nil {
err = msgp.WrapError(err, "Header", za0001)
return
}
z.Header[za0001] = za0002
}
case "body":
bts, err = z.Body.UnmarshalMsg(bts)
if err != nil {
err = msgp.WrapError(err, "Body")
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 *Data) Msgsize() (s int) {
s = 1 + 7 + msgp.MapHeaderSize
if z.Header != nil {
for za0001, za0002 := range z.Header {
_ = za0002
s += msgp.StringPrefixSize + len(za0001) + msgp.StringPrefixSize + len(za0002)
}
}
s += 5 + z.Body.Msgsize()
return
}
// DecodeMsg implements msgp.Decodable
func (z *StatusBody) 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 "batt":
z.BatteryPct, err = dc.ReadFloat32()
if err != nil {
err = msgp.WrapError(err, "BatteryPct")
return
}
case "err":
z.ErrCode, err = dc.ReadInt16()
if err != nil {
err = msgp.WrapError(err, "ErrCode")
return
}
default:
err = dc.Skip()
if err != nil {
err = msgp.WrapError(err)
return
}
}
}
return
}
// EncodeMsg implements msgp.Encodable
func (z StatusBody) EncodeMsg(en *msgp.Writer) (err error) {
// map header, size 2
// write "batt"
err = en.Append(0x82, 0xa4, 0x62, 0x61, 0x74, 0x74)
if err != nil {
return
}
err = en.WriteFloat32(z.BatteryPct)
if err != nil {
err = msgp.WrapError(err, "BatteryPct")
return
}
// write "err"
err = en.Append(0xa3, 0x65, 0x72, 0x72)
if err != nil {
return
}
err = en.WriteInt16(z.ErrCode)
if err != nil {
err = msgp.WrapError(err, "ErrCode")
return
}
return
}
// MarshalMsg implements msgp.Marshaler
func (z StatusBody) MarshalMsg(b []byte) (o []byte, err error) {
o = msgp.Require(b, z.Msgsize())
// map header, size 2
// string "batt"
o = append(o, 0x82, 0xa4, 0x62, 0x61, 0x74, 0x74)
o = msgp.AppendFloat32(o, z.BatteryPct)
// string "err"
o = append(o, 0xa3, 0x65, 0x72, 0x72)
o = msgp.AppendInt16(o, z.ErrCode)
return
}
// UnmarshalMsg implements msgp.Unmarshaler
func (z *StatusBody) 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 "batt":
z.BatteryPct, bts, err = msgp.ReadFloat32Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "BatteryPct")
return
}
case "err":
z.ErrCode, bts, err = msgp.ReadInt16Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "ErrCode")
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 StatusBody) Msgsize() (s int) {
s = 1 + 5 + msgp.Float32Size + 4 + msgp.Int16Size
return
}

View file

@ -0,0 +1,349 @@
package gotelem
// Code generated by github.com/tinylib/msgp DO NOT EDIT.
import (
"bytes"
"testing"
"github.com/tinylib/msgp/msgp"
)
func TestMarshalUnmarshalCanBody(t *testing.T) {
v := CanBody{}
bts, err := v.MarshalMsg(nil)
if err != nil {
t.Fatal(err)
}
left, err := v.UnmarshalMsg(bts)
if err != nil {
t.Fatal(err)
}
if len(left) > 0 {
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
}
left, err = msgp.Skip(bts)
if err != nil {
t.Fatal(err)
}
if len(left) > 0 {
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
}
}
func BenchmarkMarshalMsgCanBody(b *testing.B) {
v := CanBody{}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
v.MarshalMsg(nil)
}
}
func BenchmarkAppendMsgCanBody(b *testing.B) {
v := CanBody{}
bts := make([]byte, 0, v.Msgsize())
bts, _ = v.MarshalMsg(bts[0:0])
b.SetBytes(int64(len(bts)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
bts, _ = v.MarshalMsg(bts[0:0])
}
}
func BenchmarkUnmarshalCanBody(b *testing.B) {
v := CanBody{}
bts, _ := v.MarshalMsg(nil)
b.ReportAllocs()
b.SetBytes(int64(len(bts)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := v.UnmarshalMsg(bts)
if err != nil {
b.Fatal(err)
}
}
}
func TestEncodeDecodeCanBody(t *testing.T) {
v := CanBody{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
m := v.Msgsize()
if buf.Len() > m {
t.Log("WARNING: TestEncodeDecodeCanBody Msgsize() is inaccurate")
}
vn := CanBody{}
err := msgp.Decode(&buf, &vn)
if err != nil {
t.Error(err)
}
buf.Reset()
msgp.Encode(&buf, &v)
err = msgp.NewReader(&buf).Skip()
if err != nil {
t.Error(err)
}
}
func BenchmarkEncodeCanBody(b *testing.B) {
v := CanBody{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
b.SetBytes(int64(buf.Len()))
en := msgp.NewWriter(msgp.Nowhere)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
v.EncodeMsg(en)
}
en.Flush()
}
func BenchmarkDecodeCanBody(b *testing.B) {
v := CanBody{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
b.SetBytes(int64(buf.Len()))
rd := msgp.NewEndlessReader(buf.Bytes(), b)
dc := msgp.NewReader(rd)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := v.DecodeMsg(dc)
if err != nil {
b.Fatal(err)
}
}
}
func TestMarshalUnmarshalData(t *testing.T) {
v := Data{}
bts, err := v.MarshalMsg(nil)
if err != nil {
t.Fatal(err)
}
left, err := v.UnmarshalMsg(bts)
if err != nil {
t.Fatal(err)
}
if len(left) > 0 {
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
}
left, err = msgp.Skip(bts)
if err != nil {
t.Fatal(err)
}
if len(left) > 0 {
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
}
}
func BenchmarkMarshalMsgData(b *testing.B) {
v := Data{}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
v.MarshalMsg(nil)
}
}
func BenchmarkAppendMsgData(b *testing.B) {
v := Data{}
bts := make([]byte, 0, v.Msgsize())
bts, _ = v.MarshalMsg(bts[0:0])
b.SetBytes(int64(len(bts)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
bts, _ = v.MarshalMsg(bts[0:0])
}
}
func BenchmarkUnmarshalData(b *testing.B) {
v := Data{}
bts, _ := v.MarshalMsg(nil)
b.ReportAllocs()
b.SetBytes(int64(len(bts)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := v.UnmarshalMsg(bts)
if err != nil {
b.Fatal(err)
}
}
}
func TestEncodeDecodeData(t *testing.T) {
v := Data{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
m := v.Msgsize()
if buf.Len() > m {
t.Log("WARNING: TestEncodeDecodeData Msgsize() is inaccurate")
}
vn := Data{}
err := msgp.Decode(&buf, &vn)
if err != nil {
t.Error(err)
}
buf.Reset()
msgp.Encode(&buf, &v)
err = msgp.NewReader(&buf).Skip()
if err != nil {
t.Error(err)
}
}
func BenchmarkEncodeData(b *testing.B) {
v := Data{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
b.SetBytes(int64(buf.Len()))
en := msgp.NewWriter(msgp.Nowhere)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
v.EncodeMsg(en)
}
en.Flush()
}
func BenchmarkDecodeData(b *testing.B) {
v := Data{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
b.SetBytes(int64(buf.Len()))
rd := msgp.NewEndlessReader(buf.Bytes(), b)
dc := msgp.NewReader(rd)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := v.DecodeMsg(dc)
if err != nil {
b.Fatal(err)
}
}
}
func TestMarshalUnmarshalStatusBody(t *testing.T) {
v := StatusBody{}
bts, err := v.MarshalMsg(nil)
if err != nil {
t.Fatal(err)
}
left, err := v.UnmarshalMsg(bts)
if err != nil {
t.Fatal(err)
}
if len(left) > 0 {
t.Errorf("%d bytes left over after UnmarshalMsg(): %q", len(left), left)
}
left, err = msgp.Skip(bts)
if err != nil {
t.Fatal(err)
}
if len(left) > 0 {
t.Errorf("%d bytes left over after Skip(): %q", len(left), left)
}
}
func BenchmarkMarshalMsgStatusBody(b *testing.B) {
v := StatusBody{}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
v.MarshalMsg(nil)
}
}
func BenchmarkAppendMsgStatusBody(b *testing.B) {
v := StatusBody{}
bts := make([]byte, 0, v.Msgsize())
bts, _ = v.MarshalMsg(bts[0:0])
b.SetBytes(int64(len(bts)))
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
bts, _ = v.MarshalMsg(bts[0:0])
}
}
func BenchmarkUnmarshalStatusBody(b *testing.B) {
v := StatusBody{}
bts, _ := v.MarshalMsg(nil)
b.ReportAllocs()
b.SetBytes(int64(len(bts)))
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := v.UnmarshalMsg(bts)
if err != nil {
b.Fatal(err)
}
}
}
func TestEncodeDecodeStatusBody(t *testing.T) {
v := StatusBody{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
m := v.Msgsize()
if buf.Len() > m {
t.Log("WARNING: TestEncodeDecodeStatusBody Msgsize() is inaccurate")
}
vn := StatusBody{}
err := msgp.Decode(&buf, &vn)
if err != nil {
t.Error(err)
}
buf.Reset()
msgp.Encode(&buf, &v)
err = msgp.NewReader(&buf).Skip()
if err != nil {
t.Error(err)
}
}
func BenchmarkEncodeStatusBody(b *testing.B) {
v := StatusBody{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
b.SetBytes(int64(buf.Len()))
en := msgp.NewWriter(msgp.Nowhere)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
v.EncodeMsg(en)
}
en.Flush()
}
func BenchmarkDecodeStatusBody(b *testing.B) {
v := StatusBody{}
var buf bytes.Buffer
msgp.Encode(&buf, &v)
b.SetBytes(int64(buf.Len()))
rd := msgp.NewEndlessReader(buf.Bytes(), b)
dc := msgp.NewReader(rd)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
err := v.DecodeMsg(dc)
if err != nil {
b.Fatal(err)
}
}
}

View file

@ -6,7 +6,7 @@ import (
"fmt" "fmt"
"net" "net"
"github.com/kschamplin/gotelem/can" "github.com/kschamplin/gotelem/internal/can"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )

View file

@ -5,7 +5,7 @@ import (
"net" "net"
"testing" "testing"
"github.com/kschamplin/gotelem/can" "github.com/kschamplin/gotelem/internal/can"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )

235
internal/xbee/api_frame.go Normal file
View file

@ -0,0 +1,235 @@
package xbee
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
// the frames have an outer shell - we will make a function that takes
// an inner frame element and wraps it in the appropriate headers.
// first, we should make it take the frame directly, so we make an interface
// that represents "framable" things. note that bytes.Buffer also fulfils this.
type Frameable interface {
// returns the API identifier for this frame.
GetId() byte
// encodes this frame correctly.
Bytes() ([]byte, error)
}
// now we can describe our function that takes a framable and contains it + calculates checksums.
func calculateChecksum(data []byte) byte {
var sum byte
for _, v := range data {
sum += v
}
return 0xFF - sum
}
func WriteFrame(w io.Writer, cmd Frameable) (n int, err error) {
frame_data, err := cmd.Bytes()
if err != nil {
return
}
frame := make([]byte, len(frame_data)+4)
frame[0] = 0x7E
binary.BigEndian.PutUint16(frame[1:], uint16(len(frame_data)))
copy(frame[3:], frame_data)
chk := calculateChecksum(frame_data)
frame[len(frame)-1] = chk
return w.Write(frame)
}
func makeXbeeApiFrame(cmd Frameable) ([]byte, error) {
dataBuf, _ := cmd.Bytes()
frameBuf := make([]byte, len(dataBuf)+4)
// move data and construct the frame
frameBuf[0] = 0x7E // start delimiter
// length
// todo: check endiannes (0x7e, msb lsb)
binary.BigEndian.PutUint16(frameBuf[1:3], uint16(len(dataBuf)))
copy(frameBuf[3:], dataBuf)
chksum := calculateChecksum(dataBuf)
frameBuf[len(frameBuf)-1] = chksum
return frameBuf, nil
}
// now we can describe frames in other files that implement Frameable.
// the remaining challenge is reception and actual API frames.
// xbee uses the first byte of the "frame data" as the API identifier or command.
//go:generate stringer -output=api_frame_cmd.go -type xbeeCmd
type XBeeCmd byte
const (
// commands sent to the xbee s3b
ATCmd XBeeCmd = 0x08 // AT Command
ATCmdQueue XBeeCmd = 0x09 // AT Command - Queue Parameter Value
TxReq XBeeCmd = 0x10 // TX Request
TxReqExpl XBeeCmd = 0x11 // Explicit TX Request
RemoteCmdReq XBeeCmd = 0x17 // Remote Command Request
// commands recieved from the xbee
ATCmdResponse XBeeCmd = 0x88 // AT Command Response
ModemStatus XBeeCmd = 0x8A // Modem Status
TxStatus XBeeCmd = 0x8B // Transmit Status
RouteInfoPkt XBeeCmd = 0x8D // Route information packet
AddrUpdate XBeeCmd = 0x8E // Aggregate Addressing Update
RxPkt XBeeCmd = 0x90 // RX Indicator (AO=0)
RxPktExpl XBeeCmd = 0x91 // Explicit RX Indicator (AO=1)
IOSample XBeeCmd = 0x92 // Data Sample RX Indicator
NodeId XBeeCmd = 0x95 // Note Identification Indicator
RemoteCmdResp XBeeCmd = 0x97 // Remote Command Response
)
// AT commands are hard, so let's write out all the major ones here
type ATCmdFrame struct {
Id byte
Cmd string
Param []byte
Queued bool
}
// implement the frame stuff for us.
func (atFrame *ATCmdFrame) Bytes() ([]byte, error) {
buf := new(bytes.Buffer)
if atFrame.Queued {
// queued (batched) at comamnds have different Frame type
buf.WriteByte(byte(ATCmdQueue))
} else {
// normal frame type
buf.WriteByte(byte(ATCmd))
}
buf.WriteByte(atFrame.Id)
// write cmd, if it's the right length.
if cmdLen := len(atFrame.Cmd); cmdLen != 2 {
return nil, fmt.Errorf("AT command incorrect length: %d", cmdLen)
}
buf.Write([]byte(atFrame.Cmd))
// write param.
buf.Write(atFrame.Param)
return buf.Bytes(), nil
}
// transmissions to this address are instead broadcast
const BroadcastAddr = 0xFFFF
type TxFrame struct {
Id byte
Destination uint64
BCastRadius uint8
Options uint8
Payload []byte
}
func (txFrame *TxFrame) Bytes() ([]byte, error) {
buf := new(bytes.Buffer)
buf.WriteByte(byte(TxReq))
buf.WriteByte(txFrame.Id)
a := make([]byte, 8)
binary.LittleEndian.PutUint64(a, txFrame.Destination)
buf.Write(a)
// write the reserved part.
buf.Write([]byte{0xFF, 0xFE})
// write the radius
buf.WriteByte(txFrame.BCastRadius)
buf.WriteByte(txFrame.Options)
buf.Write(txFrame.Payload)
return buf.Bytes(), nil
}
type RemoteATCmdReq struct {
ATCmdFrame
Destination uint64
Options uint8
}
func (remoteAT *RemoteATCmdReq) Bytes() ([]byte, error) {
buf := new(bytes.Buffer)
buf.WriteByte(byte(RemoteCmdReq))
buf.WriteByte(remoteAT.Id)
a := make([]byte, 8)
binary.LittleEndian.PutUint64(a, remoteAT.Destination)
buf.Write(a)
// write the reserved part.
buf.Write([]byte{0xFF, 0xFE})
// write options
buf.WriteByte(remoteAT.Options)
// now, write the AT command and the data.
buf.Write([]byte(remoteAT.Cmd))
buf.Write(remoteAT.Param)
return buf.Bytes(), nil
}
// Now we will implement receiving packets from a character stream.
// we first need to make a thing that produces frames from a stream using a scanner.
// this is a split function for bufio.scanner. It makes it easier to handle the FSM
// for extracting data from a stream. For the Xbee, this means that we must
// find the magic start character, (check that it's escaped), read the length,
// and then ensure we have enough length to finish the token, requesting more data
// if we do not.
//
// see https://pkg.go.dev/bufio#SplitFunc for more info
// https://medium.com/golangspec/in-depth-introduction-to-bufio-scanner-in-golang-55483bb689b4
func xbeeFrameSplit(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
// there's no data, request more.
return 0, nil, nil
}
if startIdx := bytes.IndexByte(data, 0x7E); startIdx >= 0 {
// we have a start character. get the length.
// we add 4 since start delimiter (1) + length (2) + checksum (1).
// the length inside the packet represents the frame data only.
var frameLen = binary.BigEndian.Uint16(data[startIdx+1:startIdx+3]) + 4
if len(data[startIdx:]) < int(frameLen) {
// we got the length, but there's not enough data for the frame. we can trim the
// data that came before the start, but not return a token.
return startIdx, nil, nil
}
// there is enough data to pull a frame.
// todo: check checksum here? we can return an error.
return startIdx + int(frameLen), data[startIdx : startIdx+int(frameLen)], nil
}
// we didn't find a start character in our data, so request more. trash everythign given to us
return len(data), nil, nil
}

View file

@ -0,0 +1,119 @@
package xbee
import (
"bytes"
"reflect"
"testing"
)
func Test_xbeeFrameSplit(t *testing.T) {
type args struct {
data []byte
atEOF bool
}
tests := []struct {
name string
args args
wantAdvance int
wantToken []byte
wantErr bool
}{
// TODO: Add test cases.
{
name: "empty data",
args: args{
data: []byte{},
atEOF: false,
},
wantAdvance: 0,
wantToken: nil,
wantErr: false,
},
{
name: "no start delimiter",
args: args{
data: []byte{0x11, 0x22, 0x23, 0x44, 0x44, 0x77, 0x33},
atEOF: false,
},
wantAdvance: 7,
wantToken: nil,
wantErr: false,
},
{
name: "incomplete packet",
args: args{
data: []byte{0x7E, 0x00, 0x02, 0x23, 0x11},
atEOF: false,
},
wantAdvance: 0,
wantToken: nil,
wantErr: false,
},
{
name: "valid packet",
args: args{
data: []byte{0x7E, 0x00, 0x02, 0x23, 0x11, 0xCB},
atEOF: false,
},
wantAdvance: 6,
wantToken: []byte{0x7E, 0x00, 0x02, 0x23, 0x11, 0xCB},
wantErr: false,
},
{
name: "valid packet w/ padding",
args: args{
data: []byte{0x00, 0x7E, 0x00, 0x02, 0x23, 0x11, 0xCB, 0x00},
atEOF: false,
},
wantAdvance: 7,
wantToken: []byte{0x7E, 0x00, 0x02, 0x23, 0x11, 0xCB},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotAdvance, gotToken, err := xbeeFrameSplit(tt.args.data, tt.args.atEOF)
if (err != nil) != tt.wantErr {
t.Errorf("xbeeFrameSplit() error = %v, wantErr %v", err, tt.wantErr)
return
}
if gotAdvance != tt.wantAdvance {
t.Errorf("xbeeFrameSplit() gotAdvance = %v, want %v", gotAdvance, tt.wantAdvance)
}
if !reflect.DeepEqual(gotToken, tt.wantToken) {
t.Errorf("xbeeFrameSplit() gotToken = %v, want %v", gotToken, tt.wantToken)
}
})
}
}
func TestWriteFrame(t *testing.T) {
type args struct {
cmd Frameable
}
tests := []struct {
name string
args args
wantN int
wantW string
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
w := &bytes.Buffer{}
gotN, err := WriteFrame(w, tt.args.cmd)
if (err != nil) != tt.wantErr {
t.Errorf("WriteFrame() error = %v, wantErr %v", err, tt.wantErr)
return
}
if gotN != tt.wantN {
t.Errorf("WriteFrame() = %v, want %v", gotN, tt.wantN)
}
if gotW := w.String(); gotW != tt.wantW {
t.Errorf("WriteFrame() = %v, want %v", gotW, tt.wantW)
}
})
}
}

View file

@ -1,71 +0,0 @@
package xbee
import "encoding/binary"
// the frames have an outer shell - we will make a function that takes
// an inner frame element and wraps it in the appropriate headers.
// first, we should make it take the frame directly, so we make an interface
// that represents "framable" things. note that bytes.Buffer also fulfils this.
type Frameable interface {
Bytes() []byte
}
// now we can describe our function that takes a framable and contains it + calculates checksums.
func calculateChecksum(data []byte) byte {
var sum byte
for _, v := range data {
sum += v
}
return 0xFF - sum
}
func makeXbeeApiFrame(cmd Frameable) ([]byte, error) {
dataBuf := cmd.Bytes()
frameBuf := make([]byte, len(dataBuf)+4)
// move data and construct the frame
frameBuf[0] = 0x7E // start delimiter
// length
// todo: check endiannes (0x7e, msb lsb)
binary.LittleEndian.PutUint16(frameBuf[1:3], uint16(len(dataBuf)))
copy(frameBuf[3:], dataBuf)
chksum := calculateChecksum(dataBuf)
frameBuf[len(frameBuf)-1] = chksum
return frameBuf, nil
}
// now we can describe frames in other files that implement Frameable. this makes trasmission complete.
// the remaining challenge is reception and actual API frames.
// xbee uses the first byte of the "frame data" as the API identifier or command.
//go:generate stringer -output=api_frame_cmd.go -type xbeeCmd
type xbeeCmd byte
const (
// commands sent to the xbee s3b
ATCmd xbeeCmd = 0x08 // AT Command
ATCmdQueuePVal xbeeCmd = 0x09 // AT Command - Queue Parameter Value
TxReq xbeeCmd = 0x10 // TX Request
TxReqExpl xbeeCmd = 0x11 // Explicit TX Request
RemoteCmdReq xbeeCmd = 0x17 // Remote Command Request
// commands recieved from the xbee
ATCmdResponse xbeeCmd = 0x88 // AT Command Response
ModemStatus xbeeCmd = 0x8A // Modem Status
TxStatus xbeeCmd = 0x8B // Transmit Status
RouteInfoPkt xbeeCmd = 0x8D // Route information packet
AddrUpdate xbeeCmd = 0x8E // Aggregate Addressing Update
RxPkt xbeeCmd = 0x90 // RX Indicator (AO=0)
RxPktExpl xbeeCmd = 0x91 // Explicit RX Indicator (AO=1)
IOSample xbeeCmd = 0x92 // Data Sample RX Indicator
NodeId xbeeCmd = 0x95 // Note Identification Indicator
RemoteCmdResp xbeeCmd = 0x97 // Remote Command Response
)

View file

@ -1 +0,0 @@
package xbee_test