2023-10-16 11:37:31 +00:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use anyhow::{Error, Result};
|
|
|
|
use tibber::{Consumption, HomeId, House, PriceInfo, TibberSession, TimeResolution, User};
|
|
|
|
|
|
|
|
pub struct TibberHandler {
|
|
|
|
session: Arc<TibberSession>,
|
|
|
|
pub user: User,
|
|
|
|
pub homes: Vec<(HomeId, House)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TibberHandler {
|
|
|
|
pub async fn new(token: impl ToString + Send + 'static) -> Result<Self> {
|
|
|
|
tokio::task::spawn_blocking(move || {
|
|
|
|
let session = Arc::new(TibberSession::new(token.to_string()));
|
|
|
|
|
|
|
|
let user = session.get_user().map_err(|err| {
|
|
|
|
Error::msg(format!(
|
|
|
|
"TibberHandler: failed getting user information: {err:?}"
|
|
|
|
))
|
|
|
|
})?;
|
|
|
|
|
|
|
|
let mut homes = Vec::new();
|
|
|
|
|
|
|
|
for home_id in user.homes.clone().into_iter() {
|
|
|
|
let house = session.get_home(&home_id).map_err(|err| {
|
|
|
|
Error::msg(format!(
|
|
|
|
"TibberHandler: failed getting house information: {err:?}"
|
|
|
|
))
|
|
|
|
})?;
|
|
|
|
|
|
|
|
homes.push((home_id, house));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
homes,
|
|
|
|
user,
|
|
|
|
session,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.await?
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn get_data<F, T>(&self, f: F) -> Result<Vec<(House, T)>>
|
|
|
|
where
|
|
|
|
F: Fn(&TibberSession, &HomeId) -> Result<T> + Send + Sync + Copy + 'static,
|
|
|
|
T: Send + Sync + 'static,
|
|
|
|
{
|
|
|
|
let mut v = Vec::new();
|
|
|
|
|
|
|
|
for (home_id, house) in self.homes.iter() {
|
|
|
|
v.push((
|
|
|
|
house.clone(),
|
|
|
|
tokio::task::spawn_blocking({
|
|
|
|
let session = self.session.clone();
|
|
|
|
let home_id = home_id.clone();
|
|
|
|
|
|
|
|
move || f(&session, &home_id)
|
|
|
|
})
|
|
|
|
.await??,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn current_prices(&self) -> Result<Vec<(House, PriceInfo)>> {
|
2023-10-16 12:19:36 +00:00
|
|
|
self.get_data(|session, home_id| {
|
|
|
|
session.get_current_price(home_id).map_err(|err| {
|
|
|
|
Error::msg(format!(
|
|
|
|
"TibberHandler: failed getting current price: {err:?}"
|
|
|
|
))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.await
|
2023-10-16 11:37:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn prices_today(&self) -> Result<Vec<(House, Vec<PriceInfo>)>> {
|
2023-10-16 12:19:36 +00:00
|
|
|
self.get_data(|session, home_id| {
|
|
|
|
session.get_prices_today(home_id).map_err(|err| {
|
|
|
|
Error::msg(format!(
|
|
|
|
"TibberHandler: failed getting prices of today: {err:?}"
|
|
|
|
))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.await
|
2023-10-16 11:37:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn prices_tomorrow(&self) -> Result<Vec<(House, Vec<PriceInfo>)>> {
|
2023-10-16 12:19:36 +00:00
|
|
|
self.get_data(|session, home_id| {
|
|
|
|
session.get_prices_tomorrow(home_id).map_err(|err| {
|
|
|
|
Error::msg(format!(
|
|
|
|
"TibberHandler: failed getting prices for tomorrow: {err:?}"
|
|
|
|
))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.await
|
2023-10-16 11:37:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn consumption(
|
|
|
|
&self,
|
|
|
|
resolution: TimeResolution,
|
|
|
|
last: u32,
|
|
|
|
) -> Result<Vec<(House, Vec<Consumption>)>> {
|
|
|
|
let mut v = Vec::new();
|
|
|
|
|
|
|
|
for (home_id, house) in self.homes.iter() {
|
|
|
|
v.push((
|
|
|
|
house.clone(),
|
|
|
|
tokio::task::spawn_blocking({
|
|
|
|
let session = self.session.clone();
|
|
|
|
let home_id = home_id.clone();
|
2023-10-16 11:48:51 +00:00
|
|
|
let resolution = resolution.clone();
|
2023-10-16 11:37:31 +00:00
|
|
|
|
|
|
|
move || {
|
|
|
|
session
|
|
|
|
.get_consuption(&home_id, resolution, last)
|
|
|
|
.map_err(|err| {
|
|
|
|
Error::msg(format!(
|
|
|
|
"TibberHandler: failed getting consumption: {err:?}"
|
|
|
|
))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.await??,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::TibberHandler;
|
|
|
|
use anyhow::Result;
|
|
|
|
|
|
|
|
use std::fs;
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
async fn test_connection() -> Result<()> {
|
2023-10-16 12:19:36 +00:00
|
|
|
let tibber = TibberHandler::new(fs::read_to_string("tibber_token.txt")?).await?;
|
|
|
|
let current_prices = tibber.current_prices().await?;
|
|
|
|
|
|
|
|
println!("{current_prices:?}");
|
2023-10-16 11:37:31 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|