diff --git a/packages/node_modules/@node-red/nodes/core/sequence/17-split.html b/packages/node_modules/@node-red/nodes/core/sequence/17-split.html
index 72ab55335..053c534c4 100644
--- a/packages/node_modules/@node-red/nodes/core/sequence/17-split.html
+++ b/packages/node_modules/@node-red/nodes/core/sequence/17-split.html
@@ -15,7 +15,11 @@
-->
@@ -57,7 +60,8 @@
arraySplt: {value:1},
arraySpltType: {value:"len"},
stream: {value:false},
- addname: {value:""}
+ addname: {value:""},
+ property: {value:"payload",required:true}
},
inputs:1,
outputs:1,
@@ -69,6 +73,10 @@
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
+ if (this.property === undefined) {
+ $("#node-input-property").val("payload");
+ }
+ $("#node-input-property").typedInput({default:'msg',types:['msg']});
$("#node-input-splt").typedInput({
default: 'str',
typeField: $("#node-input-spltType"),
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/17-split.js b/packages/node_modules/@node-red/nodes/core/sequence/17-split.js
index 10c696b76..e9b54dff8 100644
--- a/packages/node_modules/@node-red/nodes/core/sequence/17-split.js
+++ b/packages/node_modules/@node-red/nodes/core/sequence/17-split.js
@@ -19,13 +19,13 @@ module.exports = function(RED) {
function sendArray(node,msg,array,send) {
for (var i = 0; i < array.length-1; i++) {
- msg.payload = array[i];
+ RED.util.setMessageProperty(msg,node.property,array[i]);
msg.parts.index = node.c++;
if (node.stream !== true) { msg.parts.count = array.length; }
send(RED.util.cloneMessage(msg));
}
if (node.stream !== true) {
- msg.payload = array[i];
+ RED.util.setMessageProperty(msg,node.property,array[i]);
msg.parts.index = node.c++;
msg.parts.count = array.length;
send(RED.util.cloneMessage(msg));
@@ -40,10 +40,12 @@ module.exports = function(RED) {
node.stream = n.stream;
node.spltType = n.spltType || "str";
node.addname = n.addname || "";
+ node.property = n.property||"payload";
try {
if (node.spltType === "str") {
this.splt = (n.splt || "\\n").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 (node.spltType === "bin") {
+ }
+ else if (node.spltType === "bin") {
var spltArray = JSON.parse(n.splt);
if (Array.isArray(spltArray)) {
this.splt = Buffer.from(spltArray);
@@ -51,7 +53,8 @@ module.exports = function(RED) {
throw new Error("not an array");
}
this.spltBuffer = spltArray;
- } else if (node.spltType === "len") {
+ }
+ else if (node.spltType === "len") {
this.splt = parseInt(n.splt);
if (isNaN(this.splt) || this.splt < 1) {
throw new Error("invalid split length: "+n.splt);
@@ -69,18 +72,23 @@ module.exports = function(RED) {
node.buffer = Buffer.from([]);
node.pendingDones = [];
this.on("input", function(msg, send, done) {
- if (msg.hasOwnProperty("payload")) {
+ var value = RED.util.getMessageProperty(msg,node.property);
+ if (value !== undefined) {
+ RED.util.setMessageProperty(msg,node.property,undefined);
if (msg.hasOwnProperty("parts")) { msg.parts = { parts:msg.parts }; } // push existing parts to a stack
else { msg.parts = {}; }
msg.parts.id = RED.util.generateId(); // generate a random id
+ if (node.property !== "payload") {
+ msg.parts.property = node.property;
+ }
delete msg._msgid;
- if (typeof msg.payload === "string") { // Split String into array
- msg.payload = (node.remainder || "") + msg.payload;
+ if (typeof value === "string") { // Split String into array
+ value = (node.remainder || "") + value;
msg.parts.type = "string";
if (node.spltType === "len") {
msg.parts.ch = "";
msg.parts.len = node.splt;
- var count = msg.payload.length/node.splt;
+ var count = value.length/node.splt;
if (Math.floor(count) !== count) {
count = Math.ceil(count);
}
@@ -89,9 +97,9 @@ module.exports = function(RED) {
node.c = 0;
}
var pos = 0;
- var data = msg.payload;
+ var data = value;
for (var i=0; i d());
@@ -119,47 +127,48 @@ module.exports = function(RED) {
if (!node.spltBufferString) {
node.spltBufferString = node.splt.toString();
}
- a = msg.payload.split(node.spltBufferString);
+ a = value.split(node.spltBufferString);
msg.parts.ch = node.spltBuffer; // pass the split char to other end for rejoin
} else if (node.spltType === "str") {
- a = msg.payload.split(node.splt);
+ a = value.split(node.splt);
msg.parts.ch = node.splt; // pass the split char to other end for rejoin
}
sendArray(node,msg,a,send);
done();
}
}
- else if (Array.isArray(msg.payload)) { // then split array into messages
+ else if (Array.isArray(value)) { // then split array into messages
msg.parts.type = "array";
- var count = msg.payload.length/node.arraySplt;
+ var count = value.length/node.arraySplt;
if (Math.floor(count) !== count) {
count = Math.ceil(count);
}
msg.parts.count = count;
var pos = 0;
- var data = msg.payload;
+ var data = value;
msg.parts.len = node.arraySplt;
for (var i=0; i d());
@@ -230,7 +239,7 @@ module.exports = function(RED) {
var i = 0, p = 0;
pos = buff.indexOf(node.splt);
while (pos > -1) {
- msg.payload = buff.slice(p,pos);
+ RED.util.setMessageProperty(msg,node.property,buff.slice(p,pos));
msg.parts.index = node.c++;
send(RED.util.cloneMessage(msg));
i++;
@@ -242,7 +251,7 @@ module.exports = function(RED) {
node.pendingDones = [];
}
if ((node.stream !== true) && (p < buff.length)) {
- msg.payload = buff.slice(p,buff.length);
+ RED.util.setMessageProperty(msg,node.property,buff.slice(p,buff.length));
msg.parts.index = node.c++;
msg.parts.count = node.c++;
send(RED.util.cloneMessage(msg));
@@ -298,7 +307,6 @@ module.exports = function(RED) {
return exp
}
-
function reduceMessageGroup(node,msgInfos,exp,fixup,count,accumulator,done) {
var msgInfo = msgInfos.shift();
exp.assign("I", msgInfo.msg.parts.index);
@@ -515,13 +523,13 @@ module.exports = function(RED) {
if (typeof group.joinChar !== 'string') {
groupJoinChar = group.joinChar.toString();
}
- RED.util.setMessageProperty(group.msg,node.property,group.payload.join(groupJoinChar));
+ RED.util.setMessageProperty(group.msg,group?.prop||"payload",group.payload.join(groupJoinChar));
}
else {
if (node.propertyType === 'full') {
group.msg = RED.util.cloneMessage(group.msg);
}
- RED.util.setMessageProperty(group.msg,node.property,group.payload);
+ RED.util.setMessageProperty(group.msg,group?.prop||"payload",group.payload);
}
if (group.msg.hasOwnProperty('parts') && group.msg.parts.hasOwnProperty('parts')) {
group.msg.parts = group.msg.parts.parts;
@@ -589,7 +597,7 @@ module.exports = function(RED) {
}
if (node.mode === 'auto' && (!msg.hasOwnProperty("parts")||!msg.parts.hasOwnProperty("id"))) {
- // if a blank reset messag erest it all.
+ // if a blank reset message reset it all.
if (msg.hasOwnProperty("reset")) {
if (inflight && inflight.hasOwnProperty("partId") && inflight[partId].timeout) {
clearTimeout(inflight[partId].timeout);
@@ -618,6 +626,7 @@ module.exports = function(RED) {
propertyKey = msg.parts.key;
arrayLen = msg.parts.len;
propertyIndex = msg.parts.index;
+ property = RED.util.getMessageProperty(msg,msg.parts.property||"payload");
}
else if (node.mode === 'reduce') {
return processReduceMessageQueue({msg, send, done});
@@ -719,6 +728,8 @@ module.exports = function(RED) {
completeSend(partId)
}, node.timer)
}
+ if (node.mode === "auto") { inflight[partId].prop = msg.parts.property; }
+ else { inflight[partId].prop = node.property; }
}
inflight[partId].dones.push(done);
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
index a7b583878..634432e37 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
@@ -1001,7 +1001,7 @@
"tip": "Tip: The filename should be an absolute path, otherwise it will be relative to the working directory of the Node-RED process."
},
"split": {
- "split": "split",
+ "split": "Split",
"intro": "Split msg.payload
based on type:",
"object": "Object",
"objectSend": "Send a message for each key/value pair",
diff --git a/test/nodes/core/sequence/17-split_spec.js b/test/nodes/core/sequence/17-split_spec.js
index 370e0cda4..a64f6e078 100644
--- a/test/nodes/core/sequence/17-split_spec.js
+++ b/test/nodes/core/sequence/17-split_spec.js
@@ -66,6 +66,27 @@ describe('SPLIT node', function() {
});
});
+ it('should split an array on a sub-property into multiple messages', function(done) {
+ var flow = [{id:"sn1", type:"split", property:"foo", wires:[["sn2"]]},
+ {id:"sn2", type:"helper"}];
+ helper.load(splitNode, flow, function() {
+ var sn1 = helper.getNode("sn1");
+ var sn2 = helper.getNode("sn2");
+ sn2.on("input", function(msg) {
+ msg.should.have.property("parts");
+ msg.parts.should.have.property("count",4);
+ msg.parts.should.have.property("type","array");
+ msg.parts.should.have.property("index");
+ msg.parts.should.have.property("property","foo");
+ if (msg.parts.index === 0) { msg.foo.should.equal(1); }
+ if (msg.parts.index === 1) { msg.foo.should.equal(2); }
+ if (msg.parts.index === 2) { msg.foo.should.equal(3); }
+ if (msg.parts.index === 3) { msg.foo.should.equal(4); done(); }
+ });
+ sn1.receive({foo:[1,2,3,4]});
+ });
+ });
+
it('should split an array into multiple messages of a specified size', function(done) {
var flow = [{id:"sn1", type:"split", wires:[["sn2"]], arraySplt:3, arraySpltType:"len"},
{id:"sn2", type:"helper"}];
@@ -108,6 +129,31 @@ describe('SPLIT node', function() {
});
});
+ it('should split an object sub property into pieces', function(done) {
+ var flow = [{id:"sn1", type:"split", property:"foo.bar",wires:[["sn2"]]},
+ {id:"sn2", type:"helper"}];
+ helper.load(splitNode, flow, function() {
+ var sn1 = helper.getNode("sn1");
+ var sn2 = helper.getNode("sn2");
+ var count = 0;
+ sn2.on("input", function(msg) {
+ msg.should.have.property("foo");
+ msg.foo.should.have.property("bar");
+ msg.should.have.property("parts");
+ msg.parts.should.have.property("type","object");
+ msg.parts.should.have.property("key");
+ msg.parts.should.have.property("count");
+ msg.parts.should.have.property("index");
+ msg.parts.should.have.property("property","foo.bar");
+ msg.topic.should.equal("foo");
+ if (msg.parts.index === 0) { msg.foo.bar.should.equal(1); }
+ if (msg.parts.index === 1) { msg.foo.bar.should.equal("2"); }
+ if (msg.parts.index === 2) { msg.foo.bar.should.equal(true); done(); }
+ });
+ sn1.receive({topic:"foo",foo:{bar:{a:1,b:"2",c:true}}});
+ });
+ });
+
it('should split an object into pieces and overwrite their topics', function(done) {
var flow = [{id:"sn1", type:"split", addname:"topic", wires:[["sn2"]]},
{id:"sn2", type:"helper"}];
@@ -516,6 +562,7 @@ describe('JOIN node', function() {
n1.receive({payload:{a:1}});
});
});
+
it('should join things into an array ignoring msg.parts.index in manual mode', function(done) {
var flow = [{id:"n1", type:"join", wires:[["n2"]], count:3, joiner:",",mode:"custom"},
{id:"n2", type:"helper"}];
@@ -562,6 +609,32 @@ describe('JOIN node', function() {
});
});
+ it('should join things into an array on a sub property in auto mode', function(done) {
+ var flow = [{id:"n1", type:"join", wires:[["n2"]], count:3, joiner:",", 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("foo");
+ msg.foo.should.have.property("bar");
+ msg.foo.bar.should.be.an.Array();
+ msg.foo.bar[0].should.equal("A");
+ msg.foo.bar[1].should.equal("B");
+ //msg.payload[2].a.should.equal(1);
+ done();
+ }
+ catch(e) {done(e);}
+ });
+ n1.receive({foo:{bar:"A"}, parts:{id:1, type:"array", len:1, index:0, count:4, property:"foo.bar"}});
+ n1.receive({foo:{bar:"B"}, parts:{id:1, type:"array", len:1, index:1, count:4, property:"foo.bar"}});
+ n1.receive({foo:{bar:"C"}, parts:{id:1, type:"array", len:1, index:2, count:4, property:"foo.bar"}});
+ n1.receive({foo:{bar:"D"}, parts:{id:1, type:"array", len:1, index:3, count:4, property:"foo.bar"}});
+ });
+ });
+
+
it('should join strings into a buffer after a count', function(done) {
var flow = [{id:"n1", type:"join", wires:[["n2"]], count:2, build:"buffer", joinerType:"bin", joiner:"", mode:"custom"},
{id:"n2", type:"helper"}];
@@ -639,6 +712,35 @@ describe('JOIN node', function() {
});
});
+ it('should merge sub property objects', function(done) {
+ var flow = [{id:"n1", type:"join", wires:[["n2"]], count:5, property:"foo.bar", build:"merged", mode:"custom"},
+ {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("foo");
+ msg.foo.should.have.property("bar");
+ msg.foo.bar.should.have.property("a",1);
+ msg.foo.bar.should.have.property("b",2);
+ msg.foo.bar.should.have.property("c",3);
+ msg.foo.bar.should.have.property("d",4);
+ msg.foo.bar.should.have.property("e",5);
+ done();
+ }
+ catch(e) { done(e)}
+ });
+ n1.receive({foo:{bar:{a:9}, topic:"f"}});
+ n1.receive({foo:{bar:{a:1}, topic:"a"}});
+ n1.receive({foo:{bar:{b:9}, topic:"b"}});
+ n1.receive({foo:{bar:{b:2}, topic:"b"}});
+ n1.receive({foo:{bar:{c:3}, topic:"c"}});
+ n1.receive({foo:{bar:{d:4}, topic:"d"}});
+ n1.receive({foo:{bar:{e:5}, topic:"e"}});
+ });
+ });
+
it('should merge full msg objects', function(done) {
var flow = [{id:"n1", type:"join", wires:[["n2"]], count:6, build:"merged", mode:"custom", propertyType:"full", property:""},
{id:"n2", type:"helper"}];