Factor out line reading into ::read_line()
This function handles the per-buffer waiting time.
This commit is contained in:
parent
8891b8b6bf
commit
33f7fbcf21
75
src/lib.rs
75
src/lib.rs
|
@ -2,7 +2,8 @@
|
||||||
// to communicate with an external device, any operation could discover a disconnection
|
// to communicate with an external device, any operation could discover a disconnection
|
||||||
// from the RN2903 serial link, so everything which does such communication will return
|
// from the RN2903 serial link, so everything which does such communication will return
|
||||||
// a `Result<T, rn2903::Error>`.
|
// a `Result<T, rn2903::Error>`.
|
||||||
#[macro_use] extern crate quick_error;
|
#[macro_use]
|
||||||
|
extern crate quick_error;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
quick_error! {
|
quick_error! {
|
||||||
|
@ -41,12 +42,12 @@ type Result<T> = std::result::Result<T, Error>;
|
||||||
// exports all the configuration information needed to configure a serial port to
|
// exports all the configuration information needed to configure a serial port to
|
||||||
// communicate correctly with an RN2903.
|
// communicate correctly with an RN2903.
|
||||||
|
|
||||||
use serialport::prelude::*;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use core::convert::AsRef;
|
use core::convert::AsRef;
|
||||||
use std::ffi::OsStr;
|
|
||||||
use std::thread;
|
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
use serialport::prelude::*;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
/// Returns a `serialport::SerialPortSettings` corresponding to the default settings of
|
/// Returns a `serialport::SerialPortSettings` corresponding to the default settings of
|
||||||
/// an RNB2903. Use this to configure your serial port.
|
/// an RNB2903. Use this to configure your serial port.
|
||||||
|
@ -61,7 +62,7 @@ pub fn serial_config() -> SerialPortSettings {
|
||||||
flow_control: FlowControl::None,
|
flow_control: FlowControl::None,
|
||||||
parity: Parity::None,
|
parity: Parity::None,
|
||||||
stop_bits: StopBits::One,
|
stop_bits: StopBits::One,
|
||||||
timeout: Duration::new(1, 0)
|
timeout: Duration::new(1, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +71,12 @@ pub fn serial_config() -> SerialPortSettings {
|
||||||
// wrapper struct's `::new()` function checks the output of the `sys get ver` command,
|
// wrapper struct's `::new()` function checks the output of the `sys get ver` command,
|
||||||
// which is well-specified.
|
// which is well-specified.
|
||||||
|
|
||||||
|
// In order to turn the raw bytes into a String for display, this helper function comes
|
||||||
|
// in handy. It also removes the trailing crlf.
|
||||||
|
fn bytes_to_string(bytes: &[u8]) -> String {
|
||||||
|
(&*String::from_utf8_lossy(bytes).trim_end()).into()
|
||||||
|
}
|
||||||
|
|
||||||
/// A handle to a serial link connected to a RN2903 module.
|
/// A handle to a serial link connected to a RN2903 module.
|
||||||
///
|
///
|
||||||
/// This library guarantees safety regardless of the state of the RN2903.
|
/// This library guarantees safety regardless of the state of the RN2903.
|
||||||
|
@ -86,18 +93,13 @@ impl Rn2903 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open a new connection to a module over the given serial connection.
|
/// Open a new connection to a module over the given serial connection.
|
||||||
pub fn new(mut port: Box<dyn SerialPort>) -> Result<Self> {
|
pub fn new(port: Box<dyn SerialPort>) -> Result<Self> {
|
||||||
let mut buf = [0; 35];
|
let mut new = Self { port };
|
||||||
port.write_all(b"sys get ver\x0D\x0A")?;
|
let version = new.system_version()?;
|
||||||
port.flush()?;
|
if &version[0..6] != "RN2903" {
|
||||||
thread::sleep(Duration::from_millis(12));
|
Err(Error::WrongDevice(version))
|
||||||
port.read(&mut buf)?;
|
|
||||||
if &buf[0..6] != b"RN2903" {
|
|
||||||
Err(Error::WrongDevice((&*String::from_utf8_lossy(&buf)).into()))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(Self {
|
Ok(new)
|
||||||
port
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,12 +107,41 @@ impl Rn2903 {
|
||||||
///
|
///
|
||||||
/// Returns a `String` like `RN2903 1.0.3 Aug 8 2017 15:11:09`
|
/// Returns a `String` like `RN2903 1.0.3 Aug 8 2017 15:11:09`
|
||||||
pub fn system_version(&mut self) -> Result<String> {
|
pub fn system_version(&mut self) -> Result<String> {
|
||||||
let mut buf = [0; 35];
|
|
||||||
self.port.write_all(b"sys get ver\x0D\x0A")?;
|
self.port.write_all(b"sys get ver\x0D\x0A")?;
|
||||||
self.port.flush()?;
|
self.port.flush()?;
|
||||||
thread::sleep(Duration::from_millis(12));
|
Ok(bytes_to_string(&self.read_line()?))
|
||||||
self.port.read(&mut buf)?;
|
|
||||||
Ok((&*String::from_utf8_lossy(&buf).trim_end()).into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read bytes from the device until a CRLF is encountered, then returns the bytes
|
||||||
|
/// read, including the CRLF.
|
||||||
|
// This operation waits 12ms between each 32-byte read because the LoStick has
|
||||||
|
// the hiccups.
|
||||||
|
fn read_line(&mut self) -> Result<Vec<u8>> {
|
||||||
|
let mut vec = Vec::with_capacity(32);
|
||||||
|
loop {
|
||||||
|
let mut buf = [0; 32];
|
||||||
|
self.port.read(&mut buf)?;
|
||||||
|
vec.extend_from_slice(&buf);
|
||||||
|
|
||||||
|
// Check if crlf was added to the buffer.
|
||||||
|
let mut found_lf = false;
|
||||||
|
let mut found_crlf = false;
|
||||||
|
for byte in vec.iter().rev() {
|
||||||
|
if found_lf {
|
||||||
|
if *byte == b'\x0D' {
|
||||||
|
found_crlf = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
found_lf = *byte == b'\x0A';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found_crlf {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
thread::sleep(Duration::from_millis(12));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue