robust_arduino_serial/
lib.rs

1//! # Robust Arduino Serial
2//!
3//! `robust_arduino_serial` is a simple and robust serial communication protocol.
4//! It was designed to make two arduinos communicate, but can also be useful
5//! when you want a computer (e.g. a Raspberry Pi) to communicate with an Arduino.
6//!
7//! It works with anything that implement the io::Write and io::Read traits.
8//!
9//!
10
11use std::io;
12
13#[derive(Debug, PartialEq, Copy, Clone)]
14#[allow(non_camel_case_types)]
15pub enum Order
16{
17    HELLO = 0,
18    SERVO = 1,
19    MOTOR = 2,
20    ALREADY_CONNECTED = 3,
21    ERROR = 4,
22    RECEIVED = 5,
23    STOP = 6
24}
25
26/// Convert an int to an Order
27///
28/// # Example
29///
30/// ```
31/// use robust_arduino_serial::Order;
32///
33/// let order: i8 = 2;  // Order::MOTOR has the index 2 in the enum
34/// let converted_order = robust_arduino_serial::convert_i8_to_order(order).unwrap();
35///
36/// assert_eq!(converted_order, Order::MOTOR);
37/// ```
38pub fn convert_i8_to_order(order: i8) -> Option<Order>
39{
40    match order
41    {
42        0 => Some(Order::HELLO),
43        1 => Some(Order::SERVO),
44        2 => Some(Order::MOTOR),
45        3 => Some(Order::ALREADY_CONNECTED),
46        4 => Some(Order::ERROR),
47        5 => Some(Order::RECEIVED),
48        6 => Some(Order::STOP),
49        _ => None
50    }
51}
52
53/// Shortcut for convert_i8_to_order
54///
55/// # Example
56///
57/// ```
58/// use robust_arduino_serial::Order;
59///
60/// let order: i8 = 2;  // Order::MOTOR has the index 2 in the enum
61/// let converted_order = Order::from_i8(order).unwrap();
62///
63/// assert_eq!(converted_order, Order::MOTOR);
64/// ```
65impl Order {
66    pub fn from_i8(num: i8) -> Option<Order> {
67        convert_i8_to_order(num)
68    }
69}
70
71/// Read one byte from a file/serial port and convert it to an order
72///
73/// # Example
74///
75/// ```
76/// use std::io::Cursor;
77/// use robust_arduino_serial::*;
78///
79/// let mut buffer = Cursor::new(vec![2]);
80/// let order = read_order(&mut buffer).unwrap().unwrap();
81/// // Order::MOTOR has the index 2 in the enum
82/// assert_eq!(Order::MOTOR, order);
83/// ```
84pub fn read_order<T: io::Read>(file: &mut T) -> Result<Option<Order>, io::Error>
85{
86    let order = read_i8(file)?;
87    Ok(Order::from_i8(order))
88}
89
90/// Read one byte from a file/serial port and convert it to a 8 bits int
91///
92/// # Example
93///
94/// ```
95/// use std::io::Cursor;
96///
97/// let mut buffer = Cursor::new(vec![2]);
98/// let num: i8 = robust_arduino_serial::read_i8(&mut buffer).unwrap();
99///
100/// assert_eq!(2, num);
101/// ```
102pub fn read_i8<T: io::Read>(file: &mut T) -> Result<i8, io::Error>
103{
104    let mut read_buffer = [0u8; 1];
105    file.read_exact(&mut read_buffer)?;
106    Ok(read_buffer[0] as i8)
107}
108
109/// Read two bytes from a file/serial port and convert it to a 16 bits int
110///
111/// # Example
112///
113/// ```
114/// use std::io::Cursor;
115/// use std::io::SeekFrom;
116/// use std::io::prelude::*;
117/// use robust_arduino_serial::*;
118///
119/// let mut buffer = Cursor::new(Vec::new());
120/// let number: i16 = -355;
121///
122/// // Write the number to the buffer
123/// write_i16(&mut buffer, number).unwrap();
124///
125/// // Go to the beginning of the buffer
126/// buffer.seek(SeekFrom::Start(0)).unwrap();
127///
128/// // Read 16 bits (two bytes) from the buffer
129/// let read_number: i16 = robust_arduino_serial::read_i16(&mut buffer).unwrap();
130///
131/// assert_eq!(read_number, number);
132/// ```
133pub fn read_i16<T: io::Read>(file: &mut T) -> Result<i16, io::Error>
134{
135    let mut read_buffer = [0u8; 2];
136    file.read_exact(&mut read_buffer)?;
137    let number: u16 = ((read_buffer[0] as u16) & 0xff) | ((read_buffer[1] as u16) << 8 & 0xff00);
138    Ok(number as i16)
139}
140
141/// Read four bytes from a file/serial port and convert it to a 32 bits int
142///
143/// # Example
144///
145/// ```
146/// use std::io::Cursor;
147/// use std::io::SeekFrom;
148/// use std::io::prelude::*;
149/// use robust_arduino_serial::*;
150///
151/// let mut buffer = Cursor::new(Vec::new());
152/// let big_number: i32 = 16384; // 2^14
153///
154/// // Write the number to the buffer
155/// write_i32(&mut buffer, big_number);
156///
157/// // Go to the beginning of the buffer
158/// buffer.seek(SeekFrom::Start(0)).unwrap();
159///
160/// // Read 32 bits (four bytes) from the buffer
161/// let read_number: i32 = robust_arduino_serial::read_i32(&mut buffer).unwrap();
162///
163/// assert_eq!(big_number, read_number);
164/// ```
165pub fn read_i32<T: io::Read>(file: &mut T) -> Result<i32, io::Error>
166{
167    let mut read_buffer = [0u8; 4];
168    file.read_exact(&mut read_buffer)?;
169    let number: u32 = ((read_buffer[0] as u32) & 0xff) | ((read_buffer[1] as u32) << 8 & 0xff00) | ((read_buffer[2] as u32) << 16 & 0xff0000) | ((read_buffer[3] as u32) << 24 & 0xff000000);
170    Ok(number as i32)
171}
172
173/// Write an order to a file/serial port.
174/// It returns the number of bytes written
175///
176/// # Example
177///
178/// ```
179/// use robust_arduino_serial::write_order;
180/// use robust_arduino_serial::Order;
181/// let mut buffer = Vec::new();
182///
183/// // write the order (one byte) to the buffer
184/// write_order(&mut buffer, Order::HELLO).unwrap();
185/// ```
186pub fn write_order<T: io::Write>(file: &mut T, order: Order) -> io::Result<usize>
187{
188    write_i8(file, order as i8)
189}
190
191/// Write one byte int to a file/serial port.
192/// It returns the number of bytes written
193///
194/// # Example
195///
196/// ```
197/// use robust_arduino_serial::write_i8;
198/// let mut buffer = Vec::new();
199/// let num: i8 = 2;
200///
201/// // write 8 bits (one byte) to the buffer
202/// write_i8(&mut buffer, num).unwrap();
203/// ```
204pub fn write_i8<T: io::Write>(file: &mut T, num: i8) -> io::Result<usize>
205{
206    let buffer = [num as u8];
207    let num_bytes = file.write(&buffer)?;
208    Ok(num_bytes)
209}
210
211/// Write two bytes int to a file/serial port.
212/// It returns the number of bytes written
213///
214/// # Example
215///
216/// ```
217/// use std::io::Cursor;
218/// use robust_arduino_serial::*;
219///
220/// let mut buffer = Cursor::new(Vec::new());
221/// let number: i16 = 366;
222///
223/// // write 16 bits (two bytes) to the buffer
224/// write_i16(&mut buffer, number).unwrap();
225/// ```
226pub fn write_i16<T: io::Write>(file: &mut T, num: i16) -> io::Result<usize>
227{
228    let buffer = [
229        (num & 0xff) as u8,
230        (num >> 8 & 0xff) as u8
231    ];
232    let num_bytes = file.write(&buffer)?;
233    Ok(num_bytes)
234}
235
236/// Write four bytes int to a file/serial port.
237/// It returns the number of bytes written
238///
239/// # Example
240///
241/// ```
242/// use std::io::Cursor;
243/// use robust_arduino_serial::*;
244///
245/// let mut buffer = Cursor::new(Vec::new());
246/// let big_number: i32 = -16384; // -2^14
247///
248/// // write 32 bits (four bytes) to the buffer
249/// write_i32(&mut buffer, big_number).unwrap();
250/// ```
251pub fn write_i32<T: io::Write>(file: &mut T, num: i32) -> io::Result<usize>
252{
253    let buffer = [
254        (num & 0xff) as u8,
255        (num >> 8 & 0xff) as u8,
256        (num >> 16 & 0xff) as u8,
257        (num >> 24 & 0xff) as u8
258    ];
259    let num_bytes = file.write(&buffer)?;
260    Ok(num_bytes)
261}
262
263
264#[cfg(test)]
265mod tests {
266    use super::*;
267    use std::io::Cursor;
268    use std::io::SeekFrom;
269    use std::io::prelude::*;
270
271    #[test]
272    fn test_order_conversion()
273    {
274        use Order::*;
275        let orders: [Order; 7] = [
276            HELLO,
277            SERVO,
278            MOTOR,
279            ALREADY_CONNECTED,
280            ERROR,
281            RECEIVED,
282            STOP
283        ];
284
285        for (i, order) in orders.iter().enumerate()
286        {
287            assert_eq!(Order::from_i8(i as i8).unwrap(), *order);
288        }
289    }
290
291    #[test]
292    fn read_write_orders() {
293        let motor_speed: i8 = -57;
294        let servo_angle: i16 = 512; // 2^9
295        let big_number: i32 = -32768; // -2^15
296
297        let mut buffer = Cursor::new(Vec::new());
298
299        write_order(&mut buffer, Order::MOTOR).unwrap();
300        write_i8(&mut buffer, motor_speed).unwrap();
301
302        write_order(&mut buffer, Order::SERVO).unwrap();
303        write_i16(&mut buffer, servo_angle).unwrap();
304
305        write_i8(&mut buffer, Order::ERROR as i8).unwrap();
306        write_i32(&mut buffer, big_number).unwrap();
307
308        // Go to the beginning of the buffer
309        buffer.seek(SeekFrom::Start(0)).unwrap();
310
311        let read_1st_order = read_order(&mut buffer).unwrap().unwrap();
312        let read_motor_speed = read_i8(&mut buffer).unwrap();
313
314        let read_2nd_order = Order::from_i8(read_i8(&mut buffer).unwrap()).unwrap();
315        let read_servo_angle = read_i16(&mut buffer).unwrap();
316
317        let read_3rd_order = Order::from_i8(read_i8(&mut buffer).unwrap()).unwrap();
318        let read_big_number = read_i32(&mut buffer).unwrap();
319
320        assert_eq!(read_1st_order, Order::MOTOR);
321        assert_eq!(read_motor_speed, motor_speed);
322
323        assert_eq!(read_2nd_order, Order::SERVO);
324        assert_eq!(read_servo_angle, servo_angle);
325
326        assert_eq!(read_3rd_order, Order::ERROR);
327        assert_eq!(read_big_number, big_number);
328    }
329}