|
|
|
|
|
|
|
|
this.config = config; |
|
|
this.config = config; |
|
|
this.state = {}; |
|
|
this.state = {}; |
|
|
var node = this; |
|
|
var node = this; |
|
|
var NodeHelper = require('./NodeHelper.js'); |
|
|
|
|
|
var fs = require('fs'); |
|
|
var fs = require('fs'); |
|
|
var h = new NodeHelper(node); |
|
|
|
|
|
|
|
|
var decimal = /^\s*[+-]{0,1}\s*([\d]+(\.[\d]*)*)\s*$/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Delete persistent states on change/deploy |
|
|
|
|
|
DeletePersistFile(); |
|
|
|
|
|
|
|
|
// 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 }); |
|
|
|
|
|
DeletePersistFile(req.query.nodeid); |
|
|
|
|
|
res.json({ status: 220 }); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
// Populate the state array with the persisten file |
|
|
// Populate the state array with the persisten file |
|
|
if (this.config.persist == true) { |
|
|
|
|
|
|
|
|
if (node.config.persist == true) { |
|
|
try { |
|
|
try { |
|
|
var contents = fs.readFileSync(node.id.toString()).toString(); |
|
|
|
|
|
|
|
|
var contents = fs.readFileSync("states/" + node.id.toString()).toString(); |
|
|
if (typeof contents !== 'undefined') { |
|
|
if (typeof contents !== 'undefined') { |
|
|
node.state = JSON.parse(contents); |
|
|
node.state = JSON.parse(contents); |
|
|
node.status({fill: "blue",shape: "ring",text: "Loaded persistent states (" + Object.keys(this.state).length + " total)."}); |
|
|
|
|
|
|
|
|
node.status({fill: "blue",shape: "ring",text: "Loaded persistent states (" + Object.keys(node.state).length + " total)."}); |
|
|
} |
|
|
} |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
node.status({fill: "grey",shape: "ring",text: "No persistent states"}); |
|
|
node.status({fill: "grey",shape: "ring",text: "No persistent states"}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (topic !== undefined && payload !== undefined) { |
|
|
if (topic !== undefined && payload !== undefined) { |
|
|
|
|
|
|
|
|
var value = h.ToBoolean( payload ); |
|
|
|
|
|
|
|
|
var value = ToBoolean( payload ); |
|
|
var state = node.state; |
|
|
var state = node.state; |
|
|
|
|
|
|
|
|
state[topic] = value; |
|
|
state[topic] = value; |
|
|
|
|
|
|
|
|
// Sabe the state array to a perisistent file |
|
|
// Sabe the state array to a perisistent file |
|
|
if (this.config.persist == true) { |
|
|
if (this.config.persist == true) { |
|
|
fs.writeFileSync(this.id.toString(),JSON.stringify(state)); |
|
|
|
|
|
|
|
|
if (!fs.existsSync("states")) fs.mkdirSync("states"); |
|
|
|
|
|
fs.writeFileSync("states/" + node.id.toString(),JSON.stringify(state)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Do we have as many inputs as we expect? |
|
|
// Do we have as many inputs as we expect? |
|
|
|
|
|
|
|
|
var resOR = CalculateResult("OR"); |
|
|
var resOR = CalculateResult("OR"); |
|
|
var resXOR = CalculateResult("XOR"); |
|
|
var resXOR = CalculateResult("XOR"); |
|
|
|
|
|
|
|
|
if (this.config.filtertrue == "onlytrue") { |
|
|
|
|
|
|
|
|
if (node.config.filtertrue == "onlytrue") { |
|
|
if (!resAND) { resAND = null }; |
|
|
if (!resAND) { resAND = null }; |
|
|
if (!resOR) { resOR = null }; |
|
|
if (!resOR) { resOR = null }; |
|
|
if (!resXOR) { resXOR = null }; |
|
|
if (!resXOR) { resXOR = null }; |
|
|
} |
|
|
} |
|
|
h.SetResult(resAND,resOR,resXOR, node.config.topic); |
|
|
|
|
|
|
|
|
SetResult(resAND,resOR,resXOR, node.config.topic); |
|
|
} |
|
|
} |
|
|
else if(keyCount > node.config.inputCount ) { |
|
|
else if(keyCount > node.config.inputCount ) { |
|
|
node.warn( |
|
|
node.warn( |
|
|
|
|
|
|
|
|
+ " [Logic]: More than the specified " |
|
|
+ " [Logic]: More than the specified " |
|
|
+ node.config.inputCount + " topics received, resetting. Will not output new value until " + node.config.inputCount + " new topics have been received."); |
|
|
+ node.config.inputCount + " topics received, resetting. Will not output new value until " + node.config.inputCount + " new topics have been received."); |
|
|
node.state = {}; |
|
|
node.state = {}; |
|
|
h.DisplayUnkownStatus(); |
|
|
|
|
|
|
|
|
DisplayUnkownStatus(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
function DeletePersistFile (){ |
|
|
|
|
|
|
|
|
this.on('close', function(removed, done) { |
|
|
|
|
|
if (removed) { |
|
|
|
|
|
// This node has been deleted |
|
|
|
|
|
// Delete persistent states on change/deploy |
|
|
|
|
|
DeletePersistFile(node.id); |
|
|
|
|
|
} else { |
|
|
|
|
|
// This node is being restarted |
|
|
|
|
|
} |
|
|
|
|
|
done(); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
function DeletePersistFile (_nodeid){ |
|
|
// Detele the persist file |
|
|
// Detele the persist file |
|
|
|
|
|
var _node = RED.nodes.getNode(_nodeid); // Gets node object from nodeit, because when called from the config html, the node object is not defined |
|
|
try { |
|
|
try { |
|
|
fs.unlinkSync(node.id.toString()); |
|
|
|
|
|
node.status({fill: "red",shape: "ring",text: "Persistent states deleted."}); |
|
|
|
|
|
|
|
|
fs.unlinkSync("states/" + _nodeid.toString()); |
|
|
|
|
|
_node.status({fill: "red",shape: "ring",text: "Persistent states deleted ("+_nodeid.toString()+")."}); |
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
node.status({fill: "red",shape: "ring",text: "Error deleting persistent file: " + error.toString()}); |
|
|
|
|
|
|
|
|
_node.status({fill: "red",shape: "ring",text: "Error deleting persistent file: " + error.toString()}); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return res; |
|
|
return res; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function ToBoolean( value ) { |
|
|
|
|
|
var res = false; |
|
|
|
|
|
|
|
|
|
|
|
if (typeof value === 'boolean') { |
|
|
|
|
|
res = value; |
|
|
|
|
|
} |
|
|
|
|
|
else if( typeof value === 'number' || typeof value === 'string' ) { |
|
|
|
|
|
// Is it formated as a decimal number? |
|
|
|
|
|
if( decimal.test( value ) ) { |
|
|
|
|
|
var v = parseFloat( value ); |
|
|
|
|
|
res = v != 0; |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
res = value.toLowerCase() === "true"; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function DisplayStatus ( value ) { |
|
|
|
|
|
node.status( |
|
|
|
|
|
{ |
|
|
|
|
|
fill: value ? "green" : "red", |
|
|
|
|
|
shape: value ? "dot" : "ring", |
|
|
|
|
|
text: value ? "true" : "false" |
|
|
|
|
|
} |
|
|
|
|
|
); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function DisplayUnkownStatus () { |
|
|
|
|
|
node.status( |
|
|
|
|
|
{ |
|
|
|
|
|
fill: "gray", |
|
|
|
|
|
shape: "dot", |
|
|
|
|
|
text: "Unknown" |
|
|
|
|
|
}); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function SetResult( _valueAND, _valueOR, _valueXOR, optionalTopic ) { |
|
|
|
|
|
DisplayStatus( "AND:" + _valueAND + " OR:" +_valueOR + " XOR:" +_valueXOR); |
|
|
|
|
|
|
|
|
|
|
|
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); |