node-red-contrib-huemagic 4.2.2 → 5.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.
Files changed (515) hide show
  1. package/CHANGELOG.md +89 -5
  2. package/README.md +506 -123
  3. package/examples/Deutsch/Hue Automation.json +176 -0
  4. package/examples/Deutsch/Hue Bridge.json +256 -0
  5. package/examples/Deutsch/Hue Brightness.json +150 -0
  6. package/examples/Deutsch/Hue Buttons.json +88 -0
  7. package/examples/Deutsch/Hue Contact.json +150 -0
  8. package/examples/Deutsch/Hue Group.json +658 -0
  9. package/examples/Deutsch/Hue Light.json +893 -0
  10. package/examples/Deutsch/Hue Magic.json +148 -0
  11. package/examples/Deutsch/Hue Motion.json +150 -0
  12. package/examples/Deutsch/Hue Rules.json +150 -0
  13. package/examples/Deutsch/Hue Scene.json +178 -0
  14. package/examples/Deutsch/Hue Speaker.json +274 -0
  15. package/examples/Deutsch/Hue Sync Box.json +378 -0
  16. package/examples/Deutsch/Hue Temperature.json +150 -0
  17. package/examples/English/Hue Automation.json +176 -0
  18. package/examples/{Hue Bridge.json → English/Hue Bridge.json } +1 -1
  19. package/examples/{Hue Brightness.json → English/Hue Brightness.json } +1 -1
  20. package/examples/{Hue Buttons.json → English/Hue Buttons.json } +1 -1
  21. package/examples/English/Hue Contact.json +150 -0
  22. package/examples/{Hue Group.json → English/Hue Group.json } +1 -1
  23. package/examples/{Hue Light.json → English/Hue Light.json } +1 -1
  24. package/examples/{Hue Magic.json → English/Hue Magic.json } +1 -1
  25. package/examples/{Hue Motion.json → English/Hue Motion.json } +1 -1
  26. package/examples/{Hue Rules.json → English/Hue Rules.json } +1 -1
  27. package/examples/{Hue Scene.json → English/Hue Scene.json } +1 -1
  28. package/examples/English/Hue Speaker.json +274 -0
  29. package/examples/English/Hue Sync Box.json +378 -0
  30. package/examples/{Hue Temperature.json → English/Hue Temperature.json } +1 -1
  31. package/examples/Espa/303/261ol/Hue Automation.json" +176 -0
  32. package/examples/Espa/303/261ol/Hue Bridge.json" +256 -0
  33. package/examples/Espa/303/261ol/Hue Brightness.json" +150 -0
  34. package/examples/Espa/303/261ol/Hue Buttons.json" +88 -0
  35. package/examples/Espa/303/261ol/Hue Contact.json" +150 -0
  36. package/examples/Espa/303/261ol/Hue Group.json" +658 -0
  37. package/examples/Espa/303/261ol/Hue Light.json" +893 -0
  38. package/examples/Espa/303/261ol/Hue Magic.json" +148 -0
  39. package/examples/Espa/303/261ol/Hue Motion.json" +150 -0
  40. package/examples/Espa/303/261ol/Hue Rules.json" +150 -0
  41. package/examples/Espa/303/261ol/Hue Scene.json" +178 -0
  42. package/examples/Espa/303/261ol/Hue Speaker.json" +274 -0
  43. package/examples/Espa/303/261ol/Hue Sync Box.json" +378 -0
  44. package/examples/Espa/303/261ol/Hue Temperature.json" +150 -0
  45. package/examples/Fran/303/247ais/Hue Automation.json" +176 -0
  46. package/examples/Fran/303/247ais/Hue Bridge.json" +256 -0
  47. package/examples/Fran/303/247ais/Hue Brightness.json" +150 -0
  48. package/examples/Fran/303/247ais/Hue Buttons.json" +88 -0
  49. package/examples/Fran/303/247ais/Hue Contact.json" +150 -0
  50. package/examples/Fran/303/247ais/Hue Group.json" +658 -0
  51. package/examples/Fran/303/247ais/Hue Light.json" +893 -0
  52. package/examples/Fran/303/247ais/Hue Magic.json" +148 -0
  53. package/examples/Fran/303/247ais/Hue Motion.json" +150 -0
  54. package/examples/Fran/303/247ais/Hue Rules.json" +150 -0
  55. package/examples/Fran/303/247ais/Hue Scene.json" +178 -0
  56. package/examples/Fran/303/247ais/Hue Speaker.json" +274 -0
  57. package/examples/Fran/303/247ais/Hue Sync Box.json" +378 -0
  58. package/examples/Fran/303/247ais/Hue Temperature.json" +150 -0
  59. package/examples/Italiano/Hue Automation.json +176 -0
  60. package/examples/Italiano/Hue Bridge.json +256 -0
  61. package/examples/Italiano/Hue Brightness.json +150 -0
  62. package/examples/Italiano/Hue Buttons.json +88 -0
  63. package/examples/Italiano/Hue Contact.json +150 -0
  64. package/examples/Italiano/Hue Group.json +658 -0
  65. package/examples/Italiano/Hue Light.json +893 -0
  66. package/examples/Italiano/Hue Magic.json +148 -0
  67. package/examples/Italiano/Hue Motion.json +150 -0
  68. package/examples/Italiano/Hue Rules.json +150 -0
  69. package/examples/Italiano/Hue Scene.json +178 -0
  70. package/examples/Italiano/Hue Speaker.json +274 -0
  71. package/examples/Italiano/Hue Sync Box.json +378 -0
  72. package/examples/Italiano/Hue Temperature.json +150 -0
  73. package/examples/Nederlands/Hue Automation.json +176 -0
  74. package/examples/Nederlands/Hue Bridge.json +256 -0
  75. package/examples/Nederlands/Hue Brightness.json +150 -0
  76. package/examples/Nederlands/Hue Buttons.json +88 -0
  77. package/examples/Nederlands/Hue Contact.json +150 -0
  78. package/examples/Nederlands/Hue Group.json +658 -0
  79. package/examples/Nederlands/Hue Light.json +893 -0
  80. package/examples/Nederlands/Hue Magic.json +148 -0
  81. package/examples/Nederlands/Hue Motion.json +150 -0
  82. package/examples/Nederlands/Hue Rules.json +150 -0
  83. package/examples/Nederlands/Hue Scene.json +178 -0
  84. package/examples/Nederlands/Hue Speaker.json +274 -0
  85. package/examples/Nederlands/Hue Sync Box.json +378 -0
  86. package/examples/Nederlands/Hue Temperature.json +150 -0
  87. package/examples/Polski/Hue Automation.json +176 -0
  88. package/examples/Polski/Hue Bridge.json +256 -0
  89. package/examples/Polski/Hue Brightness.json +150 -0
  90. package/examples/Polski/Hue Buttons.json +88 -0
  91. package/examples/Polski/Hue Contact.json +150 -0
  92. package/examples/Polski/Hue Group.json +658 -0
  93. package/examples/Polski/Hue Light.json +893 -0
  94. package/examples/Polski/Hue Magic.json +148 -0
  95. package/examples/Polski/Hue Motion.json +150 -0
  96. package/examples/Polski/Hue Rules.json +150 -0
  97. package/examples/Polski/Hue Scene.json +178 -0
  98. package/examples/Polski/Hue Speaker.json +274 -0
  99. package/examples/Polski/Hue Sync Box.json +378 -0
  100. package/examples/Polski/Hue Temperature.json +150 -0
  101. package/examples/Portugu/303/252s/Hue Automation.json" +176 -0
  102. package/examples/Portugu/303/252s/Hue Bridge.json" +256 -0
  103. package/examples/Portugu/303/252s/Hue Brightness.json" +150 -0
  104. package/examples/Portugu/303/252s/Hue Buttons.json" +88 -0
  105. package/examples/Portugu/303/252s/Hue Contact.json" +150 -0
  106. package/examples/Portugu/303/252s/Hue Group.json" +658 -0
  107. package/examples/Portugu/303/252s/Hue Light.json" +893 -0
  108. package/examples/Portugu/303/252s/Hue Magic.json" +148 -0
  109. package/examples/Portugu/303/252s/Hue Motion.json" +150 -0
  110. package/examples/Portugu/303/252s/Hue Rules.json" +150 -0
  111. package/examples/Portugu/303/252s/Hue Scene.json" +178 -0
  112. package/examples/Portugu/303/252s/Hue Speaker.json" +274 -0
  113. package/examples/Portugu/303/252s/Hue Sync Box.json" +378 -0
  114. package/examples/Portugu/303/252s/Hue Temperature.json" +150 -0
  115. package/examples/T/303/274rk/303/247e/Hue Automation.json" +176 -0
  116. package/examples/T/303/274rk/303/247e/Hue Bridge.json" +256 -0
  117. package/examples/T/303/274rk/303/247e/Hue Brightness.json" +150 -0
  118. package/examples/T/303/274rk/303/247e/Hue Buttons.json" +88 -0
  119. package/examples/T/303/274rk/303/247e/Hue Contact.json" +150 -0
  120. package/examples/T/303/274rk/303/247e/Hue Group.json" +658 -0
  121. package/examples/T/303/274rk/303/247e/Hue Light.json" +893 -0
  122. package/examples/T/303/274rk/303/247e/Hue Magic.json" +148 -0
  123. package/examples/T/303/274rk/303/247e/Hue Motion.json" +150 -0
  124. package/examples/T/303/274rk/303/247e/Hue Rules.json" +150 -0
  125. package/examples/T/303/274rk/303/247e/Hue Scene.json" +178 -0
  126. package/examples/T/303/274rk/303/247e/Hue Speaker.json" +274 -0
  127. package/examples/T/303/274rk/303/247e/Hue Sync Box.json" +378 -0
  128. package/examples/T/303/274rk/303/247e/Hue Temperature.json" +150 -0
  129. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Automation.json" +176 -0
  130. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Bridge.json" +256 -0
  131. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Brightness.json" +150 -0
  132. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Buttons.json" +88 -0
  133. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Contact.json" +150 -0
  134. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Group.json" +658 -0
  135. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Light.json" +893 -0
  136. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Magic.json" +148 -0
  137. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Motion.json" +150 -0
  138. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Rules.json" +150 -0
  139. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Scene.json" +178 -0
  140. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Speaker.json" +274 -0
  141. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Sync Box.json" +378 -0
  142. package/examples//316/225/316/273/316/273/316/267/316/275/316/271/316/272/316/254/Hue Temperature.json" +150 -0
  143. package/huemagic/assets/huemagic-examples.gif +0 -0
  144. package/huemagic/hue-automation.html +218 -0
  145. package/huemagic/hue-automation.js +173 -0
  146. package/huemagic/hue-bridge-config.html +39 -32
  147. package/huemagic/hue-bridge-config.js +290 -99
  148. package/huemagic/hue-bridge.html +8 -8
  149. package/huemagic/hue-bridge.js +29 -4
  150. package/huemagic/hue-brightness.html +21 -9
  151. package/huemagic/hue-brightness.js +20 -10
  152. package/huemagic/hue-buttons.html +16 -9
  153. package/huemagic/hue-buttons.js +90 -27
  154. package/huemagic/hue-contact.html +218 -0
  155. package/huemagic/hue-contact.js +209 -0
  156. package/huemagic/hue-group.html +16 -9
  157. package/huemagic/hue-group.js +141 -179
  158. package/huemagic/hue-light.html +19 -12
  159. package/huemagic/hue-light.js +222 -167
  160. package/huemagic/hue-magic.html +3 -5
  161. package/huemagic/hue-motion.html +16 -9
  162. package/huemagic/hue-motion.js +37 -8
  163. package/huemagic/hue-rules.html +16 -9
  164. package/huemagic/hue-rules.js +16 -8
  165. package/huemagic/hue-scene.html +9 -5
  166. package/huemagic/hue-scene.js +52 -16
  167. package/huemagic/hue-speaker.html +218 -0
  168. package/huemagic/hue-speaker.js +257 -0
  169. package/huemagic/hue-syncbox-config.html +123 -0
  170. package/huemagic/hue-syncbox-config.js +179 -0
  171. package/huemagic/hue-syncbox.html +82 -0
  172. package/huemagic/hue-syncbox.js +274 -0
  173. package/huemagic/hue-temperature.html +21 -9
  174. package/huemagic/hue-temperature.js +18 -10
  175. package/huemagic/icons/hue-automation.png +0 -0
  176. package/huemagic/icons/hue-automation.svg +3 -0
  177. package/huemagic/icons/hue-contact.png +0 -0
  178. package/huemagic/icons/hue-contact.svg +4 -0
  179. package/huemagic/icons/hue-speaker.png +0 -0
  180. package/huemagic/icons/hue-speaker.svg +6 -0
  181. package/huemagic/icons/hue-syncbox.png +0 -0
  182. package/huemagic/icons/hue-syncbox.svg +7 -0
  183. package/huemagic/locales/de/hue-automation.html +59 -0
  184. package/huemagic/locales/de/hue-automation.json +33 -0
  185. package/huemagic/locales/de/hue-bridge-config.json +23 -12
  186. package/huemagic/locales/de/hue-bridge.html +7 -4
  187. package/huemagic/locales/de/hue-bridge.json +9 -10
  188. package/huemagic/locales/de/hue-brightness.html +9 -6
  189. package/huemagic/locales/de/hue-brightness.json +13 -9
  190. package/huemagic/locales/de/hue-buttons.html +5 -4
  191. package/huemagic/locales/de/hue-buttons.json +22 -8
  192. package/huemagic/locales/de/hue-contact.html +67 -0
  193. package/huemagic/locales/de/hue-contact.json +35 -0
  194. package/huemagic/locales/de/hue-group.html +17 -6
  195. package/huemagic/locales/de/hue-group.json +16 -9
  196. package/huemagic/locales/de/hue-light.html +6 -6
  197. package/huemagic/locales/de/hue-light.json +17 -9
  198. package/huemagic/locales/de/hue-magic.html +1 -1
  199. package/huemagic/locales/de/hue-magic.json +6 -8
  200. package/huemagic/locales/de/hue-motion.html +4 -4
  201. package/huemagic/locales/de/hue-motion.json +14 -9
  202. package/huemagic/locales/de/hue-rules.html +2 -2
  203. package/huemagic/locales/de/hue-rules.json +10 -9
  204. package/huemagic/locales/de/hue-scene.html +11 -3
  205. package/huemagic/locales/de/hue-scene.json +9 -9
  206. package/huemagic/locales/de/hue-speaker.html +80 -0
  207. package/huemagic/locales/de/hue-speaker.json +38 -0
  208. package/huemagic/locales/de/hue-syncbox-config.html +19 -0
  209. package/huemagic/locales/de/hue-syncbox-config.json +25 -0
  210. package/huemagic/locales/de/hue-syncbox.html +86 -0
  211. package/huemagic/locales/de/hue-syncbox.json +30 -0
  212. package/huemagic/locales/de/hue-temperature.html +7 -5
  213. package/huemagic/locales/de/hue-temperature.json +13 -9
  214. package/huemagic/locales/el/hue-automation.html +59 -0
  215. package/huemagic/locales/el/hue-automation.json +33 -0
  216. package/huemagic/locales/el/hue-bridge-config.html +31 -0
  217. package/huemagic/locales/el/hue-bridge-config.json +40 -0
  218. package/huemagic/locales/el/hue-bridge.html +96 -0
  219. package/huemagic/locales/el/hue-bridge.json +26 -0
  220. package/huemagic/locales/el/hue-brightness.html +70 -0
  221. package/huemagic/locales/el/hue-brightness.json +37 -0
  222. package/huemagic/locales/el/hue-buttons.html +59 -0
  223. package/huemagic/locales/el/hue-buttons.json +42 -0
  224. package/huemagic/locales/el/hue-contact.html +67 -0
  225. package/huemagic/locales/el/hue-contact.json +35 -0
  226. package/huemagic/locales/el/hue-group.html +87 -0
  227. package/huemagic/locales/el/hue-group.json +46 -0
  228. package/huemagic/locales/el/hue-light.html +97 -0
  229. package/huemagic/locales/el/hue-light.json +44 -0
  230. package/huemagic/locales/el/hue-magic.html +68 -0
  231. package/huemagic/locales/el/hue-magic.json +26 -0
  232. package/huemagic/locales/el/hue-motion.html +64 -0
  233. package/huemagic/locales/el/hue-motion.json +36 -0
  234. package/huemagic/locales/el/hue-rules.html +69 -0
  235. package/huemagic/locales/el/hue-rules.json +30 -0
  236. package/huemagic/locales/el/hue-scene.html +43 -0
  237. package/huemagic/locales/el/hue-scene.json +32 -0
  238. package/huemagic/locales/el/hue-speaker.html +80 -0
  239. package/huemagic/locales/el/hue-speaker.json +38 -0
  240. package/huemagic/locales/el/hue-syncbox-config.html +19 -0
  241. package/huemagic/locales/el/hue-syncbox-config.json +25 -0
  242. package/huemagic/locales/el/hue-syncbox.html +86 -0
  243. package/huemagic/locales/el/hue-syncbox.json +30 -0
  244. package/huemagic/locales/el/hue-temperature.html +69 -0
  245. package/huemagic/locales/el/hue-temperature.json +33 -0
  246. package/huemagic/locales/en/hue-automation.html +59 -0
  247. package/huemagic/locales/en/hue-automation.json +33 -0
  248. package/huemagic/locales/en/hue-bridge-config.json +40 -0
  249. package/huemagic/locales/{en-US → en}/hue-bridge.html +5 -2
  250. package/huemagic/locales/{en-US → en}/hue-bridge.json +8 -9
  251. package/huemagic/locales/{en-US → en}/hue-brightness.html +6 -3
  252. package/huemagic/locales/{en-US → en}/hue-brightness.json +11 -9
  253. package/huemagic/locales/{en-US → en}/hue-buttons.html +4 -3
  254. package/huemagic/locales/en/hue-buttons.json +42 -0
  255. package/huemagic/locales/en/hue-contact.html +67 -0
  256. package/huemagic/locales/en/hue-contact.json +35 -0
  257. package/huemagic/locales/{en-US → en}/hue-group.html +16 -5
  258. package/huemagic/locales/{en-US → en}/hue-group.json +15 -10
  259. package/huemagic/locales/{en-US → en}/hue-light.html +3 -3
  260. package/huemagic/locales/en/hue-light.json +44 -0
  261. package/huemagic/locales/{en-US → en}/hue-magic.html +1 -1
  262. package/huemagic/locales/{en-US → en}/hue-motion.html +2 -2
  263. package/huemagic/locales/{en-US → en}/hue-motion.json +12 -9
  264. package/huemagic/locales/{en-US → en}/hue-rules.html +2 -2
  265. package/huemagic/locales/{en-US → en}/hue-rules.json +10 -9
  266. package/huemagic/locales/{en-US → en}/hue-scene.html +11 -3
  267. package/huemagic/locales/{en-US → en}/hue-scene.json +9 -9
  268. package/huemagic/locales/en/hue-speaker.html +80 -0
  269. package/huemagic/locales/en/hue-speaker.json +38 -0
  270. package/huemagic/locales/en/hue-syncbox-config.html +19 -0
  271. package/huemagic/locales/en/hue-syncbox-config.json +25 -0
  272. package/huemagic/locales/en/hue-syncbox.html +86 -0
  273. package/huemagic/locales/en/hue-syncbox.json +30 -0
  274. package/huemagic/locales/{en-US → en}/hue-temperature.html +4 -2
  275. package/huemagic/locales/{en-US → en}/hue-temperature.json +11 -9
  276. package/huemagic/locales/es/hue-automation.html +59 -0
  277. package/huemagic/locales/es/hue-automation.json +33 -0
  278. package/huemagic/locales/es/hue-bridge-config.html +31 -0
  279. package/huemagic/locales/es/hue-bridge-config.json +40 -0
  280. package/huemagic/locales/es/hue-bridge.html +96 -0
  281. package/huemagic/locales/es/hue-bridge.json +26 -0
  282. package/huemagic/locales/es/hue-brightness.html +70 -0
  283. package/huemagic/locales/es/hue-brightness.json +37 -0
  284. package/huemagic/locales/es/hue-buttons.html +59 -0
  285. package/huemagic/locales/es/hue-buttons.json +42 -0
  286. package/huemagic/locales/es/hue-contact.html +67 -0
  287. package/huemagic/locales/es/hue-contact.json +35 -0
  288. package/huemagic/locales/es/hue-group.html +87 -0
  289. package/huemagic/locales/es/hue-group.json +46 -0
  290. package/huemagic/locales/es/hue-light.html +97 -0
  291. package/huemagic/locales/es/hue-light.json +44 -0
  292. package/huemagic/locales/es/hue-magic.html +68 -0
  293. package/huemagic/locales/es/hue-magic.json +26 -0
  294. package/huemagic/locales/es/hue-motion.html +64 -0
  295. package/huemagic/locales/es/hue-motion.json +36 -0
  296. package/huemagic/locales/es/hue-rules.html +69 -0
  297. package/huemagic/locales/es/hue-rules.json +30 -0
  298. package/huemagic/locales/es/hue-scene.html +43 -0
  299. package/huemagic/locales/es/hue-scene.json +32 -0
  300. package/huemagic/locales/es/hue-speaker.html +80 -0
  301. package/huemagic/locales/es/hue-speaker.json +38 -0
  302. package/huemagic/locales/es/hue-syncbox-config.html +19 -0
  303. package/huemagic/locales/es/hue-syncbox-config.json +25 -0
  304. package/huemagic/locales/es/hue-syncbox.html +86 -0
  305. package/huemagic/locales/es/hue-syncbox.json +30 -0
  306. package/huemagic/locales/es/hue-temperature.html +69 -0
  307. package/huemagic/locales/es/hue-temperature.json +33 -0
  308. package/huemagic/locales/fr/hue-automation.html +59 -0
  309. package/huemagic/locales/fr/hue-automation.json +33 -0
  310. package/huemagic/locales/fr/hue-bridge-config.html +31 -0
  311. package/huemagic/locales/fr/hue-bridge-config.json +40 -0
  312. package/huemagic/locales/fr/hue-bridge.html +96 -0
  313. package/huemagic/locales/fr/hue-bridge.json +26 -0
  314. package/huemagic/locales/fr/hue-brightness.html +70 -0
  315. package/huemagic/locales/fr/hue-brightness.json +37 -0
  316. package/huemagic/locales/fr/hue-buttons.html +59 -0
  317. package/huemagic/locales/fr/hue-buttons.json +42 -0
  318. package/huemagic/locales/fr/hue-contact.html +67 -0
  319. package/huemagic/locales/fr/hue-contact.json +35 -0
  320. package/huemagic/locales/fr/hue-group.html +87 -0
  321. package/huemagic/locales/fr/hue-group.json +46 -0
  322. package/huemagic/locales/fr/hue-light.html +97 -0
  323. package/huemagic/locales/fr/hue-light.json +44 -0
  324. package/huemagic/locales/fr/hue-magic.html +68 -0
  325. package/huemagic/locales/fr/hue-magic.json +26 -0
  326. package/huemagic/locales/fr/hue-motion.html +64 -0
  327. package/huemagic/locales/fr/hue-motion.json +36 -0
  328. package/huemagic/locales/fr/hue-rules.html +69 -0
  329. package/huemagic/locales/fr/hue-rules.json +30 -0
  330. package/huemagic/locales/fr/hue-scene.html +43 -0
  331. package/huemagic/locales/fr/hue-scene.json +32 -0
  332. package/huemagic/locales/fr/hue-speaker.html +80 -0
  333. package/huemagic/locales/fr/hue-speaker.json +38 -0
  334. package/huemagic/locales/fr/hue-syncbox-config.html +19 -0
  335. package/huemagic/locales/fr/hue-syncbox-config.json +25 -0
  336. package/huemagic/locales/fr/hue-syncbox.html +86 -0
  337. package/huemagic/locales/fr/hue-syncbox.json +30 -0
  338. package/huemagic/locales/fr/hue-temperature.html +69 -0
  339. package/huemagic/locales/fr/hue-temperature.json +33 -0
  340. package/huemagic/locales/it/hue-automation.html +59 -0
  341. package/huemagic/locales/it/hue-automation.json +33 -0
  342. package/huemagic/locales/it/hue-bridge-config.html +31 -0
  343. package/huemagic/locales/it/hue-bridge-config.json +40 -0
  344. package/huemagic/locales/it/hue-bridge.html +96 -0
  345. package/huemagic/locales/it/hue-bridge.json +26 -0
  346. package/huemagic/locales/it/hue-brightness.html +70 -0
  347. package/huemagic/locales/it/hue-brightness.json +37 -0
  348. package/huemagic/locales/it/hue-buttons.html +59 -0
  349. package/huemagic/locales/it/hue-buttons.json +42 -0
  350. package/huemagic/locales/it/hue-contact.html +67 -0
  351. package/huemagic/locales/it/hue-contact.json +35 -0
  352. package/huemagic/locales/it/hue-group.html +87 -0
  353. package/huemagic/locales/it/hue-group.json +46 -0
  354. package/huemagic/locales/it/hue-light.html +97 -0
  355. package/huemagic/locales/it/hue-light.json +44 -0
  356. package/huemagic/locales/it/hue-magic.html +68 -0
  357. package/huemagic/locales/it/hue-magic.json +26 -0
  358. package/huemagic/locales/it/hue-motion.html +64 -0
  359. package/huemagic/locales/it/hue-motion.json +36 -0
  360. package/huemagic/locales/it/hue-rules.html +69 -0
  361. package/huemagic/locales/it/hue-rules.json +30 -0
  362. package/huemagic/locales/it/hue-scene.html +43 -0
  363. package/huemagic/locales/it/hue-scene.json +32 -0
  364. package/huemagic/locales/it/hue-speaker.html +80 -0
  365. package/huemagic/locales/it/hue-speaker.json +38 -0
  366. package/huemagic/locales/it/hue-syncbox-config.html +19 -0
  367. package/huemagic/locales/it/hue-syncbox-config.json +25 -0
  368. package/huemagic/locales/it/hue-syncbox.html +86 -0
  369. package/huemagic/locales/it/hue-syncbox.json +30 -0
  370. package/huemagic/locales/it/hue-temperature.html +69 -0
  371. package/huemagic/locales/it/hue-temperature.json +33 -0
  372. package/huemagic/locales/nl/hue-automation.html +59 -0
  373. package/huemagic/locales/nl/hue-automation.json +33 -0
  374. package/huemagic/locales/nl/hue-bridge-config.html +31 -0
  375. package/huemagic/locales/nl/hue-bridge-config.json +40 -0
  376. package/huemagic/locales/nl/hue-bridge.html +96 -0
  377. package/huemagic/locales/nl/hue-bridge.json +26 -0
  378. package/huemagic/locales/nl/hue-brightness.html +70 -0
  379. package/huemagic/locales/nl/hue-brightness.json +37 -0
  380. package/huemagic/locales/nl/hue-buttons.html +59 -0
  381. package/huemagic/locales/nl/hue-buttons.json +42 -0
  382. package/huemagic/locales/nl/hue-contact.html +67 -0
  383. package/huemagic/locales/nl/hue-contact.json +35 -0
  384. package/huemagic/locales/nl/hue-group.html +87 -0
  385. package/huemagic/locales/nl/hue-group.json +46 -0
  386. package/huemagic/locales/nl/hue-light.html +97 -0
  387. package/huemagic/locales/nl/hue-light.json +44 -0
  388. package/huemagic/locales/nl/hue-magic.html +68 -0
  389. package/huemagic/locales/nl/hue-magic.json +26 -0
  390. package/huemagic/locales/nl/hue-motion.html +64 -0
  391. package/huemagic/locales/nl/hue-motion.json +36 -0
  392. package/huemagic/locales/nl/hue-rules.html +69 -0
  393. package/huemagic/locales/nl/hue-rules.json +30 -0
  394. package/huemagic/locales/nl/hue-scene.html +43 -0
  395. package/huemagic/locales/nl/hue-scene.json +32 -0
  396. package/huemagic/locales/nl/hue-speaker.html +80 -0
  397. package/huemagic/locales/nl/hue-speaker.json +38 -0
  398. package/huemagic/locales/nl/hue-syncbox-config.html +19 -0
  399. package/huemagic/locales/nl/hue-syncbox-config.json +25 -0
  400. package/huemagic/locales/nl/hue-syncbox.html +86 -0
  401. package/huemagic/locales/nl/hue-syncbox.json +30 -0
  402. package/huemagic/locales/nl/hue-temperature.html +69 -0
  403. package/huemagic/locales/nl/hue-temperature.json +33 -0
  404. package/huemagic/locales/pl/hue-automation.html +59 -0
  405. package/huemagic/locales/pl/hue-automation.json +33 -0
  406. package/huemagic/locales/pl/hue-bridge-config.html +31 -0
  407. package/huemagic/locales/pl/hue-bridge-config.json +40 -0
  408. package/huemagic/locales/pl/hue-bridge.html +96 -0
  409. package/huemagic/locales/pl/hue-bridge.json +26 -0
  410. package/huemagic/locales/pl/hue-brightness.html +70 -0
  411. package/huemagic/locales/pl/hue-brightness.json +37 -0
  412. package/huemagic/locales/pl/hue-buttons.html +59 -0
  413. package/huemagic/locales/pl/hue-buttons.json +42 -0
  414. package/huemagic/locales/pl/hue-contact.html +67 -0
  415. package/huemagic/locales/pl/hue-contact.json +35 -0
  416. package/huemagic/locales/pl/hue-group.html +87 -0
  417. package/huemagic/locales/pl/hue-group.json +46 -0
  418. package/huemagic/locales/pl/hue-light.html +97 -0
  419. package/huemagic/locales/pl/hue-light.json +44 -0
  420. package/huemagic/locales/pl/hue-magic.html +68 -0
  421. package/huemagic/locales/pl/hue-magic.json +26 -0
  422. package/huemagic/locales/pl/hue-motion.html +64 -0
  423. package/huemagic/locales/pl/hue-motion.json +36 -0
  424. package/huemagic/locales/pl/hue-rules.html +69 -0
  425. package/huemagic/locales/pl/hue-rules.json +30 -0
  426. package/huemagic/locales/pl/hue-scene.html +43 -0
  427. package/huemagic/locales/pl/hue-scene.json +32 -0
  428. package/huemagic/locales/pl/hue-speaker.html +80 -0
  429. package/huemagic/locales/pl/hue-speaker.json +38 -0
  430. package/huemagic/locales/pl/hue-syncbox-config.html +19 -0
  431. package/huemagic/locales/pl/hue-syncbox-config.json +25 -0
  432. package/huemagic/locales/pl/hue-syncbox.html +86 -0
  433. package/huemagic/locales/pl/hue-syncbox.json +30 -0
  434. package/huemagic/locales/pl/hue-temperature.html +69 -0
  435. package/huemagic/locales/pl/hue-temperature.json +33 -0
  436. package/huemagic/locales/pt/hue-automation.html +59 -0
  437. package/huemagic/locales/pt/hue-automation.json +33 -0
  438. package/huemagic/locales/pt/hue-bridge-config.html +31 -0
  439. package/huemagic/locales/pt/hue-bridge-config.json +40 -0
  440. package/huemagic/locales/pt/hue-bridge.html +96 -0
  441. package/huemagic/locales/pt/hue-bridge.json +26 -0
  442. package/huemagic/locales/pt/hue-brightness.html +70 -0
  443. package/huemagic/locales/pt/hue-brightness.json +37 -0
  444. package/huemagic/locales/pt/hue-buttons.html +59 -0
  445. package/huemagic/locales/pt/hue-buttons.json +42 -0
  446. package/huemagic/locales/pt/hue-contact.html +67 -0
  447. package/huemagic/locales/pt/hue-contact.json +35 -0
  448. package/huemagic/locales/pt/hue-group.html +87 -0
  449. package/huemagic/locales/pt/hue-group.json +46 -0
  450. package/huemagic/locales/pt/hue-light.html +97 -0
  451. package/huemagic/locales/pt/hue-light.json +44 -0
  452. package/huemagic/locales/pt/hue-magic.html +68 -0
  453. package/huemagic/locales/pt/hue-magic.json +26 -0
  454. package/huemagic/locales/pt/hue-motion.html +64 -0
  455. package/huemagic/locales/pt/hue-motion.json +36 -0
  456. package/huemagic/locales/pt/hue-rules.html +69 -0
  457. package/huemagic/locales/pt/hue-rules.json +30 -0
  458. package/huemagic/locales/pt/hue-scene.html +43 -0
  459. package/huemagic/locales/pt/hue-scene.json +32 -0
  460. package/huemagic/locales/pt/hue-speaker.html +80 -0
  461. package/huemagic/locales/pt/hue-speaker.json +38 -0
  462. package/huemagic/locales/pt/hue-syncbox-config.html +19 -0
  463. package/huemagic/locales/pt/hue-syncbox-config.json +25 -0
  464. package/huemagic/locales/pt/hue-syncbox.html +86 -0
  465. package/huemagic/locales/pt/hue-syncbox.json +30 -0
  466. package/huemagic/locales/pt/hue-temperature.html +69 -0
  467. package/huemagic/locales/pt/hue-temperature.json +33 -0
  468. package/huemagic/locales/tr/hue-automation.html +59 -0
  469. package/huemagic/locales/tr/hue-automation.json +33 -0
  470. package/huemagic/locales/tr/hue-bridge-config.html +31 -0
  471. package/huemagic/locales/tr/hue-bridge-config.json +40 -0
  472. package/huemagic/locales/tr/hue-bridge.html +96 -0
  473. package/huemagic/locales/tr/hue-bridge.json +26 -0
  474. package/huemagic/locales/tr/hue-brightness.html +70 -0
  475. package/huemagic/locales/tr/hue-brightness.json +37 -0
  476. package/huemagic/locales/tr/hue-buttons.html +59 -0
  477. package/huemagic/locales/tr/hue-buttons.json +42 -0
  478. package/huemagic/locales/tr/hue-contact.html +67 -0
  479. package/huemagic/locales/tr/hue-contact.json +35 -0
  480. package/huemagic/locales/tr/hue-group.html +87 -0
  481. package/huemagic/locales/tr/hue-group.json +46 -0
  482. package/huemagic/locales/tr/hue-light.html +97 -0
  483. package/huemagic/locales/tr/hue-light.json +44 -0
  484. package/huemagic/locales/tr/hue-magic.html +68 -0
  485. package/huemagic/locales/tr/hue-magic.json +26 -0
  486. package/huemagic/locales/tr/hue-motion.html +64 -0
  487. package/huemagic/locales/tr/hue-motion.json +36 -0
  488. package/huemagic/locales/tr/hue-rules.html +69 -0
  489. package/huemagic/locales/tr/hue-rules.json +30 -0
  490. package/huemagic/locales/tr/hue-scene.html +43 -0
  491. package/huemagic/locales/tr/hue-scene.json +32 -0
  492. package/huemagic/locales/tr/hue-speaker.html +80 -0
  493. package/huemagic/locales/tr/hue-speaker.json +38 -0
  494. package/huemagic/locales/tr/hue-syncbox-config.html +19 -0
  495. package/huemagic/locales/tr/hue-syncbox-config.json +25 -0
  496. package/huemagic/locales/tr/hue-syncbox.html +86 -0
  497. package/huemagic/locales/tr/hue-syncbox.json +30 -0
  498. package/huemagic/locales/tr/hue-temperature.html +69 -0
  499. package/huemagic/locales/tr/hue-temperature.json +33 -0
  500. package/huemagic/utils/api.js +158 -54
  501. package/huemagic/utils/color.js +20 -2
  502. package/huemagic/utils/merge.js +3 -2
  503. package/huemagic/utils/messages.js +506 -120
  504. package/huemagic/utils/sse.js +51 -0
  505. package/huemagic/utils/syncbox.js +84 -0
  506. package/package.json +19 -11
  507. package/.github/FUNDING.yml +0 -2
  508. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -30
  509. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  510. package/.github/workflows/npm.yml +0 -18
  511. package/huemagic/locales/en-US/hue-bridge-config.json +0 -29
  512. package/huemagic/locales/en-US/hue-buttons.json +0 -34
  513. package/huemagic/locales/en-US/hue-light.json +0 -38
  514. /package/huemagic/locales/{en-US → en}/hue-bridge-config.html +0 -0
  515. /package/huemagic/locales/{en-US → en}/hue-magic.json +0 -0
@@ -16,6 +16,9 @@ module.exports = function(RED)
16
16
  // SAVE LAST COMMAND
17
17
  this.lastCommand = null;
18
18
 
19
+ // NODE UI STATUS TIMEOUT
20
+ this.statusTimeout = null;
21
+
19
22
  // HELPER
20
23
  const colorUtils = require('./utils/color');
21
24
  const merge = require('./utils/merge');
@@ -28,6 +31,43 @@ module.exports = function(RED)
28
31
  return false;
29
32
  }
30
33
 
34
+ //
35
+ // APPLY THE CURRENT STATE TO THE NODE UI
36
+ this.setNodeStatus = function(currentState)
37
+ {
38
+ if(!config.lightid || !currentState) { return false; }
39
+
40
+ if(currentState.payload.reachable === false)
41
+ {
42
+ const offNotReachableStatus = RED._("hue-light.node.turned-off") + " (" + RED._("hue-light.node.not-reachable") + ")";
43
+ scope.status({fill: "red", shape: "ring", text: offNotReachableStatus});
44
+ }
45
+ else if(currentState.payload.on !== true)
46
+ {
47
+ scope.status({fill: "grey", shape: "dot", text: "hue-light.node.turned-off"});
48
+ }
49
+ else if(currentState.payload.brightness !== false)
50
+ {
51
+ scope.status({fill: "yellow", shape: "dot", text: RED._("hue-light.node.turned-on-percent",{ percent: currentState.payload.brightness })});
52
+ }
53
+ else
54
+ {
55
+ scope.status({fill: "yellow", shape: "dot", text: "hue-light.node.turned-on"});
56
+ }
57
+ }
58
+
59
+ //
60
+ // A COMMAND WITHOUT EFFECT PRODUCES NO BRIDGE EVENT -> RESET THE UI OURSELVES
61
+ this.scheduleNodeStatus = function(id)
62
+ {
63
+ if(scope.statusTimeout !== null) { clearTimeout(scope.statusTimeout); }
64
+ scope.statusTimeout = setTimeout(function()
65
+ {
66
+ scope.statusTimeout = null;
67
+ scope.setNodeStatus(bridge.get("light", id, { colornames: config.colornamer ? true : false }));
68
+ }, 2000);
69
+ }
70
+
31
71
  //
32
72
  // UNIVERSAL MODE?
33
73
  if(!config.lightid)
@@ -44,7 +84,7 @@ module.exports = function(RED)
44
84
 
45
85
  //
46
86
  // SUBSCRIBE TO UPDATES FROM THE BRIDGE
47
- bridge.subscribe("light", config.lightid, function(info)
87
+ this.unsubscribe = bridge.subscribe("light", config.lightid, function(info)
48
88
  {
49
89
  let currentState = bridge.get("light", info.id, { colornames: config.colornamer ? true : false });
50
90
 
@@ -52,7 +92,7 @@ module.exports = function(RED)
52
92
  if(currentState !== false)
53
93
  {
54
94
  // SEND MESSAGE
55
- if(!config.skipevents && (config.initevents || info.suppressMessage == false))
95
+ if(!config.skipevents && (config.initevents || info.suppressMessage == false) && (!config.onlycommands || scope.lastCommand !== null))
56
96
  {
57
97
  // SET LAST COMMAND
58
98
  if(scope.lastCommand !== null)
@@ -70,35 +110,14 @@ module.exports = function(RED)
70
110
  // NOT IN UNIVERAL MODE? -> CHANGE UI STATES
71
111
  if(config.lightid)
72
112
  {
73
- if(currentState.payload.reachable === true)
113
+ // APPLY FUTURE STATE COMMANDS
114
+ if(currentState.payload.on === true && Object.values(scope.futurePatchState).length > 0)
74
115
  {
75
- if(currentState.payload.on === true)
76
- {
77
- // APPLY FUTURE STATE COMMANDS
78
- if(Object.values(scope.futurePatchState).length > 0)
79
- {
80
- scope.applyCommands({}, null, null);
81
- }
82
-
83
- if(currentState.payload.brightness !== false)
84
- {
85
- scope.status({fill: "yellow", shape: "dot", text: RED._("hue-light.node.turned-on-percent",{ percent: currentState.payload.brightness })});
86
- }
87
- else
88
- {
89
- scope.status({fill: "yellow", shape: "dot", text: "hue-light.node.turned-on"});
90
- }
91
- }
92
- else
93
- {
94
- scope.status({fill: "grey", shape: "dot", text: "hue-light.node.turned-off"});
95
- }
96
- }
97
- else
98
- {
99
- var offNotReachableStatus = RED._("hue-light.node.turned-off") + " (" + RED._("hue-light.node.not-reachable") + ")";
100
- scope.status({fill: "red", shape: "ring", text: offNotReachableStatus});
116
+ scope.applyCommands({}, null, null);
101
117
  }
118
+
119
+ if(scope.statusTimeout !== null) { clearTimeout(scope.statusTimeout); scope.statusTimeout = null; }
120
+ scope.setNodeStatus(currentState);
102
121
  }
103
122
  }
104
123
  });
@@ -121,19 +140,19 @@ module.exports = function(RED)
121
140
  // CREATE PATCH
122
141
  let patchObject = {};
123
142
 
124
- // DEFINE SENSOR ID & CURRENT STATE
143
+ // DEFINE LIGHT ID
125
144
  const tempLightID = (!config.lightid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.lightid;
126
- let currentState = bridge.get("light", tempLightID, { colornames: config.colornamer ? true : false });
127
- if(!currentState)
145
+ if(!tempLightID)
128
146
  {
129
- scope.error("The light in not yet available. Please wait until HueMagic has established a connection with the bridge or check whether the resource ID in the configuration is valid.");
147
+ scope.error(RED._("hue-light.node.error-no-id"), msg);
130
148
  return false;
131
149
  }
132
150
 
133
- // CHECK IF LIGHT ID IS SET
134
- if(!tempLightID)
151
+ // GET CURRENT STATE
152
+ let currentState = bridge.get("light", tempLightID, { colornames: config.colornamer ? true : false });
153
+ if(!currentState)
135
154
  {
136
- scope.error(RED._("hue-light.node.error-no-id"));
155
+ scope.error(RED._("hue-light.node.error-not-available"), msg);
137
156
  return false;
138
157
  }
139
158
 
@@ -163,22 +182,28 @@ module.exports = function(RED)
163
182
  scope.futurePatchState = {};
164
183
  }
165
184
 
166
- // COLORLOOP EFFECT
185
+ // COLORLOOP EFFECT (CLIP/v2 HAS NO EQUIVALENT, SO THIS STAYS ON THE LEGACY API)
167
186
  if(typeof msg.payload != 'undefined' && typeof msg.payload.colorloop != 'undefined' && msg.payload.colorloop > 0)
168
187
  {
188
+ if(!currentState.info.idV1)
189
+ {
190
+ scope.error(RED._("hue-light.node.error-no-colorloop"), msg);
191
+ return false;
192
+ }
193
+
169
194
  patchObject = {
170
195
  "on": true,
171
196
  "effect": "colorloop",
172
- "bri": msg.payload.brightness ? Math.round((254/100)*msg.payload.brightness) : currentState.brightnessLevel
197
+ "bri": msg.payload.brightness ? Math.round((254/100)*msg.payload.brightness) : currentState.payload.brightnessLevel
173
198
  };
174
199
 
175
200
  // PATCH!
176
201
  async.retry({
177
- times: 3,
202
+ times: 5,
178
203
  errorFilter: function(err) {
179
- return (err.status == 503);
204
+ return (err.status == 503 || err.status == 429);
180
205
  },
181
- interval: function(retryCount) { return retryCount*2000; }
206
+ interval: function(retryCount) { return 750*retryCount; }
182
207
  },
183
208
  function(callback, results)
184
209
  {
@@ -217,32 +242,16 @@ module.exports = function(RED)
217
242
  // ALERT EFFECT
218
243
  if(typeof msg.payload != 'undefined' && typeof msg.payload.alert != 'undefined' && msg.payload.alert > 0)
219
244
  {
220
- // SAVE PREVIOUS STATE
221
- scope.context().set('lightPreviousState', currentState);
222
-
223
- // TURN ON LIGHT
224
- if(currentState.payload.on === false)
225
- {
226
- patchObject["on"] = { on: true };
227
- }
228
-
229
- // SET BRIGHTNESS
230
- if(!msg.payload.brightness && currentState.payload.brightness != 100)
231
- {
232
- patchObject["dimming"] = { brightness: 100 };
233
- }
234
- else if(msg.payload.brightness)
235
- {
236
- patchObject["dimming"] = { brightness: parseInt(msg.payload.brightness) };
237
- }
245
+ // THE BRIDGE BLINKS AND RESTORES THE PREVIOUS STATE ON ITS OWN
246
+ let duration = Math.round(parseFloat(msg.payload.alert)) * 1000;
247
+ duration = (duration > 65534000) ? 65534000 : duration;
238
248
 
239
- // SET TRANSITION
240
- patchObject["dynamics"] = { duration: 0 };
249
+ let signaling = { signal: "on_off", duration: duration };
241
250
 
242
- // CAN CHANGE COLOR?
251
+ // BLINK IN A SPECIFIC COLOR?
243
252
  if(currentState.payload.xyColor)
244
253
  {
245
- let XYAlertColor = {};
254
+ let XYAlertColor = false;
246
255
 
247
256
  if(typeof msg.payload.rgb != 'undefined')
248
257
  {
@@ -255,30 +264,18 @@ module.exports = function(RED)
255
264
  }
256
265
  else if(typeof msg.payload.color != 'undefined')
257
266
  {
258
- if(new RegExp("random|any|whatever").test(msg.payload.color))
267
+ const colorHex = new RegExp("random|any|whatever").test(msg.payload.color) ? colorUtils.randomHexColor() : colorUtils.colornames(msg.payload.color);
268
+ if(colorHex)
259
269
  {
260
- const randomColor = colorUtils.randomHexColor();
261
- let rgbFromHex = colorUtils.hexRgb(rgbFromHex);
270
+ let rgbFromHex = colorUtils.hexRgb(colorHex);
262
271
  XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
263
272
  }
264
- else
265
- {
266
- var colorHex = colorUtils.colornames(msg.payload.color);
267
- if(colorHex)
268
- {
269
- let rgbFromHex = colorUtils.hexRgb(colorHex);
270
- XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
271
- }
272
- }
273
273
  }
274
- else
274
+
275
+ if(XYAlertColor)
275
276
  {
276
- XYAlertColor = colorUtils.rgbToXy(255, 0, 0, currentState.info.model.colorGamut);
277
+ signaling = { signal: "on_off_color", duration: duration, colors: [{ xy: XYAlertColor }] };
277
278
  }
278
-
279
- patchObject["color"] = {
280
- xy: XYAlertColor
281
- };
282
279
  }
283
280
 
284
281
  // CHANGE NODE UI STATE
@@ -287,66 +284,33 @@ module.exports = function(RED)
287
284
  scope.status({fill: "grey", shape: "ring", text: "hue-light.node.command"});
288
285
  }
289
286
 
290
-
291
287
  // APPLY THE EFFECT
292
288
  async.retry({
293
- times: 3,
289
+ times: 5,
294
290
  errorFilter: function(err) {
295
- return (err.status == 503);
291
+ return (err.status == 503 || err.status == 429);
296
292
  },
297
- interval: function(retryCount) { return retryCount*2000; }
293
+ interval: function(retryCount) { return 750*retryCount; }
298
294
  },
299
295
  function(callback, results)
300
296
  {
301
- // 1. TURN ON THE LIGHT BULB
302
- bridge.patch("light", tempLightID, patchObject)
303
- .then(function(status) {
304
- // 2. APPLY ALERT EFFECT
305
- const alertEffect = { alert: { action: "breathe" }};
306
- return bridge.patch("light", tempLightID, alertEffect);
307
- })
308
- .then(function(status) {
309
- // 3. RESET PREVIOUS STATE (AFTER X SECONDS)
310
- setTimeout(function()
311
- {
312
- const tempPreviousState = scope.context().get('lightPreviousState');
313
- var tempPreviousStatePatch = {};
314
-
315
- tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
316
- if(tempPreviousState.payload.xyColor)
317
- {
318
- tempPreviousStatePatch.color = { xy: tempPreviousState.payload.xyColor };
319
- }
320
- else if(tempPreviousState.payload.colorTemp)
321
- {
322
- tempPreviousStatePatch.color_temperature = { mirek: tempPreviousState.payload.colorTemp };
323
- }
324
-
325
- bridge.patch("light", tempLightID, tempPreviousStatePatch).
326
- then(function(status)
327
- {
328
- return bridge.patch("light", tempLightID, { on: { on: false } })
329
- .then(function() { if(done) { done(); }});
330
- })
331
- .then(function(status) {
332
- if(tempPreviousState.payload.on === true)
333
- {
334
- bridge.patch("light", tempLightID, { on: { on: true } })
335
- .then(function() { if(done) { done(); }});
336
- }
337
- });
338
- }, parseInt(msg.payload.alert) * 1000);
339
- callback(null, true);
297
+ bridge.patch("light", tempLightID, { signaling: signaling })
298
+ .catch(function(errors)
299
+ {
300
+ // OLDER LIGHTS ONLY KNOW THE (15 SECONDS LONG) BREATHE EFFECT
301
+ if(errors.status !== 400) { throw errors; }
302
+ return bridge.patch("light", tempLightID, { alert: { action: "breathe" } });
340
303
  })
341
- .catch(function(errors) {
342
- callback(errors, null);
343
- });
304
+ .then(function() { callback(null, true); })
305
+ .catch(function(errors) { callback(errors, null); });
344
306
  },
345
307
  function(errors, success)
346
308
  {
309
+ scope.scheduleNodeStatus(tempLightID);
310
+
347
311
  if(errors)
348
312
  {
349
- scope.error(errors);
313
+ scope.error(errors, msg);
350
314
  scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
351
315
  }
352
316
  else if(done)
@@ -365,9 +329,20 @@ module.exports = function(RED)
365
329
  else if(typeof msg.animation != 'undefined' && msg.animation.status == false && msg.animation.restore == true)
366
330
  {
367
331
  const tempPreviousState = scope.context().get('lightPreviousState');
368
- var tempPreviousStatePatch = {};
332
+ if(!tempPreviousState)
333
+ {
334
+ if(done) { done(); }
335
+ return false;
336
+ }
337
+
338
+ // RESTORE IN ONE SINGLE PATCH, OTHERWISE THE LIGHT FLICKERS
339
+ var tempPreviousStatePatch = { on: { on: tempPreviousState.payload.on } };
340
+
341
+ if(tempPreviousState.payload.brightness !== false)
342
+ {
343
+ tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
344
+ }
369
345
 
370
- tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
371
346
  if(tempPreviousState.payload.xyColor)
372
347
  {
373
348
  tempPreviousStatePatch.color = { xy: tempPreviousState.payload.xyColor };
@@ -379,31 +354,16 @@ module.exports = function(RED)
379
354
 
380
355
  // PATCH!
381
356
  async.retry({
382
- times: 3,
357
+ times: 5,
383
358
  errorFilter: function(err) {
384
- return (err.status == 503);
359
+ return (err.status == 503 || err.status == 429);
385
360
  },
386
- interval: function(retryCount) { return retryCount*2000; }
361
+ interval: function(retryCount) { return 750*retryCount; }
387
362
  },
388
363
  function(callback, results)
389
364
  {
390
365
  bridge.patch("light", tempLightID, tempPreviousStatePatch)
391
- .then(function(status)
392
- {
393
- if(tempPreviousState.payload.on === false)
394
- {
395
- bridge.patch("light", tempLightID, { on: { on: false } })
396
- .then(function() { callback(null, true); });
397
- }
398
- else
399
- {
400
- bridge.patch("light", tempLightID, { on: { on: false } })
401
- .then(function(status) {
402
- callback(null, true);
403
- return bridge.patch("light", tempLightID, { on: { on: true } });
404
- });
405
- }
406
- })
366
+ .then(function() { callback(null, true); })
407
367
  .catch(function(errors) { callback(errors, null); });
408
368
  },
409
369
  function(errors, success)
@@ -421,16 +381,16 @@ module.exports = function(RED)
421
381
  // EXTENDED COMMANDS
422
382
  else
423
383
  {
424
- // SET LIGHT STATE SIMPLE MODE
384
+ // SET LIGHT STATE SIMPLE MODE (ALWAYS SENT, THE CACHED STATE MAY BE OUTDATED)
425
385
  if(msg.payload === true||msg.payload === false)
426
386
  {
427
- if(msg.payload !== currentState.payload.on) { patchObject["on"] = { on: msg.payload }; }
387
+ patchObject["on"] = { on: msg.payload };
428
388
  }
429
389
 
430
390
  // SET LIGHT STATE
431
391
  if(typeof msg.payload != 'undefined' && typeof msg.payload.on != 'undefined' && (msg.payload.on === true || msg.payload.on === false))
432
392
  {
433
- if(msg.payload.on !== currentState.payload.on) { patchObject["on"] = { on: msg.payload.on }; }
393
+ patchObject["on"] = { on: msg.payload.on };
434
394
  }
435
395
 
436
396
  // TOGGLE ON / OFF
@@ -457,7 +417,7 @@ module.exports = function(RED)
457
417
  {
458
418
  if(msg.payload.brightness > 100 || msg.payload.brightness < 0)
459
419
  {
460
- scope.error("Invalid brightness setting. Only 0 - 100 percent allowed");
420
+ scope.error(RED._("hue-light.node.error-invalid-brightness"), msg);
461
421
  return false;
462
422
  }
463
423
  else if(msg.payload.brightness == 0)
@@ -474,10 +434,10 @@ module.exports = function(RED)
474
434
  {
475
435
  if(msg.payload.brightnessLevel > 254 || msg.payload.brightnessLevel < 0)
476
436
  {
477
- scope.error("Invalid brightness setting. Only 0 - 254 allowed");
437
+ scope.error(RED._("hue-light.node.error-invalid-brightness-level"), msg);
478
438
  return false;
479
439
  }
480
- else if(msg.payload.brightness == 0)
440
+ else if(msg.payload.brightnessLevel == 0)
481
441
  {
482
442
  if(currentState.payload.on !== false) { patchObject["on"] = { on: false }; }
483
443
  }
@@ -628,7 +588,7 @@ module.exports = function(RED)
628
588
  }
629
589
  else
630
590
  {
631
- scope.error("Invalid color temprature. Only 153 - 500 allowed");
591
+ scope.error(RED._("hue-light.node.error-invalid-temp"), msg);
632
592
  return false;
633
593
  }
634
594
  }
@@ -730,7 +690,7 @@ module.exports = function(RED)
730
690
  {
731
691
  if(msg.payload.saturation > 100 || msg.payload.saturation < 0)
732
692
  {
733
- scope.error("Invalid saturation setting. Only 0 - 100 allowed");
693
+ scope.error(RED._("hue-light.node.error-invalid-sat"), msg);
734
694
  return false;
735
695
  }
736
696
  else
@@ -760,7 +720,7 @@ module.exports = function(RED)
760
720
  {
761
721
  XYColorSet = [];
762
722
 
763
- for(let oneColor in msg.payload.gradient.hex)
723
+ for(let oneColor of msg.payload.gradient.hex)
764
724
  {
765
725
  let rgbFromHex = colorUtils.hexRgb(oneColor);
766
726
  XYColorSet.push({
@@ -773,7 +733,7 @@ module.exports = function(RED)
773
733
  {
774
734
  XYColorSet = [];
775
735
 
776
- for(let oneColor in msg.payload.gradient.rgb)
736
+ for(let oneColor of msg.payload.gradient.rgb)
777
737
  {
778
738
  XYColorSet.push({
779
739
  color: { xy: colorUtils.rgbToXy(oneColor[0], oneColor[1], oneColor[2], currentState.info.model.colorGamut) }
@@ -785,7 +745,7 @@ module.exports = function(RED)
785
745
  {
786
746
  XYColorSet = [];
787
747
 
788
- for(let oneColor in msg.payload.gradient.xyColor)
748
+ for(let oneColor of msg.payload.gradient.xyColor)
789
749
  {
790
750
  XYColorSet.push({
791
751
  color: { xy: oneColor }
@@ -794,18 +754,102 @@ module.exports = function(RED)
794
754
  }
795
755
 
796
756
  patchObject["gradient"] = { points: XYColorSet };
757
+
758
+ // HOW THE COLORS ARE SPREAD ACROSS THE LIGHT
759
+ if(typeof msg.payload.gradient.mode != 'undefined')
760
+ {
761
+ patchObject["gradient"]["mode"] = msg.payload.gradient.mode;
762
+ }
763
+ }
764
+
765
+ // SET A LIGHT EFFECT (CANDLE, FIRE, SPARKLE…)
766
+ if(typeof msg.payload != 'undefined' && typeof msg.payload.effect != 'undefined' && typeof currentState.payload.effect != 'undefined')
767
+ {
768
+ const effect = (msg.payload.effect === false) ? "no_effect" : (msg.payload.effect + "");
769
+
770
+ if(currentState.info.model.effects.indexOf(effect) === -1)
771
+ {
772
+ scope.error(RED._("hue-light.node.error-invalid-effect", { effects: currentState.info.model.effects.join(", ") }), msg);
773
+ return false;
774
+ }
775
+
776
+ // THE NEWER "effects_v2" ALSO TAKES A COLOR AND A SPEED
777
+ if(currentState.info.model.effectsV2 === true)
778
+ {
779
+ let action = { effect: effect };
780
+ let parameters = {};
781
+
782
+ if(typeof msg.payload.effectSpeed != 'undefined') { parameters.speed = parseFloat(msg.payload.effectSpeed); }
783
+ if(patchObject["color"]) { parameters.color = patchObject["color"]; delete patchObject["color"]; }
784
+ else if(patchObject["color_temperature"]) { parameters.color_temperature = patchObject["color_temperature"]; delete patchObject["color_temperature"]; }
785
+
786
+ if(Object.values(parameters).length > 0) { action.parameters = parameters; }
787
+ patchObject["effects_v2"] = { action: action };
788
+ }
789
+ else
790
+ {
791
+ patchObject["effects"] = { effect: effect };
792
+ }
793
+ }
794
+
795
+ // SET A TIMED EFFECT (SUNRISE / SUNSET)
796
+ if(typeof msg.payload != 'undefined' && typeof msg.payload.timedEffect != 'undefined' && typeof currentState.payload.timedEffect != 'undefined')
797
+ {
798
+ const timedEffect = (msg.payload.timedEffect === false) ? "no_effect" : (msg.payload.timedEffect + "");
799
+
800
+ if(currentState.info.model.timedEffects.indexOf(timedEffect) === -1)
801
+ {
802
+ scope.error(RED._("hue-light.node.error-invalid-effect", { effects: currentState.info.model.timedEffects.join(", ") }), msg);
803
+ return false;
804
+ }
805
+
806
+ patchObject["timed_effects"] = { effect: timedEffect };
807
+
808
+ // UP TO SIX HOURS
809
+ if(typeof msg.payload.duration != 'undefined')
810
+ {
811
+ let duration = Math.round(parseFloat(msg.payload.duration) * 1000);
812
+ duration = (duration > 21600000) ? 21600000 : ((duration < 0) ? 0 : duration);
813
+
814
+ patchObject["timed_effects"]["duration"] = duration;
815
+ }
816
+ }
817
+
818
+ // SET THE BEHAVIOUR AFTER A POWER CUT
819
+ if(typeof msg.payload != 'undefined' && typeof msg.payload.powerUp != 'undefined')
820
+ {
821
+ const presets = ["safety", "powerfail", "last_on_state", "custom"];
822
+ const powerUp = (typeof msg.payload.powerUp == 'string') ? { preset: msg.payload.powerUp } : msg.payload.powerUp;
823
+
824
+ if(!powerUp.preset || presets.indexOf(powerUp.preset) === -1)
825
+ {
826
+ scope.error(RED._("hue-light.node.error-invalid-powerup", { presets: presets.join(", ") }), msg);
827
+ return false;
828
+ }
829
+
830
+ patchObject["powerup"] = { preset: powerUp.preset };
831
+
832
+ // THE BRIDGE ONLY ACCEPTS THE DETAILS TOGETHER WITH THE "custom" PRESET
833
+ if(powerUp.preset === "custom")
834
+ {
835
+ if(typeof powerUp.on != 'undefined') { patchObject["powerup"]["on"] = (typeof powerUp.on == 'string') ? { mode: powerUp.on } : { mode: "on", on: { on: (powerUp.on === true) } }; }
836
+ if(typeof powerUp.brightness != 'undefined') { patchObject["powerup"]["dimming"] = { mode: "dimming", dimming: { brightness: powerUp.brightness } }; }
837
+ if(typeof powerUp.colorTemp != 'undefined') { patchObject["powerup"]["color"] = { mode: "color_temperature", color_temperature: { mirek: powerUp.colorTemp } }; }
838
+ else if(typeof powerUp.xyColor != 'undefined') { patchObject["powerup"]["color"] = { mode: "color", color: { xy: powerUp.xyColor } }; }
839
+ }
797
840
  }
798
841
 
799
842
  //
800
843
  // SHOULD PATCH?
801
844
  if(Object.values(patchObject).length > 0)
802
845
  {
803
- // IS FOR LATER?
846
+ // IS FOR LATER? (ONLY IF THE COMMAND ITSELF DOES NOT SWITCH THE LIGHT)
804
847
  if(currentState.payload.on === false || currentState.payload.reachable === false)
805
848
  {
806
- if(!patchObject["on"] || !patchObject["on"]["on"])
849
+ if(!patchObject["on"])
807
850
  {
808
851
  scope.futurePatchState = merge.deep(scope.futurePatchState, patchObject);
852
+ if(done) { done(); }
809
853
  return false;
810
854
  }
811
855
  }
@@ -818,11 +862,11 @@ module.exports = function(RED)
818
862
 
819
863
  // PATCH!
820
864
  async.retry({
821
- times: 3,
865
+ times: 5,
822
866
  errorFilter: function(err) {
823
- return (err.status == 503);
867
+ return (err.status == 503 || err.status == 429);
824
868
  },
825
- interval: function(retryCount) { return retryCount*2000; }
869
+ interval: function(retryCount) { return 750*retryCount; }
826
870
  },
827
871
  function(callback, results)
828
872
  {
@@ -832,9 +876,12 @@ module.exports = function(RED)
832
876
  },
833
877
  function(errors, success)
834
878
  {
879
+ // THE UI STAYS ON "EXECUTING COMMAND" IF THE COMMAND CHANGED NOTHING
880
+ scope.scheduleNodeStatus(tempLightID);
881
+
835
882
  if(errors)
836
883
  {
837
- scope.error(errors);
884
+ scope.error(errors, msg);
838
885
  }
839
886
  else if(done)
840
887
  {
@@ -860,7 +907,15 @@ module.exports = function(RED)
860
907
  }
861
908
  }
862
909
  }
910
+
911
+ //
912
+ // CLOSE NODE
913
+ this.on('close', function()
914
+ {
915
+ if(scope.statusTimeout !== null) { clearTimeout(scope.statusTimeout); }
916
+ if(scope.unsubscribe) { scope.unsubscribe(); }
917
+ });
863
918
  }
864
919
 
865
920
  RED.nodes.registerType("hue-light", HueLight);
866
- }
921
+ }
@@ -5,13 +5,11 @@
5
5
  </div>
6
6
  <div class="form-row">
7
7
  <label for="node-input-endless"><i class="fa fa-refresh"></i> <span data-i18n="hue-magic.config.loop"></span></label>
8
- <input type="checkbox" id="node-input-endless" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="hue-magic.config.loop-endless"></span>
9
- </label>
8
+ <input type="checkbox" id="node-input-endless" style="display:inline-block; width:auto; vertical-align:middle; margin:0 6px 0 0;"><span data-i18n="hue-magic.config.loop-endless" style="vertical-align:middle;"></span>
10
9
  </div>
11
10
  <div class="form-row">
12
11
  <label for="node-input-restore"><i class="fa fa-undo"></i> <span data-i18n="hue-magic.config.restore"></span></label>
13
- <input type="checkbox" id="node-input-restore" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="hue-magic.config.restore-state"></span>
14
- </label>
12
+ <input type="checkbox" id="node-input-restore" style="display:inline-block; width:auto; vertical-align:middle; margin:0 6px 0 0;"><span data-i18n="hue-magic.config.restore-state" style="vertical-align:middle;"></span>
15
13
  </div>
16
14
  <div class="form-row" style="margin-top: 30px">
17
15
  <label for="node-input-steps"><i class="fa fa-magic"></i> <span data-i18n="hue-magic.config.animation"></span></label>
@@ -150,7 +148,7 @@
150
148
  steps: { value: null }
151
149
  },
152
150
  align: 'left',
153
- icon: "hue-magic.png",
151
+ icon: "hue-magic.svg",
154
152
  inputs: 1,
155
153
  outputs: 1,
156
154
  label: function() {