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
@@ -4,7 +4,7 @@
4
4
  <input type="text" id="node-input-name" data-i18n="[placeholder]hue-motion.config.input-name" style="width: calc(100% - 105px)">
5
5
  </div>
6
6
  <div class="form-row">
7
- <label for="node-input-bridge"><i class="fa fa-server"></i> Bridge</label>
7
+ <label for="node-input-bridge"><i class="fa fa-server"></i> <span data-i18n="hue-motion.config.bridge"></span></label>
8
8
  <input type="text" id="node-input-bridge" style="width: calc(100% - 105px)">
9
9
  </div>
10
10
  <div class="form-row">
@@ -19,15 +19,21 @@
19
19
  </div>
20
20
  </div>
21
21
  <div class="form-row" style="margin-top: 30px">
22
- <div style="display: inline-flex; width: calc(100% - 105px)">
23
- <input type="checkbox" id="node-input-skipevents" style="flex: 15px;">
24
- <span data-i18n="hue-motion.config.skipevents-node" style="width: 100%; margin-left: 10px;"></span>
22
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
23
+ <input type="checkbox" id="node-input-skipevents" style="flex: 0 0 auto; width: auto; margin: 0;">
24
+ <span data-i18n="hue-motion.config.skipevents-node" style="flex: 1; margin-left: 8px;"></span>
25
25
  </div>
26
26
  </div>
27
27
  <div class="form-row">
28
- <div style="display: inline-flex; width: calc(100% - 105px)">
29
- <input type="checkbox" id="node-input-initevents" style="flex: 15px;">
30
- <span data-i18n="hue-motion.config.sendinitevents-node" style="width: 100%; margin-left: 10px;"></span>
28
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
29
+ <input type="checkbox" id="node-input-initevents" style="flex: 0 0 auto; width: auto; margin: 0;">
30
+ <span data-i18n="hue-motion.config.sendinitevents-node" style="flex: 1; margin-left: 8px;"></span>
31
+ </div>
32
+ </div>
33
+ <div class="form-row">
34
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
35
+ <input type="checkbox" id="node-input-onlycommands" style="flex: 0 0 auto; width: auto; margin: 0;">
36
+ <span data-i18n="hue-motion.config.onlycommands-node" style="flex: 1; margin-left: 8px;"></span>
31
37
  </div>
32
38
  </div>
33
39
  </script>
@@ -41,10 +47,11 @@
41
47
  bridge: { type: "hue-bridge", required: true },
42
48
  sensorid: { value:"", required: false },
43
49
  skipevents: { value: false },
44
- initevents: { value: false }
50
+ initevents: { value: false },
51
+ onlycommands: { value: false }
45
52
  },
46
53
  align: 'left',
47
- icon: "hue-motion.png",
54
+ icon: "hue-motion.svg",
48
55
  inputs: 1,
49
56
  outputs: 1,
50
57
  label: function() {
@@ -37,7 +37,7 @@ module.exports = function(RED)
37
37
 
38
38
  //
39
39
  // SUBSCRIBE TO UPDATES FROM THE BRIDGE
40
- bridge.subscribe("motion", config.sensorid, function(info)
40
+ this.unsubscribe = bridge.subscribe("motion", config.sensorid, function(info)
41
41
  {
42
42
  let currentState = bridge.get("motion", info.id);
43
43
 
@@ -45,7 +45,7 @@ module.exports = function(RED)
45
45
  if(currentState !== false)
46
46
  {
47
47
  // SEND MESSAGE
48
- if(!config.skipevents && (config.initevents || info.suppressMessage == false))
48
+ if(!config.skipevents && (config.initevents || info.suppressMessage == false) && (!config.onlycommands || scope.lastCommand !== null))
49
49
  {
50
50
  // SET LAST COMMAND
51
51
  if(scope.lastCommand !== null)
@@ -104,14 +104,14 @@ module.exports = function(RED)
104
104
  const tempSensorID = (!config.sensorid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.sensorid;
105
105
  if(!tempSensorID)
106
106
  {
107
- scope.error("Please submit a valid sensor ID.");
107
+ scope.error(RED._("hue-motion.node.error-no-id"), msg);
108
108
  return false;
109
109
  }
110
110
 
111
111
  let currentState = bridge.get("motion", tempSensorID);
112
112
  if(!currentState)
113
113
  {
114
- scope.error("The sensor 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.");
114
+ scope.error(RED._("hue-motion.node.error-not-available"), msg);
115
115
  return false;
116
116
  }
117
117
 
@@ -141,6 +141,27 @@ module.exports = function(RED)
141
141
  patchObject["enabled"] = (msg.payload == true);
142
142
  }
143
143
 
144
+ // TUNE THE SENSITIVITY (CAMERAS AND MOTIONAWARE AREAS)
145
+ if(typeof msg.payload != 'undefined' && typeof msg.payload.sensitivity != 'undefined')
146
+ {
147
+ const maximum = currentState.payload.sensitivityMax;
148
+
149
+ if(typeof maximum == 'undefined')
150
+ {
151
+ scope.error(RED._("hue-motion.node.error-no-sensitivity"), msg);
152
+ return false;
153
+ }
154
+
155
+ const sensitivity = parseInt(msg.payload.sensitivity);
156
+ if(isNaN(sensitivity) || sensitivity < 0 || sensitivity > maximum)
157
+ {
158
+ scope.error(RED._("hue-motion.node.error-invalid-sensitivity", { max: maximum }), msg);
159
+ return false;
160
+ }
161
+
162
+ patchObject["sensitivity"] = { sensitivity: sensitivity };
163
+ }
164
+
144
165
  //
145
166
  // SHOULD PATCH?
146
167
  if(Object.values(patchObject).length > 0)
@@ -153,15 +174,15 @@ module.exports = function(RED)
153
174
 
154
175
  // PATCH!
155
176
  async.retry({
156
- times: 3,
177
+ times: 5,
157
178
  errorFilter: function(err) {
158
- return (err.status == 503);
179
+ return (err.status == 503 || err.status == 429);
159
180
  },
160
- interval: function(retryCount) { return retryCount*2000; }
181
+ interval: function(retryCount) { return 750*retryCount; }
161
182
  },
162
183
  function(callback, results)
163
184
  {
164
- bridge.patch("motion", tempSensorID, patchObject)
185
+ bridge.patch(currentState.info.type, tempSensorID, patchObject)
165
186
  .then(function() { if(done) { callback(null, true); }})
166
187
  .catch(function(errors) { callback(errors, null); });
167
188
  },
@@ -194,6 +215,14 @@ module.exports = function(RED)
194
215
  if(done) { done(); }
195
216
  }
196
217
  });
218
+
219
+ //
220
+ // CLOSE NODE / DETACH FROM THE BRIDGE
221
+ this.on('close', function()
222
+ {
223
+ if(scope.unsubscribe) { scope.unsubscribe(); }
224
+ });
225
+
197
226
  }
198
227
 
199
228
  RED.nodes.registerType("hue-motion", HueMotion);
@@ -4,7 +4,7 @@
4
4
  <input type="text" id="node-input-name" data-i18n="[placeholder]hue-rules.config.input-name" style="width: calc(100% - 105px)">
5
5
  </div>
6
6
  <div class="form-row">
7
- <label for="node-input-bridge"><i class="fa fa-server"></i> Bridge</label>
7
+ <label for="node-input-bridge"><i class="fa fa-server"></i> <span data-i18n="hue-rules.config.bridge"></span></label>
8
8
  <input type="text" id="node-input-bridge" style="width: calc(100% - 105px)">
9
9
  </div>
10
10
  <div class="form-row">
@@ -19,15 +19,21 @@
19
19
  </div>
20
20
  </div>
21
21
  <div class="form-row" style="margin-top: 30px">
22
- <div style="display: inline-flex; width: calc(100% - 105px)">
23
- <input type="checkbox" id="node-input-skipevents" style="flex: 15px;">
24
- <span data-i18n="hue-rules.config.skipevents-node" style="width: 100%; margin-left: 10px;"></span>
22
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
23
+ <input type="checkbox" id="node-input-skipevents" style="flex: 0 0 auto; width: auto; margin: 0;">
24
+ <span data-i18n="hue-rules.config.skipevents-node" style="flex: 1; margin-left: 8px;"></span>
25
25
  </div>
26
26
  </div>
27
27
  <div class="form-row">
28
- <div style="display: inline-flex; width: calc(100% - 105px)">
29
- <input type="checkbox" id="node-input-initevents" style="flex: 15px;">
30
- <span data-i18n="hue-rules.config.sendinitevents-node" style="width: 100%; margin-left: 10px;"></span>
28
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
29
+ <input type="checkbox" id="node-input-initevents" style="flex: 0 0 auto; width: auto; margin: 0;">
30
+ <span data-i18n="hue-rules.config.sendinitevents-node" style="flex: 1; margin-left: 8px;"></span>
31
+ </div>
32
+ </div>
33
+ <div class="form-row">
34
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
35
+ <input type="checkbox" id="node-input-onlycommands" style="flex: 0 0 auto; width: auto; margin: 0;">
36
+ <span data-i18n="hue-rules.config.onlycommands-node" style="flex: 1; margin-left: 8px;"></span>
31
37
  </div>
32
38
  </div>
33
39
  </script>
@@ -41,10 +47,11 @@
41
47
  bridge: { type: "hue-bridge", required: true },
42
48
  ruleid: { value:"", required: false },
43
49
  skipevents: { value: false },
44
- initevents: { value: false }
50
+ initevents: { value: false },
51
+ onlycommands: { value: false }
45
52
  },
46
53
  align: 'left',
47
- icon: "hue-rules.png",
54
+ icon: "hue-rules.svg",
48
55
  inputs: 1,
49
56
  outputs: 1,
50
57
  label: function() {
@@ -37,7 +37,7 @@ module.exports = function(RED)
37
37
 
38
38
  //
39
39
  // SUBSCRIBE TO UPDATES FROM THE BRIDGE
40
- bridge.subscribe("rule", config.ruleid, function(info)
40
+ this.unsubscribe = bridge.subscribe("rule", config.ruleid, function(info)
41
41
  {
42
42
  let currentState = bridge.get("rule", info.id);
43
43
 
@@ -58,7 +58,7 @@ module.exports = function(RED)
58
58
  }
59
59
 
60
60
  // SEND MESSAGE
61
- if(!config.skipevents && (config.initevents || info.suppressMessage == false))
61
+ if(!config.skipevents && (config.initevents || info.suppressMessage == false) && (!config.onlycommands || scope.lastCommand !== null))
62
62
  {
63
63
  // SET LAST COMMAND
64
64
  if(scope.lastCommand !== null)
@@ -94,14 +94,14 @@ module.exports = function(RED)
94
94
  const tempRuleID = (!config.ruleid && typeof msg.topic != 'undefined' && isNaN(msg.topic) == false) ? msg.topic : config.ruleid;
95
95
  if(!tempRuleID)
96
96
  {
97
- scope.error("Please submit a valid rule ID.");
97
+ scope.error(RED._("hue-rules.node.error-no-id"), msg);
98
98
  return false;
99
99
  }
100
100
 
101
101
  let currentState = bridge.get("rule", "rule_" + tempRuleID);
102
102
  if(!currentState)
103
103
  {
104
- scope.error("The rule 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.");
104
+ scope.error(RED._("hue-rules.node.error-not-available"), msg);
105
105
  return false;
106
106
  }
107
107
 
@@ -113,11 +113,11 @@ module.exports = function(RED)
113
113
 
114
114
  // PATCH!
115
115
  async.retry({
116
- times: 3,
116
+ times: 5,
117
117
  errorFilter: function(err) {
118
- return (err.status == 503);
118
+ return (err.status == 503 || err.status == 429);
119
119
  },
120
- interval: function(retryCount) { return retryCount*2000; }
120
+ interval: function(retryCount) { return 750*retryCount; }
121
121
  },
122
122
  function(callback, results)
123
123
  {
@@ -154,7 +154,15 @@ module.exports = function(RED)
154
154
  if(done) {done();}
155
155
  }
156
156
  });
157
+
158
+ //
159
+ // CLOSE NODE / DETACH FROM THE BRIDGE
160
+ this.on('close', function()
161
+ {
162
+ if(scope.unsubscribe) { scope.unsubscribe(); }
163
+ });
164
+
157
165
  }
158
166
 
159
167
  RED.nodes.registerType("hue-rules", HueRules);
160
- }
168
+ }
@@ -4,7 +4,7 @@
4
4
  <input type="text" id="node-input-name" data-i18n="[placeholder]hue-scene.config.input-name" style="width: calc(100% - 105px)">
5
5
  </div>
6
6
  <div class="form-row">
7
- <label for="node-input-bridge"><i class="fa fa-server"></i> Bridge</label>
7
+ <label for="node-input-bridge"><i class="fa fa-server"></i> <span data-i18n="hue-scene.config.bridge"></span></label>
8
8
  <input type="text" id="node-input-bridge" style="width: calc(100% - 105px)">
9
9
  </div>
10
10
  <div class="form-row">
@@ -30,7 +30,7 @@
30
30
  sceneid: { value: null }
31
31
  },
32
32
  align: 'left',
33
- icon: "hue-scene.png",
33
+ icon: "hue-scene.svg",
34
34
  inputs: 1,
35
35
  outputs: 1,
36
36
  label: function() {
@@ -97,7 +97,11 @@
97
97
  $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "scene" })
98
98
  .done( function(data) {
99
99
  var allResources = JSON.parse(data);
100
- allResources = sortResourcesBy('name', allResources);
100
+ allResources = allResources.sort(function(a, b) {
101
+ // GROUP FIRST, SO THE SCENES OF A ROOM STAY TOGETHER
102
+ const byGroup = (a.group || "").localeCompare(b.group || "");
103
+ return (byGroup !== 0) ? byGroup : (a.name || "").localeCompare(b.name || "");
104
+ });
101
105
  if(allResources.length <= 0)
102
106
  {
103
107
  notification.close();
@@ -108,7 +112,7 @@
108
112
  // SET OPTIONS
109
113
  allResources.forEach(function(resource)
110
114
  {
111
- sceneOptions[resource.id] = { value: resource.id, label: resource.name + " ("+resource.group+")" };
115
+ sceneOptions[resource.id] = { value: resource.id, label: resource.group + " – " + resource.name };
112
116
  });
113
117
 
114
118
  // SELECT CURRENT VALUE
@@ -145,7 +149,7 @@
145
149
 
146
150
  if(currentSelectedOptionValue !== false)
147
151
  {
148
- $('#node-input-name').val(currentSelectedOptionValue.split(" (")[0]);
152
+ $('#node-input-name').val(currentSelectedOptionValue.split(" – ").pop());
149
153
  }
150
154
  });
151
155
 
@@ -12,9 +12,11 @@ module.exports = function(RED)
12
12
 
13
13
  // GET TARGET WIRED GROUPS
14
14
  this.targetGroups = {};
15
- for (var w = scope.wires[0].length - 1; w >= 0; w--)
15
+ const wiredNodes = (scope.wires && scope.wires[0]) ? scope.wires[0] : [];
16
+
17
+ for (var w = wiredNodes.length - 1; w >= 0; w--)
16
18
  {
17
- let oneWiredNode = RED.nodes.getNode(scope.wires[0][w]);
19
+ let oneWiredNode = RED.nodes.getNode(wiredNodes[w]);
18
20
  if(oneWiredNode && oneWiredNode.type == "hue-group" && oneWiredNode.exportedConfig && oneWiredNode.exportedConfig.groupid && oneWiredNode.exportedConfig.groupid.length > 1)
19
21
  {
20
22
  this.targetGroups[oneWiredNode.exportedConfig.groupid] = true;
@@ -43,8 +45,7 @@ module.exports = function(RED)
43
45
  // PREPARE TARGET GROUPS
44
46
  let copyOfTargetGroups = Object.keys(scope.targetGroups);
45
47
  if(typeof groupIDS == 'string') { copyOfTargetGroups.push(groupIDS); }
46
- else if(typeof groupIDS == 'object') { copyOfTargetGroups.concat(groupIDS); }
47
- else { return false; }
48
+ else if(Array.isArray(groupIDS)) { copyOfTargetGroups = copyOfTargetGroups.concat(groupIDS); }
48
49
 
49
50
  // CREATE PATCH
50
51
  let patchObject = {};
@@ -54,14 +55,23 @@ module.exports = function(RED)
54
55
  {
55
56
  // ERROR
56
57
  this.status({fill: "red", shape: "ring", text: "hue-scene.node.no-id"});
57
- scope.error("Scene ID not found");
58
+ scope.error(RED._("hue-scene.node.no-id"), msg);
59
+ return false;
60
+ }
61
+
62
+ // SCENE NOT (YET) KNOWN?
63
+ const targetScene = bridge.resources ? bridge.resources[sceneDef] : false;
64
+ if(!targetScene)
65
+ {
66
+ this.status({fill: "red", shape: "ring", text: "hue-scene.node.no-id"});
67
+ scope.error(RED._("hue-scene.node.error-not-available"), msg);
58
68
  return false;
59
69
  }
60
70
 
61
71
  // RECALL ON GROUP? -> USE API v1
62
- if(copyOfTargetGroups.length > 0)
72
+ if(copyOfTargetGroups.length > 0 && targetScene.id_v1)
63
73
  {
64
- let targetSceneID = bridge.resources[sceneDef].id_v1.replace("/scenes/", "");
74
+ let targetSceneID = targetScene.id_v1.replace("/scenes/", "");
65
75
 
66
76
  // SEND STATUS
67
77
  scope.status({fill: "blue", shape: "dot", text: "hue-scene.node.recalled-on-group"})
@@ -75,11 +85,11 @@ module.exports = function(RED)
75
85
  {
76
86
  // PATCH!
77
87
  async.retry({
78
- times: 3,
88
+ times: 5,
79
89
  errorFilter: function(err) {
80
- return (err.status == 503);
90
+ return (err.status == 503 || err.status == 429);
81
91
  },
82
- interval: function(retryCount) { return retryCount*2000; }
92
+ interval: function(retryCount) { return 750*retryCount; }
83
93
  },
84
94
  function(callback, results)
85
95
  {
@@ -110,23 +120,49 @@ module.exports = function(RED)
110
120
  }
111
121
  else
112
122
  {
113
- // RECALL SCENE
114
- patchObject["recall"] = { action: "active" };
123
+ // RECALL SCENE (SMART SCENES USE THEIR OWN RESOURCE AND ACTION)
124
+ const sceneType = (targetScene.type === "smart_scene") ? "smart_scene" : "scene";
125
+ patchObject["recall"] = { action: (sceneType === "smart_scene") ? "activate" : "active" };
126
+
127
+ // A NORMAL SCENE CAN ALSO FADE IN AND BE DIMMED WHILE IT IS RECALLED
128
+ if(sceneType === "scene")
129
+ {
130
+ if(typeof msg.payload != 'undefined' && typeof msg.payload.transitionTime != 'undefined')
131
+ {
132
+ let duration = Math.round(parseFloat(msg.payload.transitionTime) * 1000);
133
+ duration = (duration > 6000000) ? 6000000 : ((duration < 0) ? 0 : duration);
134
+
135
+ patchObject["recall"]["duration"] = duration;
136
+ }
137
+
138
+ if(typeof msg.payload != 'undefined' && typeof msg.payload.brightness != 'undefined')
139
+ {
140
+ const brightness = parseFloat(msg.payload.brightness);
141
+
142
+ if(isNaN(brightness) || brightness < 0 || brightness > 100)
143
+ {
144
+ scope.error(RED._("hue-scene.node.error-invalid-brightness"), msg);
145
+ return false;
146
+ }
147
+
148
+ patchObject["recall"]["dimming"] = { brightness: brightness };
149
+ }
150
+ }
115
151
 
116
152
  // CHANGE NODE UI STATE
117
153
  scope.status({fill: "grey", shape: "ring", text: "hue-scene.node.command"});
118
154
 
119
155
  // PATCH!
120
156
  async.retry({
121
- times: 3,
157
+ times: 5,
122
158
  errorFilter: function(err) {
123
- return (err.status == 503);
159
+ return (err.status == 503 || err.status == 429);
124
160
  },
125
- interval: function(retryCount) { return retryCount*2000; }
161
+ interval: function(retryCount) { return 750*retryCount; }
126
162
  },
127
163
  function(callback, results)
128
164
  {
129
- bridge.patch("scene", sceneDef, patchObject)
165
+ bridge.patch(sceneType, sceneDef, patchObject)
130
166
  .then(function()
131
167
  {
132
168
  scope.status({fill: "blue", shape: "dot", text: "hue-scene.node.recalled"});
@@ -0,0 +1,218 @@
1
+ <script type="text/x-red" data-template-name="hue-speaker">
2
+ <div class="form-row">
3
+ <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="hue-speaker.config.name"></span></label>
4
+ <input type="text" id="node-input-name" data-i18n="[placeholder]hue-speaker.config.input-name" style="width: calc(100% - 105px)">
5
+ </div>
6
+ <div class="form-row">
7
+ <label for="node-input-bridge"><i class="fa fa-server"></i> <span data-i18n="hue-speaker.config.bridge"></span></label>
8
+ <input type="text" id="node-input-bridge" style="width: calc(100% - 105px)">
9
+ </div>
10
+ <div class="form-row">
11
+ <label for="node-input-speakerid"><i class="fa fa-volume-up"></i> <span data-i18n="hue-speaker.config.speaker"></span></label>
12
+ <div style="display: inline-flex; width: calc(100% - 105px)">
13
+ <div id="input-select-toggle" style="flex-grow: 1;">
14
+ <input type="text" id="node-input-speakerid" placeholder="00000000-0000-0000-0000-000000000000" style="width: 100%"/>
15
+ </div>
16
+ <button id="node-config-input-scan-speaker" type="button" class="red-ui-button" style="margin-left: 10px;">
17
+ <i class="fa fa-search"></i>
18
+ </button>
19
+ </div>
20
+ </div>
21
+ <div class="form-row" style="margin-top: 30px">
22
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
23
+ <input type="checkbox" id="node-input-skipevents" style="flex: 0 0 auto; width: auto; margin: 0;">
24
+ <span data-i18n="hue-speaker.config.skipevents-node" style="flex: 1; margin-left: 8px;"></span>
25
+ </div>
26
+ </div>
27
+ <div class="form-row">
28
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
29
+ <input type="checkbox" id="node-input-initevents" style="flex: 0 0 auto; width: auto; margin: 0;">
30
+ <span data-i18n="hue-speaker.config.sendinitevents-node" style="flex: 1; margin-left: 8px;"></span>
31
+ </div>
32
+ </div>
33
+ <div class="form-row">
34
+ <div style="display: inline-flex; align-items: center; width: calc(100% - 105px)">
35
+ <input type="checkbox" id="node-input-onlycommands" style="flex: 0 0 auto; width: auto; margin: 0;">
36
+ <span data-i18n="hue-speaker.config.onlycommands-node" style="flex: 1; margin-left: 8px;"></span>
37
+ </div>
38
+ </div>
39
+ </script>
40
+
41
+ <script type="text/javascript">
42
+ RED.nodes.registerType('hue-speaker',{
43
+ category: 'HueMagic',
44
+ color: '#8182df',
45
+ defaults: {
46
+ name: { value:"" },
47
+ bridge: { type: "hue-bridge", required: true },
48
+ speakerid: { value:"", required: false },
49
+ skipevents: { value: false },
50
+ initevents: { value: false },
51
+ onlycommands: { value: false }
52
+ },
53
+ align: 'left',
54
+ icon: "hue-speaker.svg",
55
+ inputs: 1,
56
+ outputs: 1,
57
+ label: function() {
58
+ return this.name || this._("hue-speaker.node.title");
59
+ },
60
+ paletteLabel: function() {
61
+ return this._("hue-speaker.node.title");
62
+ },
63
+ inputLabels: function() {
64
+ return this._("hue-speaker.node.input");
65
+ },
66
+ outputLabels: function() {
67
+ return this._("hue-speaker.node.output");
68
+ },
69
+ oneditprepare: function()
70
+ {
71
+ const scope = this;
72
+ let options = [];
73
+
74
+ function manualInput()
75
+ {
76
+ // GET CURRENT SELECTED VALUE
77
+ var current = $('#node-input-speakerid').val();
78
+
79
+ // REMOVE SELECT FIELD
80
+ $('#input-select-toggle').empty();
81
+
82
+ // CREATE NEW INPUT FIELD
83
+ $('#input-select-toggle').append('<input type="text" id="node-input-speakerid" placeholder="00000000-0000-0000-0000-000000000000" style="width: 100%" value="'+current+'" />');
84
+
85
+ // CHANGE BUTTON ICON
86
+ var button = $("#node-config-input-scan-speaker");
87
+ var buttonIcon = button.find("i");
88
+ buttonIcon.removeClass("fa-pencil");
89
+ buttonIcon.addClass("fa-search");
90
+ }
91
+
92
+ function sortResourcesBy(prop, resources)
93
+ {
94
+ return resources.sort((a, b) => {
95
+ if ( a[prop] < b[prop] ){
96
+ return -1;
97
+ }
98
+ if ( a[prop] > b[prop] ){
99
+ return 1;
100
+ }
101
+ return 0;
102
+ });
103
+ }
104
+
105
+ function searchAndSelect()
106
+ {
107
+ // GET CURRENT BRIDGE CONFIGURATION
108
+ var bridgeConfig = RED.nodes.node($('#node-input-bridge option:selected').val());
109
+ if(!bridgeConfig) { return false; }
110
+
111
+ // GET CURRENT SELECTED VALUE
112
+ var current = $('#node-input-speakerid').val();
113
+
114
+ // TRIGGER SEARCHING NOTIFICATION
115
+ var notification = RED.notify(scope._("hue-speaker.config.searching"), { type: "compact", modal: true, fixed: true });
116
+
117
+ // GET THE SENSORS
118
+ $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "speaker" })
119
+ .done( function(data) {
120
+ var allResources = JSON.parse(data);
121
+ allResources = sortResourcesBy('name', allResources);
122
+ if(allResources.length <= 0)
123
+ {
124
+ notification.close();
125
+ RED.notify(scope._("hue-speaker.config.none-found"), { type: "error" });
126
+ return false;
127
+ }
128
+
129
+ // SET OPTIONS
130
+ allResources.forEach(function(resource)
131
+ {
132
+ if(resource.model)
133
+ {
134
+ options[resource.id] = { value: resource.id, label: resource.name + " ("+resource.model+")" };
135
+ }
136
+ else
137
+ {
138
+ options[resource.id] = { value: resource.id, label: resource.name };
139
+ }
140
+ });
141
+
142
+ // SELECT CURRENT VALUE
143
+ $("#node-input-speakerid").typedInput({
144
+ types: [
145
+ {
146
+ value: current,
147
+ options: Object.values(options)
148
+ }
149
+ ]
150
+ });
151
+
152
+ // CHANGE BUTTON ICON
153
+ var button = $("#node-config-input-scan-speaker");
154
+ var buttonIcon = button.find("i");
155
+ buttonIcon.removeClass("fa-search");
156
+ buttonIcon.addClass("fa-pencil");
157
+
158
+ // CLOSE SEARCH NOTIFICATION
159
+ notification.close();
160
+ })
161
+ .fail(function()
162
+ {
163
+ notification.close();
164
+ RED.notify(scope._("hue-speaker.config.unknown-error"), "error");
165
+ });
166
+ }
167
+
168
+ // CHANGED SENSOR ID? -> REPLACE NAME (IF POSSIBLE)
169
+ $(document).on('change', '#node-input-speakerid', function(e)
170
+ {
171
+ let currentSelectedOptionID = $(e.currentTarget).val();
172
+ let currentSelectedOptionValue = (currentSelectedOptionID.length > 0 && options[currentSelectedOptionID]) ? options[currentSelectedOptionID].label : false;
173
+
174
+ if(currentSelectedOptionValue !== false)
175
+ {
176
+ $('#node-input-name').val(currentSelectedOptionValue.split(" (")[0]);
177
+ }
178
+ });
179
+
180
+ // TOGGLE SELECT/INPUT FIELD
181
+ $('#node-config-input-scan-speaker').click(function()
182
+ {
183
+ if($('#input-select-toggle').find(".red-ui-typedInput-container").length > 0)
184
+ {
185
+ manualInput();
186
+ }
187
+ else
188
+ {
189
+ searchAndSelect();
190
+ }
191
+ });
192
+ },
193
+ button: {
194
+ enabled: function() {
195
+ return (this.speakerid && this.speakerid.length > 1)
196
+ },
197
+ visible: function() {
198
+ return (this.speakerid && this.speakerid.length > 1)
199
+ },
200
+ onclick: function()
201
+ {
202
+ const node = this;
203
+ if(node.bridge)
204
+ {
205
+ $.ajax({
206
+ url: "inject/" + node.id,
207
+ type: "POST",
208
+ data: JSON.stringify({ __user_inject_props__: "status"}),
209
+ contentType: "application/json; charset=utf-8",
210
+ success: function (resp) {
211
+ RED.notify(node.name + ": " + node._("hue-speaker.node.statusmsg"), { type: "success", id: "status", timeout: 2000 });
212
+ }
213
+ });
214
+ }
215
+ }
216
+ }
217
+ });
218
+ </script>