diff --git a/README.md b/README.md index 7f55299..68a039d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,9 @@ For example for My Autarco: [default] # ... -# Put your solar cloud service credentials below +# Put your solar cloud service settings below and uncomment them +[default.service] +kind = "MyAutarco" username = "foo@domain.tld" password = "secret" site_id = "abc123de" diff --git a/Rocket.toml.example b/Rocket.toml.example index 65c5a0e..f069df7 100644 --- a/Rocket.toml.example +++ b/Rocket.toml.example @@ -3,6 +3,8 @@ address = "0.0.0.0" port = 2356 # Put your solar cloud service settings below and uncomment them +[default.service] +# kind = "MyAutarco" # username = "foo@domain.tld" # password = "secret" # site_id = "abc123de" diff --git a/src/main.rs b/src/main.rs index 482b251..f237ffe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,20 +20,16 @@ use serde::{Deserialize, Serialize}; use self::update::update_loop; -/// The configuration necessary to access a cloud service API. -#[derive(Debug, Deserialize)] -struct Config { - /// The username of the account to login with - username: String, - /// The password of the account to login with - password: String, - /// The Autarco site ID to track - site_id: String, -} - /// The global, concurrently accessible current status. static STATUS: Lazy>> = Lazy::new(|| Mutex::new(None)); +/// The configuration loaded additionally by Rocket. +#[derive(Debug, Deserialize)] +struct Config { + /// The service-specific configuration + service: services::Config, +} + /// The current photovoltaic invertor status. #[derive(Clone, Copy, Debug, Serialize)] struct Status { @@ -60,8 +56,11 @@ fn rocket() -> _ { .attach(AdHoc::config::()) .attach(AdHoc::on_liftoff("Updater", |rocket| { Box::pin(async move { - let config = rocket.figment().extract().expect("Invalid configuration"); - let service = services::get("my_autarco", config).expect("Invalid service"); + let config = rocket + .figment() + .extract::() + .expect("Invalid configuration"); + let service = services::get(config.service).expect("Invalid service"); // We don't care about the join handle nor error results?t let _ = rocket::tokio::spawn(update_loop(service)); diff --git a/src/services.rs b/src/services.rs index 1174f1d..1d824a9 100644 --- a/src/services.rs +++ b/src/services.rs @@ -4,14 +4,22 @@ pub(crate) mod my_autarco; use enum_dispatch::enum_dispatch; use rocket::async_trait; +use serde::Deserialize; -use crate::{Status, Config}; +use crate::Status; + +/// The service-specific configuration necessary to access a cloud service API. +#[derive(Debug, Deserialize)] +#[serde(crate = "rocket::serde", tag = "kind")] +pub(crate) enum Config { + /// The configuration of the My Autarco service + MyAutarco(my_autarco::Config), +} /// Retrieves the service for the provided name (if supported). -pub(crate) fn get(service: &str, config: Config) -> color_eyre::Result { - match service { - "my_autarco" => Ok(Services::MyAutarco(my_autarco::service(config)?)), - _ => panic!("Unsupported service: {service}"), +pub(crate) fn get(config: Config) -> color_eyre::Result { + match config { + Config::MyAutarco(config) => Ok(Services::MyAutarco(my_autarco::service(config)?)), } } diff --git a/src/services/my_autarco.rs b/src/services/my_autarco.rs index 2d75e6f..24d26d4 100644 --- a/src/services/my_autarco.rs +++ b/src/services/my_autarco.rs @@ -9,7 +9,7 @@ use rocket::async_trait; use serde::Deserialize; use url::ParseError; -use crate::{Status, Config}; +use crate::Status; /// The base URL of My Autarco site. const BASE_URL: &str = "https://my.autarco.com"; @@ -17,6 +17,17 @@ const BASE_URL: &str = "https://my.autarco.com"; /// The interval between data polls (in seconds). const POLL_INTERVAL: u64 = 300; +/// The configuration necessary to access the My Autarco API. +#[derive(Debug, Deserialize)] +pub(crate) struct Config { + /// The username of the account to login with + username: String, + /// The password of the account to login with + password: String, + /// The Autarco site ID to track + site_id: String, +} + /// Instantiates the My Autarco service. pub(crate) fn service(config: Config) -> Result { let client = ClientBuilder::new().cookie_store(true).build()?;