node-red-contrib-knx-ultimate 2.5.1 → 3.0.0-beta2
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/.eslintrc.json +3 -2
- package/CHANGELOG.md +13 -0
- package/README.md +2 -1
- package/{KNXEngine → _JS_KNXEngine}/README.md +7 -7
- package/{KNXEngine → _JS_KNXEngine}/index.js +1 -1
- package/{KNXEngine → _JS_KNXEngine}/sample.js +5 -5
- package/{KNXEngine → _JS_KNXEngine}/sampleSecure.js +1 -1
- package/{KNXEngine → _JS_KNXEngine}/src/KNXClient.js +3 -3
- package/_JS_KNXEngine/src/dptlib/dpt60002.js +101 -0
- package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectResponse.js +2 -0
- package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConstants.js +1 -0
- package/nodes/commonFunctions.js +3 -3
- package/nodes/hue-config.html +2 -0
- package/nodes/hue-config.js +8 -0
- package/nodes/knxUltimate-config.html +2 -0
- package/nodes/knxUltimate-config.js +226 -223
- package/nodes/knxUltimate.html +124 -57
- package/nodes/knxUltimate.js +100 -60
- package/nodes/knxUltimateAlerter.html +7 -12
- package/nodes/knxUltimateAlerter.js +3 -2
- package/nodes/knxUltimateGarageDoorBarrierOpener.html +7 -12
- package/nodes/knxUltimateGarageDoorBarrierOpener.js +2 -2
- package/nodes/knxUltimateGlobalContext.html +2 -0
- package/nodes/knxUltimateHueBattery.html +11 -14
- package/nodes/knxUltimateHueButton.html +27 -22
- package/nodes/knxUltimateHueButton.js +1 -1
- package/nodes/knxUltimateHueContactSensor.html +12 -8
- package/nodes/knxUltimateHueLight.html +17 -24
- package/nodes/knxUltimateHueLight.js +1 -2
- package/nodes/knxUltimateHueLightSensor.html +11 -14
- package/nodes/knxUltimateHueMotion.html +11 -14
- package/nodes/knxUltimateHueScene.html +24 -19
- package/nodes/knxUltimateHueScene.js +2 -1
- package/nodes/knxUltimateHueTapDial.html +11 -14
- package/nodes/knxUltimateHueTemperatureSensor.html +11 -14
- package/nodes/knxUltimateHueZigbeeConnectivity.html +11 -14
- package/nodes/knxUltimateHuedevice_software_update.html +261 -0
- package/nodes/knxUltimateHuedevice_software_update.js +134 -0
- package/nodes/knxUltimateLoadControl.html +4 -11
- package/nodes/knxUltimateLoadControl.js +1 -1
- package/nodes/knxUltimateLogger.html +3 -1
- package/nodes/knxUltimateSceneController.html +14 -15
- package/nodes/knxUltimateViewer.html +2 -0
- package/nodes/knxUltimateViewer.js +1 -1
- package/nodes/knxUltimateWatchDog.html +3 -1
- package/nodes/utils/payloadManipulation.js +49 -1
- package/nodes/utils/utils.js +4 -0
- package/package.json +6 -4
- package/resources/htmlUtils.js +27 -0
- /package/{KNXEngine → _JS_KNXEngine}/CHANGELOG.md +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/LICENSE +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/dpt 2.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/dpt.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/logo 2.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/logo-big 2.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/logo-big.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/logo.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/nodered 2.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/nodered.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/package.json +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/simpleSample.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/Curve25519.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/KNXSocketOptions.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/KNXsecureKeyring.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/KnxLog.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/cur.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt1.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt10.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt11.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt12.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt13.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt14.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt15.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt16.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt17.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt18.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt19.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt2.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt20.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt21.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt213.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt22.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt222.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt232.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt235.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt237.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt238.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt242.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt249.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt251.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt275.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt28.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt29.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt3.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt4.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt5.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt6.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt60001.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt7.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt8.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt9.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt999.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/index.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/BufferLengthError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/DateFormatError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/DuplicateRequestError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/InvalidValueError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/NotImplementedError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/RequestTimeoutError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/index.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/index.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRD.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRI.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRIFactory.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/DIB.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/DeviceInfo.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/HPAI.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/IPConfig.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/IPCurrentConfig.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXAddress.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXAddresses.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectionStateRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectionStateResponse.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDataBuffer.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDescriptionRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDescriptionResponse.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDisconnectRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDisconnectResponse.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXHeader.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXPacket.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXProtocol.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXRoutingIndication.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSearchRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSearchResponse.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSecureSessionRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXTunnelingAck.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXTunnelingRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXUtils.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/ServiceFamilies.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/TunnelCRI.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/AdditionalInfo.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIConstants.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIFactory.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIMessage.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/ControlField.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataCon.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataInd.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataReq.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/NPDU.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/TLVInfo.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/index.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/util/ipAddressHelper.js +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
module.exports = function (RED) {
|
|
2
|
+
function knxUltimateHuedevice_software_update(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
const node = this;
|
|
5
|
+
node.server = RED.nodes.getNode(config.server);
|
|
6
|
+
node.serverHue = RED.nodes.getNode(config.serverHue);
|
|
7
|
+
node.topic = node.name;
|
|
8
|
+
node.name = config.name === undefined ? 'Hue' : config.name;
|
|
9
|
+
node.dpt = '';
|
|
10
|
+
node.notifyreadrequest = true;
|
|
11
|
+
node.notifyreadrequestalsorespondtobus = 'false';
|
|
12
|
+
node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = '';
|
|
13
|
+
node.notifyresponse = false;
|
|
14
|
+
node.notifywrite = true;
|
|
15
|
+
node.initialread = true;
|
|
16
|
+
node.listenallga = true; // Don't remove
|
|
17
|
+
node.outputtype = 'write';
|
|
18
|
+
node.outputRBE = 'false'; // Apply or not RBE to the output (Messages coming from flow)
|
|
19
|
+
node.inputRBE = 'false'; // Apply or not RBE to the input (Messages coming from BUS)
|
|
20
|
+
node.currentPayload = ''; // Current value for the RBE input and for the .previouspayload msg
|
|
21
|
+
node.passthrough = 'no';
|
|
22
|
+
node.formatmultiplyvalue = 1;
|
|
23
|
+
node.formatnegativevalue = 'leave';
|
|
24
|
+
node.formatdecimalsvalue = 2;
|
|
25
|
+
node.hueDevice = config.hueDevice;
|
|
26
|
+
node.initializingAtStart = (config.readStatusAtStartup === undefined || config.readStatusAtStartup === "yes");
|
|
27
|
+
node.currentDeviceValue = false;
|
|
28
|
+
|
|
29
|
+
// Used to call the status update from the config node.
|
|
30
|
+
node.setNodeStatus = ({
|
|
31
|
+
fill, shape, text, payload,
|
|
32
|
+
}) => {
|
|
33
|
+
|
|
34
|
+
};
|
|
35
|
+
// Used to call the status update from the HUE config node.
|
|
36
|
+
node.setNodeStatusHue = ({
|
|
37
|
+
fill, shape, text, payload,
|
|
38
|
+
}) => {
|
|
39
|
+
if (payload === undefined) payload = '';
|
|
40
|
+
const dDate = new Date();
|
|
41
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString();
|
|
42
|
+
node.status({ fill, shape, text: `${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})` });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
46
|
+
node.handleSend = (msg) => {
|
|
47
|
+
// Respond to KNX read telegram, by sending the current value as response telegram.
|
|
48
|
+
if (msg.knx.event === "GroupValue_Read") {
|
|
49
|
+
switch (msg.knx.destination) {
|
|
50
|
+
case config.GAdevice_software_update:
|
|
51
|
+
// To the KNX bus wires
|
|
52
|
+
node.sendResponseToKNX(node.currentDeviceValue);
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
node.handleSendHUE = (_event) => {
|
|
61
|
+
try {
|
|
62
|
+
// Event status: one of connected, disconnected, connectivity_issue, unidirectional_incoming
|
|
63
|
+
if (_event.id === config.hueDevice) {
|
|
64
|
+
if (!_event.hasOwnProperty("state") || _event.state === undefined) return;
|
|
65
|
+
|
|
66
|
+
const knxMsgPayload = {};
|
|
67
|
+
knxMsgPayload.topic = config.GAdevice_software_update;
|
|
68
|
+
knxMsgPayload.dpt = config.dptdevice_software_update;
|
|
69
|
+
|
|
70
|
+
knxMsgPayload.payload = (_event.state !== "no_update");
|
|
71
|
+
// Send to KNX bus
|
|
72
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
|
|
73
|
+
node.server.writeQueueAdd({
|
|
74
|
+
grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
node.currentDeviceValue = knxMsgPayload.payload;
|
|
78
|
+
// Setup the output msg
|
|
79
|
+
knxMsgPayload.name = node.name;
|
|
80
|
+
knxMsgPayload.status = _event.state;
|
|
81
|
+
knxMsgPayload.event = 'device_software_update';
|
|
82
|
+
// Send payload
|
|
83
|
+
knxMsgPayload.rawEvent = _event;
|
|
84
|
+
node.send(knxMsgPayload);
|
|
85
|
+
node.setNodeStatusHue({
|
|
86
|
+
fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
} catch (error) {
|
|
90
|
+
node.status({ fill: 'red', shape: 'dot', text: `HUE->KNX error ${error.message} (${new Date().getDate()}, ${new Date().toLocaleTimeString()})` });
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
node.sendResponseToKNX = (_level) => {
|
|
96
|
+
const knxMsgPayload = {};
|
|
97
|
+
knxMsgPayload.topic = config.GAdevice_software_update;
|
|
98
|
+
knxMsgPayload.dpt = config.dptdevice_software_update;
|
|
99
|
+
|
|
100
|
+
knxMsgPayload.payload = _level;
|
|
101
|
+
// Send to KNX bus
|
|
102
|
+
if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
|
|
103
|
+
node.server.writeQueueAdd({
|
|
104
|
+
grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'response', nodecallerid: node.id,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// On each deploy, unsubscribe+resubscribe
|
|
110
|
+
if (node.server) {
|
|
111
|
+
node.server.removeClient(node);
|
|
112
|
+
node.server.addClient(node);
|
|
113
|
+
}
|
|
114
|
+
if (node.serverHue) {
|
|
115
|
+
node.serverHue.removeClient(node);
|
|
116
|
+
node.serverHue.addClient(node);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
node.on('input', (msg) => {
|
|
120
|
+
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
node.on('close', (done) => {
|
|
124
|
+
if (node.server) {
|
|
125
|
+
node.server.removeClient(node);
|
|
126
|
+
}
|
|
127
|
+
if (node.serverHue) {
|
|
128
|
+
node.serverHue.removeClient(node);
|
|
129
|
+
}
|
|
130
|
+
done();
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
RED.nodes.registerType('knxUltimateHuedevice_software_update', knxUltimateHuedevice_software_update);
|
|
134
|
+
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
|
|
2
|
+
|
|
1
3
|
<script type="text/javascript">
|
|
2
4
|
RED.nodes.registerType('knxUltimateLoadControl', {
|
|
3
5
|
category: "KNX Ultimate",
|
|
@@ -79,16 +81,7 @@
|
|
|
79
81
|
} catch (error) { }
|
|
80
82
|
});
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
function fullSearch(sourceText, searchString) {
|
|
84
|
-
// This searches for all words in a string
|
|
85
|
-
var aSearchWords = searchString.toLowerCase().split(" ");
|
|
86
|
-
var i = 0;
|
|
87
|
-
for (let index = 0; index < aSearchWords.length; index++) {
|
|
88
|
-
if (sourceText.toLowerCase().indexOf(aSearchWords[index]) > -1) i += 1;
|
|
89
|
-
}
|
|
90
|
-
return i == aSearchWords.length;
|
|
91
|
-
}
|
|
84
|
+
|
|
92
85
|
|
|
93
86
|
$.getJSON("knxUltimateDpts?serverId=" + $("#node-input-server").val(), (data) => {
|
|
94
87
|
data.forEach(dpt => {
|
|
@@ -119,7 +112,7 @@
|
|
|
119
112
|
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
|
|
120
113
|
response($.map(data, function (value, key) {
|
|
121
114
|
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
|
|
122
|
-
if (
|
|
115
|
+
if (htmlUtilsfullCSVSearch(sSearch, request.term)) {
|
|
123
116
|
return {
|
|
124
117
|
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
125
118
|
value: value.ga // Value
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
|
|
2
|
+
|
|
1
3
|
<script type="text/javascript">
|
|
2
4
|
RED.nodes.registerType('knxUltimateLogger', {
|
|
3
5
|
category: "KNX Ultimate",
|
|
@@ -11,7 +13,7 @@
|
|
|
11
13
|
maxRowsInETSXML: { value: 0, required: true, validate: RED.validators.number() },
|
|
12
14
|
autoStartTimerTelegramCounter: { value: false },
|
|
13
15
|
intervalTelegramCount: { value: 60, required: false, validate: RED.validators.number() }
|
|
14
|
-
|
|
16
|
+
|
|
15
17
|
},
|
|
16
18
|
inputs: 1,
|
|
17
19
|
outputs: 2,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
|
|
2
|
+
|
|
1
3
|
<script type="text/javascript">
|
|
2
4
|
RED.nodes.registerType('knxUltimateSceneController', {
|
|
3
5
|
category: "KNX Ultimate",
|
|
@@ -50,16 +52,7 @@
|
|
|
50
52
|
} catch (error) { }
|
|
51
53
|
});
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
function fullSearch(sourceText, searchString) {
|
|
55
|
-
// This searches for all words in a string
|
|
56
|
-
var aSearchWords = searchString.toLowerCase().split(" ");
|
|
57
|
-
var i = 0;
|
|
58
|
-
for (let index = 0; index < aSearchWords.length; index++) {
|
|
59
|
-
if (sourceText.toLowerCase().indexOf(aSearchWords[index]) > -1) i += 1;
|
|
60
|
-
}
|
|
61
|
-
return i == aSearchWords.length;
|
|
62
|
-
}
|
|
55
|
+
|
|
63
56
|
|
|
64
57
|
// DPT of Scene Recall
|
|
65
58
|
// ########################
|
|
@@ -74,13 +67,13 @@
|
|
|
74
67
|
|
|
75
68
|
// Autocomplete suggestion with ETS csv File
|
|
76
69
|
$("#node-input-topic").autocomplete({
|
|
77
|
-
minLength:
|
|
70
|
+
minLength: 0,
|
|
78
71
|
source: function (request, response) {
|
|
79
72
|
//$.getJSON("csv", request, function( data, status, xhr ) {
|
|
80
73
|
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
|
|
81
74
|
response($.map(data, function (value, key) {
|
|
82
75
|
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
|
|
83
|
-
if (
|
|
76
|
+
if (htmlUtilsfullCSVSearch(sSearch, request.term)) {
|
|
84
77
|
return {
|
|
85
78
|
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
86
79
|
value: value.ga // Value
|
|
@@ -103,6 +96,8 @@
|
|
|
103
96
|
$("#node-input-dpt").val(optVal);
|
|
104
97
|
$("#node-input-dpt").trigger("change");
|
|
105
98
|
}
|
|
99
|
+
}).focus(function () {
|
|
100
|
+
$(this).autocomplete('search', $(this).val() + 'exactmatch');
|
|
106
101
|
});
|
|
107
102
|
|
|
108
103
|
// 19/03/2020 Adjust trigger value accordingly
|
|
@@ -196,12 +191,12 @@
|
|
|
196
191
|
|
|
197
192
|
// Autocomplete suggestion with ETS csv File
|
|
198
193
|
$("#node-input-topicSave").autocomplete({
|
|
199
|
-
minLength:
|
|
194
|
+
minLength: 0,
|
|
200
195
|
source: function (request, response) {
|
|
201
196
|
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
|
|
202
197
|
response($.map(data, function (value, key) {
|
|
203
198
|
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
|
|
204
|
-
if (
|
|
199
|
+
if (htmlUtilsfullCSVSearch(sSearch, request.term)) {
|
|
205
200
|
return {
|
|
206
201
|
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
207
202
|
value: value.ga // Value
|
|
@@ -224,6 +219,8 @@
|
|
|
224
219
|
$("#node-input-dptSave").val(optVal);
|
|
225
220
|
$("#node-input-dptSave").trigger("change");
|
|
226
221
|
}
|
|
222
|
+
}).focus(function () {
|
|
223
|
+
$(this).autocomplete('search', $(this).val() + 'exactmatch');
|
|
227
224
|
});
|
|
228
225
|
|
|
229
226
|
// 02/04/2020 Adjust trigger value accordingly
|
|
@@ -340,7 +337,7 @@
|
|
|
340
337
|
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
|
|
341
338
|
response($.map(data, function (value, key) {
|
|
342
339
|
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
|
|
343
|
-
if (
|
|
340
|
+
if (htmlUtilsfullCSVSearch(sSearch, request.term)) {
|
|
344
341
|
return {
|
|
345
342
|
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
346
343
|
value: value.ga // Value
|
|
@@ -361,6 +358,8 @@
|
|
|
361
358
|
var optVal = $(".rowRuleDPT option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
|
|
362
359
|
oDPTField.val(optVal);
|
|
363
360
|
}
|
|
361
|
+
}).focus(function () {
|
|
362
|
+
$(this).autocomplete('search', $(this).val() + 'exactmatch');
|
|
364
363
|
});
|
|
365
364
|
|
|
366
365
|
oTopicField.val(rule.topic);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
|
|
2
|
+
|
|
1
3
|
<script type="text/javascript">
|
|
2
4
|
RED.nodes.registerType('knxUltimateWatchDog', {
|
|
3
5
|
category: "KNX Ultimate",
|
|
@@ -16,7 +18,7 @@
|
|
|
16
18
|
outputLabels: ["Output"],
|
|
17
19
|
icon: "node-watchdog-icon.svg",
|
|
18
20
|
label: function () {
|
|
19
|
-
return ((this.name || "KNX Watchdog") + " " + (this.checkLevel == "Ethernet" ? "Gateway IP": this.topic));
|
|
21
|
+
return ((this.name || "KNX Watchdog") + " " + (this.checkLevel == "Ethernet" ? "Gateway IP" : this.topic));
|
|
20
22
|
},
|
|
21
23
|
paletteLabel: "KNX WatchDog",
|
|
22
24
|
oneditprepare: function () {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @param {object} [_oNode]
|
|
3
3
|
* @param {any} [jsValue]
|
|
4
4
|
*/
|
|
5
|
-
exports.Manipulate = function roundPayload
|
|
5
|
+
exports.Manipulate = function roundPayload(_oNode, jsValue) {
|
|
6
6
|
// 19/01/2023 FORMATTING THE OUTPUT PAYLOAD BASED ON SINGLE NODE SETUP
|
|
7
7
|
//* ********************************************************
|
|
8
8
|
// Formatting the msg output value
|
|
@@ -38,3 +38,51 @@ exports.Manipulate = function roundPayload (_oNode, jsValue) {
|
|
|
38
38
|
}
|
|
39
39
|
//* ********************************************************
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
// KNXULtimate nodes
|
|
43
|
+
module.exports.KNXULtimateChangeConfigByInputMSG = function KNXULtimateChangeConfigByInputMSG(msg, node, config) {
|
|
44
|
+
|
|
45
|
+
if (!msg.setConfig.hasOwnProperty('setGroupAddress') || !msg.setConfig.hasOwnProperty('setDPT')) {
|
|
46
|
+
node.setNodeStatus({
|
|
47
|
+
fill: 'red', shape: 'ring', text: `setGroupAddress and setDPT are mandatory`, payload: '', GA: '', dpt: '', devicename: '',
|
|
48
|
+
});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Set DPT
|
|
53
|
+
node.dpt = msg.setConfig.setDPT;
|
|
54
|
+
config.dpt = msg.setConfig.setDPT;
|
|
55
|
+
|
|
56
|
+
// SET GORUP ADDRESS
|
|
57
|
+
node.topic = msg.setConfig.setGroupAddress;
|
|
58
|
+
config.topic = msg.setConfig.setGroupAddress
|
|
59
|
+
node.outputtopic = (config.outputtopic === undefined || config.outputtopic === '') ? msg.setConfig.setGroupAddress : config.outputtopic; // 07/02/2020 Importante, per retrocompatibilità
|
|
60
|
+
config.outputtopic = node.outputtopic;
|
|
61
|
+
|
|
62
|
+
// Read from the ETS file, the missing props
|
|
63
|
+
if (node.server.csv !== undefined && node.server.csv !== null) {
|
|
64
|
+
// Read it from ETS File
|
|
65
|
+
const found = node.server.csv.find(item => item.ga === msg.setConfig.setGroupAddress);
|
|
66
|
+
if (found !== undefined) {
|
|
67
|
+
if (msg.setConfig.setDPT === 'auto') {
|
|
68
|
+
node.dpt = found.dpt; // SET THE DPT
|
|
69
|
+
config.dpt = found.dpt;
|
|
70
|
+
}
|
|
71
|
+
node.name = found.devicename;
|
|
72
|
+
config.name = found.devicename;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// If DPT is still "auto", something has going wrong
|
|
76
|
+
if (node.dpt === 'auto') {
|
|
77
|
+
// Unable to retrieve the datapoint
|
|
78
|
+
node.setNodeStatus({
|
|
79
|
+
fill: 'red', shape: 'ring', text: `Unable to retrieve the datapoint from the ETS file`, payload: '', GA: '', dpt: '', devicename: '',
|
|
80
|
+
});
|
|
81
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimate: setConfig: Node.id: ${node.id} error: Unable to retrieve the datapoint from the ETS file`);
|
|
82
|
+
} else {
|
|
83
|
+
node.setNodeStatus({
|
|
84
|
+
fill: 'blue', shape: 'ring', text: `Config changed. Current GA: ${node.topic} DPT: ${node.dpt}`, payload: '', GA: '', dpt: '', devicename: node.name,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
};
|
package/nodes/utils/utils.js
CHANGED
|
@@ -53,5 +53,9 @@ module.exports.fetchFromObject = function fetchFromObject(
|
|
|
53
53
|
if (typeof _msg[_payloadPropName] === "object") return undefined;
|
|
54
54
|
return _msg[_payloadPropName];
|
|
55
55
|
};
|
|
56
|
+
|
|
57
|
+
|
|
56
58
|
const DEFAULTTRANSLATIONINPUT =
|
|
57
59
|
"on:true\noff:false\nactive:true\ninactive:false\nopen:true\nclosed:false\nclose:false\n1:true\n0:false\ntrue:true\nfalse:false\nhome:true\nnot_home:false\nnormal:false\nviolated:true";
|
|
60
|
+
|
|
61
|
+
|
package/package.json
CHANGED
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "
|
|
6
|
+
"version": "3.0.0-beta2",
|
|
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",
|
|
10
10
|
"crypto-js": "4.2.0",
|
|
11
11
|
"dns-sync": "0.2.1",
|
|
12
12
|
"eventsource": "2.0.2",
|
|
13
|
+
"js-yaml": "4.1.0",
|
|
14
|
+
"knxultimate": ">=2.3.3",
|
|
13
15
|
"lodash": "4.17.21",
|
|
14
16
|
"log-driver": "1.2.7",
|
|
15
17
|
"mkdirp": "3.0.1",
|
|
@@ -17,8 +19,7 @@
|
|
|
17
19
|
"path": "0.12.7",
|
|
18
20
|
"ping": "0.4.4",
|
|
19
21
|
"simple-get": "4.0.1",
|
|
20
|
-
"xml2js": "0.6.0"
|
|
21
|
-
"js-yaml": "4.1.0"
|
|
22
|
+
"xml2js": "0.6.0"
|
|
22
23
|
},
|
|
23
24
|
"node-red": {
|
|
24
25
|
"version": ">=3.1.1",
|
|
@@ -46,7 +47,8 @@
|
|
|
46
47
|
"knxUltimateHueBattery": "/nodes/knxUltimateHueBattery.js",
|
|
47
48
|
"knxUltimateHueZigbeeConnectivity": "/nodes/knxUltimateHueZigbeeConnectivity.js",
|
|
48
49
|
"knxUltimateContactSensor": "/nodes/knxUltimateHueContactSensor.js",
|
|
49
|
-
"knxUltimateHATranslator": "/nodes/knxUltimateHATranslator.js"
|
|
50
|
+
"knxUltimateHATranslator": "/nodes/knxUltimateHATranslator.js",
|
|
51
|
+
"knxUltimateHuedevice_software_update": "/nodes/knxUltimateHuedevice_software_update.js"
|
|
50
52
|
}
|
|
51
53
|
},
|
|
52
54
|
"repository": {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// 31/03/2020 Search Helper
|
|
2
|
+
function htmlUtilsfullCSVSearch(sourceText, searchString) {
|
|
3
|
+
let aSearchWords = [];
|
|
4
|
+
if (searchString.toLowerCase().includes('exactmatch')) {
|
|
5
|
+
// Find only the strict exact match of group address. For example, if the string is 0/0/2exactmatch, i return only the item in the csv having
|
|
6
|
+
// group address 0/0/2 (and not also, for example 0/0/20)
|
|
7
|
+
// I can have also an exact string like '0/0/1exactmatch 1.000', (GA or any text, plus the datapoint) and i must take it into consideration
|
|
8
|
+
let aSearchStrings = searchString.split(' ');
|
|
9
|
+
for (let index = 0; index < aSearchStrings.length; index++) {
|
|
10
|
+
const element = aSearchStrings[index];
|
|
11
|
+
if (element.includes('exactmatch')) {
|
|
12
|
+
aSearchWords.push(element.replace('exactmatch', ' ')); // The last ' ' allow to return the exact match
|
|
13
|
+
} else {
|
|
14
|
+
aSearchWords.push(element); // The last ' ' allow to return the exact match
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
aSearchWords = searchString.toLowerCase().split(" ");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// This searches for all words in a string
|
|
22
|
+
let i = 0;
|
|
23
|
+
for (let index = 0; index < aSearchWords.length; index++) {
|
|
24
|
+
if (sourceText.toLowerCase().indexOf(aSearchWords[index]) > -1) i += 1;
|
|
25
|
+
}
|
|
26
|
+
return i == aSearchWords.length;
|
|
27
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|