node-red-contrib-knx-ultimate
Advanced tools
Comparing version
# node-red-contrib-knx-ultimate | ||
<p> | ||
<b>Version 1.0.6</b><br/> | ||
- Check for invalid node's group address (topic)<br/> | ||
</p> | ||
<p> | ||
<b>Version 1.0.5</b><br/> | ||
@@ -4,0 +8,0 @@ - Fixed the fix for the typo error causing a mess<br/> |
@@ -41,7 +41,5 @@ const knx = require('knx') | ||
module.exports = (RED) => { | ||
module.exports = (RED) => { | ||
RED.httpAdmin.get("/knxUltimateDpts", RED.auth.needsPermission('knxUltimate-config.read'), function (req, res) { | ||
@@ -56,3 +54,3 @@ const dpts = | ||
res.json(dpts) | ||
}); | ||
}) | ||
@@ -64,13 +62,29 @@ function knxUltimateConfigNode(config) { | ||
node.port = config.port | ||
node.csv = readCSV(); // Array from ETS CSV Group Addresses | ||
node.csv = readCSV(config.csvincollato); // Array from ETS CSV Group Addresses | ||
// Entry point for reading csv from the other nodes | ||
RED.httpAdmin.get("/knxUltimatecsv", RED.auth.needsPermission('knxUltimate-config.read'), function (req, res) { | ||
res.json(node.csv) | ||
}); | ||
var knxErrorTimeout | ||
res.json(node.csv) | ||
}); | ||
var knxErrorTimeout; | ||
node.nodeClients = [] // Stores the registered clients | ||
node.addClient = (_Node) => { | ||
// Check if the node has a valid topic and dpt | ||
if (typeof _Node.topic == "undefined" || typeof _Node.dpt == "undefined") { | ||
_Node.status({ fill: "red", shape: "dot", text: "Empty group address (topic) or datapoint." }) | ||
return; | ||
} else { | ||
// Topic must be in formar x/x/x | ||
if (_Node.topic.split("\/").length < 3) { | ||
_Node.status({ fill: "red", shape: "dot", text: "Wrong group address (topic: " + _Node.topic + ") format." }) | ||
return; | ||
} | ||
} | ||
// Add _Node to the clients array | ||
@@ -87,3 +101,3 @@ node.nodeClients.push(_Node) | ||
node.removeClient = (_Node) => { | ||
@@ -99,3 +113,3 @@ // Remove the client node from the clients array | ||
node.readInitialValues = () => { | ||
@@ -114,3 +128,3 @@ var readHistory = [] | ||
readHistory.push(element.ga) | ||
} | ||
} | ||
} else { | ||
@@ -125,20 +139,27 @@ if (readHistory.includes(oClient.topic)) return | ||
} | ||
node.readValue = topic => { | ||
if (node.knxConnection) { | ||
node.knxConnection.read(topic) | ||
try { | ||
node.knxConnection.read(topic) | ||
} catch (error) { | ||
RED.log.error('knxUltimate readValue: (' + topic + ') ' + error); | ||
node.setClientStatus("error tx", "red", 'readValue: (' + topic + ') ' + error) | ||
} | ||
} | ||
} | ||
node.setClientStatus = (_status, _color, _text) => { | ||
node.status = _status | ||
function nextStatus(oClient) { | ||
oClient.status({ fill: _color, shape: "dot", text: "("+ oClient.topic +") " + _status + " " + _text }) | ||
oClient.status({ fill: _color, shape: "dot", text: "(" + oClient.topic + ") " + _status + " " + _text }) | ||
} | ||
node.nodeClients.map(nextStatus) | ||
} | ||
node.connect = () => { | ||
node.setClientStatus("disconnected","red","") | ||
node.setClientStatus("disconnected", "red", "") | ||
node.knxConnection = new knx.Connection({ | ||
@@ -150,17 +171,17 @@ ipAddr: node.host, | ||
if (knxErrorTimeout == undefined) { | ||
node.setClientStatus("connected","green","") | ||
node.setClientStatus("connected", "green", "") | ||
node.readInitialValues() // Perform initial read if applicable | ||
} | ||
}, | ||
error: (connstatus) => { | ||
node.error(connstatus) | ||
if (connstatus == "E_KNX_CONNECTION") { | ||
node.setClientStatus("knxError","yellow","Error KNX BUS communication") | ||
} else { | ||
node.setClientStatus("disconnected","red","") | ||
} | ||
error: function(connstatus) { | ||
node.error(connstatus); | ||
if (connstatus == "E_KNX_CONNECTION") { | ||
node.setClientStatus("knxError", "yellow", "Error KNX BUS communication") | ||
} else { | ||
node.setClientStatus("disconnected", "red", "") | ||
} | ||
} | ||
} | ||
}) | ||
node.Disconnect = () => { | ||
@@ -181,9 +202,9 @@ node.setClientStatus("disconnected", "red", "") | ||
// Get the GA from CVS | ||
let oGA=node.csv.filter(sga => sga.ga == dest)[0] | ||
let oGA = node.csv.filter(sga => sga.ga == dest)[0] | ||
let msg = buildInputMessage(src, dest, evt, rawValue, oGA.dpt, oGA.devicename) | ||
input.status({ fill: "green", shape: "dot", text: "("+ msg.knx.destination +") " + msg.payload + " dpt:" + msg.knx.dpt }) | ||
input.send(msg) | ||
}else if (input.topic == dest) { | ||
input.status({ fill: "green", shape: "dot", text: "(" + msg.knx.destination + ") " + msg.payload + " dpt:" + msg.knx.dpt }) | ||
input.send(msg) | ||
} else if (input.topic == dest) { | ||
let msg = buildInputMessage(src, dest, evt, rawValue, input.dpt) | ||
input.status({ fill: "green", shape: "dot", text: "("+ input.topic +") " + msg.payload}) | ||
input.status({ fill: "green", shape: "dot", text: "(" + input.topic + ") " + msg.payload }) | ||
input.send(msg) | ||
@@ -201,9 +222,9 @@ } | ||
// Get the DPT | ||
let oGA=node.csv.filter(sga => sga.ga == dest)[0] | ||
let oGA = node.csv.filter(sga => sga.ga == dest)[0] | ||
let msg = buildInputMessage(src, dest, evt, rawValue, oGA.dpt, oGA.devicename) | ||
input.status({ fill: "blue", shape: "dot", text: "("+ msg.knx.destination +") " + msg.payload + " dpt:" + msg.knx.dpt }) | ||
input.send(msg) | ||
}else if (input.topic == dest) { | ||
input.status({ fill: "blue", shape: "dot", text: "(" + msg.knx.destination + ") " + msg.payload + " dpt:" + msg.knx.dpt }) | ||
input.send(msg) | ||
} else if (input.topic == dest) { | ||
let msg = buildInputMessage(src, dest, evt, rawValue, input.dpt) | ||
input.status({ fill: "blue", shape: "dot", text: "("+ input.topic +") " + msg.payload}) | ||
input.status({ fill: "blue", shape: "dot", text: "(" + input.topic + ") " + msg.payload }) | ||
input.send(msg) | ||
@@ -221,9 +242,9 @@ } | ||
// Get the DPT | ||
let oGA=node.csv.filter(sga => sga.ga == dest)[0] | ||
let oGA = node.csv.filter(sga => sga.ga == dest)[0] | ||
let msg = buildInputMessage(src, dest, evt, null, oGA.dpt, oGA.devicename) | ||
input.status({ fill: "grey", shape: "dot", text: "("+ msg.knx.destination +") read dpt:" + msg.knx.dpt }) | ||
input.send(msg) | ||
}else if (input.topic == dest) { | ||
input.status({ fill: "grey", shape: "dot", text: "(" + msg.knx.destination + ") read dpt:" + msg.knx.dpt }) | ||
input.send(msg) | ||
} else if (input.topic == dest) { | ||
let msg = buildInputMessage(src, dest, evt, null, input.dpt) | ||
input.status({ fill: "grey", shape: "dot", text: "("+ input.topic +") read"}) | ||
input.status({ fill: "grey", shape: "dot", text: "(" + input.topic + ") read" }) | ||
input.send(msg) | ||
@@ -239,6 +260,6 @@ } | ||
function buildInputMessage(src, dest, evt, value, inputDpt, _devicename) { | ||
// Resolve DPT and convert value if available | ||
// Resolve DPT and convert value if available | ||
var dpt = dptlib.resolve(inputDpt) | ||
@@ -266,67 +287,69 @@ var jsValue = null | ||
} | ||
function readCSV() { | ||
try { | ||
var ajsonOutput = []; // Array: qui va l'output totale con i nodi per node-red | ||
var _csvText = config.csvincollato; | ||
if (_csvText == "") { | ||
RED.log.info('knxUltimate: no csv ETS found'); | ||
return ajsonOutput; | ||
} else { | ||
RED.log.info('knxUltimate: csv ETS found !'); | ||
// Read and decode the CSV in an Array containing: "group address", "DPT", "Device Name" | ||
let fileGA = _csvText.split("\n"); | ||
// Controllo se le righe dei gruppi contengono il separatore di tabulazione | ||
if (fileGA[0].search("\t") == -1) { | ||
RED.log.error('knxUltimate: ERROR: the csv ETS file must have the tabulation as separator') | ||
return ajsonOutput; | ||
} | ||
for (let index = 0; index < fileGA.length; index++) { | ||
const element = fileGA[index].replace(/\"/g, ""); // Rimuovo le virgolette | ||
if (element !== "") { | ||
if (element.split("\t")[1].search("-") == -1 && element.split("\t")[1].search("/") !== -1) { | ||
// Ho trovato una riga contenente un GA valido, cioè con 2 "/" | ||
if (element.split("\t")[5] == "") { | ||
RED.log.error("knxUltimate: ERROR: Datapoint not set in ETS CSV. Please set the datapoint with ETS and export the group addresses again. ->" + element.split("\t")[0] + " " + element.split("\t")[1]) | ||
return ajsonOutput; | ||
} | ||
var DPTa = element.split("\t")[5].split("-")[1]; | ||
var DPTb = ""; | ||
try { | ||
DPTb = element.split("\t")[5].split("-")[2]; | ||
} catch (error) { | ||
DPTb = "001"; // default | ||
} | ||
if (!DPTb) { | ||
RED.log.warn("knxUltimate: WARNING: Datapoint not fully set (there is only the first part on the left of the '.'). I applied a default .001, but please set the datapoint with ETS and export the group addresses again. ->" + element.split("\t")[0] + " " + element.split("\t")[1] + " Datapoint: " + element.split("\t")[5]); | ||
DPTb = "001"; // default | ||
} | ||
// Trailing zeroes | ||
if (DPTb.length == 1) { | ||
DPTb = "00" + DPTb; | ||
} else if (DPTb.length == 2) { | ||
DPTb = "0" + DPTb; | ||
} if (DPTb.length == 3) { | ||
DPTb = "" + DPTb; // stupid, but for readability | ||
} | ||
ajsonOutput.push({ ga: element.split("\t")[1], dpt: DPTa + "." + DPTb, devicename: element.split("\t")[0] }); | ||
node.on("close", function () { | ||
node.setClientStatus("disconnected","red","") | ||
node.knxConnection = null | ||
}) | ||
function readCSV(_csvText) { | ||
var ajsonOutput = new Array(); // Array: qui va l'output totale con i nodi per node-red | ||
if (_csvText == "") { | ||
RED.log.info('knxUltimate: no csv ETS found'); | ||
return; | ||
} else { | ||
RED.log.info('knxUltimate: csv ETS found !'); | ||
// Read and decode the CSV in an Array containing: "group address", "DPT", "Device Name" | ||
let fileGA = _csvText.split("\n"); | ||
// Controllo se le righe dei gruppi contengono il separatore di tabulazione | ||
if (fileGA[0].search("\t") == -1) { | ||
RED.log.error('knxUltimate: ERROR: the csv ETS file must have the tabulation as separator') | ||
return; | ||
} | ||
for (let index = 0; index < fileGA.length; index++) { | ||
const element = fileGA[index].replace(/\"/g, ""); // Rimuovo le virgolette | ||
if (element !== "") { | ||
if (element.split("\t")[1].search("-") == -1 && element.split("\t")[1].search("/") !== -1) { | ||
// Ho trovato una riga contenente un GA valido, cioè con 2 "/" | ||
if (element.split("\t")[5] == "") { | ||
RED.log.error("knxUltimate: ERROR: Datapoint not set in ETS CSV. Please set the datapoint with ETS and export the group addresses again. ->" + element.split("\t")[0] + " " + element.split("\t")[1]) | ||
return; | ||
} | ||
var DPTa = element.split("\t")[5].split("-")[1]; | ||
var DPTb = element.split("\t")[5].split("-")[2]; | ||
if (typeof DPTb == "undefined") { | ||
RED.log.warn("knxUltimate: WARNING: Datapoint not fully set (there is only the first part on the left of the '.'). I applied a default .001, but please set the datapoint with ETS and export the group addresses again. ->" + element.split("\t")[0] + " " + element.split("\t")[1] + " Datapoint: " + element.split("\t")[5] ); | ||
DPTb = "001"; // default | ||
} | ||
// Trailing zeroes | ||
if (DPTb.length == 1) { | ||
DPTb = "00" + DPTb; | ||
} else if (DPTb.length == 2) { | ||
DPTb = "0" + DPTb; | ||
} if (DPTb.length == 3) { | ||
DPTb = "" + DPTb; // stupid, but for readability | ||
} | ||
//RED.log.info("OK " + element.split("\t")[1]); | ||
// var riga = new Object(); | ||
// riga.ga = encodeURIComponent(element.split("\t")[1]); | ||
// riga.dpt = encodeURIComponent( DPTa + "." + DPTb); | ||
// riga.devicename = encodeURIComponent(element.split("\t")[0]); | ||
// ajsonOutput.push(riga); | ||
ajsonOutput.push({ga:element.split("\t")[1], dpt:DPTa + "." + DPTb, devicename:element.split("\t")[0]}); | ||
//Object.assign(ajsonOutput, {ga: element.split("\t")[1], dpt: DPTa + "." + DPTb, devicename: element.split("\t")[0] }; | ||
} | ||
} | ||
return ajsonOutput; | ||
} | ||
} catch (error) { | ||
for (let index = 0; index < ajsonOutput.length; index++) { | ||
const element = ajsonOutput[index]; | ||
RED.log.error("ARRAYLIST " + element.ga + " " + element.dpt + " " + element.devicename); | ||
} | ||
return ajsonOutput; | ||
} | ||
} | ||
node.on("close", function () { | ||
node.setClientStatus("disconnected","red","") | ||
node.knxConnection = null | ||
}) | ||
@@ -333,0 +356,0 @@ } |
@@ -15,2 +15,15 @@ module.exports = function (RED) { | ||
// Check if the node has a valid topic and dpt | ||
if (typeof node.topic == "undefined" || typeof node.dpt == "undefined") { | ||
node.status({ fill: "red", shape: "dot", text: "Empty group address (topic) or datapoint." }) | ||
return; | ||
} else { | ||
// Topic must be in formar x/x/x | ||
if (node.topic.split("\/").length < 3) { | ||
node.status({ fill: "red", shape: "dot", text: "Wrong group address (topic: " + node.topic + ") format." }) | ||
return; | ||
} | ||
} | ||
node.on("input", function (msg) { | ||
@@ -17,0 +30,0 @@ // 25/07/2019 if payload is read, do a read, otherwise, write to the bus |
{ | ||
"name": "node-red-contrib-knx-ultimate", | ||
"version": "1.0.6", | ||
"version": "1.0.7", | ||
"description": "Single Node KNX IN/OUT with optional ETS group address importer.", | ||
@@ -5,0 +5,0 @@ "dependencies": { |
1151331
0.16%405
7.71%