|  |  | @@ -1,5 +1,5 @@ | 
		
	
		
			
			|  |  |  | module.exports = function(RED) { | 
		
	
		
			
			|  |  |  | function BooleanLogicUltimate(config) { | 
		
	
		
			
			|  |  |  | module.exports = function (RED) { | 
		
	
		
			
			|  |  |  | function BooleanLogicUltimate(config) { | 
		
	
		
			
			|  |  |  | RED.nodes.createNode(this, config); | 
		
	
		
			
			|  |  |  | var node = this; | 
		
	
		
			
			|  |  |  | node.config = config; | 
		
	
	
		
			
			|  |  | @@ -7,7 +7,7 @@ module.exports = function(RED) { | 
		
	
		
			
			|  |  |  | node.sInitializeWith = typeof node.config.sInitializeWith === "undefined" ? "WaitForPayload" : node.config.sInitializeWith; | 
		
	
		
			
			|  |  |  | var fs = require('fs'); | 
		
	
		
			
			|  |  |  | var decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/ | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Helper for the config html, to be able to delete the peristent states file | 
		
	
		
			
			|  |  |  | RED.httpAdmin.get("/stateoperation_delete", RED.auth.needsPermission('BooleanLogicUltimate.read'), function (req, res) { | 
		
	
		
			
			|  |  |  | //node.send({ req: req }); | 
		
	
	
		
			
			|  |  | @@ -27,35 +27,33 @@ module.exports = function(RED) { | 
		
	
		
			
			|  |  |  | var contents = fs.readFileSync("states/" + node.id.toString()).toString(); | 
		
	
		
			
			|  |  |  | if (typeof contents !== 'undefined') { | 
		
	
		
			
			|  |  |  | node.jSonStates = JSON.parse(contents); | 
		
	
		
			
			|  |  |  | setNodeStatus({fill: "blue",shape: "ring",text: "Loaded persistent states (" + Object.keys(node.jSonStates).length + " total)."}); | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "blue", shape: "ring", text: "Loaded persistent states (" + Object.keys(node.jSonStates).length + " total)." }); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } catch (error) { | 
		
	
		
			
			|  |  |  | setNodeStatus({fill: "grey",shape: "ring",text: "No persistent states"}); | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "grey", shape: "ring", text: "No persistent states" }); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } else { | 
		
	
		
			
			|  |  |  | setNodeStatus({fill: "yellow",shape: "dot",text: "Waiting for input states"}); | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "yellow", shape: "dot", text: "Waiting for input states" }); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | // 14/08/2019 If some inputs are to be initialized, create a dummy items in the array | 
		
	
		
			
			|  |  |  | initUndefinedInputs(); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | this.on('input', function (msg) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | var topic = msg.topic; | 
		
	
		
			
			|  |  |  | var payload = msg.payload; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (topic !== undefined && payload !== undefined) { | 
		
	
		
			
			|  |  |  | var value = ToBoolean( payload ); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | var value = ToBoolean(payload); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // 14/08/2019 if inputs are initialized, remove a "dummy" item from the state's array, as soon as new topic arrives | 
		
	
		
			
			|  |  |  | if(node.sInitializeWith !== "WaitForPayload") | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | if (node.sInitializeWith !== "WaitForPayload") { | 
		
	
		
			
			|  |  |  | // Search if the current topic is in the state array | 
		
	
		
			
			|  |  |  | if (typeof node.jSonStates[topic] === "undefined") | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | if (typeof node.jSonStates[topic] === "undefined") { | 
		
	
		
			
			|  |  |  | // Delete one dummy | 
		
	
		
			
			|  |  |  | for (let index = 0; index < node.config.inputCount; index++) { | 
		
	
		
			
			|  |  |  | if (node.jSonStates.hasOwnProperty("dummy" + index)) { | 
		
	
	
		
			
			|  |  | @@ -63,30 +61,30 @@ module.exports = function(RED) { | 
		
	
		
			
			|  |  |  | delete node.jSonStates["dummy" + index]; | 
		
	
		
			
			|  |  |  | //RED.log.info(JSON.stringify(node.jSonStates)) | 
		
	
		
			
			|  |  |  | break; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Add current attribute | 
		
	
		
			
			|  |  |  | node.jSonStates[topic] = value; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Save the state array to a perisistent file | 
		
	
		
			
			|  |  |  | if (node.config.persist == true) { | 
		
	
		
			
			|  |  |  | if (node.config.persist == true) { | 
		
	
		
			
			|  |  |  | try { | 
		
	
		
			
			|  |  |  | if (!fs.existsSync("states")) fs.mkdirSync("states"); | 
		
	
		
			
			|  |  |  | fs.writeFileSync("states/" + node.id.toString(),JSON.stringify(node.jSonStates)); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | fs.writeFileSync("states/" + node.id.toString(), JSON.stringify(node.jSonStates)); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } catch (error) { | 
		
	
		
			
			|  |  |  | setNodeStatus({fill: "red",shape: "dot",text: "Node cannot write to filesystem: " + error}); | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "red", shape: "dot", text: "Node cannot write to filesystem: " + error }); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // Do we have as many inputs as we expect? | 
		
	
		
			
			|  |  |  | var keyCount = Object.keys(node.jSonStates).length; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if( keyCount == node.config.inputCount ) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (keyCount == node.config.inputCount) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | var resAND = CalculateResult("AND"); | 
		
	
		
			
			|  |  |  | var resOR = CalculateResult("OR"); | 
		
	
		
			
			|  |  |  | var resXOR = CalculateResult("XOR"); | 
		
	
	
		
			
			|  |  | @@ -101,29 +99,26 @@ module.exports = function(RED) { | 
		
	
		
			
			|  |  |  | if (node.config.outputtriggeredby == "onlyonetopic") { | 
		
	
		
			
			|  |  |  | if (typeof node.config.triggertopic !== "undefined" | 
		
	
		
			
			|  |  |  | && node.config.triggertopic !== "" | 
		
	
		
			
			|  |  |  | && msg.hasOwnProperty("topic") && msg.topic !=="" | 
		
	
		
			
			|  |  |  | && node.config.triggertopic === msg.topic) | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | SetResult(resAND, resOR, resXOR, node.config.topic,msg); | 
		
	
		
			
			|  |  |  | } else | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "grey", shape: "ring", text: "Saved (" + (msg.hasOwnProperty("topic") ? msg.topic : "empty input topic") + ") " + value}); | 
		
	
		
			
			|  |  |  | && msg.hasOwnProperty("topic") && msg.topic !== "" | 
		
	
		
			
			|  |  |  | && node.config.triggertopic === msg.topic) { | 
		
	
		
			
			|  |  |  | SetResult(resAND, resOR, resXOR, node.config.topic, msg); | 
		
	
		
			
			|  |  |  | } else { | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "grey", shape: "ring", text: "Saved (" + (msg.hasOwnProperty("topic") ? msg.topic : "empty input topic") + ") " + value }); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } else | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | SetResult(resAND, resOR, resXOR, node.config.topic,msg); | 
		
	
		
			
			|  |  |  | } else { | 
		
	
		
			
			|  |  |  | SetResult(resAND, resOR, resXOR, node.config.topic, msg); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else if(keyCount > node.config.inputCount ) { | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "gray", shape: "ring", text: "Reset due to unexpected new topic"}); | 
		
	
		
			
			|  |  |  | else if (keyCount > node.config.inputCount) { | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "gray", shape: "ring", text: "Reset due to unexpected new topic" }); | 
		
	
		
			
			|  |  |  | DeletePersistFile(); | 
		
	
		
			
			|  |  |  | } else { | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "green", shape: "ring", text: "Arrived topic " + keyCount + " of " + node.config.inputCount}); | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "green", shape: "ring", text: "Arrived topic " + keyCount + " of " + node.config.inputCount }); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | this.on('close', function(removed, done) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | this.on('close', function (removed, done) { | 
		
	
		
			
			|  |  |  | if (removed) { | 
		
	
		
			
			|  |  |  | // This node has been deleted | 
		
	
		
			
			|  |  |  | // Delete persistent states on change/deploy | 
		
	
	
		
			
			|  |  | @@ -134,13 +129,13 @@ module.exports = function(RED) { | 
		
	
		
			
			|  |  |  | done(); | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | function DeletePersistFile (){ | 
		
	
		
			
			|  |  |  | function DeletePersistFile() { | 
		
	
		
			
			|  |  |  | // Detele the persist file | 
		
	
		
			
			|  |  |  | try { | 
		
	
		
			
			|  |  |  | if (fs.existsSync("states/" + node.id.toString())) fs.unlinkSync("states/" + node.id.toString()); | 
		
	
		
			
			|  |  |  | setNodeStatus({fill: "red",shape: "ring",text: "Persistent states deleted ("+node.id.toString()+")."}); | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "red", shape: "ring", text: "Persistent states deleted (" + node.id.toString() + ")." }); | 
		
	
		
			
			|  |  |  | } catch (error) { | 
		
	
		
			
			|  |  |  | setNodeStatus({fill: "red",shape: "ring",text: "Error deleting persistent file: " + error.toString()}); | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "red", shape: "ring", text: "Error deleting persistent file: " + error.toString() }); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | node.jSonStates = {}; // Resets inputs | 
		
	
		
			
			|  |  |  | // 14/08/2019 If the inputs are to be initialized, create a dummy items in the array | 
		
	
	
		
			
			|  |  | @@ -148,144 +143,121 @@ module.exports = function(RED) { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | function initUndefinedInputs() { | 
		
	
		
			
			|  |  |  | if (node.sInitializeWith !== "WaitForPayload") | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | if (node.sInitializeWith !== "WaitForPayload") { | 
		
	
		
			
			|  |  |  | var nTotalDummyToCreate = Number(node.config.inputCount) - Object.keys(node.jSonStates).length; | 
		
	
		
			
			|  |  |  | if (nTotalDummyToCreate > 0) { | 
		
	
		
			
			|  |  |  | RED.log.info("BooleanLogicUltimate: Will create " + nTotalDummyToCreate + " dummy (" + node.sInitializeWith + ") values") | 
		
	
		
			
			|  |  |  | for (let index = 0; index < nTotalDummyToCreate; index++) { | 
		
	
		
			
			|  |  |  | node.jSonStates["dummy" + index] = node.sInitializeWith === "false" ? false : true; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | setTimeout(() => { setNodeStatus({fill: "green",shape: "ring",text: "Initialized " + nTotalDummyToCreate + " undefined inputs with " + node.sInitializeWith});}, 4000) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | setTimeout(() => { setNodeStatus({ fill: "green", shape: "ring", text: "Initialized " + nTotalDummyToCreate + " undefined inputs with " + node.sInitializeWith }); }, 4000) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | function setNodeStatus({fill, shape, text}) | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | function setNodeStatus({ fill, shape, text }) { | 
		
	
		
			
			|  |  |  | var dDate = new Date(); | 
		
	
		
			
			|  |  |  | node.status({fill: fill,shape: shape,text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")"}) | 
		
	
		
			
			|  |  |  | node.status({ fill: fill, shape: shape, text: text + " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" }) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | function CalculateResult(_operation) { | 
		
	
		
			
			|  |  |  | var res; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if( _operation == "XOR") { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (_operation == "XOR") { | 
		
	
		
			
			|  |  |  | res = PerformXOR(); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else { | 
		
	
		
			
			|  |  |  | // We need a starting value to perform AND and OR operations. | 
		
	
		
			
			|  |  |  | var keys = Object.keys(node.jSonStates); | 
		
	
		
			
			|  |  |  | res = node.jSonStates[keys[0]]; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | for( var i = 1; i < keys.length; ++i ) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | for (var i = 1; i < keys.length; ++i) { | 
		
	
		
			
			|  |  |  | var key = keys[i]; | 
		
	
		
			
			|  |  |  | res = PerformSimpleOperation( _operation, res, node.jSonStates[key] ); | 
		
	
		
			
			|  |  |  | res = PerformSimpleOperation(_operation, res, node.jSonStates[key]); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | return res; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | function PerformXOR() | 
		
	
		
			
			|  |  |  | { | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | return res; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | function PerformXOR() { | 
		
	
		
			
			|  |  |  | // XOR = exclusively one input is true. As such, we just count the number of true values and compare to 1. | 
		
	
		
			
			|  |  |  | var trueCount = 0; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | for( var key in node.jSonStates ) { | 
		
	
		
			
			|  |  |  | if( node.jSonStates[key] ) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | for (var key in node.jSonStates) { | 
		
	
		
			
			|  |  |  | if (node.jSonStates[key]) { | 
		
	
		
			
			|  |  |  | trueCount++; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | return trueCount == 1; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | function PerformSimpleOperation( operation, val1, val2 ) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | function PerformSimpleOperation(operation, val1, val2) { | 
		
	
		
			
			|  |  |  | var res; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if( operation === "AND" ) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (operation === "AND") { | 
		
	
		
			
			|  |  |  | res = val1 && val2; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else if( operation === "OR" ) { | 
		
	
		
			
			|  |  |  | else if (operation === "OR") { | 
		
	
		
			
			|  |  |  | res = val1 || val2; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else { | 
		
	
		
			
			|  |  |  | node.error( "Unknown operation: " + operation ); | 
		
	
		
			
			|  |  |  | node.error("Unknown operation: " + operation); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | return res; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | function ToBoolean( value ) { | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | function ToBoolean(value) { | 
		
	
		
			
			|  |  |  | var res = false; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | if (typeof value === 'boolean') { | 
		
	
		
			
			|  |  |  | res = value; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else if( typeof value === 'number' || typeof value === 'string' ) { | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else if (typeof value === 'number' || typeof value === 'string') { | 
		
	
		
			
			|  |  |  | // Is it formated as a decimal number? | 
		
	
		
			
			|  |  |  | if( decimal.test( value ) ) { | 
		
	
		
			
			|  |  |  | var v = parseFloat( value ); | 
		
	
		
			
			|  |  |  | if (decimal.test(value)) { | 
		
	
		
			
			|  |  |  | var v = parseFloat(value); | 
		
	
		
			
			|  |  |  | res = v != 0; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | else { | 
		
	
		
			
			|  |  |  | res = value.toLowerCase() === "true"; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | return res; | 
		
	
		
			
			|  |  |  | }; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | function SetResult(_valueAND, _valueOR, _valueXOR, optionalTopic,_msg) { | 
		
	
		
			
			|  |  |  | setNodeStatus({fill: "green",shape: "dot",text: "(AND)" + _valueAND + " (OR)" +_valueOR + " (XOR)" +_valueXOR}); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // 24/01/2020 Output the entire input msg by duplicating the input and replacing only relevant fields. | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | function SetResult(_valueAND, _valueOR, _valueXOR, optionalTopic, _msg) { | 
		
	
		
			
			|  |  |  | setNodeStatus({ fill: "green", shape: "dot", text: "(AND)" + (_valueAND !== null ? _valueAND : "---") + " (OR)" + (_valueOR !== null ? _valueOR : "---") + " (XOR)" + (_valueXOR !== null ? _valueXOR : "---") }); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | var msgAND = null; | 
		
	
		
			
			|  |  |  | if (_valueAND != null) { | 
		
	
		
			
			|  |  |  | var msgAND = RED.util.cloneMessage(_msg); | 
		
	
		
			
			|  |  |  | msgAND = RED.util.cloneMessage(_msg); | 
		
	
		
			
			|  |  |  | msgAND.topic = optionalTopic === undefined ? "result" : optionalTopic; | 
		
	
		
			
			|  |  |  | msgAND.operation = "AND"; | 
		
	
		
			
			|  |  |  | msgAND.payload = _valueAND; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | if (_valueOR!=null){ | 
		
	
		
			
			|  |  |  | var msgOR = RED.util.cloneMessage(_msg); | 
		
	
		
			
			|  |  |  | var msgOR = null; | 
		
	
		
			
			|  |  |  | if (_valueOR != null) { | 
		
	
		
			
			|  |  |  | msgOR = RED.util.cloneMessage(_msg); | 
		
	
		
			
			|  |  |  | msgOR.topic = optionalTopic === undefined ? "result" : optionalTopic; | 
		
	
		
			
			|  |  |  | msgOR.operation = "OR"; | 
		
	
		
			
			|  |  |  | msgOR.payload= _valueOR; | 
		
	
		
			
			|  |  |  | msgOR.payload = _valueOR; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | var msgXOR = null; | 
		
	
		
			
			|  |  |  | if (_valueXOR != null) { | 
		
	
		
			
			|  |  |  | var msgXOR = RED.util.cloneMessage(_msg); | 
		
	
		
			
			|  |  |  | msgXOR = RED.util.cloneMessage(_msg); | 
		
	
		
			
			|  |  |  | msgXOR.topic = optionalTopic === undefined ? "result" : optionalTopic; | 
		
	
		
			
			|  |  |  | msgXOR.operation = "XOR"; | 
		
	
		
			
			|  |  |  | msgXOR.payload= _valueXOR; | 
		
	
		
			
			|  |  |  | msgXOR.payload = _valueXOR; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | node.send([msgAND, msgOR, msgXOR]); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | // if (_valueAND!=null){ | 
		
	
		
			
			|  |  |  | // 	var msgAND = { | 
		
	
		
			
			|  |  |  | // 		topic: optionalTopic === undefined ? "result" : optionalTopic, | 
		
	
		
			
			|  |  |  | // 		operation:"AND", | 
		
	
		
			
			|  |  |  | // 		payload: _valueAND | 
		
	
		
			
			|  |  |  | // 	}; | 
		
	
		
			
			|  |  |  | // } | 
		
	
		
			
			|  |  |  | // if (_valueOR!=null){ | 
		
	
		
			
			|  |  |  | // 	var msgOR = { | 
		
	
		
			
			|  |  |  | // 		topic: optionalTopic === undefined ? "result" : optionalTopic, | 
		
	
		
			
			|  |  |  | // 		operation:"OR", | 
		
	
		
			
			|  |  |  | // 		payload: _valueOR | 
		
	
		
			
			|  |  |  | // 	}; | 
		
	
		
			
			|  |  |  | // } | 
		
	
		
			
			|  |  |  | // if (_valueXOR!=null){ | 
		
	
		
			
			|  |  |  | // 	var msgXOR = { | 
		
	
		
			
			|  |  |  | // 		topic: optionalTopic === undefined ? "result" : optionalTopic, | 
		
	
		
			
			|  |  |  | // 		operation:"XOR", | 
		
	
		
			
			|  |  |  | // 		payload: _valueXOR | 
		
	
		
			
			|  |  |  | // 	}; | 
		
	
		
			
			|  |  |  | // } | 
		
	
		
			
			|  |  |  | // node.send([msgAND,msgOR,msgXOR]); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | }; | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | RED.nodes.registerType("BooleanLogicUltimate",BooleanLogicUltimate); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | RED.nodes.registerType("BooleanLogicUltimate", BooleanLogicUltimate); | 
		
	
		
			
			|  |  |  | } |