200 lines
5.2 KiB
C++
200 lines
5.2 KiB
C++
/*
|
|
* Stairs
|
|
* Copyright 2017 (c) Mark van Renswoude
|
|
*
|
|
* https://git.x2software.net/pub/Stairs
|
|
*/
|
|
#include "./time.h"
|
|
#include <string.h>
|
|
#include <ArduinoJson.h>
|
|
#include "../../debug.h"
|
|
#include "../../global.h"
|
|
|
|
|
|
timeDayOfWeek_t toTimeDayOfWeek(DayOfWeek day)
|
|
{
|
|
switch (day)
|
|
{
|
|
case Monday: return dowMonday;
|
|
case Tuesday: return dowTuesday;
|
|
case Wednesday: return dowWednesday;
|
|
case Thursday: return dowThursday;
|
|
case Friday: return dowFriday;
|
|
case Saturday: return dowSaturday;
|
|
case Sunday: return dowSunday;
|
|
}
|
|
|
|
return dowInvalid;
|
|
}
|
|
|
|
|
|
DayOfWeek toDayOfWeek(timeDayOfWeek_t timeDay)
|
|
{
|
|
switch (timeDay)
|
|
{
|
|
case dowSunday: return Sunday;
|
|
case dowMonday: return Monday;
|
|
case dowTuesday: return Tuesday;
|
|
case dowWednesday: return Wednesday;
|
|
case dowThursday: return Thursday;
|
|
case dowFriday: return Friday;
|
|
case dowSaturday: return Saturday;
|
|
default: return Monday;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void TimeTriggerSettings::toJson(Print &print)
|
|
{
|
|
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(10) + JSON_OBJECT_SIZE(3) + 10*JSON_OBJECT_SIZE(5));
|
|
|
|
JsonObject& root = jsonBuffer.createObject();
|
|
root["enabled"] = enabled();
|
|
root["transitionTime"] = transitionTime();
|
|
|
|
JsonArray& jsonTriggers = root.createNestedArray("triggers");
|
|
|
|
for (uint8_t i = 0; i < triggerCount(); i++)
|
|
{
|
|
TimeTrigger* triggerItem = trigger(i);
|
|
|
|
JsonObject& jsonTrigger = jsonTriggers.createNestedObject();
|
|
jsonTrigger["time"] = triggerItem->time;
|
|
jsonTrigger["daysOfWeek"] = triggerItem->daysOfWeek;
|
|
jsonTrigger["brightness"] = triggerItem->brightness;
|
|
jsonTrigger["triggerType"] = (uint8_t)triggerItem->triggerType;
|
|
jsonTrigger["enabled"] = triggerItem->enabled;
|
|
}
|
|
|
|
root.printTo(print);
|
|
}
|
|
|
|
|
|
bool TimeTriggerSettings::fromJson(char* data, bool* changed)
|
|
{
|
|
if (changed != nullptr)
|
|
*changed = false;
|
|
|
|
DynamicJsonBuffer jsonBuffer(JSON_ARRAY_SIZE(10) + JSON_OBJECT_SIZE(3) + 10*JSON_OBJECT_SIZE(5) + 270);
|
|
JsonObject& root = jsonBuffer.parseObject(data);
|
|
|
|
if (!root.success())
|
|
return false;
|
|
|
|
|
|
enabled(root["enabled"]);
|
|
transitionTime(root["transitionTime"]);
|
|
|
|
if (root.containsKey("triggers"))
|
|
{
|
|
JsonArray& jsonTriggers = root["triggers"];
|
|
if (mTriggers != nullptr)
|
|
delete [] mTriggers;
|
|
|
|
mTriggerCount = jsonTriggers.size();
|
|
mTriggers = new TimeTrigger[mTriggerCount];
|
|
|
|
|
|
for (uint8_t i = 0; i < mTriggerCount; i++)
|
|
{
|
|
JsonObject& jsonTrigger = jsonTriggers[i];
|
|
TimeTrigger* trigger = &mTriggers[i];
|
|
|
|
trigger->time = jsonTrigger["time"];
|
|
trigger->daysOfWeek = jsonTrigger["daysOfWeek"];
|
|
trigger->brightness = jsonTrigger["brightness"];
|
|
trigger->triggerType = (TimeTriggerType)(uint8_t)jsonTrigger["triggerType"];
|
|
trigger->enabled = jsonTrigger["enabled"];
|
|
}
|
|
}
|
|
|
|
if (changed != nullptr)
|
|
*changed = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
TimeTrigger* TimeTriggerSettings::getActiveTrigger(tmElements_t &time)
|
|
{
|
|
if (mTriggerCount == 0)
|
|
return nullptr;
|
|
|
|
|
|
DayOfWeek dayOfWeek = toDayOfWeek((timeDayOfWeek_t)time.Wday);
|
|
DayOfWeek startDayOfWeek = dayOfWeek;
|
|
TimeTrigger* activeTrigger = nullptr;
|
|
int16_t activeTriggerTime = 0;
|
|
|
|
|
|
Dusk2Dawn location(systemSettings->latitude(), systemSettings->longitude(), timezoneOffset / 3600.0f);
|
|
|
|
// Praise the sun \o/
|
|
// DST is always hardcoded as false, since it is already included in timezoneOffset
|
|
int16_t sunriseMinutes = location.sunrise(time.Year, time.Month, time.Day, false);
|
|
int16_t sunsetMinutes = location.sunset(time.Year, time.Month, time.Day, false);
|
|
|
|
int16_t dayTime = (time.Hour * 60) + time.Minute;
|
|
|
|
_d("TimeTrigger :: sunrise: "); _dln(sunriseMinutes);
|
|
_d("TimeTrigger :: sunset: "); _dln(sunsetMinutes);
|
|
_d("TimeTrigger :: current time: "); _dln(dayTime);
|
|
|
|
do
|
|
{
|
|
for (uint16_t i = 0; i < mTriggerCount; i++)
|
|
{
|
|
TimeTrigger* trigger = &mTriggers[i];
|
|
|
|
if (trigger->enabled && (trigger->daysOfWeek & dayOfWeek))
|
|
{
|
|
int16_t triggerTime = trigger->time;
|
|
|
|
switch (trigger->triggerType)
|
|
{
|
|
case RelativeToSunrise:
|
|
triggerTime += sunriseMinutes;
|
|
break;
|
|
|
|
case RelativeToSunset:
|
|
triggerTime += sunsetMinutes;
|
|
break;
|
|
|
|
case FixedTime:
|
|
// No changes (but eliminates warning)
|
|
break;
|
|
}
|
|
|
|
// Check if the current time is after the time set in the trigger, and
|
|
// if this trigger is later than any previously found trigger, so that
|
|
// we'll always get the most recent match
|
|
if (triggerTime <= dayTime && (activeTrigger == nullptr || triggerTime > activeTriggerTime))
|
|
{
|
|
activeTrigger = trigger;
|
|
activeTriggerTime = triggerTime;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (activeTrigger != nullptr)
|
|
return activeTrigger;
|
|
|
|
|
|
// If there are no active triggers on this day, go back
|
|
// one weekday and try again until we've come around completely
|
|
if (dayOfWeek == Monday)
|
|
dayOfWeek = Sunday;
|
|
else
|
|
dayOfWeek = (DayOfWeek)((uint8_t)dayOfWeek / 2);
|
|
|
|
// Set the comparison time to the end of the day, so the last
|
|
// trigger for that day will match
|
|
dayTime = 24 * 60;
|
|
} while (dayOfWeek != startDayOfWeek);
|
|
|
|
return nullptr;
|
|
}
|