diff --git a/src/main.rs b/src/main.rs index 04ecee4..a0a28dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,108 +64,119 @@ async fn main() { let config_path = args.config_dir.join("config.json"); let (config, _config_watcher) = config::init_config(config_path); config::CONFIG.get_or_init(|| RwLock::new(config)); - if let Some(mut interface) = TeslaInterface::load(auth_path) + let interface = TeslaInterface::load(auth_path) .await - .some_or_print_with("loading tesla interface") - { - // build the channel that takes messages from the webserver thread to the api thread - let (api_requests, mut api_receiver) = tokio::sync::mpsc::unbounded_channel(); - // and to the pli thread - let (pli_requests, mut pli_receiver) = tokio::sync::mpsc::unbounded_channel(); - // and to the charge rate controller thread - let (tcrc_requests, mut tcrc_receiver) = tokio::sync::mpsc::unbounded_channel(); - // try to spawn the pli loop - let pli = { - let config = access_config(); - Pli::new( - config.serial_port.clone(), - config.baud_rate, - config.pl_timeout_milliseconds, - ) - }; - let pl_state = match pli { - Ok(mut pli) => { - let pl_state = pli.state.clone(); - tokio::task::spawn(async move { - let mut interval = - tokio::time::interval(std::time::Duration::from_secs( - access_config().pl_watch_interval_seconds, - )); - loop { - tokio::select! { - _ = interval.tick() => pli.refresh(), - message = pli_receiver.recv() => match message { - Some(message) => pli.process_request(message), - None => panic!("PLI send channel dropped") - } + .some_or_print_with("loading tesla interface"); + + // build the channel that takes messages from the webserver thread to the api thread + let (api_requests, mut api_receiver) = tokio::sync::mpsc::unbounded_channel(); + // and to the pli thread + let (pli_requests, mut pli_receiver) = tokio::sync::mpsc::unbounded_channel(); + // and to the charge rate controller thread + let (tcrc_requests, mut tcrc_receiver) = tokio::sync::mpsc::unbounded_channel(); + // try to spawn the pli loop + let pli = { + let config = access_config(); + Pli::new( + config.serial_port.clone(), + config.baud_rate, + config.pl_timeout_milliseconds, + ) + }; + let pl_state = match pli { + Ok(mut pli) => { + let pl_state = pli.state.clone(); + tokio::task::spawn(async move { + let mut interval = tokio::time::interval(std::time::Duration::from_secs( + access_config().pl_watch_interval_seconds, + )); + loop { + tokio::select! { + _ = interval.tick() => pli.refresh(), + message = pli_receiver.recv() => match message { + Some(message) => pli.process_request(message), + None => panic!("PLI send channel dropped") } } - }); - Some(pl_state) - } - Err(e) => { - log::error!("Error connecting to serial device for PLI: {e:?}"); - None - } - }; - let local = tokio::task::LocalSet::new(); - // spawn a loop for each additional charge controller to log - // failed connections will print an error but the program will continue - let _additional_controllers: Vec<_> = access_config() - .additional_charge_controllers - .clone() - .into_iter() - .filter_map(|v| match v { - ChargeControllerConfig::Pl { - serial_port, - baud_rate, - timeout_milliseconds, - watch_interval_seconds, - } => Pli::new(serial_port.clone(), baud_rate, timeout_milliseconds) - .some_or_print_with("Failed to connect to additional PLI") - .map(|mut pli| { - tokio::task::spawn(async move { - let mut interval = tokio::time::interval( - std::time::Duration::from_secs(watch_interval_seconds), - ); - loop { - interval.tick().await; - pli.refresh(); - } - }) - }), - ChargeControllerConfig::Tristar { - serial_port, - baud_rate, - watch_interval_seconds, - } => Tristar::new(serial_port.clone(), baud_rate) - .some_or_print_with("Failed to connect to additional Tristar") - .map(|mut tristar| { - local.spawn_local(async move { - let mut interval = tokio::time::interval( - std::time::Duration::from_secs(watch_interval_seconds), - ); - loop { - interval.tick().await; - tristar.refresh(); - } - }) - }), - }) - .collect(); + } + }); + Some(pl_state) + } + Err(e) => { + log::error!("Error connecting to serial device for PLI: {e:?}"); + None + } + }; + let local = tokio::task::LocalSet::new(); + // spawn a loop for each additional charge controller to log + // failed connections will print an error but the program will continue + let _additional_controllers: Vec<_> = access_config() + .additional_charge_controllers + .clone() + .into_iter() + .filter_map(|v| match v { + ChargeControllerConfig::Pl { + serial_port, + baud_rate, + timeout_milliseconds, + watch_interval_seconds, + } => Pli::new(serial_port.clone(), baud_rate, timeout_milliseconds) + .some_or_print_with("Failed to connect to additional PLI") + .map(|mut pli| { + tokio::task::spawn(async move { + let mut interval = tokio::time::interval( + std::time::Duration::from_secs(watch_interval_seconds), + ); + loop { + interval.tick().await; + pli.refresh(); + } + }) + }), + ChargeControllerConfig::Tristar { + serial_port, + baud_rate, + watch_interval_seconds, + } => Tristar::new(serial_port.clone(), baud_rate) + .some_or_print_with("Failed to connect to additional Tristar") + .map(|mut tristar| { + local.spawn_local(async move { + let mut interval = tokio::time::interval( + std::time::Duration::from_secs(watch_interval_seconds), + ); + loop { + interval.tick().await; + tristar.refresh(); + } + }) + }), + }) + .collect(); - let mut tesla_charge_rate_controller = + let interface_and_tcrc = interface.map(|interface| { + let tcrc = TeslaChargeRateController::new(interface.state.clone(), pl_state.clone()); + (interface, tcrc) + }); + let car_state = interface_and_tcrc + .as_ref() + .map(|(interface, _)| interface.state.clone()) + .unwrap_or_default(); + let tcrc_state = interface_and_tcrc + .as_ref() + .map(|(_, tcrc)| tcrc.tcrc_state.clone()) + .unwrap_or_default(); - let server_handle = server::launch_server(server::ServerState { - car_state: interface.state.clone(), - pl_state, - tcrc_state: tesla_charge_rate_controller.tcrc_state.clone(), - api_requests, - pli_requests, - tcrc_requests, - }); + let server_handle = server::launch_server(server::ServerState { + car_state, + pl_state, + tcrc_state, + api_requests, + pli_requests, + tcrc_requests, + }); + if let Some((mut interface, mut tesla_charge_rate_controller)) = interface_and_tcrc { // spawn the api / charge rate control loop tokio::task::spawn(async move { let mut normal_data_update_interval = @@ -219,8 +230,8 @@ async fn main() { } } }); - tokio::join!(server_handle, local); } + tokio::join!(server_handle, local); } } }