gotelem/internal/xbee/txframe.go

95 lines
2.1 KiB
Go
Raw Normal View History

2023-04-25 21:29:49 +00:00
package xbee
import (
"bytes"
"encoding/binary"
2023-05-04 19:05:51 +00:00
"errors"
2023-04-29 15:58:56 +00:00
"fmt"
2023-04-25 21:29:49 +00:00
)
2023-04-29 15:58:56 +00:00
2023-04-25 21:29:49 +00:00
// transmissions to this address are instead broadcast
const BroadcastAddr = 0xFFFF
type TxFrame struct {
Id byte
Destination uint64
BCastRadius uint8
Options uint8
Payload []byte
}
2023-04-29 15:58:56 +00:00
func (txFrame *TxFrame) Bytes() []byte {
2023-04-25 21:29:49 +00:00
buf := new(bytes.Buffer)
2023-04-29 15:58:56 +00:00
buf.WriteByte(byte(TxReqType))
2023-04-25 21:29:49 +00:00
buf.WriteByte(txFrame.Id)
a := make([]byte, 8)
2023-04-29 15:58:56 +00:00
binary.BigEndian.PutUint64(a, txFrame.Destination)
2023-04-25 21:29:49 +00:00
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)
2023-04-29 15:58:56 +00:00
return buf.Bytes()
}
// we also handle transmit status response frames here.
// these are emitted by the xbee when the status of the tx packet is known.
// it has an Id that matches it to the corressponding transmit request.
type TxStatus uint8
//go:generate stringer -output=txStatus.go -type TxStatus
const (
2023-05-04 19:05:51 +00:00
TxStatusSuccess TxStatus = 0x00
TxStatusNoACK TxStatus = 0x01
TxStatusCCAFail TxStatus = 0x02
TxStatusIndirect TxStatus = 0x03
TxStatusACKFail TxStatus = 0x21
TxStatusNoRoute TxStatus = 0x25
TxStatusResourceError TxStatus = 0x31
TxStatusResourceUnavail TxStatus = 0x32
TxStatusPayloadTooLarge TxStatus = 0x74
TxStatusIndirectUnrequested TxStatus = 0x75
2023-04-29 15:58:56 +00:00
)
type TxStatusFrame struct {
2023-05-04 19:05:51 +00:00
Id uint8 // the Frame identifier that this status frame represents.
NRetry uint8
2023-04-29 15:58:56 +00:00
Status TxStatus // the status itself - TxStatus is a stringable.
2023-05-04 19:05:51 +00:00
Routed bool
2023-04-29 15:58:56 +00:00
}
func ParseTxStatusFrame(data []byte) (*TxStatusFrame, error) {
if data[0] != byte(TxStatusType) {
return nil, fmt.Errorf("incorrect frame type for Tx status frame 0x%x", data[0])
}
2023-05-04 19:05:51 +00:00
if len(data) < 7 {
return nil, errors.New("incomplete status frame")
}
2023-04-29 15:58:56 +00:00
status := &TxStatusFrame{
Id: data[1],
2023-05-04 19:05:51 +00:00
Status: TxStatus(data[5]),
NRetry: data[4],
}
if data[6] == 0 {
status.Routed = false
} else {
status.Routed = true
2023-04-29 15:58:56 +00:00
}
return status, nil
2023-04-25 21:29:49 +00:00
}