Feature: Schedule devices turning on/off
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-11-17 00:01:13 +01:00
parent 0154d19b71
commit db17b68e90
9 changed files with 144 additions and 3 deletions

View File

@@ -15,6 +15,7 @@ use crate::{
device_manager::DeviceConfigs,
devices::PresenceConfig,
error::{ConfigParseError, MissingEnv},
schedule::Schedule,
};
#[derive(Debug, Deserialize)]
@@ -27,6 +28,7 @@ pub struct Config {
pub ntfy: Option<NtfyConfig>,
pub presence: PresenceConfig,
pub devices: IndexMap<String, DeviceConfigs>,
pub schedule: Schedule,
}
#[derive(Debug, Clone, Deserialize)]

View File

@@ -4,9 +4,11 @@ use std::sync::Arc;
use async_trait::async_trait;
use enum_dispatch::enum_dispatch;
use futures::future::join_all;
use google_home::traits::OnOff;
use rumqttc::{matches, AsyncClient, QoS};
use serde::Deserialize;
use tokio::sync::{RwLock, RwLockReadGuard};
use tokio_cron_scheduler::{Job, JobScheduler};
use tracing::{debug, error, instrument, trace};
use crate::{
@@ -20,6 +22,7 @@ use crate::{
event::OnNotification,
event::OnPresence,
event::{Event, EventChannel, OnMqtt},
schedule::{Action, Schedule},
};
pub struct ConfigExternal<'a> {
@@ -90,6 +93,55 @@ impl DeviceManager {
device_manager
}
// TODO: This function is currently extremely cursed...
pub async fn add_schedule(&self, schedule: Schedule) {
let sched = JobScheduler::new().await.unwrap();
for (when, actions) in schedule {
let manager = self.clone();
sched
.add(
Job::new_async(when.as_str(), move |_uuid, _l| {
let actions = actions.clone();
let manager = manager.clone();
Box::pin(async move {
for (action, targets) in actions {
for target in targets {
let device = manager.get(&target).await.unwrap();
match action {
Action::On => {
As::<dyn OnOff>::cast_mut(
device.write().await.as_mut(),
)
.unwrap()
.set_on(true)
.await
.unwrap();
}
Action::Off => {
As::<dyn OnOff>::cast_mut(
device.write().await.as_mut(),
)
.unwrap()
.set_on(false)
.await
.unwrap();
}
}
}
}
})
})
.unwrap(),
)
.await
.unwrap();
}
sched.start().await.unwrap();
}
pub async fn add(&self, device: Box<dyn Device>) {
let id = device.get_id().into();

View File

@@ -9,4 +9,5 @@ pub mod error;
pub mod event;
pub mod messages;
pub mod mqtt;
pub mod schedule;
pub mod traits;

View File

@@ -64,6 +64,8 @@ async fn app() -> anyhow::Result<()> {
device_manager.create(&id, device_config).await?;
}
device_manager.add_schedule(config.schedule).await;
let event_channel = device_manager.event_channel();
// Create and add the presence system

17
src/schedule.rs Normal file
View File

@@ -0,0 +1,17 @@
use indexmap::IndexMap;
use serde::Deserialize;
#[derive(Debug, Deserialize, Hash, PartialEq, Eq, Clone, Copy)]
#[serde(rename_all = "snake_case")]
pub enum Action {
On,
Off,
}
pub type Schedule = IndexMap<String, IndexMap<Action, Vec<String>>>;
// #[derive(Debug, Deserialize)]
// pub struct Schedule {
// pub when: String,
// pub actions: IndexMap<Action, Vec<String>>,
// }