New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

node-red-contrib-knx-ultimate

Package Overview
Dependencies
Maintainers
1
Versions
461
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-red-contrib-knx-ultimate - npm Package Compare versions

Comparing version

to
1.1.29

examples/All Samples are in the Wiki.json

7

CHANGELOG.md

@@ -7,3 +7,10 @@ # node-red-contrib-knx-ultimate

<p>
<b>Version 1.1.29</b><br/>
- Changed Node KNX Icon, logo and colors, thanks @svenflender <br/>
- New in config-node: copy/paste friendly text block, with a list of all KNX Nodes (for using, for example, in KNX Router line/zone filters).<br/>
- New: added subtype decoded value **payloadsubtypevalue** ( for exampe, On/Off, Ramp/NoRamp, Start/Stop, Alarm/NoAlarm ). <a href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/-Sample---Subtype" target="_blank">See here an example</a><br/>
</p>
<p>
<b>Version 1.1.28</b><br/>

@@ -10,0 +17,0 @@ - New: Added topic property<br/>

138

knxUltimate-config.js

@@ -70,3 +70,3 @@ const knx = require('knx')

node.physAddr = config.physAddr || "15.15.22"; // the KNX physical address we'd like to use
node.suppressACKRequest = typeof config.suppressACKRequest ==="undefined" ? false:config.suppressACKRequest; // enable this option to suppress the acknowledge flag with outgoing L_Data.req requests. LoxOne needs this
node.suppressACKRequest = typeof config.suppressACKRequest === "undefined" ? false : config.suppressACKRequest; // enable this option to suppress the acknowledge flag with outgoing L_Data.req requests. LoxOne needs this
node.linkStatus = "disconnected";

@@ -84,3 +84,3 @@ node.nodeClients = [] // Stores the registered clients

node.loglevel = config.loglevel !== undefined ? config.loglevel : "info"; // 06/02/2020 by Heleon19 Loglevel default info
// Endpoint for reading csv from the other nodes

@@ -90,2 +90,3 @@ RED.httpAdmin.get("/knxUltimatecsv", RED.auth.needsPermission('knxUltimate-config.read'), function (req, res) {

});
// 14/08/2019 Endpoint for retrieving the ethernet interfaces

@@ -99,3 +100,3 @@ RED.httpAdmin.get("/knxUltimateETHInterfaces", RED.auth.needsPermission('knxUltimate-config.read'), function (req, res) {

if (Object.keys(oiFaces[ifname]).length === 1) {
if (Object.keys(oiFaces[ifname])[0].internal == false) jListInterfaces.push({ name: ifname, address:Object.keys(oiFaces[ifname])[0].address});
if (Object.keys(oiFaces[ifname])[0].internal == false) jListInterfaces.push({ name: ifname, address: Object.keys(oiFaces[ifname])[0].address });
} else {

@@ -106,13 +107,57 @@ var sAddresses = "";

});
if (sAddresses!=="") jListInterfaces.push({ name: ifname, address:sAddresses});
if (sAddresses !== "") jListInterfaces.push({ name: ifname, address: sAddresses });
}
})
} catch (error) {}
} catch (error) { }
res.json(jListInterfaces)
});
// 14/02/2020 Endpoint for retrieving all nodes in all flows
RED.httpAdmin.get("/nodeList", RED.auth.needsPermission('knxUltimate-config.read'), function (req, res) {
var sNodes = "\"Group Address\"\t\"Datapoint\"\t\"Node ID\"\t\"Device Name\"\n"; // Contains the text with nodes
var sGA = "";
var sDPT = "";
var sName = "";
var sNodeID = "";
try {
node.nodeClients
//.map( a => a.topic.indexOf("/") !== -1 ? a.topic.split('/').map( n => +n+100000 ).join('/'):0 ).sort().map( a => a.topic.indexOf("/") !== -1 ? a.topic.split('/').map( n => +n-100000 ).join('/'):0 )
.sort((a, b) => {
if (a.topic.indexOf("/") === -1) return -1;
if (b.topic.indexOf("/") === -1) return -1;
var date1 = a.topic.split("/");
var date2 = b.topic.split("/");
date1 = date1[0].padStart(2, "0") + date1[1].padStart(2, "0") + date1[2].padStart(2, "0");
date2 = date2[0].padStart(2, "0") + date2[1].padStart(2, "0") + date2[2].padStart(2, "0");
return date1.localeCompare(date2);
})
.forEach(input => {
sNodeID = "\"" + input.id + "\"";
sName = "\"" + input.name + "\"";
if (input.listenallga == true) {
// Is a ListenallGA
sGA = "\"Universal Node\"";
sDPT = "\"Any\"";
} else {
sGA = "\"" + input.topic + "\"";
sDPT = "\"" + input.dpt + "\"";
if (input.hasOwnProperty("isWatchDog")) {
// Is a watchdog node
} else {
// Is a device node
};
};
sNodes += sGA + "\t" + sDPT + "\t" + sNodeID + "\t" + sName + "\n";
});
res.json(sNodes)
} catch (error) {
}
});
node.setAllClientsStatus = (_status, _color, _text) => {
function nextStatus(oClient) {
oClient.setNodeStatus({ fill: _color, shape: "dot", text: _status + " " + _text ,payload: "", GA: oClient.topic, dpt:"", devicename:""})
oClient.setNodeStatus({ fill: _color, shape: "dot", text: _status + " " + _text, payload: "", GA: oClient.topic, dpt: "", devicename: "" })
}

@@ -148,5 +193,5 @@ node.nodeClients.map(nextStatus);

// Check if the node has a valid topic and dpt
if (_Node.listenallga==false) {
if (_Node.listenallga == false) {
if (typeof _Node.topic == "undefined" || typeof _Node.dpt == "undefined") {
_Node.setNodeStatus({ fill: "red", shape: "dot", text: "Empty Group Addr. or datapoint.",payload: "", GA: "", dpt:"", devicename:"" })
_Node.setNodeStatus({ fill: "red", shape: "dot", text: "Empty Group Addr. or datapoint.", payload: "", GA: "", dpt: "", devicename: "" })
return;

@@ -157,3 +202,3 @@ } else {

if (_Node.topic.split("\/").length < 3) {
_Node.setNodeStatus({ fill: "red", shape: "dot", text: "Wrong group address (topic: " + _Node.topic + ") format.",payload: "", GA: "", dpt:"", devicename:"" })
_Node.setNodeStatus({ fill: "red", shape: "dot", text: "Wrong group address (topic: " + _Node.topic + ") format.", payload: "", GA: "", dpt: "", devicename: "" })
return;

@@ -182,6 +227,6 @@ }

node.nodeClients = node.nodeClients.filter(x => x.id !== _Node.id)
} catch (error) {}
} catch (error) { }
//RED.log.info("AFTER Node " + _Node.id + " has been unsubscribed from receiving KNX messages. " + node.nodeClients.length);
// If no clien nodes, disconnect from bus.
// If no clien nodes, disconnect from bus.
if (node.nodeClients.length === 0) {

@@ -202,3 +247,3 @@ node.linkStatus = "disconnected";

.forEach(oClient => {
if (oClient.listenallga==true) {
if (oClient.listenallga == true) {
delay = delay + 200

@@ -328,3 +373,3 @@ for (let index = 0; index < node.csv.length; index++) {

// 25/10/2019 from v. 1.1.11, try to decode and output a datapoint.
let msg = buildInputMessage(src, dest, evt, rawValue, tryToFigureOutDataPointFromRawValue(rawValue, dest), "", dest);
let msg = buildInputMessage(src, dest, evt, rawValue, tryToFigureOutDataPointFromRawValue(rawValue, dest), "", dest);
input.setNodeStatus({ fill: "green", shape: "dot", text: "Try to decode", payload: msg.payload, GA: msg.knx.destination, dpt: "", devicename: "" });

@@ -335,3 +380,3 @@ input.send(msg)

} else {
let msg = buildInputMessage(src, dest, evt, rawValue, oGA.dpt, oGA.devicename, dest);
let msg = buildInputMessage(src, dest, evt, rawValue, oGA.dpt, oGA.devicename, dest);
input.setNodeStatus({ fill: "green", shape: "dot", text: "", payload: msg.payload, GA: msg.knx.destination, dpt: msg.knx.dpt, devicename: msg.devicename });

@@ -425,3 +470,3 @@ input.send(msg)

// 25/10/2019 from v. 1.1.11, try to decode and output a datapoint.
let msg = buildInputMessage(src, dest, evt, null, tryToFigureOutDataPointFromRawValue(rawValue, dest), "",dest)
let msg = buildInputMessage(src, dest, evt, null, tryToFigureOutDataPointFromRawValue(rawValue, dest), "", dest)
input.setNodeStatus({ fill: "green", shape: "dot", text: "Try to decode", payload: msg.payload, GA: msg.knx.destination, dpt: "", devicename: "" });

@@ -473,3 +518,3 @@ input.send(msg)

// 02/01/2020 All sent messages are queued, to allow at least 50 milliseconds between each telegram sent to the bus
// 02/01/2020 All sent messages are queued, to allow at least 50 milliseconds between each telegram sent to the bus
node.writeQueueAdd = _oKNXMessage => {

@@ -482,3 +527,3 @@ // _oKNXMessage is { grpaddr, payload,dpt,outputtype (write or response)}

if (node.knxConnection) {
if (node.telegramsQueue.length==0) {
if (node.telegramsQueue.length == 0) {
return;

@@ -490,6 +535,5 @@ }

node.telegramsQueue.pop();// Remove the last message from the queue.
if (oKNXMessage.outputtype==="response") {
if (oKNXMessage.outputtype === "response") {
node.knxConnection.respond(oKNXMessage.grpaddr, oKNXMessage.payload, oKNXMessage.dpt);
} else
{
} else {
node.knxConnection.write(oKNXMessage.grpaddr, oKNXMessage.payload, oKNXMessage.dpt);

@@ -529,4 +573,3 @@ }

var dpt = dptlib.resolve(element.value);
if (typeof dpt !== "undefined")
{
if (typeof dpt !== "undefined") {
var jsValue = dptlib.fromBuffer(_rawValue, dpt)

@@ -546,3 +589,3 @@ if (typeof jsValue !== "undefined") {

// 14/08/2019 If the node has payload same as the received telegram, return false
// 14/08/2019 If the node has payload same as the received telegram, return false
checkRBEInputFromKNXBusAllowSend = (_node, _KNXTelegramPayload) => {

@@ -553,16 +596,16 @@ if (_node.inputRBE !== true) return true;

var newVal = _KNXTelegramPayload.toString().toLowerCase();
if (curVal==="false") {
if (curVal === "false") {
curVal = "0";
}
if (curVal==="true") {
if (curVal === "true") {
curVal = "1";
}
if (newVal==="false") {
if (newVal === "false") {
newVal = "0";
}
if (newVal==="true") {
if (newVal === "true") {
newVal = "1";
}
if (curVal === newVal) {
return false;
return false;
}

@@ -582,5 +625,15 @@ return true;

var sDptdesc = "unknown";
var sPayloadsubtypevalue = "unknown";
if (dpt.subtype !== undefined) {
sPayloadmeasureunit = dpt.subtype.unit !== undefined ? dpt.subtype.unit : "unknown";
sDptdesc = dpt.subtype.desc !== undefined ? dpt.subtype.desc.charAt(0).toUpperCase() + dpt.subtype.desc.slice(1) : "unknown";
if (dpt.subtype.enc !== undefined) {
try {
if (!Boolean(jsValue)) sPayloadsubtypevalue = dpt.subtype.enc[0];
if (Boolean(jsValue)) sPayloadsubtypevalue = dpt.subtype.enc[1];
} catch (error) {
}
}
};

@@ -593,2 +646,3 @@

, payloadmeasureunit: sPayloadmeasureunit
, payloadsubtypevalue: sPayloadsubtypevalue
, devicename: (typeof _devicename !== 'undefined') ? _devicename : ""

@@ -637,3 +691,3 @@ , knx:

var sSecondGroupName = "";
var sFather="";
var sFather = "";
for (let index = 0; index < fileGA.length; index++) {

@@ -651,7 +705,7 @@ var element = fileGA[index];

}
if ((element.split("\t")[1].match(/-/g)||[]).length==1) {
if ((element.split("\t")[1].match(/-/g) || []).length == 1) {
// Found second group family name (Example First Floor light)
sSecondGroupName = element.split("\t")[0] || "";
}
if(sFirstGroupName!=="" && sSecondGroupName !==""){sFather="(" + sFirstGroupName + "->" +sSecondGroupName + ") " }
if (sFirstGroupName !== "" && sSecondGroupName !== "") { sFather = "(" + sFirstGroupName + "->" + sSecondGroupName + ") " }

@@ -670,3 +724,3 @@ if (element.split("\t")[1].search("-") == -1 && element.split("\t")[1].search("/") !== -1) {

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] );
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

@@ -682,3 +736,3 @@ }

}
ajsonOutput.push({ga:element.split("\t")[1], dpt:DPTa + "." + DPTb, devicename: sFather + element.split("\t")[0]});
ajsonOutput.push({ ga: element.split("\t")[1], dpt: DPTa + "." + DPTb, devicename: sFather + element.split("\t")[0] });
}

@@ -703,8 +757,6 @@ }

sChar = _csv.substr(index, 1);
if (sChar == "\"")
{
if (sChar == "\"") {
if (!bStart) {
bStart = true;
}else
{
} else {
bStart = false;

@@ -714,15 +766,11 @@ }

} else
{
} else {
if (bStart) {
// i'm in the phrase, delimited by "". No CRLF should be there
if (sChar !== "\n" && sChar !== "\r")
{
if (sChar !== "\n" && sChar !== "\r") {
sOut += sChar;
} else
{
} else {
sOut += " "; // Where it was a CRLF, i put a space
}
} else
{
} else {
sOut += sChar;

@@ -729,0 +777,0 @@ }

@@ -22,3 +22,3 @@ module.exports = function (RED) {

node.messageQueue = []; // 01/01/2020 All messages from the flow to the node, will be queued and will be sent separated by 60 milliseconds each. Use uf the underlying knx.js "minimumDelay" is not possible because the telegram order isn't mantained.
// Used to call the status update from the config node.

@@ -29,18 +29,18 @@ node.setNodeStatus = ({ fill, shape, text, payload, GA, dpt, devicename }) => {

// 30/08/2019 Display only the things selected in the config
_GA= (typeof _GA == "undefined" || GA == "") ? "" : "(" + GA + ") ";
_GA = (typeof _GA == "undefined" || GA == "") ? "" : "(" + GA + ") ";
_devicename = devicename || "";
_dpt= (typeof dpt == "undefined" || dpt == "") ? "" : " DPT" + dpt;
node.status({ fill: fill, shape: shape, text: _GA + payload + ((node.listenallga && node.server.statusDisplayDeviceNameWhenALL) == true ? " " + _devicename : "") +(node.server.statusDisplayDataPoint == true ? _dpt : "") + (node.server.statusDisplayLastUpdate == true ? " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" : "") + " " + text });
_dpt = (typeof dpt == "undefined" || dpt == "") ? "" : " DPT" + dpt;
node.status({ fill: fill, shape: shape, text: _GA + payload + ((node.listenallga && node.server.statusDisplayDeviceNameWhenALL) == true ? " " + _devicename : "") + (node.server.statusDisplayDataPoint == true ? _dpt : "") + (node.server.statusDisplayLastUpdate == true ? " (" + dDate.getDate() + ", " + dDate.toLocaleTimeString() + ")" : "") + " " + text });
}
// Check if the node has a valid topic and dpt
if(node.listenallga==false){
if (node.listenallga == false) {
if (typeof node.topic == "undefined" || typeof node.dpt == "undefined") {
node.setNodeStatus({ fill: "red", shape: "dot", text: "Empty Group Addr. or datapoint.",payload: "", GA: "", dpt:"", devicename:"" })
node.setNodeStatus({ fill: "red", shape: "dot", text: "Empty Group Addr. or datapoint.", payload: "", GA: "", dpt: "", devicename: "" })
return;
} else {
// topic must be in formar x/x/x
if (node.topic.split("\/").length < 3) {
node.setNodeStatus({ fill: "red", shape: "dot", text: "Wrong group address format.",payload: "", GA: node.topic, dpt:"", devicename:""})
node.setNodeStatus({ fill: "red", shape: "dot", text: "Wrong group address format.", payload: "", GA: node.topic, dpt: "", devicename: "" })
return;

@@ -69,7 +69,7 @@ }

RED.log.error("knxUltimate: Node " + node.id + " has received an INVALID payload. Please check the flow.");
return;
return;
}
}
if (!node.server) return; // 29/08/2019 Server not instantiate

@@ -85,5 +85,5 @@ if (node.server.linkStatus !== "connected") {

var grpaddr = ""
if (node.listenallga==false) {
if (node.listenallga == false) {
grpaddr = msg && msg.destination ? msg.destination : node.topic
node.setNodeStatus({ fill: "grey", shape: "dot", text: "Read",payload: "", GA: grpaddr, dpt:node.dpt, devicename:"" });
node.setNodeStatus({ fill: "grey", shape: "dot", text: "Read", payload: "", GA: grpaddr, dpt: node.dpt, devicename: "" });
node.server.readValue(grpaddr)

@@ -96,6 +96,5 @@ } else { // Listen all GAs

} else {
// Issue read to all group addresses
// Issue read to all group addresses
// 25/10/2019 the user is able not import the csv, so i need to check for it. This option should be unckecked by the knxUltimate html config, but..
if (typeof node.server.csv !== "undefined")
{
if (typeof node.server.csv !== "undefined") {
let delay = 0;

@@ -106,8 +105,8 @@ for (let index = 0; index < node.server.csv.length; index++) {

node.server.readValue(element.ga);
node.setNodeStatus({ fill: "yellow", shape: "dot", text: "Read",payload:"", GA: element.ga, dpt:element.dpt, devicename:element.devicename });
node.setNodeStatus({ fill: "yellow", shape: "dot", text: "Read", payload: "", GA: element.ga, dpt: element.dpt, devicename: element.devicename });
}, delay);
delay = delay + 200;
}
}
}
// setTimeout(() => {

@@ -118,29 +117,29 @@ // node.setNodeStatus({ fill: "yellow", shape: "dot", text: "Done requests." });

}
}
}
} else {
if (node.listenallga == false) {
// Applying RBE filter
if (node.outputRBE==true) {
var curVal=node.currentPayload.toString().toLowerCase();
var newVal=msg.payload.toString().toLowerCase();
if (curVal==="false") {
if (node.outputRBE == true) {
var curVal = node.currentPayload.toString().toLowerCase();
var newVal = msg.payload.toString().toLowerCase();
if (curVal === "false") {
curVal = "0";
}
if (curVal==="true") {
if (curVal === "true") {
curVal = "1";
}
if (newVal==="false") {
if (newVal === "false") {
newVal = "0";
}
if (newVal==="true") {
if (newVal === "true") {
newVal = "1";
}
if (curVal === newVal) {
node.setNodeStatus({ fill: "grey", shape: "ring", text: "rbe block ("+msg.payload+") to KNX", payload:"", GA: "", dpt:"", devicename:""})
node.setNodeStatus({ fill: "grey", shape: "ring", text: "rbe block (" + msg.payload + ") to KNX", payload: "", GA: "", dpt: "", devicename: "" })
return;
}
}
}
}
// 07/02/2020 Revamped flood protection (avoid accepting too many messages as input)
if (node.icountMessageInWindow == -999)return; // Locked out
if (node.icountMessageInWindow == -999) return; // Locked out
if (node.icountMessageInWindow == 0) {

@@ -150,12 +149,12 @@ setTimeout(() => {

// Looping detected
node.setNodeStatus({ fill: "red", shape: "ring", text: "DISABLED! Flood protection! Too many msg at the same time.", payload:"", GA: "", dpt:"", devicename:"" })
node.setNodeStatus({ fill: "red", shape: "ring", text: "DISABLED! Flood protection! Too many msg at the same time.", payload: "", GA: "", dpt: "", devicename: "" })
RED.log.error("knxUltimate: Node " + node.id + " has been disabled due to Flood Protection. Too many messages in a timeframe. Check your flow's design or use RBE option.");
node.icountMessageInWindow = -999; //Lock out node
return;
}else{node.icountMessageInWindow = -1;}
} else { node.icountMessageInWindow = -1; }
}, 1000);
}
}
node.icountMessageInWindow += 1;
// OUTPUT: Send message to the bus (write/response)

@@ -172,6 +171,6 @@ if (node.server) {

: node.outputtype
var grpaddr = "";
var dpt = "";
if (node.listenallga==true) {
if (node.listenallga == true) {
// The node is set to Universal mode (listen to all Group Addresses). The msg.knx.destination is needed.

@@ -181,3 +180,3 @@ if (msg.destination) {

} else {
node.setNodeStatus({ fill: "red", shape: "dot", text: "msg.destination not set!" ,payload:"", GA: "", dpt:"", devicename:""})
node.setNodeStatus({ fill: "red", shape: "dot", text: "msg.destination not set!", payload: "", GA: "", dpt: "", devicename: "" })
return;

@@ -187,7 +186,7 @@ }

grpaddr = msg.destination
? msg.destination
: node.topic
? msg.destination
: node.topic
}
if (node.listenallga==true) {
if (node.listenallga == true) {
// The node is set to Universal mode (listen to all Group Addresses). Gets the datapoint from the CSV or use the msg.dpt.

@@ -201,5 +200,4 @@ if (msg.dpt) {

dpt = oGA.dpt
} else
{
node.setNodeStatus({ fill: "red", shape: "dot", text: "msg.dpt not set!" ,payload:"", GA: "", dpt:"", devicename:""})
} else {
node.setNodeStatus({ fill: "red", shape: "dot", text: "msg.dpt not set!", payload: "", GA: "", dpt: "", devicename: "" })
return;

@@ -210,8 +208,8 @@ }

dpt = msg.dpt
? msg.dpt
: node.dpt
? msg.dpt
: node.dpt
}
// Protection over circular references (for example, if you link two Ultimate Nodes toghether with the same group address), to prevent infinite loops
// if (msg.hasOwnProperty('topic')) {
if (msg.hasOwnProperty('knx')) {
if (msg.hasOwnProperty('knx')) {
//if (msg.topic == grpaddr && msg.knx !== undefined) { // 07/02/2020 changed, to allow topic customization asked by users.

@@ -221,3 +219,3 @@ if (msg.knx.destination == grpaddr) { // 07/02/2020 changed, to allow topic customization asket by users.

setTimeout(() => {
node.setNodeStatus({ fill: "red", shape: "ring", text: "DISABLED due to a circulare reference (" + grpaddr + ").",payload:"", GA: "", dpt:"", devicename:"" })
node.setNodeStatus({ fill: "red", shape: "ring", text: "DISABLED due to a circulare reference (" + grpaddr + ").", payload: "", GA: "", dpt: "", devicename: "" })
}, 1000);

@@ -230,11 +228,11 @@ return;

node.currentPayload = msg.payload;// 31/12/2019 Set the current value (because, if the node is a virtual device, then it'll never fire "GroupValue_Write" in the server node, causing the currentPayload to never update)
node.server.writeQueueAdd({ grpaddr: grpaddr, payload:msg.payload,dpt:dpt,outputtype:outputtype})
node.setNodeStatus({ fill: "blue", shape: "dot", text: "Responding",payload: msg.payload, GA: grpaddr, dpt:dpt, devicename:"" });
} catch (error) {}
node.server.writeQueueAdd({ grpaddr: grpaddr, payload: msg.payload, dpt: dpt, outputtype: outputtype })
node.setNodeStatus({ fill: "blue", shape: "dot", text: "Responding", payload: msg.payload, GA: grpaddr, dpt: dpt, devicename: "" });
} catch (error) { }
} else {
try {
node.currentPayload = msg.payload;// 31/12/2019 Set the current value (because, if the node is a virtual device, then it'll never fire "GroupValue_Write" in the server node, causing the currentPayload to never update)
node.server.writeQueueAdd({ grpaddr: grpaddr, payload:msg.payload,dpt:dpt,outputtype:outputtype})
node.setNodeStatus({ fill: "green", shape: "dot", text: "Writing",payload: msg.payload, GA: grpaddr, dpt:dpt, devicename:"" });
} catch (error) {}
node.server.writeQueueAdd({ grpaddr: grpaddr, payload: msg.payload, dpt: dpt, outputtype: outputtype })
node.setNodeStatus({ fill: "green", shape: "dot", text: "Writing", payload: msg.payload, GA: grpaddr, dpt: dpt, devicename: "" });
} catch (error) { }
}

@@ -244,6 +242,6 @@ }

}
})
node.on('close', function () {

@@ -262,8 +260,8 @@ if (node.server) {

}
}
}
RED.nodes.registerType("knxUltimate", knxUltimate)
}
{
"name": "node-red-contrib-knx-ultimate",
"version": "1.1.28",
"version": "1.1.29",
"description": "Single Node KNX IN/OUT with optional ETS group address importer. Easy to use and highly configurable.",

@@ -5,0 +5,0 @@ "dependencies": {

# node-red-contrib-knx-ultimate
![Sample Node](img/logo.png)
![Logo](img/logo.png)
[![NPM version][npm-version-image]][npm-url]

@@ -12,11 +11,11 @@ [![NPM downloads per month][npm-downloads-month-image]][npm-url]

![Sample Node](img/readmemain.png)
![Sample Node](img/readmemain.png)
## DESCRIPTION
**Knx-ultimate device node** is a powerfull device node, all-in-one. It acts as input device as well as output device at the same time. I'ts very SIMPLE TO USE thus very customizable.<br/>
If you're here, you probably already have tried other knx nodes from npm. I hope you enjoy this one, because i've put big effort to do what i really needed, a copy/paste friendly node, with many functions and the possibility to use the ETS csv exported Group Addresses.<br />
**WatchDog node** is a professional oriented knx node for installers/companies. It allows notification (Email, Twitter, Telegram, Alexa, Siri, Sonos -with sonospollytts node- and so on) of KNX Bus connection errors, automatic or manual switchover to a backup KNX/IP router if the primary fails and allows you to programmatically change the config-node directly from a msg flow.
[![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square)](https://www.paypal.me/techtoday) and <a href="http://eepurl.com/gJm095" target="_blank">subscribe to my channel.</a> Only news about my nodes, no spam, no ads.<br/>Please never put pineapple on an italian pizza!
* **Knx-ultimate device node** allow you to control your *KNX installation* via Node-Red. You can control all your KNX devices as well as create a *Virtual Device* in Node-Red, to link external *non KNX* devices, and make it compatible with your KNX installation. I'ts very SIMPLE TO USE thus very customizable.
* **WatchDog node** is a professional oriented knx node for installers/companies. It allows notification (Email, Twitter, Telegram, Alexa, Siri, Sonos -with sonospollytts node- and so on) of KNX Bus connection errors, automatic or manual switchover to a backup KNX/IP router if the primary fails and allows you to programmatically change the config-node directly from a msg flow.
[![Donate via PayPal](https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square)](https://www.paypal.me/techtoday) and <a href="http://eepurl.com/gJm095" target="_blank">subscribe to my channel.</a> Only news about my nodes, no spam, no ads.
## CHANGELOG

@@ -39,7 +38,7 @@ * See <a href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/blob/master/CHANGELOG.md">here the changelog</a>

## HIGHLIGHTS
## Highlights
### Click a row to see the description
If you're here, you probably already have tried other knx nodes from npm. I hope you enjoy this one, because i've put big effort to do what i really needed, a copy/paste friendly node, with many functions and the possibility to use the ETS csv exported Group Addresses.<br />
<details><summary>STAND ALONE OR WITH ETS GROUP ADDRESS LIST</summary>
<details><summary>Stand alone or with ETS exported file</summary>

@@ -49,3 +48,3 @@ You can set you own group address, datapoint and device name, or you can import the ETS Group Address list and have datapoint and device name auto populated while typing in the group address.

</details>
<details><summary>AUTOMATIC DISPLAY OF ALL YOUR KNX DEVICES</summary>
<details><summary>Filling helpers</summary>

@@ -55,3 +54,3 @@ If you import your ETS CSV file, just begin typing the group address or the device name in the Group Address textbox and a list of possible matches will appear. Just select an item in the list it and have datapoint and device name auto populated. You can then accept the auto populated fields or change it.

</details>
<details><summary>AUTOMATIC ENCODING/DECONDING OF TELEGRAM</summary>
<details><summary>Automatic encoding/deconding of KNX datagrams</summary>

@@ -61,3 +60,3 @@ Just pass a normal payload to the node (true, false, a string or any nymber) and just receive a normal payload (true, false, a string or any nymber) to use in your flow.

</details>
<details><summary>DOUBLE PERSONALITY</summary>
<details><summary>Double Personality</summary>

@@ -67,3 +66,3 @@ The node can act as a single device (for example having Group Address 0/0/1), or can be used as universal node, catching all messages coming from KNX Bus (in this case the node will output a comprehensive msg to the flow, containing group address, device name, automatic decoded payload and other useful infos). The node can act as universal KNX sender as well (you can pass a message to the node, containing the destination group address, the datapont type and the payload).

</details>
<details><summary>EMULATE REAL KNX DEVICE</summary>
<details><summary>Emulate real KNX device</summary>

@@ -73,3 +72,3 @@ You can use the node to emulate a phisically non existent KNX device. The node will behave exactly as a normal KNX Device and will also respond to read requests coming from the KNX bus, by sending the current payload value to the KNX bus.

</details>
<details><summary>ADJUSTABLE STATUS DISPLAY</summary>
<details><summary>Customizable status display</summary>

@@ -79,3 +78,3 @@ You can select what to see in the status (the row below the node). For example, you can select to see the current payload value and the last time changed, or the device name as well.

</details>
<details><summary>NODE SELF PROTECTION</summary>
<details><summary>Self protection</summary>

@@ -85,24 +84,23 @@ The Node protects you, from youself. [Node Protections](https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/-Protections)

</details>
<details><summary>BUILT INPUT AND OUTPUT RBE FILTER</summary>
<details><summary>Built in RBE input/output filter</summary>
You can select to activate or deactivate it. If active, the node reacts only if payload from KNX Bus is changed.
You can select to activate or deactivate it. If active, the node reacts only if payload from KNX Bus or from input msg is changed.
</details>
<details><summary>BUILT IN RBE INPUT FILTER</summary>
<details><summary>Automatic KNX interface type</summary>
IN: You can select to activate or deactivate it. If active, the node reacts only if payload from KNX Bus is changed.
OUT: You can select to activate or deactivate it. If active, the node will send the payload to the KNX Bus, only if changed.
Full support for IP Interfaces as well for IP Routers. It's recommended the use of IP Routers because of simple setup and stability in a large environment.
</details>
<details><summary>WORKS WITH IP INTERFACES AS WELL AS IP ROUTERS</summary>
<details><summary>Old interfaces friendly</summary>
Full support for IP Interfaces as well for IP Routers. It's recommended the use of IP Routers because of simple setup and stability in a large environment.
The "Suppress ACK" option, helps compatibility with old IP Interfaces, like the Siemens SWG1 148-1AB22 IP Interface firmware etc...
</details>
<details><summary>SUPPRESS ACK REQUEST FOR OLD IP INTERFACES</summary>
<details><summary>Granular options</summary>
This option help compatibility with very old IP Interfaces, like the Siemens SWG1 148-1AB22 IP Interface firmware.
The node is very simple to use "out of the box", but you can plasmate it to achieve any goal you want.
</details>
<details><summary>WATCHDOG NODE FOR KNX CONNECTION BACKUP AND NOTIFICATION</summary>
<details><summary>WATCHDOG Node for KNX backup connection and notification</summary>

@@ -112,3 +110,3 @@ You can check the healty of your KNX Bus connection and switch over to anoter KNX/IP Router if the primary fails.

</details>
<details><summary>PROGRAMMATICALLY CHANGE THE KNX/IP INTERFACE/ROUTER CONFIG</summary>
<details><summary>WATCHDOG Node to change the KNX gateway configuration on the fly</summary>

@@ -118,7 +116,2 @@ Programmatically change the IP, Port etc... of the KNX/IP Interface or router, via msg.

</details>
<details><summary>VERY GRANULAR OPTIONS</summary>
The node is very simple to use "out of the box", but you can plasmate it to achieve any goal you want.
</details>
<details><summary>ACTIVE DEVELOPED</summary>

@@ -130,13 +123,12 @@

## WORKING WITH THE ETS CSV FILE
### WORKING WITH THE ETS CSV FILE
Instead of create a knx-ultimate node for each Group Address to control, you can import your ETS csv group addresses file.
Instead of create a knx-ultimate node for each Group Address to control, you can import your ETS csv group addresses file.
Thanks to that, the knx-ultimate node where you selected **Universal mode (listen to all Group Addresses)**, becomes an universal input/output node, aware of all Datapoints, Group Addresses and Device's name (ex: Living Room Lamp). Just send the payload to the knx-ultimate node, and it'll encode it with the right datapoint and send it to the bus. Likewise, when the knx-ultimate node receives a telegram from the bus, it outputs a right decoded payload using the datapoint specified in the ETS file.
> You can work with a mix of knx-ultimate nodes, some with **Universal mode (listen to all Group Addresses)** checked and some not. You are absolutely free! See this youtube video,
<a href="https://youtu.be/I32_qG7yhFc" target="_blank"><img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/yt.png' width='100%'></a>
<a href="https://youtu.be/I32_qG7yhFc" target="_blank"><img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/yt.png' width='60%'></a>
**Sample ETS csv file to paste into your config for testing pourposes**
<details><summary>Sample ETS csv file to paste into the ETS field of your config node.</summary>
> Copy/Paste this into your configuration node.

@@ -173,2 +165,3 @@

</details>

@@ -179,62 +172,12 @@ <br/>

# <a href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki">Click here for comprehensive samples</a>
# BRIEF TOUR (Samples are in the <a href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki">Wiki</a>)
**Turn on/off a Lamp**
```javascript
return {payload:true}
```
```javascript
return {payload:false}
```
### TURN ON AND OFF A LAMP
<img src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/simple.png" width="50%">
In this example, this is the node config. AS you can see, the Group Address is 0/0/1 and Datapoint 1.001 (1 bit switch)
The message passed to the node is simple <code>{payload=true}</code> and <code>{payload=false}</code>
<img src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/simple2.png" width="60%">
<code>
[{"id":"7840249f.8ce8a4","type":"knxUltimate","z":"71ead01a.630ba","server":"d08a9721.b34f1","topic":"0/0/1","dpt":"1.001","initialread":false,"notifyreadrequest":false,"notifyresponse":false,"notifywrite":true,"listenallga":false,"name":"Kitchen Lamp","x":340,"y":100,"wires":[[]]},{"id":"d08a9721.b34f1","type":"knxUltimate-config","z":"","host":"224.0.23.12","port":"3671","csv":"\"Group name\"\t\"Address\"\t\"Central\"\t\"Unfiltered\"\t\"Description\"\t\"DatapointType\"\t\"Security\"\n\"Attuatori luci\"\t\"0/-/-\"\t\"\"\t\"\"\t\"Attuatori luci\"\t\"\"\t\"Auto\"\n\"Luci primo piano\"\t\"0/0/-\"\t\"\"\t\"\"\t\"Luci primo piano\"\t\"\"\t\"Auto\"\n\"Camera da letto luce\"\t\"0/0/1\"\t\"\"\t\"\"\t\"Camera da letto luce\"\t\"DPST-1-8\"\t\"Auto\"\n\"Loggia camera da letto\"\t\"0/0/2\"\t\"\"\t\"\"\t\"Loggia camera da letto\"\t\"DPST-1-1\"\t\"Auto\"\n\"Camera armadi luce\"\t\"0/0/3\"\t\"\"\t\"\"\t\"Camera armadi luce\"\t\"DPST-1-1\"\t\"Auto\"\n\"Bagno grande luce\"\t\"0/0/4\"\t\"\"\t\"\"\t\"Bagno grande luce\"\t\"DPST-1-1\"\t\"Auto\"\n\"Loggia bagno grande\"\t\"0/0/5\"\t\"\"\t\"\"\t\"Loggia bagno grande\"\t\"DPST-1-1\"\t\"Auto\"\n\"Bagno grande specchio (switch)\"\t\"0/0/6\"\t\"\"\t\"\"\t\"Bagno grande specchio switch\"\t\"DPST-1-1\"\t\"Auto\""}]
</code>
### TURN ON SAME LAMP, BUT USING ETS CSV FILE (IN THE CONFIG NODE)
<img src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/overrides.png" width="50%">
In this example, we selectet "Listen to all Group Address" in the configuration and we imported the ETS csv File.<br/>
<img src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/overrides3.png" width="40%">
The configuration Node<br/>
<img src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/overrides4.png" width="40%">
<code>
node.send ({payload: true, destination: "0/0/1", dpt: "1.001"});
</code>
dpt can be omitted (it's auto detected if you've set the ETS csv file), so simply
<code>
node.send ({payload: true, destination: "0/0/1"});
</code>
<code>
[{"id":"ae2d436e.44559","type":"function","z":"71ead01a.630ba","name":"Some overrides","func":"return ({\n payload: msg.payload,\n destination: \"0/0/1\"\n });","outputs":1,"noerr":0,"x":260,"y":280,"wires":[["9ab841cd.048848"]]},{"id":"7134491f.e66e","type":"inject","z":"71ead01a.630ba","name":"Switch on","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":260,"wires":[["ae2d436e.44559"]]},{"id":"c49a1a48.5f7338","type":"inject","z":"71ead01a.630ba","name":"Switch off","topic":"","payload":"false","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":300,"wires":[["ae2d436e.44559"]]},{"id":"fab1778f.1b44e8","type":"debug","z":"71ead01a.630ba","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":530,"y":280,"wires":[]},{"id":"9ab841cd.048848","type":"knxUltimate","z":"71ead01a.630ba","server":"d08a9721.b34f1","topic":"","dpt":"1.001","initialread":false,"notifyreadrequest":false,"notifyresponse":false,"notifywrite":true,"listenallga":true,"name":"All","x":410,"y":280,"wires":[["fab1778f.1b44e8"]]},{"id":"d08a9721.b34f1","type":"knxUltimate-config","z":"","host":"224.0.23.12","port":"3671","csv":"\"Group name\"\t\"Address\"\t\"Central\"\t\"Unfiltered\"\t\"Description\"\t\"DatapointType\"\t\"Security\"\n\"Attuatori luci\"\t\"0/-/-\"\t\"\"\t\"\"\t\"Attuatori luci\"\t\"\"\t\"Auto\"\n\"Luci primo piano\"\t\"0/0/-\"\t\"\"\t\"\"\t\"Luci primo piano\"\t\"\"\t\"Auto\"\n\"Camera da letto luce\"\t\"0/0/1\"\t\"\"\t\"\"\t\"Camera da letto luce\"\t\"DPST-1-8\"\t\"Auto\"\n\"Loggia camera da letto\"\t\"0/0/2\"\t\"\"\t\"\"\t\"Loggia camera da letto\"\t\"DPST-1-1\"\t\"Auto\"\n\"Camera armadi luce\"\t\"0/0/3\"\t\"\"\t\"\"\t\"Camera armadi luce\"\t\"DPST-1-1\"\t\"Auto\"\n\"Bagno grande luce\"\t\"0/0/4\"\t\"\"\t\"\"\t\"Bagno grande luce\"\t\"DPST-1-1\"\t\"Auto\"\n\"Loggia bagno grande\"\t\"0/0/5\"\t\"\"\t\"\"\t\"Loggia bagno grande\"\t\"DPST-1-1\"\t\"Auto\"\n\"Bagno grande specchio (switch)\"\t\"0/0/6\"\t\"\"\t\"\"\t\"Bagno grande specchio switch\"\t\"DPST-1-1\"\t\"Auto\""}]
</code>
### ISSUE A READ REQUEST TO A SPECIFIED GROUP ADDRESS, USING ETS CSV FILE (IN THE CONFIG NODE)
<img src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/read.png" width="50%">
In this example, we selectet "Listen to all Group Address" in the configuration and we imported the ETS csv File.<br/>
<img src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/overrides3.png" width="40%">
The configuration Node<br/>
<img src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/overrides4.png" width="40%">
<code>
return ({readstatus: true});
</code>
<code>
[{"id":"b1d17725.e39228","type":"function","z":"71ead01a.630ba","name":"Read Request","func":"return ({\n readstatus: true,\n knx: {\n destination: \"0/0/1\"}\n });","outputs":1,"noerr":0,"x":260,"y":640,"wires":[["348e7499.c50544"]]},{"id":"94a1fc7b.9a9288","type":"inject","z":"71ead01a.630ba","name":"Trigger","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":640,"wires":[["b1d17725.e39228"]]},{"id":"348e7499.c50544","type":"knxUltimate","z":"71ead01a.630ba","server":"d08a9721.b34f1","topic":"","dpt":"1.001","initialread":false,"notifyreadrequest":false,"notifyresponse":false,"notifywrite":true,"listenallga":true,"name":"All","x":420,"y":640,"wires":[["9d34ac1a.429de"]]},{"id":"9d34ac1a.429de","type":"debug","z":"71ead01a.630ba","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":550,"y":640,"wires":[]},{"id":"d08a9721.b34f1","type":"knxUltimate-config","z":"","host":"224.0.23.12","port":"3671","csv":"\"Group name\"\t\"Address\"\t\"Central\"\t\"Unfiltered\"\t\"Description\"\t\"DatapointType\"\t\"Security\"\n\"Attuatori luci\"\t\"0/-/-\"\t\"\"\t\"\"\t\"Attuatori luci\"\t\"\"\t\"Auto\"\n\"Luci primo piano\"\t\"0/0/-\"\t\"\"\t\"\"\t\"Luci primo piano\"\t\"\"\t\"Auto\"\n\"Camera da letto luce\"\t\"0/0/1\"\t\"\"\t\"\"\t\"Camera da letto luce\"\t\"DPST-1-8\"\t\"Auto\"\n\"Loggia camera da letto\"\t\"0/0/2\"\t\"\"\t\"\"\t\"Loggia camera da letto\"\t\"DPST-1-1\"\t\"Auto\"\n\"Camera armadi luce\"\t\"0/0/3\"\t\"\"\t\"\"\t\"Camera armadi luce\"\t\"DPST-1-1\"\t\"Auto\"\n\"Bagno grande luce\"\t\"0/0/4\"\t\"\"\t\"\"\t\"Bagno grande luce\"\t\"DPST-1-1\"\t\"Auto\"\n\"Loggia bagno grande\"\t\"0/0/5\"\t\"\"\t\"\"\t\"Loggia bagno grande\"\t\"DPST-1-1\"\t\"Auto\"\n\"Bagno grande specchio (switch)\"\t\"0/0/6\"\t\"\"\t\"\"\t\"Bagno grande specchio switch\"\t\"DPST-1-1\"\t\"Auto\""}]
</code>
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg

@@ -241,0 +184,0 @@ [license-url]: https://github.com/Supergiovane/node-red-contrib-knx-ultimate/master/LICENSE

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet