tesla-charge-controller/src/types.rs

148 lines
4.7 KiB
Rust
Raw Normal View History

2024-01-08 12:00:09 +11:00
use chrono::DateTime;
2024-01-07 10:08:16 +11:00
use serde::{Deserialize, Serialize};
2024-01-18 10:01:35 +11:00
use teslatte::vehicles::{ChargingState, ShiftState};
2024-01-07 10:08:16 +11:00
use crate::{config::access_config, errors::TeslaStateParseError};
2024-01-12 08:47:21 +11:00
#[derive(Default, Clone, Copy, Serialize, Deserialize, Debug)]
2024-01-08 12:00:09 +11:00
pub struct CarState {
pub charge_state: Option<ChargeState>,
pub location_data: Option<LocationData>,
2024-01-09 11:11:16 +11:00
pub climate_state: Option<ClimateState>,
}
impl CarState {
pub fn is_charging_at_home(&self) -> bool {
self.charge_state
.is_some_and(|v| v.charging_state == ChargingState::Charging)
&& self.location_data.is_some_and(|v| v.home)
}
}
2024-01-09 11:11:16 +11:00
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
pub struct ClimateState {
pub inside_temp: f64,
2024-01-09 12:06:18 +11:00
pub outside_temp: f64,
pub battery_heater: bool,
pub climate_on: bool,
pub preconditioning: bool,
pub remote_heater_control_enabled: bool,
2024-01-18 16:32:24 +11:00
pub is_auto_conditioning_on: bool,
pub driver_temp_setting: f64,
pub passenger_temp_setting: f64,
2024-01-09 11:11:16 +11:00
}
impl TryFrom<teslatte::vehicles::ClimateState> for ClimateState {
2024-01-12 08:47:21 +11:00
type Error = TeslaStateParseError;
2024-01-09 11:11:16 +11:00
fn try_from(value: teslatte::vehicles::ClimateState) -> Result<Self, Self::Error> {
Ok(Self {
2024-01-12 08:47:21 +11:00
inside_temp: value.inside_temp.ok_or(TeslaStateParseError::NoValue)?,
outside_temp: value.outside_temp.ok_or(TeslaStateParseError::NoValue)?,
2024-01-09 12:06:18 +11:00
battery_heater: value.battery_heater,
climate_on: value.is_climate_on,
preconditioning: value.is_preconditioning,
remote_heater_control_enabled: value.remote_heater_control_enabled,
2024-01-18 16:32:24 +11:00
is_auto_conditioning_on: value.is_auto_conditioning_on.unwrap_or(false),
driver_temp_setting: value.driver_temp_setting,
passenger_temp_setting: value.passenger_temp_setting,
2024-01-09 11:11:16 +11:00
})
}
2024-01-08 12:00:09 +11:00
}
2024-01-07 10:08:16 +11:00
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
pub struct ChargeState {
pub battery_level: i64,
pub battery_range: f64,
pub charge_amps: i64,
2024-01-07 10:33:32 +11:00
pub charge_rate: f64,
2024-01-07 10:08:16 +11:00
pub charge_current_request: i64,
pub charge_current_request_max: i64,
2024-01-15 15:47:13 +11:00
pub charger_connected: bool,
2024-01-07 10:08:16 +11:00
pub charge_enable_request: bool,
2024-01-16 11:00:11 +11:00
pub charging_state: ChargingState,
2024-01-07 10:33:32 +11:00
pub charge_limit_soc: i64,
2024-01-07 10:08:16 +11:00
}
impl ChargeState {
#[allow(unused)]
pub fn range_km(&self) -> f64 {
self.battery_range * 1.60934
}
}
impl From<teslatte::vehicles::ChargeState> for ChargeState {
fn from(value: teslatte::vehicles::ChargeState) -> Self {
ChargeState {
battery_level: value.battery_level,
battery_range: value.battery_range,
charge_amps: value.charge_amps,
2024-01-07 10:33:32 +11:00
charge_rate: value.charge_rate,
2024-01-07 10:08:16 +11:00
charge_current_request: value.charge_current_request,
charge_current_request_max: value.charge_current_request_max,
2024-01-16 11:00:11 +11:00
charger_connected: value.conn_charge_cable != "<invalid>",
2024-01-07 10:08:16 +11:00
charge_enable_request: value.charge_enable_request,
2024-01-16 11:00:11 +11:00
charging_state: value.charging_state,
2024-01-07 10:33:32 +11:00
charge_limit_soc: value.charge_limit_soc,
2024-01-07 10:08:16 +11:00
}
}
}
2024-01-08 12:00:09 +11:00
2024-01-18 10:01:35 +11:00
pub struct FromDriveState(pub LocationData, pub DriveState);
2024-01-08 12:00:09 +11:00
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
pub struct LocationData {
pub gps_as_of: DateTime<chrono::Utc>,
pub home: bool,
2024-01-18 10:01:35 +11:00
}
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
pub struct DriveState {
pub power: i64,
2024-01-18 10:01:35 +11:00
pub speed: i64,
pub shift_state: ShiftState,
2024-01-08 12:00:09 +11:00
}
2024-01-18 10:01:35 +11:00
impl TryFrom<teslatte::vehicles::DriveState> for FromDriveState {
2024-01-12 08:47:21 +11:00
type Error = TeslaStateParseError;
2024-01-08 12:00:09 +11:00
fn try_from(value: teslatte::vehicles::DriveState) -> Result<Self, Self::Error> {
2024-01-12 08:47:21 +11:00
let gps_as_of = chrono::DateTime::from_timestamp(
value.gps_as_of.ok_or(TeslaStateParseError::NoValue)?,
0,
)
.ok_or(TeslaStateParseError::InvalidTimestamp)?;
2024-01-08 12:00:09 +11:00
let coords = Coords {
2024-01-12 08:47:21 +11:00
latitude: value.latitude.ok_or(TeslaStateParseError::NoValue)?,
longitude: value.longitude.ok_or(TeslaStateParseError::NoValue)?,
2024-01-08 12:00:09 +11:00
};
let home = coords.overlaps(&access_config().coords);
let power = value.power;
2024-01-18 10:01:35 +11:00
let speed = value.speed.unwrap_or(0);
let shift_state = value.shift_state;
Ok(Self(
LocationData { gps_as_of, home },
DriveState {
power,
speed,
shift_state,
},
))
2024-01-08 12:00:09 +11:00
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
pub struct Coords {
pub latitude: f64,
pub longitude: f64,
}
const COORD_PRECISION: f64 = 0.001;
impl Coords {
pub fn overlaps(&self, other: &Coords) -> bool {
(self.latitude - other.latitude).abs() < COORD_PRECISION
&& (self.longitude - other.longitude).abs() < COORD_PRECISION
}
}