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
|
|
|
}
|