diff --git a/Cargo.lock b/Cargo.lock index 458a974..9be0733 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,6 +95,19 @@ version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9" +[[package]] +name = "async-channel" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +dependencies = [ + "concurrent-queue", + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -314,6 +327,15 @@ dependencies = [ "yansi 0.5.1", ] +[[package]] +name = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -384,6 +406,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" +dependencies = [ + "cfg-if", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -490,6 +521,27 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "2.0.1" @@ -1167,6 +1219,12 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1994,6 +2052,7 @@ name = "tesla-charge-controller" version = "0.1.4" dependencies = [ "anyhow", + "async-channel", "chrono", "clap", "include_dir", diff --git a/Cargo.toml b/Cargo.toml index 9bc5cef..4f6203b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,3 +23,4 @@ rocket = { version = "0.5", features = ["json"] } anyhow = "1.0" include_dir = "0.7" chrono = "0.4" +async-channel = "2.1" diff --git a/src/api_interface.rs b/src/api_interface.rs index 67028d7..f337a6b 100644 --- a/src/api_interface.rs +++ b/src/api_interface.rs @@ -27,6 +27,11 @@ struct AuthInfo { refresh_token: Option, } +#[derive(Clone, Copy, Debug)] +pub enum InterfaceRequest { + FlashLights, +} + const REFRESH_INTERVAL: Duration = Duration::from_secs(12 * 60 * 60); impl TeslaInterface { @@ -77,6 +82,14 @@ impl TeslaInterface { self.refresh_state().await; } + pub async fn process_request(&mut self, request: InterfaceRequest) { + match request { + InterfaceRequest::FlashLights => { + let _ = self.api.flash_lights(&self.vehicle.vin).await; + } + } + } + async fn refresh_state(&mut self) { match get_state(&self.api, self.vehicle.id.clone()).await { Ok(new_state) => { diff --git a/src/main.rs b/src/main.rs index 687838b..2efe186 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,16 +51,24 @@ async fn main() { let config: Config = ron::from_str(&std::fs::read_to_string(&config_path).unwrap()).unwrap(); + let (api_requests, receiver) = async_channel::unbounded(); + let server_handle = server::launch_server(server::ServerState { config, state: interface.state.clone(), + api_requests, }); tokio::task::spawn(async move { let mut interval = tokio::time::interval(std::time::Duration::from_secs(120)); loop { - interval.tick().await; - interface.refresh().await; + tokio::select! { + _ = interval.tick() => interface.refresh().await, + message = receiver.recv() => match message { + Ok(message) => interface.process_request(message).await, + Err(e) => eprintln!("Error on receive channel: {e:#?}") + } + } } }); diff --git a/src/server/mod.rs b/src/server/mod.rs index 0007307..a604eb0 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,5 +1,6 @@ use std::sync::{Arc, RwLock}; +use async_channel::Sender; use rocket::{ fairing::{Fairing, Info, Kind}, http::Header, @@ -8,6 +9,7 @@ use rocket::{ }; use crate::{ + api_interface::InterfaceRequest, config::Config, types::{CarState, ChargeState}, }; @@ -19,6 +21,7 @@ mod static_handler; pub struct ServerState { pub config: Config, pub state: Arc>, + pub api_requests: Sender, } pub async fn launch_server(state: ServerState) { @@ -55,14 +58,7 @@ async fn charge_state(state: &State) -> Option> { #[post("/flash")] async fn flash(state: &State) { - state.flash().await; -} - -impl ServerState { - async fn flash(&self) { - println!("stubbed flash function"); - // let _ = self.auth.api().flash_lights(&self.vehicle.vin).await; - } + let _ = state.api_requests.send(InterfaceRequest::FlashLights).await; } pub struct Cors;