Hey guys,
I want to set up an SMS event when the temp goes down a specific threshold, not a big deal. And I can do it no prob. But the only way I have been able to do it is by hard-coding a custom event. All OK. The problem comes when I have a whole network of motes each in a different location and I want to set up the alerts for different temperatures. This would mean I need to define a new custom event for every single temperature threshold I want.
So, playing with things, I found that I can add any specific "setting" to my custom mote. Currently I have this:
settings: {
lowTempValue: '',
highTempValue: '',
lowVoltageValue: ''}, //blank will make it inherit from global settings.json lowVoltageValue, a specific value overrides the general setting, user can always choose his own setting in the UI
},
And I added the settings:
lowTempValue: {
value: 20,
type: 'range',
min:15,
max:25,
description: "a warning icon is shown over the node Icon when the node's voltage is less than this value (typically around 3.5v for a standard Moteino)"
},
highTempValue: {
value: 28,
type: 'range',
min:25,
max:32,
description: "a warning icon is shown over the node Icon when the node's voltage is less than this value (typically around 3.5v for a standard Moteino)"
},
Which works great. I now have the three sliders on each of my custom motes:
(http://www.oscarfrias.com/files/img/moteino_customSettings.PNG)
Now, the question is: Is there a way in which I can program my SMS event to pull the threshold from the individual setting of the mote, instead of the hard-coded value in the event?
Reading through the gateway.js, I see that at the very beginning it's pulling some values from the settings file, I think I want to do the same, but from each specific mote. Any ideas? (see the settings.serial.baud.value call)
nconf.argv().file({ file: path.resolve(__dirname, 'settings.json5'), format: JSON5 });
settings = nconf.get('settings');
serial = new serialport.SerialPort(settings.serial.port.value, { baudrate : settings.serial.baud.value, parser: serialport.parsers.readline("\n") }, false);
Thanks!
Frix
So, it works!
Super simple, just replace the hard-coded value statement in your event for the value of the node setting. Meaning, change this:
if (node.metrics['C'] && node.metrics['C'].value > 30 && (Date.now() - node.metrics['C'].updated < 2000))
To this:
if (node.metrics['C'] && node.metrics['C'].value > node.settings['highTempValue'] && (Date.now() - node.metrics['C'].updated < 2000))
And voila! dynamic, node-specific events. I can confirm with a bunch of text messages that it's working just fine.
Here's a snippet from my custom_metrics.js file with all the function for your reference:
exports.events ={
tempTooHotSMSLimiter : { label:'TooHotAlert : SMS', icon:'comment', descr:'Send SMS when Temp is > than the setting max, once per hour',
serverExecute:function(node) {
if (node.metrics['C'] && node.metrics['C'].value > node.settings['highTempValue'] && (Date.now() - node.metrics['C'].updated < 2000)) /*check if M metric exists and value is MOTION, received less than 2s ago*/
{
var approveSMS = false;
if (node.metrics['C'].lastSMS) /*check if lastSMS value is not NULL ... */
{
if (Date.now() - node.metrics['C'].lastSMS > 1800000) /*check if lastSMS timestamp is more than 1hr ago*/
{
approveSMS = true;
}
}
else
{
approveSMS = true;
}
if (approveSMS)
{
node.metrics['C'].lastSMS = Date.now();
sendSMS('Too hot!', 'Temperature alert on: [' + node._id + '] :' + node.label.replace(/\{.+\}/ig, '') + ' @ ' + new Date().toLocaleTimeString());
db.update({ _id: node._id }, { $set : node}, {}, function (err, numReplaced) { console.log(' ['+node._id+'] DB-Updates:' + numReplaced);}); /*save lastSMS timestamp to DB*/
}
else console.log(' ['+node._id+'] TooHotAlert SMS skipped.');
};
}
},
tempTooColdSMSLimiter : { label:'TooColdAlert : SMS', icon:'comment', descr:'Send SMS when Temp is < than the setting min, once per hour',
serverExecute:function(node) {
if (node.metrics['C'] && node.metrics['C'].value < node.settings['lowTempValue'] && (Date.now() - node.metrics['C'].updated < 2000)) /*check if M metric exists and value is MOTION, received less than 2s ago*/
{
var approveSMS = false;
if (node.metrics['C'].lastSMS) /*check if lastSMS value is not NULL ... */
{
if (Date.now() - node.metrics['C'].lastSMS > 1800000) /*check if lastSMS timestamp is more than 1hr ago */
{
approveSMS = true;
}
}
else
{
approveSMS = true;
}
if (approveSMS)
{
node.metrics['C'].lastSMS = Date.now();
sendSMS('Too cold!', 'Temperature alert on: [' + node._id + '] :' + node.label.replace(/\{.+\}/ig, '') + ' @ ' + new Date().toLocaleTimeString());
db.update({ _id: node._id }, { $set : node}, {}, function (err, numReplaced) { console.log(' ['+node._id+'] DB-Updates:' + numReplaced);}); /*save lastSMS timestamp to DB*/
}
else console.log(' ['+node._id+'] TooColdAlert SMS skipped.');
};
}
},
};
exports.motes = {
MyMote: {
label : 'Temp Node',
icon : 'icon_temperature2.png',
settings: {
lowTempValue: '',
highTempValue: '',
lowVoltageValue: ''}, //blank will make it inherit from global settings.json lowVoltageValue, a specific value overrides the general setting, user can always choose his own setting in the UI
},
};
Enjoy!
Frix
Nice contributions, thanks for sharing the awesome :)