fix some baaad state management (LOL)
This commit is contained in:
parent
42f249f0f4
commit
5cdda39451
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2256,7 +2256,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tesla-charge-controller"
|
name = "tesla-charge-controller"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel",
|
"async-channel",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "tesla-charge-controller"
|
name = "tesla-charge-controller"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MITNFA"
|
license = "MITNFA"
|
||||||
description = "Controls Tesla charge rate based on solar charge data"
|
description = "Controls Tesla charge rate based on solar charge data"
|
||||||
|
|
16
src/main.rs
16
src/main.rs
|
@ -10,6 +10,7 @@ use config::{access_config, CONFIG_PATH};
|
||||||
use errors::PrintErrors;
|
use errors::PrintErrors;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tesla_charge_rate::TeslaChargeRateController;
|
use tesla_charge_rate::TeslaChargeRateController;
|
||||||
|
use teslatte::vehicles::ChargingState;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
|
@ -134,6 +135,8 @@ async fn main() {
|
||||||
let mut charge_rate_update_interval = tokio::time::interval(
|
let mut charge_rate_update_interval = tokio::time::interval(
|
||||||
std::time::Duration::from_secs(config.charge_rate_update_interval_seconds),
|
std::time::Duration::from_secs(config.charge_rate_update_interval_seconds),
|
||||||
);
|
);
|
||||||
|
let mut was_connected = false;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// await either the next interval OR a message from the other thread
|
// await either the next interval OR a message from the other thread
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
@ -149,9 +152,22 @@ async fn main() {
|
||||||
},
|
},
|
||||||
_ = charge_rate_update_interval.tick() => {
|
_ = charge_rate_update_interval.tick() => {
|
||||||
if interface.state.read().unwrap().is_charging_at_home() {
|
if interface.state.read().unwrap().is_charging_at_home() {
|
||||||
|
was_connected = true;
|
||||||
if let Some(request) = tesla_charge_rate_controller.control_charge_rate() {
|
if let Some(request) = tesla_charge_rate_controller.control_charge_rate() {
|
||||||
interface.process_request(request).await;
|
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 {
|
api_message = api_receiver.recv() => match api_message {
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
use std::{
|
use std::sync::{Arc, RwLock};
|
||||||
sync::{Arc, RwLock},
|
|
||||||
time::{Duration, Instant},
|
|
||||||
};
|
|
||||||
|
|
||||||
use metrics::{describe_gauge, gauge, Gauge};
|
use metrics::{describe_gauge, gauge, Gauge};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use teslatte::vehicles::ChargingState;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api_interface::InterfaceRequest,
|
api_interface::InterfaceRequest,
|
||||||
|
@ -18,7 +14,7 @@ pub struct TeslaChargeRateController {
|
||||||
pub car_state: Arc<RwLock<CarState>>,
|
pub car_state: Arc<RwLock<CarState>>,
|
||||||
pub pl_state: Option<Arc<RwLock<PlState>>>,
|
pub pl_state: Option<Arc<RwLock<PlState>>>,
|
||||||
pub tcrc_state: Arc<RwLock<TcrcState>>,
|
pub tcrc_state: Arc<RwLock<TcrcState>>,
|
||||||
voltage_low: Option<Instant>,
|
voltage_low: u64,
|
||||||
control_enable_gauge: Gauge,
|
control_enable_gauge: Gauge,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +45,7 @@ impl TeslaChargeRateController {
|
||||||
car_state,
|
car_state,
|
||||||
pl_state,
|
pl_state,
|
||||||
tcrc_state: Default::default(),
|
tcrc_state: Default::default(),
|
||||||
voltage_low: None,
|
voltage_low: 0,
|
||||||
control_enable_gauge: gauge!("tcrc_control_enable"),
|
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 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 Ok(car_state) = self.car_state.read() {
|
||||||
if let Some(charge_state) = car_state.charge_state {
|
if let Some(charge_state) = car_state.charge_state {
|
||||||
// check if we're charging at home
|
// we don't need to check if we're at home because we only call this when we are
|
||||||
if car_state.is_charging_at_home() {
|
// TODO: enforce this through type system
|
||||||
|
|
||||||
// automatic control or not, check if we're below shutoff voltage
|
// automatic control or not, check if we're below shutoff voltage
|
||||||
if pl_state.battery_voltage < access_config().shutoff_voltage {
|
if pl_state.battery_voltage < access_config().shutoff_voltage {
|
||||||
if let Some(low_voltage_time) = self.voltage_low {
|
self.voltage_low += 1;
|
||||||
// if we've been below shutoff for long enough, stop charging
|
if (self.voltage_low * access_config().charge_rate_update_interval_seconds)
|
||||||
if Instant::now().duration_since(low_voltage_time)
|
>= access_config().shutoff_voltage_time_seconds
|
||||||
>= Duration::from_secs(
|
|
||||||
access_config().shutoff_voltage_time_seconds,
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return Some(InterfaceRequest::StopCharge);
|
return Some(InterfaceRequest::StopCharge);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.voltage_low = Some(Instant::now());
|
self.voltage_low = 0;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.voltage_low = None;
|
|
||||||
if self.tcrc_state.read().is_ok_and(|v| v.control_enable) {
|
if self.tcrc_state.read().is_ok_and(|v| v.control_enable) {
|
||||||
return get_control(&pl_state, &charge_state);
|
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.);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue