fix some baaad state management (LOL)

This commit is contained in:
Alex Janka 2024-01-17 09:11:18 +11:00
parent 42f249f0f4
commit 5cdda39451
4 changed files with 36 additions and 37 deletions

2
Cargo.lock generated
View file

@ -2256,7 +2256,7 @@ dependencies = [
[[package]]
name = "tesla-charge-controller"
version = "1.0.0"
version = "1.0.1"
dependencies = [
"async-channel",
"chrono",

View file

@ -1,6 +1,6 @@
[package]
name = "tesla-charge-controller"
version = "1.0.0"
version = "1.0.1"
edition = "2021"
license = "MITNFA"
description = "Controls Tesla charge rate based on solar charge data"

View file

@ -10,6 +10,7 @@ use config::{access_config, CONFIG_PATH};
use errors::PrintErrors;
use std::path::PathBuf;
use tesla_charge_rate::TeslaChargeRateController;
use teslatte::vehicles::ChargingState;
use crate::config::Config;
@ -134,6 +135,8 @@ async fn main() {
let mut charge_rate_update_interval = tokio::time::interval(
std::time::Duration::from_secs(config.charge_rate_update_interval_seconds),
);
let mut was_connected = false;
loop {
// await either the next interval OR a message from the other thread
tokio::select! {
@ -149,9 +152,22 @@ async fn main() {
},
_ = charge_rate_update_interval.tick() => {
if interface.state.read().unwrap().is_charging_at_home() {
was_connected = true;
if let Some(request) = tesla_charge_rate_controller.control_charge_rate() {
interface.process_request(request).await;
}
} else if was_connected
&& interface
.state
.read()
.unwrap()
.charge_state
.is_some_and(|v| v.charging_state == ChargingState::Disconnected)
{
was_connected = false;
tesla_charge_rate_controller.process_request(
tesla_charge_rate::TcrcRequest::EnableAutomaticControl,
);
}
},
api_message = api_receiver.recv() => match api_message {

View file

@ -1,11 +1,7 @@
use std::{
sync::{Arc, RwLock},
time::{Duration, Instant},
};
use std::sync::{Arc, RwLock};
use metrics::{describe_gauge, gauge, Gauge};
use serde::{Deserialize, Serialize};
use teslatte::vehicles::ChargingState;
use crate::{
api_interface::InterfaceRequest,
@ -18,7 +14,7 @@ pub struct TeslaChargeRateController {
pub car_state: Arc<RwLock<CarState>>,
pub pl_state: Option<Arc<RwLock<PlState>>>,
pub tcrc_state: Arc<RwLock<TcrcState>>,
voltage_low: Option<Instant>,
voltage_low: u64,
control_enable_gauge: Gauge,
}
@ -49,7 +45,7 @@ impl TeslaChargeRateController {
car_state,
pl_state,
tcrc_state: Default::default(),
voltage_low: None,
voltage_low: 0,
control_enable_gauge: gauge!("tcrc_control_enable"),
}
}
@ -58,36 +54,23 @@ impl TeslaChargeRateController {
if let Some(pl_state) = self.pl_state.as_ref().and_then(|v| v.read().ok()) {
if let Ok(car_state) = self.car_state.read() {
if let Some(charge_state) = car_state.charge_state {
// check if we're charging at home
if car_state.is_charging_at_home() {
// we don't need to check if we're at home because we only call this when we are
// TODO: enforce this through type system
// automatic control or not, check if we're below shutoff voltage
if pl_state.battery_voltage < access_config().shutoff_voltage {
if let Some(low_voltage_time) = self.voltage_low {
// if we've been below shutoff for long enough, stop charging
if Instant::now().duration_since(low_voltage_time)
>= Duration::from_secs(
access_config().shutoff_voltage_time_seconds,
)
self.voltage_low += 1;
if (self.voltage_low * access_config().charge_rate_update_interval_seconds)
>= access_config().shutoff_voltage_time_seconds
{
return Some(InterfaceRequest::StopCharge);
}
} else {
self.voltage_low = Some(Instant::now());
}
} else {
self.voltage_low = None;
self.voltage_low = 0;
if self.tcrc_state.read().is_ok_and(|v| v.control_enable) {
return get_control(&pl_state, &charge_state);
}
}
} else if charge_state.charging_state == ChargingState::Disconnected {
// only disable automatic control until the next time we're unplugged
self.tcrc_state
.write()
.expect("failed to write to tcrc state")
.control_enable = true;
self.control_enable_gauge.set(1.);
}
}
}
}