Serialport Support
- allow communication to elm327 device via a serialport - allow creation of elm327 device without requiring unwrap() - added some extra documentation - expose reset() functionality of device - serial_comm and ftdi_comm abstractions added
This commit is contained in:
parent
db4b4d990d
commit
821e80aaaf
14 changed files with 213 additions and 60 deletions
|
@ -1,11 +1,7 @@
|
|||
use log::{debug, info, trace};
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
io::{Read, Write},
|
||||
thread, time,
|
||||
};
|
||||
use std::{collections::VecDeque, thread, time};
|
||||
|
||||
use super::{Error, Obd2BaseDevice, Obd2Reader, Result};
|
||||
use super::{serial_comm::SerialComm, Error, Obd2BaseDevice, Obd2Reader, Result};
|
||||
|
||||
/// An ELM327 OBD-II adapter
|
||||
///
|
||||
|
@ -16,19 +12,13 @@ use super::{Error, Obd2BaseDevice, Obd2Reader, Result};
|
|||
///
|
||||
/// [Datasheet for v1.4b](https://github.com/rsammelson/obd2/blob/master/docs/ELM327DSH.pdf), and
|
||||
/// the [source](https://www.elmelectronics.com/products/dsheets/).
|
||||
pub struct Elm327 {
|
||||
device: ftdi::Device,
|
||||
pub struct Elm327<T: SerialComm> {
|
||||
device: T,
|
||||
buffer: VecDeque<u8>,
|
||||
baud_rate: u32,
|
||||
}
|
||||
|
||||
impl Default for Elm327 {
|
||||
fn default() -> Self {
|
||||
Elm327::new().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Obd2BaseDevice for Elm327 {
|
||||
impl<T: SerialComm> Obd2BaseDevice for Elm327<T> {
|
||||
fn reset(&mut self) -> Result<()> {
|
||||
self.flush_buffers()?;
|
||||
self.reset_ic()?;
|
||||
|
@ -40,7 +30,7 @@ impl Obd2BaseDevice for Elm327 {
|
|||
fn send_cmd(&mut self, data: &[u8]) -> Result<()> {
|
||||
trace!("send_cmd: sending {:?}", std::str::from_utf8(data));
|
||||
self.send_serial_str(
|
||||
data.into_iter()
|
||||
data.iter()
|
||||
.flat_map(|v| format!("{:02X}", v).chars().collect::<Vec<char>>())
|
||||
.collect::<String>()
|
||||
.as_str(),
|
||||
|
@ -48,7 +38,7 @@ impl Obd2BaseDevice for Elm327 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Obd2Reader for Elm327 {
|
||||
impl<T: SerialComm> Obd2Reader for Elm327<T> {
|
||||
fn get_line(&mut self) -> Result<Option<Vec<u8>>> {
|
||||
self.get_until(b'\n', false)
|
||||
}
|
||||
|
@ -64,22 +54,14 @@ impl Obd2Reader for Elm327 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Elm327 {
|
||||
fn new() -> Result<Self> {
|
||||
let mut ftdi_device = ftdi::find_by_vid_pid(0x0403, 0x6001)
|
||||
.interface(ftdi::Interface::A)
|
||||
.open()?;
|
||||
|
||||
ftdi_device.set_baud_rate(38400)?;
|
||||
ftdi_device.configure(ftdi::Bits::Eight, ftdi::StopBits::One, ftdi::Parity::None)?;
|
||||
// device.set_latency_timer(2).unwrap();
|
||||
|
||||
ftdi_device.usb_reset()?;
|
||||
|
||||
impl<T: SerialComm> Elm327<T> {
|
||||
/// Creates a new Elm327 adapter with the given
|
||||
/// unserlying Serial Communication device
|
||||
pub fn new(serial_device: T) -> Result<Self> {
|
||||
let mut device = Elm327 {
|
||||
device: ftdi_device,
|
||||
device: serial_device,
|
||||
buffer: VecDeque::new(),
|
||||
baud_rate: 38400,
|
||||
baud_rate: 38_400,
|
||||
};
|
||||
|
||||
device.connect(false)?;
|
||||
|
@ -98,7 +80,7 @@ impl Elm327 {
|
|||
}
|
||||
|
||||
fn flush_buffers(&mut self) -> Result<()> {
|
||||
self.device.usb_purge_buffers()?;
|
||||
self.device.purge_buffers()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -123,26 +105,28 @@ impl Elm327 {
|
|||
fn reset_ic(&mut self) -> Result<()> {
|
||||
info!("Performing IC reset");
|
||||
self.send_serial_str("ATZ")?;
|
||||
let response = self.get_response()?;
|
||||
debug!(
|
||||
"reset_ic: got response {:?}",
|
||||
self.get_response()?
|
||||
.as_ref()
|
||||
.map(|l| std::str::from_utf8(l.as_slice()))
|
||||
response.as_ref().map(|l| std::str::from_utf8(l.as_slice()))
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reset_protocol(&mut self) -> Result<()> {
|
||||
info!("Performing protocol reset");
|
||||
debug!(
|
||||
"reset_protocol: got response {:?}",
|
||||
self.serial_cmd("ATSP0")?
|
||||
);
|
||||
debug!(
|
||||
"reset_protocol: got OBD response {:?}",
|
||||
self.cmd(&[0x01, 0x00])?
|
||||
);
|
||||
|
||||
// set to use automatic protocol selection
|
||||
let elm_response = self.serial_cmd("ATSP0")?;
|
||||
debug!("reset_protocol: got response {:?}", elm_response);
|
||||
|
||||
// perform the search for ECUs
|
||||
let obd_response = self.cmd(&[0x01, 0x00])?;
|
||||
debug!("reset_protocol: got OBD response {:?}", obd_response);
|
||||
|
||||
// get rid of extra data hanging around in the buffer
|
||||
self.flush_buffers()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -259,6 +243,7 @@ impl Elm327 {
|
|||
let mut buf = [0u8; 16];
|
||||
loop {
|
||||
let len = self.device.read(&mut buf)?;
|
||||
|
||||
if len > 0 {
|
||||
self.buffer.extend(&buf[0..len]);
|
||||
trace!(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue