node-red-contrib-knx-ultimate 3.0.5 → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/nodes/knxUltimateAutoResponder.html +5 -2
- package/nodes/knxUltimateAutoResponder.js +28 -50
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
**Version 3.0.6** - August 2024<br/>
|
|
10
|
+
- Warning: Node-Red version **equals or major than 3.1.1** is needed to run this node.<br/>
|
|
11
|
+
- KNX Auto Responder node (BETA): fixed some issues when the ETS file has not been imported. Please be aware that until the node exits beta, there can be breaking changes.<br/>
|
|
12
|
+
|
|
9
13
|
**Version 3.0.5** - August 2024<br/>
|
|
10
14
|
- Warning: Node-Red version **equals or major than 3.1.1** is needed to run this node.<br/>
|
|
11
15
|
- KNX Auto Responder node (BETA): changed to JSON array instead of plain text and updated the help. Please be aware that until the node exits beta, there can be breaking changes.<br/>
|
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ msg.payload = {red:255, green:200, blue:30} // Put some colors in our life
|
|
|
43
43
|
* **VIEWER node** [here](https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/knxUltimateViewer). View all Group Addresses and values of your KNX BUS, in the Node-Red Dashboard.
|
|
44
44
|
* **PHILIPS HUE nodeset** [here](https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/en-hue-configuration). Link HUE devices to KNX in a simple way.
|
|
45
45
|
* **HOME ASSISTANT translator node** translates the HA input msg, to a KNX value. Comes with a built-in translation table, that's user editable.
|
|
46
|
-
|
|
46
|
+
* **AUTO RESPONDER node** responds to read requests coming from the bus. Used mainly for virtual group addresses.
|
|
47
47
|
<br>
|
|
48
48
|
|
|
49
49
|
## CHANGELOG
|
|
@@ -55,8 +55,11 @@
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
<div class="form-row">
|
|
58
|
-
<b>Auto Responder</b
|
|
59
|
-
|
|
58
|
+
<b>Auto Responder</b>  <span style="color:red"    <i class="fa fa-youtube"></i></span> <a
|
|
59
|
+
target="_blank" href=""><u>Youtube sample coming soon...</u></a>
|
|
60
|
+
<br />
|
|
61
|
+
<br />
|
|
62
|
+
|
|
60
63
|
<label for="node-input-server">
|
|
61
64
|
<img
|
|
62
65
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKnRFWHRDcmVhdGlvbiBUaW1lAEZyIDYgQXVnIDIwMTAgMjE6NTI6MTkgKzAxMDD84aS8AAAAB3RJTUUH3gYYCicNV+4WIQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAACUSURBVHjaY2CgFZg5c+Z/ZEyWAZ8+f/6/ZsWs/xoamqMGkGrA6Wla/1+fVARjEBuGsSoGmY4eZSCNL59d/g8DIDbIAHR14OgFGQByKjIGKX5+6/T///8gGMQGiV1+/B0Fg70GIkD+RMYgxf/O5/7//2MSmAZhkBi6OrgB6Bg5DGB4ajr3f2xqsYYLSDE2THJUDg0AAAqyDVd4tp4YAAAAAElFTkSuQmCC"></img>
|
|
@@ -45,7 +45,6 @@ module.exports = function (RED) {
|
|
|
45
45
|
node.inputRBE = 'false' // Apply or not RBE to the input (Messages coming from BUS)
|
|
46
46
|
node.exposedGAs = [];
|
|
47
47
|
node.commandText = []; // Raw list Respond To
|
|
48
|
-
node.decodedRespondToList = [];
|
|
49
48
|
node.sysLogger = require('./utils/sysLogger.js').get({ loglevel: node.server.loglevel || 'error' }); // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
|
|
50
49
|
|
|
51
50
|
// Used to call the status update from the config node.
|
|
@@ -66,7 +65,7 @@ module.exports = function (RED) {
|
|
|
66
65
|
//return;
|
|
67
66
|
} else {
|
|
68
67
|
node.server.csv.forEach(element => {
|
|
69
|
-
node.exposedGAs.push({ address: element.ga, dpt: element.dpt,
|
|
68
|
+
node.exposedGAs.push({ address: element.ga, dpt: element.dpt, default: undefined, payload: undefined })
|
|
70
69
|
})
|
|
71
70
|
node.status({ fill: 'green', shape: 'ring', text: 'ETS file loaded', payload: '', dpt: '', devicename: '' });
|
|
72
71
|
}
|
|
@@ -84,18 +83,30 @@ module.exports = function (RED) {
|
|
|
84
83
|
node.commandText.forEach(element => {
|
|
85
84
|
if (element.ga !== undefined && element.default !== undefined) {
|
|
86
85
|
let defaultVal = element.default;
|
|
86
|
+
let dpt = element.dpt;
|
|
87
87
|
if (element.ga.includes('..')) {
|
|
88
88
|
const start = Number(element.ga.substring(element.ga.lastIndexOf("/") + 1, element.ga.indexOf("..")));
|
|
89
89
|
const end = Number(element.ga.substring(element.ga.indexOf("..") + 2));
|
|
90
90
|
const twoLevel = element.ga.substring(0, element.ga.lastIndexOf("/") + 1);
|
|
91
91
|
for (let index = start; index < end; index++) {
|
|
92
92
|
const decAdd = twoLevel + index;
|
|
93
|
-
|
|
93
|
+
// Add also to the exposedGAs list, if not already present
|
|
94
|
+
let curGa = node.exposedGAs.find(a => a.address === decAdd);
|
|
95
|
+
if (curGa === undefined) {
|
|
96
|
+
node.exposedGAs.push({ address: decAdd, dpt: dpt, default: defaultVal, payload: undefined });
|
|
97
|
+
} else {
|
|
98
|
+
if (dpt !== undefined) curGa.dpt = dpt; // Take the Datapoint from the commandText directive, replacing from ETS CSV file, if exists.
|
|
99
|
+
}
|
|
94
100
|
}
|
|
95
101
|
} else {
|
|
96
|
-
node.
|
|
102
|
+
let curGa = node.exposedGAs.find(a => a.address === element.ga);
|
|
103
|
+
if (curGa === undefined) {
|
|
104
|
+
node.exposedGAs.push({ address: element.ga, dpt: dpt, default: defaultVal, payload: undefined });
|
|
105
|
+
} else {
|
|
106
|
+
if (dpt !== undefined) curGa.dpt = dpt; // Take the Datapoint from the commandText directive, replacing from ETS CSV file, if exists.
|
|
107
|
+
}
|
|
97
108
|
}
|
|
98
|
-
node.status({ fill: 'green', shape: 'ring', text: 'JSON parsed: ' + node.
|
|
109
|
+
node.status({ fill: 'green', shape: 'ring', text: 'JSON parsed: ' + node.commandText.length + " directive(s).", payload: '', dpt: '', devicename: '' });
|
|
99
110
|
} else {
|
|
100
111
|
// Error
|
|
101
112
|
node.status({ fill: 'red', shape: 'dot', text: 'JSON error: ga or default keys not set. Abort.', payload: '', dpt: '', devicename: '' });
|
|
@@ -111,69 +122,36 @@ module.exports = function (RED) {
|
|
|
111
122
|
|
|
112
123
|
// Save the value
|
|
113
124
|
try {
|
|
114
|
-
var oGa = node.exposedGAs.find(ga => ga.address === msg.knx.destination)
|
|
125
|
+
var oGa = node.exposedGAs.find(ga => ga.address === msg.knx.destination);
|
|
115
126
|
} catch (error) {
|
|
116
127
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimateAutoResponder: var oGa = node.exposedGAs.find(ga => ga.address === msg.knx.destination) ${error.stack}`);
|
|
117
128
|
}
|
|
118
|
-
if (oGa
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// Must get the dpt from the decodedRespondToList list, then decode the payload
|
|
127
|
-
try {
|
|
128
|
-
datapoint = node.decodedRespondToList.find(x => x.address === msg.knx.destination).dpt;
|
|
129
|
-
const dpt = dptlib.resolve(datapoint);
|
|
130
|
-
const decodedPayload = dptlib.fromBuffer(msg.knx.rawValue, dpt);
|
|
131
|
-
} catch (error) {
|
|
132
|
-
node.status({ fill: 'red', shape: 'dot', text: 'datapoint = node.decodedRespondToList ' + error.message, payload: '', dpt: '', devicename: '' });
|
|
133
|
-
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimateAutoResponder: datapoint = node.decodedRespondToList.find(x => x.address === msg.knx.destination).dpt ${error.stack}`);
|
|
134
|
-
}
|
|
129
|
+
if (oGa !== undefined) {
|
|
130
|
+
try {
|
|
131
|
+
// Don't care about the decoded payload, because knxUltimate-config could pass a TryToFindDatapoint from raw data
|
|
132
|
+
// Take only RAW data and decode it with the dpt specified by the commandText directive
|
|
133
|
+
const decodedPayload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(oGa.dpt));
|
|
134
|
+
} catch (error) {
|
|
135
|
+
node.status({ fill: 'red', shape: 'dot', text: 'datapoint = node.decodedRespondToList ' + error.message, payload: '', dpt: '', devicename: '' });
|
|
136
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimateAutoResponder: datapoint = node.decodedRespondToList.find(x => x.address === msg.knx.destination).dpt ${error.stack}`);
|
|
135
137
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
} else {
|
|
139
|
-
oGa.dpt = msg.knx.dpt
|
|
140
|
-
oGa.payload = msg.payload
|
|
138
|
+
oGa.payload = decodedPayload
|
|
141
139
|
}
|
|
142
140
|
} else {
|
|
143
141
|
|
|
144
|
-
// Send the response to the bus
|
|
145
|
-
var defaultValue; // Default value if no payload in the exposedGA list
|
|
146
|
-
var bFound = false;
|
|
147
|
-
// Can i handle the incoming message?
|
|
148
|
-
try {
|
|
149
|
-
for (let index = 0; index < node.decodedRespondToList.length; index++) {
|
|
150
|
-
const element = node.decodedRespondToList[index];
|
|
151
|
-
if (msg.knx.destination === element.address) {
|
|
152
|
-
defaultValue = element.default;
|
|
153
|
-
bFound = true;
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
} catch (error) {
|
|
158
|
-
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimateAutoResponder: before bFound ${error.stack}`);
|
|
159
|
-
}
|
|
160
|
-
if (!bFound) return;
|
|
161
|
-
|
|
162
142
|
try {
|
|
163
143
|
let retVal;
|
|
164
144
|
let oFoundGA = node.exposedGAs.find(ga => ga.address === msg.knx.destination);
|
|
165
145
|
if (oFoundGA === undefined) return;
|
|
166
146
|
if (oFoundGA.payload === undefined) {
|
|
167
|
-
|
|
168
|
-
if (defaultValue === 'false') defaultValue = false;
|
|
169
|
-
retVal = defaultValue;
|
|
147
|
+
retVal = oFoundGA.default;
|
|
170
148
|
} else {
|
|
171
149
|
retVal = oFoundGA.payload;
|
|
172
150
|
}
|
|
173
151
|
if (retVal !== undefined) {
|
|
174
152
|
const dDate = new Date()
|
|
175
153
|
node.status({ fill: 'blue', shape: 'dot', text: 'Respond ' + oFoundGA.address + ' => ' + retVal + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
|
|
176
|
-
node.server.writeQueueAdd({ grpaddr: oFoundGA.address, payload: retVal, dpt: oFoundGA.dpt
|
|
154
|
+
node.server.writeQueueAdd({ grpaddr: oFoundGA.address, payload: retVal, dpt: oFoundGA.dpt, outputtype: 'response', nodecallerid: node.id });
|
|
177
155
|
}
|
|
178
156
|
} catch (error) {
|
|
179
157
|
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimateAutoResponder: after bFound ${error.stack}`);
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.0.
|
|
6
|
+
"version": "3.0.6",
|
|
7
7
|
"description": "Control your KNX intallation via Node-Red! A bunch of KNX nodes, with integrated Philips HUE control and ETS group address importer. Easy to use and highly configurable.",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"binary-parser": "2.2.1",
|