ditch anyhow

This commit is contained in:
Alex Janka 2024-01-12 08:47:21 +11:00
parent 904513b71a
commit 7dd4cc43b1
6 changed files with 54 additions and 43 deletions

7
Cargo.lock generated
View file

@ -101,12 +101,6 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "anyhow"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]] [[package]]
name = "arc-swap" name = "arc-swap"
version = "1.6.0" version = "1.6.0"
@ -2264,7 +2258,6 @@ dependencies = [
name = "tesla-charge-controller" name = "tesla-charge-controller"
version = "0.1.17-prerelease" version = "0.1.17-prerelease"
dependencies = [ dependencies = [
"anyhow",
"async-channel", "async-channel",
"chrono", "chrono",
"clap", "clap",

View file

@ -20,7 +20,6 @@ tokio = { version = "1.35.1", features = ["full"] }
teslatte = { path = "./vendored/teslatte" } teslatte = { path = "./vendored/teslatte" }
thiserror = "1.0" thiserror = "1.0"
rocket = { version = "0.5", features = ["json"] } rocket = { version = "0.5", features = ["json"] }
anyhow = "1.0"
include_dir = "0.7" include_dir = "0.7"
chrono = "0.4" chrono = "0.4"
async-channel = "2.1" async-channel = "2.1"

View file

@ -1,4 +1,3 @@
use anyhow::{Context, Result};
use metrics::{describe_gauge, gauge, Gauge, Unit}; use metrics::{describe_gauge, gauge, Gauge, Unit};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
@ -93,7 +92,7 @@ impl TeslaInterface {
_ => None, _ => None,
}) })
.next() .next()
.context("No vehicles attached to account!")?; .ok_or(AuthLoadError::NoVehicles)?;
let metrics = Metrics::new(); let metrics = Metrics::new();

View file

@ -27,8 +27,8 @@ pub enum AuthLoadError {
Teslatte(#[from] teslatte::error::TeslatteError), Teslatte(#[from] teslatte::error::TeslatteError),
#[error("save error")] #[error("save error")]
Save(#[from] SaveError), Save(#[from] SaveError),
#[error("other error")] #[error("no vehicles")]
Anyhow(#[from] anyhow::Error), NoVehicles,
} }
impl AuthLoadError { impl AuthLoadError {
@ -38,7 +38,7 @@ impl AuthLoadError {
AuthLoadError::StdIo(e) => format!("Error reading access token from disk: {e:?}"), AuthLoadError::StdIo(e) => format!("Error reading access token from disk: {e:?}"),
AuthLoadError::RonSpanned(e) => format!("Error deserialising access token: {e:?}"), AuthLoadError::RonSpanned(e) => format!("Error deserialising access token: {e:?}"),
AuthLoadError::Save(e) => e.error_string(), AuthLoadError::Save(e) => e.error_string(),
AuthLoadError::Anyhow(e) => e.to_string(), AuthLoadError::NoVehicles => String::from("No vehicles attached to account"),
} }
} }
} }
@ -54,3 +54,17 @@ pub enum RequestError {
#[error("save error")] #[error("save error")]
Save(#[from] SaveError), Save(#[from] SaveError),
} }
#[derive(Error, Debug)]
pub enum PliError {
#[error("read error")]
ReadError(u8),
}
#[derive(Error, Debug)]
pub enum TeslaStateParseError {
#[error("No associated value")]
NoValue,
#[error("Invalid timestamp")]
InvalidTimestamp,
}

View file

@ -4,12 +4,13 @@ use std::{
time::Duration, time::Duration,
}; };
use anyhow::Context;
use metrics::{describe_gauge, gauge, Gauge}; use metrics::{describe_gauge, gauge, Gauge};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serialport::SerialPort; use serialport::SerialPort;
use termcolor::WriteColor; use termcolor::WriteColor;
use crate::errors::PliError;
pub struct Pli { pub struct Pli {
pub state: Arc<RwLock<PlState>>, pub state: Arc<RwLock<PlState>>,
port: Box<dyn SerialPort>, port: Box<dyn SerialPort>,
@ -122,7 +123,7 @@ pub enum PliRequest {
} }
impl Pli { impl Pli {
pub fn new(serial_port: String, baud_rate: u32) -> anyhow::Result<Self> { pub fn new(serial_port: String, baud_rate: u32) -> Result<Self, serialport::Error> {
let port = serialport::new(serial_port, baud_rate) let port = serialport::new(serial_port, baud_rate)
.timeout(Duration::from_millis(250)) .timeout(Duration::from_millis(250))
.open()?; .open()?;
@ -151,7 +152,8 @@ impl Pli {
} }
pub fn refresh(&mut self) { pub fn refresh(&mut self) {
if let Ok(new_state) = self.read_state() { match self.read_state() {
Ok(new_state) => {
self.voltage_gauge.set(new_state.battery_voltage); self.voltage_gauge.set(new_state.battery_voltage);
self.target_voltage_gauge.set(new_state.target_voltage); self.target_voltage_gauge.set(new_state.target_voltage);
self.duty_cycle.set(new_state.duty_cycle); self.duty_cycle.set(new_state.duty_cycle);
@ -163,6 +165,8 @@ impl Pli {
*self.state.write().expect("PLI state handler panicked!!") = new_state; *self.state.write().expect("PLI state handler panicked!!") = new_state;
} }
Err(e) => log::error!("State read error: {e:#?}"),
}
} }
pub fn process_request(&mut self, message: PliRequest) { pub fn process_request(&mut self, message: PliRequest) {
@ -185,7 +189,7 @@ impl Pli {
} }
} }
fn read_state(&mut self) -> anyhow::Result<PlState> { fn read_state(&mut self) -> Result<PlState, PliError> {
Ok(PlState { Ok(PlState {
battery_voltage: (self.read_ram(PlRamAddress::Batv)? as f64) * (4. / 10.), battery_voltage: (self.read_ram(PlRamAddress::Batv)? as f64) * (4. / 10.),
target_voltage: (self.read_ram(PlRamAddress::Vreg)? as f64) * (4. / 10.), target_voltage: (self.read_ram(PlRamAddress::Vreg)? as f64) * (4. / 10.),
@ -211,14 +215,17 @@ impl Pli {
buf buf
} }
fn read_ram<T>(&mut self, address: T) -> anyhow::Result<u8> fn read_ram<T>(&mut self, address: T) -> Result<u8, PliError>
where where
T: Into<u8>, T: Into<u8>,
{ {
self.send_command(command(20, address.into(), 0)); self.send_command(command(20, address.into(), 0));
let buf: [u8; 2] = self.receive(); let buf: [u8; 2] = self.receive();
if buf[0] == 200 { Some(buf[1]) } else { None } if buf[0] == 200 {
.context(format!("Error from PLI: {}", buf[0])) Ok(buf[1])
} else {
Err(PliError::ReadError(buf[0]))
}
} }
} }

View file

@ -1,7 +1,8 @@
use anyhow::Context;
use chrono::DateTime; use chrono::DateTime;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::errors::TeslaStateParseError;
#[derive(Default)] #[derive(Default)]
pub struct CarState { pub struct CarState {
pub charge_state: Option<ChargeState>, pub charge_state: Option<ChargeState>,
@ -17,17 +18,13 @@ pub struct ClimateState {
} }
impl TryFrom<teslatte::vehicles::ClimateState> for ClimateState { impl TryFrom<teslatte::vehicles::ClimateState> for ClimateState {
type Error = anyhow::Error; type Error = TeslaStateParseError;
fn try_from(value: teslatte::vehicles::ClimateState) -> Result<Self, Self::Error> { fn try_from(value: teslatte::vehicles::ClimateState) -> Result<Self, Self::Error> {
Ok(Self { Ok(Self {
inside_temp: value inside_temp: value.inside_temp.ok_or(TeslaStateParseError::NoValue)?,
.inside_temp
.context("no inside temperature in climate data")?,
outside_temp: value outside_temp: value.outside_temp.ok_or(TeslaStateParseError::NoValue)?,
.outside_temp
.context("no outside temperature in climate data")?,
battery_heater: value.battery_heater, battery_heater: value.battery_heater,
}) })
} }
@ -74,15 +71,17 @@ pub struct LocationData {
} }
impl TryFrom<teslatte::vehicles::DriveState> for LocationData { impl TryFrom<teslatte::vehicles::DriveState> for LocationData {
type Error = anyhow::Error; type Error = TeslaStateParseError;
fn try_from(value: teslatte::vehicles::DriveState) -> Result<Self, Self::Error> { fn try_from(value: teslatte::vehicles::DriveState) -> Result<Self, Self::Error> {
let gps_as_of = let gps_as_of = chrono::DateTime::from_timestamp(
chrono::DateTime::from_timestamp(value.gps_as_of.context("no gps timestamp!")?, 0) value.gps_as_of.ok_or(TeslaStateParseError::NoValue)?,
.context("could not process timestamp!")?; 0,
)
.ok_or(TeslaStateParseError::InvalidTimestamp)?;
let coords = Coords { let coords = Coords {
latitude: value.latitude.context("no longitude provided!")?, latitude: value.latitude.ok_or(TeslaStateParseError::NoValue)?,
longitude: value.longitude.context("no latitude provided!")?, longitude: value.longitude.ok_or(TeslaStateParseError::NoValue)?,
}; };
Ok(Self { coords, gps_as_of }) Ok(Self { coords, gps_as_of })
} }