node-red-contrib-huemagic 4.2.2 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (515) hide show
  1. package/CHANGELOG.md +94 -5
  2. package/README.md +525 -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 +227 -11
  153. package/huemagic/hue-buttons.js +183 -28
  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 +7 -4
  191. package/huemagic/locales/de/hue-buttons.json +42 -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 +61 -0
  223. package/huemagic/locales/el/hue-buttons.json +62 -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 +6 -3
  254. package/huemagic/locales/en/hue-buttons.json +62 -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 +61 -0
  285. package/huemagic/locales/es/hue-buttons.json +62 -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 +61 -0
  317. package/huemagic/locales/fr/hue-buttons.json +62 -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 +61 -0
  349. package/huemagic/locales/it/hue-buttons.json +62 -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 +61 -0
  381. package/huemagic/locales/nl/hue-buttons.json +62 -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 +61 -0
  413. package/huemagic/locales/pl/hue-buttons.json +62 -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 +61 -0
  445. package/huemagic/locales/pt/hue-buttons.json +62 -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 +61 -0
  477. package/huemagic/locales/tr/hue-buttons.json +62 -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
@@ -0,0 +1,69 @@
1
+ <script type="text/markdown" data-help-name="hue-temperature">
2
+ «Hue Sıcaklık» düğümü, bridge'e bağlı uygun bir sensörden güncel ortam sıcaklığını sorgulayabilir ve bildirebilir.
3
+
4
+ ### Kurulum
5
+
6
+ Önceden yapılandırılmış Hue Bridge'i seçin ve mevcut tüm sensörleri bulmak için arama düğmesine tıklayın. Sensörün kimliğini zaten biliyorsanız, buraya elle de girebilirsiniz. Sensöre dahili olarak yeni bir ad verebilir veya önceden tanımlı adı kullanabilirsiniz. İsteğe bağlı olarak «Düğümün mesajlarını yoksay» ayarıyla bu düğümün tüm otomatik durum mesajlarını devre dışı bırakabilirsiniz. Düğüm bundan sonra cihaz güncellemesi yayınlamaz. Alternatif olarak, Node-RED başlatılırken düğümün başlatma mesajının bastırılmamasını seçebilirsiniz. Bu ayarı etkinleştirirseniz her dağıtımdan sonra seçili sensörün durum mesajını alırsınız. Düğümün siz bir şey gönderene kadar sessiz kalmasını tercih ediyorsanız «Yalnızca bir komuttan sonra bildir» seçeneğini etkinleştirin. Bu durumda uygulamadan veya bir anahtardan gelen değişiklikleri yok sayar ve yalnızca sizin komutlarınıza yanıt verir.
7
+
8
+ Hareket sensörleri genellikle odanın bir köşesine monte edilir ve kendi elektroniği yüzünden çoğu zaman biraz fazla sıcak ölçer. «Düzeltme» ayarıyla sensörü dolambaçsız biçimde kalibre edebilirsiniz: buraya girdiğiniz değer (ör. `-1.5`), düğüm değeri vermeden önce her ölçüme eklenir. Düzeltme tüm sıcaklık birimleri için aynı anda geçerlidir.
9
+
10
+ Bir sensör seçmez ve düğüm yapılandırmasını bu şekilde kullanırsanız, düğüm «evrensel mod» adı verilen modda çalışır. Bu modda düğüm aynı türdeki tüm durum mesajlarını alır ve yayınlar. Evrensel modda ayarları belirli bir sensöre uygulamak için ilgili sensör kimliğini `msg.topic` içinde dize olarak ayarlarınızla birlikte gönderebilirsiniz.
11
+
12
+ ### Durumu sorgulama
13
+
14
+ Düğüme aşağıdaki içeriğe sahip bir `msg.payload` nesnesi iletildiğinde sensörün güncel durumunu verir. Alternatif olarak, önce düğüme bir mesaj göndermeden Node-RED arayüzündeki düğmeye de basabilirsiniz.
15
+
16
+ : status (boolean): Sensörün güncel durumunu döndürür
17
+
18
+ ### Sensörü açma / kapatma
19
+
20
+ Gerekirse sensör uzaktan açılıp kapatılabilir. Sensör kapatıldığında artık sıcaklık değişikliği kaydetmez ve dolayısıyla bildirmez. Bunun için aşağıdaki içeriğe sahip bir nesne gönderin:
21
+
22
+ : payload (boolean): `true` sensörü açar, `false` kapatır
23
+
24
+ ### Düğümün durum mesajları
25
+
26
+ Sensör bir sıcaklık değişikliği kaydettiği anda düğüm aşağıdaki durum mesajını döndürür:
27
+
28
+ #### `msg.payload` altındaki durum nesnesi
29
+
30
+ : active (boolean): Sensörün açık mı kapalı mı olduğunu belirtir
31
+ : reachable (boolean | string): Sensör bridge'e bağlıysa `true`, bağlantı durumu farklıysa `unknown`
32
+ : connectionStatus (string): Bridge ile olan güncel bağlantı durumu (dize olarak). Değer olarak `connected`, `disconnected`, `connectivity_issue` veya `unidirectional_incoming` içerebilir
33
+ : celsius (float): Güncel ortam sıcaklığını °C (santigrat derece) olarak belirtir
34
+ : fahrenheit (float): Güncel ortam sıcaklığını °F (fahrenhayt derece) olarak belirtir
35
+ : temperatureIs (string): Güncel sıcaklığı `very cold`, `cold`, `slightly cold`, `comfortable`, `slightly warm`, `warm`, `hot` veya `very hot` değerleriyle tanımlar
36
+ : deviceValue (float): Sensörden gelen özgün sıcaklık değeri
37
+ : updated (string): Kaynağın HueMagic tarafından son güncellenme zamanı (ISO 8601)
38
+
39
+ #### `msg.info` altındaki sensör bilgileri
40
+
41
+ : id (string): Sensörün yeni kimliğini belirtir
42
+ : idV1 (string | boolean): Sensörün eski kimliğini belirtir
43
+ : uniqueId (string): Sensörün benzersiz kimliği
44
+ : deviceId (string): Cihazın benzersiz kimliği
45
+ : name (string): Sensörün geçerli adı
46
+ : type (string): Sensörün türü (her zaman `temperature`)
47
+ : softwareVersion (string): Sensörün geçerli ürün yazılımı
48
+ : battery (float): Sensörün geçerli pil düzeyi
49
+ : batteryState (string): Pil düzeyinin geçerli durumu. Değer olarak `normal`, `low` veya `critical` içerebilir
50
+ : model (object): Sensörün model bilgilerini `id`, `manufacturer`, `name`, `type` ve `certified` altında içerir
51
+
52
+ #### `msg.updated` altındaki durum değişiklikleri
53
+
54
+ Sensörün önceki durumuna kıyasla değişen parametreleri bir nesne olarak listeler. Herhangi bir değişiklik kaydedilmediyse bu nesne boştur.
55
+
56
+ #### `msg.lastState` altındaki son sensör durumu
57
+
58
+ Son kaydedilen değişiklikten önceki durumun eksiksiz durum nesnesini içerir (yukarıdaki çıktı değerlerine bakın). HueMagic önceki durumu henüz kaydetmediyse `false` verilir.
59
+
60
+ #### `msg.command` altındaki son komut (isteğe bağlı)
61
+
62
+ Düğümün durumu belirli bir komutla değiştiyse, yürütülen komutun tamamı da çıktı olarak verilir. Aksi hâlde düğüm bu nesneyi çıktı olarak vermez.
63
+
64
+ ### HueMagic örnekleri
65
+
66
+ HueMagic bu düğüm için bazı örnek yapılandırmalar sunar. Node-RED arayüzünüze eksiksiz bir örnek aktarmak için Node-RED menü simgesine tıklayın, «Import» seçeneğini seçin ve açılan pencerenin kenar çubuğunda «Examples» bölümüne gidin. Ardından HueMagic klasörünü ve istediğiniz düğümü seçerek örnek bir akış aktarın.
67
+
68
+ ![examples](hue/assets/huemagic-examples.gif)
69
+ </script>
@@ -0,0 +1,33 @@
1
+ {
2
+ "hue-temperature": {
3
+ "config": {
4
+ "name": "Ad",
5
+ "skipevents-node": "Düğümün mesajlarını yoksay",
6
+ "sendinitevents-node": "Başlatma olayını bastırma",
7
+ "onlycommands-node": "Yalnızca bir komuttan sonra bildir",
8
+ "unknown-error": "Bir şeyler ters gitti. Lütfen tekrar deneyin.",
9
+ "bridge": "Bridge",
10
+ "universalevents": "Evrensel olaylar",
11
+ "universalevents-node": "Aynı türdeki diğer düğümlerin tüm mesajlarını alır (yalnızca evrensel modda)",
12
+ "input-name": "Sensör adı",
13
+ "searching": "sıcaklık sensörleri aranıyor…",
14
+ "none-found": "Hiç sıcaklık sensörü bulunamadı.",
15
+ "sensor": "Sensör",
16
+ "offset": "Düzeltme"
17
+ },
18
+ "node": {
19
+ "not-configured": "yapılandırılmadı",
20
+ "init": "başlatılıyor…",
21
+ "not-reachable": "erişilemiyor",
22
+ "universal": "evrensel mod",
23
+ "command": "komut yürütülüyor…",
24
+ "deactivated": "devre dışı",
25
+ "statusmsg": "Durum başarıyla sorgulandı…",
26
+ "title": "Hue Sıcaklık",
27
+ "input": "durum sorgusu",
28
+ "output": "sıcaklık (değişti)",
29
+ "error-no-id": "Lütfen geçerli bir sensör kimliği girin.",
30
+ "error-not-available": "Sensör henüz kullanılabilir değil. HueMagic bridge ile bağlantı kurana kadar bekleyin veya yapılandırmadaki kaynak kimliğinin geçerli olup olmadığını kontrol edin."
31
+ }
32
+ }
33
+ }
@@ -1,7 +1,10 @@
1
1
  const axios = require('axios');
2
2
  const dayjs = require('dayjs');
3
3
  const https = require('https');
4
- const EventSource = require('eventsource');
4
+ const { parseEventStream } = require('./sse');
5
+
6
+ // Node is somehow not able to parse the official Philips Hue PEM
7
+ const httpsAgent = new https.Agent({ rejectUnauthorized: false, keepAlive: true });
5
8
 
6
9
  function API()
7
10
  {
@@ -28,7 +31,9 @@ function API()
28
31
  "method": "GET",
29
32
  "url": "https://" + config.bridge + "/api/config",
30
33
  "headers": { "Content-Type": "application/json; charset=utf-8" },
31
- "httpsAgent": new https.Agent({ rejectUnauthorized: false }),
34
+ "httpsAgent": httpsAgent,
35
+ "proxy": false, // THE BRIDGE IS ON THE LOCAL NETWORK, NEVER GO THROUGH A PROXY
36
+ "timeout": 10000,
32
37
  })
33
38
  .then(function(response)
34
39
  {
@@ -62,7 +67,9 @@ function API()
62
67
  "Content-Type": "application/json; charset=utf-8",
63
68
  "hue-application-key": config.key
64
69
  },
65
- "httpsAgent": new https.Agent({ rejectUnauthorized: false }), // Node is somehow not able to parse the official Philips Hue PEM
70
+ "httpsAgent": httpsAgent,
71
+ "proxy": false, // THE BRIDGE IS ON THE LOCAL NETWORK, NEVER GO THROUGH A PROXY
72
+ "timeout": 15000,
66
73
  };
67
74
 
68
75
  // HAS RESOURCE? -> APPEND
@@ -90,6 +97,7 @@ function API()
90
97
  {
91
98
  if(version === 2)
92
99
  {
100
+ // THE BRIDGE ALSO PUTS NON-FATAL HINTS INTO "errors", SO ONLY THE STATUS COUNTS
93
101
  resolve(response.data.data);
94
102
  }
95
103
  else if(version === 1)
@@ -99,64 +107,143 @@ function API()
99
107
  })
100
108
  .catch(function(error)
101
109
  {
102
- reject({ status: error.response.status, errors: error.response.data.errors ? error.response.data.errors : error.response.data});
110
+ if (error.response)
111
+ {
112
+ let errors = error.response.data;
113
+
114
+ // AN OVERLOADED BRIDGE ANSWERS WITH A HTML ERROR PAGE
115
+ if(typeof errors === 'string') { errors = "The bridge is currently not able to answer (HTTP " + error.response.status + ")."; }
116
+ else if(errors && errors.errors) { errors = errors.errors; }
117
+
118
+ reject({ status: error.response.status, errors: errors });
119
+ }
120
+ else
121
+ {
122
+ reject({ status: error.code, errors: error.message});
123
+ }
103
124
  });
104
125
  });
105
126
  }
106
127
 
107
128
  //
108
129
  // SUBSCRIBE TO BRIDGE EVENTS
109
- this.subscribe = function(config, callback)
130
+ this.subscribe = function(config, callback, log = null)
110
131
  {
111
132
  const scope = this;
112
133
  return new Promise(function(resolve, reject)
113
134
  {
114
- if(!scope.events[config.id])
135
+ // ONLY ONE STREAM PER BRIDGE
136
+ scope.unsubscribe(config);
137
+
138
+ const stream = { active: true, request: null, retry: null, attempt: 0, lastEventId: null, connected: false };
139
+ scope.events[config.id] = stream;
140
+
141
+ // (RE)CONNECT TO THE EVENT STREAM
142
+ const connect = function()
115
143
  {
116
- var sseURL = "https://" + config.bridge + "/eventstream/clip/v2";
144
+ if(stream.active === false) { return false; }
145
+
146
+ const [host, port] = config.bridge.trim().split(":");
147
+ const headers = {
148
+ "Accept": "text/event-stream",
149
+ "Cache-Control": "no-cache",
150
+ "hue-application-key": config.key
151
+ };
117
152
 
118
- // INITIALIZE EVENT SOURCE
119
- scope.events[config.id] = new EventSource(sseURL, {
120
- headers: { 'hue-application-key': config.key },
121
- https: { rejectUnauthorized: false },
153
+ // CONTINUE WHERE WE LEFT OFF
154
+ if(stream.lastEventId) { headers["Last-Event-ID"] = stream.lastEventId; }
155
+
156
+ stream.request = https.request({
157
+ host: host,
158
+ port: port ? parseInt(port) : 443,
159
+ path: "/eventstream/clip/v2",
160
+ method: "GET",
161
+ headers: headers,
162
+ agent: false,
163
+ rejectUnauthorized: false
122
164
  });
123
165
 
124
- // PIPE MESSAGE TO TARGET FUNCTION
125
- scope.events[config.id].onmessage = function(event)
166
+ // ONLY GUARD THE HANDSHAKE, AN IDLE EVENT STREAM IS PERFECTLY NORMAL
167
+ stream.request.setTimeout(15000, function() { stream.request.destroy(new Error("the bridge did not answer")); });
168
+
169
+ stream.request.on('response', function(response)
126
170
  {
127
- if(event && event.type === 'message' && event.data)
171
+ if(response.statusCode !== 200)
128
172
  {
129
- const messages = JSON.parse(event.data);
130
- for (var i = messages.length - 1; i >= 0; i--)
173
+ response.resume();
174
+ reconnect("The bridge rejected the event stream (HTTP " + response.statusCode + ")");
175
+ return false;
176
+ }
177
+
178
+ // CONNECTED -> LET THE OS DETECT DEAD PEERS
179
+ const isReconnect = (stream.attempt > 0);
180
+
181
+ stream.request.setTimeout(0);
182
+ stream.attempt = 0;
183
+ stream.connected = true;
184
+ response.setEncoding('utf8');
185
+ if(response.socket) { response.socket.setKeepAlive(true, 30000); }
186
+
187
+ // EVENTS MAY HAVE BEEN MISSED WHILE WE WERE AWAY
188
+ if(isReconnect) { callback([], "reconnect"); }
189
+
190
+ let buffer = "";
191
+
192
+ response.on('data', function(chunk)
193
+ {
194
+ const parsed = parseEventStream(buffer + chunk);
195
+ buffer = (parsed.rest.length > 1048576) ? "" : parsed.rest;
196
+
197
+ for(let event of parsed.events)
131
198
  {
132
- const message = messages[i];
133
- if(message.type === "update")
199
+ if(event.id) { stream.lastEventId = event.id; }
200
+ if(!event.data) { continue; }
201
+
202
+ let messages = [];
203
+ try { messages = JSON.parse(event.data); }
204
+ catch(error) { continue; }
205
+
206
+ for(let message of messages)
134
207
  {
135
- callback(message.data);
208
+ if(message.data) { callback(message.data, message.type); }
136
209
  }
137
210
  }
138
- }
139
- };
211
+ });
140
212
 
141
- // CONNECTED?
142
- scope.events[config.id].onopen = function()
143
- {
144
- resolve(true);
145
- }
213
+ response.on('end', function() { reconnect("The bridge closed the event stream"); });
214
+ response.on('error', function(error) { reconnect(error.message); });
146
215
 
147
- // ERROR? -> RETRY?
148
- scope.events[config.id].onerror = function(error)
149
- {
150
- console.log("HueMagic:", "Connection to bridge lost. Trying to reconnect again in 30 seconds…", error);
151
- setTimeout(function(){ scope.subscribe(config, callback); }, 30000);
152
216
  resolve(true);
153
- }
217
+ });
218
+
219
+ stream.request.on('error', function(error) { reconnect(error.message); });
220
+ stream.request.end();
154
221
  }
155
- else
222
+
223
+ // RECONNECT WITH A BACKOFF, BUT NEVER MORE THAN ONCE AT A TIME
224
+ const reconnect = function(reason)
156
225
  {
157
- scope.unsubscribe(config);
158
- scope.subscribe(config, callback);
226
+ if(stream.active === false || stream.retry !== null) { return false; }
227
+
228
+ stream.connected = false;
229
+ if(stream.request) { stream.request.destroy(); stream.request = null; }
230
+
231
+ const delay = Math.min(30000, 1000 * Math.pow(2, stream.attempt));
232
+ const seconds = Math.round(delay/1000);
233
+ stream.attempt += 1;
234
+
235
+ if(log) { log(reason, seconds); }
236
+ else { console.log("HueMagic:", "Connection to bridge lost (" + reason + "). Trying to reconnect in " + seconds + " seconds…"); }
237
+ stream.retry = setTimeout(function()
238
+ {
239
+ stream.retry = null;
240
+ connect();
241
+ }, delay);
242
+
243
+ resolve(true);
159
244
  }
245
+
246
+ connect();
160
247
  });
161
248
  }
162
249
 
@@ -164,22 +251,40 @@ function API()
164
251
  // UNSUBSCRIBE
165
252
  this.unsubscribe = function(config)
166
253
  {
167
- if(this.events[config.id] !== null) { this.events[config.id].close(); }
168
- this.events[config.id] = null;
254
+ const stream = this.events[config.id];
255
+ if(!stream) { return false; }
256
+
257
+ stream.active = false;
258
+ if(stream.retry !== null) { clearTimeout(stream.retry); }
259
+ if(stream.request) { stream.request.destroy(); }
260
+
261
+ delete this.events[config.id];
262
+ }
263
+
264
+ //
265
+ // IS THE EVENT STREAM ALIVE?
266
+ this.connected = function(config)
267
+ {
268
+ const stream = this.events[config.id];
269
+ return !!stream && stream.connected === true;
169
270
  }
170
271
 
171
272
  //
172
273
  // GET FULL/ROOT RESOURCE
173
- this.fullResource = function(resource, allResources = {})
274
+ this.fullResource = function(resource, allResources = {}, seen = {})
174
275
  {
175
276
  const scope = this;
176
277
  var fullResource = Object.assign({}, resource);
177
278
 
178
- if(resource["owner"])
279
+ // PROTECT AGAINST BROKEN OWNER CHAINS
280
+ if(seen[resource["id"]]) { return fullResource; }
281
+ seen[resource["id"]] = true;
282
+
283
+ if(resource["owner"] && typeof allResources[fullResource["owner"]["rid"]] !== 'undefined')
179
284
  {
180
- fullResource = scope.fullResource(allResources[fullResource["owner"]["rid"]], allResources);
285
+ fullResource = scope.fullResource(allResources[fullResource["owner"]["rid"]], allResources, seen);
181
286
  }
182
- else if(resource["type"] === "device" || resource["type"] === "room" || resource["type"] === "zone" || resource["type"] === "bridge_home")
287
+ else if(Array.isArray(resource["services"]))
183
288
  {
184
289
  // RESOLVE SERVICES
185
290
  var allServices = {};
@@ -190,6 +295,7 @@ function API()
190
295
  const targetType = targetService["rtype"];
191
296
  const targetID = targetService["rid"];
192
297
 
298
+ if(!allResources[targetID]) { continue; }
193
299
  if(!allServices[targetType]) { allServices[targetType] = {}; }
194
300
  allServices[targetType][targetID] = Object.assign({}, allResources[targetID]);
195
301
  }
@@ -221,11 +327,9 @@ function API()
221
327
  // CREATE ID BASED OBJECT OF ALL RESOURCES
222
328
  resources.forEach(function(resource, index)
223
329
  {
224
- // IS BUTTON? -> REMOVE PREVIOUS STATE
225
- if(resource.type === "button")
226
- {
227
- delete resource["button"];
228
- }
330
+ // IS BUTTON OR DIAL? -> REMOVE PREVIOUS STATE
331
+ if(resource.type === "button") { delete resource["button"]; }
332
+ else if(resource.type === "relative_rotary") { delete resource["relative_rotary"]; }
229
333
 
230
334
  resourceList[resource.id] = resource;
231
335
  });
@@ -236,6 +340,9 @@ function API()
236
340
  // GET FULL RESOURCE
237
341
  let fullResource = scope.fullResource(resource, resourceList);
238
342
 
343
+ // A RESOURCE AND EACH OF ITS SERVICES RESOLVE TO THE SAME ROOT
344
+ if(processedResources[fullResource.id]) { return; }
345
+
239
346
  // ADD CURRENT DATE/TIME
240
347
  fullResource["updated"] = currentDateTime;
241
348
 
@@ -249,15 +356,12 @@ function API()
249
356
 
250
357
  // SET ADDITIONAL TYPES BEHIND RECCOURCE
251
358
  fullResource["types"] = fullResource["types"].concat(additionalServiceTypes);
252
- }
253
359
 
254
- // RESOURCE HAS GROUPED SERVICES?
255
- if (fullResource["services"])
256
- {
257
- for (serviceType in fullResource["services"])
360
+ // RESOURCE HAS GROUPED SERVICES?
361
+ for (const serviceType in fullResource["services"])
258
362
  {
259
- const grouped_services = fullResource['services'][serviceType];
260
- for (groupedServiceID in grouped_services)
363
+ const groupedServices = fullResource['services'][serviceType];
364
+ for (const groupedServiceID in groupedServices)
261
365
  {
262
366
  if (!processedResources["_groupsOf"][groupedServiceID]) { processedResources["_groupsOf"][groupedServiceID] = []; }
263
367
  processedResources["_groupsOf"][groupedServiceID].push(fullResource.id);
@@ -275,4 +379,4 @@ function API()
275
379
  }
276
380
 
277
381
  // EXPORT
278
- module.exports = new API;
382
+ module.exports = new API;
@@ -1,13 +1,18 @@
1
1
  // EXTERNAL HELPERS
2
2
  const colornames = require("colornames");
3
3
  const colornamer = require('color-namer');
4
- const getColors = require('get-image-colors');
4
+
5
+ // LOADED ON DEMAND, IT PULLS IN A LARGE DEPENDENCY TREE
6
+ function getColors(...args)
7
+ {
8
+ return require('get-image-colors')(...args);
9
+ }
5
10
 
6
11
  // RGB -> XY
7
12
  function rgbToXy(red, green, blue, gamut = null)
8
13
  {
9
14
  var colorGamut = { red: [1.0, 0], green: [0.0, 1.0], blue: [0.0, 0.0] };
10
- if(!!gamut)
15
+ if(!!gamut && !!gamut.red && !!gamut.green && !!gamut.blue)
11
16
  {
12
17
  colorGamut = { red: [gamut.red.x, gamut.red.y], green: [gamut.green.x, gamut.green.y], blue: [gamut.blue.x, gamut.blue.y] };
13
18
  }
@@ -34,9 +39,19 @@ function rgbToXy(red, green, blue, gamut = null)
34
39
  xy = _getClosestColor(xy, colorGamut);
35
40
  }
36
41
 
42
+ // THE BRIDGE REJECTS ANYTHING OUTSIDE 0…1 WITH A 400
43
+ xy.x = _clampToColorSpace(xy.x);
44
+ xy.y = _clampToColorSpace(xy.y);
45
+
37
46
  return xy;
38
47
  }
39
48
 
49
+ function _clampToColorSpace(value)
50
+ {
51
+ if(isNaN(value)) { return 0; }
52
+ return (value < 0) ? 0 : ((value > 1) ? 1 : value);
53
+ }
54
+
40
55
  function _getGammaCorrectedValue(value)
41
56
  {
42
57
  return (value > 0.04045) ? Math.pow((value + 0.055) / (1.0 + 0.055), 2.4) : (value / 12.92)
@@ -153,6 +168,9 @@ function _getClosestPoint(xy, pointA, pointB)
153
168
  let xy2a_dot_a2b = xy2a[0] * a2b[0] + xy2a[1] * a2b[1];
154
169
  let t = xy2a_dot_a2b /a2bSqr;
155
170
 
171
+ // STAY ON THE EDGE OF THE GAMUT, NOT ON THE INFINITE LINE BEHIND IT
172
+ t = (t < 0) ? 0 : ((t > 1) ? 1 : t);
173
+
156
174
  return {
157
175
  x: pointA.x + a2b[0] * t,
158
176
  y: pointA.y + a2b[1] * t
@@ -13,9 +13,10 @@ function mergeDeep(...objects)
13
13
  const pVal = prev[key];
14
14
  const oVal = obj[key];
15
15
 
16
- if(Array.isArray(pVal) && Array.isArray(oVal))
16
+ // AN UPDATE REPLACES A LIST, IT NEVER APPENDS TO IT
17
+ if(Array.isArray(oVal))
17
18
  {
18
- prev[key] = pVal.concat(...oVal);
19
+ prev[key] = oVal;
19
20
  }
20
21
  else if (isObject(pVal) && isObject(oVal))
21
22
  {