@hurenkam/hue-services 0.6.3 → 0.6.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/README.md +17 -5
- package/attic-bridge-v2-key.txt +2 -0
- package/package.json +1 -1
- package/src/all.html +4 -0
- package/src/all.js +4 -0
- package/src/clip/ClipApi.js +4 -35
- package/src/nodes/CameraMotionNode.js +39 -0
- package/src/nodes/ContactNode.js +52 -0
- package/src/ui/BaseUI.js +1 -3
- package/src/ui/CameraMotionUI.js +27 -0
- package/src/ui/ContactUI.js +27 -0
- package/.nyc_output/b2f41757-3a3e-4377-8622-cddcc882cf32.json +0 -1
- package/.nyc_output/processinfo/b2f41757-3a3e-4377-8622-cddcc882cf32.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/.vscode/settings.json +0 -15
- package/.vscode/sftp.json +0 -11
- package/Todo.txt +0 -18
- package/coverage/BaseNode.js.html +0 -379
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -146
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -161
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/src/RestApi.js.html +0 -499
- package/coverage/lcov-report/src/all.js.html +0 -208
- package/coverage/lcov-report/src/clip/ClipApi.js.html +0 -1096
- package/coverage/lcov-report/src/clip/Resource.js.html +0 -481
- package/coverage/lcov-report/src/clip/index.html +0 -131
- package/coverage/lcov-report/src/debug.js.html +0 -253
- package/coverage/lcov-report/src/files.js.html +0 -118
- package/coverage/lcov-report/src/index.html +0 -161
- package/coverage/lcov-report/src/nodes/BaseNode.js.html +0 -381
- package/coverage/lcov-report/src/nodes/BridgeConfigNode.js.html +0 -817
- package/coverage/lcov-report/src/nodes/ButtonNode.js.html +0 -241
- package/coverage/lcov-report/src/nodes/DevicePowerNode.js.html +0 -199
- package/coverage/lcov-report/src/nodes/GroupedLightNode.js.html +0 -226
- package/coverage/lcov-report/src/nodes/LightLevelNode.js.html +0 -205
- package/coverage/lcov-report/src/nodes/LightNode.js.html +0 -226
- package/coverage/lcov-report/src/nodes/MotionNode.js.html +0 -205
- package/coverage/lcov-report/src/nodes/RelativeRotaryNode.js.html +0 -253
- package/coverage/lcov-report/src/nodes/ResourceNode.js.html +0 -388
- package/coverage/lcov-report/src/nodes/SceneNode.js.html +0 -124
- package/coverage/lcov-report/src/nodes/ServiceNode.js.html +0 -124
- package/coverage/lcov-report/src/nodes/TemperatureNode.js.html +0 -205
- package/coverage/lcov-report/src/nodes/ZigbeeConnectivityNode.js.html +0 -199
- package/coverage/lcov-report/src/nodes/index.html +0 -311
- package/coverage/lcov-report/src/ui/BaseUI.js.html +0 -484
- package/coverage/lcov-report/src/ui/BridgeConfigUI.js.html +0 -475
- package/coverage/lcov-report/src/ui/ButtonUI.js.html +0 -166
- package/coverage/lcov-report/src/ui/DevicePowerUI.js.html +0 -166
- package/coverage/lcov-report/src/ui/GroupedLightUI.js.html +0 -178
- package/coverage/lcov-report/src/ui/LightLevelUI.js.html +0 -166
- package/coverage/lcov-report/src/ui/LightUI.js.html +0 -178
- package/coverage/lcov-report/src/ui/MotionUI.js.html +0 -166
- package/coverage/lcov-report/src/ui/RelativeRotaryUI.js.html +0 -166
- package/coverage/lcov-report/src/ui/ResourceUI.js.html +0 -511
- package/coverage/lcov-report/src/ui/SceneUI.js.html +0 -160
- package/coverage/lcov-report/src/ui/ServiceUI.js.html +0 -868
- package/coverage/lcov-report/src/ui/TemperatureUI.js.html +0 -166
- package/coverage/lcov-report/src/ui/ZigbeeConnectivityUI.js.html +0 -166
- package/coverage/lcov-report/src/ui/index.html +0 -311
- package/coverage/lcov.info +0 -2217
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -196
- package/coverage/src/RestApi.js.html +0 -499
- package/coverage/src/all.js.html +0 -208
- package/coverage/src/clip/ClipApi.js.html +0 -1183
- package/coverage/src/clip/Resource.js.html +0 -481
- package/coverage/src/clip/index.html +0 -131
- package/coverage/src/debug.js.html +0 -253
- package/coverage/src/files.js.html +0 -118
- package/coverage/src/index.html +0 -116
- package/coverage/src/nodes/BaseNode.js.html +0 -379
- package/coverage/src/nodes/BridgeConfigNode.js.html +0 -517
- package/coverage/src/nodes/ButtonNode.js.html +0 -238
- package/coverage/src/nodes/DevicePowerNode.js.html +0 -196
- package/coverage/src/nodes/GroupedLightNode.js.html +0 -223
- package/coverage/src/nodes/LightLevelNode.js.html +0 -202
- package/coverage/src/nodes/LightNode.js.html +0 -223
- package/coverage/src/nodes/MotionNode.js.html +0 -202
- package/coverage/src/nodes/RelativeRotaryNode.js.html +0 -250
- package/coverage/src/nodes/ResourceNode.js.html +0 -409
- package/coverage/src/nodes/SceneNode.js.html +0 -124
- package/coverage/src/nodes/ServiceNode.js.html +0 -124
- package/coverage/src/nodes/TemperatureNode.js.html +0 -202
- package/coverage/src/nodes/ZigbeeConnectivityNode.js.html +0 -199
- package/coverage/src/nodes/index.html +0 -311
- package/coverage/src/ui/BaseUI.js.html +0 -484
- package/coverage/src/ui/BridgeConfigUI.js.html +0 -475
- package/coverage/src/ui/ButtonUI.js.html +0 -166
- package/coverage/src/ui/DevicePowerUI.js.html +0 -166
- package/coverage/src/ui/GroupedLightUI.js.html +0 -178
- package/coverage/src/ui/LightLevelUI.js.html +0 -166
- package/coverage/src/ui/LightUI.js.html +0 -178
- package/coverage/src/ui/MotionUI.js.html +0 -166
- package/coverage/src/ui/RelativeRotaryUI.js.html +0 -166
- package/coverage/src/ui/ResourceUI.js.html +0 -511
- package/coverage/src/ui/SceneUI.js.html +0 -160
- package/coverage/src/ui/ServiceUI.js.html +0 -868
- package/coverage/src/ui/TemperatureUI.js.html +0 -166
- package/coverage/src/ui/ZigbeeConnectivityUI.js.html +0 -166
- package/coverage/src/ui/index.html +0 -311
- package/test/BaseUI_spec.js +0 -17
package/README.md
CHANGED
|
@@ -6,15 +6,20 @@ node-red palette to access hue bridge through clip v2 api
|
|
|
6
6
|
|
|
7
7
|
# Status
|
|
8
8
|
|
|
9
|
-
(Last update:
|
|
9
|
+
(Last update: 2025/12/20)
|
|
10
10
|
This is not complete, but seems to work consistent and reliable for the services I regularly use.
|
|
11
|
-
(motion/temperature/light_level/light/grouped_light/button/relative_rotary/scene).
|
|
11
|
+
(motion/temperature/light_level/light/grouped_light/button/relative_rotary/scene/contact/camera_motion).
|
|
12
12
|
|
|
13
13
|
Unit tests are in place for the server side nodes.
|
|
14
14
|
|
|
15
15
|
Editor/UI functionality is currently not being tested apart from my own use in the editor, so your mileage may vary.
|
|
16
16
|
|
|
17
17
|
# Changelog
|
|
18
|
+
v0.6.5: Added nodes for camera and contact sensor. Improved generic service usability.
|
|
19
|
+
|
|
20
|
+
v0.6.4: Fix checkbox to work with Safari
|
|
21
|
+
|
|
22
|
+
v0.6.3: Added option for nodes to generate a status event on startup (see issue #3)
|
|
18
23
|
|
|
19
24
|
v0.6.2: Fixes issue with services pointing to wrong bridge type and thus unable to add/edit bridge references.
|
|
20
25
|
|
|
@@ -27,6 +32,8 @@ This should address issue #1.
|
|
|
27
32
|
## Services:
|
|
28
33
|
- Generic Service, in case you need some service that is not supported below, you can use this.
|
|
29
34
|
- Button
|
|
35
|
+
- Camera Motion
|
|
36
|
+
- Contact
|
|
30
37
|
- Device Power
|
|
31
38
|
- Grouped Light
|
|
32
39
|
- Light
|
|
@@ -47,14 +54,19 @@ This should address issue #1.
|
|
|
47
54
|
- ~~Upload package to node-red library~~
|
|
48
55
|
- ~~Unit Tests for Clip~~
|
|
49
56
|
- ~~Unit Tests for Nodes~~
|
|
57
|
+
- ~~Contact sensor~~
|
|
58
|
+
- ~~Camera~~
|
|
59
|
+
- Geofencing
|
|
60
|
+
- Smart Scenes
|
|
50
61
|
- Unit Tests for UI
|
|
51
62
|
|
|
63
|
+
|
|
52
64
|
## Postponed until after 0.6.x release
|
|
53
65
|
- Improve 'smart' modes for Switch and Motion devices
|
|
54
|
-
- Improve the generic device node (which allows using as of yet unsupported devices)
|
|
66
|
+
- ~~Improve the generic device node (which allows using as of yet unsupported devices)~~
|
|
55
67
|
- Support more devices
|
|
56
|
-
- smart button (should be easy to do, but i don't have one to test)
|
|
57
|
-
- tap dial switch (should be similar to a lutron aurora, but i don't have one to test)
|
|
68
|
+
- ~~smart button (should be easy to do, but i don't have one to test)~~
|
|
69
|
+
- ~~tap dial switch (should be similar to a lutron aurora, but i don't have one to test)~~
|
|
58
70
|
|
|
59
71
|
# Use
|
|
60
72
|
Using these nodes requires a bit of knowledge on the clip v2 api, as i designed this palette
|
package/package.json
CHANGED
package/src/all.html
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import { BridgeConfigUI } from "/src/ui/BridgeConfigUI.js";
|
|
4
4
|
|
|
5
5
|
import { ButtonUI } from "/src/ui/ButtonUI.js";
|
|
6
|
+
import { CameraMotionUI } from "/src/ui/CameraMotionUI.js";
|
|
7
|
+
import { ContactUI } from "/src/ui/ContactUI.js";
|
|
6
8
|
import { DevicePowerUI } from "/src/ui/DevicePowerUI.js";
|
|
7
9
|
import { GroupedLightUI } from "/src/ui/GroupedLightUI.js";
|
|
8
10
|
import { LightUI } from "/src/ui/LightUI.js";
|
|
@@ -18,6 +20,8 @@
|
|
|
18
20
|
"BridgeConfigNode": BridgeConfigUI,
|
|
19
21
|
|
|
20
22
|
"ButtonNode": ButtonUI,
|
|
23
|
+
"CameraMotionNode": CameraMotionUI,
|
|
24
|
+
"ContactNode": ContactUI,
|
|
21
25
|
"DevicePowerNode": DevicePowerUI,
|
|
22
26
|
"GroupedLightNode": GroupedLightUI,
|
|
23
27
|
"LightNode": LightUI,
|
package/src/all.js
CHANGED
|
@@ -7,6 +7,8 @@ module.exports = function(RED) {
|
|
|
7
7
|
const BridgeConfigNode = require('./nodes/BridgeConfigNode');
|
|
8
8
|
|
|
9
9
|
const ButtonNode = require('./nodes/ButtonNode');
|
|
10
|
+
const CameraMotionNode = require('./nodes/CameraMotionNode');
|
|
11
|
+
const ContactNode = require('./nodes/ContactNode');
|
|
10
12
|
const DevicePowerNode = require('./nodes/DevicePowerNode');
|
|
11
13
|
const GroupedLightNode = require('./nodes/GroupedLightNode');
|
|
12
14
|
const LightNode = require('./nodes/LightNode');
|
|
@@ -23,6 +25,8 @@ module.exports = function(RED) {
|
|
|
23
25
|
"BridgeConfigNode": BridgeConfigNode,
|
|
24
26
|
|
|
25
27
|
"ButtonNode": ButtonNode,
|
|
28
|
+
"CameraMotionNode": CameraMotionNode,
|
|
29
|
+
"ContactNode": ContactNode,
|
|
26
30
|
"DevicePowerNode": DevicePowerNode,
|
|
27
31
|
"GroupedLightNode": GroupedLightNode,
|
|
28
32
|
"LightNode": LightNode,
|
package/src/clip/ClipApi.js
CHANGED
|
@@ -24,33 +24,6 @@ class ClipApi extends events.EventEmitter {
|
|
|
24
24
|
#info;
|
|
25
25
|
#trace;
|
|
26
26
|
|
|
27
|
-
#factory = {
|
|
28
|
-
"behavior_script": Resource,
|
|
29
|
-
"behavior_instance": Resource,
|
|
30
|
-
"bridge": Resource,
|
|
31
|
-
"bridge_home": Resource,
|
|
32
|
-
"button": Resource,
|
|
33
|
-
"device": Resource,
|
|
34
|
-
"device_power": Resource,
|
|
35
|
-
"entertainment": Resource,
|
|
36
|
-
"entertainment_configuration": Resource,
|
|
37
|
-
"geolocation": Resource,
|
|
38
|
-
"grouped_light": Resource,
|
|
39
|
-
"homekit": Resource,
|
|
40
|
-
"light": Resource,
|
|
41
|
-
"light_level": Resource,
|
|
42
|
-
"matter": Resource,
|
|
43
|
-
"motion": Resource,
|
|
44
|
-
"relative_rotary": Resource,
|
|
45
|
-
"room": Resource,
|
|
46
|
-
"scene": Resource,
|
|
47
|
-
"temperature": Resource,
|
|
48
|
-
"zgp_connectivity": Resource,
|
|
49
|
-
"zigbee_connectivity": Resource,
|
|
50
|
-
"zigbee_device_discovery": Resource,
|
|
51
|
-
"zone": Resource
|
|
52
|
-
};
|
|
53
|
-
|
|
54
27
|
constructor(ip,key,name) {
|
|
55
28
|
super();
|
|
56
29
|
|
|
@@ -145,13 +118,9 @@ class ClipApi extends events.EventEmitter {
|
|
|
145
118
|
response.data.forEach((item) => {
|
|
146
119
|
this.#trace("constructor() found resource:", item);
|
|
147
120
|
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this._registerResource(resource);
|
|
152
|
-
}
|
|
153
|
-
} else {
|
|
154
|
-
this.#warn("constructor(): Missing factory for type", item.type);
|
|
121
|
+
if (!this._isResourceRegistered(item.id)) {
|
|
122
|
+
var resource = new Resource(item,this);
|
|
123
|
+
this._registerResource(resource);
|
|
155
124
|
}
|
|
156
125
|
});
|
|
157
126
|
|
|
@@ -364,4 +333,4 @@ class ClipApi extends events.EventEmitter {
|
|
|
364
333
|
}
|
|
365
334
|
}
|
|
366
335
|
|
|
367
|
-
module.exports = ClipApi
|
|
336
|
+
module.exports = ClipApi
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class CameraMotionNode extends ResourceNode {
|
|
4
|
+
#info;
|
|
5
|
+
#trace;
|
|
6
|
+
|
|
7
|
+
constructor(config) {
|
|
8
|
+
super(config);
|
|
9
|
+
this.#info = require('debug')('info').extend('CameraMotionNode').extend("["+this.logid()+"]");
|
|
10
|
+
this.#trace = require('debug')('trace').extend('CameraMotionNode').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 = CameraMotionNode;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
ResourceNode = require("./ResourceNode");
|
|
2
|
+
|
|
3
|
+
class ContactNode extends ResourceNode {
|
|
4
|
+
#fill;
|
|
5
|
+
|
|
6
|
+
#info;
|
|
7
|
+
#trace;
|
|
8
|
+
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super(config);
|
|
11
|
+
|
|
12
|
+
this.#info = require('debug')('info').extend('ContactNode').extend("["+this.logid()+"]");
|
|
13
|
+
this.#trace = require('debug')('trace').extend('ContactNode').extend("["+this.logid()+"]");
|
|
14
|
+
this.#info("constructor()");
|
|
15
|
+
|
|
16
|
+
this.#fill = "grey";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
onUpdate(event) {
|
|
20
|
+
this.#trace("onUpdate(",event,")");
|
|
21
|
+
this.#fill = "blue";
|
|
22
|
+
|
|
23
|
+
var instance = this;
|
|
24
|
+
setTimeout(()=>{
|
|
25
|
+
instance.#fill = "grey";
|
|
26
|
+
instance.updateStatus();
|
|
27
|
+
},1000);
|
|
28
|
+
|
|
29
|
+
this.updateStatus();
|
|
30
|
+
super.onUpdate(event);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
updateStatus() {
|
|
34
|
+
this.#trace("updateStatus()");
|
|
35
|
+
|
|
36
|
+
var fill = this.#fill;
|
|
37
|
+
var shape = "dot";
|
|
38
|
+
var text = "";
|
|
39
|
+
|
|
40
|
+
var resource = this.resource();
|
|
41
|
+
if ((resource) && (resource.data()) && (resource.data().contact_report)) {
|
|
42
|
+
if (resource.data().contact_report.state!=null) {
|
|
43
|
+
fill = (resource.data().contact_report.state=="contact")? "grey" : "blue";
|
|
44
|
+
text = (resource.data().contact_report.state=="contact")? "closed" : "open";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.status({fill: fill, shape: shape, text: text});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = ContactNode;
|
package/src/ui/BaseUI.js
CHANGED
|
@@ -75,9 +75,7 @@ export class BaseUI {
|
|
|
75
75
|
item.setAttribute("id","node-container-" + id);
|
|
76
76
|
item.innerHTML = '\
|
|
77
77
|
<div style="display: inline-flex; width: calc(100% - 105px)">\
|
|
78
|
-
<
|
|
79
|
-
<input type="checkbox" id="' + prefix + id +'" style="flex: 15px;">\
|
|
80
|
-
</div>\
|
|
78
|
+
<input type="checkbox" id="' + prefix + id +'" style="flex: 15px;">\
|
|
81
79
|
<span style="width: 100%; margin-left: 10px;">\
|
|
82
80
|
'+ label +'\
|
|
83
81
|
</span>\
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ServiceUI } from "./ServiceUI.js"
|
|
2
|
+
|
|
3
|
+
export class CameraMotionUI extends ServiceUI {
|
|
4
|
+
constructor() {
|
|
5
|
+
super("Camera Motion","hue services","camera_motion");
|
|
6
|
+
console.log("CameraMotionUI.constructor()");
|
|
7
|
+
|
|
8
|
+
this.config.color = "#FFC0FF";
|
|
9
|
+
this.config.icon = "font-awesome/fa-rss";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
buildHelp() {
|
|
13
|
+
var help = super.buildHelp();
|
|
14
|
+
help["Outputs"] += "\
|
|
15
|
+
The CameraMotion 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 motion 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
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ServiceUI } from "./ServiceUI.js"
|
|
2
|
+
|
|
3
|
+
export class ContactUI extends ServiceUI {
|
|
4
|
+
constructor() {
|
|
5
|
+
super("Contact","hue services","contact");
|
|
6
|
+
console.log("ContactUI.constructor()");
|
|
7
|
+
|
|
8
|
+
this.config.color = "#FFD8FF";
|
|
9
|
+
this.config.icon = "font-awesome/fa-step-forward";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
buildHelp() {
|
|
13
|
+
var help = super.buildHelp();
|
|
14
|
+
help["Outputs"] += "\
|
|
15
|
+
The Contact 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 contact 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
|
+
}
|