#pragma once #include #include "../Platform.h" struct ScheduleEntry { uint8_t hour; uint8_t brightness; }; std::array schedule{{ {0, 0}, {5, 0}, {6, 0}, {7, 10}, {8, 80}, {11, 120}, {18, 200}, {19, 255}, {22, 120}, {23, 20} }}; class CircadianRhythm : public InputSource { private: bool needsUpdate = true; public: CircadianRhythm() : InputSource("CircadianRhythm") {} void onStart() { needsUpdate = true; } uint8_t brightnessForTime(uint8_t hour, uint8_t minute) const { ScheduleEntry start = schedule.back(); ScheduleEntry end = schedule.front(); for(ScheduleEntry cur : schedule) { // Find the last hour that is prior to or equal to now if (cur.hour <= hour) { start = cur; } else { break; } } for(ScheduleEntry cur : schedule) { // Find the first hour that is after now // If no such hour exists, we should automatically wrap back to hour 0 if (cur.hour > hour) { end = cur; break; } } if (start.hour > end.hour) { end.hour += 24; } uint16_t startTime = start.hour * 60; uint16_t endTime = end.hour * 60; uint16_t nowTime = hour * 60 + minute; uint16_t duration = endTime - startTime; uint16_t curDuration = nowTime - startTime; uint8_t frac = map8(curDuration, 0, duration); return lerp8by8(start.brightness, end.brightness, frac); } InputEvent read() { EVERY_N_SECONDS(60) { needsUpdate = true; } if (needsUpdate) { uint8_t hour = 0; uint8_t minute = 0; needsUpdate = false; struct tm timeinfo; if (Platform::getLocalTime(&timeinfo)) { hour = timeinfo.tm_hour; minute = timeinfo.tm_min; } else { hour = 0; minute = 0; } Log.notice("Current time: %d:%d", hour, minute); auto brightness = brightnessForTime(hour, minute); Log.notice("Adjusting brightness to %d", brightness); return InputEvent{InputEvent::SetBrightness, brightness}; } return InputEvent{}; } };