node-red-contrib-huemagic 2.8.2 → 4.0.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/CHANGELOG.md +229 -0
- package/README.md +806 -729
- package/examples/Hue Bridge.json +189 -35
- package/examples/Hue Brightness.json +124 -14
- package/examples/Hue Buttons.json +88 -0
- package/examples/Hue Group.json +575 -63
- package/examples/Hue Light.json +805 -58
- package/examples/Hue Magic.json +69 -24
- package/examples/Hue Motion.json +110 -42
- package/examples/Hue Rules.json +105 -37
- package/examples/Hue Scene.json +145 -28
- package/examples/Hue Temperature.json +124 -14
- package/huemagic/animations/001-sunny.json +22 -22
- package/huemagic/animations/002-cloudy.json +46 -46
- package/huemagic/animations/003-nightsky.json +20 -20
- package/huemagic/animations/004-sunrise.json +54 -54
- package/huemagic/animations/005-sunset.json +46 -46
- package/huemagic/animations/006-fireplace.json +74 -74
- package/huemagic/animations/007-spring.json +31 -31
- package/huemagic/animations/008-autmn.json +23 -23
- package/huemagic/animations/009-winter.json +23 -23
- package/huemagic/animations/010-dirtyfog.json +23 -23
- package/huemagic/animations/011-lgbt.json +49 -50
- package/huemagic/animations/012-rasta.json +28 -29
- package/huemagic/animations/013-strobo.json +30 -31
- package/huemagic/animations/014-randomrainbow.json +30 -31
- package/huemagic/animations/015-sos.json +158 -159
- package/huemagic/animations/016-milkyway.json +83 -0
- package/huemagic/animations/017-beach.json +40 -0
- package/huemagic/animations/018-forest.json +43 -0
- package/huemagic/animations/019-christmas.json +30 -0
- package/huemagic/animations/020-superhero.json +56 -0
- package/huemagic/animations/021-neoncity.json +52 -0
- package/huemagic/animations/previews/001-sunny.gif +0 -0
- package/huemagic/animations/previews/002-cloudy.gif +0 -0
- package/huemagic/animations/previews/003-nightsky.gif +0 -0
- package/huemagic/animations/previews/004-sunrise.gif +0 -0
- package/huemagic/animations/previews/005-sunset.gif +0 -0
- package/huemagic/animations/previews/006-fireplace.gif +0 -0
- package/huemagic/animations/previews/007-spring.gif +0 -0
- package/huemagic/animations/previews/008-autmn.gif +0 -0
- package/huemagic/animations/previews/009-winter.gif +0 -0
- package/huemagic/animations/previews/010-dirtyfog.gif +0 -0
- package/huemagic/animations/previews/011-lgbt.gif +0 -0
- package/huemagic/animations/previews/012-rasta.gif +0 -0
- package/huemagic/animations/previews/013-strobo.gif +0 -0
- package/huemagic/animations/previews/014-randomrainbow.gif +0 -0
- package/huemagic/animations/previews/015-sos.gif +0 -0
- package/huemagic/animations/previews/016-milkyway.gif +0 -0
- package/huemagic/animations/previews/017-beach.gif +0 -0
- package/huemagic/animations/previews/018-forest.gif +0 -0
- package/huemagic/animations/previews/019-christmas.gif +0 -0
- package/huemagic/animations/previews/020-superhero.gif +0 -0
- package/huemagic/animations/previews/021-neoncity.gif +0 -0
- package/huemagic/hue-bridge-config.html +105 -61
- package/huemagic/hue-bridge-config.js +629 -319
- package/huemagic/hue-bridge.html +41 -21
- package/huemagic/hue-bridge.js +191 -398
- package/huemagic/hue-brightness.html +130 -49
- package/huemagic/hue-brightness.js +131 -35
- package/huemagic/hue-buttons.html +197 -0
- package/huemagic/hue-buttons.js +152 -0
- package/huemagic/hue-group.html +137 -60
- package/huemagic/hue-group.js +394 -367
- package/huemagic/hue-light.html +133 -59
- package/huemagic/hue-light.js +551 -336
- package/huemagic/hue-magic.html +91 -237
- package/huemagic/hue-magic.js +57 -27
- package/huemagic/hue-motion.html +128 -50
- package/huemagic/hue-motion.js +116 -87
- package/huemagic/hue-rules.html +121 -50
- package/huemagic/hue-rules.js +84 -64
- package/huemagic/hue-scene.html +96 -115
- package/huemagic/hue-scene.js +65 -96
- package/huemagic/hue-temperature.html +130 -49
- package/huemagic/hue-temperature.js +136 -32
- package/huemagic/icons/hue-bridge.png +0 -0
- package/huemagic/icons/hue-bridge.svg +3 -0
- package/huemagic/icons/hue-brightness.png +0 -0
- package/huemagic/icons/hue-brightness.svg +11 -0
- package/huemagic/icons/hue-buttons.png +0 -0
- package/huemagic/icons/hue-buttons.svg +4 -0
- package/huemagic/icons/hue-group.png +0 -0
- package/huemagic/icons/hue-group.svg +12 -0
- package/huemagic/icons/hue-light.png +0 -0
- package/huemagic/icons/hue-light.svg +3 -0
- package/huemagic/icons/hue-magic.png +0 -0
- package/huemagic/icons/hue-magic.svg +3 -0
- package/huemagic/icons/hue-motion.png +0 -0
- package/huemagic/icons/hue-motion.svg +9 -0
- package/huemagic/icons/hue-rules.png +0 -0
- package/huemagic/icons/hue-rules.svg +4 -0
- package/huemagic/icons/hue-scene.png +0 -0
- package/huemagic/icons/hue-scene.svg +5 -0
- package/huemagic/icons/hue-temperature.png +0 -0
- package/huemagic/icons/hue-temperature.svg +7 -0
- package/huemagic/locales/de/hue-bridge-config.html +17 -12
- package/huemagic/locales/de/hue-bridge-config.json +7 -5
- package/huemagic/locales/de/hue-bridge.html +64 -145
- package/huemagic/locales/de/hue-bridge.json +6 -17
- package/huemagic/locales/de/hue-brightness.html +52 -38
- package/huemagic/locales/de/hue-brightness.json +7 -2
- package/huemagic/locales/de/hue-buttons.html +58 -0
- package/huemagic/locales/de/hue-buttons.json +28 -0
- package/huemagic/locales/de/hue-group.html +46 -122
- package/huemagic/locales/de/hue-group.json +4 -2
- package/huemagic/locales/de/hue-light.html +68 -116
- package/huemagic/locales/de/hue-light.json +5 -2
- package/huemagic/locales/de/hue-magic.html +65 -57
- package/huemagic/locales/de/hue-magic.json +2 -1
- package/huemagic/locales/de/hue-motion.html +48 -44
- package/huemagic/locales/de/hue-motion.json +6 -3
- package/huemagic/locales/de/hue-rules.html +68 -73
- package/huemagic/locales/de/hue-rules.json +5 -2
- package/huemagic/locales/de/hue-scene.html +23 -32
- package/huemagic/locales/de/hue-scene.json +5 -2
- package/huemagic/locales/de/hue-temperature.html +53 -36
- package/huemagic/locales/de/hue-temperature.json +7 -2
- package/huemagic/locales/en-US/hue-bridge-config.html +17 -12
- package/huemagic/locales/en-US/hue-bridge-config.json +5 -3
- package/huemagic/locales/en-US/hue-bridge.html +64 -145
- package/huemagic/locales/en-US/hue-bridge.json +5 -16
- package/huemagic/locales/en-US/hue-brightness.html +52 -38
- package/huemagic/locales/en-US/hue-brightness.json +10 -3
- package/huemagic/locales/en-US/hue-buttons.html +58 -0
- package/huemagic/locales/en-US/hue-buttons.json +34 -0
- package/huemagic/locales/en-US/hue-group.html +46 -122
- package/huemagic/locales/en-US/hue-group.json +7 -3
- package/huemagic/locales/en-US/hue-light.html +68 -116
- package/huemagic/locales/en-US/hue-light.json +8 -3
- package/huemagic/locales/en-US/hue-magic.html +65 -57
- package/huemagic/locales/en-US/hue-magic.json +3 -1
- package/huemagic/locales/en-US/hue-motion.html +48 -44
- package/huemagic/locales/en-US/hue-motion.json +9 -4
- package/huemagic/locales/en-US/hue-rules.html +68 -73
- package/huemagic/locales/en-US/hue-rules.json +5 -2
- package/huemagic/locales/en-US/hue-scene.html +23 -32
- package/huemagic/locales/en-US/hue-scene.json +5 -2
- package/huemagic/locales/en-US/hue-temperature.html +53 -36
- package/huemagic/locales/en-US/hue-temperature.json +10 -3
- package/huemagic/utils/api.js +290 -0
- package/huemagic/utils/color.js +382 -0
- package/{utils → huemagic/utils}/merge.js +9 -6
- package/huemagic/utils/messages.js +447 -0
- package/package.json +12 -12
- package/examples/Hue Switch.json +0 -40
- package/examples/Hue Tap.json +0 -40
- package/huemagic/assets/anime.js +0 -8
- package/huemagic/hue-switch.html +0 -119
- package/huemagic/hue-switch.js +0 -113
- package/huemagic/hue-tap.html +0 -119
- package/huemagic/hue-tap.js +0 -74
- package/huemagic/icons/hue-button.png +0 -0
- package/huemagic/icons/hue-switch.png +0 -0
- package/huemagic/icons/hue-tap.png +0 -0
- package/huemagic/locales/de/hue-switch.html +0 -50
- package/huemagic/locales/de/hue-switch.json +0 -31
- package/huemagic/locales/de/hue-tap.html +0 -41
- package/huemagic/locales/de/hue-tap.json +0 -23
- package/huemagic/locales/en-US/hue-switch.html +0 -50
- package/huemagic/locales/en-US/hue-switch.json +0 -31
- package/huemagic/locales/en-US/hue-tap.html +0 -41
- package/huemagic/locales/en-US/hue-tap.json +0 -23
- package/utils/messages.js +0 -571
- package/utils/rgb.js +0 -188
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
const dayjs = require('dayjs');
|
|
2
|
+
const colorUtils = require("./color");
|
|
3
|
+
|
|
4
|
+
//
|
|
5
|
+
// HUE BRIDGE
|
|
6
|
+
class HueBridgeMessage
|
|
7
|
+
{
|
|
8
|
+
constructor(ressource, options = {})
|
|
9
|
+
{
|
|
10
|
+
this.message = {};
|
|
11
|
+
this.message.payload = {};
|
|
12
|
+
this.message.payload.id = ressource.bridgeid;
|
|
13
|
+
this.message.payload.name = ressource.name;
|
|
14
|
+
this.message.payload.factoryNew = ressource.factorynew;
|
|
15
|
+
this.message.payload.replacesBridgeId = ressource.replacesbridgeid ? ressource.replacesbridgeid : false;
|
|
16
|
+
this.message.payload.dataStoreVersion = ressource.datastoreversion;
|
|
17
|
+
this.message.payload.starterKitId = ressource.starterkitid.length > 0 ? ressource.starterkitid : false;
|
|
18
|
+
this.message.payload.softwareVersion = ressource.swversion;
|
|
19
|
+
this.message.payload.apiVersion = ressource.apiversion;
|
|
20
|
+
this.message.payload.zigbeeChannel = ressource.zigbeechannel;
|
|
21
|
+
this.message.payload.macAddress = ressource.mac;
|
|
22
|
+
this.message.payload.ipAddress = ressource.ipaddress;
|
|
23
|
+
this.message.payload.dhcpEnabled = ressource.dhcp;
|
|
24
|
+
this.message.payload.netmask = ressource.netmask;
|
|
25
|
+
this.message.payload.gateway = ressource.gateway;
|
|
26
|
+
this.message.payload.proxyAddress = ressource.proxyaddress == "none" ? false : ressource.proxyaddress;
|
|
27
|
+
this.message.payload.proxyPort = ressource.proxyport;
|
|
28
|
+
this.message.payload.utcTime = ressource.UTC;
|
|
29
|
+
this.message.payload.timeZone = ressource.timezone;
|
|
30
|
+
this.message.payload.localTime = ressource.localtime;
|
|
31
|
+
this.message.payload.portalServicesEnabled = ressource.portalservices;
|
|
32
|
+
this.message.payload.portalConnected = ressource.portalconnection;
|
|
33
|
+
this.message.payload.linkButtonEnabled = ressource.linkbutton;
|
|
34
|
+
this.message.payload.touchlinkEnabled = (ressource["touchlink"] && ressource["touchlink"] == true) ? true : false;
|
|
35
|
+
this.message.payload.autoUpdatesEnabled = options["autoupdate"] ? options["autoupdate"] : false;
|
|
36
|
+
this.message.payload.users = []; // NEW!
|
|
37
|
+
this.message.payload.updated = ressource.updated; // NEW!
|
|
38
|
+
|
|
39
|
+
this.message.payload.model = {};
|
|
40
|
+
this.message.payload.model.id = ressource.modelid;
|
|
41
|
+
this.message.payload.model.manufacturer = "Philips";
|
|
42
|
+
this.message.payload.model.name = "Hue v2";
|
|
43
|
+
|
|
44
|
+
// GET USERS
|
|
45
|
+
for (const [userID, user] of Object.entries(ressource["whitelist"]))
|
|
46
|
+
{
|
|
47
|
+
this.message.payload.users.push({
|
|
48
|
+
user: userID,
|
|
49
|
+
name: user["name"],
|
|
50
|
+
created: user["create date"],
|
|
51
|
+
lastAccess: user["last use date"]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get msg()
|
|
57
|
+
{
|
|
58
|
+
return this.message;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
//
|
|
64
|
+
// HUE BRIGHTNESS
|
|
65
|
+
class HueBrightnessMessage
|
|
66
|
+
{
|
|
67
|
+
constructor(ressource, options = {})
|
|
68
|
+
{
|
|
69
|
+
const service = Object.values(ressource["services"]["light_level"])[0];
|
|
70
|
+
const connectivity = ressource.services.zigbee_connectivity ? Object.values(ressource.services.zigbee_connectivity)[0] : ((ressource.services.zgp_connectivity) ? Object.values(ressource.services.zgp_connectivity)[0] : false);
|
|
71
|
+
|
|
72
|
+
var realLUX = service.light.light_level - 1;
|
|
73
|
+
realLUX = realLUX / 10000;
|
|
74
|
+
realLUX = Math.round(Math.pow(10, realLUX));
|
|
75
|
+
|
|
76
|
+
this.message = {};
|
|
77
|
+
this.message.payload = {};
|
|
78
|
+
this.message.payload.active = service.enabled; // NEW!
|
|
79
|
+
this.message.payload.reachable = connectivity ? (connectivity.status === "connected") : "unknown"; // NEW!
|
|
80
|
+
this.message.payload.connectionStatus = connectivity ? connectivity.status : "unknown"; // NEW!
|
|
81
|
+
this.message.payload.lux = realLUX;
|
|
82
|
+
this.message.payload.lightLevel = service.light.light_level;
|
|
83
|
+
this.message.payload.dark = (realLUX < 200);
|
|
84
|
+
this.message.payload.daylight = (realLUX > 200);
|
|
85
|
+
this.message.payload.updated = ressource.updated;
|
|
86
|
+
|
|
87
|
+
this.message.info = {};
|
|
88
|
+
this.message.info.id = service.id;
|
|
89
|
+
this.message.info.idV1 = ressource.id_v1 ? ressource.id_v1 : false; // NEW
|
|
90
|
+
this.message.info.uniqueId = ressource.id + "-" + service.id;
|
|
91
|
+
this.message.info.deviceId = ressource.id; // NEW!
|
|
92
|
+
this.message.info.name = ressource.metadata.name;
|
|
93
|
+
this.message.info.type = "light_level";
|
|
94
|
+
this.message.info.softwareVersion = ressource.product_data.software_version;
|
|
95
|
+
this.message.info.battery = Object.values(ressource.services.device_power)[0].power_state.battery_level;
|
|
96
|
+
this.message.info.batteryState = Object.values(ressource.services.device_power)[0].power_state.battery_state; // NEW!
|
|
97
|
+
|
|
98
|
+
this.message.info.model = {};
|
|
99
|
+
this.message.info.model.id = ressource.product_data.model_id;
|
|
100
|
+
this.message.info.model.manufacturer = ressource.product_data.manufacturer_name;
|
|
101
|
+
this.message.info.model.name = ressource.product_data.product_name;
|
|
102
|
+
this.message.info.model.type = ressource.product_data.product_archetype;
|
|
103
|
+
this.message.info.model.certified = ressource.product_data.certified; // NEW
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
get msg()
|
|
107
|
+
{
|
|
108
|
+
return this.message;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
//
|
|
114
|
+
// HUE GROUP
|
|
115
|
+
class HueGroupMessage
|
|
116
|
+
{
|
|
117
|
+
constructor(ressource, options = {})
|
|
118
|
+
{
|
|
119
|
+
let service = Object.values(ressource["services"]["grouped_light"])[0];
|
|
120
|
+
service = options.ressources[service.id];
|
|
121
|
+
|
|
122
|
+
this.message = {};
|
|
123
|
+
this.message.payload = {};
|
|
124
|
+
this.message.payload.on = service.on.on;
|
|
125
|
+
this.message.payload.updated = ressource.updated;
|
|
126
|
+
|
|
127
|
+
this.message.info = {};
|
|
128
|
+
this.message.info.id = ressource.id;
|
|
129
|
+
this.message.info.idV1 = ressource.id_v1 ? ressource.id_v1 : false; // NEW
|
|
130
|
+
this.message.info.name = ressource.metadata ? ressource.metadata.name : "all";
|
|
131
|
+
this.message.info.type = "group";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
get msg()
|
|
135
|
+
{
|
|
136
|
+
return this.message;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
//
|
|
142
|
+
// HUE LIGHT
|
|
143
|
+
class HueLightMessage
|
|
144
|
+
{
|
|
145
|
+
constructor(ressource, options = {})
|
|
146
|
+
{
|
|
147
|
+
const service = Object.values(ressource["services"]["light"])[0];
|
|
148
|
+
const connectivity = ressource.services.zigbee_connectivity ? Object.values(ressource.services.zigbee_connectivity)[0] : ((ressource.services.zgp_connectivity) ? Object.values(ressource.services.zgp_connectivity)[0] : false);
|
|
149
|
+
|
|
150
|
+
this.message = {};
|
|
151
|
+
this.message.payload = {};
|
|
152
|
+
this.message.payload.on = service.on.on;
|
|
153
|
+
this.message.payload.brightness = service.dimming ? service.dimming.brightness : false;
|
|
154
|
+
this.message.payload.brightnessLevel = service.dimming ? Math.round((254/100)*this.message.payload.brightness) : false;
|
|
155
|
+
this.message.payload.reachable = connectivity ? (connectivity.status === "connected") : "unknown";
|
|
156
|
+
this.message.payload.connectionStatus = connectivity ? connectivity.status : "unknown"; // NEW!
|
|
157
|
+
this.message.payload.updated = ressource.updated;
|
|
158
|
+
|
|
159
|
+
this.message.info = {};
|
|
160
|
+
this.message.info.id = service.id;
|
|
161
|
+
this.message.info.idV1 = ressource.id_v1 ? ressource.id_v1 : false; // NEW
|
|
162
|
+
this.message.info.uniqueId = ressource.id + "-" + service.id;
|
|
163
|
+
this.message.info.deviceId = ressource.id; // NEW!
|
|
164
|
+
this.message.info.name = service.metadata.name;
|
|
165
|
+
this.message.info.type = "light";
|
|
166
|
+
this.message.info.softwareVersion = ressource.product_data.software_version;
|
|
167
|
+
|
|
168
|
+
this.message.info.model = {};
|
|
169
|
+
this.message.info.model.id = ressource.product_data.model_id;
|
|
170
|
+
this.message.info.model.manufacturer = ressource.product_data.manufacturer_name;
|
|
171
|
+
this.message.info.model.name = ressource.product_data.product_name;
|
|
172
|
+
this.message.info.model.type = ressource.product_data.product_archetype;
|
|
173
|
+
this.message.info.model.certified = ressource.product_data.certified; // NEW
|
|
174
|
+
this.message.info.model.friendsOfHue = true;
|
|
175
|
+
|
|
176
|
+
// HAS COLOR CAPABILITIES?
|
|
177
|
+
if(service["color"])
|
|
178
|
+
{
|
|
179
|
+
let RGB = colorUtils.xyBriToRgb(service.color.xy.x, service.color.xy.y, (service.dimming ? service.dimming.brightness : 100));
|
|
180
|
+
this.message.payload.rgb = [RGB.r, RGB.g, RGB.b];
|
|
181
|
+
this.message.payload.hex = colorUtils.rgbHex(RGB.r, RGB.g, RGB.b);
|
|
182
|
+
this.message.payload.xyColor = service.color.xy; // NEW!
|
|
183
|
+
|
|
184
|
+
if(options.colornames == true)
|
|
185
|
+
{
|
|
186
|
+
var cNamesArray = colorUtils.colornamer(colorUtils.rgbHex(RGB.r, RGB.g, RGB.b));
|
|
187
|
+
this.message.payload.color = cNamesArray.basic[0]["name"];
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
this.message.info.model.colorGamut = service.color.gamut; // NEW
|
|
191
|
+
this.message.info.model.colorGamutType = service.color.gamut_type; // NEW
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// HAS COLOR TEMPERATURE CAPABILITIES?
|
|
195
|
+
if(service["color_temperature"])
|
|
196
|
+
{
|
|
197
|
+
this.message.payload.colorTemp = service.color_temperature.mirek ? service.color_temperature.mirek : false;
|
|
198
|
+
|
|
199
|
+
if(!this.message.payload.colorTemp) { this.message.payload.colorTempName = "unknown"; }
|
|
200
|
+
else if(this.message.payload.colorTemp < 200) { this.message.payload.colorTempName = "cold"; } // NEW!
|
|
201
|
+
else if(this.message.payload.colorTemp < 350) { this.message.payload.colorTempName = "normal"; }
|
|
202
|
+
else if(this.message.payload.colorTemp < 410) { this.message.payload.colorTempName = "warm"; }
|
|
203
|
+
else { this.message.payload.colorTempName = "hot"; }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// HAS GRADIENT COLOR CAPABILITIES?
|
|
207
|
+
if(service["gradient"]) // NEW!
|
|
208
|
+
{
|
|
209
|
+
this.message.payload.gradient = {};
|
|
210
|
+
this.message.payload.gradient.colors = [];
|
|
211
|
+
|
|
212
|
+
for(let gradientColor in service["gradient"]["points"])
|
|
213
|
+
{
|
|
214
|
+
let gradientColorRGB = colorUtils.xyBriToRgb(gradientColor.color.xy.x, gradientColor.color.xy.y, (gradientColor.dimming ? service.dimming.brightness : 100));
|
|
215
|
+
|
|
216
|
+
let oneColorPack = {};
|
|
217
|
+
oneColorPack.rgb = [gradientColorRGB.r, gradientColorRGB.g, gradientColorRGB.b];
|
|
218
|
+
oneColorPack.hex = colorUtils.rgbHex(gradientColorRGB.r, gradientColorRGB.g, gradientColorRGB.b);
|
|
219
|
+
oneColorPack.xyColor = gradientColor.color.xy.x;
|
|
220
|
+
|
|
221
|
+
this.message.payload.gradient.colors.push(oneColorPack);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
this.message.payload.gradient.numColors = service["gradient"]["points"] ? service["gradient"]["points"].length : 0;
|
|
225
|
+
this.message.payload.gradient.totalColors = service["gradient"]["points_capable"];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
get msg()
|
|
230
|
+
{
|
|
231
|
+
return this.message;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
//
|
|
237
|
+
// HUE MOTION
|
|
238
|
+
class HueMotionMessage
|
|
239
|
+
{
|
|
240
|
+
constructor(ressource, options = {})
|
|
241
|
+
{
|
|
242
|
+
const service = Object.values(ressource["services"]["motion"])[0];
|
|
243
|
+
const connectivity = ressource.services.zigbee_connectivity ? Object.values(ressource.services.zigbee_connectivity)[0] : ((ressource.services.zgp_connectivity) ? Object.values(ressource.services.zgp_connectivity)[0] : false);
|
|
244
|
+
|
|
245
|
+
this.message = {};
|
|
246
|
+
this.message.payload = {
|
|
247
|
+
active: service.enabled,
|
|
248
|
+
reachable: connectivity ? (connectivity.status === "connected") : "unknown",
|
|
249
|
+
connectionStatus: connectivity ? connectivity.status : "unknown", // NEW!
|
|
250
|
+
motion: (service.motion.motion && service.motion.motion_valid),
|
|
251
|
+
updated: ressource.updated
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
this.message.info = {};
|
|
255
|
+
this.message.info.id = service.id;
|
|
256
|
+
this.message.info.idV1 = ressource.id_v1 ? ressource.id_v1 : false; // NEW
|
|
257
|
+
this.message.info.uniqueId = ressource.id + "-" + service.id;
|
|
258
|
+
this.message.info.deviceId = ressource.id; // NEW!
|
|
259
|
+
this.message.info.name = ressource.metadata.name;
|
|
260
|
+
this.message.info.type = "motion";
|
|
261
|
+
this.message.info.softwareVersion = ressource.product_data.software_version;
|
|
262
|
+
this.message.info.battery = Object.values(ressource.services.device_power)[0].power_state.battery_level;
|
|
263
|
+
this.message.info.batteryState = Object.values(ressource.services.device_power)[0].power_state.battery_state; // NEW!
|
|
264
|
+
|
|
265
|
+
this.message.info.model = {};
|
|
266
|
+
this.message.info.model.id = ressource.product_data.model_id;
|
|
267
|
+
this.message.info.model.manufacturer = ressource.product_data.manufacturer_name;
|
|
268
|
+
this.message.info.model.name = ressource.product_data.product_name;
|
|
269
|
+
this.message.info.model.type = ressource.product_data.product_archetype;
|
|
270
|
+
this.message.info.model.certified = ressource.product_data.certified; // NEW
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
get msg()
|
|
274
|
+
{
|
|
275
|
+
return this.message;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
//
|
|
281
|
+
// HUE RULES
|
|
282
|
+
class HueRulesMessage
|
|
283
|
+
{
|
|
284
|
+
constructor(ressource, options = {})
|
|
285
|
+
{
|
|
286
|
+
this.message = {};
|
|
287
|
+
this.message.payload = {};
|
|
288
|
+
this.message.payload.enabled = (ressource["status"] == "enabled"); // NEW!
|
|
289
|
+
this.message.payload.triggered = (ressource["lasttriggered"] != null) ? dayjs(ressource["lasttriggered"]).format() : false;
|
|
290
|
+
|
|
291
|
+
this.message.info = {};
|
|
292
|
+
this.message.info.id = ressource["id"];
|
|
293
|
+
this.message.info.created = dayjs(ressource["created"]).format();
|
|
294
|
+
this.message.info.name = ressource["name"];
|
|
295
|
+
this.message.info.timesTriggered = ressource["timestriggered"];
|
|
296
|
+
this.message.info.owner = ressource["_owner"];
|
|
297
|
+
this.message.info.status = ressource["status"];
|
|
298
|
+
|
|
299
|
+
this.message.conditions = ressource["conditions"];
|
|
300
|
+
this.message.actions = ressource["actions"];
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
get msg()
|
|
304
|
+
{
|
|
305
|
+
return this.message;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
//
|
|
311
|
+
// HUE BUTTONS
|
|
312
|
+
class HueButtonsMessage
|
|
313
|
+
{
|
|
314
|
+
constructor(ressource, options = {})
|
|
315
|
+
{
|
|
316
|
+
const connectivity = ressource.services.zigbee_connectivity ? Object.values(ressource.services.zigbee_connectivity)[0] : ((ressource.services.zgp_connectivity) ? Object.values(ressource.services.zgp_connectivity)[0] : false);
|
|
317
|
+
|
|
318
|
+
// FIND PRESSED BUTTON
|
|
319
|
+
var pressedButton = false;
|
|
320
|
+
const allButtons = Object.values(ressource.services.button);
|
|
321
|
+
|
|
322
|
+
for (var i = allButtons.length - 1; i >= 0; i--)
|
|
323
|
+
{
|
|
324
|
+
if(allButtons[i]["button"])
|
|
325
|
+
{
|
|
326
|
+
pressedButton = allButtons[i];
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
this.message = {};
|
|
332
|
+
this.message.payload = {
|
|
333
|
+
reachable: connectivity ? (connectivity.status === "connected") : "unknown", // NEW!
|
|
334
|
+
connectionStatus: connectivity ? connectivity.status : "unknown", // NEW!
|
|
335
|
+
button: pressedButton ? pressedButton.metadata.control_id : false, // NEW
|
|
336
|
+
action: pressedButton ? pressedButton.button.last_event : false, // NEW
|
|
337
|
+
updated: ressource.updated
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
this.message.info = {};
|
|
341
|
+
this.message.info.id = pressedButton ? pressedButton.id : ressource.id;
|
|
342
|
+
this.message.info.idV1 = ressource.id_v1 ? ressource.id_v1 : false; // NEW
|
|
343
|
+
this.message.info.uniqueId = ressource.id + "-" + (pressedButton ? pressedButton.id : "");
|
|
344
|
+
this.message.info.deviceId = ressource.id; // NEW!
|
|
345
|
+
this.message.info.name = ressource.metadata.name;
|
|
346
|
+
this.message.info.type = "button";
|
|
347
|
+
this.message.info.softwareVersion = ressource.product_data.software_version;
|
|
348
|
+
this.message.info.battery = Object.values(ressource.services.device_power)[0].power_state.battery_level;
|
|
349
|
+
this.message.info.batteryState = Object.values(ressource.services.device_power)[0].power_state.battery_state; // NEW!
|
|
350
|
+
|
|
351
|
+
this.message.info.model = {};
|
|
352
|
+
this.message.info.model.id = ressource.product_data.model_id;
|
|
353
|
+
this.message.info.model.manufacturer = ressource.product_data.manufacturer_name;
|
|
354
|
+
this.message.info.model.name = ressource.product_data.product_name;
|
|
355
|
+
this.message.info.model.type = ressource.product_data.product_archetype;
|
|
356
|
+
this.message.info.model.certified = ressource.product_data.certified; // NEW
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
get msg()
|
|
360
|
+
{
|
|
361
|
+
return this.message;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
//
|
|
367
|
+
// HUE TEMPERATURE
|
|
368
|
+
class HueTemperatureMessage
|
|
369
|
+
{
|
|
370
|
+
constructor(ressource, options = {})
|
|
371
|
+
{
|
|
372
|
+
const service = Object.values(ressource["services"]["temperature"])[0];
|
|
373
|
+
const connectivity = ressource.services.zigbee_connectivity ? Object.values(ressource.services.zigbee_connectivity)[0] : ((ressource.services.zgp_connectivity) ? Object.values(ressource.services.zgp_connectivity)[0] : false);
|
|
374
|
+
|
|
375
|
+
var deviceValue = service.temperature.temperature;
|
|
376
|
+
var celsius = Math.round(deviceValue * 100) / 100;
|
|
377
|
+
var fahrenheit = Math.round(((celsius * 1.8)+32) * 100) / 100;
|
|
378
|
+
|
|
379
|
+
// TEMPERATURE MESSAGE
|
|
380
|
+
let temperatureMessage = "comfortable";
|
|
381
|
+
|
|
382
|
+
if(celsius < 0) {
|
|
383
|
+
temperatureMessage = "very cold";
|
|
384
|
+
}
|
|
385
|
+
else if(celsius < 11) {
|
|
386
|
+
temperatureMessage = "cold";
|
|
387
|
+
}
|
|
388
|
+
else if(celsius < 16) {
|
|
389
|
+
temperatureMessage = "slightly cold";
|
|
390
|
+
}
|
|
391
|
+
else if(celsius < 22) {
|
|
392
|
+
temperatureMessage = "comfortable";
|
|
393
|
+
}
|
|
394
|
+
else if(celsius < 27) {
|
|
395
|
+
temperatureMessage = "slightly warm";
|
|
396
|
+
}
|
|
397
|
+
else if(celsius < 33) {
|
|
398
|
+
temperatureMessage = "warm";
|
|
399
|
+
}
|
|
400
|
+
else if(celsius < 39) {
|
|
401
|
+
temperatureMessage = "hot";
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
temperatureMessage = "very hot";
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
this.message = {};
|
|
408
|
+
this.message.payload = {
|
|
409
|
+
active: service.enabled, // NEW!
|
|
410
|
+
reachable: connectivity ? (connectivity.status === "connected") : "unknown", // NEW!
|
|
411
|
+
connectionStatus: connectivity ? connectivity.status : "unknown", // NEW!
|
|
412
|
+
celsius: celsius,
|
|
413
|
+
fahrenheit: fahrenheit,
|
|
414
|
+
temperatureIs: temperatureMessage,
|
|
415
|
+
deviceValue: deviceValue,
|
|
416
|
+
updated: ressource.updated
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
this.message.info = {};
|
|
420
|
+
this.message.info.id = service.id;
|
|
421
|
+
this.message.info.idV1 = ressource.id_v1 ? ressource.id_v1 : false; // NEW
|
|
422
|
+
this.message.info.uniqueId = ressource.id + "-" + service.id;
|
|
423
|
+
this.message.info.deviceId = ressource.id; // NEW!
|
|
424
|
+
this.message.info.name = ressource.metadata.name;
|
|
425
|
+
this.message.info.type = "temperature";
|
|
426
|
+
this.message.info.softwareVersion = ressource.product_data.software_version;
|
|
427
|
+
this.message.info.battery = Object.values(ressource.services.device_power)[0].power_state.battery_level;
|
|
428
|
+
this.message.info.batteryState = Object.values(ressource.services.device_power)[0].power_state.battery_state; // NEW!
|
|
429
|
+
|
|
430
|
+
this.message.info.model = {};
|
|
431
|
+
this.message.info.model.id = ressource.product_data.model_id;
|
|
432
|
+
this.message.info.model.manufacturer = ressource.product_data.manufacturer_name;
|
|
433
|
+
this.message.info.model.name = ressource.product_data.product_name;
|
|
434
|
+
this.message.info.model.type = ressource.product_data.product_archetype;
|
|
435
|
+
this.message.info.model.certified = ressource.product_data.certified; // NEW
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
get msg()
|
|
439
|
+
{
|
|
440
|
+
return this.message;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
//
|
|
445
|
+
// EXPORT
|
|
446
|
+
module.exports = { HueBridgeMessage, HueBrightnessMessage, HueGroupMessage, HueLightMessage, HueMotionMessage, HueRulesMessage, HueButtonsMessage, HueTemperatureMessage }
|
|
447
|
+
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-huemagic",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Philips Hue node to control bridges, lights, groups, scenes, rules, taps, switches, motion sensors, temperature sensors and Lux sensors using Node-RED.",
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"description": "Philips Hue node to control bridges, lights, groups, scenes, rules, taps, switches, buttons, motion sensors, temperature sensors and Lux sensors using Node-RED.",
|
|
5
5
|
"author": "foddy",
|
|
6
6
|
"homepage": "https://github.com/Foddy/node-red-contrib-huemagic",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
"contrib",
|
|
22
22
|
"philips",
|
|
23
23
|
"hue",
|
|
24
|
+
"smart-home",
|
|
25
|
+
"home-automation",
|
|
24
26
|
"api",
|
|
25
27
|
"iot"
|
|
26
28
|
],
|
|
@@ -32,8 +34,7 @@
|
|
|
32
34
|
"hue-light": "huemagic/hue-light.js",
|
|
33
35
|
"hue-group": "huemagic/hue-group.js",
|
|
34
36
|
"hue-scene": "huemagic/hue-scene.js",
|
|
35
|
-
"hue-
|
|
36
|
-
"hue-switch": "huemagic/hue-switch.js",
|
|
37
|
+
"hue-buttons": "huemagic/hue-buttons.js",
|
|
37
38
|
"hue-motion": "huemagic/hue-motion.js",
|
|
38
39
|
"hue-temperature": "huemagic/hue-temperature.js",
|
|
39
40
|
"hue-brightness": "huemagic/hue-brightness.js",
|
|
@@ -44,14 +45,13 @@
|
|
|
44
45
|
"access": "public"
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
|
-
"async": "^3.2.
|
|
48
|
-
"
|
|
49
|
-
"huejay": "^1.9.0",
|
|
50
|
-
"moment": "^2.27.0",
|
|
51
|
-
"rgb-hex": "^3.0.0",
|
|
52
|
-
"request": "^2.88.2",
|
|
53
|
-
"colornames": "^1.1.1",
|
|
48
|
+
"async": "^3.2.2",
|
|
49
|
+
"axios": "^0.24.0",
|
|
54
50
|
"color-namer": "^1.4.0",
|
|
55
|
-
"
|
|
51
|
+
"colornames": "^1.1.1",
|
|
52
|
+
"dayjs": "^1.10.7",
|
|
53
|
+
"deep-object-diff": "^1.1.0",
|
|
54
|
+
"eventsource": "^1.1.0",
|
|
55
|
+
"get-image-colors": "^4.0.0"
|
|
56
56
|
}
|
|
57
57
|
}
|
package/examples/Hue Switch.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": "e3a959fd.39da6",
|
|
4
|
-
"type": "tab",
|
|
5
|
-
"label": "Hue Switch (example)",
|
|
6
|
-
"disabled": false,
|
|
7
|
-
"info": "Example use of the Hue Switch node"
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
"id": "d481c97b.56f63",
|
|
11
|
-
"type": "debug",
|
|
12
|
-
"z": "e3a959fd.39da6",
|
|
13
|
-
"name": "Information",
|
|
14
|
-
"active": true,
|
|
15
|
-
"tosidebar": true,
|
|
16
|
-
"console": false,
|
|
17
|
-
"tostatus": false,
|
|
18
|
-
"complete": "payload",
|
|
19
|
-
"targetType": "msg",
|
|
20
|
-
"x": 330,
|
|
21
|
-
"y": 60,
|
|
22
|
-
"wires": [],
|
|
23
|
-
"icon": "font-awesome/fa-info-circle"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"id": "de4dca53.31075",
|
|
27
|
-
"type": "hue-switch",
|
|
28
|
-
"z": "e3a959fd.39da6",
|
|
29
|
-
"name": "",
|
|
30
|
-
"sensorid": "",
|
|
31
|
-
"skipevents": false,
|
|
32
|
-
"x": 130,
|
|
33
|
-
"y": 60,
|
|
34
|
-
"wires": [
|
|
35
|
-
[
|
|
36
|
-
"d481c97b.56f63"
|
|
37
|
-
]
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
]
|
package/examples/Hue Tap.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": "e3a959fd.39da6",
|
|
4
|
-
"type": "tab",
|
|
5
|
-
"label": "Hue Tap (example)",
|
|
6
|
-
"disabled": false,
|
|
7
|
-
"info": "Example use of the Hue Tap node"
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
"id": "d481c97b.56f63",
|
|
11
|
-
"type": "debug",
|
|
12
|
-
"z": "e3a959fd.39da6",
|
|
13
|
-
"name": "Information",
|
|
14
|
-
"active": true,
|
|
15
|
-
"tosidebar": true,
|
|
16
|
-
"console": false,
|
|
17
|
-
"tostatus": false,
|
|
18
|
-
"complete": "payload",
|
|
19
|
-
"targetType": "msg",
|
|
20
|
-
"x": 310,
|
|
21
|
-
"y": 60,
|
|
22
|
-
"wires": [],
|
|
23
|
-
"icon": "font-awesome/fa-info-circle"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"id": "7553e1a.fc48c2",
|
|
27
|
-
"type": "hue-tap",
|
|
28
|
-
"z": "e3a959fd.39da6",
|
|
29
|
-
"name": "",
|
|
30
|
-
"sensorid": "",
|
|
31
|
-
"skipevents": false,
|
|
32
|
-
"x": 120,
|
|
33
|
-
"y": 60,
|
|
34
|
-
"wires": [
|
|
35
|
-
[
|
|
36
|
-
"d481c97b.56f63"
|
|
37
|
-
]
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
]
|
package/huemagic/assets/anime.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* anime.js v3.1.0
|
|
3
|
-
* (c) 2019 Julian Garnier
|
|
4
|
-
* Released under the MIT license
|
|
5
|
-
* animejs.com
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):n.anime=e()}(this,function(){"use strict";var n={update:null,begin:null,loopBegin:null,changeBegin:null,change:null,changeComplete:null,loopComplete:null,complete:null,loop:1,direction:"normal",autoplay:!0,timelineOffset:0},e={duration:1e3,delay:0,endDelay:0,easing:"easeOutElastic(1, .5)",round:0},r=["translateX","translateY","translateZ","rotate","rotateX","rotateY","rotateZ","scale","scaleX","scaleY","scaleZ","skew","skewX","skewY","perspective"],t={CSS:{},springs:{}};function a(n,e,r){return Math.min(Math.max(n,e),r)}function o(n,e){return n.indexOf(e)>-1}function u(n,e){return n.apply(null,e)}var i={arr:function(n){return Array.isArray(n)},obj:function(n){return o(Object.prototype.toString.call(n),"Object")},pth:function(n){return i.obj(n)&&n.hasOwnProperty("totalLength")},svg:function(n){return n instanceof SVGElement},inp:function(n){return n instanceof HTMLInputElement},dom:function(n){return n.nodeType||i.svg(n)},str:function(n){return"string"==typeof n},fnc:function(n){return"function"==typeof n},und:function(n){return void 0===n},hex:function(n){return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(n)},rgb:function(n){return/^rgb/.test(n)},hsl:function(n){return/^hsl/.test(n)},col:function(n){return i.hex(n)||i.rgb(n)||i.hsl(n)},key:function(r){return!n.hasOwnProperty(r)&&!e.hasOwnProperty(r)&&"targets"!==r&&"keyframes"!==r}};function c(n){var e=/\(([^)]+)\)/.exec(n);return e?e[1].split(",").map(function(n){return parseFloat(n)}):[]}function s(n,e){var r=c(n),o=a(i.und(r[0])?1:r[0],.1,100),u=a(i.und(r[1])?100:r[1],.1,100),s=a(i.und(r[2])?10:r[2],.1,100),f=a(i.und(r[3])?0:r[3],.1,100),l=Math.sqrt(u/o),d=s/(2*Math.sqrt(u*o)),p=d<1?l*Math.sqrt(1-d*d):0,h=1,v=d<1?(d*l-f)/p:-f+l;function g(n){var r=e?e*n/1e3:n;return r=d<1?Math.exp(-r*d*l)*(h*Math.cos(p*r)+v*Math.sin(p*r)):(h+v*r)*Math.exp(-r*l),0===n||1===n?n:1-r}return e?g:function(){var e=t.springs[n];if(e)return e;for(var r=0,a=0;;)if(1===g(r+=1/6)){if(++a>=16)break}else a=0;var o=r*(1/6)*1e3;return t.springs[n]=o,o}}function f(n){return void 0===n&&(n=10),function(e){return Math.round(e*n)*(1/n)}}var l,d,p=function(){var n=11,e=1/(n-1);function r(n,e){return 1-3*e+3*n}function t(n,e){return 3*e-6*n}function a(n){return 3*n}function o(n,e,o){return((r(e,o)*n+t(e,o))*n+a(e))*n}function u(n,e,o){return 3*r(e,o)*n*n+2*t(e,o)*n+a(e)}return function(r,t,a,i){if(0<=r&&r<=1&&0<=a&&a<=1){var c=new Float32Array(n);if(r!==t||a!==i)for(var s=0;s<n;++s)c[s]=o(s*e,r,a);return function(n){return r===t&&a===i?n:0===n||1===n?n:o(f(n),t,i)}}function f(t){for(var i=0,s=1,f=n-1;s!==f&&c[s]<=t;++s)i+=e;var l=i+(t-c[--s])/(c[s+1]-c[s])*e,d=u(l,r,a);return d>=.001?function(n,e,r,t){for(var a=0;a<4;++a){var i=u(e,r,t);if(0===i)return e;e-=(o(e,r,t)-n)/i}return e}(t,l,r,a):0===d?l:function(n,e,r,t,a){for(var u,i,c=0;(u=o(i=e+(r-e)/2,t,a)-n)>0?r=i:e=i,Math.abs(u)>1e-7&&++c<10;);return i}(t,i,i+e,r,a)}}}(),h=(l={linear:function(){return function(n){return n}}},d={Sine:function(){return function(n){return 1-Math.cos(n*Math.PI/2)}},Circ:function(){return function(n){return 1-Math.sqrt(1-n*n)}},Back:function(){return function(n){return n*n*(3*n-2)}},Bounce:function(){return function(n){for(var e,r=4;n<((e=Math.pow(2,--r))-1)/11;);return 1/Math.pow(4,3-r)-7.5625*Math.pow((3*e-2)/22-n,2)}},Elastic:function(n,e){void 0===n&&(n=1),void 0===e&&(e=.5);var r=a(n,1,10),t=a(e,.1,2);return function(n){return 0===n||1===n?n:-r*Math.pow(2,10*(n-1))*Math.sin((n-1-t/(2*Math.PI)*Math.asin(1/r))*(2*Math.PI)/t)}}},["Quad","Cubic","Quart","Quint","Expo"].forEach(function(n,e){d[n]=function(){return function(n){return Math.pow(n,e+2)}}}),Object.keys(d).forEach(function(n){var e=d[n];l["easeIn"+n]=e,l["easeOut"+n]=function(n,r){return function(t){return 1-e(n,r)(1-t)}},l["easeInOut"+n]=function(n,r){return function(t){return t<.5?e(n,r)(2*t)/2:1-e(n,r)(-2*t+2)/2}}}),l);function v(n,e){if(i.fnc(n))return n;var r=n.split("(")[0],t=h[r],a=c(n);switch(r){case"spring":return s(n,e);case"cubicBezier":return u(p,a);case"steps":return u(f,a);default:return u(t,a)}}function g(n){try{return document.querySelectorAll(n)}catch(n){return}}function m(n,e){for(var r=n.length,t=arguments.length>=2?arguments[1]:void 0,a=[],o=0;o<r;o++)if(o in n){var u=n[o];e.call(t,u,o,n)&&a.push(u)}return a}function y(n){return n.reduce(function(n,e){return n.concat(i.arr(e)?y(e):e)},[])}function b(n){return i.arr(n)?n:(i.str(n)&&(n=g(n)||n),n instanceof NodeList||n instanceof HTMLCollection?[].slice.call(n):[n])}function M(n,e){return n.some(function(n){return n===e})}function x(n){var e={};for(var r in n)e[r]=n[r];return e}function w(n,e){var r=x(n);for(var t in n)r[t]=e.hasOwnProperty(t)?e[t]:n[t];return r}function k(n,e){var r=x(n);for(var t in e)r[t]=i.und(n[t])?e[t]:n[t];return r}function O(n){return i.rgb(n)?(r=/rgb\((\d+,\s*[\d]+,\s*[\d]+)\)/g.exec(e=n))?"rgba("+r[1]+",1)":e:i.hex(n)?(t=n.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i,function(n,e,r,t){return e+e+r+r+t+t}),a=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t),"rgba("+parseInt(a[1],16)+","+parseInt(a[2],16)+","+parseInt(a[3],16)+",1)"):i.hsl(n)?function(n){var e,r,t,a=/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(n)||/hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(n),o=parseInt(a[1],10)/360,u=parseInt(a[2],10)/100,i=parseInt(a[3],10)/100,c=a[4]||1;function s(n,e,r){return r<0&&(r+=1),r>1&&(r-=1),r<1/6?n+6*(e-n)*r:r<.5?e:r<2/3?n+(e-n)*(2/3-r)*6:n}if(0==u)e=r=t=i;else{var f=i<.5?i*(1+u):i+u-i*u,l=2*i-f;e=s(l,f,o+1/3),r=s(l,f,o),t=s(l,f,o-1/3)}return"rgba("+255*e+","+255*r+","+255*t+","+c+")"}(n):void 0;var e,r,t,a}function C(n){var e=/[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(n);if(e)return e[1]}function B(n,e){return i.fnc(n)?n(e.target,e.id,e.total):n}function P(n,e){return n.getAttribute(e)}function I(n,e,r){if(M([r,"deg","rad","turn"],C(e)))return e;var a=t.CSS[e+r];if(!i.und(a))return a;var o=document.createElement(n.tagName),u=n.parentNode&&n.parentNode!==document?n.parentNode:document.body;u.appendChild(o),o.style.position="absolute",o.style.width=100+r;var c=100/o.offsetWidth;u.removeChild(o);var s=c*parseFloat(e);return t.CSS[e+r]=s,s}function T(n,e,r){if(e in n.style){var t=e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase(),a=n.style[e]||getComputedStyle(n).getPropertyValue(t)||"0";return r?I(n,a,r):a}}function D(n,e){return i.dom(n)&&!i.inp(n)&&(P(n,e)||i.svg(n)&&n[e])?"attribute":i.dom(n)&&M(r,e)?"transform":i.dom(n)&&"transform"!==e&&T(n,e)?"css":null!=n[e]?"object":void 0}function E(n){if(i.dom(n)){for(var e,r=n.style.transform||"",t=/(\w+)\(([^)]*)\)/g,a=new Map;e=t.exec(r);)a.set(e[1],e[2]);return a}}function F(n,e,r,t){var a,u=o(e,"scale")?1:0+(o(a=e,"translate")||"perspective"===a?"px":o(a,"rotate")||o(a,"skew")?"deg":void 0),i=E(n).get(e)||u;return r&&(r.transforms.list.set(e,i),r.transforms.last=e),t?I(n,i,t):i}function N(n,e,r,t){switch(D(n,e)){case"transform":return F(n,e,t,r);case"css":return T(n,e,r);case"attribute":return P(n,e);default:return n[e]||0}}function A(n,e){var r=/^(\*=|\+=|-=)/.exec(n);if(!r)return n;var t=C(n)||0,a=parseFloat(e),o=parseFloat(n.replace(r[0],""));switch(r[0][0]){case"+":return a+o+t;case"-":return a-o+t;case"*":return a*o+t}}function L(n,e){if(i.col(n))return O(n);if(/\s/g.test(n))return n;var r=C(n),t=r?n.substr(0,n.length-r.length):n;return e?t+e:t}function j(n,e){return Math.sqrt(Math.pow(e.x-n.x,2)+Math.pow(e.y-n.y,2))}function S(n){for(var e,r=n.points,t=0,a=0;a<r.numberOfItems;a++){var o=r.getItem(a);a>0&&(t+=j(e,o)),e=o}return t}function q(n){if(n.getTotalLength)return n.getTotalLength();switch(n.tagName.toLowerCase()){case"circle":return o=n,2*Math.PI*P(o,"r");case"rect":return 2*P(a=n,"width")+2*P(a,"height");case"line":return j({x:P(t=n,"x1"),y:P(t,"y1")},{x:P(t,"x2"),y:P(t,"y2")});case"polyline":return S(n);case"polygon":return r=(e=n).points,S(e)+j(r.getItem(r.numberOfItems-1),r.getItem(0))}var e,r,t,a,o}function $(n,e){var r=e||{},t=r.el||function(n){for(var e=n.parentNode;i.svg(e)&&i.svg(e.parentNode);)e=e.parentNode;return e}(n),a=t.getBoundingClientRect(),o=P(t,"viewBox"),u=a.width,c=a.height,s=r.viewBox||(o?o.split(" "):[0,0,u,c]);return{el:t,viewBox:s,x:s[0]/1,y:s[1]/1,w:u/s[2],h:c/s[3]}}function X(n,e){function r(r){void 0===r&&(r=0);var t=e+r>=1?e+r:0;return n.el.getPointAtLength(t)}var t=$(n.el,n.svg),a=r(),o=r(-1),u=r(1);switch(n.property){case"x":return(a.x-t.x)*t.w;case"y":return(a.y-t.y)*t.h;case"angle":return 180*Math.atan2(u.y-o.y,u.x-o.x)/Math.PI}}function Y(n,e){var r=/[+-]?\d*\.?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g,t=L(i.pth(n)?n.totalLength:n,e)+"";return{original:t,numbers:t.match(r)?t.match(r).map(Number):[0],strings:i.str(n)||e?t.split(r):[]}}function Z(n){return m(n?y(i.arr(n)?n.map(b):b(n)):[],function(n,e,r){return r.indexOf(n)===e})}function Q(n){var e=Z(n);return e.map(function(n,r){return{target:n,id:r,total:e.length,transforms:{list:E(n)}}})}function V(n,e){var r=x(e);if(/^spring/.test(r.easing)&&(r.duration=s(r.easing)),i.arr(n)){var t=n.length;2===t&&!i.obj(n[0])?n={value:n}:i.fnc(e.duration)||(r.duration=e.duration/t)}var a=i.arr(n)?n:[n];return a.map(function(n,r){var t=i.obj(n)&&!i.pth(n)?n:{value:n};return i.und(t.delay)&&(t.delay=r?0:e.delay),i.und(t.endDelay)&&(t.endDelay=r===a.length-1?e.endDelay:0),t}).map(function(n){return k(n,r)})}function z(n,e){var r=[],t=e.keyframes;for(var a in t&&(e=k(function(n){for(var e=m(y(n.map(function(n){return Object.keys(n)})),function(n){return i.key(n)}).reduce(function(n,e){return n.indexOf(e)<0&&n.push(e),n},[]),r={},t=function(t){var a=e[t];r[a]=n.map(function(n){var e={};for(var r in n)i.key(r)?r==a&&(e.value=n[r]):e[r]=n[r];return e})},a=0;a<e.length;a++)t(a);return r}(t),e)),e)i.key(a)&&r.push({name:a,tweens:V(e[a],n)});return r}function H(n,e){var r;return n.tweens.map(function(t){var a=function(n,e){var r={};for(var t in n){var a=B(n[t],e);i.arr(a)&&1===(a=a.map(function(n){return B(n,e)})).length&&(a=a[0]),r[t]=a}return r.duration=parseFloat(r.duration),r.delay=parseFloat(r.delay),r}(t,e),o=a.value,u=i.arr(o)?o[1]:o,c=C(u),s=N(e.target,n.name,c,e),f=r?r.to.original:s,l=i.arr(o)?o[0]:f,d=C(l)||C(s),p=c||d;return i.und(u)&&(u=f),a.from=Y(l,p),a.to=Y(A(u,l),p),a.start=r?r.end:0,a.end=a.start+a.delay+a.duration+a.endDelay,a.easing=v(a.easing,a.duration),a.isPath=i.pth(o),a.isColor=i.col(a.from.original),a.isColor&&(a.round=1),r=a,a})}var G={css:function(n,e,r){return n.style[e]=r},attribute:function(n,e,r){return n.setAttribute(e,r)},object:function(n,e,r){return n[e]=r},transform:function(n,e,r,t,a){if(t.list.set(e,r),e===t.last||a){var o="";t.list.forEach(function(n,e){o+=e+"("+n+") "}),n.style.transform=o}}};function R(n,e){Q(n).forEach(function(n){for(var r in e){var t=B(e[r],n),a=n.target,o=C(t),u=N(a,r,o,n),i=A(L(t,o||C(u)),u),c=D(a,r);G[c](a,r,i,n.transforms,!0)}})}function W(n,e){return m(y(n.map(function(n){return e.map(function(e){return function(n,e){var r=D(n.target,e.name);if(r){var t=H(e,n),a=t[t.length-1];return{type:r,property:e.name,animatable:n,tweens:t,duration:a.end,delay:t[0].delay,endDelay:a.endDelay}}}(n,e)})})),function(n){return!i.und(n)})}function J(n,e){var r=n.length,t=function(n){return n.timelineOffset?n.timelineOffset:0},a={};return a.duration=r?Math.max.apply(Math,n.map(function(n){return t(n)+n.duration})):e.duration,a.delay=r?Math.min.apply(Math,n.map(function(n){return t(n)+n.delay})):e.delay,a.endDelay=r?a.duration-Math.max.apply(Math,n.map(function(n){return t(n)+n.duration-n.endDelay})):e.endDelay,a}var K=0;var U,_=[],nn=[],en=function(){function n(){U=requestAnimationFrame(e)}function e(e){var r=_.length;if(r){for(var t=0;t<r;){var a=_[t];if(a.paused){var o=_.indexOf(a);o>-1&&(_.splice(o,1),r=_.length)}else a.tick(e);t++}n()}else U=cancelAnimationFrame(U)}return n}();function rn(r){void 0===r&&(r={});var t,o=0,u=0,i=0,c=0,s=null;function f(n){var e=window.Promise&&new Promise(function(n){return s=n});return n.finished=e,e}var l,d,p,h,v,g,y,b,M=(d=w(n,l=r),p=w(e,l),h=z(p,l),v=Q(l.targets),g=W(v,h),y=J(g,p),b=K,K++,k(d,{id:b,children:[],animatables:v,animations:g,duration:y.duration,delay:y.delay,endDelay:y.endDelay}));f(M);function x(){var n=M.direction;"alternate"!==n&&(M.direction="normal"!==n?"normal":"reverse"),M.reversed=!M.reversed,t.forEach(function(n){return n.reversed=M.reversed})}function O(n){return M.reversed?M.duration-n:n}function C(){o=0,u=O(M.currentTime)*(1/rn.speed)}function B(n,e){e&&e.seek(n-e.timelineOffset)}function P(n){for(var e=0,r=M.animations,t=r.length;e<t;){var o=r[e],u=o.animatable,i=o.tweens,c=i.length-1,s=i[c];c&&(s=m(i,function(e){return n<e.end})[0]||s);for(var f=a(n-s.start-s.delay,0,s.duration)/s.duration,l=isNaN(f)?1:s.easing(f),d=s.to.strings,p=s.round,h=[],v=s.to.numbers.length,g=void 0,y=0;y<v;y++){var b=void 0,x=s.to.numbers[y],w=s.from.numbers[y]||0;b=s.isPath?X(s.value,l*x):w+l*(x-w),p&&(s.isColor&&y>2||(b=Math.round(b*p)/p)),h.push(b)}var k=d.length;if(k){g=d[0];for(var O=0;O<k;O++){d[O];var C=d[O+1],B=h[O];isNaN(B)||(g+=C?B+C:B+" ")}}else g=h[0];G[o.type](u.target,o.property,g,u.transforms),o.currentValue=g,e++}}function I(n){M[n]&&!M.passThrough&&M[n](M)}function T(n){var e=M.duration,r=M.delay,l=e-M.endDelay,d=O(n);M.progress=a(d/e*100,0,100),M.reversePlayback=d<M.currentTime,t&&function(n){if(M.reversePlayback)for(var e=c;e--;)B(n,t[e]);else for(var r=0;r<c;r++)B(n,t[r])}(d),!M.began&&M.currentTime>0&&(M.began=!0,I("begin")),!M.loopBegan&&M.currentTime>0&&(M.loopBegan=!0,I("loopBegin")),d<=r&&0!==M.currentTime&&P(0),(d>=l&&M.currentTime!==e||!e)&&P(e),d>r&&d<l?(M.changeBegan||(M.changeBegan=!0,M.changeCompleted=!1,I("changeBegin")),I("change"),P(d)):M.changeBegan&&(M.changeCompleted=!0,M.changeBegan=!1,I("changeComplete")),M.currentTime=a(d,0,e),M.began&&I("update"),n>=e&&(u=0,M.remaining&&!0!==M.remaining&&M.remaining--,M.remaining?(o=i,I("loopComplete"),M.loopBegan=!1,"alternate"===M.direction&&x()):(M.paused=!0,M.completed||(M.completed=!0,I("loopComplete"),I("complete"),!M.passThrough&&"Promise"in window&&(s(),f(M)))))}return M.reset=function(){var n=M.direction;M.passThrough=!1,M.currentTime=0,M.progress=0,M.paused=!0,M.began=!1,M.loopBegan=!1,M.changeBegan=!1,M.completed=!1,M.changeCompleted=!1,M.reversePlayback=!1,M.reversed="reverse"===n,M.remaining=M.loop,t=M.children;for(var e=c=t.length;e--;)M.children[e].reset();(M.reversed&&!0!==M.loop||"alternate"===n&&1===M.loop)&&M.remaining++,P(M.reversed?M.duration:0)},M.set=function(n,e){return R(n,e),M},M.tick=function(n){i=n,o||(o=i),T((i+(u-o))*rn.speed)},M.seek=function(n){T(O(n))},M.pause=function(){M.paused=!0,C()},M.play=function(){M.paused&&(M.completed&&M.reset(),M.paused=!1,_.push(M),C(),U||en())},M.reverse=function(){x(),C()},M.restart=function(){M.reset(),M.play()},M.reset(),M.autoplay&&M.play(),M}function tn(n,e){for(var r=e.length;r--;)M(n,e[r].animatable.target)&&e.splice(r,1)}return"undefined"!=typeof document&&document.addEventListener("visibilitychange",function(){document.hidden?(_.forEach(function(n){return n.pause()}),nn=_.slice(0),rn.running=_=[]):nn.forEach(function(n){return n.play()})}),rn.version="3.1.0",rn.speed=1,rn.running=_,rn.remove=function(n){for(var e=Z(n),r=_.length;r--;){var t=_[r],a=t.animations,o=t.children;tn(e,a);for(var u=o.length;u--;){var i=o[u],c=i.animations;tn(e,c),c.length||i.children.length||o.splice(u,1)}a.length||o.length||t.pause()}},rn.get=N,rn.set=R,rn.convertPx=I,rn.path=function(n,e){var r=i.str(n)?g(n)[0]:n,t=e||100;return function(n){return{property:n,el:r,svg:$(r),totalLength:q(r)*(t/100)}}},rn.setDashoffset=function(n){var e=q(n);return n.setAttribute("stroke-dasharray",e),e},rn.stagger=function(n,e){void 0===e&&(e={});var r=e.direction||"normal",t=e.easing?v(e.easing):null,a=e.grid,o=e.axis,u=e.from||0,c="first"===u,s="center"===u,f="last"===u,l=i.arr(n),d=l?parseFloat(n[0]):parseFloat(n),p=l?parseFloat(n[1]):0,h=C(l?n[1]:n)||0,g=e.start||0+(l?d:0),m=[],y=0;return function(n,e,i){if(c&&(u=0),s&&(u=(i-1)/2),f&&(u=i-1),!m.length){for(var v=0;v<i;v++){if(a){var b=s?(a[0]-1)/2:u%a[0],M=s?(a[1]-1)/2:Math.floor(u/a[0]),x=b-v%a[0],w=M-Math.floor(v/a[0]),k=Math.sqrt(x*x+w*w);"x"===o&&(k=-x),"y"===o&&(k=-w),m.push(k)}else m.push(Math.abs(u-v));y=Math.max.apply(Math,m)}t&&(m=m.map(function(n){return t(n/y)*y})),"reverse"===r&&(m=m.map(function(n){return o?n<0?-1*n:-n:Math.abs(y-n)}))}return g+(l?(p-d)/y:d)*(Math.round(100*m[e])/100)+h}},rn.timeline=function(n){void 0===n&&(n={});var r=rn(n);return r.duration=0,r.add=function(t,a){var o=_.indexOf(r),u=r.children;function c(n){n.passThrough=!0}o>-1&&_.splice(o,1);for(var s=0;s<u.length;s++)c(u[s]);var f=k(t,w(e,n));f.targets=f.targets||n.targets;var l=r.duration;f.autoplay=!1,f.direction=r.direction,f.timelineOffset=i.und(a)?l:A(a,l),c(r),r.seek(f.timelineOffset);var d=rn(f);c(d),u.push(d);var p=J(u,n);return r.delay=p.delay,r.endDelay=p.endDelay,r.duration=p.duration,r.seek(0),r.reset(),r.autoplay&&r.play(),r},r},rn.easing=v,rn.penner=h,rn.random=function(n,e){return Math.floor(Math.random()*(e-n+1))+n},rn});
|