node-red-contrib-topic-timeframe-trigger
Advanced tools
Comparing version 0.1.0 to 0.2.0
67
index.js
@@ -31,28 +31,56 @@ /** | ||
RED.nodes.registerType('topic-timeframe-trigger', function (config) { | ||
RED.nodes.createNode(this, config); | ||
var node = this; | ||
var topics = null; | ||
var timeout; | ||
var node = this, | ||
triggers = null, | ||
timeout = null, | ||
globalConfig = { | ||
debug: false | ||
}; | ||
function getGlobalConfig() { | ||
return _.assign(globalConfig, node.context().global.get('topic-timeframe-trigger')); | ||
} | ||
function debug() { | ||
if (getGlobalConfig().debug) node.log.apply(node, arguments); | ||
} | ||
node.on('input', function (msg) { | ||
if (!msg.topic) { | ||
node.status({fill: 'red', shape: 'dot', text: 'Msg has no topic'}); | ||
node.error('Message has no topic: ' + msg.payload); | ||
node.status({ | ||
fill: 'red', | ||
shape: 'dot', | ||
text: 'Msg has no topic' | ||
}); | ||
return; | ||
} | ||
if (!topics) { | ||
if (!triggers) { | ||
timeout = setTimeout(reset, config.timeframe * 1000); | ||
topics = {}; | ||
triggers = []; | ||
} | ||
var topicCount = topics[msg.topic]; | ||
topics[msg.topic] = !topicCount ? 1 : topicCount + 1; | ||
triggers.push(msg); | ||
var countExceeded = _.filter(topics, function (count) { | ||
return count >= config.count; | ||
var grouped = _.groupBy(triggers, 'topic'); | ||
var countExceeded = _.filter(grouped, function (msgs) { | ||
return msgs.length >= config.count; | ||
}); | ||
if (countExceeded.length >= config.topics) { | ||
debug('Triggered by count: ' + countExceeded.length); | ||
node.send({ | ||
topic: config.triggeredtopic, | ||
payload: config.triggeredpayload, | ||
triggers: triggers | ||
}); | ||
reset(); | ||
node.send({topic: config.triggeredtopic, payload: config.triggeredpayload}); | ||
// node.status({fill: 'green', shape: 'dot', text: 'Triggered: ' + config.triggeredtopic}); | ||
} else { | ||
node.status({fill: 'green', shape: 'dot', text: msg.topic + ':' + topics[msg.topic]}); | ||
debug('Msg received: ' + msg.topic + ' => ' + grouped[msg.topic].length); | ||
node.status({ | ||
fill: 'green', | ||
shape: 'dot', | ||
text: msg.topic + ':' + grouped[msg.topic].length | ||
}); | ||
} | ||
@@ -62,3 +90,7 @@ }); | ||
node.on('close', reset); | ||
node.status({fill: 'blue', shape: 'dot', text: 'Idle'}); | ||
node.status({ | ||
fill: 'blue', | ||
shape: 'dot', | ||
text: 'Idle' | ||
}); | ||
@@ -70,6 +102,11 @@ function reset() { | ||
} | ||
topics = null; | ||
node.status({fill: 'blue', shape: 'dot', text: 'Idle'}); | ||
triggers = null; | ||
node.status({ | ||
fill: 'blue', | ||
shape: 'dot', | ||
text: 'Idle' | ||
}); | ||
debug('Timeframe reset after ' + config.timeframe + 's'); | ||
} | ||
}); | ||
}; |
{ | ||
"name": "node-red-contrib-topic-timeframe-trigger", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "Node-RED node which observes input topics and only produces an output if n distinct topics are received n times each within the specified time frame.", | ||
@@ -28,4 +28,20 @@ "main": "index.js", | ||
"devDependencies": { | ||
"chai": "^3.5.0" | ||
"chai": "^3.5.0", | ||
"mocha": "^3.5.0", | ||
"eslint": "^3.19.0", | ||
"eslint-config-biddster": "^0.3.0", | ||
"node-red-contrib-mock-node": "^0.3.0" | ||
}, | ||
"eslintConfig": { | ||
"env": { | ||
"es6": true, | ||
"node": true, | ||
"mocha": true | ||
}, | ||
"parserOptions": { | ||
"ecmaVersion": 6, | ||
"sourceType": "module" | ||
}, | ||
"extends": "eslint-config-biddster/es6-node" | ||
}, | ||
"node-red": { | ||
@@ -36,2 +52,2 @@ "nodes": { | ||
} | ||
} | ||
} |
@@ -11,2 +11,11 @@ # node-red-contrib-topic-timeframe-trigger | ||
### Outputs | ||
When enough messages are received to trigger, a message is output as per the configuration. In addition, all of the messages received within the | ||
timeframe are added to the message as an array property called `triggers`. | ||
### Enabling extra debugging | ||
Install `node-red-contrib-config` and drag a config node into your workspace. Configure the node to set a global variable called `topic-timeframe-trigger` | ||
with a JSON value of `{"debug": true}`. Also make sure that the config tickbox for `active` is unchecked. Redeploy. Now click the button on the config node. | ||
This will trigger all instances of `topic-timeframe-trigger` to write extra logging to the os syslog next time they're invoked. |
@@ -28,45 +28,3 @@ /** | ||
var _ = require('lodash'); | ||
function loadNode(config, redModule) { | ||
var _events = [], _status = undefined, _error = undefined, _messages = []; | ||
var RED = { | ||
nodes: { | ||
registerType: function (nodeName, nodeConfigFunc) { | ||
this.nodeConfigFunc = nodeConfigFunc; | ||
}, | ||
createNode: function () { | ||
} | ||
}, | ||
on: function (event, eventFunc) { | ||
_events[event] = eventFunc; | ||
}, | ||
emit: function (event, data) { | ||
_events[event](data); | ||
}, | ||
error: function (error) { | ||
if (error) _error = error; | ||
return _error; | ||
}, | ||
status: function (status) { | ||
if (status) _status = status; | ||
return _status; | ||
}, | ||
log: function () { | ||
console.log.apply(this, arguments); | ||
}, | ||
send: function (msg) { | ||
assert(msg); | ||
_messages.push(msg); | ||
}, | ||
messages: function (messages) { | ||
if (messages) _messages = messages; | ||
return _messages; | ||
} | ||
}; | ||
redModule(RED); | ||
RED.nodes.nodeConfigFunc.call(RED, config); | ||
return RED; | ||
} | ||
var mock = require('node-red-contrib-mock-node'); | ||
var nodeRedModule = require('../index.js'); | ||
@@ -77,3 +35,33 @@ | ||
it('should work', function () { | ||
var node = newNode(); | ||
var msg1 = { | ||
topic: 't1', | ||
payload: 'p1' | ||
}; | ||
node.emit('input', msg1); | ||
var msg2 = { | ||
topic: 't2', | ||
payload: 'p2' | ||
}; | ||
node.emit('input', msg2); | ||
assert.strictEqual(node.sent(0).payload, 'triggered payload'); | ||
assert.strictEqual(node.sent(0).topic, 'triggered topic'); | ||
assert.strictEqual(node.sent(0).triggers[0], msg1); | ||
assert.strictEqual(node.sent(0).triggers[1], msg2); | ||
}); | ||
}); | ||
function newNode(configOverrides) { | ||
var config = { | ||
timeframe: 1000, | ||
count: 1, | ||
topics: 2, | ||
triggeredtopic: 'triggered topic', | ||
triggeredpayload: 'triggered payload' | ||
}; | ||
if (configOverrides) { | ||
_.assign(config, configOverrides); | ||
} | ||
return mock(nodeRedModule, config); | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
11939
148
21
5