forked from bartbutenaers/node-red-contrib-msg-speed
-
Notifications
You must be signed in to change notification settings - Fork 0
/
msg_speed.js
103 lines (83 loc) · 3.98 KB
/
msg_speed.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
module.exports = function(RED) {
"use strict";
var CircularBuffer = require("circular-buffer");
var Math = require("mathjs");
function speed(config) {
RED.nodes.createNode(this, config);
// The buffer size depends on the frequency
switch(config.frequency) {
case 'sec':
this.bufferSize = 1;
break;
case 'min':
this.bufferSize = 60;
break;
case 'hour':
this.bufferSize = 60 * 60;
break;
case 'day':
this.bufferSize = 24 * 60 * 60;
break;
default:
this.bufferSize = 1; // Default 'sec'
}
this.circularBuffer = new CircularBuffer(this.bufferSize);
// Fill the buffer with zeros
for (var i = 0; i < this.bufferSize; i++) {
this.circularBuffer.enq(0);
}
this.frequency = config.frequency || 'sec';
this.msgCount = 0;
this.prevTotalMsgCount = 0;
this.totalMsgCount = 0;
this.startTime = null;
this.timer = null;
var analyse = function() {
var currentTime = new Date().getTime();
if (node.startTime == null) {
node.startTime = currentTime;
}
// Store the message count (of the previous second) in the circular buffer. However the timer can be
// delayed, so make sure this is done for EVERY second since the last time we got here ...
var seconds = Math.round((currentTime - node.startTime) / 1000);
for(var i = 0; i < seconds; i++) {
// The total msg count is the sum of all message counts in the circular buffer. Instead of summing
// those continiously, we will update the sum together with the buffer content.
// Sum = previous sum + message count of last second (which is going to be added to the buffer)
// - message count of the first second (which is going to be removed from the buffer).
node.totalMsgCount += node.msgCount;
node.totalMsgCount -= node.circularBuffer.get(node.bufferSize-1);
node.circularBuffer.enq(node.msgCount);
// Update the status in the editor with the last message count (only if it has changed)
if (node.prevTotalMsgCount != node.totalMsgCount) {
node.status({fill:"green",shape:"dot",text:" " + node.totalMsgCount + "/" + node.frequency });
node.prevTotalMsgCount = node.totalMsgCount;
}
node.send({ payload: node.totalMsgCount, frequency: node.frequency });
if (RED.settings.verbose) {
console.log(new Date().toISOString() + " " + node.totalMsgCount);
}
// Start counting all over again (for the next seconds)
node.msgCount = 0;
node.startTime = currentTime;
}
}
var node = this;
// Initially display a 0 count
node.status({fill:"green",shape:"dot",text:" " + node.msgCount + "/" + node.frequency });
this.on("input", function(msg) {
if (node.timer) {
// An msg has arrived during the specified (timeout) interval, so remove the (timeout) timer.
clearInterval(node.timer);
}
node.msgCount += 1;
analyse();
// Register a new timer (with a timeout interval of 1 second), in case no msg should arrive during the next second.
node.timer = setInterval(function() {
// Seems no msg has arrived during the last second, so register a zero count
analyse();
}, 1000);
});
}
RED.nodes.registerType("msg-speed", speed);
};