platform: esp32: implement a circadian rhythm event source
This commit is contained in:
parent
2f8b94ae61
commit
3c3952a8a9
@ -4,6 +4,7 @@ use std::fmt::Debug;
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
|
use chrono::Timelike;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
|
|
||||||
use esp_idf_svc::eventloop::{EspSubscription, EspSystemEventLoop, System};
|
use esp_idf_svc::eventloop::{EspSubscription, EspSystemEventLoop, System};
|
||||||
@ -203,11 +204,95 @@ impl Board for Esp32Board {
|
|||||||
let nvs = EspDefaultNvsPartition::take().unwrap();
|
let nvs = EspDefaultNvsPartition::take().unwrap();
|
||||||
FixedSizeScheduler::new([
|
FixedSizeScheduler::new([
|
||||||
Box::new(WifiTask::new(self.modem.take().unwrap(), self.sys_loop.clone(), &nvs)),
|
Box::new(WifiTask::new(self.modem.take().unwrap(), self.sys_loop.clone(), &nvs)),
|
||||||
|
Box::new(CircadianRhythm::new()),
|
||||||
Box::new(self.surfaces.clone())
|
Box::new(self.surfaces.clone())
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
struct ScheduleEntry {
|
||||||
|
hour: u8,
|
||||||
|
brightness: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CircadianRhythm {
|
||||||
|
time_check: Periodically,
|
||||||
|
schedule: [ScheduleEntry;10]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CircadianRhythm {
|
||||||
|
fn new() -> Self {
|
||||||
|
CircadianRhythm {
|
||||||
|
time_check: Periodically::new_every_n_seconds(5),
|
||||||
|
schedule: [
|
||||||
|
ScheduleEntry { hour: 0, brightness: 0 },
|
||||||
|
ScheduleEntry { hour: 5, brightness: 0 },
|
||||||
|
ScheduleEntry { hour: 6, brightness: 10 },
|
||||||
|
ScheduleEntry { hour: 7, brightness: 20 },
|
||||||
|
ScheduleEntry { hour: 8, brightness: 80 },
|
||||||
|
ScheduleEntry { hour: 11, brightness: 120 },
|
||||||
|
ScheduleEntry { hour: 18, brightness: 200 },
|
||||||
|
ScheduleEntry { hour: 19, brightness: 255 },
|
||||||
|
ScheduleEntry { hour: 22, brightness: 120 },
|
||||||
|
ScheduleEntry { hour: 23, brightness: 5 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn brightness_for_time(&self, hour: u8, minute: u8) -> u8 {
|
||||||
|
let mut start = self.schedule.last().unwrap();
|
||||||
|
let mut end = self.schedule.first().unwrap();
|
||||||
|
for cur in self.schedule.iter() {
|
||||||
|
if (cur.hour <= hour ) {
|
||||||
|
start = cur;
|
||||||
|
} else {
|
||||||
|
end = cur;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!("hour={:?} minute={:?} start={:?} end={:?}", hour, minute, start, end);
|
||||||
|
|
||||||
|
let mut adjusted_end = end.clone();
|
||||||
|
if start.hour > end.hour {
|
||||||
|
adjusted_end.hour += 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
let start_time = start.hour * 60;
|
||||||
|
let end_time = end.hour * 60;
|
||||||
|
let now_time = hour * 60 + minute;
|
||||||
|
|
||||||
|
let duration = end_time - start_time;
|
||||||
|
let cur_duration = now_time - start_time;
|
||||||
|
|
||||||
|
let frac = map_range(cur_duration.into(), 0, duration.into(), 0, 255) as u8;
|
||||||
|
|
||||||
|
lerp8by8(start.brightness, end.brightness, frac)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_range(x: u16, in_min: u16, in_max: u16, out_min: u16, out_max: u16) -> u16 {
|
||||||
|
let run = in_max - in_min;
|
||||||
|
if run == 0 {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let rise = out_max - out_min;
|
||||||
|
let delta = x - in_min;
|
||||||
|
return (delta * rise) / run + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Task for CircadianRhythm {
|
||||||
|
fn tick(&mut self, event: &Event, bus: &mut EventBus) {
|
||||||
|
if self.time_check.tick() || event.eq(&Event::ReadyToRock) {
|
||||||
|
let now: DateTime<Utc> = std::time::SystemTime::now().into();
|
||||||
|
let next_brightness = self.brightness_for_time(now.hour() as u8, now.minute() as u8);
|
||||||
|
bus.push(Event::new_property_change("output.brightness", next_brightness));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Debug for WifiTask {
|
impl Debug for WifiTask {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("WifiTask").finish()
|
f.debug_struct("WifiTask").finish()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user