rustbee/
api.rs

1#![allow(dead_code)]
2//!
3//! XBee API Frame
4//!
5//!
6
7use bytes::{BufMut, BytesMut};
8use downcast_rs::{impl_downcast, DowncastSync};
9use rand::Rng;
10use serialport::prelude::*;
11use std::convert::TryFrom;
12
13pub static BROADCAST_ADDR: u64 = 0xffff;
14
15static DELIM: u8 = 0x7e;
16
17#[derive(Debug)]
18pub enum Error {
19    FrameError(String),
20    PayloadError(String),
21    IOError(std::io::Error),
22    SerialPortError(serialport::Error),
23    DerefError,
24}
25
26impl std::error::Error for Error {}
27
28impl std::fmt::Display for Error {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        match *self {
31            Error::FrameError(ref err) => write!(f, "{}", err),
32            Error::PayloadError(ref err) => write!(f, "{}", err),
33            Error::IOError(ref err) => write!(f, "{}", err),
34            Error::SerialPortError(ref err) => write!(f, "{}", err),
35            Error::DerefError => write!(f, "Unable to deref trait"),
36        }
37    }
38}
39
40impl From<std::io::Error> for Error {
41    fn from(err: std::io::Error) -> Self {
42        Error::IOError(err)
43    }
44}
45
46impl From<serialport::Error> for Error {
47    fn from(err: serialport::Error) -> Self {
48        Error::SerialPortError(err)
49    }
50}
51
52pub type Result<T> = std::result::Result<T, Error>;
53
54#[derive(Debug, PartialEq)]
55pub enum FrameId {
56    TransmitRequest,
57    TransmitStatus,
58    AtCommand,
59    AtCommandResponse,
60    RemoteAtCommand,
61    RemoteAtCommandResponse,
62    Null,
63}
64
65impl FrameId {
66    fn id(&self) -> u8 {
67        match *self {
68            FrameId::TransmitRequest => 0x90,
69            FrameId::TransmitStatus => 0x8b,
70            FrameId::AtCommand => 0x08,
71            FrameId::AtCommandResponse => 0x88,
72            FrameId::RemoteAtCommand => 0x17,
73            FrameId::RemoteAtCommandResponse => 0x97,
74            FrameId::Null => 0xff,
75        }
76    }
77}
78
79pub trait RecieveApiFrame: std::fmt::Debug + DowncastSync {
80    fn recieve(ser: Box<dyn SerialPort>) -> Result<Self>
81    where
82        Self: std::marker::Sized;
83
84    fn id(&self) -> FrameId;
85    fn summary(&self) {
86        println!("{:#x?}", self);
87    }
88    fn payload(&self) -> Result<BytesMut>;
89}
90
91impl_downcast!(sync RecieveApiFrame);
92
93pub trait TransmitApiFrame {
94    fn gen(&self) -> Result<BytesMut>;
95    fn delim(&self) -> u8 {
96        0x7e
97    }
98    fn id(&self) -> FrameId;
99    fn calc_checksum(&self, frame: &[u8]) -> Result<u8> {
100        if frame.len() < 5 {
101            return Err(Error::FrameError(
102                "Frame length does not meet minimum requirements".to_string(),
103            ));
104        }
105
106        let mut checksum: u64 = 0;
107        for (pos, byte) in frame.iter().enumerate() {
108            if pos > 2 {
109                checksum += *byte as u64;
110            }
111        }
112
113        Ok(0xff - (checksum as u8))
114    }
115
116    fn gen_frame_id(&self) -> u8 {
117        let mut rng = rand::thread_rng();
118        let r: u8 = rng.gen();
119        r
120    }
121}
122
123/**
124 * AtCommand Support
125 *
126 *
127 */
128pub struct AtCommand<'a> {
129    pub command: &'a str,
130    pub parameter: &'a Option<&'a [u8]>,
131    pub rcr_len: usize, // the number of carriage returns in the reponse for this command
132}
133
134#[derive(Debug)]
135pub enum AtCommands<'a> {
136    Discover(Option<&'a [u8]>),
137    AtCmd((&'a str, Option<&'a [u8]>)),
138    CmdMode(bool),
139}
140
141impl AtCommands<'_> {
142    pub fn create(&self) -> AtCommand {
143        match *self {
144            AtCommands::CmdMode(ref state) => match state {
145                true => AtCommand {
146                    command: "+++",
147                    parameter: &None,
148                    rcr_len: 1,
149                },
150                false => AtCommand {
151                    command: "CN",
152                    parameter: &None,
153                    rcr_len: 1,
154                },
155            },
156            AtCommands::Discover(ref param) => AtCommand {
157                command: "ND",
158                parameter: param,
159                rcr_len: 10 + 1,
160            },
161            AtCommands::AtCmd((ref cmd, ref param)) => AtCommand {
162                command: cmd,
163                parameter: param,
164                rcr_len: 1,
165            },
166        }
167    }
168}
169/************ Null Recieve **********************/
170
171#[derive(Debug)]
172pub struct NullRecieve;
173impl RecieveApiFrame for NullRecieve {
174    fn id(&self) -> FrameId {
175        FrameId::Null
176    }
177    fn recieve(mut _ser: Box<dyn SerialPort>) -> Result<Self> {
178        Ok(Self)
179    }
180
181    fn summary(&self) {
182        println!("{:#?}", self);
183    }
184
185    fn payload(&self) -> Result<BytesMut> {
186        Err(Error::FrameError(
187            "Uncallabe method for Null Recieve Frame".to_string(),
188        ))
189    }
190}
191
192/************ Transmit Status **********************/
193
194#[derive(Debug)]
195pub struct TransmitStatus {
196    frame_id: u8,
197    transmit_retry_count: u8,
198    deliver_status: u8,
199    discovery_status: u8,
200    payload: Option<BytesMut>,
201}
202
203impl RecieveApiFrame for TransmitStatus {
204    fn id(&self) -> FrameId {
205        FrameId::TransmitStatus
206    }
207
208    fn recieve(mut ser: Box<dyn SerialPort>) -> Result<Self> {
209        // wait for first
210        let mut response: [u8; 11] = [0; 11];
211        ser.read_exact(&mut response)?;
212        Ok(Self {
213            frame_id: response[4],
214            transmit_retry_count: response[7],
215            deliver_status: response[8],
216            discovery_status: response[9],
217            payload: Some(BytesMut::from(&response[..])),
218        })
219    }
220
221    fn payload(&self) -> Result<BytesMut> {
222        match &self.payload {
223            Some(p) => Ok(p.clone()),
224            None => Err(Error::FrameError("Empty payload".to_string())),
225        }
226    }
227}
228
229/********************* Transmit Request ****************************************/
230
231pub enum MessagingMode {
232    PointToPoint,
233    Repeater,
234    DigiMesh,
235}
236
237pub struct TransmitRequestOptions {
238    pub disable_ack: bool,
239    pub disable_route_discovery: bool,
240    pub enable_unicast_nack: bool,
241    pub enable_unicast_trace_route: bool,
242    pub mode: MessagingMode,
243}
244
245impl TransmitRequestOptions {
246    pub fn compile(&self) -> u8 {
247        let mut val: u8 = 0;
248
249        if self.disable_ack == true {
250            val |= 1 << 0;
251        }
252        if self.disable_route_discovery == true {
253            val |= 1 << 1;
254        }
255        if self.enable_unicast_nack == true {
256            val |= 1 << 2;
257        }
258
259        if self.enable_unicast_trace_route == true {
260            val |= 1 << 3;
261        }
262
263        match self.mode {
264            MessagingMode::PointToPoint => (0x1 << 6) | val,
265            MessagingMode::Repeater => (0x2 << 6) | val,
266            MessagingMode::DigiMesh => (0x3 << 6) | val,
267        }
268    }
269}
270
271pub struct TransmitRequestFrame<'a> {
272    pub dest_addr: u64,
273    pub broadcast_radius: u8,
274    pub options: Option<&'a TransmitRequestOptions>,
275    pub payload: &'a [u8],
276}
277
278impl TransmitApiFrame for TransmitRequestFrame<'_> {
279    fn id(&self) -> FrameId {
280        FrameId::TransmitRequest
281    }
282
283    fn gen(&self) -> Result<BytesMut> {
284        let mut packet = BytesMut::new();
285        let mut rng = rand::thread_rng();
286        if self.payload.len() > 65535 - 112 {
287            return Err(Error::PayloadError("Payload exceeds max size".to_string()));
288        }
289
290        let frame_id: u8 = rng.gen();
291
292        packet.put_u8(self.delim());
293        packet.put_u16((self.payload.len() as u16) + (0x0e as u16));
294        packet.put_u8(0x10);
295        packet.put_u8(frame_id);
296        packet.put_u64(self.dest_addr);
297        packet.put_u16(0xfffe);
298        packet.put_u8(self.broadcast_radius);
299
300        match self.options {
301            Some(opts) => packet.put_u8(opts.compile()),
302            None => packet.put_u8(0),
303        }
304        packet.put(self.payload);
305
306        let chksum = self.calc_checksum(&packet[..])?;
307        packet.put_u8(chksum);
308
309        Ok(packet)
310    }
311}
312
313/********************* Remote AtCommand Frame ****************************************/
314pub struct RemoteCommandOptions {
315    pub apply_changes: bool,
316}
317
318pub struct RemoteAtCommandFrame<'a> {
319    pub dest_addr: u64,
320    pub options: &'a RemoteCommandOptions,
321    pub atcmd: &'a str,
322    pub cmd_param: Option<&'a [u8]>,
323}
324
325impl TransmitApiFrame for RemoteAtCommandFrame<'_> {
326    fn id(&self) -> FrameId {
327        FrameId::RemoteAtCommand
328    }
329
330    fn gen(&self) -> Result<BytesMut> {
331        let mut packet = BytesMut::with_capacity(64);
332        let frame_id: u8 = self.gen_frame_id();
333        packet.put_u8(DELIM);
334        packet.put_u16(0); // length; just to initalize
335        packet.put_u8(self.id().id());
336        packet.put_u8(frame_id);
337        packet.put_u64(self.dest_addr);
338        packet.put_u16(0xfffe);
339
340        if self.options.apply_changes == true {
341            packet.put_u8(0x02);
342        } else {
343            packet.put_u8(0);
344        }
345
346        packet.put(self.atcmd.as_bytes());
347
348        if let Some(param) = self.cmd_param {
349            packet.put(&param[..]);
350        }
351
352        // change length here
353        let packet_len = (packet.len() - 3) as u16;
354        packet[1] = (packet_len >> 8) as u8;
355        packet[2] = (packet_len & 0xff) as u8;
356        // checksum now
357        let chksum = self.calc_checksum(&packet[..])?;
358        packet.put_u8(chksum);
359
360        Ok(packet)
361    }
362}
363
364/********************* Remote Command Response Frame ****************************************/
365pub struct RemoteAtCommandResponse {
366    frame_id: u8,
367    pub dest_addr: u64,
368    pub at_command: Vec<u8>,
369    command_status: u8,
370    pub command_data: Option<BytesMut>,
371    payload: Option<BytesMut>,
372}
373
374impl std::fmt::Debug for RemoteAtCommandResponse {
375    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
376        let atcmd = std::str::from_utf8(&self.at_command[..]).ok();
377
378        let cmd_data = match self.command_data {
379            Some(ref data) => format!("{:x?}", &data[..]),
380            None => format!("None"),
381        };
382
383        f.debug_struct("AtCommandResponse")
384            .field("FrameId", &format!("0x{:02x?}", self.frame_id))
385            .field("Dest Addr", &format!("0x{:016x?}", self.dest_addr))
386            .field("AtCommand", &format!("{}", atcmd.unwrap()))
387            .field("Command Status", &format!("{}", self.command_status))
388            .field("Command Data", &cmd_data)
389            .finish()
390    }
391}
392
393impl RecieveApiFrame for RemoteAtCommandResponse {
394    fn id(&self) -> FrameId {
395        FrameId::RemoteAtCommandResponse
396    }
397
398    fn recieve(mut ser: Box<dyn SerialPort>) -> Result<Self> {
399        let mut buffer = BytesMut::with_capacity(1024);
400        let mut mini_buf: [u8; 1] = [0];
401        loop {
402            if let Err(err) = ser.read_exact(&mut mini_buf) {
403                if err.kind() == std::io::ErrorKind::TimedOut {
404                    break;
405                } else {
406                    return Err(Error::IOError(err));
407                }
408            }
409            buffer.put_u8(mini_buf[0]);
410        }
411
412        let mut cmd_data = None;
413        if buffer.len() > 18 {
414            cmd_data = Some(BytesMut::from(&buffer[18..buffer.len() - 1]));
415        }
416        let mut at_cmd: Vec<u8> = Vec::new();
417        at_cmd.push(buffer[15]);
418        at_cmd.push(buffer[16]);
419        let dest_buf = &buffer[5..13];
420        let dest_addr = u64::from_be_bytes(<[u8; 8]>::try_from(dest_buf).unwrap()); // messy but works
421        Ok(Self {
422            frame_id: buffer[4],
423            dest_addr: dest_addr,
424            at_command: at_cmd,
425            command_status: buffer[17],
426            command_data: cmd_data,
427            payload: Some(buffer),
428        })
429    }
430
431    fn payload(&self) -> Result<BytesMut> {
432        match &self.payload {
433            Some(p) => Ok(p.clone()),
434            None => Err(Error::FrameError("Empty payload".to_string())),
435        }
436    }
437}
438/********************* AtCommand Frame ****************************************/
439
440pub struct AtCommandFrame<'a>(pub &'a str, pub Option<&'a [u8]>);
441impl TransmitApiFrame for AtCommandFrame<'_> {
442    fn id(&self) -> FrameId {
443        FrameId::AtCommand
444    }
445
446    fn gen(&self) -> Result<BytesMut> {
447        let mut packet = BytesMut::with_capacity(9);
448        let frame_id: u8 = self.gen_frame_id();
449        packet.put_u8(DELIM);
450        packet.put_u16(0); // length 0 just a placeholder
451        packet.put_u8(self.id().id());
452        packet.put_u8(frame_id);
453        packet.put(self.0.as_bytes());
454        if let Some(param) = self.1 {
455            packet.put(&param[..])
456        }
457
458        let packet_len = (packet.len() - 3) as u16;
459        packet[1] = (packet_len >> 8) as u8;
460        packet[2] = (packet_len & 0xff) as u8;
461        let chksum = self.calc_checksum(&packet[..])?;
462        packet.put_u8(chksum);
463        Ok(packet)
464    }
465}
466
467/******************* AtCommand Response Frame *******************/
468pub struct AtCommandResponse {
469    pub frame_id: u8,
470    pub at_command: Vec<u8>,
471    pub command_status: u8,
472    pub command_data: Option<BytesMut>,
473    pub payload: Option<BytesMut>,
474}
475
476impl std::fmt::Debug for AtCommandResponse {
477    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
478        let atcmd = std::str::from_utf8(&self.at_command[..]).ok();
479
480        let cmd_data = match self.command_data {
481            Some(ref data) => format!("{:x?}", &data[..]),
482            None => format!("None"),
483        };
484
485        f.debug_struct("AtCommandResponse")
486            .field("FrameId", &format!("0x{:02x?}", self.frame_id))
487            .field("AtCommand", &format!("{}", atcmd.unwrap()))
488            .field("Command Status", &format!("{}", self.command_status))
489            .field("Command Data", &cmd_data)
490            .finish()
491    }
492}
493
494impl RecieveApiFrame for AtCommandResponse {
495    fn id(&self) -> FrameId {
496        FrameId::AtCommandResponse
497    }
498
499    fn recieve(mut ser: Box<dyn SerialPort>) -> Result<Self> {
500        let mut buffer = BytesMut::with_capacity(256);
501        let mut mini_buf: [u8; 1] = [0];
502        loop {
503            if let Err(err) = ser.read_exact(&mut mini_buf) {
504                if err.kind() == std::io::ErrorKind::TimedOut {
505                    break;
506                } else {
507                    return Err(Error::IOError(err));
508                }
509            }
510            buffer.put_u8(mini_buf[0]);
511        }
512        let mut cmd_data = None;
513        if buffer.len() > 9 {
514            cmd_data = Some(BytesMut::from(&buffer[8..buffer.len() - 1]));
515        }
516
517        if buffer.len() == 0 {
518            return Err(Error::FrameError("No frame detected".to_string()));
519        }
520        let mut at_cmd: Vec<u8> = Vec::new();
521        at_cmd.push(buffer[5]);
522        at_cmd.push(buffer[6]);
523        Ok(Self {
524            frame_id: buffer[4],
525            at_command: at_cmd,
526            command_status: buffer[7],
527            command_data: cmd_data,
528            payload: Some(buffer),
529        })
530    }
531
532    fn payload(&self) -> Result<BytesMut> {
533        match &self.payload {
534            Some(p) => Ok(p.clone()),
535            None => Err(Error::FrameError("Emtpy payload".to_string())),
536        }
537    }
538}