gauge revamp... fingers crossed
All checks were successful
Build .deb on release / Build-Deb (push) Successful in 1m52s
All checks were successful
Build .deb on release / Build-Deb (push) Successful in 1m52s
This commit is contained in:
parent
9d9755515d
commit
65e86c2359
122
Cargo.lock
generated
122
Cargo.lock
generated
|
@ -17,18 +17,6 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.6.10"
|
||||
|
@ -119,12 +107,6 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.5"
|
||||
|
@ -494,17 +476,6 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.18"
|
||||
|
@ -878,15 +849,6 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
|
@ -1091,7 +1053,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.3",
|
||||
"hashbrown",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
@ -1359,45 +1321,6 @@ version = "2.6.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "metrics"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77b9e10a211c839210fd7f99954bda26e5f8e26ec686ad68da6a32df7c80e782"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "metrics-prometheus"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3e1316f9ef05b91f4d0e0a0da5b620ba919d336280b83b36be096b86c030fdd"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"metrics",
|
||||
"metrics-util",
|
||||
"once_cell",
|
||||
"prometheus",
|
||||
"sealed",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "metrics-util"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2670b8badcc285d486261e2e9f1615b506baff91427b61bd336a472b65bbf5ed"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"hashbrown 0.13.1",
|
||||
"metrics",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miette"
|
||||
version = "5.10.0"
|
||||
|
@ -1731,12 +1654,6 @@ version = "0.3.28"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
|
@ -2280,18 +2197,6 @@ dependencies = [
|
|||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sealed"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4a8caec23b7800fb97971a1c6ae365b6239aaeddfb934d6265f8505e795699d"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote 1.0.33",
|
||||
"syn 2.0.43",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.9.2"
|
||||
|
@ -2633,17 +2538,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tesla-charge-controller"
|
||||
version = "1.0.31"
|
||||
version = "1.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"clap 4.4.11",
|
||||
"env_logger 0.10.1",
|
||||
"if_chain",
|
||||
"include_dir",
|
||||
"lazy_static 1.4.0",
|
||||
"libmodbus-rs",
|
||||
"log 0.4.20",
|
||||
"metrics",
|
||||
"metrics-prometheus",
|
||||
"notify-debouncer-mini",
|
||||
"prometheus",
|
||||
"rocket",
|
||||
|
@ -3463,26 +3367,6 @@ dependencies = [
|
|||
"is-terminal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote 1.0.33",
|
||||
"syn 2.0.43",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.7.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "tesla-charge-controller"
|
||||
version = "1.0.31"
|
||||
version = "1.1.0"
|
||||
edition = "2021"
|
||||
license = "MITNFA"
|
||||
description = "Controls Tesla charge rate based on solar charge data"
|
||||
|
@ -23,8 +23,6 @@ thiserror = "1.0"
|
|||
rocket = { version = "0.5", features = ["json"] }
|
||||
include_dir = "0.7"
|
||||
chrono = "0.4"
|
||||
metrics = "0.22"
|
||||
metrics-prometheus = "0.6.0"
|
||||
prometheus = "0.13"
|
||||
env_logger = "0.10"
|
||||
log = "0.4"
|
||||
|
@ -32,3 +30,4 @@ serialport = "4.3"
|
|||
libmodbus-rs = "0.8.3"
|
||||
if_chain = "1.0.2"
|
||||
notify-debouncer-mini = { version = "0.4.1", default-features = false }
|
||||
lazy_static = "1.4"
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
use metrics::{describe_gauge, gauge, Gauge, Label, Unit};
|
||||
use lazy_static::lazy_static;
|
||||
use prometheus::{
|
||||
core::{AtomicI64, GenericGauge},
|
||||
register_gauge, register_int_gauge, register_int_gauge_vec, Gauge, IntGauge, IntGaugeVec,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
|
@ -20,153 +24,82 @@ use crate::{
|
|||
types::{CarState, FromDriveState},
|
||||
};
|
||||
|
||||
struct Metrics {
|
||||
battery_level: Gauge,
|
||||
charge_rate: Gauge,
|
||||
charge_request: Gauge,
|
||||
charge_enable_request: Gauge,
|
||||
charger_connected: Gauge,
|
||||
inside_temp: Gauge,
|
||||
outside_temp: Gauge,
|
||||
battery_heater: Gauge,
|
||||
climate_on: Gauge,
|
||||
preconditioning: Gauge,
|
||||
remote_heater_control_enabled: Gauge,
|
||||
is_auto_conditioning_on: Gauge,
|
||||
driver_temp_setting: Gauge,
|
||||
passenger_temp_setting: Gauge,
|
||||
tesla_online: Gauge,
|
||||
charging_state: ChargingStateGauges,
|
||||
cabin_overheat_protection: CabinOverheatProtectionGauges,
|
||||
hvac_auto: HvacAutoRequestGauges,
|
||||
home: Gauge,
|
||||
sentry_mode: Gauge,
|
||||
sentry_mode_available: Gauge,
|
||||
charger_actual_current: Gauge,
|
||||
charger_phases: Gauge,
|
||||
charger_pilot_current: Gauge,
|
||||
charger_power: Gauge,
|
||||
charger_voltage: Gauge,
|
||||
}
|
||||
|
||||
impl Metrics {
|
||||
fn new() -> Self {
|
||||
describe_gauge!("tesla_battery_level", Unit::Percent, "Battery level");
|
||||
let battery_level = gauge!("tesla_battery_level");
|
||||
describe_gauge!("tesla_charge_rate", "Charge rate");
|
||||
let charge_rate = gauge!("tesla_charge_rate");
|
||||
describe_gauge!("tesla_charge_request", "Requested charge rate");
|
||||
let charge_request = gauge!("tesla_charge_request");
|
||||
describe_gauge!("tesla_charge_enable_request", "Charge enable request");
|
||||
let charge_enable_request = gauge!("tesla_charge_enable_request");
|
||||
describe_gauge!("tesla_charger_connected", "Charger connected");
|
||||
let charger_connected = gauge!("tesla_charger_connected");
|
||||
describe_gauge!("tesla_inside_temp", "Inside temperature");
|
||||
let inside_temp = gauge!("tesla_inside_temp");
|
||||
describe_gauge!("tesla_outside_temp", "Outside temperature");
|
||||
let outside_temp = gauge!("tesla_outside_temp");
|
||||
describe_gauge!("tesla_battery_heater", "Battery heater");
|
||||
let battery_heater = gauge!("tesla_battery_heater");
|
||||
describe_gauge!("tesla_climate_on", "Climate control");
|
||||
let climate_on = gauge!("tesla_climate_on");
|
||||
describe_gauge!("tesla_preconditioning", "Preconditioning");
|
||||
let preconditioning = gauge!("tesla_preconditioning");
|
||||
describe_gauge!(
|
||||
lazy_static! {
|
||||
pub static ref BATTERY_LEVEL: IntGauge =
|
||||
register_int_gauge!("tesla_battery_level", "Battery level",).unwrap();
|
||||
pub static ref CHARGE_RATE: Gauge =
|
||||
register_gauge!("tesla_charge_rate", "Charge rate",).unwrap();
|
||||
pub static ref CHARGE_REQUEST: IntGauge =
|
||||
register_int_gauge!("tesla_charge_request", "Requested charge rate",).unwrap();
|
||||
pub static ref CHARGE_ENABLE_REQUEST: IntGauge =
|
||||
register_int_gauge!("tesla_charge_enable_request", "Charge enable request",).unwrap();
|
||||
pub static ref CHARGER_CONNECTED: IntGauge =
|
||||
register_int_gauge!("tesla_charger_connected", "Charger connected",).unwrap();
|
||||
pub static ref INSIDE_TEMP: Gauge =
|
||||
register_gauge!("tesla_inside_temp", "Inside temperature",).unwrap();
|
||||
pub static ref OUTSIDE_TEMP: Gauge =
|
||||
register_gauge!("tesla_outside_temp", "Outside temperature",).unwrap();
|
||||
pub static ref BATTERY_HEATER: IntGauge =
|
||||
register_int_gauge!("tesla_battery_heater", "Battery heater",).unwrap();
|
||||
pub static ref CLIMATE_ON: IntGauge =
|
||||
register_int_gauge!("tesla_climate_on", "Climate control",).unwrap();
|
||||
pub static ref PRECONDITIONING: IntGauge =
|
||||
register_int_gauge!("tesla_preconditioning", "Preconditioning",).unwrap();
|
||||
pub static ref REMOTE_HEATER_CONTROL_ENABLED: IntGauge = register_int_gauge!(
|
||||
"tesla_remote_heater_control_enabled",
|
||||
"Remote heater control enabled"
|
||||
);
|
||||
let remote_heater_control_enabled = gauge!("tesla_remote_heater_control_enabled");
|
||||
describe_gauge!("tesla_is_auto_conditioning_on", "Auto conditioning on");
|
||||
let is_auto_conditioning_on = gauge!("tesla_is_auto_conditioning_on");
|
||||
describe_gauge!("tesla_driver_temp_setting", "Driver temp");
|
||||
let driver_temp_setting = gauge!("tesla_driver_temp_setting");
|
||||
describe_gauge!("tesla_passenger_temp_setting", "Passenger temp");
|
||||
let passenger_temp_setting = gauge!("tesla_passenger_temp_setting");
|
||||
describe_gauge!("tesla_online", "Tesla online");
|
||||
let tesla_online = gauge!("tesla_online");
|
||||
describe_gauge!("tesla_charging_state", "Tesla charging state");
|
||||
let charging_state = ChargingStateGauges::new();
|
||||
describe_gauge!(
|
||||
"Remote heater control enabled",
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref IS_AUTO_CONDITIONING_ON: IntGauge =
|
||||
register_int_gauge!("tesla_is_auto_conditioning_on", "Auto conditioning on",).unwrap();
|
||||
pub static ref DRIVER_TEMP_SETTING: Gauge =
|
||||
register_gauge!("tesla_driver_temp_setting", "Driver temp",).unwrap();
|
||||
pub static ref PASSENGER_TEMP_SETTING: Gauge =
|
||||
register_gauge!("tesla_passenger_temp_setting", "Passenger temp",).unwrap();
|
||||
pub static ref TESLA_ONLINE: IntGauge =
|
||||
register_int_gauge!("tesla_online", "Tesla online",).unwrap();
|
||||
pub static ref HOME: IntGauge = register_int_gauge!("tesla_home", "Is home",).unwrap();
|
||||
pub static ref SENTRY_MODE: IntGauge =
|
||||
register_int_gauge!("tesla_sentry_mode", "Sentry mode",).unwrap();
|
||||
pub static ref SENTRY_MODE_AVAILABLE: IntGauge =
|
||||
register_int_gauge!("tesla_sentry_mode_available", "Sentry mode available",).unwrap();
|
||||
pub static ref CHARGER_ACTUAL_CURRENT: IntGauge =
|
||||
register_int_gauge!("tesla_charger_actual_current", "Charger actual current",).unwrap();
|
||||
pub static ref CHARGER_PHASES: IntGauge =
|
||||
register_int_gauge!("tesla_charger_phases", "Charger phases",).unwrap();
|
||||
pub static ref CHARGER_PILOT_CURRENT: IntGauge =
|
||||
register_int_gauge!("tesla_charger_pilot_current", "Charger pilot current",).unwrap();
|
||||
pub static ref CHARGER_POWER: IntGauge =
|
||||
register_int_gauge!("tesla_charger_power", "Charger power",).unwrap();
|
||||
pub static ref CHARGER_VOLTAGE: IntGauge =
|
||||
register_int_gauge!("tesla_charger_voltage", "Charger voltage",).unwrap();
|
||||
pub static ref CHARGING_STATE: IntGaugeVec =
|
||||
register_int_gauge_vec!("tesla_charging_state", "Tesla charging state", &["state"])
|
||||
.unwrap();
|
||||
pub static ref CABIN_OVERHEAT_PROTECTION: IntGaugeVec = register_int_gauge_vec!(
|
||||
"tesla_cabin_overheat_protection_state",
|
||||
"Cabin overheat protection state"
|
||||
);
|
||||
let cabin_overheat_protection = CabinOverheatProtectionGauges::new();
|
||||
describe_gauge!("tesla_hvac_auto_request", "HVAC auto");
|
||||
let hvac_auto = HvacAutoRequestGauges::new();
|
||||
describe_gauge!("tesla_home", "Is home");
|
||||
let home = gauge!("tesla_home");
|
||||
describe_gauge!("tesla_sentry_mode", "Sentry mode");
|
||||
let sentry_mode = gauge!("tesla_sentry_mode");
|
||||
describe_gauge!("tesla_sentry_mode_available", "Sentry mode available");
|
||||
let sentry_mode_available = gauge!("tesla_sentry_mode_available");
|
||||
|
||||
describe_gauge!("tesla_charger_actual_current", "Charger actual current");
|
||||
let charger_actual_current = gauge!("tesla_charger_actual_current");
|
||||
describe_gauge!("tesla_charger_phases", "Charger phases");
|
||||
let charger_phases = gauge!("tesla_charger_phases");
|
||||
describe_gauge!("tesla_charger_pilot_current", "Charger pilot current");
|
||||
let charger_pilot_current = gauge!("tesla_charger_pilot_current");
|
||||
describe_gauge!("tesla_charger_power", "Charger power");
|
||||
let charger_power = gauge!("tesla_charger_power");
|
||||
describe_gauge!("tesla_charger_voltage", "Charger voltage");
|
||||
let charger_voltage = gauge!("tesla_charger_voltage");
|
||||
|
||||
Self {
|
||||
battery_level,
|
||||
charge_rate,
|
||||
charge_request,
|
||||
charge_enable_request,
|
||||
charger_connected,
|
||||
inside_temp,
|
||||
outside_temp,
|
||||
battery_heater,
|
||||
climate_on,
|
||||
preconditioning,
|
||||
remote_heater_control_enabled,
|
||||
is_auto_conditioning_on,
|
||||
driver_temp_setting,
|
||||
passenger_temp_setting,
|
||||
tesla_online,
|
||||
charging_state,
|
||||
cabin_overheat_protection,
|
||||
hvac_auto,
|
||||
home,
|
||||
sentry_mode,
|
||||
sentry_mode_available,
|
||||
charger_actual_current,
|
||||
charger_phases,
|
||||
charger_pilot_current,
|
||||
charger_power,
|
||||
charger_voltage,
|
||||
}
|
||||
}
|
||||
"Cabin overheat protection state",
|
||||
&["state"]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref HVAC_AUTO: IntGaugeVec =
|
||||
register_int_gauge_vec!("tesla_hvac_auto_request", "HVAC auto", &["state"]).unwrap();
|
||||
}
|
||||
|
||||
struct ChargingStateGauges {
|
||||
charging: Gauge,
|
||||
stopped: Gauge,
|
||||
disconnected: Gauge,
|
||||
other: Gauge,
|
||||
charging: GenericGauge<AtomicI64>,
|
||||
stopped: GenericGauge<AtomicI64>,
|
||||
disconnected: GenericGauge<AtomicI64>,
|
||||
other: GenericGauge<AtomicI64>,
|
||||
}
|
||||
|
||||
impl ChargingStateGauges {
|
||||
fn new() -> Self {
|
||||
let charging = gauge!(
|
||||
"tesla_charging_state",
|
||||
vec![Label::new("state", String::from("charging"))]
|
||||
);
|
||||
let stopped = gauge!(
|
||||
"tesla_charging_state",
|
||||
vec![Label::new("state", String::from("stopped"))]
|
||||
);
|
||||
let disconnected = gauge!(
|
||||
"tesla_charging_state",
|
||||
vec![Label::new("state", String::from("disconnected"))]
|
||||
);
|
||||
let other = gauge!(
|
||||
"tesla_charging_state",
|
||||
vec![Label::new("state", String::from("other"))]
|
||||
);
|
||||
let charging = CHARGING_STATE.with_label_values(&["charging"]);
|
||||
let stopped = CHARGING_STATE.with_label_values(&["stopped"]);
|
||||
let disconnected = CHARGING_STATE.with_label_values(&["disconnected"]);
|
||||
let other = CHARGING_STATE.with_label_values(&["other"]);
|
||||
|
||||
Self {
|
||||
charging,
|
||||
stopped,
|
||||
|
@ -178,58 +111,47 @@ impl ChargingStateGauges {
|
|||
fn set(&mut self, state: ChargingState) {
|
||||
match state {
|
||||
ChargingState::Charging => {
|
||||
self.charging.set(1.);
|
||||
self.stopped.set(0.);
|
||||
self.disconnected.set(0.);
|
||||
self.other.set(0.);
|
||||
self.charging.set(1);
|
||||
self.stopped.set(0);
|
||||
self.disconnected.set(0);
|
||||
self.other.set(0);
|
||||
}
|
||||
ChargingState::Stopped => {
|
||||
self.charging.set(0.);
|
||||
self.stopped.set(1.);
|
||||
self.disconnected.set(0.);
|
||||
self.other.set(0.);
|
||||
self.charging.set(0);
|
||||
self.stopped.set(1);
|
||||
self.disconnected.set(0);
|
||||
self.other.set(0);
|
||||
}
|
||||
ChargingState::Disconnected => {
|
||||
self.charging.set(0.);
|
||||
self.stopped.set(0.);
|
||||
self.disconnected.set(1.);
|
||||
self.other.set(0.);
|
||||
self.charging.set(0);
|
||||
self.stopped.set(0);
|
||||
self.disconnected.set(1);
|
||||
self.other.set(0);
|
||||
}
|
||||
ChargingState::Other => {
|
||||
self.charging.set(0.);
|
||||
self.stopped.set(0.);
|
||||
self.disconnected.set(0.);
|
||||
self.other.set(1.);
|
||||
self.charging.set(0);
|
||||
self.stopped.set(0);
|
||||
self.disconnected.set(0);
|
||||
self.other.set(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CabinOverheatProtectionGauges {
|
||||
off: Gauge,
|
||||
on: Gauge,
|
||||
fan_only: Gauge,
|
||||
unknown: Gauge,
|
||||
off: GenericGauge<AtomicI64>,
|
||||
on: GenericGauge<AtomicI64>,
|
||||
fan_only: GenericGauge<AtomicI64>,
|
||||
unknown: GenericGauge<AtomicI64>,
|
||||
}
|
||||
|
||||
impl CabinOverheatProtectionGauges {
|
||||
fn new() -> Self {
|
||||
let off = gauge!(
|
||||
"tesla_cabin_overheat_protection_state",
|
||||
vec![Label::new("state", String::from("off"))]
|
||||
);
|
||||
let on = gauge!(
|
||||
"tesla_cabin_overheat_protection_state",
|
||||
vec![Label::new("state", String::from("on"))]
|
||||
);
|
||||
let fan_only = gauge!(
|
||||
"tesla_cabin_overheat_protection_state",
|
||||
vec![Label::new("state", String::from("fan_only"))]
|
||||
);
|
||||
let unknown = gauge!(
|
||||
"tesla_cabin_overheat_protection_state",
|
||||
vec![Label::new("state", String::from("unknown"))]
|
||||
);
|
||||
let off = CABIN_OVERHEAT_PROTECTION.with_label_values(&["off"]);
|
||||
let on = CABIN_OVERHEAT_PROTECTION.with_label_values(&["on"]);
|
||||
let fan_only = CABIN_OVERHEAT_PROTECTION.with_label_values(&["fan_only"]);
|
||||
let unknown = CABIN_OVERHEAT_PROTECTION.with_label_values(&["unknown"]);
|
||||
|
||||
Self {
|
||||
off,
|
||||
on,
|
||||
|
@ -241,53 +163,45 @@ impl CabinOverheatProtectionGauges {
|
|||
fn set(&mut self, state: CabinOverheatProtection) {
|
||||
match state {
|
||||
CabinOverheatProtection::Off => {
|
||||
self.off.set(1.);
|
||||
self.on.set(0.);
|
||||
self.fan_only.set(0.);
|
||||
self.unknown.set(0.);
|
||||
self.off.set(1);
|
||||
self.on.set(0);
|
||||
self.fan_only.set(0);
|
||||
self.unknown.set(0);
|
||||
}
|
||||
CabinOverheatProtection::On => {
|
||||
self.off.set(0.);
|
||||
self.on.set(1.);
|
||||
self.fan_only.set(0.);
|
||||
self.unknown.set(0.);
|
||||
self.off.set(0);
|
||||
self.on.set(1);
|
||||
self.fan_only.set(0);
|
||||
self.unknown.set(0);
|
||||
}
|
||||
CabinOverheatProtection::FanOnly => {
|
||||
self.off.set(0.);
|
||||
self.on.set(0.);
|
||||
self.fan_only.set(1.);
|
||||
self.unknown.set(0.);
|
||||
self.off.set(0);
|
||||
self.on.set(0);
|
||||
self.fan_only.set(1);
|
||||
self.unknown.set(0);
|
||||
}
|
||||
CabinOverheatProtection::Unknown => {
|
||||
self.off.set(0.);
|
||||
self.on.set(0.);
|
||||
self.fan_only.set(0.);
|
||||
self.unknown.set(1.);
|
||||
self.off.set(0);
|
||||
self.on.set(0);
|
||||
self.fan_only.set(0);
|
||||
self.unknown.set(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct HvacAutoRequestGauges {
|
||||
override_g: Gauge,
|
||||
on: Gauge,
|
||||
unknown: Gauge,
|
||||
override_g: GenericGauge<AtomicI64>,
|
||||
on: GenericGauge<AtomicI64>,
|
||||
unknown: GenericGauge<AtomicI64>,
|
||||
}
|
||||
|
||||
impl HvacAutoRequestGauges {
|
||||
fn new() -> Self {
|
||||
let override_g = gauge!(
|
||||
"tesla_hvac_auto_request",
|
||||
vec![Label::new("state", String::from("override"))]
|
||||
);
|
||||
let on = gauge!(
|
||||
"tesla_hvac_auto_request",
|
||||
vec![Label::new("state", String::from("on"))]
|
||||
);
|
||||
let unknown = gauge!(
|
||||
"tesla_hvac_auto_request",
|
||||
vec![Label::new("state", String::from("unknown"))]
|
||||
);
|
||||
let override_g = HVAC_AUTO.with_label_values(&["override"]);
|
||||
let on = HVAC_AUTO.with_label_values(&["on"]);
|
||||
let unknown = HVAC_AUTO.with_label_values(&["unknown"]);
|
||||
|
||||
Self {
|
||||
override_g,
|
||||
on,
|
||||
|
@ -298,19 +212,19 @@ impl HvacAutoRequestGauges {
|
|||
fn set(&mut self, state: HvacAutoRequest) {
|
||||
match state {
|
||||
HvacAutoRequest::Override => {
|
||||
self.override_g.set(1.);
|
||||
self.on.set(0.);
|
||||
self.unknown.set(0.);
|
||||
self.override_g.set(1);
|
||||
self.on.set(0);
|
||||
self.unknown.set(0);
|
||||
}
|
||||
HvacAutoRequest::On => {
|
||||
self.override_g.set(0.);
|
||||
self.on.set(1.);
|
||||
self.unknown.set(0.);
|
||||
self.override_g.set(0);
|
||||
self.on.set(1);
|
||||
self.unknown.set(0);
|
||||
}
|
||||
HvacAutoRequest::Unknown => {
|
||||
self.override_g.set(0.);
|
||||
self.on.set(0.);
|
||||
self.unknown.set(1.);
|
||||
self.override_g.set(0);
|
||||
self.on.set(0);
|
||||
self.unknown.set(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -322,8 +236,10 @@ pub struct TeslaInterface {
|
|||
vehicle: Box<teslatte::vehicles::VehicleData>,
|
||||
last_refresh: Instant,
|
||||
auth_path: PathBuf,
|
||||
metrics: Metrics,
|
||||
monitored_values: MonitoredValues,
|
||||
charging_state: ChargingStateGauges,
|
||||
cabin_overheat_protection: CabinOverheatProtectionGauges,
|
||||
hvac_auto: HvacAutoRequestGauges,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -366,16 +282,16 @@ impl TeslaInterface {
|
|||
.next()
|
||||
.ok_or(AuthLoadError::NoVehicles)?;
|
||||
|
||||
let metrics = Metrics::new();
|
||||
|
||||
let interface = Self {
|
||||
state: Arc::new(RwLock::new(Default::default())),
|
||||
api,
|
||||
last_refresh,
|
||||
auth_path,
|
||||
vehicle,
|
||||
metrics,
|
||||
monitored_values: Default::default(),
|
||||
charging_state: ChargingStateGauges::new(),
|
||||
cabin_overheat_protection: CabinOverheatProtectionGauges::new(),
|
||||
hvac_auto: HvacAutoRequestGauges::new(),
|
||||
};
|
||||
interface.save_key()?;
|
||||
|
||||
|
@ -423,97 +339,65 @@ impl TeslaInterface {
|
|||
async fn refresh_state(&mut self) {
|
||||
match self.get_state().await {
|
||||
Ok(new_state) => {
|
||||
self.metrics.tesla_online.set(1.);
|
||||
TESLA_ONLINE.set(1);
|
||||
let mut state = self
|
||||
.state
|
||||
.write()
|
||||
.expect("Tesla API state handler panicked!!");
|
||||
|
||||
if let Some(new_charge_state) = new_state.charge_state {
|
||||
self.metrics
|
||||
.battery_level
|
||||
.set(new_charge_state.battery_level as f64);
|
||||
self.metrics.charge_rate.set(new_charge_state.charge_rate);
|
||||
self.metrics
|
||||
.charge_request
|
||||
.set(new_charge_state.charge_current_request as f64);
|
||||
self.metrics
|
||||
.charge_enable_request
|
||||
.set(bf(new_charge_state.charge_enable_request));
|
||||
self.metrics
|
||||
.charger_connected
|
||||
.set(bf(new_charge_state.charger_connected));
|
||||
self.metrics
|
||||
.charging_state
|
||||
.set(new_charge_state.charging_state);
|
||||
BATTERY_LEVEL.set(new_charge_state.battery_level);
|
||||
CHARGE_RATE.set(new_charge_state.charge_rate);
|
||||
CHARGE_REQUEST.set(new_charge_state.charge_current_request);
|
||||
CHARGE_ENABLE_REQUEST.set(bi(new_charge_state.charge_enable_request));
|
||||
CHARGER_CONNECTED.set(bi(new_charge_state.charger_connected));
|
||||
self.charging_state.set(new_charge_state.charging_state);
|
||||
if let Some(v) = new_charge_state.charger_actual_current {
|
||||
self.metrics.charger_actual_current.set(v as f64);
|
||||
CHARGER_ACTUAL_CURRENT.set(v);
|
||||
}
|
||||
if let Some(v) = new_charge_state.charger_phases {
|
||||
self.metrics.charger_phases.set(v as f64);
|
||||
CHARGER_PHASES.set(v);
|
||||
}
|
||||
if let Some(v) = new_charge_state.charger_pilot_current {
|
||||
self.metrics.charger_pilot_current.set(v as f64);
|
||||
CHARGER_PILOT_CURRENT.set(v);
|
||||
}
|
||||
if let Some(v) = new_charge_state.charger_power {
|
||||
self.metrics.charger_power.set(v as f64);
|
||||
CHARGER_POWER.set(v);
|
||||
}
|
||||
if let Some(v) = new_charge_state.charger_voltage {
|
||||
self.metrics.charger_voltage.set(v as f64);
|
||||
CHARGER_VOLTAGE.set(v);
|
||||
}
|
||||
state.charge_state = Some(new_charge_state);
|
||||
}
|
||||
if let Some(new_location_data) = new_state.location_data {
|
||||
self.metrics.home.set(bf(new_location_data.home));
|
||||
HOME.set(bi(new_location_data.home));
|
||||
state.location_data = Some(new_location_data);
|
||||
}
|
||||
if let Some(new_climate_state) = new_state.climate_state {
|
||||
self.metrics.inside_temp.set(new_climate_state.inside_temp);
|
||||
self.metrics
|
||||
.outside_temp
|
||||
.set(new_climate_state.outside_temp);
|
||||
self.metrics
|
||||
.battery_heater
|
||||
.set(bf(new_climate_state.battery_heater));
|
||||
self.metrics
|
||||
.climate_on
|
||||
.set(bf(new_climate_state.climate_on));
|
||||
self.metrics
|
||||
.preconditioning
|
||||
.set(bf(new_climate_state.preconditioning));
|
||||
self.metrics
|
||||
.remote_heater_control_enabled
|
||||
.set(bf(new_climate_state.remote_heater_control_enabled));
|
||||
self.metrics
|
||||
.is_auto_conditioning_on
|
||||
.set(bf(new_climate_state.is_auto_conditioning_on));
|
||||
self.metrics
|
||||
.driver_temp_setting
|
||||
.set(new_climate_state.driver_temp_setting);
|
||||
self.metrics
|
||||
.passenger_temp_setting
|
||||
.set(new_climate_state.passenger_temp_setting);
|
||||
self.metrics
|
||||
.cabin_overheat_protection
|
||||
INSIDE_TEMP.set(new_climate_state.inside_temp);
|
||||
OUTSIDE_TEMP.set(new_climate_state.outside_temp);
|
||||
BATTERY_HEATER.set(bi(new_climate_state.battery_heater));
|
||||
CLIMATE_ON.set(bi(new_climate_state.climate_on));
|
||||
PRECONDITIONING.set(bi(new_climate_state.preconditioning));
|
||||
REMOTE_HEATER_CONTROL_ENABLED
|
||||
.set(bi(new_climate_state.remote_heater_control_enabled));
|
||||
IS_AUTO_CONDITIONING_ON.set(bi(new_climate_state.is_auto_conditioning_on));
|
||||
DRIVER_TEMP_SETTING.set(new_climate_state.driver_temp_setting);
|
||||
PASSENGER_TEMP_SETTING.set(new_climate_state.passenger_temp_setting);
|
||||
self.cabin_overheat_protection
|
||||
.set(new_climate_state.cabin_overheat_protection);
|
||||
self.metrics
|
||||
.hvac_auto
|
||||
.set(new_climate_state.hvac_auto_request);
|
||||
self.hvac_auto.set(new_climate_state.hvac_auto_request);
|
||||
|
||||
state.climate_state = Some(new_climate_state);
|
||||
}
|
||||
if let Some(new_vehicle_state) = new_state.vehicle_state {
|
||||
self.metrics
|
||||
.sentry_mode
|
||||
.set(obf(new_vehicle_state.sentry_mode));
|
||||
self.metrics
|
||||
.sentry_mode_available
|
||||
.set(obf(new_vehicle_state.sentry_mode_available));
|
||||
SENTRY_MODE.set(obi(new_vehicle_state.sentry_mode));
|
||||
SENTRY_MODE_AVAILABLE.set(obi(new_vehicle_state.sentry_mode_available));
|
||||
state.vehicle_state = Some(new_vehicle_state);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
self.metrics.tesla_online.set(0.);
|
||||
TESLA_ONLINE.set(0);
|
||||
match e {
|
||||
teslatte::error::TeslatteError::DecodeJsonError {
|
||||
source,
|
||||
|
@ -616,14 +500,14 @@ impl TeslaInterface {
|
|||
}
|
||||
}
|
||||
|
||||
fn bf(value: bool) -> f64 {
|
||||
fn bi(value: bool) -> i64 {
|
||||
if value {
|
||||
1.0
|
||||
1
|
||||
} else {
|
||||
0.0
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
fn obf(value: Option<bool>) -> f64 {
|
||||
value.map_or(-1., bf)
|
||||
fn obi(value: Option<bool>) -> i64 {
|
||||
value.map_or(-1, bi)
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
pub const CHARGE_CONTROLLER_LABEL: &str = "charge_controller";
|
||||
pub const PL_LABEL: &str = "pl_device";
|
||||
pub const TRISTAR_LABEL: &str = "tristar_device";
|
||||
|
||||
pub const BATTERY_VOLTAGE: &str = "battery_voltage";
|
||||
pub const TARGET_VOLTAGE: &str = "target_voltage";
|
||||
pub const INPUT_CURRENT: &str = "input_current";
|
||||
pub const CHARGE_STATE: &str = "charge_state";
|
||||
pub const BATTERY_TEMP: &str = "battery_temp";
|
||||
|
||||
pub const PL_DUTY_CYCLE: &str = "pl_duty_cycle";
|
||||
pub const PL_LOAD_CURRENT: &str = "pl_internal_load_current";
|
||||
|
||||
pub const TRISTAR_INPUT_VOLTAGE: &str = "tristar_input_voltage";
|
||||
pub const TRISTAR_CHARGE_CURRENT: &str = "tristar_charge_current";
|
||||
pub const TRISTAR_POWER_OUT: &str = "tristar_power_out";
|
||||
pub const TRISTAR_POWER_IN: &str = "tristar_power_in";
|
||||
pub const TRISTAR_MAX_ARRAY_POWER: &str = "tristar_max_array_power";
|
||||
pub const TRISTAR_MAX_ARRAY_VOLTAGE: &str = "tristar_max_array_voltage";
|
||||
pub const TRISTAR_OPEN_CIRCUIT_VOLTAGE: &str = "tristar_open_circuit_voltage";
|
70
src/charge_controllers/gauges.rs
Normal file
70
src/charge_controllers/gauges.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use super::{CHARGE_CONTROLLER_LABEL, PL_LABEL, TRISTAR_LABEL};
|
||||
use lazy_static::lazy_static;
|
||||
use prometheus::{register_gauge_vec, register_int_gauge_vec, GaugeVec, IntGaugeVec};
|
||||
|
||||
lazy_static! {
|
||||
pub static ref BATTERY_VOLTAGE: GaugeVec = register_gauge_vec!(
|
||||
"battery_voltage",
|
||||
"Battery voltage",
|
||||
&[CHARGE_CONTROLLER_LABEL]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref TARGET_VOLTAGE: GaugeVec = register_gauge_vec!(
|
||||
"target_voltage",
|
||||
"Target voltage",
|
||||
&[CHARGE_CONTROLLER_LABEL]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref INPUT_CURRENT: GaugeVec = register_gauge_vec!(
|
||||
"input_current",
|
||||
"Internal charge current",
|
||||
&[CHARGE_CONTROLLER_LABEL]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref CHARGE_STATE: IntGaugeVec = register_int_gauge_vec!(
|
||||
"charge_state",
|
||||
"Regulator state",
|
||||
&[CHARGE_CONTROLLER_LABEL, "state"]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref BATTERY_TEMP: GaugeVec = register_gauge_vec!(
|
||||
"battery_temp",
|
||||
"Battery temperature",
|
||||
&[CHARGE_CONTROLLER_LABEL]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref PL_DUTY_CYCLE: GaugeVec =
|
||||
register_gauge_vec!("pl_duty_cycle", "Duty cycle", &[PL_LABEL]).unwrap();
|
||||
pub static ref PL_LOAD_CURRENT: GaugeVec = register_gauge_vec!(
|
||||
"pl_internal_load_current",
|
||||
"Internal load current",
|
||||
&[PL_LABEL]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref TRISTAR_INPUT_VOLTAGE: GaugeVec =
|
||||
register_gauge_vec!("tristar_input_voltage", "Input voltage", &[TRISTAR_LABEL]).unwrap();
|
||||
pub static ref TRISTAR_CHARGE_CURRENT: GaugeVec =
|
||||
register_gauge_vec!("tristar_charge_current", "Charge current", &[TRISTAR_LABEL]).unwrap();
|
||||
pub static ref TRISTAR_POWER_OUT: GaugeVec =
|
||||
register_gauge_vec!("tristar_power_out", "Power out", &[TRISTAR_LABEL]).unwrap();
|
||||
pub static ref TRISTAR_POWER_IN: GaugeVec =
|
||||
register_gauge_vec!("tristar_power_in", "Power in", &[TRISTAR_LABEL]).unwrap();
|
||||
pub static ref TRISTAR_MAX_ARRAY_POWER: GaugeVec = register_gauge_vec!(
|
||||
"tristar_max_array_power",
|
||||
"Maximum array power",
|
||||
&[TRISTAR_LABEL]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref TRISTAR_MAX_ARRAY_VOLTAGE: GaugeVec = register_gauge_vec!(
|
||||
"tristar_max_array_voltage",
|
||||
"Maximum array voltage",
|
||||
&[TRISTAR_LABEL]
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref TRISTAR_OPEN_CIRCUIT_VOLTAGE: GaugeVec = register_gauge_vec!(
|
||||
"tristar_open_circuit_voltage",
|
||||
"Open circuit voltage",
|
||||
&[TRISTAR_LABEL]
|
||||
)
|
||||
.unwrap();
|
||||
}
|
|
@ -1,54 +1,7 @@
|
|||
use std::sync::OnceLock;
|
||||
|
||||
use metrics::{describe_gauge, Unit};
|
||||
|
||||
mod gauge_names;
|
||||
pub mod gauges;
|
||||
pub mod pl;
|
||||
pub mod tristar;
|
||||
|
||||
static HAS_REGISTERED_SHARED: OnceLock<()> = OnceLock::new();
|
||||
static HAS_REGISTERED_PL: OnceLock<()> = OnceLock::new();
|
||||
static HAS_REGISTERED_TRISTAR: OnceLock<()> = OnceLock::new();
|
||||
|
||||
fn register_metrics() {
|
||||
if HAS_REGISTERED_SHARED.get().is_none() {
|
||||
describe_gauge!(gauge_names::BATTERY_VOLTAGE, "Battery voltage");
|
||||
describe_gauge!(gauge_names::TARGET_VOLTAGE, "Target voltage");
|
||||
describe_gauge!(gauge_names::INPUT_CURRENT, "Internal charge current");
|
||||
describe_gauge!(gauge_names::CHARGE_STATE, "Regulator state");
|
||||
describe_gauge!(gauge_names::BATTERY_TEMP, "Battery temperature");
|
||||
|
||||
HAS_REGISTERED_SHARED.get_or_init(|| ());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_pl_metrics() {
|
||||
register_metrics();
|
||||
if HAS_REGISTERED_PL.get().is_none() {
|
||||
describe_gauge!(gauge_names::PL_DUTY_CYCLE, Unit::Percent, "Duty cycle");
|
||||
describe_gauge!(gauge_names::PL_LOAD_CURRENT, "Internal load current");
|
||||
|
||||
HAS_REGISTERED_PL.get_or_init(|| ());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_tristar_metrics() {
|
||||
register_metrics();
|
||||
if HAS_REGISTERED_TRISTAR.get().is_none() {
|
||||
describe_gauge!(gauge_names::TRISTAR_INPUT_VOLTAGE, "Input voltage");
|
||||
describe_gauge!(gauge_names::TRISTAR_CHARGE_CURRENT, "Charge current");
|
||||
describe_gauge!(gauge_names::TRISTAR_POWER_OUT, "Power out");
|
||||
describe_gauge!(gauge_names::TRISTAR_POWER_IN, "Power in");
|
||||
describe_gauge!(gauge_names::TRISTAR_MAX_ARRAY_POWER, "Maximum array power");
|
||||
describe_gauge!(
|
||||
gauge_names::TRISTAR_MAX_ARRAY_VOLTAGE,
|
||||
"Maximum array voltage"
|
||||
);
|
||||
describe_gauge!(
|
||||
gauge_names::TRISTAR_OPEN_CIRCUIT_VOLTAGE,
|
||||
"Open circuit voltage"
|
||||
);
|
||||
|
||||
HAS_REGISTERED_TRISTAR.get_or_init(|| ());
|
||||
}
|
||||
}
|
||||
pub const CHARGE_CONTROLLER_LABEL: &str = "charge_controller";
|
||||
pub const PL_LABEL: &str = "pl_device";
|
||||
pub const TRISTAR_LABEL: &str = "tristar_device";
|
||||
|
|
|
@ -5,24 +5,18 @@ use std::{
|
|||
};
|
||||
|
||||
use chrono::Timelike;
|
||||
use metrics::{gauge, Gauge, Label};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serialport::SerialPort;
|
||||
|
||||
use crate::errors::{PliError, PrintErrors};
|
||||
|
||||
use super::{gauge_names, register_pl_metrics};
|
||||
use crate::{
|
||||
charge_controllers::gauges::*,
|
||||
errors::{PliError, PrintErrors},
|
||||
};
|
||||
|
||||
pub struct Pli {
|
||||
pub state: Arc<RwLock<PlState>>,
|
||||
port_name: String,
|
||||
port: Box<dyn SerialPort>,
|
||||
battery_voltage: Gauge,
|
||||
target_voltage: Gauge,
|
||||
duty_cycle: Gauge,
|
||||
internal_charge_current: Gauge,
|
||||
internal_load_current: Gauge,
|
||||
battery_temp: Gauge,
|
||||
regulator_gauges: RegulatorGauges,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)]
|
||||
|
@ -62,77 +56,36 @@ impl Default for RegulatorState {
|
|||
}
|
||||
}
|
||||
|
||||
struct RegulatorGauges {
|
||||
boost: Gauge,
|
||||
equalise: Gauge,
|
||||
absorption: Gauge,
|
||||
float: Gauge,
|
||||
}
|
||||
fn set_regulator_gauges(state: &RegulatorState, label: &str) {
|
||||
let boost = CHARGE_STATE.with_label_values(&[label, "boost"]);
|
||||
let equalise = CHARGE_STATE.with_label_values(&[label, "equalise"]);
|
||||
let absorption = CHARGE_STATE.with_label_values(&[label, "absorption"]);
|
||||
let float = CHARGE_STATE.with_label_values(&[label, "float"]);
|
||||
|
||||
impl RegulatorGauges {
|
||||
fn new(labels: Vec<Label>) -> Self {
|
||||
let boost = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("boost"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let equalise = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("equalise"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let absorption = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("absorption"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let float = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[labels, vec![Label::new("state", String::from("float"))]].concat()
|
||||
);
|
||||
Self {
|
||||
boost,
|
||||
equalise,
|
||||
absorption,
|
||||
float,
|
||||
}
|
||||
}
|
||||
|
||||
fn set(&mut self, state: &RegulatorState) {
|
||||
match state {
|
||||
RegulatorState::Boost => {
|
||||
self.boost.set(1.);
|
||||
self.equalise.set(0.);
|
||||
self.absorption.set(0.);
|
||||
self.float.set(0.);
|
||||
boost.set(1);
|
||||
equalise.set(0);
|
||||
absorption.set(0);
|
||||
float.set(0);
|
||||
}
|
||||
RegulatorState::Equalise => {
|
||||
self.boost.set(0.);
|
||||
self.equalise.set(1.);
|
||||
self.absorption.set(0.);
|
||||
self.float.set(0.);
|
||||
boost.set(0);
|
||||
equalise.set(1);
|
||||
absorption.set(0);
|
||||
float.set(0);
|
||||
}
|
||||
RegulatorState::Absorption => {
|
||||
self.boost.set(0.);
|
||||
self.equalise.set(0.);
|
||||
self.absorption.set(1.);
|
||||
self.float.set(0.);
|
||||
boost.set(0);
|
||||
equalise.set(0);
|
||||
absorption.set(1);
|
||||
float.set(0);
|
||||
}
|
||||
RegulatorState::Float => {
|
||||
self.boost.set(0.);
|
||||
self.equalise.set(0.);
|
||||
self.absorption.set(0.);
|
||||
self.float.set(1.);
|
||||
}
|
||||
boost.set(0);
|
||||
equalise.set(0);
|
||||
absorption.set(0);
|
||||
float.set(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,44 +107,35 @@ impl Pli {
|
|||
.timeout(Duration::from_millis(timeout))
|
||||
.open()?;
|
||||
|
||||
register_pl_metrics();
|
||||
|
||||
let device_labels = vec![
|
||||
Label::new(gauge_names::CHARGE_CONTROLLER_LABEL, serial_port.clone()),
|
||||
Label::new(gauge_names::PL_LABEL, serial_port),
|
||||
];
|
||||
|
||||
let battery_voltage = gauge!(gauge_names::BATTERY_VOLTAGE, device_labels.clone());
|
||||
let target_voltage = gauge!(gauge_names::TARGET_VOLTAGE, device_labels.clone());
|
||||
let duty_cycle = gauge!(gauge_names::PL_DUTY_CYCLE, device_labels.clone());
|
||||
let internal_charge_current = gauge!(gauge_names::INPUT_CURRENT, device_labels.clone());
|
||||
let internal_load_current = gauge!(gauge_names::PL_LOAD_CURRENT, device_labels.clone());
|
||||
let battery_temp = gauge!(gauge_names::BATTERY_TEMP, device_labels.clone());
|
||||
|
||||
Ok(Self {
|
||||
state: Arc::new(RwLock::new(Default::default())),
|
||||
port_name: serial_port,
|
||||
port,
|
||||
battery_voltage,
|
||||
target_voltage,
|
||||
duty_cycle,
|
||||
internal_charge_current,
|
||||
internal_load_current,
|
||||
battery_temp,
|
||||
regulator_gauges: RegulatorGauges::new(device_labels),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self) {
|
||||
if let Some(new_state) = self.read_state().some_or_print_with("reading pl state") {
|
||||
self.battery_voltage.set(new_state.battery_voltage);
|
||||
self.target_voltage.set(new_state.target_voltage);
|
||||
self.duty_cycle.set(new_state.duty_cycle);
|
||||
self.internal_charge_current
|
||||
BATTERY_VOLTAGE
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.battery_voltage);
|
||||
TARGET_VOLTAGE
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.target_voltage);
|
||||
PL_DUTY_CYCLE
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.duty_cycle);
|
||||
INPUT_CURRENT
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.internal_charge_current);
|
||||
self.internal_load_current
|
||||
PL_LOAD_CURRENT
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.internal_load_current);
|
||||
self.battery_temp.set(new_state.battery_temp);
|
||||
self.regulator_gauges.set(&new_state.regulator_state);
|
||||
BATTERY_TEMP
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.battery_temp);
|
||||
|
||||
set_regulator_gauges(&new_state.regulator_state, &self.port_name);
|
||||
|
||||
*self.state.write().expect("PLI state handler panicked!!") = new_state;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
use libmodbus_rs::{Modbus, ModbusClient, ModbusRTU};
|
||||
use metrics::{gauge, Gauge, Label};
|
||||
use prometheus::core::{AtomicI64, GenericGauge};
|
||||
|
||||
use crate::errors::TristarError;
|
||||
|
||||
use super::{gauge_names, register_tristar_metrics};
|
||||
use crate::{charge_controllers::gauges::*, errors::TristarError};
|
||||
|
||||
const DEVICE_ID: u8 = 0x01;
|
||||
const RAM_DATA_SIZE: u16 = 0x005B;
|
||||
|
@ -42,70 +40,10 @@ impl Scaling {
|
|||
|
||||
pub struct Tristar {
|
||||
state: TristarState,
|
||||
gauges: TristarGauges,
|
||||
port_name: String,
|
||||
modbus: Modbus,
|
||||
data_in: [u16; RAM_ARRAY_SIZE],
|
||||
}
|
||||
|
||||
pub struct TristarGauges {
|
||||
battery_voltage: Gauge,
|
||||
target_voltage: Gauge,
|
||||
input_current: Gauge,
|
||||
battery_temp: Gauge,
|
||||
charge_state: ChargeStateGauges,
|
||||
tristar_input_voltage: Gauge,
|
||||
tristar_charge_current: Gauge,
|
||||
tristar_power_out: Gauge,
|
||||
tristar_power_in: Gauge,
|
||||
tristar_max_array_power: Gauge,
|
||||
tristar_max_array_voltage: Gauge,
|
||||
tristar_open_circuit_voltage: Gauge,
|
||||
}
|
||||
|
||||
impl TristarGauges {
|
||||
fn new(serial_port: String) -> Self {
|
||||
let device_labels = vec![
|
||||
Label::new(gauge_names::CHARGE_CONTROLLER_LABEL, serial_port.clone()),
|
||||
Label::new(gauge_names::TRISTAR_LABEL, serial_port),
|
||||
];
|
||||
|
||||
let battery_voltage = gauge!(gauge_names::BATTERY_VOLTAGE, device_labels.clone());
|
||||
let target_voltage = gauge!(gauge_names::TARGET_VOLTAGE, device_labels.clone());
|
||||
let input_current = gauge!(gauge_names::INPUT_CURRENT, device_labels.clone());
|
||||
let battery_temp = gauge!(gauge_names::BATTERY_TEMP, device_labels.clone());
|
||||
let charge_state = ChargeStateGauges::new(device_labels.clone());
|
||||
let tristar_input_voltage =
|
||||
gauge!(gauge_names::TRISTAR_INPUT_VOLTAGE, device_labels.clone());
|
||||
let tristar_charge_current =
|
||||
gauge!(gauge_names::TRISTAR_CHARGE_CURRENT, device_labels.clone());
|
||||
let tristar_power_out = gauge!(gauge_names::TRISTAR_POWER_OUT, device_labels.clone());
|
||||
let tristar_power_in = gauge!(gauge_names::TRISTAR_POWER_IN, device_labels.clone());
|
||||
let tristar_max_array_power =
|
||||
gauge!(gauge_names::TRISTAR_MAX_ARRAY_POWER, device_labels.clone());
|
||||
let tristar_max_array_voltage = gauge!(
|
||||
gauge_names::TRISTAR_MAX_ARRAY_VOLTAGE,
|
||||
device_labels.clone()
|
||||
);
|
||||
let tristar_open_circuit_voltage = gauge!(
|
||||
gauge_names::TRISTAR_OPEN_CIRCUIT_VOLTAGE,
|
||||
device_labels.clone()
|
||||
);
|
||||
|
||||
Self {
|
||||
battery_voltage,
|
||||
target_voltage,
|
||||
input_current,
|
||||
battery_temp,
|
||||
charge_state,
|
||||
tristar_input_voltage,
|
||||
tristar_charge_current,
|
||||
tristar_power_out,
|
||||
tristar_power_in,
|
||||
tristar_max_array_power,
|
||||
tristar_max_array_voltage,
|
||||
tristar_open_circuit_voltage,
|
||||
}
|
||||
}
|
||||
charge_state_gauges: ChargeStateGauges,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy)]
|
||||
|
@ -183,109 +121,32 @@ impl From<u16> for ChargeState {
|
|||
}
|
||||
|
||||
struct ChargeStateGauges {
|
||||
start: Gauge,
|
||||
night_check: Gauge,
|
||||
disconnect: Gauge,
|
||||
night: Gauge,
|
||||
fault: Gauge,
|
||||
mppt: Gauge,
|
||||
absorption: Gauge,
|
||||
float: Gauge,
|
||||
equalize: Gauge,
|
||||
slave: Gauge,
|
||||
unknown: Gauge,
|
||||
start: GenericGauge<AtomicI64>,
|
||||
night_check: GenericGauge<AtomicI64>,
|
||||
disconnect: GenericGauge<AtomicI64>,
|
||||
night: GenericGauge<AtomicI64>,
|
||||
fault: GenericGauge<AtomicI64>,
|
||||
mppt: GenericGauge<AtomicI64>,
|
||||
absorption: GenericGauge<AtomicI64>,
|
||||
float: GenericGauge<AtomicI64>,
|
||||
equalize: GenericGauge<AtomicI64>,
|
||||
slave: GenericGauge<AtomicI64>,
|
||||
unknown: GenericGauge<AtomicI64>,
|
||||
}
|
||||
|
||||
impl ChargeStateGauges {
|
||||
fn new(labels: Vec<Label>) -> Self {
|
||||
let start = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("start"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let night_check = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("night_check"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let disconnect = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("disconnect"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let night = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("night"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let fault = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("fault"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let mppt = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("mppt"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let absorption = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("absorption"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let float = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("float"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let equalize = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("equalize"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let slave = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("slave"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
let unknown = gauge!(
|
||||
gauge_names::CHARGE_STATE,
|
||||
[
|
||||
labels.clone(),
|
||||
vec![Label::new("state", String::from("unknown"))]
|
||||
]
|
||||
.concat()
|
||||
);
|
||||
fn new(label: &str) -> Self {
|
||||
let start = CHARGE_STATE.with_label_values(&[label, "start"]);
|
||||
let night_check = CHARGE_STATE.with_label_values(&[label, "night_check"]);
|
||||
let disconnect = CHARGE_STATE.with_label_values(&[label, "disconnect"]);
|
||||
let night = CHARGE_STATE.with_label_values(&[label, "night"]);
|
||||
let fault = CHARGE_STATE.with_label_values(&[label, "fault"]);
|
||||
let mppt = CHARGE_STATE.with_label_values(&[label, "mppt"]);
|
||||
let absorption = CHARGE_STATE.with_label_values(&[label, "absorption"]);
|
||||
let float = CHARGE_STATE.with_label_values(&[label, "float"]);
|
||||
let equalize = CHARGE_STATE.with_label_values(&[label, "equalize"]);
|
||||
let slave = CHARGE_STATE.with_label_values(&[label, "slave"]);
|
||||
let unknown = CHARGE_STATE.with_label_values(&[label, "unknown"]);
|
||||
Self {
|
||||
start,
|
||||
night_check,
|
||||
|
@ -302,64 +163,64 @@ impl ChargeStateGauges {
|
|||
}
|
||||
|
||||
fn zero_all(&mut self) {
|
||||
self.start.set(0.);
|
||||
self.night_check.set(0.);
|
||||
self.disconnect.set(0.);
|
||||
self.night.set(0.);
|
||||
self.fault.set(0.);
|
||||
self.mppt.set(0.);
|
||||
self.absorption.set(0.);
|
||||
self.float.set(0.);
|
||||
self.equalize.set(0.);
|
||||
self.slave.set(0.);
|
||||
self.unknown.set(0.);
|
||||
self.start.set(0);
|
||||
self.night_check.set(0);
|
||||
self.disconnect.set(0);
|
||||
self.night.set(0);
|
||||
self.fault.set(0);
|
||||
self.mppt.set(0);
|
||||
self.absorption.set(0);
|
||||
self.float.set(0);
|
||||
self.equalize.set(0);
|
||||
self.slave.set(0);
|
||||
self.unknown.set(0);
|
||||
}
|
||||
|
||||
fn set(&mut self, state: ChargeState) {
|
||||
match state {
|
||||
ChargeState::Start => {
|
||||
self.zero_all();
|
||||
self.start.set(1.);
|
||||
self.start.set(1);
|
||||
}
|
||||
ChargeState::NightCheck => {
|
||||
self.zero_all();
|
||||
self.night_check.set(1.);
|
||||
self.night_check.set(1);
|
||||
}
|
||||
ChargeState::Disconnect => {
|
||||
self.zero_all();
|
||||
self.disconnect.set(1.);
|
||||
self.disconnect.set(1);
|
||||
}
|
||||
ChargeState::Night => {
|
||||
self.zero_all();
|
||||
self.night.set(1.);
|
||||
self.night.set(1);
|
||||
}
|
||||
ChargeState::Fault => {
|
||||
self.zero_all();
|
||||
self.fault.set(1.);
|
||||
self.fault.set(1);
|
||||
}
|
||||
ChargeState::Mppt => {
|
||||
self.zero_all();
|
||||
self.mppt.set(1.);
|
||||
self.mppt.set(1);
|
||||
}
|
||||
ChargeState::Absorption => {
|
||||
self.zero_all();
|
||||
self.absorption.set(1.);
|
||||
self.absorption.set(1);
|
||||
}
|
||||
ChargeState::Float => {
|
||||
self.zero_all();
|
||||
self.float.set(1.);
|
||||
self.float.set(1);
|
||||
}
|
||||
ChargeState::Equalize => {
|
||||
self.zero_all();
|
||||
self.equalize.set(1.);
|
||||
self.equalize.set(1);
|
||||
}
|
||||
ChargeState::Slave => {
|
||||
self.zero_all();
|
||||
self.slave.set(1.);
|
||||
self.slave.set(1);
|
||||
}
|
||||
ChargeState::Unknown => {
|
||||
self.zero_all();
|
||||
self.unknown.set(1.);
|
||||
self.unknown.set(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -373,12 +234,13 @@ impl Tristar {
|
|||
let mut modbus = Modbus::new_rtu(&serial_port, baud_rate, parity, data_bit, stop_bit)?;
|
||||
modbus.set_slave(DEVICE_ID)?;
|
||||
modbus.connect()?;
|
||||
register_tristar_metrics();
|
||||
let charge_state_gauges = ChargeStateGauges::new(&serial_port);
|
||||
Ok(Self {
|
||||
state: Default::default(),
|
||||
gauges: TristarGauges::new(serial_port.clone()),
|
||||
port_name: serial_port,
|
||||
modbus,
|
||||
data_in: [0; RAM_ARRAY_SIZE],
|
||||
charge_state_gauges,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -387,30 +249,41 @@ impl Tristar {
|
|||
.get_data()
|
||||
.map(|scaling| TristarState::from_ram(scaling, &self.data_in))
|
||||
{
|
||||
self.gauges.battery_voltage.set(new_state.battery_voltage);
|
||||
self.gauges.target_voltage.set(new_state.target_voltage);
|
||||
self.gauges.input_current.set(new_state.input_current);
|
||||
self.gauges.battery_temp.set(new_state.battery_temp as f64);
|
||||
self.gauges.charge_state.set(new_state.charge_state);
|
||||
self.gauges
|
||||
.tristar_input_voltage
|
||||
BATTERY_VOLTAGE
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.battery_voltage);
|
||||
TARGET_VOLTAGE
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.target_voltage);
|
||||
INPUT_CURRENT
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.input_current);
|
||||
BATTERY_TEMP
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.battery_temp.into());
|
||||
TRISTAR_INPUT_VOLTAGE
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.tristar_input_voltage);
|
||||
self.gauges
|
||||
.tristar_charge_current
|
||||
TRISTAR_CHARGE_CURRENT
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.tristar_charge_current);
|
||||
self.gauges
|
||||
.tristar_power_out
|
||||
TRISTAR_POWER_OUT
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.tristar_power_out);
|
||||
self.gauges.tristar_power_in.set(new_state.tristar_power_in);
|
||||
self.gauges
|
||||
.tristar_max_array_power
|
||||
TRISTAR_POWER_IN
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.tristar_power_in);
|
||||
TRISTAR_MAX_ARRAY_POWER
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.tristar_max_array_power);
|
||||
self.gauges
|
||||
.tristar_max_array_voltage
|
||||
TRISTAR_MAX_ARRAY_VOLTAGE
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.tristar_max_array_voltage);
|
||||
self.gauges
|
||||
.tristar_open_circuit_voltage
|
||||
TRISTAR_OPEN_CIRCUIT_VOLTAGE
|
||||
.with_label_values(&[&self.port_name])
|
||||
.set(new_state.tristar_open_circuit_voltage);
|
||||
|
||||
self.charge_state_gauges.set(new_state.charge_state);
|
||||
self.state = new_state;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ async fn main() {
|
|||
.init();
|
||||
|
||||
let args = Args::parse();
|
||||
let _recorder = metrics_prometheus::install();
|
||||
|
||||
match args.command {
|
||||
Commands::GenerateConfig => {
|
||||
|
|
|
@ -129,7 +129,7 @@ async fn flash(state: &State<ServerState>, remote_addr: std::net::IpAddr) {
|
|||
async fn disable_control(state: &State<ServerState>, remote_addr: std::net::IpAddr) {
|
||||
log::warn!("disabling control: {remote_addr:?}");
|
||||
match state.tcrc_state.write() {
|
||||
Ok(mut handle) => handle.control_enable = false,
|
||||
Ok(mut handle) => handle.set_control_enable(false),
|
||||
Err(e) => log::error!("Error disabling control: {e:?}"),
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ async fn disable_control(state: &State<ServerState>, remote_addr: std::net::IpAd
|
|||
async fn enable_control(state: &State<ServerState>, remote_addr: std::net::IpAddr) {
|
||||
log::warn!("enabling control: {remote_addr:?}");
|
||||
match state.tcrc_state.write() {
|
||||
Ok(mut handle) => handle.control_enable = true,
|
||||
Ok(mut handle) => handle.set_control_enable(true),
|
||||
Err(e) => log::error!("Error enabling control: {e:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use if_chain::if_chain;
|
||||
use metrics::{describe_gauge, gauge, Gauge};
|
||||
use lazy_static::lazy_static;
|
||||
use prometheus::{register_gauge, register_int_gauge, Gauge, IntGauge};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
|
@ -11,13 +12,34 @@ use crate::{
|
|||
types::{CarState, ChargeState},
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
pub static ref CONTROL_ENABLE_GAUGE: IntGauge =
|
||||
register_int_gauge!("tcrc_control_enable", "Enable Tesla charge rate control",).unwrap();
|
||||
pub static ref PROPORTIONAL_GAUGE: Gauge = register_gauge!(
|
||||
"tcrc_proportional",
|
||||
"Proportional component of requested change to charge rate",
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref DERIVATIVE_GAUGE: Gauge = register_gauge!(
|
||||
"tcrc_derivative",
|
||||
"Derivative component of requested change to charge rate",
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref LOAD_GAUGE: Gauge = register_gauge!(
|
||||
"tcrc_load",
|
||||
"Fudge factor from internal load of requested change to charge rate",
|
||||
)
|
||||
.unwrap();
|
||||
pub static ref CHANGE_REQUEST_GAUGE: Gauge =
|
||||
register_gauge!("tcrc_change_request", "Requested change to charge rate",).unwrap();
|
||||
}
|
||||
|
||||
pub struct TeslaChargeRateController {
|
||||
pub car_state: Arc<RwLock<CarState>>,
|
||||
pub pl_state: Option<Arc<RwLock<PlState>>>,
|
||||
pub tcrc_state: Arc<RwLock<TcrcState>>,
|
||||
pid: PidLoop,
|
||||
voltage_low: u64,
|
||||
control_enable_gauge: Gauge,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -31,6 +53,13 @@ pub struct TcrcState {
|
|||
pub control_enable: bool,
|
||||
}
|
||||
|
||||
impl TcrcState {
|
||||
pub fn set_control_enable(&mut self, to: bool) {
|
||||
self.control_enable = to;
|
||||
CONTROL_ENABLE_GAUGE.set(if to { 1 } else { 0 });
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TcrcState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
@ -41,14 +70,12 @@ impl Default for TcrcState {
|
|||
|
||||
impl TeslaChargeRateController {
|
||||
pub fn new(car_state: Arc<RwLock<CarState>>, pl_state: Option<Arc<RwLock<PlState>>>) -> Self {
|
||||
describe_gauge!("tcrc_control_enable", "Enable Tesla charge rate control");
|
||||
Self {
|
||||
car_state,
|
||||
pl_state,
|
||||
tcrc_state: Default::default(),
|
||||
pid: Default::default(),
|
||||
voltage_low: 0,
|
||||
control_enable_gauge: gauge!("tcrc_control_enable"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,15 +109,13 @@ impl TeslaChargeRateController {
|
|||
self.tcrc_state
|
||||
.write()
|
||||
.expect("failed to write to tcrc state")
|
||||
.control_enable = false;
|
||||
self.control_enable_gauge.set(0.);
|
||||
.set_control_enable(false);
|
||||
}
|
||||
TcrcRequest::EnableAutomaticControl => {
|
||||
self.tcrc_state
|
||||
.write()
|
||||
.expect("failed to write to tcrc state")
|
||||
.control_enable = true;
|
||||
self.control_enable_gauge.set(1.);
|
||||
.set_control_enable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,38 +123,11 @@ impl TeslaChargeRateController {
|
|||
|
||||
struct PidLoop {
|
||||
previous_error: f64,
|
||||
proportional_gauge: Gauge,
|
||||
derivative_gauge: Gauge,
|
||||
load_gauge: Gauge,
|
||||
change_request_gauge: Gauge,
|
||||
}
|
||||
|
||||
impl Default for PidLoop {
|
||||
fn default() -> Self {
|
||||
describe_gauge!(
|
||||
"tcrc_proportional",
|
||||
"Proportional component of requested change to charge rate"
|
||||
);
|
||||
let proportional_gauge = gauge!("tcrc_proportional");
|
||||
describe_gauge!(
|
||||
"tcrc_proportional",
|
||||
"Derivative component of requested change to charge rate"
|
||||
);
|
||||
let derivative_gauge = gauge!("tcrc_derivative");
|
||||
describe_gauge!(
|
||||
"tcrc_load",
|
||||
"Fudge factor from internal load of requested change to charge rate"
|
||||
);
|
||||
let load_gauge = gauge!("tcrc_load");
|
||||
describe_gauge!("tcrc_change_request", "Requested change to charge rate");
|
||||
let change_request_gauge = gauge!("tcrc_change_request");
|
||||
Self {
|
||||
previous_error: 0.,
|
||||
proportional_gauge,
|
||||
derivative_gauge,
|
||||
load_gauge,
|
||||
change_request_gauge,
|
||||
}
|
||||
Self { previous_error: 0. }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,10 +150,10 @@ impl PidLoop {
|
|||
|
||||
let offset = proportional_component + derivative_component + extra_offsets;
|
||||
|
||||
self.proportional_gauge.set(proportional_component);
|
||||
self.derivative_gauge.set(derivative_component);
|
||||
self.load_gauge.set(extra_offsets);
|
||||
self.change_request_gauge.set(offset);
|
||||
PROPORTIONAL_GAUGE.set(proportional_component);
|
||||
DERIVATIVE_GAUGE.set(derivative_component);
|
||||
LOAD_GAUGE.set(extra_offsets);
|
||||
CHANGE_REQUEST_GAUGE.set(offset);
|
||||
|
||||
let new_target = offset + (charge_state.charge_amps as f64);
|
||||
|
||||
|
|
Loading…
Reference in a new issue