From 67611f6bb692ea6355150c2906d86f38db0530d0 Mon Sep 17 00:00:00 2001 From: Dave Conway-Jones Date: Fri, 22 Jul 2022 10:18:02 +0100 Subject: [PATCH] Add cbor object packing node and test --- parsers/cbor/70-cbor.html | 44 +++++++++++++ parsers/cbor/70-cbor.js | 38 +++++++++++ parsers/cbor/LICENSE | 14 ++++ parsers/cbor/README.md | 27 ++++++++ parsers/cbor/icons/parser-cbor.png | Bin 0 -> 274 bytes parsers/cbor/package.json | 28 ++++++++ test/parsers/cbor/70-cbor_spec.js | 101 +++++++++++++++++++++++++++++ 7 files changed, 252 insertions(+) create mode 100644 parsers/cbor/70-cbor.html create mode 100644 parsers/cbor/70-cbor.js create mode 100644 parsers/cbor/LICENSE create mode 100644 parsers/cbor/README.md create mode 100644 parsers/cbor/icons/parser-cbor.png create mode 100644 parsers/cbor/package.json create mode 100644 test/parsers/cbor/70-cbor_spec.js diff --git a/parsers/cbor/70-cbor.html b/parsers/cbor/70-cbor.html new file mode 100644 index 00000000..8367e80e --- /dev/null +++ b/parsers/cbor/70-cbor.html @@ -0,0 +1,44 @@ + + + + + + diff --git a/parsers/cbor/70-cbor.js b/parsers/cbor/70-cbor.js new file mode 100644 index 00000000..abed6dbf --- /dev/null +++ b/parsers/cbor/70-cbor.js @@ -0,0 +1,38 @@ + +module.exports = function(RED) { + "use strict"; + var cbor = require('cbor-x'); + + function CborNode(n) { + RED.nodes.createNode(this,n); + this.property = n.property||"payload"; + var node = this; + this.on("input", function(msg) { + var value = RED.util.getMessageProperty(msg,node.property); + if (value !== undefined) { + if (Buffer.isBuffer(value)) { + var l = value.length; + try { + value = cbor.decode(value); + RED.util.setMessageProperty(msg,node.property,value); + node.send(msg); + node.status({text:l +" b->o "+ JSON.stringify(value).length}); + } + catch (e) { + node.error("Bad decode",msg); + node.status({text:"not a cbor buffer"}); + } + } + else { + var le = JSON.stringify(value).length; + value = cbor.encode(value); + RED.util.setMessageProperty(msg,node.property,value); + node.send(msg); + node.status({text:le +" o->b "+ value.length}); + } + } + else { node.warn("No payload found to process"); } + }); + } + RED.nodes.registerType("cbor",CborNode); +} diff --git a/parsers/cbor/LICENSE b/parsers/cbor/LICENSE new file mode 100644 index 00000000..f5b60114 --- /dev/null +++ b/parsers/cbor/LICENSE @@ -0,0 +1,14 @@ +Copyright 2016 JS Foundation and other contributors, https://js.foundation/ +Copyright 2013-2016 IBM Corp. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/parsers/cbor/README.md b/parsers/cbor/README.md new file mode 100644 index 00000000..d0c7fbf9 --- /dev/null +++ b/parsers/cbor/README.md @@ -0,0 +1,27 @@ +node-red-node-cbor +================== + +A Node-RED node to pack and unpack objects to cbor format buffers. + +Install +------- + +Run the following command in your Node-RED user directory - typically `~/.node-red` + + npm install node-red-node-cbor + +Changes +------- + +Version 1.0.0 - move to cbor-x library (more supported and faster). +Usage +----- + +Uses the cbor-x npm to pack and unpack msg.payload objects to cbor format buffers. + +**Note**: this node does not currently encode raw buffer types. +It will automatically try to *decode* any buffer received, and may not cause an error. + +If the input is NOT a buffer it converts it into a msgpack buffer. + +If the input is a msgpack buffer it converts it back to the original type. diff --git a/parsers/cbor/icons/parser-cbor.png b/parsers/cbor/icons/parser-cbor.png new file mode 100644 index 0000000000000000000000000000000000000000..02b5ddc0827853bf3ab620a1f75530fdeb164a43 GIT binary patch literal 274 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6kC$Fy9>jA5L~c#`DCC7XMsm# zF#`j)FbFd;%$g$s6l5>)^mS!_#KbJX#O@!t;~P+DzNd?0h{y4#lh1NB8wj+dd+{B0 ze);%Ei(P~M)87@@j>oziJ7Rlxc_|j3(&(hXT31tjqj=@ z%fGFh{N)qNI%j^S+!ve=n0^&-Y-77{%=tzQo62Orlqq{{WzTKl>{%Cf=ca?-sb7L_ zYpYKys`tn~jCnpGOu{|*+EU{)zQ3kP{KG*bNPSd+y^`=_8P&;onpeP7|t$O Q0(2^ar>mdKI;Vst0Qie#$N&HU literal 0 HcmV?d00001 diff --git a/parsers/cbor/package.json b/parsers/cbor/package.json new file mode 100644 index 00000000..eb0534c2 --- /dev/null +++ b/parsers/cbor/package.json @@ -0,0 +1,28 @@ +{ + "name" : "node-red-node-cbor", + "version" : "1.0.0", + "description" : "A Node-RED node to pack and unpack objects to cbor format", + "dependencies" : { + "cbor-x" : "^1.3.2" + }, + "bundledDependencies": [ + "cbor-x" + ], + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes.git", + "directory": "tree/master/parsers/cbor" + }, + "license": "Apache-2.0", + "keywords": [ "node-red", "cbor" ], + "node-red" : { + "nodes" : { + "cbor": "70-cbor.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "dceejay@gmail.com", + "url": "http://nodered.org" + } +} diff --git a/test/parsers/cbor/70-cbor_spec.js b/test/parsers/cbor/70-cbor_spec.js new file mode 100644 index 00000000..bcebe91c --- /dev/null +++ b/test/parsers/cbor/70-cbor_spec.js @@ -0,0 +1,101 @@ + +var should = require("should"); +var helper = require("node-red-node-test-helper"); +var testNode = require('../../../parsers/cbor/70-cbor.js'); + +describe('cbor node', function() { + "use strict"; + + beforeEach(function(done) { + helper.startServer(done); + }); + + afterEach(function(done) { + helper.unload().then(function() { + helper.stopServer(done); + }); + }); + + it("should be loaded with correct defaults", function(done) { + var flow = [{"id":"n1", "type":"cbor", "name":"cbor1", "wires":[[]]}]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.should.have.property("name", "cbor1"); + done(); + }); + }); + + var buf; + + it('should pack an object', function(done) { + var flow = [{"id":"n1", "type":"cbor", wires:[["n2"]] }, + {id:"n2", type:"helper"}]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.a.property("payload"); + msg.payload.should.be.a.Object; + msg.payload.should.have.length(47); + buf = msg.payload; + done(); + }); + n1.emit("input", {payload:{A:1, B:"string", C:true, D:[1,true,"string"], E:{Y:9,Z:"string"}}}); + }); + }); + + it('should unpack a Buffer', function(done) { + var flow = [{"id":"n1", "type":"cbor", wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.a.property("payload"); + msg.payload.should.have.a.property("A",1); + msg.payload.should.have.a.property("B",'string'); + msg.payload.should.have.a.property("C",true); + msg.payload.should.have.a.property("D",[1,true,"string"]); + msg.payload.should.have.a.property("E"); + msg.payload.E.should.have.a.property("Y",9); + msg.payload.E.should.have.a.property("Z","string"); + done(); + }); + n1.emit("input", {payload:buf}); + }); + }); + + it('should error if the buffer fails to decode', function(done) { + buf[0] = 0x87; + var flow = [{"id":"n1", "type":"cbor", wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + done("should not get here if there is an error."); + }); + setTimeout(function() { + done(); + }, 25); + n1.emit("input", {payload:buf}); + }); + }); + + it('ignore msg with no payload', function(done) { + var flow = [{"id":"n1", "type":"cbor", wires:[["n2"]] }, + {id:"n2", type:"helper"} ]; + helper.load(testNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + done("should not get here with no payload."); + }); + setTimeout(function() { + done(); + }, 25); + n1.emit("input", {topic:1}); + }); + }); + +});