dash7_alp/wizzilab/v5_3/dash7/
interface_tx_status.rs1#[cfg(test)]
2use crate::test_tools::test_item;
3use crate::{
4 codec::{Codec, StdError, WithOffset, WithSize},
5 wizzilab::v5_3::dash7::{
6 stack_error::InterfaceFinalStatusCode, Address, AddressType, NlsMethod,
7 },
8};
9#[cfg(test)]
10use hex_literal::hex;
11use std::convert::TryFrom;
12
13#[derive(Clone, Debug, PartialEq)]
15pub struct InterfaceTxStatus {
16 pub ch_header: u8,
18 pub ch_idx: u16,
20 pub eirp: i8,
22 pub err: InterfaceFinalStatusCode,
24 pub rfu_0: u8,
27 pub rfu_1: u8,
28 pub rfu_2: u8,
29 pub lts: u32,
31 pub access_class: u8,
33 pub nls_method: NlsMethod,
35 pub address: Address,
37}
38impl std::fmt::Display for InterfaceTxStatus {
39 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
40 write!(
41 f,
42 "ch({};{}),eirp={},err={},lts={},address={}",
43 self.ch_header, self.ch_idx, self.eirp, self.err, self.lts, self.address
44 )
45 }
46}
47#[derive(Debug, Copy, Clone, PartialEq)]
48pub enum InterfaceTxStatusDecodingError {
49 MissingBytes(usize),
50 UnknownStatusCode(u8),
51}
52impl From<StdError> for InterfaceTxStatusDecodingError {
53 fn from(e: StdError) -> Self {
54 match e {
55 StdError::MissingBytes(n) => Self::MissingBytes(n),
56 }
57 }
58}
59impl Codec for InterfaceTxStatus {
60 type Error = InterfaceTxStatusDecodingError;
61 fn encoded_size(&self) -> usize {
62 1 + 2 + 1 + 1 + 1 + 1 + 1 + 4 + 1 + 1 + self.address.encoded_size()
63 }
64
65 unsafe fn encode_in(&self, out: &mut [u8]) -> usize {
66 let mut i = 0;
67 out[i] = self.ch_header;
68 i += 1;
69 out[i..(i + 2)].clone_from_slice(&self.ch_idx.to_be_bytes());
70 i += 2;
71 out[i] = self.eirp as u8;
72 i += 1;
73 out[i] = self.err as u8;
74 i += 1;
75 out[i] = self.rfu_0;
76 i += 1;
77 out[i] = self.rfu_1;
78 i += 1;
79 out[i] = self.rfu_2;
80 i += 1;
81 out[i..(i + 4)].clone_from_slice(&self.lts.to_le_bytes());
82 i += 4;
83 out[i] = ((self.address.id_type() as u8) << 4) | (self.nls_method as u8);
84 i += 1;
85 out[i] = self.access_class;
86 i += 1;
87 i += self.address.encode_in(&mut out[i..]);
88 i
89 }
90 fn decode(out: &[u8]) -> Result<WithSize<Self>, WithOffset<Self::Error>> {
91 if out.len() < 15 {
92 return Err(WithOffset::new_head(Self::Error::MissingBytes(
93 15 - out.len(),
94 )));
95 }
96
97 let ch_header = out[0];
98 let ch_idx = ((out[1] as u16) << 8) + out[2] as u16;
99 let eirp = out[3] as i8;
100 let err = InterfaceFinalStatusCode::try_from(out[4])
101 .map_err(|e| WithOffset::new(4, Self::Error::UnknownStatusCode(e)))?;
102 let rfu_0 = out[5];
103 let rfu_1 = out[6];
104 let rfu_2 = out[7];
105 let lts = u32::from_le_bytes([out[8], out[9], out[10], out[11]]);
106 let address_type = AddressType::from((out[12] & 0x30) >> 4);
107 let nls_method = unsafe { NlsMethod::from(out[12] & 0x07) };
108 let access_class = out[13];
109 let WithSize {
110 size: address_size,
111 value: address,
112 } = Address::parse(address_type, &out[14..]).map_err(|e| {
113 let WithOffset { offset, value } = e;
114 WithOffset {
115 offset: offset + 5,
116 value: value.into(),
117 }
118 })?;
119 let size = 14 + address_size;
120 Ok(WithSize {
121 value: Self {
122 ch_header,
123 ch_idx,
124 eirp,
125 err,
126 rfu_0,
127 rfu_1,
128 rfu_2,
129 lts,
130 access_class,
131 nls_method,
132 address,
133 },
134 size,
135 })
136 }
137}
138#[test]
139fn test_interface_tx_status() {
140 test_item(
141 InterfaceTxStatus {
142 ch_header: 1,
143 ch_idx: 0x0123,
144 eirp: 2,
145 err: InterfaceFinalStatusCode::Busy,
146 rfu_0: 4,
147 rfu_1: 5,
148 rfu_2: 6,
149 lts: 0x0708_0000,
150 access_class: 0xFF,
151 nls_method: NlsMethod::AesCcm64,
152 address: Address::Vid([0x00, 0x11]),
153 },
154 &hex!("01 0123 02 FF 04 05 06 0000 0807 36 FF 0011 000000000000"),
155 )
156}