@hurenkam/hue-services 0.6.0
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/.github/workflows/node.js.yml +31 -0
- package/.nyc_output/ecb1b16f-015c-458b-96d5-32cb9569c1e8.json +1 -0
- package/.nyc_output/processinfo/ecb1b16f-015c-458b-96d5-32cb9569c1e8.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -0
- package/.vscode/settings.json +15 -0
- package/.vscode/sftp.json +11 -0
- package/LICENSE +201 -0
- package/README.md +340 -0
- package/Todo.txt +18 -0
- package/coverage/BaseNode.js.html +379 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +101 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +161 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +196 -0
- package/coverage/lcov-report/src/RestApi.js.html +499 -0
- package/coverage/lcov-report/src/all.js.html +208 -0
- package/coverage/lcov-report/src/clip/ClipApi.js.html +1096 -0
- package/coverage/lcov-report/src/clip/Resource.js.html +481 -0
- package/coverage/lcov-report/src/clip/index.html +131 -0
- package/coverage/lcov-report/src/debug.js.html +253 -0
- package/coverage/lcov-report/src/files.js.html +118 -0
- package/coverage/lcov-report/src/index.html +161 -0
- package/coverage/lcov-report/src/nodes/BaseNode.js.html +381 -0
- package/coverage/lcov-report/src/nodes/BridgeConfigNode.js.html +817 -0
- package/coverage/lcov-report/src/nodes/ButtonNode.js.html +241 -0
- package/coverage/lcov-report/src/nodes/DevicePowerNode.js.html +199 -0
- package/coverage/lcov-report/src/nodes/GroupedLightNode.js.html +226 -0
- package/coverage/lcov-report/src/nodes/LightLevelNode.js.html +205 -0
- package/coverage/lcov-report/src/nodes/LightNode.js.html +226 -0
- package/coverage/lcov-report/src/nodes/MotionNode.js.html +205 -0
- package/coverage/lcov-report/src/nodes/RelativeRotaryNode.js.html +253 -0
- package/coverage/lcov-report/src/nodes/ResourceNode.js.html +388 -0
- package/coverage/lcov-report/src/nodes/SceneNode.js.html +124 -0
- package/coverage/lcov-report/src/nodes/ServiceNode.js.html +124 -0
- package/coverage/lcov-report/src/nodes/TemperatureNode.js.html +205 -0
- package/coverage/lcov-report/src/nodes/ZigbeeConnectivityNode.js.html +199 -0
- package/coverage/lcov-report/src/nodes/index.html +311 -0
- package/coverage/lcov-report/src/ui/BaseUI.js.html +484 -0
- package/coverage/lcov-report/src/ui/BridgeConfigUI.js.html +475 -0
- package/coverage/lcov-report/src/ui/ButtonUI.js.html +166 -0
- package/coverage/lcov-report/src/ui/DevicePowerUI.js.html +166 -0
- package/coverage/lcov-report/src/ui/GroupedLightUI.js.html +178 -0
- package/coverage/lcov-report/src/ui/LightLevelUI.js.html +166 -0
- package/coverage/lcov-report/src/ui/LightUI.js.html +178 -0
- package/coverage/lcov-report/src/ui/MotionUI.js.html +166 -0
- package/coverage/lcov-report/src/ui/RelativeRotaryUI.js.html +166 -0
- package/coverage/lcov-report/src/ui/ResourceUI.js.html +511 -0
- package/coverage/lcov-report/src/ui/SceneUI.js.html +160 -0
- package/coverage/lcov-report/src/ui/ServiceUI.js.html +868 -0
- package/coverage/lcov-report/src/ui/TemperatureUI.js.html +166 -0
- package/coverage/lcov-report/src/ui/ZigbeeConnectivityUI.js.html +166 -0
- package/coverage/lcov-report/src/ui/index.html +311 -0
- package/coverage/lcov.info +2217 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/coverage/src/RestApi.js.html +499 -0
- package/coverage/src/all.js.html +208 -0
- package/coverage/src/clip/ClipApi.js.html +1183 -0
- package/coverage/src/clip/Resource.js.html +481 -0
- package/coverage/src/clip/index.html +131 -0
- package/coverage/src/debug.js.html +253 -0
- package/coverage/src/files.js.html +118 -0
- package/coverage/src/index.html +116 -0
- package/coverage/src/nodes/BaseNode.js.html +379 -0
- package/coverage/src/nodes/BridgeConfigNode.js.html +517 -0
- package/coverage/src/nodes/ButtonNode.js.html +238 -0
- package/coverage/src/nodes/DevicePowerNode.js.html +196 -0
- package/coverage/src/nodes/GroupedLightNode.js.html +223 -0
- package/coverage/src/nodes/LightLevelNode.js.html +202 -0
- package/coverage/src/nodes/LightNode.js.html +223 -0
- package/coverage/src/nodes/MotionNode.js.html +202 -0
- package/coverage/src/nodes/RelativeRotaryNode.js.html +250 -0
- package/coverage/src/nodes/ResourceNode.js.html +373 -0
- package/coverage/src/nodes/SceneNode.js.html +124 -0
- package/coverage/src/nodes/ServiceNode.js.html +124 -0
- package/coverage/src/nodes/TemperatureNode.js.html +202 -0
- package/coverage/src/nodes/ZigbeeConnectivityNode.js.html +199 -0
- package/coverage/src/nodes/index.html +311 -0
- package/coverage/src/ui/BaseUI.js.html +484 -0
- package/coverage/src/ui/BridgeConfigUI.js.html +475 -0
- package/coverage/src/ui/ButtonUI.js.html +166 -0
- package/coverage/src/ui/DevicePowerUI.js.html +166 -0
- package/coverage/src/ui/GroupedLightUI.js.html +178 -0
- package/coverage/src/ui/LightLevelUI.js.html +166 -0
- package/coverage/src/ui/LightUI.js.html +178 -0
- package/coverage/src/ui/MotionUI.js.html +166 -0
- package/coverage/src/ui/RelativeRotaryUI.js.html +166 -0
- package/coverage/src/ui/ResourceUI.js.html +511 -0
- package/coverage/src/ui/SceneUI.js.html +160 -0
- package/coverage/src/ui/ServiceUI.js.html +868 -0
- package/coverage/src/ui/TemperatureUI.js.html +166 -0
- package/coverage/src/ui/ZigbeeConnectivityUI.js.html +166 -0
- package/coverage/src/ui/index.html +311 -0
- package/examples/flows.json +959 -0
- package/package.json +53 -0
- package/screenshots/Screenshot from 2022-11-29 00-29-23.png +0 -0
- package/screenshots/Screenshot from 2022-11-29 00-30-16.png +0 -0
- package/screenshots/Screenshot from 2022-11-29 00-30-58.png +0 -0
- package/screenshots/Screenshot from 2022-11-29 00-31-29.png +0 -0
- package/src/RestApi.js +138 -0
- package/src/all.html +52 -0
- package/src/all.js +42 -0
- package/src/clip/ClipApi.js +367 -0
- package/src/clip/Resource.js +132 -0
- package/src/debug.js +56 -0
- package/src/files.js +12 -0
- package/src/hue.js +98 -0
- package/src/nodes/BaseNode.js +98 -0
- package/src/nodes/BridgeConfigNode.js +144 -0
- package/src/nodes/ButtonNode.js +51 -0
- package/src/nodes/DevicePowerNode.js +37 -0
- package/src/nodes/GroupedLightNode.js +46 -0
- package/src/nodes/LightLevelNode.js +39 -0
- package/src/nodes/LightNode.js +46 -0
- package/src/nodes/MotionNode.js +39 -0
- package/src/nodes/RelativeRotaryNode.js +55 -0
- package/src/nodes/ResourceNode.js +95 -0
- package/src/nodes/SceneNode.js +13 -0
- package/src/nodes/ServiceNode.js +13 -0
- package/src/nodes/TemperatureNode.js +39 -0
- package/src/nodes/ZigbeeConnectivityNode.js +38 -0
- package/src/ui/BaseUI.js +133 -0
- package/src/ui/BridgeConfigUI.js +130 -0
- package/src/ui/ButtonUI.js +27 -0
- package/src/ui/DevicePowerUI.js +27 -0
- package/src/ui/GroupedLightUI.js +31 -0
- package/src/ui/LightLevelUI.js +27 -0
- package/src/ui/LightUI.js +31 -0
- package/src/ui/MotionUI.js +27 -0
- package/src/ui/RelativeRotaryUI.js +27 -0
- package/src/ui/ResourceUI.js +142 -0
- package/src/ui/SceneUI.js +25 -0
- package/src/ui/ServiceUI.js +261 -0
- package/src/ui/TemperatureUI.js +27 -0
- package/src/ui/ZigbeeConnectivityUI.js +27 -0
- package/test/BaseNode_spec.js +246 -0
- package/test/BaseUI_spec.js +17 -0
- package/test/BridgeConfigNode_spec.js +184 -0
- package/test/ButtonNode_spec.js +178 -0
- package/test/ClipApi_spec.js +769 -0
- package/test/DevicePowerNode_spec.js +186 -0
- package/test/GroupedLightNode_spec.js +218 -0
- package/test/LightLevelNode_spec.js +154 -0
- package/test/LightNode_spec.js +218 -0
- package/test/MotionNode_spec.js +186 -0
- package/test/RelativeRotataryNode_spec.js +325 -0
- package/test/ResourceNode_spec.js +308 -0
- package/test/Resource_spec.js +392 -0
- package/test/SceneNode_spec.js +33 -0
- package/test/ServiceNode_spec.js +33 -0
- package/test/TemperatureNode_spec.js +153 -0
- package/test/ZigbeeConnectivityNode_spec.js +186 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class LightLevelNode extends ResourceNode {
|
|
4
|
+
#info;
|
|
5
|
+
#trace;
|
|
6
|
+
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super(config);
|
|
9
|
+
this.#info = require('debug')('info').extend('LightLevelNode').extend("["+this.logid()+"]");
|
|
10
|
+
this.#trace = require('debug')('trace').extend('LightLevelNode').extend("["+this.logid()+"]");
|
|
11
|
+
this.#info("constructor()");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
onUpdate(event) {
|
|
15
|
+
this.#trace("onUpdate(",event,")");
|
|
16
|
+
this.updateStatus();
|
|
17
|
+
super.onUpdate(event);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
updateStatus() {
|
|
21
|
+
this.#trace("updateStatus()");
|
|
22
|
+
|
|
23
|
+
var fill = "grey";
|
|
24
|
+
var shape = "dot";
|
|
25
|
+
var text = "";
|
|
26
|
+
|
|
27
|
+
var resource = this.resource();
|
|
28
|
+
if ((resource) && (resource.data()) && (resource.data().light)) {
|
|
29
|
+
if (resource.data().light.light_level!=null) {
|
|
30
|
+
fill = "green";
|
|
31
|
+
text = ""+resource.data().light.light_level;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.status({fill: fill, shape: shape, text: text});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = LightLevelNode;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class LightNode extends ResourceNode {
|
|
4
|
+
#info;
|
|
5
|
+
#trace;
|
|
6
|
+
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super(config);
|
|
9
|
+
this.#info = require('debug')('info').extend('LightNode').extend("["+this.logid()+"]");
|
|
10
|
+
this.#trace = require('debug')('trace').extend('LightNode').extend("["+this.logid()+"]");
|
|
11
|
+
this.#info("constructor()");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
onUpdate(event) {
|
|
15
|
+
this.#trace("onUpdate(",event,")");
|
|
16
|
+
this.updateStatus();
|
|
17
|
+
super.onUpdate(event);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
updateStatus() {
|
|
21
|
+
this.#trace("updateStatus()");
|
|
22
|
+
|
|
23
|
+
var fill = "grey";
|
|
24
|
+
var shape = "dot";
|
|
25
|
+
var text = "";
|
|
26
|
+
|
|
27
|
+
var resource = this.resource();
|
|
28
|
+
if ((resource) && (resource.data()) && (resource.data().on)) {
|
|
29
|
+
if (resource.data().on.on==true) {
|
|
30
|
+
fill = "yellow";
|
|
31
|
+
|
|
32
|
+
if (resource.data().dimming) {
|
|
33
|
+
text = resource.data().dimming.brightness+"%";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
} else if (resource.data().on.on==false) {
|
|
37
|
+
fill = "grey";
|
|
38
|
+
text = "off";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.status({fill: fill, shape: shape, text: text});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = LightNode;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class MotionNode extends ResourceNode {
|
|
4
|
+
#info;
|
|
5
|
+
#trace;
|
|
6
|
+
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super(config);
|
|
9
|
+
this.#info = require('debug')('info').extend('MotionNode').extend("["+this.logid()+"]");
|
|
10
|
+
this.#trace = require('debug')('trace').extend('MotionNode').extend("["+this.logid()+"]");
|
|
11
|
+
this.#info("constructor()");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
onUpdate(event) {
|
|
15
|
+
this.#trace("onUpdate(",event,")")
|
|
16
|
+
this.updateStatus();
|
|
17
|
+
super.onUpdate(event);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
updateStatus() {
|
|
21
|
+
this.#trace("updateStatus()")
|
|
22
|
+
|
|
23
|
+
var fill = "grey";
|
|
24
|
+
var shape = "dot";
|
|
25
|
+
var text = "";
|
|
26
|
+
|
|
27
|
+
var resource = this.resource();
|
|
28
|
+
if ((resource) && (resource.data()) && (resource.data().motion)) {
|
|
29
|
+
if (resource.data().motion.motion!=null) {
|
|
30
|
+
fill = (resource.data().motion.motion==true)? "blue" : "grey";
|
|
31
|
+
text = (resource.data().motion.motion==true)? "motion" : "no motion";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.status({fill: fill, shape: shape, text: text});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = MotionNode;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class RelativeRotaryNode extends ResourceNode {
|
|
4
|
+
#fill;
|
|
5
|
+
|
|
6
|
+
#info;
|
|
7
|
+
#trace;
|
|
8
|
+
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super(config);
|
|
11
|
+
this.#info = require('debug')('info').extend('RelativeRotaryNode').extend("["+this.logid()+"]");
|
|
12
|
+
this.#trace = require('debug')('trace').extend('RelativeRotaryNode').extend("["+this.logid()+"]");
|
|
13
|
+
this.#info("constructor()");
|
|
14
|
+
|
|
15
|
+
this.#fill = "grey";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
onUpdate(event) {
|
|
19
|
+
this.#trace("onUpdate(",event,")");
|
|
20
|
+
this.#fill = "blue";
|
|
21
|
+
|
|
22
|
+
var instance = this;
|
|
23
|
+
setTimeout(()=>{
|
|
24
|
+
instance.#fill = "grey";
|
|
25
|
+
instance.updateStatus();
|
|
26
|
+
},1000);
|
|
27
|
+
|
|
28
|
+
this.updateStatus();
|
|
29
|
+
super.onUpdate(event);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
updateStatus() {
|
|
33
|
+
this.#trace("updateStatus()");
|
|
34
|
+
|
|
35
|
+
var fill = this.#fill;
|
|
36
|
+
var shape = "dot";
|
|
37
|
+
var text = "";
|
|
38
|
+
|
|
39
|
+
var resource = this.resource();
|
|
40
|
+
if ((resource) && (resource.data()) && (resource.data().relative_rotary)) {
|
|
41
|
+
if (resource.data().relative_rotary.last_event!=null) {
|
|
42
|
+
var event = resource.data().relative_rotary.last_event;
|
|
43
|
+
text = event.action;
|
|
44
|
+
if (event.rotation) {
|
|
45
|
+
text += (event.rotation.direction == "clock_wise")? " >> " : " << ";
|
|
46
|
+
text += event.rotation.duration + " | " + event.rotation.steps;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.status({fill: fill, shape: shape, text: text});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
module.exports = RelativeRotaryNode;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
BaseNode = require("./BaseNode");
|
|
2
|
+
|
|
3
|
+
const _error = require('debug')('error').extend('ResourceNode');
|
|
4
|
+
const _warn = require('debug')('warn').extend('ResourceNode');
|
|
5
|
+
const _info = require('debug')('info').extend('ResourceNode');
|
|
6
|
+
const _trace = require('debug')('trace').extend('ResourceNode');
|
|
7
|
+
|
|
8
|
+
class ResourceNode extends BaseNode {
|
|
9
|
+
#onUpdate;
|
|
10
|
+
#resource;
|
|
11
|
+
|
|
12
|
+
#error;
|
|
13
|
+
#warn;
|
|
14
|
+
#info;
|
|
15
|
+
#trace;
|
|
16
|
+
|
|
17
|
+
constructor(config) {
|
|
18
|
+
super(config);
|
|
19
|
+
|
|
20
|
+
this.#error = _error.extend("["+this.logid()+"]");
|
|
21
|
+
this.#warn = _warn. extend("["+this.logid()+"]");
|
|
22
|
+
this.#info = _info. extend("["+this.logid()+"]");
|
|
23
|
+
this.#trace = _trace.extend("["+this.logid()+"]");
|
|
24
|
+
|
|
25
|
+
this.#info("constructor()");
|
|
26
|
+
if (this.bridge()) {
|
|
27
|
+
this.bridge().requestStartup(this);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
start(resource) {
|
|
32
|
+
if (resource==null)
|
|
33
|
+
return;
|
|
34
|
+
|
|
35
|
+
this.#info("start()");
|
|
36
|
+
this.#resource = resource;
|
|
37
|
+
|
|
38
|
+
var instance = this;
|
|
39
|
+
this.#onUpdate = function(event) {
|
|
40
|
+
instance.onUpdate(event);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this.resource().on('update',this.#onUpdate);
|
|
44
|
+
this.updateStatus();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
destructor() {
|
|
48
|
+
this.#info("destructor()");
|
|
49
|
+
this.removeAllListeners();
|
|
50
|
+
this.#resource = null;
|
|
51
|
+
super.destructor();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
resource() {
|
|
55
|
+
return this.#resource;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
rid() {
|
|
59
|
+
return this.config.uuid;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
bridge() {
|
|
63
|
+
return BaseNode.nodeAPI.nodes.getNode(this.config.bridge);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
onUpdate(event) {
|
|
67
|
+
this.#trace("onUpdate()");
|
|
68
|
+
this.send({ payload: event });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
onInput(msg) {
|
|
72
|
+
var resource = this.resource();
|
|
73
|
+
if (!resource) {
|
|
74
|
+
this.#trace("onInput(): Resource not found",this.rid());
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (msg.rtypes) {
|
|
78
|
+
if ((resource) && (msg.rtypes.includes(resource.rtype()))) {
|
|
79
|
+
this.#trace("onInput(",msg.payload,")");
|
|
80
|
+
resource.put(msg.payload);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (msg.rids) {
|
|
85
|
+
if ((resource) && (msg.rids.includes(resource.rid()))) {
|
|
86
|
+
this.#trace("onInput(",msg.payload,")");
|
|
87
|
+
resource.put(msg.payload);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
super.onInput(msg);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = ResourceNode;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ServiceNode = require("./ServiceNode");
|
|
2
|
+
|
|
3
|
+
class SceneNode extends ServiceNode {
|
|
4
|
+
#info;
|
|
5
|
+
|
|
6
|
+
constructor(config) {
|
|
7
|
+
super(config,"scene");
|
|
8
|
+
this.#info = require('debug')('info').extend('SceneNode').extend("["+this.logid()+"]");
|
|
9
|
+
this.#info("constructor()");
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = SceneNode;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class ServiceNode extends ResourceNode {
|
|
4
|
+
#info;
|
|
5
|
+
|
|
6
|
+
constructor(config) {
|
|
7
|
+
super(config);
|
|
8
|
+
this.#info = require('debug')('info').extend('ServiceNode').extend("["+this.logid()+"]");
|
|
9
|
+
this.#info("constructor()");
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
module.exports = ServiceNode;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class TemperatureNode extends ResourceNode {
|
|
4
|
+
#info;
|
|
5
|
+
#trace;
|
|
6
|
+
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super(config);
|
|
9
|
+
this.#info = require('debug')('info').extend('TemperatureNode').extend("["+this.logid()+"]");
|
|
10
|
+
this.#trace = require('debug')('trace').extend('TemperatureNode').extend("["+this.logid()+"]");
|
|
11
|
+
this.#info("constructor()");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
onUpdate(event) {
|
|
15
|
+
this.#trace("onUpdate(",event,")");
|
|
16
|
+
this.updateStatus();
|
|
17
|
+
super.onUpdate(event);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
updateStatus() {
|
|
21
|
+
this.#trace("updateStatus()");
|
|
22
|
+
|
|
23
|
+
var fill = "grey";
|
|
24
|
+
var shape = "dot";
|
|
25
|
+
var text = "";
|
|
26
|
+
|
|
27
|
+
var resource = this.resource();
|
|
28
|
+
if ((resource) && (resource.data()) && (resource.data().temperature)) {
|
|
29
|
+
if (resource.data().temperature.temperature!=null) {
|
|
30
|
+
fill = "green";
|
|
31
|
+
text = ""+resource.data().temperature.temperature+"c";
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
this.status({fill: fill, shape: shape, text: text});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = TemperatureNode;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class ZigbeeConnectivityNode extends ResourceNode {
|
|
4
|
+
#info;
|
|
5
|
+
#trace;
|
|
6
|
+
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super(config);
|
|
9
|
+
this.#info = require('debug')('info').extend('ZigbeeConnectivityNode').extend("["+this.logid()+"]");
|
|
10
|
+
this.#trace = require('debug')('trace').extend('ZigbeeConnectivityNode').extend("["+this.logid()+"]");
|
|
11
|
+
this.#info("constructor()");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
onUpdate(event) {
|
|
15
|
+
this.#trace("onUpdate()");
|
|
16
|
+
this.updateStatus();
|
|
17
|
+
super.onUpdate(event);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
updateStatus() {
|
|
21
|
+
this.#trace("updateStatus()");
|
|
22
|
+
super.updateStatus();
|
|
23
|
+
|
|
24
|
+
var fill = "grey";
|
|
25
|
+
var shape = "dot";
|
|
26
|
+
var text = "";
|
|
27
|
+
|
|
28
|
+
var resource = this.resource();
|
|
29
|
+
if ((resource) && (resource.data) && (resource.data().status!=null)) {
|
|
30
|
+
fill = (resource.data().status == "connected")? "green": "red";
|
|
31
|
+
text = resource.data().status;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this.status({fill: fill, shape: shape, text: text});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = ZigbeeConnectivityNode;
|
package/src/ui/BaseUI.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
export class BaseUI {
|
|
2
|
+
#category;
|
|
3
|
+
|
|
4
|
+
constructor(label="Base", category="base") {
|
|
5
|
+
console.log("BaseUI.constructor()");
|
|
6
|
+
this.#category = category;
|
|
7
|
+
|
|
8
|
+
var instance = this;
|
|
9
|
+
this.config = {
|
|
10
|
+
category: category,
|
|
11
|
+
defaults: {
|
|
12
|
+
name: { value: "" },
|
|
13
|
+
inputs: { value: 1 },
|
|
14
|
+
outputs: { value: 1 }
|
|
15
|
+
},
|
|
16
|
+
label: function() {
|
|
17
|
+
return this.name||label;
|
|
18
|
+
},
|
|
19
|
+
paletteLabel: label,
|
|
20
|
+
oneditprepare: function() { instance.onEditPrepare(this) },
|
|
21
|
+
oneditsave: function() { instance.onEditSave(this) },
|
|
22
|
+
oneditcancel: function() { instance.onEditCancel(this) },
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
buildHelp() {
|
|
27
|
+
return {
|
|
28
|
+
"intro": "",
|
|
29
|
+
"Settings": "",
|
|
30
|
+
"Input": "",
|
|
31
|
+
"Outputs": "",
|
|
32
|
+
"Details": ""
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
ui() {
|
|
37
|
+
console.log("BaseUI.ui()");
|
|
38
|
+
var text = "";
|
|
39
|
+
text += this.uiTextInput("name","Name");
|
|
40
|
+
return text;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
uiTextInput(id,label) {
|
|
44
|
+
console.log("BaseUI.uiTextInput("+id+")");
|
|
45
|
+
var prefix = (this.#category=="config")? "node-config-input-" : "node-input-";
|
|
46
|
+
|
|
47
|
+
var item = document.createElement("div");
|
|
48
|
+
item.setAttribute("class","form-row");
|
|
49
|
+
item.setAttribute("id","node-container-" + id);
|
|
50
|
+
item.innerHTML = '\
|
|
51
|
+
<label for="' + prefix + id +'"><i class="fa fa-tag"></i> '+ label +'</label>\
|
|
52
|
+
<input type="text" id="' + prefix + id + '">';
|
|
53
|
+
return item.outerHTML;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
uiNumberInput(id,label) {
|
|
57
|
+
console.log("BaseUI.uiNumberInput("+id+")");
|
|
58
|
+
var prefix = (this.#category=="config")? "node-config-input-" : "node-input-";
|
|
59
|
+
|
|
60
|
+
var item = document.createElement("div");
|
|
61
|
+
item.setAttribute("class","form-row");
|
|
62
|
+
item.setAttribute("id","node-container-" + id);
|
|
63
|
+
item.innerHTML = '\
|
|
64
|
+
<label for="' + prefix + id +'"><i class="fa fa-tag"></i> '+ label +'</label>\
|
|
65
|
+
<input type="number" id="' + prefix + id + '">';
|
|
66
|
+
return item.outerHTML;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
uiCheckboxInput(id,label) {
|
|
70
|
+
console.log("BaseUI.checkboxInput("+id+")");
|
|
71
|
+
var prefix = (this.#category=="config")? "node-config-input-" : "node-input-";
|
|
72
|
+
|
|
73
|
+
var item = document.createElement("div");
|
|
74
|
+
item.setAttribute("class","form-row");
|
|
75
|
+
item.setAttribute("id","node-container-" + id);
|
|
76
|
+
item.innerHTML = '\
|
|
77
|
+
<div style="display: inline-flex; width: calc(100% - 105px)">\
|
|
78
|
+
<div id="input-select-'+ id +'" style="flex-grow: 1;">\
|
|
79
|
+
<input type="checkbox" id="' + prefix + id +'" style="flex: 15px;">\
|
|
80
|
+
</div>\
|
|
81
|
+
<span style="width: 100%; margin-left: 10px;">\
|
|
82
|
+
'+ label +'\
|
|
83
|
+
</span>\
|
|
84
|
+
</div>';
|
|
85
|
+
return item.outerHTML;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
uiSelectInput(id,label) {
|
|
89
|
+
console.log("BaseUI.uiSelectInput("+id+")");
|
|
90
|
+
var prefix = (this.#category=="config")? "node-config-input-" : "node-input-";
|
|
91
|
+
|
|
92
|
+
var item = document.createElement("div");
|
|
93
|
+
item.setAttribute("class","form-row");
|
|
94
|
+
item.setAttribute("id","node-container-" + id);
|
|
95
|
+
item.innerHTML = '\
|
|
96
|
+
<label for="' + prefix + id +'"><i class="fa fa-tag"></i> '+ label +'</label>\
|
|
97
|
+
<div style="display: inline-flex; width: calc(100% - 105px)">\
|
|
98
|
+
<div id="input-select-'+ id +'" style="flex-grow: 1;">\
|
|
99
|
+
<input type="text" id="' + prefix + id +'" style="width: 100%">\
|
|
100
|
+
</div>\
|
|
101
|
+
<button id="input-select-'+ id +'-search" type="button" class="red-ui-button" style="margin-left: 10px;">\
|
|
102
|
+
<i class="fa fa-search"></i>\
|
|
103
|
+
</button>\
|
|
104
|
+
</div>';
|
|
105
|
+
return item.outerHTML;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
manual() {
|
|
109
|
+
var text = "";
|
|
110
|
+
var help = this.buildHelp();
|
|
111
|
+
Object.keys(help).forEach((key)=>{
|
|
112
|
+
if ((help[key]) && (help[key]!="")) {
|
|
113
|
+
if (key != "intro") {
|
|
114
|
+
text += "\n### " + key + "\n";
|
|
115
|
+
}
|
|
116
|
+
text += help[key];
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return text;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
onEditPrepare(config) {
|
|
123
|
+
console.log("BaseUI.onEditPrepare()");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
onEditSave(config) {
|
|
127
|
+
console.log("BaseUI.onEditSave()");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
onEditCancel(config) {
|
|
131
|
+
console.log("BaseUI.onEditCancel()");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { BaseUI } from "./BaseUI.js"
|
|
2
|
+
|
|
3
|
+
export class BridgeConfigUI extends BaseUI {
|
|
4
|
+
constructor() {
|
|
5
|
+
super("BridgeConfig","config");
|
|
6
|
+
console.log("BridgeConfigUI.constructor()");
|
|
7
|
+
|
|
8
|
+
this.config.defaults.ip = { value:"", required: true }
|
|
9
|
+
this.config.defaults.key = { value:"", required: true }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
ui() {
|
|
13
|
+
var text = super.ui();
|
|
14
|
+
text += this.uiSelectInput("ip","IP");
|
|
15
|
+
text += this.uiSelectInput("key","Key");
|
|
16
|
+
return text;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
selectText(id) {
|
|
20
|
+
//console.log("BridgeConfigUI.selectText()");
|
|
21
|
+
|
|
22
|
+
var current = $('#node-config-input-'+id).val();
|
|
23
|
+
$('#input-select-'+id).empty();
|
|
24
|
+
$('#input-select-'+id).append('<input type="text" id="node-config-input-'+id+'" style="width: 100%" value="'+current+'" />');
|
|
25
|
+
|
|
26
|
+
var button = $("#input-select-"+id+"-search");
|
|
27
|
+
var icon = button.find("i");
|
|
28
|
+
icon.removeClass("fa-pencil");
|
|
29
|
+
icon.addClass("fa-search");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
selectIp() {
|
|
33
|
+
//console.log("BridgeConfigUI.selectIp()");
|
|
34
|
+
var current = $('#node-config-input-ip').val();
|
|
35
|
+
var notification = RED.notify("Searching for bridges...", {
|
|
36
|
+
type: "compact", modal: true, fixed: true
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
$.get("/BridgeConfigNode/DiscoverBridges",{})
|
|
40
|
+
.done( function(data) {
|
|
41
|
+
var options = JSON.parse(data);
|
|
42
|
+
|
|
43
|
+
if(options.length <= 0)
|
|
44
|
+
{
|
|
45
|
+
notification.close();
|
|
46
|
+
RED.notify("No options found.", { type: "error" });
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
$("#node-config-input-ip").typedInput({
|
|
51
|
+
types: [
|
|
52
|
+
{
|
|
53
|
+
value: current,
|
|
54
|
+
options: options
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
var button = $("#input-select-ip-search");
|
|
60
|
+
var icon = button.find("i");
|
|
61
|
+
icon.removeClass("fa-search");
|
|
62
|
+
icon.addClass("fa-pencil");
|
|
63
|
+
|
|
64
|
+
// Remove the notification
|
|
65
|
+
notification.close();
|
|
66
|
+
})
|
|
67
|
+
.fail(function()
|
|
68
|
+
{
|
|
69
|
+
console.log("ResourceUI.selectOption(): failed");
|
|
70
|
+
|
|
71
|
+
// Remove the notification
|
|
72
|
+
notification.close();
|
|
73
|
+
RED.notify("unknown error", "error");
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
acquireKey() {
|
|
78
|
+
//console.log("BridgeConfigUI.aquireKey()");
|
|
79
|
+
var ip = $('#node-config-input-ip').val();
|
|
80
|
+
var key = $('#node-config-input-key').val();
|
|
81
|
+
if (!ip) {
|
|
82
|
+
console.log("BridgeConfigUI.acquireKey(): no ip address selected");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
var notification = RED.notify("Press the button on the bridge...", {
|
|
87
|
+
type: "compact", modal: true, fixed: true
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
$.get("/BridgeConfigNode/AcquireApplicationKey",{ ip: ip })
|
|
91
|
+
.done( function(response) {
|
|
92
|
+
var data = JSON.parse(response);
|
|
93
|
+
//console.log("BridgeConfigUI.acquireKey()",data);
|
|
94
|
+
notification.close();
|
|
95
|
+
if (Object.keys(data).includes("key")) {
|
|
96
|
+
$('#node-config-input-key').val(data.key);
|
|
97
|
+
} else {
|
|
98
|
+
RED.notify(data.error.description, "error");
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
.fail(function()
|
|
102
|
+
{
|
|
103
|
+
notification.close();
|
|
104
|
+
RED.notify("unknown error", "error");
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
onEditPrepare(config) {
|
|
109
|
+
//console.log("BridgeConfigUI.onEditPrepare()");
|
|
110
|
+
var instance = this;
|
|
111
|
+
|
|
112
|
+
$('#input-select-ip-search').click(function()
|
|
113
|
+
{
|
|
114
|
+
if($('#input-select-ip').find(".red-ui-typedInput-container").length > 0) {
|
|
115
|
+
instance.selectText("ip");
|
|
116
|
+
} else {
|
|
117
|
+
instance.selectIp();
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
$('#input-select-key-search').click(function()
|
|
122
|
+
{
|
|
123
|
+
if($('#input-select-key').find(".red-ui-typedInput-container").length > 0) {
|
|
124
|
+
instance.selectText("key");
|
|
125
|
+
} else {
|
|
126
|
+
instance.acquireKey();
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ServiceUI } from "./ServiceUI.js"
|
|
2
|
+
|
|
3
|
+
export class ButtonUI extends ServiceUI {
|
|
4
|
+
constructor() {
|
|
5
|
+
super("Button","hue services","button");
|
|
6
|
+
console.log("ButtonUI.constructor()");
|
|
7
|
+
|
|
8
|
+
this.config.color = "#B0FFE0";
|
|
9
|
+
this.config.icon = "font-awesome/fa-circle";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
buildHelp() {
|
|
13
|
+
var help = super.buildHelp();
|
|
14
|
+
help["Outputs"] += "\
|
|
15
|
+
The Button node only has one output. It will listen to events for the specified service \
|
|
16
|
+
and forward them to the output as `msg.payload` which contains the button events in a \
|
|
17
|
+
JSON format conform the clip v2 specification.\n\n\
|
|
18
|
+
Please see the Hue CLIP API documentation: \n\n\
|
|
19
|
+
https://developers.meethue.com/develop/hue-api-v2";
|
|
20
|
+
return help;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
onEditPrepare(config) {
|
|
24
|
+
super.onEditPrepare(config);
|
|
25
|
+
$('#node-container-rtype').hide();
|
|
26
|
+
}
|
|
27
|
+
}
|