use crate::obd2::data_pids::DataPid;
use crate::obd2::units::ObdValue;
use crate::obd2::{decode_pid_response, OBD2Cmd, OBD2Command, OBD2DiagnosticServer};
use crate::{DiagError, DiagServerResult};
#[derive(Debug)]
pub struct Service01<'a> {
server: &'a mut OBD2DiagnosticServer,
support_list: Vec<bool>,
}
impl OBD2DiagnosticServer {
pub fn init_service_01(&mut self) -> DiagServerResult<Service01> {
let mut total_support_list = Vec::new();
for i in (0..0xFF).step_by(0x20) {
let x = self.exec_command(OBD2Cmd::new(OBD2Command::Service01, &[i as u8]));
match x {
Ok(resp) => total_support_list.extend_from_slice(&resp[2..]),
Err(e) => {
if let DiagError::ECUError { code: _, def: _ } = e {
total_support_list.extend_from_slice(&[0x00, 0x00, 0x00, 0x00])
} else {
return Err(e); }
}
}
}
Ok(Service01 {
server: self,
support_list: decode_pid_response(&total_support_list),
})
}
}
impl<'a> Service01<'a> {
pub fn get_supported_pids(&self) -> Vec<DataPid> {
let mut r = Vec::new();
for (idx, supported) in self.support_list.iter().enumerate() {
if *supported {
let pid = (idx+1) as u8;
if !&[0x13, 0x1D, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0].contains(&pid) {
r.push(DataPid::from(pid))
}
}
}
r
}
pub fn query_pid(&mut self, pid: DataPid) -> DiagServerResult<Vec<ObdValue>> {
pid.get_value(self.server, None)
}
}
#[cfg(test)]
pub mod service_09_test {
use crate::channel::IsoTPSettings;
use crate::hardware::socketcan::SocketCanScanner;
use crate::hardware::Hardware;
use crate::hardware::HardwareScanner;
use crate::obd2::units::{ObdUnitType, ObdValue};
use crate::obd2::{OBD2DiagnosticServer, Obd2ServerOptions};
use crate::DiagServerResult;
fn print_pid(v: DiagServerResult<ObdValue>) {
match v {
Ok(value) => {
if let ObdUnitType::Encoded(e) = value.get_value() {
println!("{} OK! Enum {}", value.get_name(), e)
} else {
println!(
"{} OK! Metric: {}{}, Imperial: {}{}",
value.get_name(),
value.get_metric_data(),
value.get_metric_unit().unwrap_or_default(),
value.get_imperial_data(),
value.get_imperial_unit().unwrap_or_default()
);
}
}
Err(e) => {
eprintln!("PID request failed {}", e);
}
}
}
#[test]
#[ignore] pub fn test_init() {
let scan = SocketCanScanner::new().open_device_by_name("can0").unwrap();
let socket = Hardware::create_iso_tp_channel(scan).unwrap();
let mut obd = OBD2DiagnosticServer::new_over_iso_tp(
Obd2ServerOptions {
send_id: 0x07E0,
recv_id: 0x07E8,
read_timeout_ms: 500,
write_timeout_ms: 500,
},
socket,
IsoTPSettings {
block_size: 8,
st_min: 20,
extended_addressing: false,
pad_frame: true,
can_speed: 500_000,
can_use_ext_addr: false,
},
)
.unwrap();
obd.read_dtcs();
let mut s_01 = obd.init_service_01().unwrap();
let pids = s_01.get_supported_pids();
for p in pids {
match s_01.query_pid(p) {
Err(e) => println!("Query for {:?} failed {}", p, e),
Ok(res) => {
for param in res {
println!("{}", param.to_string())
}
}
}
}
}
}