Syncing device at certain times of the day

In my use case, I must sync the device in 9.30, 14.30, 21.30 and 02.30 every day. So 5 h, 7h, 5h, 7h.
Can you please take a look at my code I have modeled it after one of the default apps I found on your server. Is everything ok with it, is this the simplest way to do this or is there a better way?
Is it interfering with the ‘stolen’ mode the way it is written?

 var TRIGGER_TIME9 = {
   hour: 15, // 0-23
   minute: 30 // 0-59
 };
 
 var TRIGGER_TIME14 = {
   hour: 15, // 0-23
   minute: 33 // 0-59
 };
 
 var TRIGGER_TIME19 = {
   hour: 15, // 0-23
   minute: 35 // 0-59
 };
 
 var TRIGGER_TIME0 = {
   hour: 15, // 0-23
   minute: 39 // 0-59
 };
 
 
 
 function runTaskAndScheduleNext9() {
   runTask( location.startUpdates((position) => {
       cloud.enqueue('position-change', { lat: position.lat, long: position.long});
     }, {minInterval: 10, minDistance: 10.2, timeout: 120}));
   scheduleNextTask(timers.at(TRIGGER_TIME14, runTaskAndScheduleNext14));
 }
 
 
 timers.at(TRIGGER_TIME9, runTaskAndScheduleNext9);
 
 
 function runTaskAndScheduleNext14() {
   runTask( location.startUpdates((position) => {
       cloud.enqueue('position-change', { lat: position.lat, long: position.long});
     }, {minInterval: 10, minDistance: 10.2, timeout: 120}));
   scheduleNextTask(timers.at(TRIGGER_TIME19, runTaskAndScheduleNext19));
 }
 
 
 timers.at(TRIGGER_TIME14, runTaskAndScheduleNext14);
 
 
 function runTaskAndScheduleNext19() {
   runTask( location.startUpdates((position) => {
       cloud.enqueue('position-change', { lat: position.lat, long: position.long});
     }, {minInterval: 10, minDistance: 10.2, timeout: 120}));
   scheduleNextTask(timers.at(TRIGGER_TIME0, runTaskAndScheduleNext0));
 }
 
 timers.at(TRIGGER_TIME19, runTaskAndScheduleNext19);
 
 function runTaskAndScheduleNext0() {
   runTask( location.startUpdates((position) => {
       cloud.enqueue('position-change', { lat: position.lat, long: position.long});
     }, {minInterval: 10, minDistance: 10.2, timeout: 120}));
   scheduleNextTask(timers.at(TRIGGER_TIME9, runTaskAndScheduleNext9));
 }
 
 timers.at(TRIGGER_TIME0, runTaskAndScheduleNext0);
 
 
 
 
 // updating location every 4 hours conserving battery 
 location.startUpdates((position) => {
       cloud.enqueue('position-change', { lat: position.lat, long: position.long});
     }, { minInterval: 120, minDistance: 0, timeout: 0});
 
 // button turns alarm mode 
 io.press(() => {
     sync.setSyncPeriod(300);
     sync.now();
     print('ALARM MODE');
     
     location.startUpdates((position) => {
       cloud.enqueue('position-change', { lat: position.lat, long: position.long});
     }, { minInterval: 0, minDistance: 1, timeout: 0});
     print('cordinates are send to cloud');
       
 });
 
 // alarm mode activated from distance 
 cloud.onReceive( msg => {
  if(msg.type === 'stolen') {
   sync.setSyncPeriod(msg.payload.sync_period);}
   
 }
 );

Your code won’t work, because timers.at needs a JavaScript Date object with the date + time, but instead you’re passing {hour: 15, minute: 30}. The example app uses an extra function, computeNextTriggerDate, to convert between the two.

If you need to have multiple triggers a day, modify these three functions in the example slightly to allow specifying which trigger time to use, instead of using a single, hard-coded value:

function computeNextTriggerDate(afterThisDate, triggerTime) {
  var nextTriggerDate = new Date(afterThisDate);
  
  nextTriggerDate.setUTCHours(triggerTime.hour);
  nextTriggerDate.setUTCMinutes(triggerTime.minute);
  nextTriggerDate.setUTCSeconds(0);
  nextTriggerDate.setUTCMilliseconds(0);

  if (nextTriggerDate.getTime() <= afterThisDate.getTime()) {
    // it's already past the trigger time today, let's schedule it for tomorrow
    nextTriggerDate.setUTCDate(nextTriggerDate.getUTCDate() + 1);
    // note: this will wrap around properly on the last day of the month/year
  }
  
  return nextTriggerDate;
}

function scheduleNextTask(triggerTime) {
  var currentDate = new Date();
  print('current date: ' + currentDate.toUTCString());
  
  var nextTriggerDate = computeNextTriggerDate(currentDate, triggerTime);
  print('next trigger date: ' + nextTriggerDate.toUTCString());
  
  var triggerTimestamp = nextTriggerDate.getTime();
  timers.at(triggerTimestamp, () => runTaskAndScheduleNext(triggerTime));
}

function runTaskAndScheduleNext(triggerTime) {
  runTask();
  scheduleNextTask(triggerTime);
}

And then you can do what you were trying to do:

scheduleNextTask(TRIGGER_TIME9);
scheduleNextTask(TRIGGER_TIME14);
// etc.

Oh, and don’t do this:

runTask(location.startUpdates((position) => {
   cloud.enqueue('position-change', { lat: position.lat, long: position.long});
}, {minInterval: 10, minDistance: 10.2, timeout: 120}));

I believe it will technically work, but is a bit confusing. (You’re starting location updates, and passing the promise it returns to runTask, but runTask doesn’t expect any arguments. And in fact, the piece of code you posted doesn’t even have a runTask function, so that’ll throw an error.)

Instead, as the comment inside runTask suggests, put your code inside runTask:

function runTask() {
  print('running the scheduled task');
  
  // put your task here ...
  location.startUpdates((position) => {
   cloud.enqueue('position-change', {lat: position.lat, long: position.long});
  }, {minInterval: 10, minDistance: 10.2, timeout: 120})
}
1 Like

Thanks for the detailed answer