I spend a lot of time on presence simulation projects that do things like turning on/off various things in our home at seemingly random times. The classic example of this use case is an indoor or outdoor light that comes on and off randomly as to fool would be villains into believing someone is home.
I developed a library for Arduino some time back and finally ported it to Particle. It uses the Time class in particle and you can set timers for WEEKENDS, WEEKDAYS, single days (e.g. WEDNESDAY) or even random days or custom templates (e.g. Monday Tuesday and Friday). I used a technique to allow the time to run over midnight, allowing timers to start in the evening and stop in the early am, for example.
I uploaded it to the Particle Library of Libraries and I hope maybe someone finds it useful, besides me. Of course, I would appreciate any contribution/feedback or suggestions for improvement. I’ve been working with it across the Arduino and Particle universe and it seems stable.
Find DailyTimerSpark here on GitHub and in the Particle Library of Libraries in the Build IDE.
Code snippet to see how easy it can be to set up a daily timer:
#include "DailyTimerSpark.h"
DailyTimer timer1(18, 30, 1, 30, EVERY_DAY, RANDOM_END, customSeedGenerator); // optional callback function for random number generation, see below example
DailyTimer timer2(12, 0, 13, 0, SATURDAY, FIXED); // default is FIXED, this will randomize the start time only
DailyTimer timer3( 8, 30, 23, 30, WEEKENDS); // creates with a default fixed start time and end time
bool timer1_LastState = false;
uint32_t lastUpdateTime = 0;
void setup()
{
timer3.begin(); // use this for syncing the state change tools startTrigger() and endTrigger() on startup
timer2.begin();
timer1.begin();
Serial.begin(9600);
pinMode(D7, OUTPUT);
timer1.setRandomOffset(15, RANDOM_END);
//timer1.setDaysActive(WEEKDAYS); // Set the timer to be active on weekdays
//timer1.setDaysActive(B10101010); // or define a custom day mask... SMTWTFS0 example: Sunday, Tuesday, Yhursday, Saturday
//timer1.setRandomDays(4); // or four random days per week
//timer3.setRandomOffset(5); // Change random start time, +/- 5 minutes... max 59 mins, default is 15mins
//Serial.println(timer1.getDays(), BIN); // getDays() returns active days as a byte in the format above
}
void loop()
{
bool timerState = timer1.isActive(); //State Change method this block
if(timerState != timer1_LastState)
{
if(timerState)
{
digitalWrite(D7, HIGH);
Serial.println("LED is ON");
Particle.publish("DailyTimer", "LED is ON", 60, PRIVATE);
}
else
{
digitalWrite(D7, LOW);
Serial.println("LED is OFF");
Particle.publish("DailyTimer", "LED is OFF", 60, PRIVATE);
}
timer1_LastState = timerState;
}
if(timer2.startTrigger()) // Boundary method following blocks
{
Serial.println("Timer 2 FIRED!");
Particle.publish("DailyTimer", "Timer2 Fired", 60, PRIVATE);
}
if(timer3.startTrigger())
{
Serial.println("Timer 3 FIRED!");
Particle.publish("DailyTimer", "Timer3 Fired", 60, PRIVATE);
}
if(timer3.endTrigger())
{
Serial.println("Timer 3 Expired!");
Particle.publish("DailyTimer", "Timer3 is Inactive", 60, PRIVATE);
}
if(millis() - lastUpdateTime > 1000UL)
{
char timeBuffer[32] = "";
Serial.println(Time.timeStr());
lastUpdateTime += 1000UL;
}
}
uint32_t customSeedGenerator()
{
Serial.println("New Seed Created");
return random(0xFFFFFFFF);
}