use crate::obd2::ObdEnumValue;
use std::fmt::{Display, Formatter};
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub struct ObdValue {
name: String,
value: ObdUnitType,
}
impl ObdValue {
pub fn new<T: Into<String>>(x: T, value: ObdUnitType) -> Self {
Self {
name: x.into(),
value,
}
}
pub fn get_value_as_string(&self, use_metric: bool) -> String {
match use_metric {
true => self.value.to_metric_string(),
false => self.value.to_imperial_string(),
}
}
pub fn get_imperial_data(&self) -> f32 {
self.value.as_imperial()
}
pub fn get_metric_data(&self) -> f32 {
self.value.as_metric()
}
pub fn get_imperial_unit(&self) -> Option<&'static str> {
self.value.get_imperial_unit()
}
pub fn get_metric_unit(&self) -> Option<&'static str> {
self.value.get_metric_unit()
}
pub fn get_name(&self) -> String {
self.name.clone()
}
pub fn get_value(&self) -> ObdUnitType {
self.value.clone()
}
}
impl Display for ObdValue {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}: {}", self.name, self.value)
}
}
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub struct Speed(f32);
impl Speed {
pub fn from_kmh(kmh: f32) -> Self {
Self(kmh / 3.6)
}
pub fn from_mph(mph: f32) -> Self {
Self(mph / 2.237)
}
pub fn to_kmh(&self) -> f32 {
self.0 * 3.6
}
pub fn to_mph(&self) -> f32 {
self.0 * 2.237
}
pub fn to_m_s(&self) -> f32 {
self.0
}
}
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub struct Temperature(f32);
impl Temperature {
pub fn from_celsius(c: f32) -> Self {
Self(c)
}
pub fn from_fahrenheit(f: f32) -> Self {
Self((f - 32.0) * (5.0 / 9.0))
}
pub fn to_celsius(&self) -> f32 {
self.0
}
pub fn to_fahrenheit(&self) -> f32 {
(self.0 * (9.0 / 5.0)) + 32.0
}
}
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub struct Pressure(f32);
impl Pressure {
pub fn from_bar(b: f32) -> Self {
Self(b * 100.0)
}
pub fn from_kilo_pascal(kpa: f32) -> Self {
Self(kpa)
}
pub fn from_psi(psi: f32) -> Self {
Self(psi * 68.95)
}
pub fn from_atmosphere(atmos: f32) -> Self {
Self(atmos * 1013.25)
}
pub fn to_bar(&self) -> f32 {
self.0 * 0.01
}
pub fn to_kilo_pascal(&self) -> f32 {
self.0
}
pub fn to_psi(&self) -> f32 {
self.0 * 0.145038
}
pub fn to_atmosphere(&self) -> f32 {
self.0 * 0.00986923
}
}
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub struct Time(f32);
impl Time {
pub fn from_seconds(seconds: f32) -> Self {
Self(seconds)
}
pub fn to_seconds(&self) -> f32 {
self.0
}
pub fn to_elapsed_string(&self) -> String {
format!(
"{}:{}:{}",
(self.0 / 3600.0).floor() as u32,
((self.0 / 60.0).floor() as u32) % 60,
self.0 as u32 % 60
)
}
}
#[derive(Debug, Copy, Clone, PartialOrd, PartialEq)]
pub struct Distance(f32);
impl Distance {
pub fn from_kilometers(km: f32) -> Self {
Self(km * 1000.0)
}
pub fn to_meters(&self) -> f32 {
self.0
}
pub fn to_kilometers(&self) -> f32 {
self.0 / 1000.0
}
pub fn to_miles(&self) -> f32 {
self.0 / 1609.0
}
}
#[derive(Debug, Clone, PartialOrd, PartialEq)]
pub enum ObdUnitType {
Raw(f32),
Speed(Speed),
Percent(f32), Temperature(Temperature),
Rpm(u32),
Volts(f32),
Time(Time),
Distance(Distance),
Pressure(Pressure),
Encoded(ObdEnumValue),
ByteArray(Vec<u8>),
}
impl ObdUnitType {
pub fn to_metric_string(&self) -> String {
match self {
ObdUnitType::Raw(i) => format!("{i:.1}"),
ObdUnitType::Rpm(i) => format!("{i} Rpm"),
ObdUnitType::Speed(s) => format!("{} km/h", s.to_kmh()),
ObdUnitType::Percent(p) => format!("{p:.1} %"),
ObdUnitType::Temperature(t) => format!("{}°C", t.to_celsius()),
ObdUnitType::Volts(v) => format!("{v}V"),
ObdUnitType::Time(t) => t.to_elapsed_string(),
ObdUnitType::Distance(d) => format!("{} km", d.to_kilometers()),
ObdUnitType::Pressure(p) => format!("{} bar", p.to_bar()),
ObdUnitType::Encoded(e) => e.to_string(),
ObdUnitType::ByteArray(v) => format!("{v:02X?}"),
}
}
pub fn to_imperial_string(&self) -> String {
match self {
ObdUnitType::Raw(i) => format!("{i:.1}"),
ObdUnitType::Rpm(i) => format!("{i} Rpm"),
ObdUnitType::Speed(s) => format!("{} mph", s.to_mph()),
ObdUnitType::Percent(p) => format!("{p:.1} %"),
ObdUnitType::Temperature(t) => format!("{} F", t.to_fahrenheit()),
ObdUnitType::Volts(v) => format!("{v}V"),
ObdUnitType::Time(t) => t.to_elapsed_string(),
ObdUnitType::Distance(d) => format!("{} miles", d.to_miles()),
ObdUnitType::Pressure(p) => format!("{} bar", p.to_psi()),
ObdUnitType::Encoded(e) => e.to_string(),
ObdUnitType::ByteArray(v) => format!("{v:02X?}"),
}
}
pub fn get_imperial_unit(&self) -> Option<&'static str> {
match self {
ObdUnitType::Speed(_) => Some("mph"),
ObdUnitType::Percent(_) => Some("%"),
ObdUnitType::Rpm(_) => Some("Rpm"),
ObdUnitType::Temperature(_) => Some("F"),
ObdUnitType::Volts(_) => Some("V"),
ObdUnitType::Distance(_) => Some("miles"),
ObdUnitType::Pressure(_) => Some("psi"),
_ => None,
}
}
pub fn get_metric_unit(&self) -> Option<&'static str> {
match self {
ObdUnitType::Speed(_) => Some("km/h"),
ObdUnitType::Percent(_) => Some("%"),
ObdUnitType::Rpm(_) => Some("Rpm"),
ObdUnitType::Temperature(_) => Some("°C"),
ObdUnitType::Volts(_) => Some("V"),
ObdUnitType::Distance(_) => Some("km"),
ObdUnitType::Pressure(_) => Some("bar"),
_ => None,
}
}
pub fn as_imperial(&self) -> f32 {
match self {
ObdUnitType::Raw(x) => *x,
ObdUnitType::Speed(x) => x.to_mph(),
ObdUnitType::Percent(x) => *x,
ObdUnitType::Temperature(x) => x.to_fahrenheit(),
ObdUnitType::Rpm(x) => *x as f32,
ObdUnitType::Volts(x) => *x,
ObdUnitType::Time(x) => x.to_seconds(),
ObdUnitType::Distance(x) => x.to_miles(),
ObdUnitType::Pressure(x) => x.to_bar(),
ObdUnitType::Encoded(x) => u32::from(*x) as f32,
ObdUnitType::ByteArray(v) => v.iter().map(|x| *x as f32).sum::<f32>(),
}
}
pub fn as_metric(&self) -> f32 {
match self {
ObdUnitType::Raw(x) => *x,
ObdUnitType::Speed(x) => x.to_kmh(),
ObdUnitType::Percent(x) => *x,
ObdUnitType::Temperature(x) => x.to_celsius(),
ObdUnitType::Rpm(x) => *x as f32,
ObdUnitType::Volts(x) => *x,
ObdUnitType::Time(x) => x.to_seconds(),
ObdUnitType::Distance(x) => x.to_kilometers(),
ObdUnitType::Pressure(x) => x.to_bar(),
ObdUnitType::Encoded(x) => u32::from(*x) as f32,
ObdUnitType::ByteArray(v) => v.iter().map(|x| *x as f32).sum::<f32>(),
}
}
}
impl Display for ObdUnitType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_metric_string())
}
}