Use fairing to read the My Autarco config (closes: #3)
* Read My Autarco credentials from `Rocket.toml` * Remove custom config loading function and `autarco.toml.example` * Update `Rocket.toml.example` but comment out the variables so that the user won't forget to set them * Update `.gitignore` * Update documentation
This commit is contained in:
parent
31e8ca65af
commit
3c35c4fe72
|
@ -2,4 +2,4 @@
|
||||||
/target
|
/target
|
||||||
|
|
||||||
# Config
|
# Config
|
||||||
autarco.toml
|
Rocket.toml
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
[default]
|
[default]
|
||||||
address = "0.0.0.0"
|
address = "0.0.0.0"
|
||||||
port = 2356
|
port = 2356
|
||||||
|
|
||||||
|
# Put your My Autarco credentials below and uncomment them
|
||||||
|
# username = "foo@domain.tld"
|
||||||
|
# password = "secret"
|
||||||
|
# site_id = "abc123de"
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Put your My Autarco credentials below
|
|
||||||
username = "foo@domain.tld"
|
|
||||||
password = "secret"
|
|
33
src/main.rs
33
src/main.rs
|
@ -7,15 +7,11 @@
|
||||||
)]
|
)]
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use std::path::Path;
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use color_eyre::Result;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rocket::fairing::AdHoc;
|
use rocket::fairing::AdHoc;
|
||||||
use rocket::serde::json::Json;
|
use rocket::serde::json::Json;
|
||||||
use rocket::tokio::fs::File;
|
|
||||||
use rocket::tokio::io::AsyncReadExt;
|
|
||||||
use rocket::{get, routes};
|
use rocket::{get, routes};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -31,7 +27,7 @@ const BASE_URL: &str = "https://my.autarco.com";
|
||||||
/// This depends on with which interval Autaurco processes new information from the invertor.
|
/// This depends on with which interval Autaurco processes new information from the invertor.
|
||||||
const POLL_INTERVAL: u64 = 300;
|
const POLL_INTERVAL: u64 = 300;
|
||||||
|
|
||||||
/// The configuration for the My Autarco site
|
/// The extra configuration necessary to access the My Autarco site.
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
struct Config {
|
struct Config {
|
||||||
/// The username of the account to login with
|
/// The username of the account to login with
|
||||||
|
@ -45,25 +41,6 @@ struct Config {
|
||||||
/// The global, concurrently accessible current status.
|
/// The global, concurrently accessible current status.
|
||||||
static STATUS: Lazy<Mutex<Option<Status>>> = Lazy::new(|| Mutex::new(None));
|
static STATUS: Lazy<Mutex<Option<Status>>> = Lazy::new(|| Mutex::new(None));
|
||||||
|
|
||||||
/// Loads the configuration.
|
|
||||||
///
|
|
||||||
/// The configuration file `autarco.toml` should be located in the project path.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an error if the file could not be found, opened or read and if the contents are
|
|
||||||
/// not valid TOML or does not contain all the necessary keys (see [`Config`]).
|
|
||||||
async fn load_config() -> Result<Config> {
|
|
||||||
let config_file_name = Path::new(env!("CARGO_MANIFEST_DIR")).join("autarco.toml");
|
|
||||||
let mut file = File::open(config_file_name).await?;
|
|
||||||
|
|
||||||
let mut contents = String::new();
|
|
||||||
file.read_to_string(&mut contents).await?;
|
|
||||||
let config = toml::from_str(&contents)?;
|
|
||||||
|
|
||||||
Ok(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The current photovoltaic invertor status.
|
/// The current photovoltaic invertor status.
|
||||||
#[derive(Clone, Copy, Debug, Serialize)]
|
#[derive(Clone, Copy, Debug, Serialize)]
|
||||||
struct Status {
|
struct Status {
|
||||||
|
@ -82,15 +59,17 @@ async fn status() -> Option<Json<Status>> {
|
||||||
status_guard.map(Json)
|
status_guard.map(Json)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Rocket and attaches the update loop as fairing.
|
/// Creates a Rocket and attaches the config parsing and update loop as fairings.
|
||||||
#[rocket::launch]
|
#[rocket::launch]
|
||||||
fn rocket() -> _ {
|
fn rocket() -> _ {
|
||||||
rocket::build()
|
rocket::build()
|
||||||
.mount("/", routes![status])
|
.mount("/", routes![status])
|
||||||
.attach(AdHoc::on_liftoff("Updater", |_| {
|
.attach(AdHoc::config::<Config>())
|
||||||
|
.attach(AdHoc::on_liftoff("Updater", |rocket| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// We don't care about the join handle nor error results?
|
// We don't care about the join handle nor error results?
|
||||||
let _ = rocket::tokio::spawn(update_loop());
|
let config = rocket.figment().extract().expect("Invalid configuration");
|
||||||
|
let _ = rocket::tokio::spawn(update_loop(config));
|
||||||
})
|
})
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rocket::tokio::time::sleep;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use url::{ParseError, Url};
|
use url::{ParseError, Url};
|
||||||
|
|
||||||
use super::{load_config, Config, Status, BASE_URL, POLL_INTERVAL, STATUS};
|
use super::{Config, Status, BASE_URL, POLL_INTERVAL, STATUS};
|
||||||
|
|
||||||
/// Returns the login URL for the My Autarco site.
|
/// Returns the login URL for the My Autarco site.
|
||||||
fn login_url() -> Result<Url, ParseError> {
|
fn login_url() -> Result<Url, ParseError> {
|
||||||
|
@ -88,8 +88,7 @@ async fn update(config: &Config, client: &Client, last_updated: u64) -> Result<S
|
||||||
///
|
///
|
||||||
/// It updates the mutex-guarded current update [`Status`] struct which can be retrieved via
|
/// It updates the mutex-guarded current update [`Status`] struct which can be retrieved via
|
||||||
/// Rocket.
|
/// Rocket.
|
||||||
pub(super) async fn update_loop() -> color_eyre::Result<()> {
|
pub(super) async fn update_loop(config: Config) -> color_eyre::Result<()> {
|
||||||
let config = load_config().await?;
|
|
||||||
let client = ClientBuilder::new().cookie_store(true).build()?;
|
let client = ClientBuilder::new().cookie_store(true).build()?;
|
||||||
|
|
||||||
// Go to the My Autarco site and login.
|
// Go to the My Autarco site and login.
|
||||||
|
|
Reference in New Issue