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}