mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Delay node enhancements (#2294)
* Remove unused messages in message catalog
* Support msg.rate in delay node
* Support nodeMessageBufferMaxLength in delay node
* Add logging function for queue size
* Support msg.nodeMessageBufferMaxLength
* Revert "Support msg.nodeMessageBufferMaxLength"
This reverts commit cc72f892f7
.
* Improve logging function for delay node
* Add support for Messaging API to delay node
* Add documentation about msg.rate in delay node
* Add test cases for msg.rate in delay node
Co-authored-by: Dave Conway-Jones <dceejay@users.noreply.github.com>
This commit is contained in:
parent
719aea2a58
commit
a20049c82a
@ -20,6 +20,20 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
var MILLIS_TO_NANOS = 1000000;
|
var MILLIS_TO_NANOS = 1000000;
|
||||||
var SECONDS_TO_NANOS = 1000000000;
|
var SECONDS_TO_NANOS = 1000000000;
|
||||||
|
var _maxKeptMsgsCount;
|
||||||
|
|
||||||
|
function maxKeptMsgsCount(node) {
|
||||||
|
if (_maxKeptMsgsCount === undefined) {
|
||||||
|
var name = "nodeMessageBufferMaxLength";
|
||||||
|
if (RED.settings.hasOwnProperty(name)) {
|
||||||
|
_maxKeptMsgsCount = RED.settings[name];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_maxKeptMsgsCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _maxKeptMsgsCount;
|
||||||
|
}
|
||||||
|
|
||||||
function DelayNode(n) {
|
function DelayNode(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
@ -78,6 +92,7 @@ module.exports = function(RED) {
|
|||||||
this.randomID = -1;
|
this.randomID = -1;
|
||||||
this.lastSent = null;
|
this.lastSent = null;
|
||||||
this.drop = n.drop;
|
this.drop = n.drop;
|
||||||
|
this.droppedMsgs = 0;
|
||||||
var node = this;
|
var node = this;
|
||||||
|
|
||||||
function ourTimeout(handler, delay, clearHandler) {
|
function ourTimeout(handler, delay, clearHandler) {
|
||||||
@ -88,6 +103,19 @@ module.exports = function(RED) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sendMsgFromBuffer = function() {
|
||||||
|
if (node.buffer.length === 0) {
|
||||||
|
clearInterval(node.intervalID);
|
||||||
|
node.intervalID = -1;
|
||||||
|
}
|
||||||
|
if (node.buffer.length > 0) {
|
||||||
|
const msgInfo = node.buffer.shift();
|
||||||
|
msgInfo.send(msgInfo.msg);
|
||||||
|
msgInfo.done();
|
||||||
|
}
|
||||||
|
node.reportDepth();
|
||||||
|
}
|
||||||
|
|
||||||
var clearDelayList = function(s) {
|
var clearDelayList = function(s) {
|
||||||
for (var i=0; i<node.idList.length; i++ ) { node.idList[i].clear(); }
|
for (var i=0; i<node.idList.length; i++ ) { node.idList[i].clear(); }
|
||||||
node.idList = [];
|
node.idList = [];
|
||||||
@ -112,6 +140,14 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var loggerId = setInterval(function () {
|
||||||
|
if (node.droppedMsgs !== 0) {
|
||||||
|
node.debug("node.droppedMsgs = " + node.droppedMsgs);
|
||||||
|
node.droppedMsgs = 0;
|
||||||
|
}
|
||||||
|
}, 15 * 1000);
|
||||||
|
node.on("close", function() { clearInterval(loggerId); });
|
||||||
|
|
||||||
if (node.pauseType === "delay") {
|
if (node.pauseType === "delay") {
|
||||||
node.on("input", function(msg, send, done) {
|
node.on("input", function(msg, send, done) {
|
||||||
if (msg.hasOwnProperty("flush")) { flushDelayList(); done(); }
|
if (msg.hasOwnProperty("flush")) { flushDelayList(); done(); }
|
||||||
@ -166,28 +202,32 @@ module.exports = function(RED) {
|
|||||||
done();
|
done();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node.drop) {
|
if (!node.drop) {
|
||||||
var m = RED.util.cloneMessage(msg);
|
var m = RED.util.cloneMessage(msg);
|
||||||
delete m.flush;
|
delete m.flush;
|
||||||
if (node.intervalID !== -1) {
|
if (node.intervalID !== -1) {
|
||||||
node.buffer.push({msg: m, send: send, done: done});
|
if (msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate)) && node.rate !== msg.rate) {
|
||||||
node.reportDepth();
|
node.rate = msg.rate;
|
||||||
|
clearInterval(node.intervalID);
|
||||||
|
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||||
|
}
|
||||||
|
var max_msgs = maxKeptMsgsCount(node);
|
||||||
|
if ((max_msgs > 0) && (node.buffer.length >= max_msgs)) {
|
||||||
|
node.buffer = [];
|
||||||
|
node.error(RED._("delay.errors.too-many"), msg);
|
||||||
|
} else {
|
||||||
|
node.buffer.push({msg: m, send: send, done: done});
|
||||||
|
node.reportDepth();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
|
||||||
|
node.rate = msg.rate;
|
||||||
|
}
|
||||||
send(m);
|
send(m);
|
||||||
node.reportDepth();
|
node.reportDepth();
|
||||||
node.intervalID = setInterval(function() {
|
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||||
if (node.buffer.length === 0) {
|
|
||||||
clearInterval(node.intervalID);
|
|
||||||
node.intervalID = -1;
|
|
||||||
}
|
|
||||||
if (node.buffer.length > 0) {
|
|
||||||
const msgInfo = node.buffer.shift();
|
|
||||||
msgInfo.send(msgInfo.msg);
|
|
||||||
msgInfo.done();
|
|
||||||
}
|
|
||||||
node.reportDepth();
|
|
||||||
}, node.rate);
|
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
if (msg.hasOwnProperty("flush")) {
|
if (msg.hasOwnProperty("flush")) {
|
||||||
@ -201,17 +241,40 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var timeSinceLast;
|
if (maxKeptMsgsCount(node) > 0) {
|
||||||
if (node.lastSent) {
|
if (node.intervalID === -1) {
|
||||||
timeSinceLast = process.hrtime(node.lastSent);
|
node.send(msg);
|
||||||
}
|
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||||
if (!node.lastSent) { // ensuring that we always send the first message
|
} else {
|
||||||
node.lastSent = process.hrtime();
|
if (msg.hasOwnProperty("rate") && node.rate !== msg.rate) {
|
||||||
send(msg);
|
node.rate = msg.rate;
|
||||||
}
|
clearInterval(node.intervalID);
|
||||||
else if ( ( (timeSinceLast[0] * SECONDS_TO_NANOS) + timeSinceLast[1] ) > (node.rate * MILLIS_TO_NANOS) ) {
|
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||||
node.lastSent = process.hrtime();
|
}
|
||||||
send(msg);
|
if (node.buffer.length < _maxKeptMsgsCount) {
|
||||||
|
var m = RED.util.cloneMessage(msg);
|
||||||
|
node.buffer.push({msg: m, send: send, done: done});
|
||||||
|
} else {
|
||||||
|
node.trace("dropped due to buffer overflow. msg._msgid = " + msg._msgid);
|
||||||
|
node.droppedMsgs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (msg.hasOwnProperty("rate")) {
|
||||||
|
node.rate = msg.rate;
|
||||||
|
}
|
||||||
|
var timeSinceLast;
|
||||||
|
if (node.lastSent) {
|
||||||
|
timeSinceLast = process.hrtime(node.lastSent);
|
||||||
|
}
|
||||||
|
if (!node.lastSent) { // ensuring that we always send the first message
|
||||||
|
node.lastSent = process.hrtime();
|
||||||
|
send(msg);
|
||||||
|
}
|
||||||
|
else if ( ( (timeSinceLast[0] * SECONDS_TO_NANOS) + timeSinceLast[1] ) > (node.rate * MILLIS_TO_NANOS) ) {
|
||||||
|
node.lastSent = process.hrtime();
|
||||||
|
send(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,567 @@
|
|||||||
"errors": {
|
"errors": {
|
||||||
"nooverride": "Warnung: Nachrichten-Eigenschaften können die Eigenschaften des festgelegten Nodes nicht mehr außer Kraft setzen. Siehe Bit.ly/nr-override-msg-props"
|
"nooverride": "Warnung: Nachrichten-Eigenschaften können die Eigenschaften des festgelegten Nodes nicht mehr außer Kraft setzen. Siehe Bit.ly/nr-override-msg-props"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"trigger" : {
|
||||||
|
"send" : "Senden",
|
||||||
|
"then" : "dann",
|
||||||
|
"then-send" : "dann senden",
|
||||||
|
"output" : {
|
||||||
|
"string" : "die Zeichenfolge",
|
||||||
|
"number" : "die Zahl",
|
||||||
|
"existing" : "das vorhandene Nachrichtenobjekt",
|
||||||
|
"original" : "das ursprüngliche Nachrichtenobjekt",
|
||||||
|
"latest" : "das neueste Nachrichtenobjekt",
|
||||||
|
"nothing" : "nichts"
|
||||||
|
},
|
||||||
|
"wait-reset" : "warten auf Zurücksetzen",
|
||||||
|
"wait-for" : "warten auf",
|
||||||
|
"wait-loop" : "erneut senden aller",
|
||||||
|
"for" : "Handhabung",
|
||||||
|
"bytopics" : "für jeden <code>msg.topic</code> Wert unabhängig",
|
||||||
|
"alltopics" : "alle Nachrichten",
|
||||||
|
"duration" : {
|
||||||
|
"ms" : "Millisek.",
|
||||||
|
"s" : "Sekunden",
|
||||||
|
"m" : "Minuten",
|
||||||
|
"h" : "Stunden"
|
||||||
|
},
|
||||||
|
"extend" : " Verlängerung der Verzögerung bei Eingang neuer Nachricht",
|
||||||
|
"label" : {
|
||||||
|
"trigger" : "Auslöser",
|
||||||
|
"trigger-block" : "Auslöser & Block",
|
||||||
|
"trigger-loop" : "alle erneut senden",
|
||||||
|
"reset" : "Setzen Sie den Auslöser zurück, wenn:",
|
||||||
|
"resetMessage" : "msg.reset gesetzt ist oder ",
|
||||||
|
"resetPayload" : "msg.payload ist gleich" ,
|
||||||
|
"resetprompt" : "optional"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"comment" : {
|
||||||
|
"comment" : "Kommentar"
|
||||||
|
},
|
||||||
|
"unknown" : {
|
||||||
|
"label" : {
|
||||||
|
"unknown" : "unbekannt"
|
||||||
|
},
|
||||||
|
"tip" : "<p> Dieser Node ist ein Typ, der Ihrer Installation von Node-RED unbekannt ist. </p> <p> <i> Wenn Sie mit dem Node in diesem Status deployen, wird die Konfiguration beibehalten, aber der Fluss wird erst gestartet, wenn der fehlende Typ installiert ist. </i> </p> <p> Weitere Informationen finden Sie in der Info-Seitenleiste für. Weitere Hilfe </p>"
|
||||||
|
},
|
||||||
|
"mqtt" : {
|
||||||
|
"label" : {
|
||||||
|
"broker" : "Server",
|
||||||
|
"example" : "z. B. lokaler_Host",
|
||||||
|
"qos" : "QoS",
|
||||||
|
"retain" : "Retain",
|
||||||
|
"clientid" : "Client-ID",
|
||||||
|
"port" : "Port",
|
||||||
|
"keepalive" : "Keepalive-Zeit (en)",
|
||||||
|
"cleansession" : "Bereinigte Sitzung verwenden",
|
||||||
|
"use-tls" : "Sichere Verbindung (SSL/TLS) aktivieren",
|
||||||
|
"tls-config" : "TLS-Konfiguration",
|
||||||
|
"verify-server-cert" : "Serverzertifikat überprüfen",
|
||||||
|
"compatmode" : "Traditionelle MQTT 3.1-Unterstützung verwenden"
|
||||||
|
},
|
||||||
|
"sections-label" : {
|
||||||
|
"birth-message" : "Nachricht über Verbindungsaufbau ",
|
||||||
|
"will-message" : "Nachricht über unerwarteten Abschaltung",
|
||||||
|
"close-message" : "Nachricht bevor die Verbindung beendet wird"
|
||||||
|
},
|
||||||
|
"tabs-label" : {
|
||||||
|
"connection" : "Verbindung",
|
||||||
|
"security" : "Sicherheit",
|
||||||
|
"messages" : "Nachrichten"
|
||||||
|
},
|
||||||
|
"placeholder" : {
|
||||||
|
"clientid" : "Leerer Wert für automatische Generierung",
|
||||||
|
"clientid-nonclean" : "Muss für nicht bereinigte Sitzungen festgelegt werden.",
|
||||||
|
"will-topic" : "inaktivieren wenn leer",
|
||||||
|
"birth-topic" : "inaktivieren wenn leer",
|
||||||
|
"close-topic" : "inaktivieren wenn leer"
|
||||||
|
},
|
||||||
|
"state" : {
|
||||||
|
"connected" : "Verbindung zum Broker __broker__ hergestellt.",
|
||||||
|
"disconnected" : "Verbindung zum Broker __broker__ wurde beendet.",
|
||||||
|
"connect-failed" : "Verbindung zum Broker __broker__ konnte nicht hergestellt werden."
|
||||||
|
},
|
||||||
|
"retain" : "Retain",
|
||||||
|
"true" : "Wahr",
|
||||||
|
"false" : "Falsch",
|
||||||
|
"tip" : "Tipp: Behalten Sie das Topic \"Artikel\", \"qos\" oder \"retain\" bei, wenn Sie diese über die Eigenschaft \"msg\" festlegen",
|
||||||
|
"errors" : {
|
||||||
|
"not-defined" : "Topic nicht definiert",
|
||||||
|
"missing-config" : "Fehlende Brokerkonfiguration",
|
||||||
|
"invalid-topic" : "Ungültiges Topic angegeben",
|
||||||
|
"nonclean-missingclientid" : "Keine Client-ID-Gruppe unter Verwendung einer bereinigten Sitzung"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"httpin" : {
|
||||||
|
"label" : {
|
||||||
|
"method" : "Methode",
|
||||||
|
"url" : "URL",
|
||||||
|
"doc" : "Docs",
|
||||||
|
"return" : "Rückgabe",
|
||||||
|
"upload" : "Dateiuploads akzeptieren?",
|
||||||
|
"status" : "Statuscode",
|
||||||
|
"headers" : "Kopfzeilen",
|
||||||
|
"other" : "andere"
|
||||||
|
},
|
||||||
|
"setby" : "-durch msg.method festgelegt-",
|
||||||
|
"basicauth" : "Basisauthentifizierung verwenden",
|
||||||
|
"use-tls" : "Sichere Verbindung (SSL/TLS) aktivieren",
|
||||||
|
"tls-config" : "TLS-Konfiguration",
|
||||||
|
"utf8" : "eine UTF-8-Zeichenfolge",
|
||||||
|
"binary" : "einen binären Buffer",
|
||||||
|
"json" : "ein analysiertes JSON-Objekt",
|
||||||
|
"tip" : {
|
||||||
|
"in" : "Die URL ist relativ zu ",
|
||||||
|
"res" : "Die an diesen Node gesendeten Nachrichten <b> müssen </b> von einem <i> http-Input </i> -Node stammen",
|
||||||
|
"req" : "Tipp: Wenn die JSON-Syntaxanalyse fehlschlägt, wird die abgerufene Zeichenfolge als-ist zurückgegeben."
|
||||||
|
},
|
||||||
|
"httpreq" : "HTTP-Anforderung",
|
||||||
|
"errors" : {
|
||||||
|
"not-created" : "http-in-Node kann nicht erstellt werden, wenn httpNodeRoot auf 'false' gesetzt ist.",
|
||||||
|
"missing-path" : "Fehlendes Pfad",
|
||||||
|
"no-response" : "Kein Antwortobjekt",
|
||||||
|
"json-error" : "JSON-Parsing-Fehler",
|
||||||
|
"no-url" : "Keine URL angegeben",
|
||||||
|
"deprecated-call" : "Nicht weiter unterstützter Aufruf von __method__",
|
||||||
|
"invalid-transport" : "Nicht-http-Transport angefordert"
|
||||||
|
},
|
||||||
|
"status" : {
|
||||||
|
"requesting" : "anfordern"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"websocket" : {
|
||||||
|
"label" : {
|
||||||
|
"type" : "Typ",
|
||||||
|
"path" : "Pfad",
|
||||||
|
"url" : "URL"
|
||||||
|
},
|
||||||
|
"listenon" : "Empfangsbereit",
|
||||||
|
"connectto" : "Verbinden mit",
|
||||||
|
"sendrec" : "Senden/Empfangen",
|
||||||
|
"payload" : "Nutzdaten",
|
||||||
|
"message" : "gesamte Nachricht",
|
||||||
|
"tip" : {
|
||||||
|
"path1" : "Standardmäßig enthält <code> Nutzdaten </code> die Daten, die über einen Websocket gesendet oder von einem Websocket empfangen werden. Der Listener kann so konfiguriert werden, dass er das gesamte Nachrichtenobjekt als eine JSON-formatierte Zeichenfolge sendet oder empfängt.",
|
||||||
|
"path2" : "Dieser Pfad ist relativ zu <code>__path__</code>.",
|
||||||
|
"url1" : "URL sollte ws: / & #47; oder wss: / & #47; Schema verwenden und auf einen vorhandenen Websocket-Listener verweisen.",
|
||||||
|
"url2" : "Standardmäßig enthält <code> Nutzdaten </code> die Daten, die über einen Websocket gesendet oder von einem Websocket empfangen werden. Der Client kann so konfiguriert werden, dass er das gesamte Nachrichtenobjekt als eine JSON-formatierte Zeichenfolge sendet oder empfängt."
|
||||||
|
},
|
||||||
|
"status" : {
|
||||||
|
"connected" : "verbunden __count__",
|
||||||
|
"connected_plural" : "verbunden __count__"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"connect-error" : "Bei der WS-Verbindung ist ein Fehler aufgetreten: ",
|
||||||
|
"send-error" : "Beim Senden ist ein Fehler aufgetreten: ",
|
||||||
|
"missing-conf" : "Fehlende Serverkonfiguration"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"watch" : {
|
||||||
|
"watch" : "Überwachung",
|
||||||
|
"label" : {
|
||||||
|
"files" : "Datei (en)",
|
||||||
|
"recursive" : "Unterverzeichnisse rekursiv überwachen"
|
||||||
|
},
|
||||||
|
"placeholder" : {
|
||||||
|
"files" : "Durch Komma getrennte Liste von Dateien und/oder Verzeichnissen"
|
||||||
|
},
|
||||||
|
"tip" : "Unter Windows müssen Sie doppelte Backslashes \\\\ in beliebigen Verzeichnisnamen verwenden."
|
||||||
|
},
|
||||||
|
"tcpin" : {
|
||||||
|
"label" : {
|
||||||
|
"type" : "Typ",
|
||||||
|
"output" : "Ausgabe",
|
||||||
|
"port" : "Port",
|
||||||
|
"host" : "auf Host",
|
||||||
|
"payload" : "Payload (en)",
|
||||||
|
"delimited" : "begrenzt durch",
|
||||||
|
"close-connection" : "Schließen Sie die Verbindung, nachdem jede Nachricht gesendet wurde?",
|
||||||
|
"decode-base64" : "Nachricht aus Base64 dekodierien?",
|
||||||
|
"server" : "Server",
|
||||||
|
"return" : "Rückgabe",
|
||||||
|
"ms" : "ms",
|
||||||
|
"chars" : "Chars"
|
||||||
|
},
|
||||||
|
"type" : {
|
||||||
|
"listen" : "Empfangsbereit",
|
||||||
|
"connect" : "Verbinden mit",
|
||||||
|
"reply" : "Auf TCP antworten"
|
||||||
|
},
|
||||||
|
"output" : {
|
||||||
|
"stream" : "Datenstrom von",
|
||||||
|
"single" : "Single",
|
||||||
|
"buffer" : "Buffer",
|
||||||
|
"string" : "Zeichenfolge",
|
||||||
|
"base64" : "Base64-Zeichenfolge"
|
||||||
|
},
|
||||||
|
"return" : {
|
||||||
|
"timeout" : "nach einem festen Zeitlimit von",
|
||||||
|
"character" : "wenn folgendes Zeichen empfangen wird",
|
||||||
|
"number" : "eine festgelegte Anzahl von Zeichen",
|
||||||
|
"never" : "keine Rückgabe - Verbindung wird offen gehalten",
|
||||||
|
"immed" : "sofort - Wartet nicht auf Antwort."
|
||||||
|
},
|
||||||
|
"status" : {
|
||||||
|
"connecting" : "Verbindung zu __host__: __port__",
|
||||||
|
"connected" : "Verbindung zu __host__: __port__",
|
||||||
|
"listening-port" : "empfangsbereit an Port __port__",
|
||||||
|
"stopped-listening" : "Empfangsbereitschaft an Port gestoppt",
|
||||||
|
"connection-from" : "Verbindung von __host__: __port__",
|
||||||
|
"connection-closed" : "Verbindung geschlossen von __host__: __port__",
|
||||||
|
"connections" : "__count__connection",
|
||||||
|
"connections_plural" : "__count__connections"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"connection-lost" : "Verbindung verloren zu __host__: __port__",
|
||||||
|
"timeout" : "Zeitlimit für geschlossenen Socket-Port __port__",
|
||||||
|
"cannot-listen" : "Port __port__ kann nicht empfangsbereit sein. Fehler: __error__",
|
||||||
|
"error" : "Fehler: __error__",
|
||||||
|
"socket-error" : "Socketfehler von __host__: __port__",
|
||||||
|
"no-host" : "Host und/oder Port nicht festgelegt",
|
||||||
|
"connect-timeout" : "Verbindungszeitlimit",
|
||||||
|
"connect-fail" : "Verbindung fehlgeschlagen"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"udp" : {
|
||||||
|
"label" : {
|
||||||
|
"listen" : "Empfangsbereit",
|
||||||
|
"onport" : "an Port",
|
||||||
|
"using" : "verwenden",
|
||||||
|
"output" : "Ausgabe",
|
||||||
|
"group" : "Gruppe",
|
||||||
|
"interface" : "Lokal IF",
|
||||||
|
"send" : "Schicken Sie eine",
|
||||||
|
"toport" : "an Port",
|
||||||
|
"address" : "Adresse",
|
||||||
|
"decode-base64" : "Dekodiere Base64-kodierte Nutzdaten?"
|
||||||
|
},
|
||||||
|
"placeholder" : {
|
||||||
|
"interface" : "(optional) lokale Schnittstelle oder Adresse, an die gebunden werden soll",
|
||||||
|
"interfaceprompt" : "(optional) lokale Schnittstelle oder Adresse, an die gebunden werden soll",
|
||||||
|
"address" : "Ziel-IP"
|
||||||
|
},
|
||||||
|
"udpmsgs" : "udp-Nachrichten",
|
||||||
|
"mcmsgs" : "Multicastnachrichten",
|
||||||
|
"udpmsg" : "udp-Nachricht",
|
||||||
|
"bcmsg" : "Broadcastnachricht",
|
||||||
|
"mcmsg" : "Multicastnachricht",
|
||||||
|
"output" : {
|
||||||
|
"buffer" : "ein Buffer",
|
||||||
|
"string" : "eine Zeichenfolge",
|
||||||
|
"base64" : "Eine Base64-codierte Zeichenfolge"
|
||||||
|
},
|
||||||
|
"bind" : {
|
||||||
|
"random" : "an zufälliger lokaler Port binden",
|
||||||
|
"local" : "Bindung an lokalen Port",
|
||||||
|
"target" : "Bindung an Zielport"
|
||||||
|
},
|
||||||
|
"tip" : {
|
||||||
|
"in" : "Tipp: Stellen Sie sicher, dass Ihre Firewall die Daten in zulässt.",
|
||||||
|
"out" : "Tipp: Lassen Sie die Adresse und den Port leer, wenn Sie mit <code> msg.ip </code> und <code> msg.port </code> festlegen möchten.",
|
||||||
|
"port" : "Ports, die bereits verwendet werden: "
|
||||||
|
},
|
||||||
|
"status" : {
|
||||||
|
"listener-at" : "udp listener at __host__: __port__",
|
||||||
|
"mc-group" : "udp Multicastgruppe __Gruppe__",
|
||||||
|
"listener-stopped" : "udp-Listener gestoppt",
|
||||||
|
"output-stopped" : "udp-Ausgabe gestoppt",
|
||||||
|
"mc-ready" : "udp multicast ready: __iface__: __outport__-> __host__: __port__",
|
||||||
|
"bc-ready" : "udp broadcast ready: __outport__-> __host__: __port__",
|
||||||
|
"ready" : "udp ready: __outport__-> __host__: __port__",
|
||||||
|
"ready-nolocal" : "udp bereit: __host__: __port__",
|
||||||
|
"re-use" : "udp re-use socket: __outport__-> __host__: __port__"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"access-error" : "UDP-Zugriffsfehler, Sie benötigen möglicherweise Rootzugriff für Ports unter 1024",
|
||||||
|
"error" : "Fehler: __error__",
|
||||||
|
"bad-mcaddress" : "Ungültige Multicastadresse",
|
||||||
|
"interface" : "Sie müssen die IP-Adresse der erforderlichen Schnittstelle sein.",
|
||||||
|
"ip-notset" : "udp: ip-Adresse nicht festgelegt",
|
||||||
|
"port-notset" : "udp: Port nicht festgelegt",
|
||||||
|
"port-invalid" : "udp: Portnummer nicht gültig",
|
||||||
|
"alreadyused" : "udp: Port __port__ wird bereits verwendet",
|
||||||
|
"ifnotfound" : "udp: interface __iface__ nicht gefunden"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"switch" : {
|
||||||
|
"switch" : "Switch",
|
||||||
|
"label" : {
|
||||||
|
"property" : "Eigenschaft",
|
||||||
|
"rule" : "Regel",
|
||||||
|
"repair" : "Nachrichtenfolgen erneut erstellen"
|
||||||
|
},
|
||||||
|
"and" : "und",
|
||||||
|
"checkall" : "Alle Regeln überprüfen",
|
||||||
|
"stopfirst" : "Nach erster Übereinstimmung stoppen",
|
||||||
|
"ignorecase" : "Groß-/Kleinschreibung ignorieren",
|
||||||
|
"rules" : {
|
||||||
|
"btwn" : "liegt zwischen",
|
||||||
|
"cont" : "enthält",
|
||||||
|
"regex" : "Übereinstimmungen mit regex",
|
||||||
|
"true" : "ist wahr",
|
||||||
|
"false" : "ist falsch",
|
||||||
|
"null" : "ist null",
|
||||||
|
"nnull" : "ist nicht null",
|
||||||
|
"istype" : "ist vom Typ",
|
||||||
|
"empty" : "ist leer",
|
||||||
|
"nempty" : "ist nicht leer",
|
||||||
|
"head" : "Header",
|
||||||
|
"tail" : "Trailer",
|
||||||
|
"index" : "Index zwischen",
|
||||||
|
"exp" : "JSONata Ausdruck",
|
||||||
|
"else" : "Andernfalls"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"invalid-expr" : "Ungültiger JSONata Ausdruck: __error__",
|
||||||
|
"too-many" : "Zu viele anstehende Nachrichten im Switch-Node"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"change" : {
|
||||||
|
"label" : {
|
||||||
|
"rules" : "Regeln",
|
||||||
|
"rule" : "Regel",
|
||||||
|
"set" : "setze __property__",
|
||||||
|
"change" : "__property__ ändern",
|
||||||
|
"delete" : "__property__ löschen",
|
||||||
|
"move" : "bewege __property__",
|
||||||
|
"changeCount" : "Ändern: __count__rules",
|
||||||
|
"regex" : "Reguläre Ausdrücke verwenden"
|
||||||
|
},
|
||||||
|
"action" : {
|
||||||
|
"set" : "Setze",
|
||||||
|
"change" : "Ändern",
|
||||||
|
"delete" : "Löschen",
|
||||||
|
"move" : "Bewegen",
|
||||||
|
"to" : "auf",
|
||||||
|
"search" : "Suchen nach",
|
||||||
|
"replace" : "Ersetzen durch"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"invalid-from" : "Ungültiges 'from' Merkmal: __error__",
|
||||||
|
"invalid-json" : "Ungültiges 'to' JSON Merkmal",
|
||||||
|
"invalid-expr" : "Ungültiger JSONata Ausdruck: __error__"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"range" : {
|
||||||
|
"range" : "Bereich",
|
||||||
|
"label" : {
|
||||||
|
"action" : "Aktion",
|
||||||
|
"inputrange" : "von einem Eingabebereich",
|
||||||
|
"resultrange" : "in einen Zielbereich",
|
||||||
|
"from" : "von",
|
||||||
|
"to" : "auf",
|
||||||
|
"roundresult" : "Runde das Ergebnis auf die nächste ganze Zahl?"
|
||||||
|
},
|
||||||
|
"placeholder" : {
|
||||||
|
"min" : "z. B. 0",
|
||||||
|
"maxin" : "z. B. 99",
|
||||||
|
"maxout" : "z. B. 255"
|
||||||
|
},
|
||||||
|
"scale" : {
|
||||||
|
"payload" : "Skaliere die Nachrichteneigenschaft",
|
||||||
|
"limit" : "Skalieren und Begrenzen auf den Zielbereich",
|
||||||
|
"wrap" : "Skaliere und Einhüllen innerhalb des Zielbereichs"
|
||||||
|
},
|
||||||
|
"tip" : "Tipp: Dieser Node funktioniert NUR mit Zahlen.",
|
||||||
|
"errors" : {
|
||||||
|
"notnumber" : "Keine Zahl"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"csv" : {
|
||||||
|
"label" : {
|
||||||
|
"columns" : "Spalten",
|
||||||
|
"separator" : "Trennzeichen",
|
||||||
|
"c2o" : "Optionen für CSV-zu-Objekt",
|
||||||
|
"o2c" : "Objekt-zu-CSV-Optionen",
|
||||||
|
"input" : "Eingabe",
|
||||||
|
"skip-s" : "Zuerst überspringen",
|
||||||
|
"skip-e" : "Zeilen",
|
||||||
|
"firstrow" : "erste Zeile enthält Spaltennamen",
|
||||||
|
"output" : "Ausgabe",
|
||||||
|
"includerow" : "Spaltennamenszeile einschließen",
|
||||||
|
"newline" : "Zeilenneuerzeile"
|
||||||
|
},
|
||||||
|
"placeholder" : {
|
||||||
|
"columns" : "durch Kommas getrennte Spaltennamen"
|
||||||
|
},
|
||||||
|
"separator" : {
|
||||||
|
"comma" : "Komma",
|
||||||
|
"tab" : "Tabulatorzunge",
|
||||||
|
"space" : "Leerzeichen",
|
||||||
|
"semicolon" : "Semikolon",
|
||||||
|
"colon" : "Doppelpunkt",
|
||||||
|
"hashtag" : "hashtag",
|
||||||
|
"other" : "andere ..."
|
||||||
|
},
|
||||||
|
"output" : {
|
||||||
|
"row" : "eine Nachricht pro Zeile",
|
||||||
|
"array" : "eine einzelne Nachricht [ Array]"
|
||||||
|
},
|
||||||
|
"newline" : {
|
||||||
|
"linux" : "Linux (\\n)",
|
||||||
|
"mac" : "Mac (\\r)",
|
||||||
|
"windows" : "Windows (\\r \\n)"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"csv_js" : "Dieser Node verarbeitet nur CSV-Zeichenfolgen oder JS-Objekte.",
|
||||||
|
"obj_csv" : "Es wurde keine Spaltenschablone für Objekt-> CSV angegeben."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"html" : {
|
||||||
|
"label" : {
|
||||||
|
"select" : "Selektor",
|
||||||
|
"output" : "Ausgabe",
|
||||||
|
"in" : "in"
|
||||||
|
},
|
||||||
|
"output" : {
|
||||||
|
"html" : "den HTML-Inhalt der Elemente",
|
||||||
|
"text" : "nur der Textinhalt der Elemente",
|
||||||
|
"attr" : "ein Objekt mit allen Attributen der Elemente"
|
||||||
|
},
|
||||||
|
"format" : {
|
||||||
|
"single" : "als einzelne Nachricht mit einem Array",
|
||||||
|
"multi" : "als mehrere Nachrichten, eine für jedes Element"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"json" : {
|
||||||
|
"errors" : {
|
||||||
|
"dropped-object" : "Ignorierte Nicht-Objekt-Nutzdaten",
|
||||||
|
"dropped" : "Ignorierter nicht unterstützter Nutzdatentyp",
|
||||||
|
"dropped-error" : "Fehler beim Konvertieren der Nutzdaten",
|
||||||
|
"schema-error" : "JSON-Schema-Fehler",
|
||||||
|
"schema-error-compile" : "JSON-Schema-Fehler: Schema konnte nicht kompiliert werden"
|
||||||
|
},
|
||||||
|
"label" : {
|
||||||
|
"o2j" : "Objekt zu JSON-Optionen",
|
||||||
|
"pretty" : "JSON-Zeichenfolge formatieren",
|
||||||
|
"action" : "Aktion",
|
||||||
|
"property" : "Eigenschaft",
|
||||||
|
"actions" : {
|
||||||
|
"toggle" : "Konvertieren zwischen JSON-Zeichenfolge und Objekt",
|
||||||
|
"str" : "Immer in JSON-Zeichenfolge konvertieren",
|
||||||
|
"obj" : "Immer in JavaScript-Objekt konvertieren"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"yaml" : {
|
||||||
|
"errors" : {
|
||||||
|
"dropped-object" : "Ignorierte Nicht-Objekt-Nutzdaten",
|
||||||
|
"dropped" : "Ignorierter nicht unterstützter Nutzdatentyp",
|
||||||
|
"dropped-error" : "Fehler beim Konvertieren der Nutzdaten"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xml" : {
|
||||||
|
"label" : {
|
||||||
|
"represent" : "Eigenschaftsname für XML-Tagattribute",
|
||||||
|
"prefix" : "Eigenschaftsname für Tagtextinhalt",
|
||||||
|
"advanced" : "Erweiterte Optionen",
|
||||||
|
"x2o" : "Optionen für XML zu Objekt"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"xml_js" : "Dieser Node verarbeitet nur XML-Zeichenfolgen oder JS-Objekte."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"file" : {
|
||||||
|
"label" : {
|
||||||
|
"filename" : "Name der Datei",
|
||||||
|
"action" : "Aktion",
|
||||||
|
"addnewline" : "Neue Zeile (\\n) zu den einzelnen Nutzdaten hinzufügen?",
|
||||||
|
"createdir" : "Verzeichnis erstellen, wenn es nicht vorhanden ist?",
|
||||||
|
"outputas" : "Ausgabe",
|
||||||
|
"breakchunks" : "In Chunks aufbrechen",
|
||||||
|
"breaklines" : "In Linien aufbrechen",
|
||||||
|
"filelabel" : "Datei",
|
||||||
|
"sendError" : "Nachricht bei Fehler senden (traditioneller Modus)",
|
||||||
|
"deletelabel" : "__file__ löschen"
|
||||||
|
},
|
||||||
|
"action" : {
|
||||||
|
"append" : "an Datei anhängen",
|
||||||
|
"overwrite" : "Datei überschreiben",
|
||||||
|
"delete" : "Datei löschen"
|
||||||
|
},
|
||||||
|
"output" : {
|
||||||
|
"utf8" : "eine einzelne utf8-Zeichenfolge",
|
||||||
|
"buffer" : "ein einzelnes Bufferobjekt",
|
||||||
|
"lines" : "ein Nachricht pro Zeile",
|
||||||
|
"stream" : "ein Datenstrom von Buffers"
|
||||||
|
},
|
||||||
|
"status" : {
|
||||||
|
"wrotefile" : "in Datei geschrieben: __file__",
|
||||||
|
"deletedfile" : "gelöschte Datei: __file__",
|
||||||
|
"appendedfile" : "an Datei angefügt: __file__"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"nofilename" : "Kein Dateiname angegeben",
|
||||||
|
"invaliddelete" : "Warnung: Ungültiges Löschen. Bitte verwenden Sie im Konfigurationsdialog eine bestimmte Löschoption.",
|
||||||
|
"deletefail" : "Fehler beim Löschen der Datei: __error__",
|
||||||
|
"writefail" : "Schreiben in Datei fehlgeschlagen: __error__",
|
||||||
|
"appendfail" : "Anhängen an Datei fehlgeschlagen: __error__",
|
||||||
|
"createfail" : "Fehler beim Erstellen der Datei: __error__"
|
||||||
|
},
|
||||||
|
"tip" : "Tipp: Der Dateiname muss ein absoluter Pfad sein. Andernfalls wird er relativ zum Arbeitsverzeichnis des Node-RED-Prozesses verwendet."
|
||||||
|
},
|
||||||
|
"split" : {
|
||||||
|
"split" : "aufteilen",
|
||||||
|
"intro" : "Trennen Sie <code> msg.payload </code> basierend auf dem Typ:",
|
||||||
|
"object" : "<b> Objekt </b>",
|
||||||
|
"objectSend" : "Eine Nachricht für jedes Schlüssel/Wert-Paar senden",
|
||||||
|
"strBuff" : "<b> Zeichenfolge </b> / <b> Buffer </b>",
|
||||||
|
"array" : "<b> Array </b>",
|
||||||
|
"splitUsing" : "Trennen mit",
|
||||||
|
"splitLength" : "Feste Länge von",
|
||||||
|
"stream" : "Behandeln als Strom von Nachrichten",
|
||||||
|
"addname" : "Schlüssel kopieren nach "
|
||||||
|
},
|
||||||
|
"join" : {
|
||||||
|
"join" : "Join",
|
||||||
|
"mode" : {
|
||||||
|
"mode" : "Modus",
|
||||||
|
"auto" : "Automatisch",
|
||||||
|
"merge" : "Sequenzen zusammenführen",
|
||||||
|
"reduce" : "Reihenfolge bestimmen",
|
||||||
|
"custom" : "Manuell"
|
||||||
|
},
|
||||||
|
"combine" : "Kombiniere alle",
|
||||||
|
"create" : "und erstelle",
|
||||||
|
"type" : {
|
||||||
|
"string" : "eine Zeichenfolge",
|
||||||
|
"array" : "ein Array",
|
||||||
|
"buffer" : "ein Buffer",
|
||||||
|
"object" : "ein Schlüssel/Wert-Objekt",
|
||||||
|
"merged" : "ein zusammengefasstes Objekt"
|
||||||
|
},
|
||||||
|
"using" : "mit dem Wert von",
|
||||||
|
"key" : "als Schlüssel",
|
||||||
|
"joinedUsing" : "verbunden mit",
|
||||||
|
"send" : "Senden Sie die Nachricht:",
|
||||||
|
"afterCount" : "nach einer Reihe von Nachrichtenteilen",
|
||||||
|
"count" : "Zähler",
|
||||||
|
"subsequent" : "und jede nachfolgende Nachricht.",
|
||||||
|
"afterTimeout" : "nach Zeitlimitüberschreitung von",
|
||||||
|
"seconds" : "Sekunden",
|
||||||
|
"complete" : "Nach einer Nachricht mit der gesetzten Eigenschaft <code>msg.complete</code>",
|
||||||
|
"tip" : "Dieser Modus setzt voraus, dass dieser Node entweder mit einem <i> split </i> Node verbunden ist oder dass die empfangenen Nachrichten über eine ordnungsgemäß konfigurierte Eigenschaft <code> msg.parts </code> verfügen.",
|
||||||
|
"too-many" : "Zu viele anstehende Nachrichten im Verknüpfungs-Node",
|
||||||
|
"merge" : {
|
||||||
|
"topics-label" : "Zusammengemiedene Themen",
|
||||||
|
"topics" : "Themen",
|
||||||
|
"topic" : "Topic",
|
||||||
|
"on-change" : "Zusammengefügte Nachricht bei Ankunft eines neuen Topics senden"
|
||||||
|
},
|
||||||
|
"reduce" : {
|
||||||
|
"exp" : "Zusammenfassen durch",
|
||||||
|
"exp-value" : "Ausdruck",
|
||||||
|
"init" : "Anfangswert",
|
||||||
|
"right" : "In umgekehrter Reihenfolge auswerten (letzter auf den ersten)",
|
||||||
|
"fixup" : "Fix-up"
|
||||||
|
},
|
||||||
|
"errors" : {
|
||||||
|
"invalid-expr" : "Ungültiger JSONata-Ausdruck: __error__"
|
||||||
|
=======
|
||||||
},
|
},
|
||||||
"inject": {
|
"inject": {
|
||||||
"inject": "inject",
|
"inject": "inject",
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
<dd>Sets the delay, in milliseconds, to be applied to the message. This
|
<dd>Sets the delay, in milliseconds, to be applied to the message. This
|
||||||
option only applies if the node is configured to allow the message to
|
option only applies if the node is configured to allow the message to
|
||||||
override the configured default delay interval.</dd>
|
override the configured default delay interval.</dd>
|
||||||
|
<dt class="optional">rate <span class="property-type">number</span></dt>
|
||||||
|
<dd>Sets the rate value in milliseconds between messages.
|
||||||
|
This node overwrites the existing rate value defined in the node configuration
|
||||||
|
when it receives the message which contains <code>msg.rate</code> value.</dd>
|
||||||
<dt class="optional">reset</dt>
|
<dt class="optional">reset</dt>
|
||||||
<dd>If the received message has this property set to any value, all
|
<dd>If the received message has this property set to any value, all
|
||||||
outstanding messages held by the node are cleared without being sent.</dd>
|
outstanding messages held by the node are cleared without being sent.</dd>
|
||||||
|
@ -301,9 +301,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"errors": {
|
||||||
"buffer": "buffer exceeded 1000 messages",
|
"too-many" : "too many pending messages in delay node"
|
||||||
"buffer1": "buffer exceeded 10000 messages"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"trigger": {
|
"trigger": {
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
<dl class="message-properties">
|
<dl class="message-properties">
|
||||||
<dt class="optional">delay <span class="property-type">数値</span></dt>
|
<dt class="optional">delay <span class="property-type">数値</span></dt>
|
||||||
<dd>メッセージの遅延時間をミリ秒単位で設定します。これはノードの設定でデフォルトの遅延時間を上書きできるようノードを設定した場合にのみ適用します。</dd>
|
<dd>メッセージの遅延時間をミリ秒単位で設定します。これはノードの設定でデフォルトの遅延時間を上書きできるようノードを設定した場合にのみ適用します。</dd>
|
||||||
|
<dt class="optional">rate <span class="property-type">数値</span></dt>
|
||||||
|
<dd>メッセージ間のレート値をミリ秒単位で設定します。本ノードは、<code>msg.rate</code>値を含むメッセージを受け取ると、ノード設定で定義された既存のレート値を上書きします。</dd>
|
||||||
<dt class="optional">reset</dt>
|
<dt class="optional">reset</dt>
|
||||||
<dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージをクリアします。</dd>
|
<dd>受信メッセージでこのプロパティを任意の値に設定すると、ノードが保持する全ての未送信メッセージをクリアします。</dd>
|
||||||
<dt class="optional">flush</dt>
|
<dt class="optional">flush</dt>
|
||||||
|
@ -301,9 +301,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"errors": {
|
||||||
"buffer": "バッファ上限の1000メッセージを超えました",
|
"too-many": "delayノード内で保持しているメッセージが多すぎます"
|
||||||
"buffer1": "バッファ上限の10000メッセージを超えました"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"trigger": {
|
"trigger": {
|
||||||
|
@ -272,10 +272,6 @@
|
|||||||
"singular": "일"
|
"singular": "일"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
"buffer": "버퍼 상한의 1000메세지를 넘었습니다",
|
|
||||||
"buffer1": "버퍼 상한의 10000메세지를 넘었습니다"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"trigger": {
|
"trigger": {
|
||||||
|
@ -290,10 +290,6 @@
|
|||||||
"singular": "天"
|
"singular": "天"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"error": {
|
|
||||||
"buffer": "缓冲了超过 1000 条信息",
|
|
||||||
"buffer1": "缓冲了超过 10000 条信息"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"trigger": {
|
"trigger": {
|
||||||
|
@ -18,6 +18,7 @@ var should = require("should");
|
|||||||
|
|
||||||
var delayNode = require("nr-test-utils").require("@node-red/nodes/core/function/89-delay.js");
|
var delayNode = require("nr-test-utils").require("@node-red/nodes/core/function/89-delay.js");
|
||||||
var helper = require("node-red-node-test-helper");
|
var helper = require("node-red-node-test-helper");
|
||||||
|
var RED = require("nr-test-utils").require("node-red/lib/red");
|
||||||
|
|
||||||
var GRACE_PERCENTAGE=10;
|
var GRACE_PERCENTAGE=10;
|
||||||
|
|
||||||
@ -35,6 +36,7 @@ describe('delay Node', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function(done) {
|
afterEach(function(done) {
|
||||||
|
RED.settings.nodeMessageBufferMaxLength = 0;
|
||||||
helper.unload();
|
helper.unload();
|
||||||
helper.stopServer(done);
|
helper.stopServer(done);
|
||||||
});
|
});
|
||||||
@ -150,6 +152,7 @@ describe('delay Node', function() {
|
|||||||
* We send a message, take a timestamp then when the message is received by the helper node, we take another timestamp.
|
* We send a message, take a timestamp then when the message is received by the helper node, we take another timestamp.
|
||||||
* Then check if the message has been delayed by the expected amount.
|
* Then check if the message has been delayed by the expected amount.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
it('delays the message in seconds', function(done) {
|
it('delays the message in seconds', function(done) {
|
||||||
genericDelayTest(0.5, "seconds", done);
|
genericDelayTest(0.5, "seconds", done);
|
||||||
});
|
});
|
||||||
@ -176,14 +179,14 @@ describe('delay Node', function() {
|
|||||||
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
||||||
* @param runtimeInMillis - when to terminate run and count messages received
|
* @param runtimeInMillis - when to terminate run and count messages received
|
||||||
*/
|
*/
|
||||||
function genericRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, done) {
|
function genericRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, rateValue, done) {
|
||||||
var flow = [{"id":"delayNode1","type":"delay","nbRateUnits":nbUnit,"name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
var flow = [{"id":"delayNode1","type":"delay","nbRateUnits":nbUnit,"name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
||||||
{id:"helperNode1", type:"helper", wires:[]}];
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
helper.load(delayNode, flow, function() {
|
helper.load(delayNode, flow, function() {
|
||||||
var delayNode1 = helper.getNode("delayNode1");
|
var delayNode1 = helper.getNode("delayNode1");
|
||||||
var helperNode1 = helper.getNode("helperNode1");
|
var helperNode1 = helper.getNode("helperNode1");
|
||||||
var receivedMessagesStack = [];
|
var receivedMessagesStack = [];
|
||||||
var rate = 1000/aLimit;
|
var rate = 1000 / aLimit * nbUnit;
|
||||||
|
|
||||||
var receiveTimestamp;
|
var receiveTimestamp;
|
||||||
|
|
||||||
@ -201,7 +204,7 @@ describe('delay Node', function() {
|
|||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
for (; i < possibleMaxMessageCount + 1; i++) {
|
for (; i < possibleMaxMessageCount + 1; i++) {
|
||||||
delayNode1.receive({payload:i});
|
delayNode1.receive({ payload: i, rate: rateValue });
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
@ -224,17 +227,22 @@ describe('delay Node', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it('limits the message rate to 1 per second', function(done) {
|
it('limits the message rate to 1 per second', function(done) {
|
||||||
genericRateLimitSECONDSTest(1, 1, 1500, done);
|
genericRateLimitSECONDSTest(1, 1, 1500, null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('limits the message rate to 1 per 2 seconds', function(done) {
|
it('limits the message rate to 1 per 2 seconds', function(done) {
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
genericRateLimitSECONDSTest(1, 2, 3000, done);
|
genericRateLimitSECONDSTest(1, 2, 3000, null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('limits the message rate to 2 per seconds, 2 seconds', function(done) {
|
it('limits the message rate to 2 per seconds, 2 seconds', function(done) {
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
genericRateLimitSECONDSTest(2, 1, 2100, done);
|
genericRateLimitSECONDSTest(2, 1, 2100, null, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('limits the message rate using msg.rate', function (done) {
|
||||||
|
RED.settings.nodeMessageBufferMaxLength = 3;
|
||||||
|
genericRateLimitSECONDSTest(1, 1, 1500, 2000, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,7 +251,7 @@ describe('delay Node', function() {
|
|||||||
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
* @param nbUnit - the multiple of the unit, aLimit Message for nbUnit Seconds
|
||||||
* @param runtimeInMillis - when to terminate run and count messages received
|
* @param runtimeInMillis - when to terminate run and count messages received
|
||||||
*/
|
*/
|
||||||
function dropRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, done) {
|
function dropRateLimitSECONDSTest(aLimit, nbUnit, runtimeInMillis, rateValue, done) {
|
||||||
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"nbRateUnits":nbUnit,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"wires":[["helperNode1"]]},
|
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"nbRateUnits":nbUnit,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"wires":[["helperNode1"]]},
|
||||||
{id:"helperNode1", type:"helper", wires:[]}];
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
helper.load(delayNode, flow, function() {
|
helper.load(delayNode, flow, function() {
|
||||||
@ -269,7 +277,7 @@ describe('delay Node', function() {
|
|||||||
var possibleMaxMessageCount = Math.ceil(aLimit * (runtimeInMillis / 1000) + aLimit); // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst
|
var possibleMaxMessageCount = Math.ceil(aLimit * (runtimeInMillis / 1000) + aLimit); // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
delayNode1.receive({payload:i});
|
delayNode1.receive({ payload: i, rate: rateValue });
|
||||||
i++;
|
i++;
|
||||||
for (; i < possibleMaxMessageCount + 1; i++) {
|
for (; i < possibleMaxMessageCount + 1; i++) {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
@ -306,17 +314,23 @@ describe('delay Node', function() {
|
|||||||
|
|
||||||
it('limits the message rate to 1 per second, 4 seconds, with drop', function(done) {
|
it('limits the message rate to 1 per second, 4 seconds, with drop', function(done) {
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
dropRateLimitSECONDSTest(1, 1, 4000, done);
|
dropRateLimitSECONDSTest(1, 1, 4000, null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('limits the message rate to 1 per 2 seconds, 4 seconds, with drop', function(done) {
|
it('limits the message rate to 1 per 2 seconds, 4 seconds, with drop', function(done) {
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
dropRateLimitSECONDSTest(1, 2, 4500, done);
|
dropRateLimitSECONDSTest(1, 2, 4500, null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('limits the message rate to 2 per second, 5 seconds, with drop', function(done) {
|
it('limits the message rate to 2 per second, 5 seconds, with drop', function(done) {
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
dropRateLimitSECONDSTest(2, 1, 5000, done);
|
dropRateLimitSECONDSTest(2, 1, 5000, null, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('limits the message rate with drop using msg.rate', function (done) {
|
||||||
|
this.timeout(6000);
|
||||||
|
RED.settings.nodeMessageBufferMaxLength = 3;
|
||||||
|
dropRateLimitSECONDSTest(2, 1, 5000, 1000, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -719,7 +733,7 @@ describe('delay Node', function() {
|
|||||||
setImmediate( function() { delayNode1.receive({reset:true}); }); // reset the queue
|
setImmediate( function() { delayNode1.receive({reset:true}); }); // reset the queue
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Messaging API support */
|
/* Messaging API support */
|
||||||
function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) {
|
function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) {
|
||||||
const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
|
const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
|
||||||
@ -747,7 +761,7 @@ describe('delay Node', function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
it('calls done when queued message is emitted (type: delay)', function(done) {
|
it('calls done when queued message is emitted (type: delay)', function(done) {
|
||||||
mapiDoneTestHelper(done, "delay", false, [{msg:{payload:1}, avr:1000, var:100}]);
|
mapiDoneTestHelper(done, "delay", false, [{msg:{payload:1}, avr:1000, var:100}]);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user