DailyTimerSpark library added

Then it seems to work as expected. (Except the SETUP BUTTON (20)) Thank you all for good help! Here is the final code. Maybe it could be of interest for others:

// To wake the Photon from deep skeep and set it in safe mode (wifi is on in safe mode) press SETUP and RESET, relese RESET after 2sec, wait for violet)
// 
// This #include statement was automatically added by the Particle IDE.
#include <DailyTimerSpark.h>

const uint32_t SLEEP_MINUTES   = 50;      // wake every xx minutes
const uint32_t WAKE_HOUR       = 18;      // starting hour per day
const uint32_t SLEEP_HOUR      = 23;      // stopping hour per day
int relay1                     = D0;      // initialize and give the D0 the variable name relay1
int relay2                     = D1;      // initialize and give the D1 the variable name relay2
retained uint32_t expectedWake =  0;
STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY));

void setup()
{
  Time.zone(+1); //utc time - 1 hour behind GMT - I use GMT
//  pinMode(D7, OUTPUT);
  pinMode(relay1, OUTPUT);
  pinMode(relay2, OUTPUT);
}


void loop()
{
  uint32_t dt;
  if (WAKE_HOUR <= (uint32_t)Time.hour() && (uint32_t)Time.hour() < SLEEP_HOUR)
  {
    dt = (SLEEP_MINUTES - Time.minute() % SLEEP_MINUTES) * 60 - Time.second();  // wake at next time boundary
  }
  else
  {
    uint32_t now = 86400 - Time.local() % 86400;
    dt = (now + WAKE_HOUR * 3600) % 86400;
  }
  // delay(3000);                         // 3sek delay where Photoen is awake but relay/power is off
  digitalWrite(relay1, HIGH);          // turn on relay1/power for the router
  delay(120000);                       // delay for 2 min for the internet to establish
  digitalWrite(relay2, HIGH);          // turn on relay2/power for the Raspberry Pi
  delay(480000);                       // delay for 8 min for the data collection to be finished, then go to deep sleep.
  System.sleep(SLEEP_MODE_DEEP , dt);  // , SLEEP_NETWORK_STANDBY); go to Deep Sleep
  System.sleep(BTN, FALLING  , dt);    // , SLEEP_NETWORK_STANDBY);  // use SETUP BUTTON (20) to wake    (don\t work!)
  expectedWake = Time.now() + dt;      // calculate next wakeup.
}

With your code below that button is never set up to wake the device.

  // since this code sends the device to deep sleep and it'll reset on wake
  System.sleep(SLEEP_MODE_DEEP , dt);  // , SLEEP_NETWORK_STANDBY); go to Deep Sleep

  // these two lines will never execute ;-)
  System.sleep(BTN, FALLING  , dt);    // , SLEEP_NETWORK_STANDBY);  // use SETUP BUTTON (20) to wake    (don\t work!)
  expectedWake = Time.now() + dt;      // calculate next wakeup.

And in order to have the timing correct, your (my :sunglasses:) calculation of dt should be done immediately before the System.sleep() call.

Not sure what calculation you mean.

dt = (SLEEP_MINUTES - Time.minute() % SLEEP_MINUTES) * 60 - Time.second();  // wake at next time boundary

or

dt = (now + WAKE_HOUR * 3600) % 86400;

or like this:

..digitalWrite(relay1, LOW);           // turn off relay1/power for the router
  digitalWrite(relay2, LOW);           // turn off relay2/power for the Raspberry Pi
  expectedWake = Time.now() + dt;      // calculate next wakeup.
  System.sleep(SLEEP_MODE_DEEP , dt);  // , SLEEP_NETWORK_STANDBY); go to Deep Sleep

Both those first calculations that set dt
The others just use dt and hence rely on a correctly set value.

Ok, then I don’t understand what to put where, sorry. But it seems to work as expected.

Another thing that come to my mind. At the point of wake up and running setup there is no internet. Internet occurs after 1,5minutes(when in the first delay). How does the Photon sync its clock? Should i initialize a timesync before going to sleep again? If so, how could that be done?

void loop()
{
  // delay(3000);                         // 3sek delay where Photoen is awake but relay/power is off
  digitalWrite(relay1, HIGH);          // turn on relay1/power for the router
  delay(120000);                       // delay for 2 min for the internet to establish
  digitalWrite(relay2, HIGH);          // turn on relay2/power for the Raspberry Pi
  delay(480000);                       // delay for 8 min for the data collection to be finished, then go to deep sleep.

  // ---------------- no own code beyond here ----------------

  uint32_t dt;
  if (WAKE_HOUR <= (uint32_t)Time.hour() && (uint32_t)Time.hour() < SLEEP_HOUR)
  {
    dt = (SLEEP_MINUTES - Time.minute() % SLEEP_MINUTES) * 60 - Time.second();  // wake at next time boundary
  }
  else
  {
    uint32_t now = 86400 - Time.local() % 86400;
    dt = (now + WAKE_HOUR * 3600) % 86400;
  }
  expectedWake = Time.now() + dt;      // calculate next wakeup.

  //System.sleep(SLEEP_MODE_DEEP , dt);  // , SLEEP_NETWORK_STANDBY); go to Deep Sleep
  System.sleep(BTN, FALLING  , dt);    // , SLEEP_NETWORK_STANDBY);  // use SETUP BUTTON (20) to wake    (don\t work!)
}

Why not? Your code is using default SYSTEM_MODE(AUTOMATIC) so the first thing after deep sleep will be the reestablishment of the cloud connection. And that way your code will never start running to switch the router on.
So you’d need to go for another SYSTEM_MODE() and/or SYSTEM_THREAD(ENABLED).
And why would the device need to resync the clock after a few hours sleep? The RTC should have merely a few sec drift per day.

I am hoping someone can help me with this. I have just started learning the photon and C programming. I have two projects that I have use this library on and have found an anomaly with it that has shown up on both projects. At midnight one of the timers will fire randomly. I have caught it occasionally on the console but because of intermittent internet connections the console will drop after several hours so I miss the timer showing up on the console. The project of greatest concern runs a pump for irrigation so I need it to be reliable. When the pump turns on it at midnight it will never turn off. Below is the code I have running for the pump.

//Program Start

//#include "DailyTimerSpark/DailyTimerSpark.h"

int ENABLE_PIN = D0;
int ProblemPump =D5;
int PressureSw = D6; //bypasses pressure switch on pump startup
int RELAY1 = D7;  //Pump relay
DailyTimer timer1(8,00,8,10, EVERY_DAY);      // optional callback function for random number generation, see below example
DailyTimer timer2(9,11,9,11, EVERY_DAY);                                 // default is FIXED, this will randomize the start time only
DailyTimer timer3( 21, 32, 21, 32, EVERY_DAY);                                        // creates with a default fixed start time and end time
bool timer1_LastState = false;

uint32_t lastUpdateTime = 0;

void setup()
{
    Time.zone(-4);
  timer3.begin(); // use this for syncing the state change tools startTrigger() and endTrigger() on startup
  timer2.begin();
  timer1.begin();
  Serial.begin(9600);
  pinMode(ProblemPump,INPUT);
  pinMode(PressureSw, OUTPUT);
  pinMode(ENABLE_PIN, INPUT);
  pinMode(RELAY1, OUTPUT);
  WiFi.selectAntenna(ANT_EXTERNAL);
  timer1.setDaysActive(0B10101000);

}

void loop()
{
  bool timerState = timer1.isActive();  //State Change method this block
  if(timerState != timer1_LastState)
  {
    if(timerState)
    {
        if ( digitalRead(ENABLE_PIN) )
        Particle.publish("DailyTimer", "Pump Disabled", 60, PRIVATE);
        else digitalWrite(RELAY1,HIGH);
        digitalWrite(PressureSw, HIGH);
        delay(3000);
        digitalWrite(PressureSw, LOW);
        Serial.println("PUMP is ON");
        Particle.publish("DailyTimer", "PUMP is ON", 60, PRIVATE);
     }
     else
     {
         if ( digitalRead(ProblemPump) )
         digitalWrite(RELAY1,LOW);
         else Particle.publish("DailyTimer", "Pump Problem", 60, PRIVATE);
         digitalWrite(RELAY1,LOW);
         Particle.publish("DailyTimer", "Pump Off", 60,PRIVATE);
    }
    timer1_LastState = timerState;
    }

  if(timer2.startTrigger())  // Boundary method following blocks
  {
      Serial.println("Timer 2 FIRED!");
    }
  if(timer3.startTrigger())
  {
    Serial.println("Timer 3 FIRED!");
    Particle.publish("DailyTimer", "Timer3 Fired", 60, PRIVATE);
    digitalWrite(RELAY1, LOW);
  Serial.println("LED is OFF");
   Particle.publish("DailyTimer", "LED is OFF", 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);
}

I noticed a am/pm boundary problem and corrected it about 7 months ago… are you working with that (latest) version?

I am using the WEB IDE and pulled the file from there. It should pull the latest I assume each time I do a compile.

Nope, that won’t be the case.
When you import a library, you import that exact version of it and will not get an updated version automatically.

Imagine a library contributor would make breaking changes to his lib and all projects using that lib would get brokend by that.

Makes sense. Thanks for the info.

I’m a bit unclear how to get the automated sunrise/sunset times using the Json Webhook.

I followed the example and created the Webhook, which works correctly, but how do you get the firmware to update that for use with the library?

Have you got the original response from the server reduced to some consumable subset via the custom response pattern in the webhook?
Do you get the webhook response delivered to your device?
Did you parse the response for the desired content? (e.g. using this)