voltage as prometheus gauge
This commit is contained in:
parent
14a3b3132c
commit
d555c60922
81
Cargo.lock
generated
81
Cargo.lock
generated
|
@ -972,6 +972,16 @@ version = "0.1.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
|
||||
|
||||
[[package]]
|
||||
name = "io-kit-sys"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4769cb30e5dcf1710fc6730d3e94f78c47723a014a567de385e113c737394640"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"mach2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.9.0"
|
||||
|
@ -1022,6 +1032,26 @@ version = "0.2.151"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
|
||||
[[package]]
|
||||
name = "libudev"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78b324152da65df7bb95acfcaab55e3097ceaab02fb19b228a9eb74d55f135e0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libudev-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libudev-sys"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.12"
|
||||
|
@ -1059,6 +1089,15 @@ dependencies = [
|
|||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mach2"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
|
@ -1215,6 +1254,17 @@ dependencies = [
|
|||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.26.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
|
@ -1970,6 +2020,25 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serialport"
|
||||
version = "4.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"cfg-if",
|
||||
"core-foundation-sys",
|
||||
"io-kit-sys",
|
||||
"libudev",
|
||||
"mach2",
|
||||
"nix",
|
||||
"regex",
|
||||
"scopeguard",
|
||||
"unescaper",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
|
@ -2193,7 +2262,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tesla-charge-controller"
|
||||
version = "0.1.8-prerelease"
|
||||
version = "0.1.8"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-channel",
|
||||
|
@ -2208,6 +2277,7 @@ dependencies = [
|
|||
"rocket",
|
||||
"ron",
|
||||
"serde",
|
||||
"serialport",
|
||||
"teslatte",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
|
@ -2529,6 +2599,15 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unescaper"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8f0f68e58d297ba8b22b8b5a96a87b863ba6bb46aaf51e19a4b02c5a6dd5b7f"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.14"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "tesla-charge-controller"
|
||||
version = "0.1.8-prerelease"
|
||||
version = "0.1.8"
|
||||
edition = "2021"
|
||||
license = "MITNFA"
|
||||
description = "Controls Tesla charge rate based on solar charge data"
|
||||
|
@ -29,3 +29,4 @@ metrics-prometheus = "0.6.0"
|
|||
prometheus = "0.13"
|
||||
env_logger = "0.10"
|
||||
log = "0.4"
|
||||
serialport = "4.3"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use anyhow::{Context, Result};
|
||||
use metrics::{describe_gauge, gauge, Gauge, Unit};
|
||||
use metrics_prometheus::Recorder;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
|
@ -25,9 +24,7 @@ struct Metrics {
|
|||
}
|
||||
|
||||
impl Metrics {
|
||||
fn new() -> (Self, Recorder) {
|
||||
let recorder = metrics_prometheus::install();
|
||||
|
||||
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");
|
||||
|
@ -41,17 +38,14 @@ impl Metrics {
|
|||
describe_gauge!("tesla_battery_heater", "Battery heater");
|
||||
let battery_heater = gauge!("tesla_battery_heater");
|
||||
|
||||
(
|
||||
Self {
|
||||
battery_level,
|
||||
charge_rate,
|
||||
charge_request,
|
||||
inside_temp,
|
||||
outside_temp,
|
||||
battery_heater,
|
||||
},
|
||||
recorder,
|
||||
)
|
||||
Self {
|
||||
battery_level,
|
||||
charge_rate,
|
||||
charge_request,
|
||||
inside_temp,
|
||||
outside_temp,
|
||||
battery_heater,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,7 +91,7 @@ impl TeslaInterface {
|
|||
.next()
|
||||
.context("No vehicles attached to account!")?;
|
||||
|
||||
let (metrics, _recorder) = Metrics::new();
|
||||
let metrics = Metrics::new();
|
||||
|
||||
let interface = Self {
|
||||
state: Arc::new(RwLock::new(Default::default())),
|
||||
|
|
|
@ -8,6 +8,8 @@ use crate::types::Coords;
|
|||
pub struct Config {
|
||||
pub watch_interval: Duration,
|
||||
pub coords: Coords,
|
||||
pub serial_port: String,
|
||||
pub baud_rate: u32,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
|
@ -18,6 +20,8 @@ impl Default for Config {
|
|||
latitude: 0.,
|
||||
longitude: 0.,
|
||||
},
|
||||
serial_port: String::from("/dev/ttyUSB0"),
|
||||
baud_rate: 9600,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
21
src/main.rs
21
src/main.rs
|
@ -5,6 +5,7 @@ extern crate rocket;
|
|||
|
||||
use api_interface::TeslaInterface;
|
||||
use clap::{Parser, Subcommand};
|
||||
use pl_interface::Pli;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::config::Config;
|
||||
|
@ -12,6 +13,7 @@ use crate::config::Config;
|
|||
mod api_interface;
|
||||
mod config;
|
||||
mod errors;
|
||||
mod pl_interface;
|
||||
mod server;
|
||||
mod types;
|
||||
|
||||
|
@ -40,6 +42,8 @@ async fn main() {
|
|||
let auth_path = args.config_dir.join("auth");
|
||||
let config_path = args.config_dir.join("config");
|
||||
|
||||
let _recorder = metrics_prometheus::install();
|
||||
|
||||
match args.command {
|
||||
Commands::GenerateConfig => {
|
||||
println!(
|
||||
|
@ -56,7 +60,7 @@ async fn main() {
|
|||
let (api_requests, receiver) = async_channel::unbounded();
|
||||
|
||||
let server_handle = server::launch_server(server::ServerState {
|
||||
config,
|
||||
config: config.clone(),
|
||||
state: interface.state.clone(),
|
||||
api_requests,
|
||||
});
|
||||
|
@ -76,6 +80,21 @@ async fn main() {
|
|||
}
|
||||
});
|
||||
|
||||
// try to spawn the pli loop
|
||||
match Pli::new(config.serial_port, config.baud_rate) {
|
||||
Ok(mut pli) => {
|
||||
tokio::task::spawn(async move {
|
||||
let mut interval =
|
||||
tokio::time::interval(std::time::Duration::from_secs(30));
|
||||
loop {
|
||||
interval.tick().await;
|
||||
pli.refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
Err(e) => log::error!("Error connecting to serial device for PLI: {e:?}"),
|
||||
}
|
||||
|
||||
server_handle.await;
|
||||
}
|
||||
Err(e) => error!("{}", e.error_string()),
|
||||
|
|
55
src/pl_interface.rs
Normal file
55
src/pl_interface.rs
Normal file
|
@ -0,0 +1,55 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use metrics::{describe_gauge, gauge, Gauge};
|
||||
use serialport::SerialPort;
|
||||
|
||||
pub struct Pli {
|
||||
port: Box<dyn SerialPort>,
|
||||
voltage_gauge: Gauge,
|
||||
}
|
||||
|
||||
impl Pli {
|
||||
pub fn new(serial_port: String, baud_rate: u32) -> anyhow::Result<Self> {
|
||||
let port = serialport::new(serial_port, baud_rate)
|
||||
.timeout(Duration::from_millis(250))
|
||||
.open()?;
|
||||
|
||||
describe_gauge!("pl_battery_voltage", "Battery voltage");
|
||||
let voltage_gauge = gauge!("pl_battery_voltage");
|
||||
Ok(Self {
|
||||
port,
|
||||
voltage_gauge,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self) {
|
||||
let batv = (self.read_ram(50) as f64) * (4. / 10.);
|
||||
self.voltage_gauge.set(batv);
|
||||
}
|
||||
|
||||
fn send_command(&mut self, req: [u8; 4]) {
|
||||
self.port
|
||||
.write_all(&req)
|
||||
.expect("failed to write to serial port");
|
||||
}
|
||||
|
||||
fn receive<const LENGTH: usize>(&mut self) -> [u8; LENGTH] {
|
||||
let mut buf = [0; LENGTH];
|
||||
match self.port.read_exact(&mut buf) {
|
||||
Ok(_) => {
|
||||
println!("got buf {buf:?}")
|
||||
}
|
||||
Err(e) => println!("read error: {e:#?}"),
|
||||
}
|
||||
buf
|
||||
}
|
||||
|
||||
fn read_ram(&mut self, address: u8) -> u8 {
|
||||
self.send_command(command(20, address, 0));
|
||||
self.receive::<2>()[1]
|
||||
}
|
||||
}
|
||||
|
||||
fn command(operation: u8, address: u8, data: u8) -> [u8; 4] {
|
||||
[operation, address, data, !operation]
|
||||
}
|
Loading…
Reference in a new issue