Stuff
This commit is contained in:
@ -1,14 +1,49 @@
|
||||
use common::{ClientMessage, ServerMessage};
|
||||
use lighter_manager::manager::{BulbCommand, BulbManager, BulbSelector};
|
||||
use tokio::select;
|
||||
use tokio::time::{sleep, Duration};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::State;
|
||||
use chrono::{Datelike, Local, NaiveTime, Weekday};
|
||||
use common::{ClientMessage, ServerMessage};
|
||||
use lighter_lib::{BulbColor, BulbId};
|
||||
use lighter_manager::manager::{BulbCommand, BulbManager, BulbSelector};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use tokio::select;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tokio::task::{spawn, JoinHandle};
|
||||
use tokio::time::sleep;
|
||||
|
||||
use crate::persistence::PersistenceFile;
|
||||
use crate::{ClientRequest, State};
|
||||
|
||||
#[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
struct LightsState {
|
||||
wake_schedule: HashMap<(BulbId, Weekday), NaiveTime>,
|
||||
}
|
||||
|
||||
pub async fn lights_task(state: &State) {
|
||||
let config = &state.config;
|
||||
let server_message = &state.server_message;
|
||||
let mut client_message = state.client_message.subscribe();
|
||||
let mut lights_state: PersistenceFile<LightsState> = state
|
||||
.persistence
|
||||
.open("lights".into())
|
||||
.await
|
||||
.expect("Failed to open lights config");
|
||||
|
||||
let mut wake_tasks: HashMap<(BulbId, Weekday), JoinHandle<()>> = lights_state
|
||||
.get()
|
||||
.wake_schedule
|
||||
.iter()
|
||||
.map(|((bulb, day), time)| {
|
||||
let handle = spawn(wake_task(
|
||||
state.client_message.clone(),
|
||||
bulb.clone(),
|
||||
*day,
|
||||
*time,
|
||||
));
|
||||
|
||||
((bulb.clone(), *day), handle)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let (cmd, bulb_states) = BulbManager::launch(config.bulbs.clone(), config.mqtt.clone())
|
||||
.await
|
||||
@ -16,7 +51,7 @@ pub async fn lights_task(state: &State) {
|
||||
|
||||
loop {
|
||||
let notify = bulb_states.notify_on_change();
|
||||
sleep(Duration::from_millis(1000 / 10)).await; // limit to 10 updates/second
|
||||
sleep(tokio::time::Duration::from_millis(1000 / 10)).await; // limit to 10 updates/second
|
||||
select! {
|
||||
_ = notify => {
|
||||
for (id, mode) in bulb_states.bulbs().await.clone().into_iter() {
|
||||
@ -55,9 +90,70 @@ pub async fn lights_task(state: &State) {
|
||||
}
|
||||
}
|
||||
}
|
||||
ClientMessage::SetBulbWakeTime { id, day, time } => {
|
||||
if let Err(e) = lights_state.update(|lights_state| {
|
||||
lights_state.wake_schedule.insert((id.clone(), day), time);
|
||||
}).await {
|
||||
error!("Failed to save wake schedule: {e}");
|
||||
};
|
||||
|
||||
let handle = spawn(wake_task(state.client_message.clone(), id.clone(), day, time));
|
||||
if let Some(old_handle) = wake_tasks.insert((id, day), handle) {
|
||||
old_handle.abort();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn wake_task(
|
||||
channel: broadcast::Sender<ClientRequest>,
|
||||
id: BulbId,
|
||||
day: Weekday,
|
||||
time: NaiveTime,
|
||||
) {
|
||||
let now = Local::now();
|
||||
let day_num = day.num_days_from_monday();
|
||||
let now_day = now.weekday();
|
||||
let now_day_num = now_day.num_days_from_monday();
|
||||
|
||||
let mut alarm = now;
|
||||
if day_num >= now_day_num {
|
||||
// next alarm is this week
|
||||
alarm += chrono::Duration::days((day_num - now_day_num).into());
|
||||
alarm = alarm.date().and_time(time).unwrap();
|
||||
} else {
|
||||
// next alarm is next week
|
||||
alarm += chrono::Duration::weeks(1);
|
||||
alarm -= chrono::Duration::days((now_day_num - day_num).into());
|
||||
alarm = alarm.date().and_time(time).unwrap();
|
||||
}
|
||||
|
||||
loop {
|
||||
info!("sleeping until {alarm}");
|
||||
sleep((alarm - Local::now()).to_std().unwrap()).await;
|
||||
alarm += chrono::Duration::weeks(1);
|
||||
|
||||
for brightness in (1..=50).map(|i| (i as f32) * 0.01) {
|
||||
sleep(Duration::from_secs(12)).await;
|
||||
|
||||
let message = ClientMessage::SetBulbColor {
|
||||
id: id.clone(),
|
||||
color: BulbColor::Kelvin {
|
||||
t: 0.0,
|
||||
b: brightness,
|
||||
},
|
||||
};
|
||||
|
||||
let (response, _) = mpsc::channel(1);
|
||||
let request = ClientRequest { message, response };
|
||||
|
||||
if channel.send(request).is_err() {
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user