ditch anyhow
This commit is contained in:
parent
904513b71a
commit
7dd4cc43b1
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
|
@ -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]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
src/types.rs
27
src/types.rs
|
@ -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 })
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue