@mp-consulting/homebridge-daikin-cloud 1.3.6 → 1.3.7

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 (287) hide show
  1. package/LICENSE +39 -1
  2. package/README.md +3 -1
  3. package/dist/src/accessories/air-conditioning-accessory.d.ts +2 -2
  4. package/dist/src/accessories/air-conditioning-accessory.d.ts.map +1 -1
  5. package/dist/src/accessories/air-conditioning-accessory.js.map +1 -1
  6. package/dist/src/accessories/altherma-accessory.d.ts +2 -2
  7. package/dist/src/accessories/altherma-accessory.d.ts.map +1 -1
  8. package/dist/src/accessories/altherma-accessory.js.map +1 -1
  9. package/dist/src/accessories/base-accessory.d.ts +5 -5
  10. package/dist/src/accessories/base-accessory.d.ts.map +1 -1
  11. package/dist/src/accessories/base-accessory.js +7 -4
  12. package/dist/src/accessories/base-accessory.js.map +1 -1
  13. package/dist/src/api/daikin-api.d.ts +25 -25
  14. package/dist/src/api/daikin-api.d.ts.map +1 -1
  15. package/dist/src/api/daikin-api.js +41 -31
  16. package/dist/src/api/daikin-api.js.map +1 -1
  17. package/dist/src/api/daikin-cloud.repository.d.ts.map +1 -1
  18. package/dist/src/api/daikin-cloud.repository.js.map +1 -1
  19. package/dist/src/api/daikin-controller.d.ts +41 -42
  20. package/dist/src/api/daikin-controller.d.ts.map +1 -1
  21. package/dist/src/api/daikin-controller.js +39 -39
  22. package/dist/src/api/daikin-controller.js.map +1 -1
  23. package/dist/src/api/daikin-device.d.ts +33 -31
  24. package/dist/src/api/daikin-device.d.ts.map +1 -1
  25. package/dist/src/api/daikin-device.js +40 -29
  26. package/dist/src/api/daikin-device.js.map +1 -1
  27. package/dist/src/api/daikin-mobile-oauth.d.ts +16 -16
  28. package/dist/src/api/daikin-mobile-oauth.d.ts.map +1 -1
  29. package/dist/src/api/daikin-mobile-oauth.js +32 -22
  30. package/dist/src/api/daikin-mobile-oauth.js.map +1 -1
  31. package/dist/src/api/daikin-oauth.d.ts +29 -29
  32. package/dist/src/api/daikin-oauth.d.ts.map +1 -1
  33. package/dist/src/api/daikin-oauth.js +45 -35
  34. package/dist/src/api/daikin-oauth.js.map +1 -1
  35. package/dist/src/api/daikin-schemas.d.ts +4 -4
  36. package/dist/src/api/daikin-schemas.js +3 -3
  37. package/dist/src/api/daikin-schemas.js.map +1 -1
  38. package/dist/src/api/daikin-types.js.map +1 -1
  39. package/dist/src/api/daikin-websocket.d.ts +31 -32
  40. package/dist/src/api/daikin-websocket.d.ts.map +1 -1
  41. package/dist/src/api/daikin-websocket.js +30 -30
  42. package/dist/src/api/daikin-websocket.js.map +1 -1
  43. package/dist/src/api/index.d.ts +1 -1
  44. package/dist/src/api/index.d.ts.map +1 -1
  45. package/dist/src/api/index.js +2 -1
  46. package/dist/src/api/index.js.map +1 -1
  47. package/dist/src/api/token-storage.d.ts +1 -1
  48. package/dist/src/api/token-storage.d.ts.map +1 -1
  49. package/dist/src/api/token-storage.js +20 -11
  50. package/dist/src/api/token-storage.js.map +1 -1
  51. package/dist/src/config/config-manager.d.ts +33 -33
  52. package/dist/src/config/config-manager.d.ts.map +1 -1
  53. package/dist/src/config/config-manager.js +33 -33
  54. package/dist/src/config/config-manager.js.map +1 -1
  55. package/dist/src/constants/api.constants.js.map +1 -1
  56. package/dist/src/device/accessory-factory.d.ts +10 -10
  57. package/dist/src/device/accessory-factory.d.ts.map +1 -1
  58. package/dist/src/device/accessory-factory.js +6 -6
  59. package/dist/src/device/accessory-factory.js.map +1 -1
  60. package/dist/src/device/capability-detector.d.ts +8 -8
  61. package/dist/src/device/capability-detector.d.ts.map +1 -1
  62. package/dist/src/device/capability-detector.js +6 -6
  63. package/dist/src/device/capability-detector.js.map +1 -1
  64. package/dist/src/device/capability-docs.d.ts +1 -1
  65. package/dist/src/device/capability-docs.d.ts.map +1 -1
  66. package/dist/src/device/capability-docs.js +1 -2
  67. package/dist/src/device/capability-docs.js.map +1 -1
  68. package/dist/src/device/profiles/device-profile.d.ts +1 -1
  69. package/dist/src/device/profiles/device-profile.d.ts.map +1 -1
  70. package/dist/src/device/profiles/device-profile.js +4 -4
  71. package/dist/src/device/profiles/device-profile.js.map +1 -1
  72. package/dist/src/features/base-feature.d.ts +2 -2
  73. package/dist/src/features/base-feature.d.ts.map +1 -1
  74. package/dist/src/features/base-feature.js +2 -3
  75. package/dist/src/features/base-feature.js.map +1 -1
  76. package/dist/src/features/feature-manager.d.ts +8 -8
  77. package/dist/src/features/feature-manager.d.ts.map +1 -1
  78. package/dist/src/features/feature-manager.js +5 -5
  79. package/dist/src/features/feature-manager.js.map +1 -1
  80. package/dist/src/features/modes/dry-operation-mode.feature.d.ts +1 -1
  81. package/dist/src/features/modes/dry-operation-mode.feature.d.ts.map +1 -1
  82. package/dist/src/features/modes/dry-operation-mode.feature.js.map +1 -1
  83. package/dist/src/features/modes/econo-mode.feature.d.ts +1 -1
  84. package/dist/src/features/modes/econo-mode.feature.d.ts.map +1 -1
  85. package/dist/src/features/modes/econo-mode.feature.js.map +1 -1
  86. package/dist/src/features/modes/fan-only-operation-mode.feature.d.ts +1 -1
  87. package/dist/src/features/modes/fan-only-operation-mode.feature.d.ts.map +1 -1
  88. package/dist/src/features/modes/fan-only-operation-mode.feature.js.map +1 -1
  89. package/dist/src/features/modes/indoor-silent-mode.feature.d.ts +1 -1
  90. package/dist/src/features/modes/indoor-silent-mode.feature.d.ts.map +1 -1
  91. package/dist/src/features/modes/indoor-silent-mode.feature.js.map +1 -1
  92. package/dist/src/features/modes/outdoor-silent-mode.feature.d.ts +1 -1
  93. package/dist/src/features/modes/outdoor-silent-mode.feature.d.ts.map +1 -1
  94. package/dist/src/features/modes/outdoor-silent-mode.feature.js.map +1 -1
  95. package/dist/src/features/modes/powerful-mode.feature.d.ts +1 -1
  96. package/dist/src/features/modes/powerful-mode.feature.d.ts.map +1 -1
  97. package/dist/src/features/modes/powerful-mode.feature.js.map +1 -1
  98. package/dist/src/features/modes/streamer-mode.feature.d.ts +1 -1
  99. package/dist/src/features/modes/streamer-mode.feature.d.ts.map +1 -1
  100. package/dist/src/features/modes/streamer-mode.feature.js.map +1 -1
  101. package/dist/src/index.d.ts +1 -1
  102. package/dist/src/index.d.ts.map +1 -1
  103. package/dist/src/index.js.map +1 -1
  104. package/dist/src/platform.d.ts +6 -5
  105. package/dist/src/platform.d.ts.map +1 -1
  106. package/dist/src/platform.js +2 -2
  107. package/dist/src/platform.js.map +1 -1
  108. package/dist/src/services/climate-control.service.d.ts +8 -2
  109. package/dist/src/services/climate-control.service.d.ts.map +1 -1
  110. package/dist/src/services/climate-control.service.js +53 -59
  111. package/dist/src/services/climate-control.service.js.map +1 -1
  112. package/dist/src/services/hot-water-tank.service.d.ts +6 -2
  113. package/dist/src/services/hot-water-tank.service.d.ts.map +1 -1
  114. package/dist/src/services/hot-water-tank.service.js +31 -34
  115. package/dist/src/services/hot-water-tank.service.js.map +1 -1
  116. package/dist/src/types/daikin-enums.js +12 -12
  117. package/dist/src/types/daikin-enums.js.map +1 -1
  118. package/dist/src/types/device-capabilities.d.ts +1 -1
  119. package/dist/src/types/device-capabilities.d.ts.map +1 -1
  120. package/dist/src/utils/log-context.d.ts +23 -23
  121. package/dist/src/utils/log-context.d.ts.map +1 -1
  122. package/dist/src/utils/log-context.js +28 -28
  123. package/dist/src/utils/log-context.js.map +1 -1
  124. package/dist/src/utils/strings.d.ts.map +1 -1
  125. package/dist/src/utils/strings.js.map +1 -1
  126. package/dist/src/utils/update-mapper.d.ts +16 -16
  127. package/dist/src/utils/update-mapper.d.ts.map +1 -1
  128. package/dist/src/utils/update-mapper.js +14 -14
  129. package/dist/src/utils/update-mapper.js.map +1 -1
  130. package/homebridge-ui/public/script.js +956 -897
  131. package/homebridge-ui/server.js +739 -695
  132. package/package.json +27 -24
  133. package/.claude/settings.json +0 -3
  134. package/.claude/settings.local.json +0 -24
  135. package/CHANGELOG.md +0 -114
  136. package/CLAUDE.md +0 -269
  137. package/config.md +0 -2
  138. package/docs/ARCHITECTURE.md +0 -645
  139. package/docs/IMPLEMENTATION_GUIDE.md +0 -899
  140. package/docs/IMPROVEMENTS_SUMMARY.md +0 -415
  141. package/docs/NEXT_STEPS.md +0 -368
  142. package/docs/Screenshot 2024-07-04 at 18.41.28.png +0 -0
  143. package/docs/TROUBLESHOOTING.md +0 -475
  144. package/docs/api-response-for-BRP069A8x.json +0 -520
  145. package/docs/api-response-for-BRP069C4x-2.json +0 -881
  146. package/docs/api-response-for-BRP069C4x.json +0 -916
  147. package/docs/api-response-for-altherma.json +0 -759
  148. package/docs/api-response-for-altherma2.json +0 -2735
  149. package/docs/api-response-with-multiple-devices-incl-heatpump.json +0 -2544
  150. package/docs/cr-insance-altherma-id-0.json +0 -834
  151. package/docs/mock-air-to-air-dx23.json +0 -759
  152. package/docs/mock-air-to-air-dx4.json +0 -1134
  153. package/docs/mock-airpurifier-with-humidifier.json +0 -732
  154. package/docs/mock-airpurifier.json +0 -450
  155. package/docs/mock-altherma-air-to-water-lan.json +0 -845
  156. package/docs/mock-altherma-air-to-water-wlan.json +0 -845
  157. package/docs/mock-d2cnd-gas-boiler.json +0 -649
  158. package/docs/setpointmode-vs-controlmode-vs-setpoints-vs-sensorydata.txt +0 -6
  159. package/images/fan-speed.jpeg +0 -0
  160. package/images/homekit-controls.jpeg +0 -0
  161. package/images/homekit-settings.jpeg +0 -0
  162. package/images/swing-mode.png +0 -0
  163. package/jest.config.ts +0 -21
  164. package/test/fixtures/altherma-crSense-2.ts +0 -834
  165. package/test/fixtures/altherma-fraction.ts +0 -718
  166. package/test/fixtures/altherma-heat-pump-2.ts +0 -479
  167. package/test/fixtures/altherma-heat-pump.ts +0 -757
  168. package/test/fixtures/altherma-miladcerkic-off.ts +0 -524
  169. package/test/fixtures/altherma-miladcerkic.ts +0 -524
  170. package/test/fixtures/altherma-v1ckoeln.ts +0 -644
  171. package/test/fixtures/altherma-with-embedded-id-zero.ts +0 -834
  172. package/test/fixtures/dx23-airco-2.ts +0 -343
  173. package/test/fixtures/dx23-airco.ts +0 -518
  174. package/test/fixtures/dx4-airco.ts +0 -914
  175. package/test/fixtures/unknown-jan.ts +0 -488
  176. package/test/fixtures/unknown-kitchen-guests.ts +0 -488
  177. package/test/hbConfig/.daikin-mobile-tokenset +0 -8
  178. package/test/hbConfig/.uix-dashboard.json +0 -1
  179. package/test/hbConfig/.uix-secrets +0 -1
  180. package/test/hbConfig/accessories/.cachedAccessories.bak +0 -1
  181. package/test/hbConfig/accessories/cachedAccessories +0 -1
  182. package/test/hbConfig/accessories/uiAccessoriesLayout.json +0 -1
  183. package/test/hbConfig/auth.json +0 -10
  184. package/test/hbConfig/backups/config-backups/config.json.1767953686461 +0 -25
  185. package/test/hbConfig/backups/config-backups/config.json.1767953695236 +0 -29
  186. package/test/hbConfig/backups/config-backups/config.json.1767953814763 +0 -29
  187. package/test/hbConfig/backups/config-backups/config.json.1767953823101 +0 -29
  188. package/test/hbConfig/backups/config-backups/config.json.1767954822835 +0 -29
  189. package/test/hbConfig/backups/config-backups/config.json.1767954859218 +0 -29
  190. package/test/hbConfig/backups/config-backups/config.json.1767960145503 +0 -33
  191. package/test/hbConfig/backups/config-backups/config.json.1767960168068 +0 -44
  192. package/test/hbConfig/backups/config-backups/config.json.1767960170333 +0 -46
  193. package/test/hbConfig/backups/config-backups/config.json.1767960172731 +0 -44
  194. package/test/hbConfig/backups/config-backups/config.json.1767960179323 +0 -44
  195. package/test/hbConfig/backups/config-backups/config.json.1767960182114 +0 -44
  196. package/test/hbConfig/backups/config-backups/config.json.1767960189302 +0 -44
  197. package/test/hbConfig/backups/config-backups/config.json.1767960195194 +0 -44
  198. package/test/hbConfig/backups/config-backups/config.json.1767960197301 +0 -44
  199. package/test/hbConfig/backups/config-backups/config.json.1767960199151 +0 -44
  200. package/test/hbConfig/backups/config-backups/config.json.1767960199667 +0 -44
  201. package/test/hbConfig/backups/config-backups/config.json.1767960329839 +0 -44
  202. package/test/hbConfig/backups/config-backups/config.json.1767960334503 +0 -44
  203. package/test/hbConfig/backups/config-backups/config.json.1767960336208 +0 -44
  204. package/test/hbConfig/backups/config-backups/config.json.1767960338537 +0 -44
  205. package/test/hbConfig/backups/config-backups/config.json.1767963223953 +0 -44
  206. package/test/hbConfig/backups/config-backups/config.json.1767963241753 +0 -44
  207. package/test/hbConfig/backups/config-backups/config.json.1767963252785 +0 -44
  208. package/test/hbConfig/backups/config-backups/config.json.1767963463944 +0 -44
  209. package/test/hbConfig/backups/config-backups/config.json.1767963834475 +0 -44
  210. package/test/hbConfig/backups/config-backups/config.json.1767963838474 +0 -44
  211. package/test/hbConfig/backups/config-backups/config.json.1767963843066 +0 -44
  212. package/test/hbConfig/backups/config-backups/config.json.1767965217715 +0 -44
  213. package/test/hbConfig/backups/config-backups/config.json.1767965419624 +0 -25
  214. package/test/hbConfig/backups/config-backups/config.json.1767965870934 +0 -32
  215. package/test/hbConfig/backups/config-backups/config.json.1767977675045 +0 -32
  216. package/test/hbConfig/backups/config-backups/config.json.1767977677222 +0 -33
  217. package/test/hbConfig/backups/config-backups/config.json.1767977710226 +0 -33
  218. package/test/hbConfig/backups/config-backups/config.json.1767977741397 +0 -33
  219. package/test/hbConfig/backups/config-backups/config.json.1767977977093 +0 -35
  220. package/test/hbConfig/backups/config-backups/config.json.1767977981773 +0 -35
  221. package/test/hbConfig/backups/config-backups/config.json.1767977986514 +0 -35
  222. package/test/hbConfig/backups/config-backups/config.json.1767977991174 +0 -35
  223. package/test/hbConfig/backups/config-backups/config.json.1767979424487 +0 -35
  224. package/test/hbConfig/backups/config-backups/config.json.1767979424987 +0 -35
  225. package/test/hbConfig/backups/config-backups/config.json.1767979432646 +0 -47
  226. package/test/hbConfig/backups/config-backups/config.json.1767979433150 +0 -47
  227. package/test/hbConfig/backups/config-backups/config.json.1767979436933 +0 -47
  228. package/test/hbConfig/backups/config-backups/config.json.1767979437438 +0 -47
  229. package/test/hbConfig/backups/config-backups/config.json.1767979441676 +0 -47
  230. package/test/hbConfig/backups/config-backups/config.json.1767979442180 +0 -47
  231. package/test/hbConfig/backups/config-backups/config.json.1767979466735 +0 -47
  232. package/test/hbConfig/backups/config-backups/config.json.1767979903636 +0 -47
  233. package/test/hbConfig/backups/config-backups/config.json.1767979904135 +0 -47
  234. package/test/hbConfig/backups/config-backups/config.json.1767979906606 +0 -47
  235. package/test/hbConfig/backups/config-backups/config.json.1767979907108 +0 -47
  236. package/test/hbConfig/backups/config-backups/config.json.1767988702341 +0 -47
  237. package/test/hbConfig/backups/config-backups/config.json.1767988702837 +0 -47
  238. package/test/hbConfig/backups/config-backups/config.json.1767988713159 +0 -47
  239. package/test/hbConfig/backups/config-backups/config.json.1767988713664 +0 -47
  240. package/test/hbConfig/backups/config-backups/config.json.1767988918139 +0 -47
  241. package/test/hbConfig/backups/config-backups/config.json.1767988918639 +0 -47
  242. package/test/hbConfig/backups/config-backups/config.json.1767988921120 +0 -47
  243. package/test/hbConfig/backups/config-backups/config.json.1767988921624 +0 -47
  244. package/test/hbConfig/backups/config-backups/config.json.1767988930307 +0 -47
  245. package/test/hbConfig/backups/config-backups/config.json.1767988935070 +0 -47
  246. package/test/hbConfig/backups/config-backups/config.json.1767988935574 +0 -47
  247. package/test/hbConfig/backups/config-backups/config.json.1767989710262 +0 -47
  248. package/test/hbConfig/backups/config-backups/config.json.1767989710760 +0 -47
  249. package/test/hbConfig/backups/config-backups/config.json.1767989729668 +0 -47
  250. package/test/hbConfig/backups/config-backups/config.json.1767990295225 +0 -47
  251. package/test/hbConfig/backups/config-backups/config.json.1767990479921 +0 -47
  252. package/test/hbConfig/backups/config-backups/config.json.1767990481702 +0 -49
  253. package/test/hbConfig/backups/instance-backups/homebridge-backup-1E4A432551BA.1768010187391.tar.gz +0 -0
  254. package/test/hbConfig/backups/instance-backups/homebridge-backup-1E4A432551BA.1768096587387.tar.gz +0 -0
  255. package/test/hbConfig/backups/instance-backups/homebridge-backup-1E4A432551BA.1768182987404.tar.gz +0 -0
  256. package/test/hbConfig/config.json +0 -47
  257. package/test/hbConfig/daikin-cloud-certs/server.crt +0 -22
  258. package/test/hbConfig/daikin-cloud-certs/server.key +0 -28
  259. package/test/hbConfig/persist/AccessoryInfo.1E4A432551BA.json +0 -1
  260. package/test/hbConfig/persist/IdentifierCache.1E4A432551BA.json +0 -1
  261. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14758 +0 -1
  262. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14759 +0 -1
  263. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14760 +0 -1
  264. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14761 +0 -1
  265. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14762 +0 -1
  266. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14764 +0 -1
  267. package/test/helpers/test-isolation.ts +0 -228
  268. package/test/integration/air-conditioning.test.ts +0 -396
  269. package/test/integration/altherma.test.ts +0 -279
  270. package/test/integration/platform.test.ts +0 -118
  271. package/test/mobile-tokens.json +0 -8
  272. package/test/mocks/index.ts +0 -27
  273. package/test/test-gigya-auth.js +0 -443
  274. package/test/test-mobile-oauth.js +0 -175
  275. package/test/test-websocket-mobile.js +0 -123
  276. package/test/test-websocket.js +0 -116
  277. package/test/unit/api/__snapshots__/daikinCloud.test.ts.snap +0 -1320
  278. package/test/unit/api/daikin-api.test.ts +0 -442
  279. package/test/unit/api/daikin-cloud-repository.test.ts +0 -107
  280. package/test/unit/api/daikin-oauth.test.ts +0 -214
  281. package/test/unit/api/daikinCloud.test.ts +0 -12
  282. package/test/unit/api/token-storage.test.ts +0 -90
  283. package/test/unit/config/config-manager.test.ts +0 -271
  284. package/test/unit/device/daikin-device.test.ts +0 -73
  285. package/test/unit/services/hot-water-tank.service.test.ts +0 -123
  286. package/test/unit/utils/log-context.test.ts +0 -271
  287. package/test/unit/utils/update-mapper.test.ts +0 -404
@@ -1,404 +0,0 @@
1
- import {UpdateMapper, DeviceUpdate} from '../../../src/utils/update-mapper';
2
-
3
- // Mock homebridge types
4
- const mockLogger = {
5
- debug: jest.fn(),
6
- info: jest.fn(),
7
- warn: jest.fn(),
8
- error: jest.fn(),
9
- log: jest.fn(),
10
- success: jest.fn(),
11
- };
12
-
13
- // Mock characteristic values
14
- const CharacteristicMock = {
15
- Active: Object.assign(jest.fn(), {ACTIVE: 1, INACTIVE: 0}),
16
- CurrentHeaterCoolerState: Object.assign(jest.fn(), {INACTIVE: 0, IDLE: 1, HEATING: 2, COOLING: 3}),
17
- TargetHeaterCoolerState: Object.assign(jest.fn(), {AUTO: 0, HEAT: 1, COOL: 2}),
18
- CurrentHeatingCoolingState: Object.assign(jest.fn(), {OFF: 0, HEAT: 1, COOL: 2}),
19
- TargetHeatingCoolingState: Object.assign(jest.fn(), {OFF: 0, HEAT: 1, COOL: 2, AUTO: 3}),
20
- CurrentTemperature: jest.fn(),
21
- HeatingThresholdTemperature: jest.fn(),
22
- CoolingThresholdTemperature: jest.fn(),
23
- };
24
-
25
- const ServiceMock = {
26
- HeaterCooler: 'HeaterCooler',
27
- Thermostat: 'Thermostat',
28
- };
29
-
30
- function createMockAccessory(serviceType: string, deviceData: Record<string, unknown> = {}) {
31
- const updatedCharacteristics: Array<{char: unknown; value: unknown}> = [];
32
- const mockService = {
33
- updateCharacteristic: jest.fn((char, value) => {
34
- updatedCharacteristics.push({char, value});
35
- }),
36
- };
37
-
38
- return {
39
- accessory: {
40
- getService: jest.fn((type: string) => {
41
- if (type === serviceType) {
42
- return mockService;
43
- }
44
- return undefined;
45
- }),
46
- context: {
47
- device: {
48
- getId: () => 'device-1',
49
- getData: (embeddedId: string, dataPoint: string) => {
50
- return deviceData[dataPoint] || {value: undefined};
51
- },
52
- },
53
- },
54
- } as any,
55
- mockService,
56
- updatedCharacteristics,
57
- };
58
- }
59
-
60
- describe('UpdateMapper', () => {
61
- let mapper: UpdateMapper;
62
-
63
- beforeEach(() => {
64
- jest.clearAllMocks();
65
- mapper = new UpdateMapper(mockLogger as any, ServiceMock as any, CharacteristicMock as any);
66
- });
67
-
68
- describe('applyUpdate', () => {
69
- it('should return unsuccessful result when no service found', () => {
70
- const {accessory} = createMockAccessory('UnknownService');
71
- const update: DeviceUpdate = {
72
- deviceId: 'device-1',
73
- embeddedId: 'climateControl',
74
- characteristicName: 'onOffMode',
75
- data: {value: 'on'},
76
- };
77
-
78
- const result = mapper.applyUpdate(accessory, update);
79
- expect(result.success).toBe(false);
80
- expect(result.updated).toHaveLength(0);
81
- });
82
-
83
- describe('onOffMode updates', () => {
84
- it('should update HeaterCooler Active to ACTIVE when turned on', () => {
85
- const {accessory, mockService} = createMockAccessory('HeaterCooler');
86
- const update: DeviceUpdate = {
87
- deviceId: 'device-1',
88
- embeddedId: 'climateControl',
89
- characteristicName: 'onOffMode',
90
- data: {value: 'on'},
91
- };
92
-
93
- const result = mapper.applyUpdate(accessory, update);
94
- expect(result.success).toBe(true);
95
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
96
- CharacteristicMock.Active,
97
- CharacteristicMock.Active.ACTIVE,
98
- );
99
- });
100
-
101
- it('should update HeaterCooler Active to INACTIVE and state when turned off', () => {
102
- const {accessory, mockService} = createMockAccessory('HeaterCooler');
103
- const update: DeviceUpdate = {
104
- deviceId: 'device-1',
105
- embeddedId: 'climateControl',
106
- characteristicName: 'onOffMode',
107
- data: {value: 'off'},
108
- };
109
-
110
- const result = mapper.applyUpdate(accessory, update);
111
- expect(result.success).toBe(true);
112
- expect(result.updated).toContain('Active=INACTIVE');
113
- expect(result.updated).toContain('CurrentHeaterCoolerState=INACTIVE');
114
- expect(mockService.updateCharacteristic).toHaveBeenCalledTimes(2);
115
- });
116
-
117
- it('should update Thermostat CurrentHeatingCoolingState when turned off', () => {
118
- const {accessory, mockService} = createMockAccessory('Thermostat', {
119
- operationMode: {value: 'heating'},
120
- });
121
- const update: DeviceUpdate = {
122
- deviceId: 'device-1',
123
- embeddedId: 'climateControl',
124
- characteristicName: 'onOffMode',
125
- data: {value: 'off'},
126
- };
127
-
128
- const result = mapper.applyUpdate(accessory, update);
129
- expect(result.success).toBe(true);
130
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
131
- CharacteristicMock.CurrentHeatingCoolingState,
132
- CharacteristicMock.CurrentHeatingCoolingState.OFF,
133
- );
134
- });
135
-
136
- it('should map heating operation mode for thermostat when on', () => {
137
- const {accessory, mockService} = createMockAccessory('Thermostat', {
138
- operationMode: {value: 'heating'},
139
- });
140
- const update: DeviceUpdate = {
141
- deviceId: 'device-1',
142
- embeddedId: 'climateControl',
143
- characteristicName: 'onOffMode',
144
- data: {value: 'on'},
145
- };
146
-
147
- const result = mapper.applyUpdate(accessory, update);
148
- expect(result.success).toBe(true);
149
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
150
- CharacteristicMock.CurrentHeatingCoolingState,
151
- CharacteristicMock.CurrentHeatingCoolingState.HEAT,
152
- );
153
- });
154
-
155
- it('should map cooling operation mode for thermostat when on', () => {
156
- const {accessory, mockService} = createMockAccessory('Thermostat', {
157
- operationMode: {value: 'cooling'},
158
- });
159
- const update: DeviceUpdate = {
160
- deviceId: 'device-1',
161
- embeddedId: 'climateControl',
162
- characteristicName: 'onOffMode',
163
- data: {value: 'on'},
164
- };
165
-
166
- const result = mapper.applyUpdate(accessory, update);
167
- expect(result.success).toBe(true);
168
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
169
- CharacteristicMock.CurrentHeatingCoolingState,
170
- CharacteristicMock.CurrentHeatingCoolingState.COOL,
171
- );
172
- });
173
- });
174
-
175
- describe('operationMode updates', () => {
176
- it('should not update target state when device is off', () => {
177
- const {accessory, mockService} = createMockAccessory('HeaterCooler', {
178
- onOffMode: {value: 'off'},
179
- });
180
- const update: DeviceUpdate = {
181
- deviceId: 'device-1',
182
- embeddedId: 'climateControl',
183
- characteristicName: 'operationMode',
184
- data: {value: 'cooling'},
185
- };
186
-
187
- const result = mapper.applyUpdate(accessory, update);
188
- expect(result.success).toBe(false);
189
- expect(mockService.updateCharacteristic).not.toHaveBeenCalled();
190
- });
191
-
192
- it('should map cooling mode to HeaterCooler COOL', () => {
193
- const {accessory, mockService} = createMockAccessory('HeaterCooler', {
194
- onOffMode: {value: 'on'},
195
- });
196
- const update: DeviceUpdate = {
197
- deviceId: 'device-1',
198
- embeddedId: 'climateControl',
199
- characteristicName: 'operationMode',
200
- data: {value: 'cooling'},
201
- };
202
-
203
- const result = mapper.applyUpdate(accessory, update);
204
- expect(result.success).toBe(true);
205
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
206
- CharacteristicMock.TargetHeaterCoolerState,
207
- CharacteristicMock.TargetHeaterCoolerState.COOL,
208
- );
209
- });
210
-
211
- it('should map heating mode to HeaterCooler HEAT', () => {
212
- const {accessory, mockService} = createMockAccessory('HeaterCooler', {
213
- onOffMode: {value: 'on'},
214
- });
215
- const update: DeviceUpdate = {
216
- deviceId: 'device-1',
217
- embeddedId: 'climateControl',
218
- characteristicName: 'operationMode',
219
- data: {value: 'heating'},
220
- };
221
-
222
- const result = mapper.applyUpdate(accessory, update);
223
- expect(result.success).toBe(true);
224
- expect(result.updated).toContain('TargetHeaterCoolerState=1');
225
- expect(result.updated).toContain('CurrentHeaterCoolerState=2');
226
- });
227
-
228
- it('should map auto mode to HeaterCooler AUTO', () => {
229
- const {accessory, mockService} = createMockAccessory('HeaterCooler', {
230
- onOffMode: {value: 'on'},
231
- });
232
- const update: DeviceUpdate = {
233
- deviceId: 'device-1',
234
- embeddedId: 'climateControl',
235
- characteristicName: 'operationMode',
236
- data: {value: 'auto'},
237
- };
238
-
239
- const result = mapper.applyUpdate(accessory, update);
240
- expect(result.success).toBe(true);
241
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
242
- CharacteristicMock.TargetHeaterCoolerState,
243
- CharacteristicMock.TargetHeaterCoolerState.AUTO,
244
- );
245
- });
246
-
247
- it('should handle unknown operation mode gracefully', () => {
248
- const {accessory, mockService} = createMockAccessory('HeaterCooler', {
249
- onOffMode: {value: 'on'},
250
- });
251
- const update: DeviceUpdate = {
252
- deviceId: 'device-1',
253
- embeddedId: 'climateControl',
254
- characteristicName: 'operationMode',
255
- data: {value: 'dry'},
256
- };
257
-
258
- const result = mapper.applyUpdate(accessory, update);
259
- expect(result.success).toBe(false);
260
- expect(mockService.updateCharacteristic).not.toHaveBeenCalled();
261
- });
262
-
263
- it('should map cooling mode for thermostat', () => {
264
- const {accessory, mockService} = createMockAccessory('Thermostat', {
265
- onOffMode: {value: 'on'},
266
- });
267
- const update: DeviceUpdate = {
268
- deviceId: 'device-1',
269
- embeddedId: 'climateControl',
270
- characteristicName: 'operationMode',
271
- data: {value: 'cooling'},
272
- };
273
-
274
- const result = mapper.applyUpdate(accessory, update);
275
- expect(result.success).toBe(true);
276
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
277
- CharacteristicMock.TargetHeatingCoolingState,
278
- CharacteristicMock.TargetHeatingCoolingState.COOL,
279
- );
280
- });
281
- });
282
-
283
- describe('sensoryData updates', () => {
284
- it('should update current temperature from roomTemperature', () => {
285
- const {accessory, mockService} = createMockAccessory('HeaterCooler');
286
- const update: DeviceUpdate = {
287
- deviceId: 'device-1',
288
- embeddedId: 'climateControl',
289
- characteristicName: 'sensoryData',
290
- data: {value: {roomTemperature: {value: 22.5}}},
291
- };
292
-
293
- const result = mapper.applyUpdate(accessory, update);
294
- expect(result.success).toBe(true);
295
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
296
- CharacteristicMock.CurrentTemperature,
297
- 22.5,
298
- );
299
- });
300
-
301
- it('should not update when sensoryData has no roomTemperature', () => {
302
- const {accessory, mockService} = createMockAccessory('HeaterCooler');
303
- const update: DeviceUpdate = {
304
- deviceId: 'device-1',
305
- embeddedId: 'climateControl',
306
- characteristicName: 'sensoryData',
307
- data: {value: {outdoorTemperature: {value: 15}}},
308
- };
309
-
310
- const result = mapper.applyUpdate(accessory, update);
311
- expect(result.success).toBe(false);
312
- expect(mockService.updateCharacteristic).not.toHaveBeenCalled();
313
- });
314
- });
315
-
316
- describe('temperatureControl updates', () => {
317
- it('should update heating threshold temperature', () => {
318
- const {accessory, mockService} = createMockAccessory('HeaterCooler');
319
- const update: DeviceUpdate = {
320
- deviceId: 'device-1',
321
- embeddedId: 'climateControl',
322
- characteristicName: 'temperatureControl',
323
- data: {
324
- value: {
325
- operationModes: {
326
- heating: {setpoints: {roomTemperature: {value: 22}}},
327
- },
328
- },
329
- },
330
- };
331
-
332
- const result = mapper.applyUpdate(accessory, update);
333
- expect(result.success).toBe(true);
334
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
335
- CharacteristicMock.HeatingThresholdTemperature,
336
- 22,
337
- );
338
- });
339
-
340
- it('should update cooling threshold temperature', () => {
341
- const {accessory, mockService} = createMockAccessory('HeaterCooler');
342
- const update: DeviceUpdate = {
343
- deviceId: 'device-1',
344
- embeddedId: 'climateControl',
345
- characteristicName: 'temperatureControl',
346
- data: {
347
- value: {
348
- operationModes: {
349
- cooling: {setpoints: {roomTemperature: {value: 26}}},
350
- },
351
- },
352
- },
353
- };
354
-
355
- const result = mapper.applyUpdate(accessory, update);
356
- expect(result.success).toBe(true);
357
- expect(mockService.updateCharacteristic).toHaveBeenCalledWith(
358
- CharacteristicMock.CoolingThresholdTemperature,
359
- 26,
360
- );
361
- });
362
-
363
- it('should update both heating and cooling thresholds', () => {
364
- const {accessory, mockService} = createMockAccessory('HeaterCooler');
365
- const update: DeviceUpdate = {
366
- deviceId: 'device-1',
367
- embeddedId: 'climateControl',
368
- characteristicName: 'temperatureControl',
369
- data: {
370
- value: {
371
- operationModes: {
372
- heating: {setpoints: {roomTemperature: {value: 20}}},
373
- cooling: {setpoints: {roomTemperature: {value: 28}}},
374
- },
375
- },
376
- },
377
- };
378
-
379
- const result = mapper.applyUpdate(accessory, update);
380
- expect(result.success).toBe(true);
381
- expect(result.updated).toHaveLength(2);
382
- expect(mockService.updateCharacteristic).toHaveBeenCalledTimes(2);
383
- });
384
- });
385
-
386
- describe('unhandled characteristics', () => {
387
- it('should log debug message for unknown characteristic', () => {
388
- const {accessory} = createMockAccessory('HeaterCooler');
389
- const update: DeviceUpdate = {
390
- deviceId: 'device-1',
391
- embeddedId: 'climateControl',
392
- characteristicName: 'unknownCharacteristic',
393
- data: {value: 'something'},
394
- };
395
-
396
- const result = mapper.applyUpdate(accessory, update);
397
- expect(result.success).toBe(false);
398
- expect(mockLogger.debug).toHaveBeenCalledWith(
399
- expect.stringContaining('Unhandled characteristic'),
400
- );
401
- });
402
- });
403
- });
404
- });