node-red-contrib-zwave-js 6.5.1 → 6.5.5
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 +41 -5
- package/README.md +3 -3
- package/examples/Full Example.json +1 -0
- package/package.json +9 -8
- package/{zwave-js/ui/smartstart/ui → resources/SmartStart}/Livescan.html +7 -3
- package/{zwave-js/ui/smartstart/ui → resources/SmartStart}/Scanchoice.html +11 -10
- package/{zwave-js/ui/smartstart/ui → resources/SmartStart}/Snapscan.html +0 -0
- package/{zwave-js/ui/smartstart/ui → resources/SmartStart}/jquery-3.6.0.min.js +0 -0
- package/{zwave-js/ui/smartstart/ui → resources/SmartStart}/jsQR.js +0 -0
- package/{zwave-js/ui/smartstart/ui → resources/SmartStart}/scripts.js +32 -14
- package/{zwave-js/ui → resources/UITab}/Exclude.png +0 -0
- package/{zwave-js/ui → resources/UITab}/Include.png +0 -0
- package/{zwave-js/ui → resources/UITab}/NodeAdded.png +0 -0
- package/{zwave-js/ui/NodeAddedInsecure.png → resources/UITab/NodeError.png} +0 -0
- package/{zwave-js/ui → resources/UITab}/NodeRemoved.png +0 -0
- package/{zwave-js/ui → resources/UITab}/client.js +35 -1
- package/{zwave-js/ui → resources/UITab}/handlebars.min.js +0 -0
- package/{zwave-js/ui → resources/UITab}/jquery-steps.css +0 -0
- package/{zwave-js/ui → resources/UITab}/jquery-steps.min.js +0 -0
- package/{zwave-js/ui → resources/UITab}/qrcode.min.js +0 -0
- package/{zwave-js/ui → resources/UITab}/styles.css +0 -0
- package/{zwave-js/ui → resources/UITab}/vis-network.min.js +0 -0
- package/validation_result.json +18 -0
- package/zwave-js/cmd-factory.html +2 -1
- package/zwave-js/event-filter.html +8 -2
- package/zwave-js/event-filter.js +20 -20
- package/zwave-js/ui/server.js +9 -5
- package/zwave-js/ui/smartstart/server.js +33 -38
- package/zwave-js/zwave-device.html +8 -2
- package/zwave-js/zwave-device.js +25 -36
- package/zwave-js/zwave-js.html +79 -15
- package/zwave-js/zwave-js.js +54 -15
- package/zwave-js/ui/smartstart/certificate.p12 +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,49 @@
|
|
|
1
1
|
# node-red-contrib-zwave-js Change Log
|
|
2
2
|
|
|
3
|
+
- 6.5.5
|
|
4
|
+
|
|
5
|
+
**Fixes**
|
|
6
|
+
- Fix NPM Ignore rules
|
|
7
|
+
|
|
8
|
+
- 6.5.4
|
|
9
|
+
|
|
10
|
+
**Changes**
|
|
11
|
+
- Smart Start Web Application, has been moved to use the express instance provided by Node RED
|
|
12
|
+
- Live QR Scanning now requires Node RED to be SSL Enabled - basic QR capture can still be used without SSL.
|
|
13
|
+
- Added Min Node RED Version to package.json
|
|
14
|
+
- Switched static resources to use /resources/ endpoint provided by Node RED
|
|
15
|
+
- Added node examples
|
|
16
|
+
- Bump Zwave JS to 8.11.3
|
|
17
|
+
- Bump ESLint to 8.8.0
|
|
18
|
+
|
|
19
|
+
- 6.5.3
|
|
20
|
+
|
|
21
|
+
**Fixes**
|
|
22
|
+
- Wait for driver unload.
|
|
23
|
+
|
|
24
|
+
- 6.5.2
|
|
25
|
+
|
|
26
|
+
**Fixes**
|
|
27
|
+
- Don't soley depend on the **node removed** event to progress the exclusion Wizard
|
|
28
|
+
- Check if a node is selected before opening up a dialog
|
|
29
|
+
|
|
30
|
+
**New Features**
|
|
31
|
+
- Expose the Driver option to disable Optimistic Value Updates
|
|
32
|
+
- Added the ability to hide the status label for device and event filter nodes
|
|
33
|
+
|
|
34
|
+
**Changes**
|
|
35
|
+
- Renamed the **Abort** button during S2 inclusion to better identify its intention
|
|
36
|
+
- Bump ZWJS to 8.11.2
|
|
37
|
+
- Bump Winston to 3.5.0
|
|
38
|
+
|
|
3
39
|
- 6.5.1
|
|
4
40
|
|
|
5
41
|
**Fixes**
|
|
6
|
-
- Battery icon/popup text in the UI is now (finally) kept in sync
|
|
7
|
-
- Driver readiness
|
|
42
|
+
- Battery icon/popup text in the UI is now (finally) kept in sync
|
|
43
|
+
- Driver readiness for Health Checks and Keep Alive requests in the UI
|
|
8
44
|
|
|
9
45
|
**Changes**
|
|
10
|
-
- Improvements to node
|
|
46
|
+
- Improvements to node readiness in the UI
|
|
11
47
|
- Bump ZWJS to 8.11.0
|
|
12
48
|
|
|
13
49
|
|
|
@@ -15,8 +51,8 @@
|
|
|
15
51
|
|
|
16
52
|
**New Features**
|
|
17
53
|
- Added the ability to keep a node awake via the UI
|
|
18
|
-
- Added a new method in the UI to report the health of a nodes conection to the controller
|
|
19
|
-
- Added native camera/image capture controls for Smart Start QR Scanning on the mobile client
|
|
54
|
+
- Added a new method in the UI to report the health of a nodes conection to the controller
|
|
55
|
+
- Added native camera/image capture controls for Smart Start QR Scanning on the mobile client
|
|
20
56
|
|
|
21
57
|
**Changes**
|
|
22
58
|
- Replace **EventEmitter** with an internal instance - to address a **MaxListenersExceeded** warning.
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-

|
|
2
2
|
|
|
3
3
|
# node-red-contrib-zwave-js
|
|
4
4
|
|
|
@@ -37,13 +37,13 @@ Since `node-red-contrib-zwave-js` is based on [Z-Wave JS](https://zwave-js.githu
|
|
|
37
37
|
|
|
38
38
|
### The User Interface
|
|
39
39
|
|
|
40
|
-

|
|
41
41
|
|
|
42
42
|
Included with the contrib is a [user interface](https://github.com/zwave-js/node-red-contrib-zwave-js/wiki/User-Interface) where Z-Wave network management is handled. The controller side of the UI is used to include/exclude devices, heal the network, update firmware, and view the network map for diagnosing problems. The device side of the UI is used to configure devices, manage associations, and provide setup help for the nodes which will be used in your flows.
|
|
43
43
|
|
|
44
44
|
### The Nodes
|
|
45
45
|
|
|
46
|
-

|
|
47
47
|
|
|
48
48
|
There are 4 node types included with this contrib ([click here](https://github.com/zwave-js/node-red-contrib-zwave-js/wiki/node-types) for full details about these nodes)
|
|
49
49
|
- `zwave-js`: this node is used to set up a connection to your USB Z-Wave controller, set security keys, and manage various advanced controller options
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"id":"2f2f5384cf841491","type":"tab","label":"Full Example","disabled":false,"info":"","env":[]},{"id":"159049e0f35da22b","type":"zwave-js","z":"2f2f5384cf841491","d":true,"serialPort":"Select Port","name":"Z-Wave JS Controller","encryptionKey":"","encryptionKeyS2U":"","encryptionKeyS2A":"","encryptionKeyS2AC":"","ackTimeout":"","controllerTimeout":"","sendResponseTimeout":"","sendDataCallback":"","serialAPIStarted":"","logLevelPin":"none","logLevel":"none","logFile":"","logNodeFilter":"","sendUsageStatistics":true,"valueCacheDiskThrottle":"normal","customConfigPath":"","intvwUserCodes":false,"softResetUSB":false,"outputs":1,"disableOptimisticValueUpdate":false,"x":700,"y":160,"wires":[["21a01062cb3b9839"]]},{"id":"68dc316395696ed4","type":"comment","z":"2f2f5384cf841491","name":"Controller Node (Read Me)","info":"The controller node : **zwave-js** \nis the main node. It is the node that all communication is passed.\n\nThis node supports all commands. \n\nTo set it up, double click and select your serial port, \nand if using security, provide your encryption keys (or generate new ones)\n\n**NOTE:** Only 1 copy of this node can be deployed. \nThis node has been disabled, as to not affect any setup you may have already achieved.","x":710,"y":120,"wires":[]},{"id":"6dcd0dc03e0c3559","type":"zwave-device","z":"2f2f5384cf841491","name":"Some Z-Wave Device","filteredNodeId":"All","multicast":false,"datamode":"Send/Receive","messagesPerMS":1,"messageInterval":250,"isolated":false,"outputs":1,"inputs":1,"showStatus":true,"x":860,"y":380,"wires":[["dbb0e87b15b2fd3c"]]},{"id":"dcd9a6bacdcab86b","type":"comment","z":"2f2f5384cf841491","name":"Zwave Device (Read Me)","info":"A single, or mulitple zwave device : **zwave-device**. \nThis node can represent one or multiple zwave devices. \n\nIt communicates with the main **zwave-js** node.\n\nMany copies of this node can be deployed.","x":870,"y":340,"wires":[]},{"id":"42b77dc6dca017d8","type":"function","z":"2f2f5384cf841491","name":"Command","func":"// Changing a Binary Switch State (to true) on node 5\n// You can obtain a ValueID - by double clicking a value title in the UI\n\nlet ValueID = {\n \"commandClassName\": \"Binary Switch\",\n \"commandClass\": 37,\n \"endpoint\": 0,\n \"property\": \"targetValue\",\n \"propertyName\": \"targetValue\"\n}\nlet Message = {\n \"payload\": {\n \"mode\": \"ValueAPI\",\n \"node\": 5,/* This can be omitted, if your device node is set to Specific Node */\n \"method\": \"setValue\",\n \"params\": [ValueID,true]\n }\n}\nreturn Message","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":380,"wires":[["6dcd0dc03e0c3559","59b4cf7d6f673102"]]},{"id":"80583e90febe9a15","type":"inject","z":"2f2f5384cf841491","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":240,"y":380,"wires":[["42b77dc6dca017d8"]]},{"id":"c09caf2bfa47f0f4","type":"comment","z":"2f2f5384cf841491","name":"Manually constructing commands","info":"","x":320,"y":340,"wires":[]},{"id":"a34dcb38a73f4bc4","type":"comment","z":"2f2f5384cf841491","name":"Commands can be sent directly to the controler","info":"","x":460,"y":240,"wires":[]},{"id":"31396cd9b583e1d7","type":"cmd-factory","z":"2f2f5384cf841491","name":"ZWave CMD Factory","node":"Node","endpoint":"","cc":"Select Command Class","method":"Select Method","params":"payload","noEvent":false,"forceUpdate":"forceUpdate","api":"ValueAPI","vapiMode":"setValue","vapiValue":"Value","vapiValueId":"ValueID","vapiOptions":"","x":660,"y":540,"wires":[["6dcd0dc03e0c3559"]]},{"id":"d4cc366646c4013d","type":"comment","z":"2f2f5384cf841491","name":"Constructing commands with CMD-Factory","info":"","x":350,"y":500,"wires":[]},{"id":"8fb56f9d226bef12","type":"function","z":"2f2f5384cf841491","name":"Command Values","func":"// Node, ValueID and Value are referenced in the CMD Factory.\n// It uses JSONata so can be highly configurable.\n\n\nmsg.Node = 5;\nmsg.ValueID = {\n \"commandClassName\": \"Binary Switch\",\n \"commandClass\": 37,\n \"endpoint\": 0,\n \"property\": \"targetValue\",\n \"propertyName\": \"targetValue\"\n};\nmsg.Value = false;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":540,"wires":[["31396cd9b583e1d7"]]},{"id":"83159be8b5438fc4","type":"inject","z":"2f2f5384cf841491","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":240,"y":540,"wires":[["8fb56f9d226bef12"]]},{"id":"dbb0e87b15b2fd3c","type":"event-filter","z":"2f2f5384cf841491","name":"ZWave Event Filter","filters":[{"index":0,"name":"Temp Changes","valueIds":[{"commandClassName":"Multilevel Sensor","commandClass":49,"endpoint":0,"property":"Air temperature","propertyName":"Air temperature"}],"events":["VALUE_UPDATED"],"strict":false,"id":"210290","_id":0},{"index":1,"name":"Light Level Changes","valueIds":[{"commandClassName":"Multilevel Sensor","commandClass":49,"endpoint":0,"property":"Illuminance","propertyName":"Illuminance"}],"events":["VALUE_UPDATED"],"strict":false,"id":"293826","_id":1}],"outputs":2,"changeDate":"2022-02-01T16:55:32.003Z","showStatus":true,"x":1210,"y":380,"wires":[["899af27929142c45"],["f7d66b6a07aa4868"]]},{"id":"f662f69f25a23e83","type":"comment","z":"2f2f5384cf841491","name":"Event Filter (Read Me)","info":"A node to split/ route events : **event-filter**. \nThis node can direct various events and ValueIDs out to different paths. \n\nEach filter can group 1 or more ValueIDs - you can add them from the UI. \ndouble click a value title and choose 'Add To Filter Set' whilst a filter set is expaned","x":1220,"y":340,"wires":[]},{"id":"59b4cf7d6f673102","type":"change","z":"2f2f5384cf841491","name":"","rules":[],"action":"","property":"","from":"","to":"","reg":false,"x":555,"y":160,"wires":[[]],"l":false},{"id":"899af27929142c45","type":"function","z":"2f2f5384cf841491","name":"Do something with temp change value","func":"const Temp = msg.payload.object.newValue","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1530,"y":340,"wires":[[]]},{"id":"f7d66b6a07aa4868","type":"function","z":"2f2f5384cf841491","name":"Do something with light level change value","func":"const Lux = msg.payload.object.newValue","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1550,"y":400,"wires":[[]]},{"id":"21a01062cb3b9839","type":"change","z":"2f2f5384cf841491","name":"","rules":[],"action":"","property":"","from":"","to":"","reg":false,"x":1075,"y":360,"wires":[[]],"l":false},{"id":"a13f0bc39b98b13e","type":"comment","z":"2f2f5384cf841491","name":"The controller also emits all events","info":"","x":960,"y":240,"wires":[]}]
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-zwave-js",
|
|
3
|
-
"version": "6.5.
|
|
3
|
+
"version": "6.5.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "An extremely powerful, easy to use, and feature rich Z-Wave node for Node Red, based on Z-Wave JS.",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"express": "^4.17.2",
|
|
8
7
|
"limiter": "^2.1.0",
|
|
9
8
|
"lodash": "^4.17.21",
|
|
10
9
|
"serialport": "9.2.8",
|
|
11
|
-
"winston": "^3.
|
|
10
|
+
"winston": "^3.5.1",
|
|
12
11
|
"winston-transport": "^4.4.2",
|
|
13
|
-
"zwave-js": "^8.11.
|
|
14
|
-
"ip": "^1.1.5"
|
|
12
|
+
"zwave-js": "^8.11.3"
|
|
15
13
|
},
|
|
16
14
|
"devDependencies": {
|
|
17
|
-
"eslint": "^8.
|
|
15
|
+
"eslint": "^8.8.0",
|
|
18
16
|
"prettier": "^2.5.1"
|
|
19
17
|
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"validate": "node-red-dev validate -o validation_result.json"
|
|
20
|
+
},
|
|
20
21
|
"engines": {
|
|
21
|
-
"node": ">=12.22.2"
|
|
22
|
-
"npm": ">=6.14.13"
|
|
22
|
+
"node": ">=12.22.2"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|
|
25
25
|
"node-red",
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"home"
|
|
33
33
|
],
|
|
34
34
|
"node-red": {
|
|
35
|
+
"version": ">=2.0.0",
|
|
35
36
|
"nodes": {
|
|
36
37
|
"zwave-js": "zwave-js/zwave-js.js",
|
|
37
38
|
"zwave-device": "zwave-js/zwave-device.js",
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
font-size: 16px;
|
|
19
19
|
}
|
|
20
20
|
</style>
|
|
21
|
-
<script src="jquery-3.6.0.min.js"></script>
|
|
22
|
-
<script src="jsQR.js"></script>
|
|
23
|
-
<script src="scripts.js"></script>
|
|
21
|
+
<script src="./jquery-3.6.0.min.js"></script>
|
|
22
|
+
<script src="./jsQR.js"></script>
|
|
23
|
+
<script src="./scripts.js"></script>
|
|
24
24
|
<style type="text/css">
|
|
25
25
|
body {
|
|
26
26
|
font-family: HelveticaNeue-Light, Roboto;
|
|
@@ -35,15 +35,16 @@
|
|
|
35
35
|
Select the Camera Source Mode
|
|
36
36
|
</p>
|
|
37
37
|
|
|
38
|
+
<input type="button" value="Native (More Control)" onclick="GrabImage()" />
|
|
38
39
|
<input
|
|
40
|
+
id="LiveScanButton"
|
|
39
41
|
type="button"
|
|
40
|
-
value="
|
|
41
|
-
onclick="
|
|
42
|
-
|
|
43
|
-
<input
|
|
44
|
-
type="button"
|
|
45
|
-
value="Live (Faster, Less Control)"
|
|
46
|
-
onclick="location.href='Livescan.html'"
|
|
42
|
+
value="Live (Less Control, Requires SSL)"
|
|
43
|
+
onclick="location.href='./Livescan.html'"
|
|
44
|
+
style="filter: grayscale(1); pointer-events: none"
|
|
47
45
|
/>
|
|
46
|
+
<script>
|
|
47
|
+
EnableLive();
|
|
48
|
+
</script>
|
|
48
49
|
</body>
|
|
49
50
|
</html>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -7,15 +7,19 @@ let offset;
|
|
|
7
7
|
const ScannedCodes = {};
|
|
8
8
|
|
|
9
9
|
function GrabImage() {
|
|
10
|
-
SendActive()
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
SendActive()
|
|
11
|
+
.then(() => {
|
|
12
|
+
const FI = document.createElement('input');
|
|
13
|
+
FI.hidden = true;
|
|
14
|
+
document.body.append(FI);
|
|
15
|
+
FI.addEventListener('change', SubmitPhoto, false);
|
|
16
|
+
FI.setAttribute('type', 'file');
|
|
17
|
+
FI.setAttribute('accept', 'image/*;capture=camera');
|
|
18
|
+
FI.click();
|
|
19
|
+
})
|
|
20
|
+
.catch((Err) => {
|
|
21
|
+
alert(Err);
|
|
22
|
+
});
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
function SubmitPhoto(e) {
|
|
@@ -157,10 +161,18 @@ function tick() {
|
|
|
157
161
|
}
|
|
158
162
|
}
|
|
159
163
|
|
|
160
|
-
function SendActive() {
|
|
161
|
-
return new Promise((resolve) => {
|
|
162
|
-
$.ajax({
|
|
163
|
-
|
|
164
|
+
async function SendActive() {
|
|
165
|
+
return new Promise((resolve, reject) => {
|
|
166
|
+
const Res = $.ajax({
|
|
167
|
+
url: '../../../../zwave-js/smartstart-event/started',
|
|
168
|
+
method: 'get',
|
|
169
|
+
async: false
|
|
170
|
+
});
|
|
171
|
+
if (Res.status === 200) {
|
|
172
|
+
resolve();
|
|
173
|
+
} else {
|
|
174
|
+
reject('Smart start is not ready.');
|
|
175
|
+
}
|
|
164
176
|
});
|
|
165
177
|
}
|
|
166
178
|
|
|
@@ -204,7 +216,7 @@ function SendCode(Code, skipRender) {
|
|
|
204
216
|
} else {
|
|
205
217
|
let Result;
|
|
206
218
|
$.ajax({
|
|
207
|
-
url: '/event
|
|
219
|
+
url: '../../../../zwave-js/smartstart-event/code/' + Code.data,
|
|
208
220
|
method: 'get',
|
|
209
221
|
success: (data) => {
|
|
210
222
|
Result = data;
|
|
@@ -217,3 +229,9 @@ function SendCode(Code, skipRender) {
|
|
|
217
229
|
}
|
|
218
230
|
});
|
|
219
231
|
}
|
|
232
|
+
|
|
233
|
+
function EnableLive() {
|
|
234
|
+
if (location.protocol === 'https:') {
|
|
235
|
+
$('#LiveScanButton').css({ filter: '', pointerEvents: 'all' });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -25,7 +25,8 @@ const StepList = {
|
|
|
25
25
|
SmartStart: 10,
|
|
26
26
|
SmartStartList: 11,
|
|
27
27
|
SmartStartListEdit: 12,
|
|
28
|
-
SmartStartDone: 13
|
|
28
|
+
SmartStartDone: 13,
|
|
29
|
+
RemoveDoneUnconfirmed: 14
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
const JSONFormatter = {};
|
|
@@ -212,6 +213,7 @@ const ZwaveJsUI = (function () {
|
|
|
212
213
|
|
|
213
214
|
function HealthCheck() {
|
|
214
215
|
IsDriverReady();
|
|
216
|
+
IsNodeSelected();
|
|
215
217
|
const Buttons = {
|
|
216
218
|
'Yes (1 Round)': () => {
|
|
217
219
|
RenderHealthCheck(1);
|
|
@@ -233,6 +235,7 @@ const ZwaveJsUI = (function () {
|
|
|
233
235
|
|
|
234
236
|
function KeepAwake() {
|
|
235
237
|
IsDriverReady();
|
|
238
|
+
IsNodeSelected();
|
|
236
239
|
const Node = $(
|
|
237
240
|
".red-ui-treeList-label.zwave-js-node-row[data-nodeid='" +
|
|
238
241
|
selectedNode +
|
|
@@ -793,6 +796,13 @@ const ZwaveJsUI = (function () {
|
|
|
793
796
|
return $.ajax(Options);
|
|
794
797
|
}
|
|
795
798
|
|
|
799
|
+
function IsNodeSelected() {
|
|
800
|
+
if (selectedNode === undefined) {
|
|
801
|
+
modalAlert('Please select a Node.', 'No Node Selected');
|
|
802
|
+
throw new Error('No Node Selected');
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
796
806
|
function IsDriverReady() {
|
|
797
807
|
if (!DriverReady) {
|
|
798
808
|
modalAlert(
|
|
@@ -1268,6 +1278,7 @@ const ZwaveJsUI = (function () {
|
|
|
1268
1278
|
|
|
1269
1279
|
function RenameNode(KB, El) {
|
|
1270
1280
|
IsDriverReady();
|
|
1281
|
+
IsNodeSelected();
|
|
1271
1282
|
let input;
|
|
1272
1283
|
let Button;
|
|
1273
1284
|
if (KB === true) {
|
|
@@ -1302,6 +1313,7 @@ const ZwaveJsUI = (function () {
|
|
|
1302
1313
|
|
|
1303
1314
|
function SetNodeLocation(KB, El) {
|
|
1304
1315
|
IsDriverReady();
|
|
1316
|
+
IsNodeSelected();
|
|
1305
1317
|
let input;
|
|
1306
1318
|
let Button;
|
|
1307
1319
|
if (KB === true) {
|
|
@@ -1350,6 +1362,7 @@ const ZwaveJsUI = (function () {
|
|
|
1350
1362
|
}
|
|
1351
1363
|
|
|
1352
1364
|
function OpenDB() {
|
|
1365
|
+
IsNodeSelected();
|
|
1353
1366
|
const info =
|
|
1354
1367
|
$(`.zwave-js-node-row.selected`).data('info')?.deviceConfig || {};
|
|
1355
1368
|
const id = [
|
|
@@ -1379,6 +1392,7 @@ const ZwaveJsUI = (function () {
|
|
|
1379
1392
|
if (err.status !== 504) {
|
|
1380
1393
|
modalAlert(err.responseText, 'Could Not Remove Node');
|
|
1381
1394
|
}
|
|
1395
|
+
|
|
1382
1396
|
Removing = false;
|
|
1383
1397
|
});
|
|
1384
1398
|
}
|
|
@@ -1604,6 +1618,7 @@ const ZwaveJsUI = (function () {
|
|
|
1604
1618
|
.css('min-width', '125px')
|
|
1605
1619
|
.click(() => {
|
|
1606
1620
|
IsDriverReady();
|
|
1621
|
+
IsNodeSelected();
|
|
1607
1622
|
InterviewNode();
|
|
1608
1623
|
})
|
|
1609
1624
|
.html('Interview Node')
|
|
@@ -1615,6 +1630,7 @@ const ZwaveJsUI = (function () {
|
|
|
1615
1630
|
.css('min-width', '125px')
|
|
1616
1631
|
.click(() => {
|
|
1617
1632
|
IsDriverReady();
|
|
1633
|
+
IsNodeSelected();
|
|
1618
1634
|
StartNodeHeal();
|
|
1619
1635
|
})
|
|
1620
1636
|
.html('Heal Node')
|
|
@@ -1628,6 +1644,7 @@ const ZwaveJsUI = (function () {
|
|
|
1628
1644
|
.css('min-width', '125px')
|
|
1629
1645
|
.click(() => {
|
|
1630
1646
|
IsDriverReady();
|
|
1647
|
+
IsNodeSelected();
|
|
1631
1648
|
RemoveFailedNode();
|
|
1632
1649
|
})
|
|
1633
1650
|
.html('Remove Failed Node')
|
|
@@ -1638,6 +1655,7 @@ const ZwaveJsUI = (function () {
|
|
|
1638
1655
|
.css('min-width', '125px')
|
|
1639
1656
|
.click(() => {
|
|
1640
1657
|
IsDriverReady();
|
|
1658
|
+
IsNodeSelected();
|
|
1641
1659
|
ShowReplacePrompt();
|
|
1642
1660
|
})
|
|
1643
1661
|
.html('Replace Failed Node')
|
|
@@ -1651,6 +1669,7 @@ const ZwaveJsUI = (function () {
|
|
|
1651
1669
|
.css('min-width', '125px')
|
|
1652
1670
|
.click(() => {
|
|
1653
1671
|
IsDriverReady();
|
|
1672
|
+
IsNodeSelected();
|
|
1654
1673
|
AssociationMGMT();
|
|
1655
1674
|
})
|
|
1656
1675
|
.html('Association Management')
|
|
@@ -1661,6 +1680,7 @@ const ZwaveJsUI = (function () {
|
|
|
1661
1680
|
.css('min-width', '125px')
|
|
1662
1681
|
.click(() => {
|
|
1663
1682
|
IsDriverReady();
|
|
1683
|
+
IsNodeSelected();
|
|
1664
1684
|
getProperties();
|
|
1665
1685
|
})
|
|
1666
1686
|
.html('Refresh Property List')
|
|
@@ -1741,6 +1761,7 @@ const ZwaveJsUI = (function () {
|
|
|
1741
1761
|
$('#zwave-js-controller-status').html(data.status);
|
|
1742
1762
|
}
|
|
1743
1763
|
|
|
1764
|
+
let RemovedShown = false;
|
|
1744
1765
|
function handleControllerEvent(topic, data) {
|
|
1745
1766
|
switch (data.type) {
|
|
1746
1767
|
case 'node-collection-change':
|
|
@@ -1759,9 +1780,11 @@ const ZwaveJsUI = (function () {
|
|
|
1759
1780
|
$('#IEButton').text('Close');
|
|
1760
1781
|
}
|
|
1761
1782
|
if (data.event === 'node removed') {
|
|
1783
|
+
RemovedShown = true;
|
|
1762
1784
|
ClearIETimer();
|
|
1763
1785
|
ClearSecurityCountDown();
|
|
1764
1786
|
GetNodes();
|
|
1787
|
+
selectedNode = undefined;
|
|
1765
1788
|
StepsAPI.setStepIndex(StepList.RemoveDone);
|
|
1766
1789
|
$('#IEButton').text('Close');
|
|
1767
1790
|
}
|
|
@@ -1769,11 +1792,13 @@ const ZwaveJsUI = (function () {
|
|
|
1769
1792
|
|
|
1770
1793
|
case 'node-inclusion-step':
|
|
1771
1794
|
if (data.event === 'grant security') {
|
|
1795
|
+
$('#IEButton').text('Abort S2 Bootstrap');
|
|
1772
1796
|
ListRequestedClass(data.classes);
|
|
1773
1797
|
ClearIETimer();
|
|
1774
1798
|
StartSecurityCountDown();
|
|
1775
1799
|
}
|
|
1776
1800
|
if (data.event === 'verify dsk') {
|
|
1801
|
+
$('#IEButton').text('Abort S2 Bootstrap');
|
|
1777
1802
|
DisplayDSK(data.dsk);
|
|
1778
1803
|
ClearIETimer();
|
|
1779
1804
|
StartSecurityCountDown();
|
|
@@ -1785,6 +1810,15 @@ const ZwaveJsUI = (function () {
|
|
|
1785
1810
|
if (data.event === 'exclusion started') {
|
|
1786
1811
|
StepsAPI.setStepIndex(StepList.Remove);
|
|
1787
1812
|
StartIECountDown();
|
|
1813
|
+
RemovedShown = false;
|
|
1814
|
+
}
|
|
1815
|
+
if (data.event === 'exclusion stopped') {
|
|
1816
|
+
if (!RemovedShown) {
|
|
1817
|
+
ClearIETimer();
|
|
1818
|
+
ClearSecurityCountDown();
|
|
1819
|
+
StepsAPI.setStepIndex(StepList.RemoveDoneUnconfirmed);
|
|
1820
|
+
$('#IEButton').text('Close');
|
|
1821
|
+
}
|
|
1788
1822
|
}
|
|
1789
1823
|
if (data.event === 'aborted') {
|
|
1790
1824
|
StepsAPI.setStepIndex(StepList.Aborted);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"package": { "name": "node-red-contrib-zwave-js", "version": "6.5.4" },
|
|
3
|
+
"P01": { "test": true, "license": "MIT" },
|
|
4
|
+
"P03": { "test": true },
|
|
5
|
+
"P04": { "test": true },
|
|
6
|
+
"P08": { "test": true },
|
|
7
|
+
"P05": { "test": true },
|
|
8
|
+
"P06": { "test": true, "versions": ["2.2.0"] },
|
|
9
|
+
"P07": { "test": false, "version": ">=12.22.2" },
|
|
10
|
+
"N01": { "test": true },
|
|
11
|
+
"N02": {
|
|
12
|
+
"test": true,
|
|
13
|
+
"nodes": ["zwave-js", "zwave-device", "event-filter", "cmd-factory"]
|
|
14
|
+
},
|
|
15
|
+
"D01": { "test": true, "total": 6 },
|
|
16
|
+
"D02": { "test": true },
|
|
17
|
+
"D03": { "test": true }
|
|
18
|
+
}
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
name: { value: 'ZWave Event Filter' },
|
|
10
10
|
filters: { value: [] },
|
|
11
11
|
outputs: { value: 0 },
|
|
12
|
-
changeDate: { value: undefined }
|
|
12
|
+
changeDate: { value: undefined },
|
|
13
|
+
showStatus: { value: true }
|
|
13
14
|
},
|
|
14
15
|
inputs: 1,
|
|
15
16
|
outputs: 0,
|
|
@@ -25,7 +26,8 @@
|
|
|
25
26
|
},
|
|
26
27
|
outputLabels: function (index) {
|
|
27
28
|
return this.filters[index].name;
|
|
28
|
-
}
|
|
29
|
+
},
|
|
30
|
+
paletteLabel: 'event-filter'
|
|
29
31
|
});
|
|
30
32
|
|
|
31
33
|
function compare(a, b) {
|
|
@@ -257,6 +259,10 @@
|
|
|
257
259
|
<label for="node-input-name" style="width:130px"><i class="fa fa-pencil"></i> Name</label>
|
|
258
260
|
<input type="text" id="node-input-name" placeholder="Filter Name">
|
|
259
261
|
</div>
|
|
262
|
+
<div class="form-row">
|
|
263
|
+
<label for="node-input-showStatus" style="width:130px"><i class="fa fa-pencil"></i> Show Status</label>
|
|
264
|
+
<input type="checkbox" id="node-input-showStatus" />
|
|
265
|
+
</div>
|
|
260
266
|
|
|
261
267
|
<div>
|
|
262
268
|
<ol id="filtersets" style="min-height:450px;min-width:400px"> </ol>
|
package/zwave-js/event-filter.js
CHANGED
|
@@ -5,6 +5,20 @@ module.exports = function (RED) {
|
|
|
5
5
|
RED.nodes.createNode(this, config);
|
|
6
6
|
const node = this;
|
|
7
7
|
|
|
8
|
+
function UpdateStatus(Color, Shape, Text) {
|
|
9
|
+
if (config.showStatus === undefined || config.showStatus) {
|
|
10
|
+
node.status({
|
|
11
|
+
fill: Color,
|
|
12
|
+
shape: Shape,
|
|
13
|
+
text: Text
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
node.status({});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
node.status({});
|
|
21
|
+
|
|
8
22
|
node.on('input', Input);
|
|
9
23
|
|
|
10
24
|
function compare(a, b) {
|
|
@@ -46,11 +60,8 @@ module.exports = function (RED) {
|
|
|
46
60
|
) {
|
|
47
61
|
msg.filter = Filter;
|
|
48
62
|
SendingArray[ArrayIndex] = msg;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
shape: 'dot',
|
|
52
|
-
text: 'Last match: ' + Filter.name
|
|
53
|
-
});
|
|
63
|
+
UpdateStatus('green', 'dot', 'Last match: ' + Filter.name);
|
|
64
|
+
|
|
54
65
|
send(SendingArray);
|
|
55
66
|
Matched = true;
|
|
56
67
|
break;
|
|
@@ -62,11 +73,8 @@ module.exports = function (RED) {
|
|
|
62
73
|
} else {
|
|
63
74
|
msg.filter = Filter;
|
|
64
75
|
SendingArray[ArrayIndex] = msg;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
shape: 'dot',
|
|
68
|
-
text: 'Last match: ' + Filter.name
|
|
69
|
-
});
|
|
76
|
+
UpdateStatus('green', 'dot', 'Last match: ' + Filter.name);
|
|
77
|
+
|
|
70
78
|
Matched = true;
|
|
71
79
|
send(SendingArray);
|
|
72
80
|
break;
|
|
@@ -76,18 +84,10 @@ module.exports = function (RED) {
|
|
|
76
84
|
}
|
|
77
85
|
|
|
78
86
|
if (!Matched) {
|
|
79
|
-
|
|
80
|
-
fill: 'yellow',
|
|
81
|
-
shape: 'dot',
|
|
82
|
-
text: 'No match'
|
|
83
|
-
});
|
|
87
|
+
UpdateStatus('yellow', 'dot', 'No match');
|
|
84
88
|
}
|
|
85
89
|
} else {
|
|
86
|
-
|
|
87
|
-
fill: 'red',
|
|
88
|
-
shape: 'dot',
|
|
89
|
-
text: 'Not a ZWave message'
|
|
90
|
-
});
|
|
90
|
+
UpdateStatus('red', 'dot', 'Not a ZWave message');
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
if (done) {
|
package/zwave-js/ui/server.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const express = require('express');
|
|
2
1
|
const SP = require('serialport');
|
|
3
2
|
const ModulePackage = require('../../package.json');
|
|
4
3
|
const { CommandClasses } = require('@zwave-js/core');
|
|
@@ -244,9 +243,6 @@ module.exports = {
|
|
|
244
243
|
}
|
|
245
244
|
);
|
|
246
245
|
|
|
247
|
-
/* Res */
|
|
248
|
-
RED.httpAdmin.use('/zwave-js/res', express.static(__dirname));
|
|
249
|
-
|
|
250
246
|
// Frimware
|
|
251
247
|
RED.httpAdmin.post(
|
|
252
248
|
'/zwave-js/firmwareupdate/:code',
|
|
@@ -284,13 +280,14 @@ module.exports = {
|
|
|
284
280
|
);
|
|
285
281
|
|
|
286
282
|
// Smart Start
|
|
283
|
+
SmartStart.Prep(RED.httpAdmin);
|
|
287
284
|
RED.httpAdmin.get(
|
|
288
285
|
'/zwave-js/smartstart/:Method',
|
|
289
286
|
RED.auth.needsPermission('flows.write'),
|
|
290
287
|
async (req, res) => {
|
|
291
288
|
switch (req.params.Method) {
|
|
292
289
|
case 'startserver':
|
|
293
|
-
SmartStart.Start(SmartStartCallback).then((QRCode) => {
|
|
290
|
+
SmartStart.Start(SmartStartCallback, req).then((QRCode) => {
|
|
294
291
|
res.status(200);
|
|
295
292
|
res.end(QRCode);
|
|
296
293
|
});
|
|
@@ -413,6 +410,13 @@ module.exports = {
|
|
|
413
410
|
});
|
|
414
411
|
});
|
|
415
412
|
|
|
413
|
+
_Context.controller.on('exclusion stopped', () => {
|
|
414
|
+
_RED.comms.publish(`/zwave-js/cmd`, {
|
|
415
|
+
type: 'node-inclusion-step',
|
|
416
|
+
event: 'exclusion stopped'
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
|
|
416
420
|
_Context.controller.on('node added', (N, IR) => {
|
|
417
421
|
WireNodeEvents(N);
|
|
418
422
|
_RED.comms.publish(`/zwave-js/cmd`, {
|
|
@@ -1,60 +1,55 @@
|
|
|
1
|
-
const express = require('express');
|
|
2
|
-
const https = require('https');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const ip = require('ip');
|
|
6
|
-
|
|
7
|
-
let App;
|
|
8
|
-
let Server;
|
|
9
1
|
let _Callback;
|
|
2
|
+
let _Enabled = false;
|
|
10
3
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
const Prep = (HTTPAdmin) => {
|
|
5
|
+
HTTPAdmin.get('/zwave-js/smartstart-event/started', SendStarted);
|
|
6
|
+
HTTPAdmin.get('/zwave-js/smartstart-event/code/:Code', ParseCode);
|
|
14
7
|
};
|
|
15
8
|
|
|
16
|
-
const
|
|
9
|
+
const CheckStatus = (res) => {
|
|
10
|
+
if (_Enabled) {
|
|
11
|
+
return true;
|
|
12
|
+
} else {
|
|
13
|
+
res.sendStatus(503).end();
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const Start = (Callback, Req) => {
|
|
17
19
|
_Callback = Callback;
|
|
18
|
-
|
|
19
|
-
App.use(express.static(path.join(__dirname, 'ui')));
|
|
20
|
-
App.get('/event.started', SendStarted);
|
|
21
|
-
App.get('/event.code/:Code', ParseCode);
|
|
22
|
-
Server = https.createServer(Options, App);
|
|
20
|
+
_Enabled = true;
|
|
23
21
|
|
|
22
|
+
const Secure = Req.connection.encrypted !== undefined;
|
|
23
|
+
const Prot = Secure ? 'https://' : 'http://';
|
|
24
24
|
return new Promise((resolve) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
ip.address() +
|
|
29
|
-
':' +
|
|
30
|
-
Server.address().port +
|
|
31
|
-
'/Scanchoice.html'
|
|
32
|
-
);
|
|
33
|
-
});
|
|
25
|
+
resolve(
|
|
26
|
+
`${Prot}${Req.headers.host}/resources/node-red-contrib-zwave-js/SmartStart/Scanchoice.html`
|
|
27
|
+
);
|
|
34
28
|
});
|
|
35
29
|
};
|
|
36
30
|
|
|
37
31
|
function SendStarted(req, res) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
if (CheckStatus(res)) {
|
|
33
|
+
_Callback('Started');
|
|
34
|
+
res.status(200);
|
|
35
|
+
res.end();
|
|
36
|
+
}
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
function ParseCode(req, res) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
if (CheckStatus(res)) {
|
|
41
|
+
const Result = _Callback('Code', req.params.Code);
|
|
42
|
+
res.status(200);
|
|
43
|
+
res.end(Result.toString());
|
|
44
|
+
}
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
const Stop = () => {
|
|
50
|
-
|
|
51
|
-
Server.close();
|
|
52
|
-
Server = undefined;
|
|
53
|
-
App = undefined;
|
|
54
|
-
}
|
|
48
|
+
_Enabled = false;
|
|
55
49
|
};
|
|
56
50
|
|
|
57
51
|
module.exports = {
|
|
58
52
|
Start: Start,
|
|
59
|
-
Stop: Stop
|
|
53
|
+
Stop: Stop,
|
|
54
|
+
Prep: Prep
|
|
60
55
|
};
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
messageInterval: { value: 250 },
|
|
12
12
|
isolated: { value: false },
|
|
13
13
|
outputs: { value: 1 },
|
|
14
|
-
inputs: { value: 1 }
|
|
14
|
+
inputs: { value: 1 },
|
|
15
|
+
showStatus: { value: true }
|
|
15
16
|
},
|
|
16
17
|
inputs: 1,
|
|
17
18
|
outputs: 1,
|
|
@@ -20,7 +21,8 @@
|
|
|
20
21
|
return this.name;
|
|
21
22
|
},
|
|
22
23
|
oneditprepare: SortUI,
|
|
23
|
-
oneditsave: SetIO
|
|
24
|
+
oneditsave: SetIO,
|
|
25
|
+
paletteLabel: 'zwave-device'
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
function SetIO() {
|
|
@@ -287,6 +289,10 @@
|
|
|
287
289
|
<select id="node-input-filteredNodeId">
|
|
288
290
|
</select>
|
|
289
291
|
</div>
|
|
292
|
+
<div class="form-row">
|
|
293
|
+
<label for="node-input-showStatus" style="width:130px"><i class="fa fa-pencil"></i> Show Status</label>
|
|
294
|
+
<input type="checkbox" id="node-input-showStatus" />
|
|
295
|
+
</div>
|
|
290
296
|
<div class="form-tips" id="node-tip">
|
|
291
297
|
Note: This node works in conjunction with the main Z-Wave JS Controller node, therefore, ensure the controller node is in one of your flows and in a deployed state before using this node.
|
|
292
298
|
</div>
|
package/zwave-js/zwave-device.js
CHANGED
|
@@ -6,6 +6,18 @@ module.exports = function (RED) {
|
|
|
6
6
|
RED.nodes.createNode(this, config);
|
|
7
7
|
const RedNode = this;
|
|
8
8
|
|
|
9
|
+
function UpdateStatus(Color, Shape, Text) {
|
|
10
|
+
if (config.showStatus === undefined || config.showStatus) {
|
|
11
|
+
RedNode.status({
|
|
12
|
+
fill: Color,
|
|
13
|
+
shape: Shape,
|
|
14
|
+
text: Text
|
|
15
|
+
});
|
|
16
|
+
} else {
|
|
17
|
+
RedNode.status({});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
9
21
|
const LimiterSettings = {
|
|
10
22
|
tokensPerInterval: 1,
|
|
11
23
|
interval: 250
|
|
@@ -73,18 +85,10 @@ module.exports = function (RED) {
|
|
|
73
85
|
}
|
|
74
86
|
if (config.multicast) {
|
|
75
87
|
DeviceMode = 'Multicast';
|
|
76
|
-
|
|
77
|
-
fill: 'green',
|
|
78
|
-
shape: 'dot',
|
|
79
|
-
text: 'Mode: Mulitcast'
|
|
80
|
-
});
|
|
88
|
+
UpdateStatus('green', 'dot', 'Mode: Multicast');
|
|
81
89
|
} else {
|
|
82
90
|
DeviceMode = 'Multiple';
|
|
83
|
-
|
|
84
|
-
fill: 'green',
|
|
85
|
-
shape: 'dot',
|
|
86
|
-
text: 'Mode: Multiple'
|
|
87
|
-
});
|
|
91
|
+
UpdateStatus('green', 'dot', 'Mode: Multiple');
|
|
88
92
|
}
|
|
89
93
|
} else if (!isNaN(config.filteredNodeId)) {
|
|
90
94
|
DeviceMode = 'Specific';
|
|
@@ -94,24 +98,20 @@ module.exports = function (RED) {
|
|
|
94
98
|
processEventMessage
|
|
95
99
|
);
|
|
96
100
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
UpdateStatus(
|
|
102
|
+
'green',
|
|
103
|
+
'dot',
|
|
104
|
+
`Mode: Specific Node (${config.filteredNodeId})`
|
|
105
|
+
);
|
|
102
106
|
} else if (config.filteredNodeId === 'All') {
|
|
103
107
|
DeviceMode = 'All';
|
|
104
108
|
if (Out) {
|
|
105
109
|
NodeEventEmitter.on('zwjs:node:event:all', processEventMessage);
|
|
106
110
|
}
|
|
107
|
-
|
|
111
|
+
UpdateStatus('green', 'dot', 'Mode: All Nodes');
|
|
108
112
|
} else if (config.filteredNodeId === 'AS') {
|
|
109
113
|
DeviceMode = 'AS';
|
|
110
|
-
|
|
111
|
-
fill: 'green',
|
|
112
|
-
shape: 'dot',
|
|
113
|
-
text: 'Mode: As Specifed (Waiting)'
|
|
114
|
-
});
|
|
114
|
+
UpdateStatus('yellow', 'dot', 'Mode: As Specified (Waiting)');
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
function processEventMessage(MSG) {
|
|
@@ -157,11 +157,7 @@ module.exports = function (RED) {
|
|
|
157
157
|
);
|
|
158
158
|
}
|
|
159
159
|
DynamicIDListener = Node;
|
|
160
|
-
|
|
161
|
-
fill: 'green',
|
|
162
|
-
shape: 'dot',
|
|
163
|
-
text: `Mode: As Specifed (${Node})`
|
|
164
|
-
});
|
|
160
|
+
UpdateStatus('green', 'dot', `Mode: As Specified (${Node})`);
|
|
165
161
|
}
|
|
166
162
|
break;
|
|
167
163
|
|
|
@@ -200,21 +196,14 @@ module.exports = function (RED) {
|
|
|
200
196
|
|
|
201
197
|
if (DeviceMode === 'Multiple' && msg.payload.node === undefined) {
|
|
202
198
|
for (let i = 0; i < config.filteredNodeId.length; i++) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
shape: 'dot',
|
|
206
|
-
text: 'Mode: Multiple (Throttling)'
|
|
207
|
-
});
|
|
199
|
+
UpdateStatus('yellow', 'dot', 'Mode: Multiple (Throttling)');
|
|
200
|
+
|
|
208
201
|
await RateLimiter.removeTokens(1);
|
|
209
202
|
const TR = LD.cloneDeep(msg);
|
|
210
203
|
TR.payload.node = parseInt(config.filteredNodeId[i]);
|
|
211
204
|
NodeEventEmitter.emit('zwjs:node:command', TR);
|
|
212
205
|
}
|
|
213
|
-
|
|
214
|
-
fill: 'green',
|
|
215
|
-
shape: 'dot',
|
|
216
|
-
text: 'Mode: Multiple'
|
|
217
|
-
});
|
|
206
|
+
UpdateStatus('green', 'dot', 'Mode: Multiple');
|
|
218
207
|
} else {
|
|
219
208
|
NodeEventEmitter.emit('zwjs:node:command', msg);
|
|
220
209
|
}
|
package/zwave-js/zwave-js.html
CHANGED
|
@@ -1,15 +1,36 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script
|
|
2
|
+
type="text/javascript"
|
|
3
|
+
src="resources/node-red-contrib-zwave-js/UITab/handlebars.min.js"
|
|
4
|
+
></script>
|
|
2
5
|
<script>
|
|
3
6
|
Handlebars.registerHelper('inc', function (value, options) {
|
|
4
7
|
return parseInt(value) + 1;
|
|
5
8
|
});
|
|
6
9
|
</script>
|
|
7
|
-
<script
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<
|
|
12
|
-
|
|
10
|
+
<script
|
|
11
|
+
type="text/javascript"
|
|
12
|
+
src="resources/node-red-contrib-zwave-js/UITab/client.js"
|
|
13
|
+
></script>
|
|
14
|
+
<script
|
|
15
|
+
type="text/javascript"
|
|
16
|
+
src="resources/node-red-contrib-zwave-js/UITab/vis-network.min.js"
|
|
17
|
+
></script>
|
|
18
|
+
<script
|
|
19
|
+
type="text/javascript"
|
|
20
|
+
src="resources/node-red-contrib-zwave-js/UITab/jquery-steps.min.js"
|
|
21
|
+
></script>
|
|
22
|
+
<script
|
|
23
|
+
type="text/javascript"
|
|
24
|
+
src="resources/node-red-contrib-zwave-js/UITab/qrcode.min.js"
|
|
25
|
+
></script>
|
|
26
|
+
<link
|
|
27
|
+
rel="stylesheet"
|
|
28
|
+
href="resources/node-red-contrib-zwave-js/UITab/styles.css"
|
|
29
|
+
/>
|
|
30
|
+
<link
|
|
31
|
+
rel="stylesheet"
|
|
32
|
+
href="resources/node-red-contrib-zwave-js/UITab/jquery-steps.css"
|
|
33
|
+
/>
|
|
13
34
|
|
|
14
35
|
<!-- templates used for modal dialogs *-->
|
|
15
36
|
|
|
@@ -108,6 +129,7 @@
|
|
|
108
129
|
<li data-step-target='SmartStartList'></li>
|
|
109
130
|
<li data-step-target='SmartStartListEdit'></li>
|
|
110
131
|
<li data-step-target='SmartStartDone'></li>
|
|
132
|
+
<li data-step-target='RemoveDoneUnconfirmed'></li>
|
|
111
133
|
</ul>
|
|
112
134
|
<div class='step-content' style='border: none;'>
|
|
113
135
|
<!-- Secuity Mode-->
|
|
@@ -205,7 +227,10 @@
|
|
|
205
227
|
<table style='width: 100%; height: 290px;'>
|
|
206
228
|
<tr>
|
|
207
229
|
<td style='text-align: center;'>
|
|
208
|
-
<img
|
|
230
|
+
<img
|
|
231
|
+
src='resources/node-red-contrib-zwave-js/UITab/Include.png'
|
|
232
|
+
width='200px'
|
|
233
|
+
/>
|
|
209
234
|
</td>
|
|
210
235
|
</tr>
|
|
211
236
|
<tr>
|
|
@@ -229,7 +254,10 @@
|
|
|
229
254
|
<table style='width: 100%; height: 290px;'>
|
|
230
255
|
<tr>
|
|
231
256
|
<td style='text-align: center;'>
|
|
232
|
-
<img
|
|
257
|
+
<img
|
|
258
|
+
src='resources/node-red-contrib-zwave-js/UITab/Exclude.png'
|
|
259
|
+
width='200px'
|
|
260
|
+
/>
|
|
233
261
|
</td>
|
|
234
262
|
</tr>
|
|
235
263
|
<tr>
|
|
@@ -387,7 +415,10 @@
|
|
|
387
415
|
<table style='width: 100%; height: 290px;'>
|
|
388
416
|
<tr>
|
|
389
417
|
<td style='text-align: center;'>
|
|
390
|
-
<img
|
|
418
|
+
<img
|
|
419
|
+
src='resources/node-red-contrib-zwave-js/UITab/NodeAdded.png'
|
|
420
|
+
width='200px'
|
|
421
|
+
/>
|
|
391
422
|
</td>
|
|
392
423
|
</tr>
|
|
393
424
|
<tr>
|
|
@@ -405,7 +436,10 @@
|
|
|
405
436
|
<table style='width: 100%; height: 290px;'>
|
|
406
437
|
<tr>
|
|
407
438
|
<td style='text-align: center;'>
|
|
408
|
-
<img
|
|
439
|
+
<img
|
|
440
|
+
src='resources/node-red-contrib-zwave-js/UITab/NodeError.png'
|
|
441
|
+
width='200px'
|
|
442
|
+
/>
|
|
409
443
|
</td>
|
|
410
444
|
</tr>
|
|
411
445
|
<tr>
|
|
@@ -424,7 +458,10 @@
|
|
|
424
458
|
<table style='width: 100%; height: 290px;'>
|
|
425
459
|
<tr>
|
|
426
460
|
<td style='text-align: center;'>
|
|
427
|
-
<img
|
|
461
|
+
<img
|
|
462
|
+
src='resources/node-red-contrib-zwave-js/UITab/NodeRemoved.png'
|
|
463
|
+
width='200px'
|
|
464
|
+
/>
|
|
428
465
|
</td>
|
|
429
466
|
</tr>
|
|
430
467
|
<tr>
|
|
@@ -478,7 +515,10 @@
|
|
|
478
515
|
<table style='width: 100%; height: 290px;'>
|
|
479
516
|
<tr>
|
|
480
517
|
<td style='text-align: center;'>
|
|
481
|
-
<img
|
|
518
|
+
<img
|
|
519
|
+
src='resources/node-red-contrib-zwave-js/UITab/NodeError.png'
|
|
520
|
+
width='200px'
|
|
521
|
+
/>
|
|
482
522
|
</td>
|
|
483
523
|
</tr>
|
|
484
524
|
<tr>
|
|
@@ -586,6 +626,24 @@
|
|
|
586
626
|
broadcast has been recieved, the device should get interviewed and
|
|
587
627
|
added to your network.</p>
|
|
588
628
|
</div>
|
|
629
|
+
<!--Remove Done Uncofirmed-->
|
|
630
|
+
<div class='step-tab-panel' data-step='RemoveDoneUnconfirmed'>
|
|
631
|
+
<br />
|
|
632
|
+
<table style='width: 100%; height: 290px;'>
|
|
633
|
+
<tr>
|
|
634
|
+
<td style='text-align: center;'>
|
|
635
|
+
<img
|
|
636
|
+
src='resources/node-red-contrib-zwave-js/UITab/NodeError.png'
|
|
637
|
+
width='200px'
|
|
638
|
+
/>
|
|
639
|
+
</td>
|
|
640
|
+
</tr>
|
|
641
|
+
<tr>
|
|
642
|
+
<td style='text-align: center;'>Node exclusion has finished.<br />No
|
|
643
|
+
nodes were removed from this network.</td>
|
|
644
|
+
</tr>
|
|
645
|
+
</table>
|
|
646
|
+
</div>
|
|
589
647
|
</div>
|
|
590
648
|
</div>
|
|
591
649
|
</script>
|
|
@@ -856,7 +914,8 @@
|
|
|
856
914
|
customConfigPath: { value: undefined },
|
|
857
915
|
intvwUserCodes: { value: false },
|
|
858
916
|
softResetUSB: { value: false },
|
|
859
|
-
outputs: { value: 1 }
|
|
917
|
+
outputs: { value: 1 },
|
|
918
|
+
disableOptimisticValueUpdate: { value: false }
|
|
860
919
|
},
|
|
861
920
|
inputs: 1,
|
|
862
921
|
outputs: 1,
|
|
@@ -866,7 +925,8 @@
|
|
|
866
925
|
},
|
|
867
926
|
onpaletteadd: ZwaveJsUI.init,
|
|
868
927
|
oneditprepare: SortUI,
|
|
869
|
-
oneditsave: SortIO
|
|
928
|
+
oneditsave: SortIO,
|
|
929
|
+
paletteLabel: 'zwave-js'
|
|
870
930
|
});
|
|
871
931
|
|
|
872
932
|
function SortIO() {
|
|
@@ -1058,6 +1118,10 @@
|
|
|
1058
1118
|
<option value="fast">Fast</option>
|
|
1059
1119
|
</select>
|
|
1060
1120
|
</div>
|
|
1121
|
+
<div class="form-row">
|
|
1122
|
+
<label for="node-input-disableOptimisticValueUpdate" style="width:130px"><i class="fa fa-pencil"></i> No Optimistic</label>
|
|
1123
|
+
<input type="checkbox" id="node-input-disableOptimisticValueUpdate">
|
|
1124
|
+
</div>
|
|
1061
1125
|
<div class="form-row">
|
|
1062
1126
|
<label for="node-input-intvwUserCodes" style="width:130px"><i class="fa fa-pencil"></i> Lock Code Intvw</label>
|
|
1063
1127
|
<input type="checkbox" id="node-input-intvwUserCodes">
|
package/zwave-js/zwave-js.js
CHANGED
|
@@ -221,6 +221,41 @@ module.exports = function (RED) {
|
|
|
221
221
|
DriverOptions.interview = {
|
|
222
222
|
queryAllUserCodes: true
|
|
223
223
|
};
|
|
224
|
+
} else {
|
|
225
|
+
Log(
|
|
226
|
+
'debug',
|
|
227
|
+
'NDERED',
|
|
228
|
+
undefined,
|
|
229
|
+
'[options] [interview.queryAllUserCodes]',
|
|
230
|
+
'Disabled'
|
|
231
|
+
);
|
|
232
|
+
DriverOptions.interview = {
|
|
233
|
+
queryAllUserCodes: false
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Optimsitic Value Updates
|
|
238
|
+
if (
|
|
239
|
+
config.disableOptimisticValueUpdate !== undefined &&
|
|
240
|
+
config.disableOptimisticValueUpdate
|
|
241
|
+
) {
|
|
242
|
+
Log(
|
|
243
|
+
'debug',
|
|
244
|
+
'NDERED',
|
|
245
|
+
undefined,
|
|
246
|
+
'[options] [disableOptimisticValueUpdate]',
|
|
247
|
+
'Enabled'
|
|
248
|
+
);
|
|
249
|
+
DriverOptions.disableOptimisticValueUpdate = true;
|
|
250
|
+
} else {
|
|
251
|
+
Log(
|
|
252
|
+
'debug',
|
|
253
|
+
'NDERED',
|
|
254
|
+
undefined,
|
|
255
|
+
'[options] [disableOptimisticValueUpdate]',
|
|
256
|
+
'Disabled'
|
|
257
|
+
);
|
|
258
|
+
DriverOptions.disableOptimisticValueUpdate = false;
|
|
224
259
|
}
|
|
225
260
|
|
|
226
261
|
// Soft Reset
|
|
@@ -440,21 +475,25 @@ module.exports = function (RED) {
|
|
|
440
475
|
'Cleaning up...'
|
|
441
476
|
);
|
|
442
477
|
UI.unregister();
|
|
443
|
-
Driver.destroy()
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
478
|
+
Driver.destroy().then(() => {
|
|
479
|
+
NodeEventEmitter.removeListener(
|
|
480
|
+
'zwjs:node:command',
|
|
481
|
+
processMessageEvent
|
|
482
|
+
);
|
|
483
|
+
if (Logger !== undefined) {
|
|
484
|
+
Logger.clear();
|
|
485
|
+
Logger = undefined;
|
|
486
|
+
}
|
|
487
|
+
if (Pin2Transport !== undefined) {
|
|
488
|
+
Pin2Transport = undefined;
|
|
489
|
+
}
|
|
490
|
+
if (FileTransport !== undefined) {
|
|
491
|
+
FileTransport = undefined;
|
|
492
|
+
}
|
|
493
|
+
if (done) {
|
|
494
|
+
done();
|
|
495
|
+
}
|
|
496
|
+
});
|
|
458
497
|
});
|
|
459
498
|
|
|
460
499
|
RedNode.on('input', Input);
|
|
Binary file
|