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?
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'});
}
},
};
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:
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'});
}
},
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:
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'});
}
},
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 (https://lowpowerlab.com/forum/pi-gateway/pi-gateway-datastore-js-issue/) at 06:36 AM, so I need to re-visit this. Needless to say, don't use my above example!
[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 =]
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:
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'});
}
},