Compare commits
5 Commits
2370faa718
...
01a7576d7f
| Author | SHA1 | Date | |
|---|---|---|---|
|
01a7576d7f
|
|||
|
1e55385645
|
|||
|
1ac0dbe210
|
|||
|
939e4d9785
|
|||
|
08bdeb693b
|
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -172,7 +172,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"lighter_lib",
|
||||
@ -525,7 +525,7 @@ checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
|
||||
|
||||
[[package]]
|
||||
name = "hemma"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -549,7 +549,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hemma_web"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "hemma"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use chrono::{Datelike, Local, NaiveTime, Weekday};
|
||||
use chrono::{DateTime, Datelike, Local, NaiveTime, Weekday};
|
||||
use common::{ClientMessage, ServerMessage};
|
||||
use lighter_lib::{BulbColor, BulbId};
|
||||
use lighter_manager::manager::{BulbCommand, BulbManager, BulbSelector};
|
||||
@ -40,7 +40,7 @@ pub async fn lights_task(state: &State) {
|
||||
.flat_map(|(bulb, schedule)| schedule.iter().map(move |(day, time)| (bulb, day, time)))
|
||||
.map(|(bulb, day, time)| {
|
||||
let handle = spawn(wake_task(
|
||||
state.client_message.subscribe(),
|
||||
state.client_message.clone(),
|
||||
cmd.clone(),
|
||||
bulb.clone(),
|
||||
*day,
|
||||
@ -105,21 +105,21 @@ pub async fn lights_task(state: &State) {
|
||||
schedule.insert(day, time);
|
||||
}
|
||||
else {
|
||||
schedule.remove(&day);
|
||||
schedule.remove(&day);
|
||||
}
|
||||
}).await {
|
||||
error!("Failed to save wake schedule: {e}");
|
||||
};
|
||||
|
||||
|
||||
if let Some(time) = time {
|
||||
let handle = spawn(wake_task(
|
||||
state.client_message.subscribe(),
|
||||
state.client_message.clone(),
|
||||
cmd.clone(),
|
||||
id.clone(),
|
||||
day,
|
||||
time,
|
||||
));
|
||||
|
||||
|
||||
if let Some(old_handle) = wake_tasks.insert((id, day), handle) {
|
||||
old_handle.abort();
|
||||
}} else {
|
||||
@ -136,39 +136,23 @@ pub async fn lights_task(state: &State) {
|
||||
}
|
||||
|
||||
async fn wake_task(
|
||||
mut client_messages: broadcast::Receiver<ClientRequest>,
|
||||
client_messages: broadcast::Sender<ClientRequest>,
|
||||
cmd: mpsc::Sender<BulbCommand>,
|
||||
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();
|
||||
}
|
||||
let mut alarm = next_alarm(Local::now(), day, time);
|
||||
|
||||
loop {
|
||||
info!("sleeping until {alarm}");
|
||||
sleep((alarm - Local::now()).to_std().unwrap()).await;
|
||||
alarm += chrono::Duration::weeks(1);
|
||||
|
||||
// slowly turn up brightness of bulb
|
||||
for brightness in (1..=75).map(|i| (i as f32) * 0.01) {
|
||||
select! {
|
||||
// abort if the client pokes the bulb
|
||||
_ = wait_for_bulb_command(&id, &mut client_messages) => break,
|
||||
_ = wait_for_bulb_command(&id, client_messages.subscribe()) => break,
|
||||
_ = sleep(Duration::from_secs(12)) => {}
|
||||
};
|
||||
|
||||
@ -186,13 +170,30 @@ async fn wake_task(
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
alarm = next_alarm(Local::now(), day, time);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the next alarm, from a weekday+time schedule.
|
||||
fn next_alarm(now: DateTime<Local>, day: Weekday, time: NaiveTime) -> DateTime<Local> {
|
||||
let day_of_alarm = day.num_days_from_monday() as i64;
|
||||
let day_now = now.weekday().num_days_from_monday() as i64;
|
||||
|
||||
let alarm = now + chrono::Duration::days(day_of_alarm - day_now);
|
||||
let mut alarm = alarm.date().and_time(time).unwrap();
|
||||
|
||||
if alarm <= now {
|
||||
alarm += chrono::Duration::weeks(1);
|
||||
}
|
||||
|
||||
alarm
|
||||
}
|
||||
|
||||
/// Wait until we receive a client request that mutates the given bulb
|
||||
async fn wait_for_bulb_command(
|
||||
bulb_id: &BulbId,
|
||||
client_messages: &mut broadcast::Receiver<ClientRequest>,
|
||||
mut client_messages: broadcast::Receiver<ClientRequest>,
|
||||
) {
|
||||
loop {
|
||||
match client_messages.recv().await {
|
||||
@ -210,3 +211,31 @@ async fn wait_for_bulb_command(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use chrono::{offset::TimeZone, Local, NaiveTime, Weekday};
|
||||
|
||||
use super::next_alarm;
|
||||
|
||||
#[test]
|
||||
fn test_alarm_date() {
|
||||
const FMT: &str = "%Y-%m-%d %H:%M";
|
||||
let now = Local.datetime_from_str("2022-10-18 15:30", FMT).unwrap();
|
||||
let test_values = [
|
||||
(Weekday::Tue, (16, 30), "2022-10-18 16:30"),
|
||||
(Weekday::Tue, (14, 30), "2022-10-25 14:30"),
|
||||
(Weekday::Wed, (15, 30), "2022-10-19 15:30"),
|
||||
(Weekday::Mon, (15, 30), "2022-10-24 15:30"),
|
||||
];
|
||||
|
||||
for (day, (hour, min), expected) in test_values {
|
||||
let expected = Local.datetime_from_str(expected, FMT).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
next_alarm(now, day, NaiveTime::from_hms(hour, min, 0)),
|
||||
expected
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "hemma_web"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
authors = ["Joakim Hulthe <joakim@hulthe.net"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user