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
@@ -1,6 +1,72 @@
1
1
  const dayjs = require('dayjs');
2
2
  const colorUtils = require("./color");
3
3
 
4
+ //
5
+ // ONE NODE TYPE CAN BE FED BY SEVERAL SERVICES OF THE BRIDGE
6
+ const serviceTypes = {
7
+ "light": ["light"],
8
+ "group": ["grouped_light"],
9
+ "motion": ["motion", "camera_motion", "grouped_motion", "convenience_area_motion", "security_area_motion"],
10
+ "button": ["button", "bell_button", "relative_rotary"],
11
+ "contact": ["contact"],
12
+ "temperature": ["temperature"],
13
+ "light_level": ["light_level", "grouped_light_level"],
14
+ "speaker": ["speaker"]
15
+ };
16
+
17
+ //
18
+ // GET THE FIRST SERVICE OF A TYPE BEHIND A RESOURCE
19
+ function service(resource, type)
20
+ {
21
+ const wanted = serviceTypes[type] ? serviceTypes[type] : [type];
22
+
23
+ for (const one of wanted)
24
+ {
25
+ const services = resource["services"] ? resource["services"][one] : false;
26
+ if(services && Object.values(services).length > 0) { return Object.values(services)[0]; }
27
+ }
28
+
29
+ return false;
30
+ }
31
+
32
+ //
33
+ // DOES A RESOURCE OFFER ANYTHING THIS NODE TYPE CAN USE?
34
+ function servesType(resource, type)
35
+ {
36
+ const wanted = serviceTypes[type] ? serviceTypes[type] : [type];
37
+ return !!resource["services"] && wanted.some(function(one) { return !!resource["services"][one]; });
38
+ }
39
+
40
+ //
41
+ // GET THE CONNECTION STATE OF A DEVICE
42
+ function connectivity(resource)
43
+ {
44
+ return service(resource, "zigbee_connectivity") || service(resource, "zgp_connectivity");
45
+ }
46
+
47
+ //
48
+ // GET THE BATTERY STATE OF A DEVICE (MAINS POWERED DEVICES HAVE NONE)
49
+ function battery(resource)
50
+ {
51
+ const power = service(resource, "device_power");
52
+ return (power && power.power_state) ? power.power_state : { battery_level: false, battery_state: false };
53
+ }
54
+
55
+ //
56
+ // DESCRIBE THE DEVICE BEHIND A RESOURCE
57
+ function model(resource)
58
+ {
59
+ const productData = resource.product_data ? resource.product_data : {};
60
+
61
+ return {
62
+ id: productData.model_id ? productData.model_id : false,
63
+ manufacturer: productData.manufacturer_name ? productData.manufacturer_name : false,
64
+ name: productData.product_name ? productData.product_name : false,
65
+ type: productData.product_archetype ? productData.product_archetype : false,
66
+ certified: productData.certified ? productData.certified : false
67
+ };
68
+ }
69
+
4
70
  //
5
71
  // HUE BRIDGE
6
72
  class HueBridgeMessage
@@ -68,41 +134,47 @@ class HueBrightnessMessage
68
134
  {
69
135
  constructor(resource, options = {})
70
136
  {
71
- const service = Object.values(resource["services"]["light_level"])[0];
72
- const connectivity = resource.services.zigbee_connectivity ? Object.values(resource.services.zigbee_connectivity)[0] : ((resource.services.zgp_connectivity) ? Object.values(resource.services.zgp_connectivity)[0] : false);
137
+ const lightLevelService = service(resource, "light_level");
138
+ if(!lightLevelService || !lightLevelService.light) { throw new Error("The light level sensor is not available."); }
139
+
140
+ const connection = connectivity(resource);
141
+ const power = battery(resource);
73
142
 
74
- var realLUX = service.light.light_level - 1;
143
+ // NEWER FIRMWARES REPORT THE VALUE, THE FLAT PROPERTY IS DEPRECATED
144
+ const light = lightLevelService.light;
145
+ const lightLevel = light.light_level_report ? light.light_level_report.light_level : light.light_level;
146
+
147
+ var realLUX = lightLevel - 1;
75
148
  realLUX = realLUX / 10000;
76
149
  realLUX = Math.round(Math.pow(10, realLUX));
77
150
 
78
151
  this.message = {};
79
152
  this.message.payload = {};
80
- this.message.payload.active = service.enabled;
81
- this.message.payload.reachable = connectivity ? (connectivity.status === "connected") : "unknown";
82
- this.message.payload.connectionStatus = connectivity ? connectivity.status : "unknown";
153
+ this.message.payload.active = lightLevelService.enabled;
154
+ this.message.payload.reachable = connection ? (connection.status === "connected") : "unknown";
155
+ this.message.payload.connectionStatus = connection ? connection.status : "unknown";
83
156
  this.message.payload.lux = realLUX;
84
- this.message.payload.lightLevel = service.light.light_level;
85
- this.message.payload.dark = (realLUX < 90);
86
- this.message.payload.daylight = (realLUX >= 90);
157
+ this.message.payload.lightLevel = lightLevel;
158
+ // WHERE "DARK" ENDS CAN BE SET PER NODE
159
+ const darkThreshold = (options.darkThreshold && !isNaN(options.darkThreshold)) ? parseInt(options.darkThreshold) : 90;
160
+
161
+ this.message.payload.dark = (realLUX < darkThreshold);
162
+ this.message.payload.daylight = (realLUX >= darkThreshold);
163
+ this.message.payload.darkThreshold = darkThreshold;
87
164
  this.message.payload.updated = resource.updated;
88
165
 
89
166
  this.message.info = {};
90
- this.message.info.id = service.id;
167
+ this.message.info.id = lightLevelService.id;
91
168
  this.message.info.idV1 = resource.id_v1 ? resource.id_v1 : false;
92
- this.message.info.uniqueId = resource.id + "-" + service.id;
169
+ this.message.info.uniqueId = resource.id + "-" + lightLevelService.id;
93
170
  this.message.info.deviceId = resource.id;
94
- this.message.info.name = resource.metadata.name;
171
+ this.message.info.name = resource.metadata ? resource.metadata.name : false;
95
172
  this.message.info.type = "light_level";
96
- this.message.info.softwareVersion = resource.product_data.software_version;
97
- this.message.info.battery = Object.values(resource.services.device_power)[0].power_state.battery_level;
98
- this.message.info.batteryState = Object.values(resource.services.device_power)[0].power_state.battery_state;
99
-
100
- this.message.info.model = {};
101
- this.message.info.model.id = resource.product_data.model_id;
102
- this.message.info.model.manufacturer = resource.product_data.manufacturer_name;
103
- this.message.info.model.name = resource.product_data.product_name;
104
- this.message.info.model.type = resource.product_data.product_archetype;
105
- this.message.info.model.certified = resource.product_data.certified;
173
+ this.message.info.softwareVersion = resource.product_data ? resource.product_data.software_version : false;
174
+ this.message.info.battery = power.battery_level;
175
+ this.message.info.batteryState = power.battery_state;
176
+
177
+ this.message.info.model = model(resource);
106
178
  }
107
179
 
108
180
  get msg()
@@ -118,8 +190,8 @@ class HueGroupMessage
118
190
  {
119
191
  constructor(resource, options = {})
120
192
  {
121
- let service = Object.values(resource["services"]["grouped_light"])[0];
122
- service = options.resources[service.id];
193
+ const groupedLight = service(resource, "grouped_light");
194
+ if(!groupedLight) { throw new Error("The group has no grouped light service."); }
123
195
 
124
196
  // GET ALL RESOURCES
125
197
  let allResourcesInsideGroup = {};
@@ -130,7 +202,9 @@ class HueGroupMessage
130
202
 
131
203
  this.message = {};
132
204
  this.message.payload = {};
133
- this.message.payload.on = service.on.on;
205
+ this.message.payload.on = groupedLight.on ? groupedLight.on.on : false;
206
+ this.message.payload.brightness = groupedLight.dimming ? groupedLight.dimming.brightness : false;
207
+ this.message.payload.brightnessLevel = groupedLight.dimming ? Math.round((254/100)*groupedLight.dimming.brightness) : false;
134
208
  this.message.payload.updated = resource.updated;
135
209
 
136
210
  this.message.info = {};
@@ -139,6 +213,27 @@ class HueGroupMessage
139
213
  this.message.info.name = resource.metadata ? resource.metadata.name : "all";
140
214
  this.message.info.resources = allResourcesInsideGroup;
141
215
  this.message.info.type = "group";
216
+
217
+ // HAS COLOR CAPABILITIES?
218
+ if(groupedLight["color"] && groupedLight["color"]["xy"])
219
+ {
220
+ let RGB = colorUtils.xyBriToRgb(groupedLight.color.xy.x, groupedLight.color.xy.y, (groupedLight.dimming ? groupedLight.dimming.brightness : 100));
221
+ this.message.payload.rgb = [RGB.r, RGB.g, RGB.b];
222
+ this.message.payload.hex = colorUtils.rgbHex(RGB.r, RGB.g, RGB.b);
223
+ this.message.payload.xyColor = groupedLight.color.xy;
224
+
225
+ if(options.colornames == true)
226
+ {
227
+ var cNamesArray = colorUtils.colornamer(colorUtils.rgbHex(RGB.r, RGB.g, RGB.b));
228
+ this.message.payload.color = cNamesArray.basic[0]["name"];
229
+ }
230
+ }
231
+
232
+ // HAS COLOR TEMPERATURE CAPABILITIES?
233
+ if(groupedLight["color_temperature"] && groupedLight["color_temperature"]["mirek"])
234
+ {
235
+ this.message.payload.colorTemp = groupedLight.color_temperature.mirek;
236
+ }
142
237
  }
143
238
 
144
239
  get msg()
@@ -154,42 +249,39 @@ class HueLightMessage
154
249
  {
155
250
  constructor(resource, options = {})
156
251
  {
157
- const service = Object.values(resource["services"]["light"])[0];
158
- const connectivity = resource.services.zigbee_connectivity ? Object.values(resource.services.zigbee_connectivity)[0] : ((resource.services.zgp_connectivity) ? Object.values(resource.services.zgp_connectivity)[0] : false);
252
+ const lightService = service(resource, "light");
253
+ if(!lightService) { throw new Error("The light is not available."); }
254
+
255
+ const connection = connectivity(resource);
159
256
 
160
257
  this.message = {};
161
258
  this.message.payload = {};
162
- this.message.payload.on = service.on.on;
163
- this.message.payload.brightness = service.dimming ? service.dimming.brightness : false;
164
- this.message.payload.brightnessLevel = service.dimming ? Math.round((254/100)*this.message.payload.brightness) : false;
165
- this.message.payload.reachable = connectivity ? (connectivity.status === "connected") : "unknown";
166
- this.message.payload.connectionStatus = connectivity ? connectivity.status : "unknown";
259
+ this.message.payload.on = lightService.on ? lightService.on.on : false;
260
+ this.message.payload.brightness = lightService.dimming ? lightService.dimming.brightness : false;
261
+ this.message.payload.brightnessLevel = lightService.dimming ? Math.round((254/100)*this.message.payload.brightness) : false;
262
+ this.message.payload.reachable = connection ? (connection.status === "connected") : "unknown";
263
+ this.message.payload.connectionStatus = connection ? connection.status : "unknown";
167
264
  this.message.payload.updated = resource.updated;
168
265
 
169
266
  this.message.info = {};
170
- this.message.info.id = service.id;
267
+ this.message.info.id = lightService.id;
171
268
  this.message.info.idV1 = resource.id_v1 ? resource.id_v1 : false;
172
- this.message.info.uniqueId = resource.id + "-" + service.id;
269
+ this.message.info.uniqueId = resource.id + "-" + lightService.id;
173
270
  this.message.info.deviceId = resource.id;
174
- this.message.info.name = service.metadata.name;
271
+ this.message.info.name = lightService.metadata ? lightService.metadata.name : (resource.metadata ? resource.metadata.name : false);
175
272
  this.message.info.type = "light";
176
- this.message.info.softwareVersion = resource.product_data.software_version;
177
-
178
- this.message.info.model = {};
179
- this.message.info.model.id = resource.product_data.model_id;
180
- this.message.info.model.manufacturer = resource.product_data.manufacturer_name;
181
- this.message.info.model.name = resource.product_data.product_name;
182
- this.message.info.model.type = resource.product_data.product_archetype;
183
- this.message.info.model.certified = resource.product_data.certified;
273
+ this.message.info.softwareVersion = resource.product_data ? resource.product_data.software_version : false;
274
+
275
+ this.message.info.model = model(resource);
184
276
  this.message.info.model.friendsOfHue = true;
185
277
 
186
278
  // HAS COLOR CAPABILITIES?
187
- if(service["color"])
279
+ if(lightService["color"] && lightService["color"]["xy"])
188
280
  {
189
- let RGB = colorUtils.xyBriToRgb(service.color.xy.x, service.color.xy.y, (service.dimming ? service.dimming.brightness : 100));
281
+ let RGB = colorUtils.xyBriToRgb(lightService.color.xy.x, lightService.color.xy.y, (lightService.dimming ? lightService.dimming.brightness : 100));
190
282
  this.message.payload.rgb = [RGB.r, RGB.g, RGB.b];
191
283
  this.message.payload.hex = colorUtils.rgbHex(RGB.r, RGB.g, RGB.b);
192
- this.message.payload.xyColor = service.color.xy;
284
+ this.message.payload.xyColor = lightService.color.xy;
193
285
 
194
286
  if(options.colornames == true)
195
287
  {
@@ -197,14 +289,14 @@ class HueLightMessage
197
289
  this.message.payload.color = cNamesArray.basic[0]["name"];
198
290
  }
199
291
 
200
- this.message.info.model.colorGamut = service.color.gamut;
201
- this.message.info.model.colorGamutType = service.color.gamut_type;
292
+ this.message.info.model.colorGamut = lightService.color.gamut;
293
+ this.message.info.model.colorGamutType = lightService.color.gamut_type;
202
294
  }
203
295
 
204
296
  // HAS COLOR TEMPERATURE CAPABILITIES?
205
- if(service["color_temperature"])
297
+ if(lightService["color_temperature"])
206
298
  {
207
- this.message.payload.colorTemp = service.color_temperature.mirek ? service.color_temperature.mirek : false;
299
+ this.message.payload.colorTemp = lightService.color_temperature.mirek ? lightService.color_temperature.mirek : false;
208
300
 
209
301
  if(!this.message.payload.colorTemp) { this.message.payload.colorTempName = "unknown"; }
210
302
  else if(this.message.payload.colorTemp < 200) { this.message.payload.colorTempName = "cold"; }
@@ -213,26 +305,60 @@ class HueLightMessage
213
305
  else { this.message.payload.colorTempName = "hot"; }
214
306
  }
215
307
 
308
+ // HAS EFFECT CAPABILITIES? "effects_v2" SUPERSEDES "effects" AND NESTS ITS VALUES DIFFERENTLY
309
+ if(lightService["effects_v2"])
310
+ {
311
+ const effects = lightService["effects_v2"];
312
+
313
+ this.message.payload.effect = (effects.status && effects.status.effect) ? effects.status.effect : "no_effect";
314
+ this.message.info.model.effectsV2 = true;
315
+ this.message.info.model.effects = (effects.action && effects.action.effect_values) ? effects.action.effect_values : [];
316
+ }
317
+ else if(lightService["effects"])
318
+ {
319
+ const effects = lightService["effects"];
320
+
321
+ this.message.payload.effect = effects.status ? effects.status : "no_effect";
322
+ this.message.info.model.effectsV2 = false;
323
+ this.message.info.model.effects = effects.effect_values ? effects.effect_values : [];
324
+ }
325
+
326
+ // HAS TIMED EFFECT CAPABILITIES? (SUNRISE / SUNSET)
327
+ if(lightService["timed_effects"])
328
+ {
329
+ this.message.payload.timedEffect = lightService.timed_effects.status ? lightService.timed_effects.status : "no_effect";
330
+ this.message.info.model.timedEffects = lightService.timed_effects.effect_values ? lightService.timed_effects.effect_values : [];
331
+ }
332
+
333
+ // HOW THE LIGHT COMES BACK AFTER A POWER CUT
334
+ if(lightService["powerup"])
335
+ {
336
+ this.message.payload.powerUp = lightService.powerup.preset ? lightService.powerup.preset : false;
337
+ }
338
+
216
339
  // HAS GRADIENT COLOR CAPABILITIES?
217
- if(service["gradient"])
340
+ if(lightService["gradient"])
218
341
  {
342
+ const points = lightService["gradient"]["points"] ? lightService["gradient"]["points"] : [];
343
+
219
344
  this.message.payload.gradient = {};
220
345
  this.message.payload.gradient.colors = [];
221
346
 
222
- for(let gradientColor in service["gradient"]["points"])
347
+ for(let gradientColor of points)
223
348
  {
224
- let gradientColorRGB = colorUtils.xyBriToRgb(gradientColor.color.xy.x, gradientColor.color.xy.y, (gradientColor.dimming ? service.dimming.brightness : 100));
349
+ let gradientColorRGB = colorUtils.xyBriToRgb(gradientColor.color.xy.x, gradientColor.color.xy.y, (lightService.dimming ? lightService.dimming.brightness : 100));
225
350
 
226
351
  let oneColorPack = {};
227
352
  oneColorPack.rgb = [gradientColorRGB.r, gradientColorRGB.g, gradientColorRGB.b];
228
353
  oneColorPack.hex = colorUtils.rgbHex(gradientColorRGB.r, gradientColorRGB.g, gradientColorRGB.b);
229
- oneColorPack.xyColor = gradientColor.color.xy.x;
354
+ oneColorPack.xyColor = gradientColor.color.xy;
230
355
 
231
356
  this.message.payload.gradient.colors.push(oneColorPack);
232
357
  }
233
358
 
234
- this.message.payload.gradient.numColors = service["gradient"]["points"] ? service["gradient"]["points"].length : 0;
235
- this.message.payload.gradient.totalColors = service["gradient"]["points_capable"];
359
+ this.message.payload.gradient.numColors = points.length;
360
+ this.message.payload.gradient.totalColors = lightService["gradient"]["points_capable"];
361
+ this.message.payload.gradient.mode = lightService["gradient"]["mode"] ? lightService["gradient"]["mode"] : false;
236
362
  }
237
363
  }
238
364
 
@@ -249,35 +375,97 @@ class HueMotionMessage
249
375
  {
250
376
  constructor(resource, options = {})
251
377
  {
252
- const service = Object.values(resource["services"]["motion"])[0];
253
- const connectivity = resource.services.zigbee_connectivity ? Object.values(resource.services.zigbee_connectivity)[0] : ((resource.services.zgp_connectivity) ? Object.values(resource.services.zgp_connectivity)[0] : false);
378
+ const motionService = service(resource, "motion");
379
+ if(!motionService || !motionService.motion) { throw new Error("The motion sensor is not available."); }
380
+
381
+ const connection = connectivity(resource);
382
+ const power = battery(resource);
383
+
384
+ // NEWER FIRMWARES REPORT THE VALUE, THE FLAT PROPERTIES ARE DEPRECATED
385
+ const motion = motionService.motion;
386
+ const detected = motion.motion_report ? motion.motion_report.motion : (motion.motion && motion.motion_valid);
254
387
 
255
388
  this.message = {};
256
389
  this.message.payload = {
257
- active: service.enabled,
258
- reachable: connectivity ? (connectivity.status === "connected") : "unknown",
259
- connectionStatus: connectivity ? connectivity.status : "unknown",
260
- motion: (service.motion.motion && service.motion.motion_valid),
390
+ active: motionService.enabled,
391
+ reachable: connection ? (connection.status === "connected") : "unknown",
392
+ connectionStatus: connection ? connection.status : "unknown",
393
+ motion: (detected === true),
261
394
  updated: resource.updated
262
395
  };
263
396
 
397
+ // CAMERAS AND MOTIONAWARE AREAS CAN BE TUNED
398
+ if(motionService.sensitivity)
399
+ {
400
+ this.message.payload.sensitivity = motionService.sensitivity.sensitivity;
401
+ this.message.payload.sensitivityMax = motionService.sensitivity.sensitivity_max;
402
+ }
403
+
264
404
  this.message.info = {};
265
- this.message.info.id = service.id;
405
+ this.message.info.id = motionService.id;
266
406
  this.message.info.idV1 = resource.id_v1 ? resource.id_v1 : false;
267
- this.message.info.uniqueId = resource.id + "-" + service.id;
407
+ this.message.info.uniqueId = resource.id + "-" + motionService.id;
268
408
  this.message.info.deviceId = resource.id;
269
- this.message.info.name = resource.metadata.name;
270
- this.message.info.type = "motion";
271
- this.message.info.softwareVersion = resource.product_data.software_version;
272
- this.message.info.battery = Object.values(resource.services.device_power)[0].power_state.battery_level;
273
- this.message.info.batteryState = Object.values(resource.services.device_power)[0].power_state.battery_state;
274
-
275
- this.message.info.model = {};
276
- this.message.info.model.id = resource.product_data.model_id;
277
- this.message.info.model.manufacturer = resource.product_data.manufacturer_name;
278
- this.message.info.model.name = resource.product_data.product_name;
279
- this.message.info.model.type = resource.product_data.product_archetype;
280
- this.message.info.model.certified = resource.product_data.certified;
409
+ this.message.info.name = resource.metadata ? resource.metadata.name : (resource.name ? resource.name : false);
410
+ this.message.info.type = motionService.type ? motionService.type : "motion";
411
+ this.message.info.softwareVersion = resource.product_data ? resource.product_data.software_version : false;
412
+ this.message.info.battery = power.battery_level;
413
+ this.message.info.batteryState = power.battery_state;
414
+
415
+ this.message.info.model = model(resource);
416
+ }
417
+
418
+ get msg()
419
+ {
420
+ return this.message;
421
+ }
422
+ }
423
+
424
+
425
+ //
426
+ // HUE CONTACT
427
+ class HueContactMessage
428
+ {
429
+ constructor(resource, options = {})
430
+ {
431
+ const contactService = service(resource, "contact");
432
+ if(!contactService) { throw new Error("The contact sensor is not available."); }
433
+
434
+ const connection = connectivity(resource);
435
+ const power = battery(resource);
436
+ const tamperService = service(resource, "tamper");
437
+
438
+ // THE SENSOR ONLY REPORTS AFTER THE FIRST STATE CHANGE
439
+ const report = contactService.contact_report ? contactService.contact_report : { state: false, changed: false };
440
+
441
+ this.message = {};
442
+ this.message.payload = {
443
+ active: contactService.enabled,
444
+ reachable: connection ? (connection.status === "connected") : "unknown",
445
+ connectionStatus: connection ? connection.status : "unknown",
446
+ contact: report.state,
447
+ changed: report.changed,
448
+ updated: resource.updated
449
+ };
450
+
451
+ // HAS TAMPER DETECTION? (HUE SECURE)
452
+ if(tamperService && Array.isArray(tamperService.tamper_reports))
453
+ {
454
+ this.message.payload.tampered = tamperService.tamper_reports.some(function(oneReport) { return oneReport.state === "tampered"; });
455
+ }
456
+
457
+ this.message.info = {};
458
+ this.message.info.id = contactService.id;
459
+ this.message.info.idV1 = resource.id_v1 ? resource.id_v1 : false;
460
+ this.message.info.uniqueId = resource.id + "-" + contactService.id;
461
+ this.message.info.deviceId = resource.id;
462
+ this.message.info.name = resource.metadata ? resource.metadata.name : false;
463
+ this.message.info.type = "contact";
464
+ this.message.info.softwareVersion = resource.product_data ? resource.product_data.software_version : false;
465
+ this.message.info.battery = power.battery_level;
466
+ this.message.info.batteryState = power.battery_state;
467
+
468
+ this.message.info.model = model(resource);
281
469
  }
282
470
 
283
471
  get msg()
@@ -323,47 +511,86 @@ class HueButtonsMessage
323
511
  {
324
512
  constructor(resource, options = {})
325
513
  {
326
- const connectivity = resource.services.zigbee_connectivity ? Object.values(resource.services.zigbee_connectivity)[0] : ((resource.services.zgp_connectivity) ? Object.values(resource.services.zgp_connectivity)[0] : false);
514
+ const connection = connectivity(resource);
515
+ const power = battery(resource);
327
516
 
328
- // FIND PRESSED BUTTON
517
+ // FIND PRESSED BUTTON (A DOORBELL BEHAVES EXACTLY LIKE ONE)
329
518
  var pressedButton = false;
330
- const allButtons = Object.values(resource.services.button);
519
+ var isDoorbell = false;
520
+
521
+ for (const oneType of ["button", "bell_button"])
522
+ {
523
+ const allButtons = resource.services[oneType] ? Object.values(resource.services[oneType]) : [];
524
+
525
+ for (var i = allButtons.length - 1; i >= 0; i--)
526
+ {
527
+ if(allButtons[i]["button"])
528
+ {
529
+ pressedButton = allButtons[i];
530
+ isDoorbell = (oneType === "bell_button");
531
+ break;
532
+ }
533
+ }
331
534
 
332
- for (var i = allButtons.length - 1; i >= 0; i--)
535
+ if(pressedButton) { break; }
536
+ }
537
+
538
+ // FIND ROTATION (HUE TAP DIAL, LUTRON AURORA)
539
+ var rotaryDial = false;
540
+ const allRotaries = resource.services.relative_rotary ? Object.values(resource.services.relative_rotary) : [];
541
+
542
+ for (var r = allRotaries.length - 1; r >= 0; r--)
333
543
  {
334
- if(allButtons[i]["button"])
544
+ if(allRotaries[r]["relative_rotary"])
335
545
  {
336
- pressedButton = allButtons[i];
546
+ rotaryDial = allRotaries[r];
337
547
  break;
338
548
  }
339
549
  }
340
550
 
551
+ // NEWER FIRMWARES REPORT THE EVENT, "last_event" IS DEPRECATED
552
+ const buttonEvent = pressedButton ? (pressedButton.button.button_report ? pressedButton.button.button_report.event : pressedButton.button.last_event) : false;
553
+ const rotaryEvent = rotaryDial ? (rotaryDial.relative_rotary.rotary_report ? rotaryDial.relative_rotary.rotary_report : rotaryDial.relative_rotary.last_event) : false;
554
+
341
555
  this.message = {};
342
556
  this.message.payload = {
343
- reachable: connectivity ? (connectivity.status === "connected") : "unknown",
344
- connectionStatus: connectivity ? connectivity.status : "unknown",
557
+ reachable: connection ? (connection.status === "connected") : "unknown",
558
+ connectionStatus: connection ? connection.status : "unknown",
345
559
  button: pressedButton ? pressedButton.metadata.control_id : false,
346
- action: pressedButton ? pressedButton.button.last_event : false,
560
+ action: buttonEvent ? buttonEvent : false,
347
561
  updated: resource.updated
348
562
  };
349
563
 
564
+ // IS A DOORBELL?
565
+ this.message.payload.doorbell = isDoorbell;
566
+
567
+ // HAS BEEN ROTATED?
568
+ this.message.payload.rotation = (rotaryEvent && rotaryEvent.rotation) ? {
569
+ action: rotaryEvent.action,
570
+ direction: rotaryEvent.rotation.direction,
571
+ clockwise: (rotaryEvent.rotation.direction === "clock_wise"),
572
+ steps: rotaryEvent.rotation.steps,
573
+ degrees: Math.round((360/1000)*rotaryEvent.rotation.steps),
574
+ duration: rotaryEvent.rotation.duration
575
+ } : false;
576
+
350
577
  this.message.info = {};
351
- this.message.info.id = pressedButton ? pressedButton.id : resource.id;
578
+ this.message.info.id = pressedButton ? pressedButton.id : (rotaryDial ? rotaryDial.id : resource.id);
352
579
  this.message.info.idV1 = resource.id_v1 ? resource.id_v1 : false;
353
- this.message.info.uniqueId = resource.id + "-" + (pressedButton ? pressedButton.id : "");
580
+ this.message.info.uniqueId = resource.id + "-" + (pressedButton ? pressedButton.id : (rotaryDial ? rotaryDial.id : ""));
354
581
  this.message.info.deviceId = resource.id;
355
- this.message.info.name = resource.metadata.name;
582
+ this.message.info.name = resource.metadata ? resource.metadata.name : false;
356
583
  this.message.info.type = "button";
357
- this.message.info.softwareVersion = resource.product_data.software_version;
358
- this.message.info.battery = resource.services.device_power ? Object.values(resource.services.device_power)[0].power_state.battery_level : false;
359
- this.message.info.batteryState = resource.services.device_power ? Object.values(resource.services.device_power)[0].power_state.battery_state : false;
360
-
361
- this.message.info.model = {};
362
- this.message.info.model.id = resource.product_data.model_id;
363
- this.message.info.model.manufacturer = resource.product_data.manufacturer_name;
364
- this.message.info.model.name = resource.product_data.product_name;
365
- this.message.info.model.type = resource.product_data.product_archetype;
366
- this.message.info.model.certified = resource.product_data.certified;
584
+ this.message.info.softwareVersion = resource.product_data ? resource.product_data.software_version : false;
585
+ this.message.info.battery = power.battery_level;
586
+ this.message.info.batteryState = power.battery_state;
587
+
588
+ // WALL SWITCH MODULES CAN RUN AS ROCKERS OR AS PUSHBUTTONS
589
+ const switchConfig = service(resource, "switch_input_configuration");
590
+ this.message.info.switchMode = (switchConfig && switchConfig.switch_mode) ? switchConfig.switch_mode.mode : false;
591
+ this.message.info.switchModes = (switchConfig && switchConfig.switch_mode) ? switchConfig.switch_mode.mode_values : false;
592
+
593
+ this.message.info.model = model(resource);
367
594
  }
368
595
 
369
596
  get msg()
@@ -379,11 +606,19 @@ class HueTemperatureMessage
379
606
  {
380
607
  constructor(resource, options = {})
381
608
  {
382
- const service = Object.values(resource["services"]["temperature"])[0];
383
- const connectivity = resource.services.zigbee_connectivity ? Object.values(resource.services.zigbee_connectivity)[0] : ((resource.services.zgp_connectivity) ? Object.values(resource.services.zgp_connectivity)[0] : false);
609
+ const temperatureService = service(resource, "temperature");
610
+ if(!temperatureService || !temperatureService.temperature) { throw new Error("The temperature sensor is not available."); }
611
+
612
+ const connection = connectivity(resource);
613
+ const power = battery(resource);
384
614
 
385
- var deviceValue = service.temperature.temperature;
386
- var celsius = Math.round(deviceValue * 100) / 100;
615
+ // NEWER FIRMWARES REPORT THE VALUE, THE FLAT PROPERTY IS DEPRECATED
616
+ const temperature = temperatureService.temperature;
617
+ var deviceValue = temperature.temperature_report ? temperature.temperature_report.temperature : temperature.temperature;
618
+
619
+ // SENSORS SIT NEXT TO WARM ELECTRONICS, SO THE READING CAN BE CALIBRATED PER NODE
620
+ const offset = (options.offset && !isNaN(options.offset)) ? parseFloat(options.offset) : 0;
621
+ var celsius = Math.round((deviceValue + offset) * 100) / 100;
387
622
  var fahrenheit = Math.round(((celsius * 1.8)+32) * 100) / 100;
388
623
 
389
624
  // TEMPERATURE MESSAGE
@@ -416,33 +651,29 @@ class HueTemperatureMessage
416
651
 
417
652
  this.message = {};
418
653
  this.message.payload = {
419
- active: service.enabled,
420
- reachable: connectivity ? (connectivity.status === "connected") : "unknown",
421
- connectionStatus: connectivity ? connectivity.status : "unknown",
654
+ active: temperatureService.enabled,
655
+ reachable: connection ? (connection.status === "connected") : "unknown",
656
+ connectionStatus: connection ? connection.status : "unknown",
422
657
  celsius: celsius,
423
658
  fahrenheit: fahrenheit,
424
659
  temperatureIs: temperatureMessage,
425
660
  deviceValue: deviceValue,
661
+ offset: offset,
426
662
  updated: resource.updated
427
663
  };
428
664
 
429
665
  this.message.info = {};
430
- this.message.info.id = service.id;
666
+ this.message.info.id = temperatureService.id;
431
667
  this.message.info.idV1 = resource.id_v1 ? resource.id_v1 : false;
432
- this.message.info.uniqueId = resource.id + "-" + service.id;
668
+ this.message.info.uniqueId = resource.id + "-" + temperatureService.id;
433
669
  this.message.info.deviceId = resource.id;
434
- this.message.info.name = resource.metadata.name;
670
+ this.message.info.name = resource.metadata ? resource.metadata.name : false;
435
671
  this.message.info.type = "temperature";
436
- this.message.info.softwareVersion = resource.product_data.software_version;
437
- this.message.info.battery = Object.values(resource.services.device_power)[0].power_state.battery_level;
438
- this.message.info.batteryState = Object.values(resource.services.device_power)[0].power_state.battery_state;
439
-
440
- this.message.info.model = {};
441
- this.message.info.model.id = resource.product_data.model_id;
442
- this.message.info.model.manufacturer = resource.product_data.manufacturer_name;
443
- this.message.info.model.name = resource.product_data.product_name;
444
- this.message.info.model.type = resource.product_data.product_archetype;
445
- this.message.info.model.certified = resource.product_data.certified;
672
+ this.message.info.softwareVersion = resource.product_data ? resource.product_data.software_version : false;
673
+ this.message.info.battery = power.battery_level;
674
+ this.message.info.batteryState = power.battery_state;
675
+
676
+ this.message.info.model = model(resource);
446
677
  }
447
678
 
448
679
  get msg()
@@ -452,6 +683,161 @@ class HueTemperatureMessage
452
683
  }
453
684
 
454
685
  //
455
- // EXPORT
456
- module.exports = { HueBridgeMessage, HueBrightnessMessage, HueGroupMessage, HueLightMessage, HueMotionMessage, HueRulesMessage, HueButtonsMessage, HueTemperatureMessage }
686
+ // HUE SPEAKER (HUE SECURE CHIME / SIREN)
687
+ class HueSpeakerMessage
688
+ {
689
+ constructor(resource, options = {})
690
+ {
691
+ const speaker = service(resource, "speaker");
692
+ if(!speaker) { throw new Error("The speaker is not available."); }
693
+
694
+ const connection = connectivity(resource);
695
+ const power = battery(resource);
696
+
697
+ // THE BRIDGE REPORTS THE SOUND THAT WAS PLAYED LAST AND CLEARS IT LATE
698
+ const playing = function(sound)
699
+ {
700
+ return (sound && sound.status && sound.status.sound && sound.status.sound !== "no_sound") ? sound.status.sound : false;
701
+ };
702
+
703
+ this.message = {};
704
+ this.message.payload = {
705
+ reachable: connection ? (connection.status === "connected") : "unknown",
706
+ connectionStatus: connection ? connection.status : "unknown",
707
+ muted: (speaker.mute && speaker.mute.mute === "mute"),
708
+ alarm: playing(speaker.alarm),
709
+ chime: playing(speaker.chime),
710
+ alert: playing(speaker.alert),
711
+ updated: resource.updated
712
+ };
713
+
714
+ this.message.payload.playing = !!(this.message.payload.alarm || this.message.payload.chime || this.message.payload.alert);
715
+
716
+ this.message.info = {};
717
+ this.message.info.id = speaker.id;
718
+ this.message.info.idV1 = resource.id_v1 ? resource.id_v1 : false;
719
+ this.message.info.uniqueId = resource.id + "-" + speaker.id;
720
+ this.message.info.deviceId = resource.id;
721
+ this.message.info.name = resource.metadata ? resource.metadata.name : false;
722
+ this.message.info.type = "speaker";
723
+ this.message.info.softwareVersion = resource.product_data ? resource.product_data.software_version : false;
724
+ this.message.info.battery = power.battery_level;
725
+ this.message.info.batteryState = power.battery_state;
726
+
727
+ // WHICH SOUNDS THIS DEVICE ACTUALLY KNOWS
728
+ this.message.info.sounds = {
729
+ alarm: speaker.alarm ? speaker.alarm.sound_values : false,
730
+ chime: speaker.chime ? speaker.chime.sound_values : false,
731
+ alert: speaker.alert ? speaker.alert.sound_values : false
732
+ };
733
+
734
+ this.message.info.model = model(resource);
735
+ }
736
+
737
+ get msg()
738
+ {
739
+ return this.message;
740
+ }
741
+ }
742
+
743
+
744
+ //
745
+ // HUE AUTOMATION (BEHAVIOR INSTANCE)
746
+ class HueAutomationMessage
747
+ {
748
+ constructor(resource, options = {})
749
+ {
750
+ this.message = {};
751
+ this.message.payload = {
752
+ enabled: (resource["enabled"] === true),
753
+ status: resource["status"] ? resource["status"] : false,
754
+ running: (resource["status"] === "running"),
755
+ lastError: resource["last_error"] ? resource["last_error"] : false,
756
+ updated: resource.updated
757
+ };
758
+
759
+ this.message.info = {};
760
+ this.message.info.id = resource["id"];
761
+ this.message.info.idV1 = resource.id_v1 ? resource.id_v1 : false;
762
+ this.message.info.name = (resource["metadata"] && resource["metadata"]["name"]) ? resource["metadata"]["name"] : false;
763
+ this.message.info.type = "automation";
764
+ this.message.info.script = resource["script_id"] ? resource["script_id"] : false;
765
+
766
+ this.message.configuration = resource["configuration"] ? resource["configuration"] : {};
767
+ }
768
+
769
+ get msg()
770
+ {
771
+ return this.message;
772
+ }
773
+ }
774
+
457
775
 
776
+ //
777
+ // HUE PLAY HDMI SYNC BOX
778
+ class HueSyncBoxMessage
779
+ {
780
+ constructor(resource, options = {})
781
+ {
782
+ const device = resource["device"] ? resource["device"] : {};
783
+ const execution = resource["execution"] ? resource["execution"] : {};
784
+ const hdmi = resource["hdmi"] ? resource["hdmi"] : {};
785
+
786
+ // THE INTENSITY IS STORED PER SYNC MODE
787
+ const activeMode = execution[execution.mode] ? execution[execution.mode] : false;
788
+
789
+ this.message = {};
790
+ this.message.payload = {
791
+ on: (execution.mode ? (execution.mode !== "powersave") : false),
792
+ syncing: (execution.syncActive === true),
793
+ passthrough: (execution.hdmiActive === true),
794
+ mode: execution.mode ? execution.mode : false,
795
+ lastSyncMode: execution.lastSyncMode ? execution.lastSyncMode : false,
796
+ intensity: activeMode ? activeMode.intensity : false,
797
+ brightness: (typeof execution.brightness != 'undefined') ? Math.round((100/200)*execution.brightness) : false,
798
+ brightnessLevel: (typeof execution.brightness != 'undefined') ? execution.brightness : false,
799
+ input: execution.hdmiSource ? execution.hdmiSource : false,
800
+ entertainmentArea: execution.hueTarget ? execution.hueTarget : false,
801
+ updated: resource.updated
802
+ };
803
+
804
+ // WHAT IS PLUGGED INTO THE FOUR INPUTS
805
+ this.message.payload.inputs = {};
806
+ for (const one of ["input1", "input2", "input3", "input4"])
807
+ {
808
+ if(!hdmi[one]) { continue; }
809
+ this.message.payload.inputs[one] = {
810
+ name: hdmi[one].name ? hdmi[one].name : one,
811
+ type: hdmi[one].type ? hdmi[one].type : false,
812
+ status: hdmi[one].status ? hdmi[one].status : "unknown",
813
+ active: (execution.hdmiSource === one)
814
+ };
815
+ }
816
+
817
+ this.message.info = {};
818
+ this.message.info.id = device.uniqueId ? device.uniqueId : false;
819
+ this.message.info.name = device.name ? device.name : false;
820
+ this.message.info.type = "syncbox";
821
+ this.message.info.ipAddress = device.ipAddress ? device.ipAddress : false;
822
+ this.message.info.softwareVersion = device.firmwareVersion ? device.firmwareVersion : false;
823
+ this.message.info.apiLevel = device.apiLevel ? device.apiLevel : false;
824
+ this.message.info.ledMode = (typeof device.ledMode != 'undefined') ? device.ledMode : false;
825
+ this.message.info.wifi = device.wifi ? { ssid: device.wifi.ssid, strength: device.wifi.strength } : false;
826
+
827
+ this.message.info.model = {
828
+ id: device.deviceType ? device.deviceType : false,
829
+ manufacturer: "Signify",
830
+ name: "Hue Play HDMI Sync Box"
831
+ };
832
+ }
833
+
834
+ get msg()
835
+ {
836
+ return this.message;
837
+ }
838
+ }
839
+
840
+
841
+ //
842
+ // EXPORT
843
+ module.exports = { HueBridgeMessage, HueBrightnessMessage, HueGroupMessage, HueLightMessage, HueMotionMessage, HueContactMessage, HueRulesMessage, HueButtonsMessage, HueTemperatureMessage, HueSpeakerMessage, HueAutomationMessage, HueSyncBoxMessage, serviceTypes, servesType }