Author Topic: example UserMetrics events timing  (Read 489 times)

gigawatts

  • NewMember
  • *
  • Posts: 23
example UserMetrics events timing
« on: March 03, 2020, 03:37:02 PM »
I am trying to create a custom event that triggers once per month.

I have looked through some of the examples in https://github.com/LowPowerLab/RaspberryPi-Gateway/blob/master/userMetrics/

Is this the cleanest way to trigger a monthly message to a node? The event itself will run every day at the specified time, but will only send a message on the 1st of the month?

Code: [Select]
exports.events = {
  resetWaterGal_monthly : {
    label:'WaterMote: Reset Gallons Total metric',
    icon:'clock',
    descr:'Runs @ midnight on the first day of every month',
    nextSchedule:function(node) { return exports.timeoutOffset(0,00); },
    scheduledExecute:function(node) {
      if (new Date().getDate()==1) sendMessageToNode({nodeId:node._id, action:'GALRST'});
    }
  },

};

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6533
  • Country: us
    • LowPowerLab
Re: example UserMetrics events timing
« Reply #1 on: March 04, 2020, 02:25:25 PM »
Just look in the metrics.js examples. And use more readable macros that are provided. For instance without getting fancy, you could do it in 30 day intervals:

Code: [Select]
resetWaterGal_monthly : {
  label:'WaterMote: Reset Gallons Total metric',
  icon:'clock',
  descr:'Runs @ midnight on the first day of every month',
  nextSchedule:function(node) {
    return exports.millisToFutureDate(exports.ONEDAY*30); },
  scheduledExecute:function(node) {
    sendMessageToNode({nodeId:node._id, action:'GALRST'});
    }
},

gigawatts

  • NewMember
  • *
  • Posts: 23
Re: example UserMetrics events timing
« Reply #2 on: November 23, 2020, 11:02:49 PM »
I finally found the time to re-write the custom event so that it doesn't show itself as running every day a midnight (but actually skips due to that if statement), and instead has a proper countdown to midnight on the first day of the coming month:

Code: [Select]
  resetWaterGal_monthly : {
    label:'WaterMote: Reset Gallons Total metric monthly',
    icon:'clock',
    descr:'Runs @ midnight on the first day of every month',
    nextSchedule:function(node) {
      var today = new Date();
      var firstDayOfNextMonth = new Date(today.getFullYear(), today.getMonth()+1, 1);
      return exports.millisToFutureDate(firstDayOfNextMonth);
    },
    scheduledExecute:function(node) {
      sendMessageToNode({nodeId:node._id, action:'GALRST'});
    }
  },

gigawatts

  • NewMember
  • *
  • Posts: 23
Re: example UserMetrics events timing
« Reply #3 on: December 01, 2020, 09:32:13 PM »
Soooo, this worked a little too well. Instead of only firing ONCE at mid-night, it fired continuously (I estimated about 100 times per second) starting at midnight, and inflated my gateway.db file until it broke at 06:36 AM, so I need to re-visit this. Needless to say, don't use my above example!

Code: [Select]
[11-30-20_23:59:58.015] [LOG]    >: [5] GAL:2738.83 GPM:0.0 PUL:273883   [RSSI:-39]
[11-30-20_23:59:58.019] [LOG]    post: /home/pi/gateway-v9.0.0/data/db/0005_GPM.bin[1606802398,0]
[11-30-20_23:59:58.024] [LOG]    post: /home/pi/gateway-v9.0.0/data/db/0005_RSSI.bin[1606802398,-39]
[11-30-20_23:59:58.031] [LOG]       [5] DB-Updates:1
[12-01-20_00:00:00.007] [LOG]    **** RUNNING SCHEDULED EVENT - nodeId:5 event:resetWaterGal_monthly...
[12-01-20_00:00:00.010] [LOG]    NODEACTION: {"nodeId":5,"action":"GALRST"}
[12-01-20_00:00:00.011] [LOG]    **** SCHEDULING EVENT - nodeId:5 event:resetWaterGal_monthly to run in ~743h59m
[12-01-20_00:00:00.014] [ERROR]  (node:26715) TimeoutOverflowWarning: 2678399989 does not fit into a 32-bit signed integer.
Timeout duration was set to 1.
[12-01-20_00:00:00.015] [LOG]    **** RUNNING SCHEDULED EVENT - nodeId:5 event:resetWaterGal_monthly...
[12-01-20_00:00:00.020] [LOG]    NODEACTION: {"nodeId":5,"action":"GALRST"}
[12-01-20_00:00:00.021] [LOG]    **** SCHEDULING EVENT - nodeId:5 event:resetWaterGal_monthly to run in ~743h59m
[12-01-20_00:00:00.023] [ERROR]  (node:26715) TimeoutOverflowWarning: 2678399979 does not fit into a 32-bit signed integer.
Timeout duration was set to 1.
[12-01-20_00:00:00.025] [LOG]    **** RUNNING SCHEDULED EVENT - nodeId:5 event:resetWaterGal_monthly...
[12-01-20_00:00:00.031] [LOG]       [5] DB-Updates:1
[12-01-20_00:00:00.034] [LOG]    NODEACTION: {"nodeId":5,"action":"GALRST"}
[12-01-20_00:00:00.035] [LOG]    **** SCHEDULING EVENT - nodeId:5 event:resetWaterGal_monthly to run in ~743h59m
[12-01-20_00:00:00.037] [ERROR]  (node:26715) TimeoutOverflowWarning: 2678399965 does not fit into a 32-bit signed integer.
Timeout duration was set to 1.
[12-01-20_00:00:00.039] [LOG]    **** RUNNING SCHEDULED EVENT - nodeId:5 event:resetWaterGal_monthly...
[12-01-20_00:00:00.044] [LOG]       [5] DB-Updates:1
[12-01-20_00:00:00.047] [LOG]    NODEACTION: {"nodeId":5,"action":"GALRST"}
[12-01-20_00:00:00.049] [LOG]    **** SCHEDULING EVENT - nodeId:5 event:resetWaterGal_monthly to run in ~743h59m
[12-01-20_00:00:00.050] [ERROR]  (node:26715) TimeoutOverflowWarning: 2678399952 does not fit into a 32-bit signed integer.
Timeout duration was set to 1.


If anyone would like to point out where I went wrong there, so myself and others can learn from the mistake, I welcome the feedback =]
« Last Edit: December 01, 2020, 10:46:52 PM by gigawatts »

Uncle Buzz

  • Full Member
  • ***
  • Posts: 144
  • Country: fr
Re: example UserMetrics events timing
« Reply #4 on: December 03, 2020, 03:53:22 AM »
I don't use the Pi Gateway, so I can't help you to make it work, but I can tell you why it's not working :

Code: [Select]
[12-01-20_00:00:00.011] [LOG]    **** SCHEDULING EVENT - nodeId:5 event:resetWaterGal_monthly to run in ~743h59m
[12-01-20_00:00:00.014] [ERROR]  (node:26715) TimeoutOverflowWarning: 2678399989 does not fit into a 32-bit signed integer.
Timeout duration was set to 1.

I don't know why exports.millisToFutureDate returns a 32-bit signed integer instead of a 32-bit unsigned integer.
With a 32-bit unsigned integer, you can wait about [0; 49] days before overflowing the milliseconds counter, so with a 32 bit signed integer counter, you overflow at about 49/2 = 24 days [-24; 24], which is less than a month.

Your log tells you what's wrong :
Quote
TimeoutOverflowWarning: 2678399989 does not fit into a 32-bit signed integer.
Since you overflow the 32-bit signed integer value, the default value of 1ms is used instead.

You have to find another way to schedule your event for more than 24 days. Maybe schedule a smaller interval with a counter and execute your function every 2 events?
« Last Edit: December 03, 2020, 03:56:18 AM by Uncle Buzz »

gigawatts

  • NewMember
  • *
  • Posts: 23
Re: example UserMetrics events timing
« Reply #5 on: December 07, 2020, 01:51:58 PM »
Thank you Uncle Buzz, that explains exactly why when I implemented it half way through November, that it had a proper scheduled countdown till Dec 1st 00:00, but then freaked out when it had more than 24 days till the next event.

I fell back to the way I was running it before, which schedules itself every 24 hours at 00:00, but skips the execute action with an IF statement if the day of the month is not "1". I just personally didn't like that method (even though it works just fine), because I like seeing the countdown properly represent when the next reset event will be, instead of just counting down every day till midnight.

This is my old (but working) version that I'm using again for now:
Code: [Select]
  resetWaterGal_monthly : {
    label:'WaterMote: Reset Gallons Total metric',
    icon:'clock',
    descr:'Runs @ midnight on the first day of every month',
    nextSchedule:function(node) { return exports.timeoutOffset(0,00); },
    scheduledExecute:function(node) {
      if (new Date().getDate()==1) sendMessageToNode({nodeId:node._id, action:'GALRST'});
    }
  },