#[macro_use] extern crate rocket; use anyhow::Result; use clap::{Parser, Subcommand}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; use teslatte::{ auth::{AccessToken, RefreshToken}, FleetApi, }; use crate::{config::Config, errors::*}; mod config; mod errors; mod server; #[derive(Parser, Debug, Clone)] #[clap(author, version, about, long_about = None)] struct Args { #[command(subcommand)] command: Commands, #[clap(long, default_value = "/etc/tesla-charge-controller")] config_dir: PathBuf, } #[derive(Subcommand, Debug, Clone)] enum Commands { /// Run charge controller server Watch, /// Print the default config file GenerateConfig, } #[tokio::main] async fn main() { let args = Args::parse(); let auth_path = args.config_dir.join("auth"); let config_path = args.config_dir.join("config"); match args.command { Commands::GenerateConfig => { println!( "{}", ron::ser::to_string_pretty(&Config::default(), Default::default()).unwrap() ); } Commands::Watch => match get_auth(auth_path).await { Ok(api) => { let config: Config = ron::from_str(&std::fs::read_to_string(&config_path).unwrap()).unwrap(); let products = api.products().await; match products { Ok(res) => match res.first() { Some(teslatte::products::Product::Vehicle(vehicle)) => { server::launch_server(server::ServerState { config, api, vehicle: vehicle.clone(), }) .await; } _ => println!("No first item"), }, Err(e) => println!("Error getting products: {e:#?}"), } } Err(e) => println!("{}", e.error_string()), }, } } #[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct Coords { pub latitude: f64, pub longitude: f64, } const COORD_PRECISION: f64 = 0.001; impl Coords { fn overlaps(&self, other: &Coords) -> bool { (self.latitude - other.latitude).abs() < COORD_PRECISION && (self.longitude - other.longitude).abs() < COORD_PRECISION } } async fn get_auth(auth_path: PathBuf) -> Result { let key: AuthInfo = ron::from_str(&std::fs::read_to_string(&auth_path)?)?; let mut api = FleetApi::new(key.access_token, key.refresh_token); api.refresh().await?; println!("Refreshed auth key"); save_key(auth_path, &api)?; // api.print_responses = teslatte::PrintResponses::Pretty; Ok(api) } #[derive(Serialize, Deserialize)] struct AuthInfo { access_token: AccessToken, refresh_token: Option, } fn save_key(auth_path: PathBuf, api: &FleetApi) -> Result<(), SaveError> { std::fs::write( auth_path, ron::ser::to_string(&AuthInfo { access_token: api.access_token.clone(), refresh_token: api.refresh_token.clone(), })?, )?; println!("Auth successfully saved"); Ok(()) }