node-red-contrib-huemagic 4.2.2 → 5.0.1
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 +94 -5
- package/README.md +525 -123
- package/examples/Deutsch/Hue Automation.json +176 -0
- package/examples/Deutsch/Hue Bridge.json +256 -0
- package/examples/Deutsch/Hue Brightness.json +150 -0
- package/examples/Deutsch/Hue Buttons.json +88 -0
- package/examples/Deutsch/Hue Contact.json +150 -0
- package/examples/Deutsch/Hue Group.json +658 -0
- package/examples/Deutsch/Hue Light.json +893 -0
- package/examples/Deutsch/Hue Magic.json +148 -0
- package/examples/Deutsch/Hue Motion.json +150 -0
- package/examples/Deutsch/Hue Rules.json +150 -0
- package/examples/Deutsch/Hue Scene.json +178 -0
- package/examples/Deutsch/Hue Speaker.json +274 -0
- package/examples/Deutsch/Hue Sync Box.json +378 -0
- package/examples/Deutsch/Hue Temperature.json +150 -0
- package/examples/English/Hue Automation.json +176 -0
- package/examples/{Hue Bridge.json → English/Hue Bridge.json } +1 -1
- package/examples/{Hue Brightness.json → English/Hue Brightness.json } +1 -1
- package/examples/{Hue Buttons.json → English/Hue Buttons.json } +1 -1
- package/examples/English/Hue Contact.json +150 -0
- package/examples/{Hue Group.json → English/Hue Group.json } +1 -1
- package/examples/{Hue Light.json → English/Hue Light.json } +1 -1
- package/examples/{Hue Magic.json → English/Hue Magic.json } +1 -1
- package/examples/{Hue Motion.json → English/Hue Motion.json } +1 -1
- package/examples/{Hue Rules.json → English/Hue Rules.json } +1 -1
- package/examples/{Hue Scene.json → English/Hue Scene.json } +1 -1
- package/examples/English/Hue Speaker.json +274 -0
- package/examples/English/Hue Sync Box.json +378 -0
- package/examples/{Hue Temperature.json → English/Hue Temperature.json } +1 -1
- package/examples/Espa/303/261ol/Hue Automation.json" +176 -0
- package/examples/Espa/303/261ol/Hue Bridge.json" +256 -0
- package/examples/Espa/303/261ol/Hue Brightness.json" +150 -0
- package/examples/Espa/303/261ol/Hue Buttons.json" +88 -0
- package/examples/Espa/303/261ol/Hue Contact.json" +150 -0
- package/examples/Espa/303/261ol/Hue Group.json" +658 -0
- package/examples/Espa/303/261ol/Hue Light.json" +893 -0
- package/examples/Espa/303/261ol/Hue Magic.json" +148 -0
- package/examples/Espa/303/261ol/Hue Motion.json" +150 -0
- package/examples/Espa/303/261ol/Hue Rules.json" +150 -0
- package/examples/Espa/303/261ol/Hue Scene.json" +178 -0
- package/examples/Espa/303/261ol/Hue Speaker.json" +274 -0
- package/examples/Espa/303/261ol/Hue Sync Box.json" +378 -0
- package/examples/Espa/303/261ol/Hue Temperature.json" +150 -0
- package/examples/Fran/303/247ais/Hue Automation.json" +176 -0
- package/examples/Fran/303/247ais/Hue Bridge.json" +256 -0
- package/examples/Fran/303/247ais/Hue Brightness.json" +150 -0
- package/examples/Fran/303/247ais/Hue Buttons.json" +88 -0
- package/examples/Fran/303/247ais/Hue Contact.json" +150 -0
- package/examples/Fran/303/247ais/Hue Group.json" +658 -0
- package/examples/Fran/303/247ais/Hue Light.json" +893 -0
- package/examples/Fran/303/247ais/Hue Magic.json" +148 -0
- package/examples/Fran/303/247ais/Hue Motion.json" +150 -0
- package/examples/Fran/303/247ais/Hue Rules.json" +150 -0
- package/examples/Fran/303/247ais/Hue Scene.json" +178 -0
- package/examples/Fran/303/247ais/Hue Speaker.json" +274 -0
- package/examples/Fran/303/247ais/Hue Sync Box.json" +378 -0
- package/examples/Fran/303/247ais/Hue Temperature.json" +150 -0
- package/examples/Italiano/Hue Automation.json +176 -0
- package/examples/Italiano/Hue Bridge.json +256 -0
- package/examples/Italiano/Hue Brightness.json +150 -0
- package/examples/Italiano/Hue Buttons.json +88 -0
- package/examples/Italiano/Hue Contact.json +150 -0
- package/examples/Italiano/Hue Group.json +658 -0
- package/examples/Italiano/Hue Light.json +893 -0
- package/examples/Italiano/Hue Magic.json +148 -0
- package/examples/Italiano/Hue Motion.json +150 -0
- package/examples/Italiano/Hue Rules.json +150 -0
- package/examples/Italiano/Hue Scene.json +178 -0
- package/examples/Italiano/Hue Speaker.json +274 -0
- package/examples/Italiano/Hue Sync Box.json +378 -0
- package/examples/Italiano/Hue Temperature.json +150 -0
- package/examples/Nederlands/Hue Automation.json +176 -0
- package/examples/Nederlands/Hue Bridge.json +256 -0
- package/examples/Nederlands/Hue Brightness.json +150 -0
- package/examples/Nederlands/Hue Buttons.json +88 -0
- package/examples/Nederlands/Hue Contact.json +150 -0
- package/examples/Nederlands/Hue Group.json +658 -0
- package/examples/Nederlands/Hue Light.json +893 -0
- package/examples/Nederlands/Hue Magic.json +148 -0
- package/examples/Nederlands/Hue Motion.json +150 -0
- package/examples/Nederlands/Hue Rules.json +150 -0
- package/examples/Nederlands/Hue Scene.json +178 -0
- package/examples/Nederlands/Hue Speaker.json +274 -0
- package/examples/Nederlands/Hue Sync Box.json +378 -0
- package/examples/Nederlands/Hue Temperature.json +150 -0
- package/examples/Polski/Hue Automation.json +176 -0
- package/examples/Polski/Hue Bridge.json +256 -0
- package/examples/Polski/Hue Brightness.json +150 -0
- package/examples/Polski/Hue Buttons.json +88 -0
- package/examples/Polski/Hue Contact.json +150 -0
- package/examples/Polski/Hue Group.json +658 -0
- package/examples/Polski/Hue Light.json +893 -0
- package/examples/Polski/Hue Magic.json +148 -0
- package/examples/Polski/Hue Motion.json +150 -0
- package/examples/Polski/Hue Rules.json +150 -0
- package/examples/Polski/Hue Scene.json +178 -0
- package/examples/Polski/Hue Speaker.json +274 -0
- package/examples/Polski/Hue Sync Box.json +378 -0
- package/examples/Polski/Hue Temperature.json +150 -0
- package/examples/Portugu/303/252s/Hue Automation.json" +176 -0
- package/examples/Portugu/303/252s/Hue Bridge.json" +256 -0
- package/examples/Portugu/303/252s/Hue Brightness.json" +150 -0
- package/examples/Portugu/303/252s/Hue Buttons.json" +88 -0
- package/examples/Portugu/303/252s/Hue Contact.json" +150 -0
- package/examples/Portugu/303/252s/Hue Group.json" +658 -0
- package/examples/Portugu/303/252s/Hue Light.json" +893 -0
- package/examples/Portugu/303/252s/Hue Magic.json" +148 -0
- package/examples/Portugu/303/252s/Hue Motion.json" +150 -0
- package/examples/Portugu/303/252s/Hue Rules.json" +150 -0
- package/examples/Portugu/303/252s/Hue Scene.json" +178 -0
- package/examples/Portugu/303/252s/Hue Speaker.json" +274 -0
- package/examples/Portugu/303/252s/Hue Sync Box.json" +378 -0
- package/examples/Portugu/303/252s/Hue Temperature.json" +150 -0
- package/examples/T/303/274rk/303/247e/Hue Automation.json" +176 -0
- package/examples/T/303/274rk/303/247e/Hue Bridge.json" +256 -0
- package/examples/T/303/274rk/303/247e/Hue Brightness.json" +150 -0
- package/examples/T/303/274rk/303/247e/Hue Buttons.json" +88 -0
- package/examples/T/303/274rk/303/247e/Hue Contact.json" +150 -0
- package/examples/T/303/274rk/303/247e/Hue Group.json" +658 -0
- package/examples/T/303/274rk/303/247e/Hue Light.json" +893 -0
- package/examples/T/303/274rk/303/247e/Hue Magic.json" +148 -0
- package/examples/T/303/274rk/303/247e/Hue Motion.json" +150 -0
- package/examples/T/303/274rk/303/247e/Hue Rules.json" +150 -0
- package/examples/T/303/274rk/303/247e/Hue Scene.json" +178 -0
- package/examples/T/303/274rk/303/247e/Hue Speaker.json" +274 -0
- package/examples/T/303/274rk/303/247e/Hue Sync Box.json" +378 -0
- package/examples/T/303/274rk/303/247e/Hue Temperature.json" +150 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Automation.json" +176 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Bridge.json" +256 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Brightness.json" +150 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Buttons.json" +88 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Contact.json" +150 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Group.json" +658 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Light.json" +893 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Magic.json" +148 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Motion.json" +150 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Rules.json" +150 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Scene.json" +178 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Speaker.json" +274 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Sync Box.json" +378 -0
- package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Temperature.json" +150 -0
- package/huemagic/assets/huemagic-examples.gif +0 -0
- package/huemagic/hue-automation.html +218 -0
- package/huemagic/hue-automation.js +173 -0
- package/huemagic/hue-bridge-config.html +39 -32
- package/huemagic/hue-bridge-config.js +290 -99
- package/huemagic/hue-bridge.html +8 -8
- package/huemagic/hue-bridge.js +29 -4
- package/huemagic/hue-brightness.html +21 -9
- package/huemagic/hue-brightness.js +20 -10
- package/huemagic/hue-buttons.html +227 -11
- package/huemagic/hue-buttons.js +183 -28
- package/huemagic/hue-contact.html +218 -0
- package/huemagic/hue-contact.js +209 -0
- package/huemagic/hue-group.html +16 -9
- package/huemagic/hue-group.js +141 -179
- package/huemagic/hue-light.html +19 -12
- package/huemagic/hue-light.js +222 -167
- package/huemagic/hue-magic.html +3 -5
- package/huemagic/hue-motion.html +16 -9
- package/huemagic/hue-motion.js +37 -8
- package/huemagic/hue-rules.html +16 -9
- package/huemagic/hue-rules.js +16 -8
- package/huemagic/hue-scene.html +9 -5
- package/huemagic/hue-scene.js +52 -16
- package/huemagic/hue-speaker.html +218 -0
- package/huemagic/hue-speaker.js +257 -0
- package/huemagic/hue-syncbox-config.html +123 -0
- package/huemagic/hue-syncbox-config.js +179 -0
- package/huemagic/hue-syncbox.html +82 -0
- package/huemagic/hue-syncbox.js +274 -0
- package/huemagic/hue-temperature.html +21 -9
- package/huemagic/hue-temperature.js +18 -10
- package/huemagic/icons/hue-automation.png +0 -0
- package/huemagic/icons/hue-automation.svg +3 -0
- package/huemagic/icons/hue-contact.png +0 -0
- package/huemagic/icons/hue-contact.svg +4 -0
- package/huemagic/icons/hue-speaker.png +0 -0
- package/huemagic/icons/hue-speaker.svg +6 -0
- package/huemagic/icons/hue-syncbox.png +0 -0
- package/huemagic/icons/hue-syncbox.svg +7 -0
- package/huemagic/locales/de/hue-automation.html +59 -0
- package/huemagic/locales/de/hue-automation.json +33 -0
- package/huemagic/locales/de/hue-bridge-config.json +23 -12
- package/huemagic/locales/de/hue-bridge.html +7 -4
- package/huemagic/locales/de/hue-bridge.json +9 -10
- package/huemagic/locales/de/hue-brightness.html +9 -6
- package/huemagic/locales/de/hue-brightness.json +13 -9
- package/huemagic/locales/de/hue-buttons.html +7 -4
- package/huemagic/locales/de/hue-buttons.json +42 -8
- package/huemagic/locales/de/hue-contact.html +67 -0
- package/huemagic/locales/de/hue-contact.json +35 -0
- package/huemagic/locales/de/hue-group.html +17 -6
- package/huemagic/locales/de/hue-group.json +16 -9
- package/huemagic/locales/de/hue-light.html +6 -6
- package/huemagic/locales/de/hue-light.json +17 -9
- package/huemagic/locales/de/hue-magic.html +1 -1
- package/huemagic/locales/de/hue-magic.json +6 -8
- package/huemagic/locales/de/hue-motion.html +4 -4
- package/huemagic/locales/de/hue-motion.json +14 -9
- package/huemagic/locales/de/hue-rules.html +2 -2
- package/huemagic/locales/de/hue-rules.json +10 -9
- package/huemagic/locales/de/hue-scene.html +11 -3
- package/huemagic/locales/de/hue-scene.json +9 -9
- package/huemagic/locales/de/hue-speaker.html +80 -0
- package/huemagic/locales/de/hue-speaker.json +38 -0
- package/huemagic/locales/de/hue-syncbox-config.html +19 -0
- package/huemagic/locales/de/hue-syncbox-config.json +25 -0
- package/huemagic/locales/de/hue-syncbox.html +86 -0
- package/huemagic/locales/de/hue-syncbox.json +30 -0
- package/huemagic/locales/de/hue-temperature.html +7 -5
- package/huemagic/locales/de/hue-temperature.json +13 -9
- package/huemagic/locales/el/hue-automation.html +59 -0
- package/huemagic/locales/el/hue-automation.json +33 -0
- package/huemagic/locales/el/hue-bridge-config.html +31 -0
- package/huemagic/locales/el/hue-bridge-config.json +40 -0
- package/huemagic/locales/el/hue-bridge.html +96 -0
- package/huemagic/locales/el/hue-bridge.json +26 -0
- package/huemagic/locales/el/hue-brightness.html +70 -0
- package/huemagic/locales/el/hue-brightness.json +37 -0
- package/huemagic/locales/el/hue-buttons.html +61 -0
- package/huemagic/locales/el/hue-buttons.json +62 -0
- package/huemagic/locales/el/hue-contact.html +67 -0
- package/huemagic/locales/el/hue-contact.json +35 -0
- package/huemagic/locales/el/hue-group.html +87 -0
- package/huemagic/locales/el/hue-group.json +46 -0
- package/huemagic/locales/el/hue-light.html +97 -0
- package/huemagic/locales/el/hue-light.json +44 -0
- package/huemagic/locales/el/hue-magic.html +68 -0
- package/huemagic/locales/el/hue-magic.json +26 -0
- package/huemagic/locales/el/hue-motion.html +64 -0
- package/huemagic/locales/el/hue-motion.json +36 -0
- package/huemagic/locales/el/hue-rules.html +69 -0
- package/huemagic/locales/el/hue-rules.json +30 -0
- package/huemagic/locales/el/hue-scene.html +43 -0
- package/huemagic/locales/el/hue-scene.json +32 -0
- package/huemagic/locales/el/hue-speaker.html +80 -0
- package/huemagic/locales/el/hue-speaker.json +38 -0
- package/huemagic/locales/el/hue-syncbox-config.html +19 -0
- package/huemagic/locales/el/hue-syncbox-config.json +25 -0
- package/huemagic/locales/el/hue-syncbox.html +86 -0
- package/huemagic/locales/el/hue-syncbox.json +30 -0
- package/huemagic/locales/el/hue-temperature.html +69 -0
- package/huemagic/locales/el/hue-temperature.json +33 -0
- package/huemagic/locales/en/hue-automation.html +59 -0
- package/huemagic/locales/en/hue-automation.json +33 -0
- package/huemagic/locales/en/hue-bridge-config.json +40 -0
- package/huemagic/locales/{en-US → en}/hue-bridge.html +5 -2
- package/huemagic/locales/{en-US → en}/hue-bridge.json +8 -9
- package/huemagic/locales/{en-US → en}/hue-brightness.html +6 -3
- package/huemagic/locales/{en-US → en}/hue-brightness.json +11 -9
- package/huemagic/locales/{en-US → en}/hue-buttons.html +6 -3
- package/huemagic/locales/en/hue-buttons.json +62 -0
- package/huemagic/locales/en/hue-contact.html +67 -0
- package/huemagic/locales/en/hue-contact.json +35 -0
- package/huemagic/locales/{en-US → en}/hue-group.html +16 -5
- package/huemagic/locales/{en-US → en}/hue-group.json +15 -10
- package/huemagic/locales/{en-US → en}/hue-light.html +3 -3
- package/huemagic/locales/en/hue-light.json +44 -0
- package/huemagic/locales/{en-US → en}/hue-magic.html +1 -1
- package/huemagic/locales/{en-US → en}/hue-motion.html +2 -2
- package/huemagic/locales/{en-US → en}/hue-motion.json +12 -9
- package/huemagic/locales/{en-US → en}/hue-rules.html +2 -2
- package/huemagic/locales/{en-US → en}/hue-rules.json +10 -9
- package/huemagic/locales/{en-US → en}/hue-scene.html +11 -3
- package/huemagic/locales/{en-US → en}/hue-scene.json +9 -9
- package/huemagic/locales/en/hue-speaker.html +80 -0
- package/huemagic/locales/en/hue-speaker.json +38 -0
- package/huemagic/locales/en/hue-syncbox-config.html +19 -0
- package/huemagic/locales/en/hue-syncbox-config.json +25 -0
- package/huemagic/locales/en/hue-syncbox.html +86 -0
- package/huemagic/locales/en/hue-syncbox.json +30 -0
- package/huemagic/locales/{en-US → en}/hue-temperature.html +4 -2
- package/huemagic/locales/{en-US → en}/hue-temperature.json +11 -9
- package/huemagic/locales/es/hue-automation.html +59 -0
- package/huemagic/locales/es/hue-automation.json +33 -0
- package/huemagic/locales/es/hue-bridge-config.html +31 -0
- package/huemagic/locales/es/hue-bridge-config.json +40 -0
- package/huemagic/locales/es/hue-bridge.html +96 -0
- package/huemagic/locales/es/hue-bridge.json +26 -0
- package/huemagic/locales/es/hue-brightness.html +70 -0
- package/huemagic/locales/es/hue-brightness.json +37 -0
- package/huemagic/locales/es/hue-buttons.html +61 -0
- package/huemagic/locales/es/hue-buttons.json +62 -0
- package/huemagic/locales/es/hue-contact.html +67 -0
- package/huemagic/locales/es/hue-contact.json +35 -0
- package/huemagic/locales/es/hue-group.html +87 -0
- package/huemagic/locales/es/hue-group.json +46 -0
- package/huemagic/locales/es/hue-light.html +97 -0
- package/huemagic/locales/es/hue-light.json +44 -0
- package/huemagic/locales/es/hue-magic.html +68 -0
- package/huemagic/locales/es/hue-magic.json +26 -0
- package/huemagic/locales/es/hue-motion.html +64 -0
- package/huemagic/locales/es/hue-motion.json +36 -0
- package/huemagic/locales/es/hue-rules.html +69 -0
- package/huemagic/locales/es/hue-rules.json +30 -0
- package/huemagic/locales/es/hue-scene.html +43 -0
- package/huemagic/locales/es/hue-scene.json +32 -0
- package/huemagic/locales/es/hue-speaker.html +80 -0
- package/huemagic/locales/es/hue-speaker.json +38 -0
- package/huemagic/locales/es/hue-syncbox-config.html +19 -0
- package/huemagic/locales/es/hue-syncbox-config.json +25 -0
- package/huemagic/locales/es/hue-syncbox.html +86 -0
- package/huemagic/locales/es/hue-syncbox.json +30 -0
- package/huemagic/locales/es/hue-temperature.html +69 -0
- package/huemagic/locales/es/hue-temperature.json +33 -0
- package/huemagic/locales/fr/hue-automation.html +59 -0
- package/huemagic/locales/fr/hue-automation.json +33 -0
- package/huemagic/locales/fr/hue-bridge-config.html +31 -0
- package/huemagic/locales/fr/hue-bridge-config.json +40 -0
- package/huemagic/locales/fr/hue-bridge.html +96 -0
- package/huemagic/locales/fr/hue-bridge.json +26 -0
- package/huemagic/locales/fr/hue-brightness.html +70 -0
- package/huemagic/locales/fr/hue-brightness.json +37 -0
- package/huemagic/locales/fr/hue-buttons.html +61 -0
- package/huemagic/locales/fr/hue-buttons.json +62 -0
- package/huemagic/locales/fr/hue-contact.html +67 -0
- package/huemagic/locales/fr/hue-contact.json +35 -0
- package/huemagic/locales/fr/hue-group.html +87 -0
- package/huemagic/locales/fr/hue-group.json +46 -0
- package/huemagic/locales/fr/hue-light.html +97 -0
- package/huemagic/locales/fr/hue-light.json +44 -0
- package/huemagic/locales/fr/hue-magic.html +68 -0
- package/huemagic/locales/fr/hue-magic.json +26 -0
- package/huemagic/locales/fr/hue-motion.html +64 -0
- package/huemagic/locales/fr/hue-motion.json +36 -0
- package/huemagic/locales/fr/hue-rules.html +69 -0
- package/huemagic/locales/fr/hue-rules.json +30 -0
- package/huemagic/locales/fr/hue-scene.html +43 -0
- package/huemagic/locales/fr/hue-scene.json +32 -0
- package/huemagic/locales/fr/hue-speaker.html +80 -0
- package/huemagic/locales/fr/hue-speaker.json +38 -0
- package/huemagic/locales/fr/hue-syncbox-config.html +19 -0
- package/huemagic/locales/fr/hue-syncbox-config.json +25 -0
- package/huemagic/locales/fr/hue-syncbox.html +86 -0
- package/huemagic/locales/fr/hue-syncbox.json +30 -0
- package/huemagic/locales/fr/hue-temperature.html +69 -0
- package/huemagic/locales/fr/hue-temperature.json +33 -0
- package/huemagic/locales/it/hue-automation.html +59 -0
- package/huemagic/locales/it/hue-automation.json +33 -0
- package/huemagic/locales/it/hue-bridge-config.html +31 -0
- package/huemagic/locales/it/hue-bridge-config.json +40 -0
- package/huemagic/locales/it/hue-bridge.html +96 -0
- package/huemagic/locales/it/hue-bridge.json +26 -0
- package/huemagic/locales/it/hue-brightness.html +70 -0
- package/huemagic/locales/it/hue-brightness.json +37 -0
- package/huemagic/locales/it/hue-buttons.html +61 -0
- package/huemagic/locales/it/hue-buttons.json +62 -0
- package/huemagic/locales/it/hue-contact.html +67 -0
- package/huemagic/locales/it/hue-contact.json +35 -0
- package/huemagic/locales/it/hue-group.html +87 -0
- package/huemagic/locales/it/hue-group.json +46 -0
- package/huemagic/locales/it/hue-light.html +97 -0
- package/huemagic/locales/it/hue-light.json +44 -0
- package/huemagic/locales/it/hue-magic.html +68 -0
- package/huemagic/locales/it/hue-magic.json +26 -0
- package/huemagic/locales/it/hue-motion.html +64 -0
- package/huemagic/locales/it/hue-motion.json +36 -0
- package/huemagic/locales/it/hue-rules.html +69 -0
- package/huemagic/locales/it/hue-rules.json +30 -0
- package/huemagic/locales/it/hue-scene.html +43 -0
- package/huemagic/locales/it/hue-scene.json +32 -0
- package/huemagic/locales/it/hue-speaker.html +80 -0
- package/huemagic/locales/it/hue-speaker.json +38 -0
- package/huemagic/locales/it/hue-syncbox-config.html +19 -0
- package/huemagic/locales/it/hue-syncbox-config.json +25 -0
- package/huemagic/locales/it/hue-syncbox.html +86 -0
- package/huemagic/locales/it/hue-syncbox.json +30 -0
- package/huemagic/locales/it/hue-temperature.html +69 -0
- package/huemagic/locales/it/hue-temperature.json +33 -0
- package/huemagic/locales/nl/hue-automation.html +59 -0
- package/huemagic/locales/nl/hue-automation.json +33 -0
- package/huemagic/locales/nl/hue-bridge-config.html +31 -0
- package/huemagic/locales/nl/hue-bridge-config.json +40 -0
- package/huemagic/locales/nl/hue-bridge.html +96 -0
- package/huemagic/locales/nl/hue-bridge.json +26 -0
- package/huemagic/locales/nl/hue-brightness.html +70 -0
- package/huemagic/locales/nl/hue-brightness.json +37 -0
- package/huemagic/locales/nl/hue-buttons.html +61 -0
- package/huemagic/locales/nl/hue-buttons.json +62 -0
- package/huemagic/locales/nl/hue-contact.html +67 -0
- package/huemagic/locales/nl/hue-contact.json +35 -0
- package/huemagic/locales/nl/hue-group.html +87 -0
- package/huemagic/locales/nl/hue-group.json +46 -0
- package/huemagic/locales/nl/hue-light.html +97 -0
- package/huemagic/locales/nl/hue-light.json +44 -0
- package/huemagic/locales/nl/hue-magic.html +68 -0
- package/huemagic/locales/nl/hue-magic.json +26 -0
- package/huemagic/locales/nl/hue-motion.html +64 -0
- package/huemagic/locales/nl/hue-motion.json +36 -0
- package/huemagic/locales/nl/hue-rules.html +69 -0
- package/huemagic/locales/nl/hue-rules.json +30 -0
- package/huemagic/locales/nl/hue-scene.html +43 -0
- package/huemagic/locales/nl/hue-scene.json +32 -0
- package/huemagic/locales/nl/hue-speaker.html +80 -0
- package/huemagic/locales/nl/hue-speaker.json +38 -0
- package/huemagic/locales/nl/hue-syncbox-config.html +19 -0
- package/huemagic/locales/nl/hue-syncbox-config.json +25 -0
- package/huemagic/locales/nl/hue-syncbox.html +86 -0
- package/huemagic/locales/nl/hue-syncbox.json +30 -0
- package/huemagic/locales/nl/hue-temperature.html +69 -0
- package/huemagic/locales/nl/hue-temperature.json +33 -0
- package/huemagic/locales/pl/hue-automation.html +59 -0
- package/huemagic/locales/pl/hue-automation.json +33 -0
- package/huemagic/locales/pl/hue-bridge-config.html +31 -0
- package/huemagic/locales/pl/hue-bridge-config.json +40 -0
- package/huemagic/locales/pl/hue-bridge.html +96 -0
- package/huemagic/locales/pl/hue-bridge.json +26 -0
- package/huemagic/locales/pl/hue-brightness.html +70 -0
- package/huemagic/locales/pl/hue-brightness.json +37 -0
- package/huemagic/locales/pl/hue-buttons.html +61 -0
- package/huemagic/locales/pl/hue-buttons.json +62 -0
- package/huemagic/locales/pl/hue-contact.html +67 -0
- package/huemagic/locales/pl/hue-contact.json +35 -0
- package/huemagic/locales/pl/hue-group.html +87 -0
- package/huemagic/locales/pl/hue-group.json +46 -0
- package/huemagic/locales/pl/hue-light.html +97 -0
- package/huemagic/locales/pl/hue-light.json +44 -0
- package/huemagic/locales/pl/hue-magic.html +68 -0
- package/huemagic/locales/pl/hue-magic.json +26 -0
- package/huemagic/locales/pl/hue-motion.html +64 -0
- package/huemagic/locales/pl/hue-motion.json +36 -0
- package/huemagic/locales/pl/hue-rules.html +69 -0
- package/huemagic/locales/pl/hue-rules.json +30 -0
- package/huemagic/locales/pl/hue-scene.html +43 -0
- package/huemagic/locales/pl/hue-scene.json +32 -0
- package/huemagic/locales/pl/hue-speaker.html +80 -0
- package/huemagic/locales/pl/hue-speaker.json +38 -0
- package/huemagic/locales/pl/hue-syncbox-config.html +19 -0
- package/huemagic/locales/pl/hue-syncbox-config.json +25 -0
- package/huemagic/locales/pl/hue-syncbox.html +86 -0
- package/huemagic/locales/pl/hue-syncbox.json +30 -0
- package/huemagic/locales/pl/hue-temperature.html +69 -0
- package/huemagic/locales/pl/hue-temperature.json +33 -0
- package/huemagic/locales/pt/hue-automation.html +59 -0
- package/huemagic/locales/pt/hue-automation.json +33 -0
- package/huemagic/locales/pt/hue-bridge-config.html +31 -0
- package/huemagic/locales/pt/hue-bridge-config.json +40 -0
- package/huemagic/locales/pt/hue-bridge.html +96 -0
- package/huemagic/locales/pt/hue-bridge.json +26 -0
- package/huemagic/locales/pt/hue-brightness.html +70 -0
- package/huemagic/locales/pt/hue-brightness.json +37 -0
- package/huemagic/locales/pt/hue-buttons.html +61 -0
- package/huemagic/locales/pt/hue-buttons.json +62 -0
- package/huemagic/locales/pt/hue-contact.html +67 -0
- package/huemagic/locales/pt/hue-contact.json +35 -0
- package/huemagic/locales/pt/hue-group.html +87 -0
- package/huemagic/locales/pt/hue-group.json +46 -0
- package/huemagic/locales/pt/hue-light.html +97 -0
- package/huemagic/locales/pt/hue-light.json +44 -0
- package/huemagic/locales/pt/hue-magic.html +68 -0
- package/huemagic/locales/pt/hue-magic.json +26 -0
- package/huemagic/locales/pt/hue-motion.html +64 -0
- package/huemagic/locales/pt/hue-motion.json +36 -0
- package/huemagic/locales/pt/hue-rules.html +69 -0
- package/huemagic/locales/pt/hue-rules.json +30 -0
- package/huemagic/locales/pt/hue-scene.html +43 -0
- package/huemagic/locales/pt/hue-scene.json +32 -0
- package/huemagic/locales/pt/hue-speaker.html +80 -0
- package/huemagic/locales/pt/hue-speaker.json +38 -0
- package/huemagic/locales/pt/hue-syncbox-config.html +19 -0
- package/huemagic/locales/pt/hue-syncbox-config.json +25 -0
- package/huemagic/locales/pt/hue-syncbox.html +86 -0
- package/huemagic/locales/pt/hue-syncbox.json +30 -0
- package/huemagic/locales/pt/hue-temperature.html +69 -0
- package/huemagic/locales/pt/hue-temperature.json +33 -0
- package/huemagic/locales/tr/hue-automation.html +59 -0
- package/huemagic/locales/tr/hue-automation.json +33 -0
- package/huemagic/locales/tr/hue-bridge-config.html +31 -0
- package/huemagic/locales/tr/hue-bridge-config.json +40 -0
- package/huemagic/locales/tr/hue-bridge.html +96 -0
- package/huemagic/locales/tr/hue-bridge.json +26 -0
- package/huemagic/locales/tr/hue-brightness.html +70 -0
- package/huemagic/locales/tr/hue-brightness.json +37 -0
- package/huemagic/locales/tr/hue-buttons.html +61 -0
- package/huemagic/locales/tr/hue-buttons.json +62 -0
- package/huemagic/locales/tr/hue-contact.html +67 -0
- package/huemagic/locales/tr/hue-contact.json +35 -0
- package/huemagic/locales/tr/hue-group.html +87 -0
- package/huemagic/locales/tr/hue-group.json +46 -0
- package/huemagic/locales/tr/hue-light.html +97 -0
- package/huemagic/locales/tr/hue-light.json +44 -0
- package/huemagic/locales/tr/hue-magic.html +68 -0
- package/huemagic/locales/tr/hue-magic.json +26 -0
- package/huemagic/locales/tr/hue-motion.html +64 -0
- package/huemagic/locales/tr/hue-motion.json +36 -0
- package/huemagic/locales/tr/hue-rules.html +69 -0
- package/huemagic/locales/tr/hue-rules.json +30 -0
- package/huemagic/locales/tr/hue-scene.html +43 -0
- package/huemagic/locales/tr/hue-scene.json +32 -0
- package/huemagic/locales/tr/hue-speaker.html +80 -0
- package/huemagic/locales/tr/hue-speaker.json +38 -0
- package/huemagic/locales/tr/hue-syncbox-config.html +19 -0
- package/huemagic/locales/tr/hue-syncbox-config.json +25 -0
- package/huemagic/locales/tr/hue-syncbox.html +86 -0
- package/huemagic/locales/tr/hue-syncbox.json +30 -0
- package/huemagic/locales/tr/hue-temperature.html +69 -0
- package/huemagic/locales/tr/hue-temperature.json +33 -0
- package/huemagic/utils/api.js +158 -54
- package/huemagic/utils/color.js +20 -2
- package/huemagic/utils/merge.js +3 -2
- package/huemagic/utils/messages.js +506 -120
- package/huemagic/utils/sse.js +51 -0
- package/huemagic/utils/syncbox.js +84 -0
- package/package.json +19 -11
- package/.github/FUNDING.yml +0 -2
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -30
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/workflows/npm.yml +0 -18
- package/huemagic/locales/en-US/hue-bridge-config.json +0 -29
- package/huemagic/locales/en-US/hue-buttons.json +0 -34
- package/huemagic/locales/en-US/hue-light.json +0 -38
- /package/huemagic/locales/{en-US → en}/hue-bridge-config.html +0 -0
- /package/huemagic/locales/{en-US → en}/hue-magic.json +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<script type="text/markdown" data-help-name="hue-temperature">
|
|
2
|
+
«Hue Sıcaklık» düğümü, bridge'e bağlı uygun bir sensörden güncel ortam sıcaklığını sorgulayabilir ve bildirebilir.
|
|
3
|
+
|
|
4
|
+
### Kurulum
|
|
5
|
+
|
|
6
|
+
Önceden yapılandırılmış Hue Bridge'i seçin ve mevcut tüm sensörleri bulmak için arama düğmesine tıklayın. Sensörün kimliğini zaten biliyorsanız, buraya elle de girebilirsiniz. Sensöre dahili olarak yeni bir ad verebilir veya önceden tanımlı adı kullanabilirsiniz. İsteğe bağlı olarak «Düğümün mesajlarını yoksay» ayarıyla bu düğümün tüm otomatik durum mesajlarını devre dışı bırakabilirsiniz. Düğüm bundan sonra cihaz güncellemesi yayınlamaz. Alternatif olarak, Node-RED başlatılırken düğümün başlatma mesajının bastırılmamasını seçebilirsiniz. Bu ayarı etkinleştirirseniz her dağıtımdan sonra seçili sensörün durum mesajını alırsınız. Düğümün siz bir şey gönderene kadar sessiz kalmasını tercih ediyorsanız «Yalnızca bir komuttan sonra bildir» seçeneğini etkinleştirin. Bu durumda uygulamadan veya bir anahtardan gelen değişiklikleri yok sayar ve yalnızca sizin komutlarınıza yanıt verir.
|
|
7
|
+
|
|
8
|
+
Hareket sensörleri genellikle odanın bir köşesine monte edilir ve kendi elektroniği yüzünden çoğu zaman biraz fazla sıcak ölçer. «Düzeltme» ayarıyla sensörü dolambaçsız biçimde kalibre edebilirsiniz: buraya girdiğiniz değer (ör. `-1.5`), düğüm değeri vermeden önce her ölçüme eklenir. Düzeltme tüm sıcaklık birimleri için aynı anda geçerlidir.
|
|
9
|
+
|
|
10
|
+
Bir sensör seçmez ve düğüm yapılandırmasını bu şekilde kullanırsanız, düğüm «evrensel mod» adı verilen modda çalışır. Bu modda düğüm aynı türdeki tüm durum mesajlarını alır ve yayınlar. Evrensel modda ayarları belirli bir sensöre uygulamak için ilgili sensör kimliğini `msg.topic` içinde dize olarak ayarlarınızla birlikte gönderebilirsiniz.
|
|
11
|
+
|
|
12
|
+
### Durumu sorgulama
|
|
13
|
+
|
|
14
|
+
Düğüme aşağıdaki içeriğe sahip bir `msg.payload` nesnesi iletildiğinde sensörün güncel durumunu verir. Alternatif olarak, önce düğüme bir mesaj göndermeden Node-RED arayüzündeki düğmeye de basabilirsiniz.
|
|
15
|
+
|
|
16
|
+
: status (boolean): Sensörün güncel durumunu döndürür
|
|
17
|
+
|
|
18
|
+
### Sensörü açma / kapatma
|
|
19
|
+
|
|
20
|
+
Gerekirse sensör uzaktan açılıp kapatılabilir. Sensör kapatıldığında artık sıcaklık değişikliği kaydetmez ve dolayısıyla bildirmez. Bunun için aşağıdaki içeriğe sahip bir nesne gönderin:
|
|
21
|
+
|
|
22
|
+
: payload (boolean): `true` sensörü açar, `false` kapatır
|
|
23
|
+
|
|
24
|
+
### Düğümün durum mesajları
|
|
25
|
+
|
|
26
|
+
Sensör bir sıcaklık değişikliği kaydettiği anda düğüm aşağıdaki durum mesajını döndürür:
|
|
27
|
+
|
|
28
|
+
#### `msg.payload` altındaki durum nesnesi
|
|
29
|
+
|
|
30
|
+
: active (boolean): Sensörün açık mı kapalı mı olduğunu belirtir
|
|
31
|
+
: reachable (boolean | string): Sensör bridge'e bağlıysa `true`, bağlantı durumu farklıysa `unknown`
|
|
32
|
+
: connectionStatus (string): Bridge ile olan güncel bağlantı durumu (dize olarak). Değer olarak `connected`, `disconnected`, `connectivity_issue` veya `unidirectional_incoming` içerebilir
|
|
33
|
+
: celsius (float): Güncel ortam sıcaklığını °C (santigrat derece) olarak belirtir
|
|
34
|
+
: fahrenheit (float): Güncel ortam sıcaklığını °F (fahrenhayt derece) olarak belirtir
|
|
35
|
+
: temperatureIs (string): Güncel sıcaklığı `very cold`, `cold`, `slightly cold`, `comfortable`, `slightly warm`, `warm`, `hot` veya `very hot` değerleriyle tanımlar
|
|
36
|
+
: deviceValue (float): Sensörden gelen özgün sıcaklık değeri
|
|
37
|
+
: updated (string): Kaynağın HueMagic tarafından son güncellenme zamanı (ISO 8601)
|
|
38
|
+
|
|
39
|
+
#### `msg.info` altındaki sensör bilgileri
|
|
40
|
+
|
|
41
|
+
: id (string): Sensörün yeni kimliğini belirtir
|
|
42
|
+
: idV1 (string | boolean): Sensörün eski kimliğini belirtir
|
|
43
|
+
: uniqueId (string): Sensörün benzersiz kimliği
|
|
44
|
+
: deviceId (string): Cihazın benzersiz kimliği
|
|
45
|
+
: name (string): Sensörün geçerli adı
|
|
46
|
+
: type (string): Sensörün türü (her zaman `temperature`)
|
|
47
|
+
: softwareVersion (string): Sensörün geçerli ürün yazılımı
|
|
48
|
+
: battery (float): Sensörün geçerli pil düzeyi
|
|
49
|
+
: batteryState (string): Pil düzeyinin geçerli durumu. Değer olarak `normal`, `low` veya `critical` içerebilir
|
|
50
|
+
: model (object): Sensörün model bilgilerini `id`, `manufacturer`, `name`, `type` ve `certified` altında içerir
|
|
51
|
+
|
|
52
|
+
#### `msg.updated` altındaki durum değişiklikleri
|
|
53
|
+
|
|
54
|
+
Sensörün önceki durumuna kıyasla değişen parametreleri bir nesne olarak listeler. Herhangi bir değişiklik kaydedilmediyse bu nesne boştur.
|
|
55
|
+
|
|
56
|
+
#### `msg.lastState` altındaki son sensör durumu
|
|
57
|
+
|
|
58
|
+
Son kaydedilen değişiklikten önceki durumun eksiksiz durum nesnesini içerir (yukarıdaki çıktı değerlerine bakın). HueMagic önceki durumu henüz kaydetmediyse `false` verilir.
|
|
59
|
+
|
|
60
|
+
#### `msg.command` altındaki son komut (isteğe bağlı)
|
|
61
|
+
|
|
62
|
+
Düğümün durumu belirli bir komutla değiştiyse, yürütülen komutun tamamı da çıktı olarak verilir. Aksi hâlde düğüm bu nesneyi çıktı olarak vermez.
|
|
63
|
+
|
|
64
|
+
### HueMagic örnekleri
|
|
65
|
+
|
|
66
|
+
HueMagic bu düğüm için bazı örnek yapılandırmalar sunar. Node-RED arayüzünüze eksiksiz bir örnek aktarmak için Node-RED menü simgesine tıklayın, «Import» seçeneğini seçin ve açılan pencerenin kenar çubuğunda «Examples» bölümüne gidin. Ardından HueMagic klasörünü ve istediğiniz düğümü seçerek örnek bir akış aktarın.
|
|
67
|
+
|
|
68
|
+

|
|
69
|
+
</script>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hue-temperature": {
|
|
3
|
+
"config": {
|
|
4
|
+
"name": "Ad",
|
|
5
|
+
"skipevents-node": "Düğümün mesajlarını yoksay",
|
|
6
|
+
"sendinitevents-node": "Başlatma olayını bastırma",
|
|
7
|
+
"onlycommands-node": "Yalnızca bir komuttan sonra bildir",
|
|
8
|
+
"unknown-error": "Bir şeyler ters gitti. Lütfen tekrar deneyin.",
|
|
9
|
+
"bridge": "Bridge",
|
|
10
|
+
"universalevents": "Evrensel olaylar",
|
|
11
|
+
"universalevents-node": "Aynı türdeki diğer düğümlerin tüm mesajlarını alır (yalnızca evrensel modda)",
|
|
12
|
+
"input-name": "Sensör adı",
|
|
13
|
+
"searching": "sıcaklık sensörleri aranıyor…",
|
|
14
|
+
"none-found": "Hiç sıcaklık sensörü bulunamadı.",
|
|
15
|
+
"sensor": "Sensör",
|
|
16
|
+
"offset": "Düzeltme"
|
|
17
|
+
},
|
|
18
|
+
"node": {
|
|
19
|
+
"not-configured": "yapılandırılmadı",
|
|
20
|
+
"init": "başlatılıyor…",
|
|
21
|
+
"not-reachable": "erişilemiyor",
|
|
22
|
+
"universal": "evrensel mod",
|
|
23
|
+
"command": "komut yürütülüyor…",
|
|
24
|
+
"deactivated": "devre dışı",
|
|
25
|
+
"statusmsg": "Durum başarıyla sorgulandı…",
|
|
26
|
+
"title": "Hue Sıcaklık",
|
|
27
|
+
"input": "durum sorgusu",
|
|
28
|
+
"output": "sıcaklık (değişti)",
|
|
29
|
+
"error-no-id": "Lütfen geçerli bir sensör kimliği girin.",
|
|
30
|
+
"error-not-available": "Sensör henüz kullanılabilir değil. HueMagic bridge ile bağlantı kurana kadar bekleyin veya yapılandırmadaki kaynak kimliğinin geçerli olup olmadığını kontrol edin."
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
package/huemagic/utils/api.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
const axios = require('axios');
|
|
2
2
|
const dayjs = require('dayjs');
|
|
3
3
|
const https = require('https');
|
|
4
|
-
const
|
|
4
|
+
const { parseEventStream } = require('./sse');
|
|
5
|
+
|
|
6
|
+
// Node is somehow not able to parse the official Philips Hue PEM
|
|
7
|
+
const httpsAgent = new https.Agent({ rejectUnauthorized: false, keepAlive: true });
|
|
5
8
|
|
|
6
9
|
function API()
|
|
7
10
|
{
|
|
@@ -28,7 +31,9 @@ function API()
|
|
|
28
31
|
"method": "GET",
|
|
29
32
|
"url": "https://" + config.bridge + "/api/config",
|
|
30
33
|
"headers": { "Content-Type": "application/json; charset=utf-8" },
|
|
31
|
-
"httpsAgent":
|
|
34
|
+
"httpsAgent": httpsAgent,
|
|
35
|
+
"proxy": false, // THE BRIDGE IS ON THE LOCAL NETWORK, NEVER GO THROUGH A PROXY
|
|
36
|
+
"timeout": 10000,
|
|
32
37
|
})
|
|
33
38
|
.then(function(response)
|
|
34
39
|
{
|
|
@@ -62,7 +67,9 @@ function API()
|
|
|
62
67
|
"Content-Type": "application/json; charset=utf-8",
|
|
63
68
|
"hue-application-key": config.key
|
|
64
69
|
},
|
|
65
|
-
"httpsAgent":
|
|
70
|
+
"httpsAgent": httpsAgent,
|
|
71
|
+
"proxy": false, // THE BRIDGE IS ON THE LOCAL NETWORK, NEVER GO THROUGH A PROXY
|
|
72
|
+
"timeout": 15000,
|
|
66
73
|
};
|
|
67
74
|
|
|
68
75
|
// HAS RESOURCE? -> APPEND
|
|
@@ -90,6 +97,7 @@ function API()
|
|
|
90
97
|
{
|
|
91
98
|
if(version === 2)
|
|
92
99
|
{
|
|
100
|
+
// THE BRIDGE ALSO PUTS NON-FATAL HINTS INTO "errors", SO ONLY THE STATUS COUNTS
|
|
93
101
|
resolve(response.data.data);
|
|
94
102
|
}
|
|
95
103
|
else if(version === 1)
|
|
@@ -99,64 +107,143 @@ function API()
|
|
|
99
107
|
})
|
|
100
108
|
.catch(function(error)
|
|
101
109
|
{
|
|
102
|
-
|
|
110
|
+
if (error.response)
|
|
111
|
+
{
|
|
112
|
+
let errors = error.response.data;
|
|
113
|
+
|
|
114
|
+
// AN OVERLOADED BRIDGE ANSWERS WITH A HTML ERROR PAGE
|
|
115
|
+
if(typeof errors === 'string') { errors = "The bridge is currently not able to answer (HTTP " + error.response.status + ")."; }
|
|
116
|
+
else if(errors && errors.errors) { errors = errors.errors; }
|
|
117
|
+
|
|
118
|
+
reject({ status: error.response.status, errors: errors });
|
|
119
|
+
}
|
|
120
|
+
else
|
|
121
|
+
{
|
|
122
|
+
reject({ status: error.code, errors: error.message});
|
|
123
|
+
}
|
|
103
124
|
});
|
|
104
125
|
});
|
|
105
126
|
}
|
|
106
127
|
|
|
107
128
|
//
|
|
108
129
|
// SUBSCRIBE TO BRIDGE EVENTS
|
|
109
|
-
this.subscribe = function(config, callback)
|
|
130
|
+
this.subscribe = function(config, callback, log = null)
|
|
110
131
|
{
|
|
111
132
|
const scope = this;
|
|
112
133
|
return new Promise(function(resolve, reject)
|
|
113
134
|
{
|
|
114
|
-
|
|
135
|
+
// ONLY ONE STREAM PER BRIDGE
|
|
136
|
+
scope.unsubscribe(config);
|
|
137
|
+
|
|
138
|
+
const stream = { active: true, request: null, retry: null, attempt: 0, lastEventId: null, connected: false };
|
|
139
|
+
scope.events[config.id] = stream;
|
|
140
|
+
|
|
141
|
+
// (RE)CONNECT TO THE EVENT STREAM
|
|
142
|
+
const connect = function()
|
|
115
143
|
{
|
|
116
|
-
|
|
144
|
+
if(stream.active === false) { return false; }
|
|
145
|
+
|
|
146
|
+
const [host, port] = config.bridge.trim().split(":");
|
|
147
|
+
const headers = {
|
|
148
|
+
"Accept": "text/event-stream",
|
|
149
|
+
"Cache-Control": "no-cache",
|
|
150
|
+
"hue-application-key": config.key
|
|
151
|
+
};
|
|
117
152
|
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
153
|
+
// CONTINUE WHERE WE LEFT OFF
|
|
154
|
+
if(stream.lastEventId) { headers["Last-Event-ID"] = stream.lastEventId; }
|
|
155
|
+
|
|
156
|
+
stream.request = https.request({
|
|
157
|
+
host: host,
|
|
158
|
+
port: port ? parseInt(port) : 443,
|
|
159
|
+
path: "/eventstream/clip/v2",
|
|
160
|
+
method: "GET",
|
|
161
|
+
headers: headers,
|
|
162
|
+
agent: false,
|
|
163
|
+
rejectUnauthorized: false
|
|
122
164
|
});
|
|
123
165
|
|
|
124
|
-
//
|
|
125
|
-
|
|
166
|
+
// ONLY GUARD THE HANDSHAKE, AN IDLE EVENT STREAM IS PERFECTLY NORMAL
|
|
167
|
+
stream.request.setTimeout(15000, function() { stream.request.destroy(new Error("the bridge did not answer")); });
|
|
168
|
+
|
|
169
|
+
stream.request.on('response', function(response)
|
|
126
170
|
{
|
|
127
|
-
if(
|
|
171
|
+
if(response.statusCode !== 200)
|
|
128
172
|
{
|
|
129
|
-
|
|
130
|
-
|
|
173
|
+
response.resume();
|
|
174
|
+
reconnect("The bridge rejected the event stream (HTTP " + response.statusCode + ")");
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// CONNECTED -> LET THE OS DETECT DEAD PEERS
|
|
179
|
+
const isReconnect = (stream.attempt > 0);
|
|
180
|
+
|
|
181
|
+
stream.request.setTimeout(0);
|
|
182
|
+
stream.attempt = 0;
|
|
183
|
+
stream.connected = true;
|
|
184
|
+
response.setEncoding('utf8');
|
|
185
|
+
if(response.socket) { response.socket.setKeepAlive(true, 30000); }
|
|
186
|
+
|
|
187
|
+
// EVENTS MAY HAVE BEEN MISSED WHILE WE WERE AWAY
|
|
188
|
+
if(isReconnect) { callback([], "reconnect"); }
|
|
189
|
+
|
|
190
|
+
let buffer = "";
|
|
191
|
+
|
|
192
|
+
response.on('data', function(chunk)
|
|
193
|
+
{
|
|
194
|
+
const parsed = parseEventStream(buffer + chunk);
|
|
195
|
+
buffer = (parsed.rest.length > 1048576) ? "" : parsed.rest;
|
|
196
|
+
|
|
197
|
+
for(let event of parsed.events)
|
|
131
198
|
{
|
|
132
|
-
|
|
133
|
-
if(
|
|
199
|
+
if(event.id) { stream.lastEventId = event.id; }
|
|
200
|
+
if(!event.data) { continue; }
|
|
201
|
+
|
|
202
|
+
let messages = [];
|
|
203
|
+
try { messages = JSON.parse(event.data); }
|
|
204
|
+
catch(error) { continue; }
|
|
205
|
+
|
|
206
|
+
for(let message of messages)
|
|
134
207
|
{
|
|
135
|
-
callback(message.data);
|
|
208
|
+
if(message.data) { callback(message.data, message.type); }
|
|
136
209
|
}
|
|
137
210
|
}
|
|
138
|
-
}
|
|
139
|
-
};
|
|
211
|
+
});
|
|
140
212
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
{
|
|
144
|
-
resolve(true);
|
|
145
|
-
}
|
|
213
|
+
response.on('end', function() { reconnect("The bridge closed the event stream"); });
|
|
214
|
+
response.on('error', function(error) { reconnect(error.message); });
|
|
146
215
|
|
|
147
|
-
// ERROR? -> RETRY?
|
|
148
|
-
scope.events[config.id].onerror = function(error)
|
|
149
|
-
{
|
|
150
|
-
console.log("HueMagic:", "Connection to bridge lost. Trying to reconnect again in 30 seconds…", error);
|
|
151
|
-
setTimeout(function(){ scope.subscribe(config, callback); }, 30000);
|
|
152
216
|
resolve(true);
|
|
153
|
-
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
stream.request.on('error', function(error) { reconnect(error.message); });
|
|
220
|
+
stream.request.end();
|
|
154
221
|
}
|
|
155
|
-
|
|
222
|
+
|
|
223
|
+
// RECONNECT WITH A BACKOFF, BUT NEVER MORE THAN ONCE AT A TIME
|
|
224
|
+
const reconnect = function(reason)
|
|
156
225
|
{
|
|
157
|
-
|
|
158
|
-
|
|
226
|
+
if(stream.active === false || stream.retry !== null) { return false; }
|
|
227
|
+
|
|
228
|
+
stream.connected = false;
|
|
229
|
+
if(stream.request) { stream.request.destroy(); stream.request = null; }
|
|
230
|
+
|
|
231
|
+
const delay = Math.min(30000, 1000 * Math.pow(2, stream.attempt));
|
|
232
|
+
const seconds = Math.round(delay/1000);
|
|
233
|
+
stream.attempt += 1;
|
|
234
|
+
|
|
235
|
+
if(log) { log(reason, seconds); }
|
|
236
|
+
else { console.log("HueMagic:", "Connection to bridge lost (" + reason + "). Trying to reconnect in " + seconds + " seconds…"); }
|
|
237
|
+
stream.retry = setTimeout(function()
|
|
238
|
+
{
|
|
239
|
+
stream.retry = null;
|
|
240
|
+
connect();
|
|
241
|
+
}, delay);
|
|
242
|
+
|
|
243
|
+
resolve(true);
|
|
159
244
|
}
|
|
245
|
+
|
|
246
|
+
connect();
|
|
160
247
|
});
|
|
161
248
|
}
|
|
162
249
|
|
|
@@ -164,22 +251,40 @@ function API()
|
|
|
164
251
|
// UNSUBSCRIBE
|
|
165
252
|
this.unsubscribe = function(config)
|
|
166
253
|
{
|
|
167
|
-
|
|
168
|
-
|
|
254
|
+
const stream = this.events[config.id];
|
|
255
|
+
if(!stream) { return false; }
|
|
256
|
+
|
|
257
|
+
stream.active = false;
|
|
258
|
+
if(stream.retry !== null) { clearTimeout(stream.retry); }
|
|
259
|
+
if(stream.request) { stream.request.destroy(); }
|
|
260
|
+
|
|
261
|
+
delete this.events[config.id];
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//
|
|
265
|
+
// IS THE EVENT STREAM ALIVE?
|
|
266
|
+
this.connected = function(config)
|
|
267
|
+
{
|
|
268
|
+
const stream = this.events[config.id];
|
|
269
|
+
return !!stream && stream.connected === true;
|
|
169
270
|
}
|
|
170
271
|
|
|
171
272
|
//
|
|
172
273
|
// GET FULL/ROOT RESOURCE
|
|
173
|
-
this.fullResource = function(resource, allResources = {})
|
|
274
|
+
this.fullResource = function(resource, allResources = {}, seen = {})
|
|
174
275
|
{
|
|
175
276
|
const scope = this;
|
|
176
277
|
var fullResource = Object.assign({}, resource);
|
|
177
278
|
|
|
178
|
-
|
|
279
|
+
// PROTECT AGAINST BROKEN OWNER CHAINS
|
|
280
|
+
if(seen[resource["id"]]) { return fullResource; }
|
|
281
|
+
seen[resource["id"]] = true;
|
|
282
|
+
|
|
283
|
+
if(resource["owner"] && typeof allResources[fullResource["owner"]["rid"]] !== 'undefined')
|
|
179
284
|
{
|
|
180
|
-
fullResource = scope.fullResource(allResources[fullResource["owner"]["rid"]], allResources);
|
|
285
|
+
fullResource = scope.fullResource(allResources[fullResource["owner"]["rid"]], allResources, seen);
|
|
181
286
|
}
|
|
182
|
-
else if(resource["
|
|
287
|
+
else if(Array.isArray(resource["services"]))
|
|
183
288
|
{
|
|
184
289
|
// RESOLVE SERVICES
|
|
185
290
|
var allServices = {};
|
|
@@ -190,6 +295,7 @@ function API()
|
|
|
190
295
|
const targetType = targetService["rtype"];
|
|
191
296
|
const targetID = targetService["rid"];
|
|
192
297
|
|
|
298
|
+
if(!allResources[targetID]) { continue; }
|
|
193
299
|
if(!allServices[targetType]) { allServices[targetType] = {}; }
|
|
194
300
|
allServices[targetType][targetID] = Object.assign({}, allResources[targetID]);
|
|
195
301
|
}
|
|
@@ -221,11 +327,9 @@ function API()
|
|
|
221
327
|
// CREATE ID BASED OBJECT OF ALL RESOURCES
|
|
222
328
|
resources.forEach(function(resource, index)
|
|
223
329
|
{
|
|
224
|
-
// IS BUTTON? -> REMOVE PREVIOUS STATE
|
|
225
|
-
if(resource.type === "button")
|
|
226
|
-
{
|
|
227
|
-
delete resource["button"];
|
|
228
|
-
}
|
|
330
|
+
// IS BUTTON OR DIAL? -> REMOVE PREVIOUS STATE
|
|
331
|
+
if(resource.type === "button") { delete resource["button"]; }
|
|
332
|
+
else if(resource.type === "relative_rotary") { delete resource["relative_rotary"]; }
|
|
229
333
|
|
|
230
334
|
resourceList[resource.id] = resource;
|
|
231
335
|
});
|
|
@@ -236,6 +340,9 @@ function API()
|
|
|
236
340
|
// GET FULL RESOURCE
|
|
237
341
|
let fullResource = scope.fullResource(resource, resourceList);
|
|
238
342
|
|
|
343
|
+
// A RESOURCE AND EACH OF ITS SERVICES RESOLVE TO THE SAME ROOT
|
|
344
|
+
if(processedResources[fullResource.id]) { return; }
|
|
345
|
+
|
|
239
346
|
// ADD CURRENT DATE/TIME
|
|
240
347
|
fullResource["updated"] = currentDateTime;
|
|
241
348
|
|
|
@@ -249,15 +356,12 @@ function API()
|
|
|
249
356
|
|
|
250
357
|
// SET ADDITIONAL TYPES BEHIND RECCOURCE
|
|
251
358
|
fullResource["types"] = fullResource["types"].concat(additionalServiceTypes);
|
|
252
|
-
}
|
|
253
359
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
{
|
|
257
|
-
for (serviceType in fullResource["services"])
|
|
360
|
+
// RESOURCE HAS GROUPED SERVICES?
|
|
361
|
+
for (const serviceType in fullResource["services"])
|
|
258
362
|
{
|
|
259
|
-
const
|
|
260
|
-
for (groupedServiceID in
|
|
363
|
+
const groupedServices = fullResource['services'][serviceType];
|
|
364
|
+
for (const groupedServiceID in groupedServices)
|
|
261
365
|
{
|
|
262
366
|
if (!processedResources["_groupsOf"][groupedServiceID]) { processedResources["_groupsOf"][groupedServiceID] = []; }
|
|
263
367
|
processedResources["_groupsOf"][groupedServiceID].push(fullResource.id);
|
|
@@ -275,4 +379,4 @@ function API()
|
|
|
275
379
|
}
|
|
276
380
|
|
|
277
381
|
// EXPORT
|
|
278
|
-
module.exports = new API;
|
|
382
|
+
module.exports = new API;
|
package/huemagic/utils/color.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
// EXTERNAL HELPERS
|
|
2
2
|
const colornames = require("colornames");
|
|
3
3
|
const colornamer = require('color-namer');
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
// LOADED ON DEMAND, IT PULLS IN A LARGE DEPENDENCY TREE
|
|
6
|
+
function getColors(...args)
|
|
7
|
+
{
|
|
8
|
+
return require('get-image-colors')(...args);
|
|
9
|
+
}
|
|
5
10
|
|
|
6
11
|
// RGB -> XY
|
|
7
12
|
function rgbToXy(red, green, blue, gamut = null)
|
|
8
13
|
{
|
|
9
14
|
var colorGamut = { red: [1.0, 0], green: [0.0, 1.0], blue: [0.0, 0.0] };
|
|
10
|
-
if(!!gamut)
|
|
15
|
+
if(!!gamut && !!gamut.red && !!gamut.green && !!gamut.blue)
|
|
11
16
|
{
|
|
12
17
|
colorGamut = { red: [gamut.red.x, gamut.red.y], green: [gamut.green.x, gamut.green.y], blue: [gamut.blue.x, gamut.blue.y] };
|
|
13
18
|
}
|
|
@@ -34,9 +39,19 @@ function rgbToXy(red, green, blue, gamut = null)
|
|
|
34
39
|
xy = _getClosestColor(xy, colorGamut);
|
|
35
40
|
}
|
|
36
41
|
|
|
42
|
+
// THE BRIDGE REJECTS ANYTHING OUTSIDE 0…1 WITH A 400
|
|
43
|
+
xy.x = _clampToColorSpace(xy.x);
|
|
44
|
+
xy.y = _clampToColorSpace(xy.y);
|
|
45
|
+
|
|
37
46
|
return xy;
|
|
38
47
|
}
|
|
39
48
|
|
|
49
|
+
function _clampToColorSpace(value)
|
|
50
|
+
{
|
|
51
|
+
if(isNaN(value)) { return 0; }
|
|
52
|
+
return (value < 0) ? 0 : ((value > 1) ? 1 : value);
|
|
53
|
+
}
|
|
54
|
+
|
|
40
55
|
function _getGammaCorrectedValue(value)
|
|
41
56
|
{
|
|
42
57
|
return (value > 0.04045) ? Math.pow((value + 0.055) / (1.0 + 0.055), 2.4) : (value / 12.92)
|
|
@@ -153,6 +168,9 @@ function _getClosestPoint(xy, pointA, pointB)
|
|
|
153
168
|
let xy2a_dot_a2b = xy2a[0] * a2b[0] + xy2a[1] * a2b[1];
|
|
154
169
|
let t = xy2a_dot_a2b /a2bSqr;
|
|
155
170
|
|
|
171
|
+
// STAY ON THE EDGE OF THE GAMUT, NOT ON THE INFINITE LINE BEHIND IT
|
|
172
|
+
t = (t < 0) ? 0 : ((t > 1) ? 1 : t);
|
|
173
|
+
|
|
156
174
|
return {
|
|
157
175
|
x: pointA.x + a2b[0] * t,
|
|
158
176
|
y: pointA.y + a2b[1] * t
|
package/huemagic/utils/merge.js
CHANGED
|
@@ -13,9 +13,10 @@ function mergeDeep(...objects)
|
|
|
13
13
|
const pVal = prev[key];
|
|
14
14
|
const oVal = obj[key];
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// AN UPDATE REPLACES A LIST, IT NEVER APPENDS TO IT
|
|
17
|
+
if(Array.isArray(oVal))
|
|
17
18
|
{
|
|
18
|
-
prev[key] =
|
|
19
|
+
prev[key] = oVal;
|
|
19
20
|
}
|
|
20
21
|
else if (isObject(pVal) && isObject(oVal))
|
|
21
22
|
{
|