mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Add buffer joiner mode to Join node
This commit is contained in:
parent
d99432bff1
commit
52c0d360b2
@ -812,10 +812,11 @@
|
||||
"type":{
|
||||
"string":"a String",
|
||||
"array":"an Array",
|
||||
"buffer":"a Buffer",
|
||||
"object":"a key/value Object",
|
||||
"merged":"a merged Object"
|
||||
},
|
||||
"using":"using",
|
||||
"using":"using the value of",
|
||||
"key":"as the key",
|
||||
"joinedUsing":"joined using",
|
||||
"send":"Send the message:",
|
||||
|
@ -181,21 +181,23 @@
|
||||
<div class="form-row">
|
||||
<label data-i18n="join.create"></label>
|
||||
<select id="node-input-build" style="width:70%;">
|
||||
<option id="node-input-build-string" value="string" data-i18n="join.type.string"></option>
|
||||
<option value="string" data-i18n="join.type.string"></option>
|
||||
<option value="buffer" data-i18n="join.type.buffer"></option>
|
||||
<option value="array" data-i18n="join.type.array"></option>
|
||||
<option value="object" data-i18n="join.type.object"></option>
|
||||
<option value="merged" data-i18n="join.type.merged"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-row-key">
|
||||
<label style="vertical-align:top; margin-top:7px;" data-i18n="join.using"></label>
|
||||
<label style="vertical-align:top; margin-top:7px; width:auto; margin-right: 5px;" data-i18n="join.using"></label>
|
||||
<div style="display:inline-block">
|
||||
<input type="text" id="node-input-key" style="width:252px;"> <span data-i18n="join.key"></span>
|
||||
<input type="text" id="node-input-key" style="width:220px;"> <span data-i18n="join.key"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row node-row-joiner">
|
||||
<label for="node-input-joiner" data-i18n="join.joinedUsing"></label>
|
||||
<input type="text" id="node-input-joiner" style="width:40px">
|
||||
<input type="text" id="node-input-joiner" style="width:70%">
|
||||
<input type="hidden" id="node-input-joinerType">
|
||||
</div>
|
||||
<div class="form-row node-row-trigger" id="trigger-row">
|
||||
<label style="width:auto;" data-i18n="join.send"></label>
|
||||
@ -203,8 +205,8 @@
|
||||
<li>
|
||||
<label style="width:280px;" for="node-input-count" data-i18n="join.afterCount"></label> <input id="node-input-count" data-i18n="[placeholder]join.count" type="text" style="width:75px;">
|
||||
</li>
|
||||
<li style="list-style-type:none;">
|
||||
<input type="checkbox" id="node-input-accumulate" style="display:inline-block; width:20px; list-style-type:none; margin-left:20px; vertical-align:top;"> <span data-i18n="join.subsequent"></span>
|
||||
<li class="node-row-accumulate" style="list-style-type:none;">
|
||||
<input type="checkbox" id="node-input-accumulate" style="display:inline-block; width:20px; margin-left:20px; vertical-align:top;"> <label style="width: auto" for="node-input-accumulate" data-i18n="join.subsequent"></label>
|
||||
</li>
|
||||
<li>
|
||||
<label style="width:280px;" for="node-input-timeout" data-i18n="join.afterTimeout"></label> <input id="node-input-timeout" data-i18n="[placeholder]join.seconds" type="text" style="width:75px;">
|
||||
@ -249,14 +251,16 @@
|
||||
<p>When configured to join in manual mode, the node is able to join sequences
|
||||
of messages in a variety of ways.</p>
|
||||
<ul>
|
||||
<li>a <b>string</b> - created by joining the selected property of each message with the specified join character.</li>
|
||||
<li>an <b>array</b>.</li>
|
||||
<li>a <b>string</b> or <b>buffer</b> - created by joining the selected property of each message with the specified join characters or buffer.</li>
|
||||
<li>an <b>array</b> - created by adding each selected property, or entire message, to the output array.</li>
|
||||
<li>a <b>key/value object</b> - created by using a property of each message to determine the key under which
|
||||
the required value is stored.</li>
|
||||
<li>a <b>merged object</b> - created by merging the property of each message under a single object.</li>
|
||||
</ul>
|
||||
<p>The other properties of the output message are taken from the last message received before the result is sent.</p>
|
||||
<p>A <i>count</i> can be set for how many messages should be received before generating the output message.</p>
|
||||
<p>A <i>count</i> can be set for how many messages should be received before generating the output message.
|
||||
For object outputs, once this count has been reached, the node can be configured to send a message for each subsequent message
|
||||
received.</p>
|
||||
<p>A <i>timeout</i> can be set to trigger sending the new message using whatever has been received so far.</p>
|
||||
<p>If a message is received with the <b>msg.complete</b> property set, the output message is sent.</p>
|
||||
</script>
|
||||
@ -273,8 +277,8 @@
|
||||
propertyType: { value:"msg"},
|
||||
key: {value:"topic"},
|
||||
joiner: { value:"\\n"},
|
||||
joinerType: { value:"str"},
|
||||
accumulate: { value:"false" },
|
||||
//topic: { value:""},
|
||||
timeout: {value:""},
|
||||
count: {value:""}
|
||||
},
|
||||
@ -300,15 +304,25 @@
|
||||
$("#node-input-build").change(function(e) {
|
||||
var val = $(this).val();
|
||||
$(".node-row-key").toggle(val==='object');
|
||||
$(".node-row-joiner").toggle(val==='string');
|
||||
$(".node-row-accumulate").toggle(val==='object' || val==='merged');
|
||||
$(".node-row-joiner").toggle(val==='string' || val==='buffer');
|
||||
$(".node-row-trigger").toggle(val!=='auto');
|
||||
if (val === 'string') {
|
||||
if (val === 'string' || val==='buffer') {
|
||||
$("#node-input-property").typedInput('types',['msg']);
|
||||
} else {
|
||||
$("#node-input-property").typedInput('types',['msg', {value:"full",label:"complete message",hasValue:false}]);
|
||||
}
|
||||
});
|
||||
|
||||
$("#node-input-joiner").typedInput({
|
||||
default: 'str',
|
||||
typeField: $("#node-input-joinerType"),
|
||||
types:[
|
||||
'str',
|
||||
'bin'
|
||||
]
|
||||
});
|
||||
|
||||
$("#node-input-property").typedInput({
|
||||
typeField: $("#node-input-propertyType"),
|
||||
types:['msg', {value:"full", label:"complete message", hasValue:false}]
|
||||
@ -320,6 +334,12 @@
|
||||
|
||||
$("#node-input-build").change();
|
||||
$("#node-input-mode").change();
|
||||
},
|
||||
oneditsave: function() {
|
||||
var build = $("#node-input-build").val();
|
||||
if (build !== 'object' && build !== 'merged') {
|
||||
$("#node-input-accumulate").prop("checked",false);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -66,7 +66,7 @@ module.exports = function(RED) {
|
||||
return;
|
||||
}
|
||||
node.c = 0;
|
||||
node.buffer = new Buffer.from([]);
|
||||
node.buffer = Buffer.from([]);
|
||||
this.on("input", function(msg) {
|
||||
if (msg.hasOwnProperty("payload")) {
|
||||
if (msg.hasOwnProperty("parts")) { msg.parts = { parts:msg.parts }; } // push existing parts to a stack
|
||||
@ -182,7 +182,7 @@ module.exports = function(RED) {
|
||||
msg.payload = node.buffer;
|
||||
msg.parts.index = node.c++;
|
||||
node.send(RED.util.cloneMessage(msg));
|
||||
node.buffer = new Buffer.from([]);
|
||||
node.buffer = Buffer.from([]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -243,7 +243,20 @@ module.exports = function(RED) {
|
||||
this.key = n.key||"topic";
|
||||
this.timer = (this.mode === "auto") ? 0 : Number(n.timeout || 0)*1000;
|
||||
this.count = Number(n.count || 0);
|
||||
this.joiner = (n.joiner||"").replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g,"\t").replace(/\\e/g,"\e").replace(/\\f/g,"\f").replace(/\\0/g,"\0");
|
||||
this.joiner = n.joiner||"";
|
||||
this.joinerType = n.joinerType||"str";
|
||||
|
||||
if (this.joinerType === "str") {
|
||||
this.joiner = this.joiner.replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g,"\t").replace(/\\e/g,"\e").replace(/\\f/g,"\f").replace(/\\0/g,"\0");
|
||||
} else if (this.joinerType === "bin") {
|
||||
var joinArray = JSON.parse(n.joiner)
|
||||
if (Array.isArray(joinArray)) {
|
||||
this.joiner = Buffer.from(joinArray);
|
||||
} else {
|
||||
throw new Error("not an array");
|
||||
}
|
||||
}
|
||||
|
||||
this.build = n.build || "array";
|
||||
this.accumulate = n.accumulate || "false";
|
||||
//this.topic = n.topic;
|
||||
@ -281,7 +294,11 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
if (group.type === 'string') {
|
||||
RED.util.setMessageProperty(group.msg,node.property,group.payload.join(group.joinChar));
|
||||
var groupJoinChar = group.joinChar;
|
||||
if (typeof group.joinChar !== 'string') {
|
||||
groupJoinChar = group.joinChar.toString();
|
||||
}
|
||||
RED.util.setMessageProperty(group.msg,node.property,group.payload.join(groupJoinChar));
|
||||
} else {
|
||||
RED.util.setMessageProperty(group.msg,node.property,group.payload);
|
||||
}
|
||||
@ -378,7 +395,7 @@ module.exports = function(RED) {
|
||||
type:payloadType,
|
||||
msg:msg
|
||||
}
|
||||
if (payloadType === 'string') {
|
||||
if (payloadType === 'string' || payloadType === 'array' || payloadType === 'buffer') {
|
||||
inflight[partId].payload = [];
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ describe('SPLIT node', function() {
|
||||
msg.parts.should.have.property("count",2);
|
||||
msg.parts.should.have.property("type","array");
|
||||
msg.parts.should.have.property("index");
|
||||
msg.payload.should.be.an.Array;
|
||||
msg.payload.should.be.an.Array();
|
||||
if (msg.parts.index === 0) { msg.payload.length.should.equal(3); }
|
||||
if (msg.parts.index === 1) { msg.payload.length.should.equal(1); done(); }
|
||||
});
|
||||
@ -213,16 +213,20 @@ describe('SPLIT node', function() {
|
||||
var sn1 = helper.getNode("sn1");
|
||||
var sn2 = helper.getNode("sn2");
|
||||
sn2.on("input", function(msg) {
|
||||
//console.log(msg);
|
||||
msg.should.have.property("parts");
|
||||
msg.payload.should.be.a.Buffer;
|
||||
msg.parts.should.have.property("count",4);
|
||||
msg.parts.should.have.property("index");
|
||||
msg.parts.should.have.property("type","buffer");
|
||||
if (msg.parts.index === 0) { msg.payload.toString().should.equal("12"); }
|
||||
if (msg.parts.index === 1) { msg.payload.toString().should.equal("34"); }
|
||||
if (msg.parts.index === 2) { msg.payload.toString().should.equal("56"); }
|
||||
if (msg.parts.index === 3) { msg.payload.toString().should.equal("78"); done(); }
|
||||
try {
|
||||
//console.log(msg);
|
||||
msg.should.have.property("parts");
|
||||
Buffer.isBuffer(msg.payload).should.be.true();
|
||||
msg.parts.should.have.property("count",4);
|
||||
msg.parts.should.have.property("index");
|
||||
msg.parts.should.have.property("type","buffer");
|
||||
if (msg.parts.index === 0) { msg.payload.toString().should.equal("12"); }
|
||||
if (msg.parts.index === 1) { msg.payload.toString().should.equal("34"); }
|
||||
if (msg.parts.index === 2) { msg.payload.toString().should.equal("56"); }
|
||||
if (msg.parts.index === 3) { msg.payload.toString().should.equal("78"); done(); }
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
var b = new Buffer.from("12345678");
|
||||
sn1.receive({payload:b});
|
||||
@ -236,14 +240,17 @@ describe('SPLIT node', function() {
|
||||
var sn1 = helper.getNode("sn1");
|
||||
var sn2 = helper.getNode("sn2");
|
||||
sn2.on("input", function(msg) {
|
||||
//console.log(msg);
|
||||
msg.should.have.property("parts");
|
||||
msg.payload.should.be.a.Buffer;
|
||||
msg.parts.should.have.property("index");
|
||||
msg.parts.should.have.property("type","buffer");
|
||||
if (msg.parts.index === 0) { msg.payload.toString().should.equal("123"); }
|
||||
if (msg.parts.index === 1) { msg.payload.toString().should.equal("123"); }
|
||||
if (msg.parts.index === 2) { msg.payload.toString().should.equal("123"); done(); }
|
||||
try {
|
||||
msg.should.have.property("parts");
|
||||
Buffer.isBuffer(msg.payload).should.be.true();
|
||||
msg.parts.should.have.property("index");
|
||||
msg.parts.should.have.property("type","buffer");
|
||||
if (msg.parts.index === 0) { msg.payload.toString().should.equal("123"); }
|
||||
if (msg.parts.index === 1) { msg.payload.toString().should.equal("123"); }
|
||||
if (msg.parts.index === 2) { msg.payload.toString().should.equal("123"); done(); }
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
var b1 = new Buffer.from("123412");
|
||||
var b2 = new Buffer.from("341234");
|
||||
@ -296,7 +303,26 @@ describe('JOIN node', function() {
|
||||
n1.receive({payload:"D", parts:{id:1, type:"string", ch:",", index:3, count:4}});
|
||||
});
|
||||
});
|
||||
|
||||
it('should join bits of string back together automatically with a buffer joiner', function(done) {
|
||||
var flow = [{id:"n1", type:"join", wires:[["n2"]], joiner:"[44]", joinerType:"bin", build:"string", mode:"auto"},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(joinNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.payload.should.equal("A,B,C,D");
|
||||
done();
|
||||
}
|
||||
catch(e) {done(e);}
|
||||
});
|
||||
n1.receive({payload:"A", parts:{id:1, type:"string", ch:",", index:0, count:4}});
|
||||
n1.receive({payload:"B", parts:{id:1, type:"string", ch:",", index:1, count:4}});
|
||||
n1.receive({payload:"C", parts:{id:1, type:"string", ch:",", index:2, count:4}});
|
||||
n1.receive({payload:"D", parts:{id:1, type:"string", ch:",", index:3, count:4}});
|
||||
});
|
||||
});
|
||||
it('should join bits of buffer back together automatically', function(done) {
|
||||
var flow = [{id:"n1", type:"join", wires:[["n2"]], joiner:",", build:"buffer", mode:"auto"},
|
||||
{id:"n2", type:"helper"}];
|
||||
@ -306,7 +332,7 @@ describe('JOIN node', function() {
|
||||
n2.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property("payload");
|
||||
msg.should.be.a.Buffer;
|
||||
Buffer.isBuffer(msg.payload).should.be.true();
|
||||
msg.payload.toString().should.equal("A-B-C-D");
|
||||
done();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user