@mp-consulting/homebridge-daikin-cloud 1.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 (202) hide show
  1. package/.claude/settings.json +3 -0
  2. package/.claude/settings.local.json +8 -0
  3. package/CLAUDE.md +34 -0
  4. package/LICENSE +176 -0
  5. package/README.md +180 -0
  6. package/changelog.md +217 -0
  7. package/config.md +2 -0
  8. package/config.schema.json +146 -0
  9. package/dist/src/accessories/air-conditioning-accessory.d.ts +9 -0
  10. package/dist/src/accessories/air-conditioning-accessory.d.ts.map +1 -0
  11. package/dist/src/accessories/air-conditioning-accessory.js +19 -0
  12. package/dist/src/accessories/air-conditioning-accessory.js.map +1 -0
  13. package/dist/src/accessories/altherma-accessory.d.ts +11 -0
  14. package/dist/src/accessories/altherma-accessory.d.ts.map +1 -0
  15. package/dist/src/accessories/altherma-accessory.js +31 -0
  16. package/dist/src/accessories/altherma-accessory.js.map +1 -0
  17. package/dist/src/accessories/base-accessory.d.ts +16 -0
  18. package/dist/src/accessories/base-accessory.d.ts.map +1 -0
  19. package/dist/src/accessories/base-accessory.js +56 -0
  20. package/dist/src/accessories/base-accessory.js.map +1 -0
  21. package/dist/src/accessories/index.d.ts +4 -0
  22. package/dist/src/accessories/index.d.ts.map +1 -0
  23. package/dist/src/accessories/index.js +20 -0
  24. package/dist/src/accessories/index.js.map +1 -0
  25. package/dist/src/api/daikin-cloud.repository.d.ts +4 -0
  26. package/dist/src/api/daikin-cloud.repository.d.ts.map +1 -0
  27. package/dist/src/api/daikin-cloud.repository.js +31 -0
  28. package/dist/src/api/daikin-cloud.repository.js.map +1 -0
  29. package/dist/src/api/index.d.ts +2 -0
  30. package/dist/src/api/index.d.ts.map +1 -0
  31. package/dist/src/api/index.js +18 -0
  32. package/dist/src/api/index.js.map +1 -0
  33. package/dist/src/device/accessory-factory.d.ts +36 -0
  34. package/dist/src/device/accessory-factory.d.ts.map +1 -0
  35. package/dist/src/device/accessory-factory.js +61 -0
  36. package/dist/src/device/accessory-factory.js.map +1 -0
  37. package/dist/src/device/capability-detector.d.ts +36 -0
  38. package/dist/src/device/capability-detector.d.ts.map +1 -0
  39. package/dist/src/device/capability-detector.js +130 -0
  40. package/dist/src/device/capability-detector.js.map +1 -0
  41. package/dist/src/device/capability-docs.d.ts +20 -0
  42. package/dist/src/device/capability-docs.d.ts.map +1 -0
  43. package/dist/src/device/capability-docs.js +98 -0
  44. package/dist/src/device/capability-docs.js.map +1 -0
  45. package/dist/src/device/index.d.ts +5 -0
  46. package/dist/src/device/index.d.ts.map +1 -0
  47. package/dist/src/device/index.js +21 -0
  48. package/dist/src/device/index.js.map +1 -0
  49. package/dist/src/device/profiles/device-profile.d.ts +42 -0
  50. package/dist/src/device/profiles/device-profile.d.ts.map +1 -0
  51. package/dist/src/device/profiles/device-profile.js +103 -0
  52. package/dist/src/device/profiles/device-profile.js.map +1 -0
  53. package/dist/src/device/profiles/index.d.ts +2 -0
  54. package/dist/src/device/profiles/index.d.ts.map +1 -0
  55. package/dist/src/device/profiles/index.js +18 -0
  56. package/dist/src/device/profiles/index.js.map +1 -0
  57. package/dist/src/features/base-feature.d.ts +65 -0
  58. package/dist/src/features/base-feature.d.ts.map +1 -0
  59. package/dist/src/features/base-feature.js +99 -0
  60. package/dist/src/features/base-feature.js.map +1 -0
  61. package/dist/src/features/feature-manager.d.ts +37 -0
  62. package/dist/src/features/feature-manager.d.ts.map +1 -0
  63. package/dist/src/features/feature-manager.js +68 -0
  64. package/dist/src/features/feature-manager.js.map +1 -0
  65. package/dist/src/features/index.d.ts +4 -0
  66. package/dist/src/features/index.d.ts.map +1 -0
  67. package/dist/src/features/index.js +20 -0
  68. package/dist/src/features/index.js.map +1 -0
  69. package/dist/src/features/modes/dry-operation-mode.feature.d.ts +16 -0
  70. package/dist/src/features/modes/dry-operation-mode.feature.d.ts.map +1 -0
  71. package/dist/src/features/modes/dry-operation-mode.feature.js +40 -0
  72. package/dist/src/features/modes/dry-operation-mode.feature.js.map +1 -0
  73. package/dist/src/features/modes/econo-mode.feature.d.ts +15 -0
  74. package/dist/src/features/modes/econo-mode.feature.d.ts.map +1 -0
  75. package/dist/src/features/modes/econo-mode.feature.js +37 -0
  76. package/dist/src/features/modes/econo-mode.feature.js.map +1 -0
  77. package/dist/src/features/modes/fan-only-operation-mode.feature.d.ts +16 -0
  78. package/dist/src/features/modes/fan-only-operation-mode.feature.d.ts.map +1 -0
  79. package/dist/src/features/modes/fan-only-operation-mode.feature.js +40 -0
  80. package/dist/src/features/modes/fan-only-operation-mode.feature.js.map +1 -0
  81. package/dist/src/features/modes/index.d.ts +8 -0
  82. package/dist/src/features/modes/index.d.ts.map +1 -0
  83. package/dist/src/features/modes/index.js +24 -0
  84. package/dist/src/features/modes/index.js.map +1 -0
  85. package/dist/src/features/modes/indoor-silent-mode.feature.d.ts +17 -0
  86. package/dist/src/features/modes/indoor-silent-mode.feature.d.ts.map +1 -0
  87. package/dist/src/features/modes/indoor-silent-mode.feature.js +47 -0
  88. package/dist/src/features/modes/indoor-silent-mode.feature.js.map +1 -0
  89. package/dist/src/features/modes/outdoor-silent-mode.feature.d.ts +15 -0
  90. package/dist/src/features/modes/outdoor-silent-mode.feature.d.ts.map +1 -0
  91. package/dist/src/features/modes/outdoor-silent-mode.feature.js +37 -0
  92. package/dist/src/features/modes/outdoor-silent-mode.feature.js.map +1 -0
  93. package/dist/src/features/modes/powerful-mode.feature.d.ts +15 -0
  94. package/dist/src/features/modes/powerful-mode.feature.d.ts.map +1 -0
  95. package/dist/src/features/modes/powerful-mode.feature.js +37 -0
  96. package/dist/src/features/modes/powerful-mode.feature.js.map +1 -0
  97. package/dist/src/features/modes/streamer-mode.feature.d.ts +15 -0
  98. package/dist/src/features/modes/streamer-mode.feature.d.ts.map +1 -0
  99. package/dist/src/features/modes/streamer-mode.feature.js +37 -0
  100. package/dist/src/features/modes/streamer-mode.feature.js.map +1 -0
  101. package/dist/src/index.d.ts +7 -0
  102. package/dist/src/index.d.ts.map +1 -0
  103. package/dist/src/index.js +7 -0
  104. package/dist/src/index.js.map +1 -0
  105. package/dist/src/platform.d.ts +33 -0
  106. package/dist/src/platform.d.ts.map +1 -0
  107. package/dist/src/platform.js +209 -0
  108. package/dist/src/platform.js.map +1 -0
  109. package/dist/src/services/climate-control.service.d.ts +43 -0
  110. package/dist/src/services/climate-control.service.d.ts.map +1 -0
  111. package/dist/src/services/climate-control.service.js +366 -0
  112. package/dist/src/services/climate-control.service.js.map +1 -0
  113. package/dist/src/services/hot-water-tank.service.d.ts +23 -0
  114. package/dist/src/services/hot-water-tank.service.d.ts.map +1 -0
  115. package/dist/src/services/hot-water-tank.service.js +214 -0
  116. package/dist/src/services/hot-water-tank.service.js.map +1 -0
  117. package/dist/src/services/index.d.ts +3 -0
  118. package/dist/src/services/index.d.ts.map +1 -0
  119. package/dist/src/services/index.js +19 -0
  120. package/dist/src/services/index.js.map +1 -0
  121. package/dist/src/settings.d.ts +9 -0
  122. package/dist/src/settings.d.ts.map +1 -0
  123. package/dist/src/settings.js +12 -0
  124. package/dist/src/settings.js.map +1 -0
  125. package/dist/src/types/daikin-enums.d.ts +61 -0
  126. package/dist/src/types/daikin-enums.d.ts.map +1 -0
  127. package/dist/src/types/daikin-enums.js +76 -0
  128. package/dist/src/types/daikin-enums.js.map +1 -0
  129. package/dist/src/types/device-capabilities.d.ts +47 -0
  130. package/dist/src/types/device-capabilities.d.ts.map +1 -0
  131. package/dist/src/types/device-capabilities.js +7 -0
  132. package/dist/src/types/device-capabilities.js.map +1 -0
  133. package/dist/src/types/index.d.ts +3 -0
  134. package/dist/src/types/index.d.ts.map +1 -0
  135. package/dist/src/types/index.js +19 -0
  136. package/dist/src/types/index.js.map +1 -0
  137. package/dist/src/utils/strings.d.ts +5 -0
  138. package/dist/src/utils/strings.d.ts.map +1 -0
  139. package/dist/src/utils/strings.js +22 -0
  140. package/dist/src/utils/strings.js.map +1 -0
  141. package/docs/Screenshot 2024-07-04 at 18.41.28.png +0 -0
  142. package/docs/api-response-for-BRP069A8x.json +520 -0
  143. package/docs/api-response-for-BRP069C4x-2.json +881 -0
  144. package/docs/api-response-for-BRP069C4x.json +916 -0
  145. package/docs/api-response-for-altherma.json +759 -0
  146. package/docs/api-response-for-altherma2.json +2735 -0
  147. package/docs/api-response-with-multiple-devices-incl-heatpump.json +2544 -0
  148. package/docs/cr-insance-altherma-id-0.json +834 -0
  149. package/docs/mock-air-to-air-dx23.json +759 -0
  150. package/docs/mock-air-to-air-dx4.json +1134 -0
  151. package/docs/mock-airpurifier-with-humidifier.json +732 -0
  152. package/docs/mock-airpurifier.json +450 -0
  153. package/docs/mock-altherma-air-to-water-lan.json +845 -0
  154. package/docs/mock-altherma-air-to-water-wlan.json +845 -0
  155. package/docs/mock-d2cnd-gas-boiler.json +649 -0
  156. package/docs/setpointmode-vs-controlmode-vs-setpoints-vs-sensorydata.txt +6 -0
  157. package/homebridge-ui/README.md +35 -0
  158. package/homebridge-ui/public/index.html +222 -0
  159. package/homebridge-ui/public/script.js +796 -0
  160. package/homebridge-ui/public/styles.css +456 -0
  161. package/homebridge-ui/server.js +909 -0
  162. package/jest.config.ts +13 -0
  163. package/package.json +63 -0
  164. package/test/fixtures/altherma-crSense-2.ts +834 -0
  165. package/test/fixtures/altherma-fraction.ts +719 -0
  166. package/test/fixtures/altherma-heat-pump-2.ts +479 -0
  167. package/test/fixtures/altherma-heat-pump.ts +758 -0
  168. package/test/fixtures/altherma-miladcerkic-off.ts +524 -0
  169. package/test/fixtures/altherma-miladcerkic.ts +524 -0
  170. package/test/fixtures/altherma-v1ckoeln.ts +645 -0
  171. package/test/fixtures/altherma-with-embedded-id-zero.ts +834 -0
  172. package/test/fixtures/dx23-airco-2.ts +343 -0
  173. package/test/fixtures/dx23-airco.ts +519 -0
  174. package/test/fixtures/dx4-airco.ts +915 -0
  175. package/test/fixtures/unknown-jan.ts +489 -0
  176. package/test/fixtures/unknown-kitchen-guests.ts +489 -0
  177. package/test/hbConfig/.daikin-controller-cloud-tokenset +8 -0
  178. package/test/hbConfig/.uix-dashboard.json +1 -0
  179. package/test/hbConfig/.uix-secrets +1 -0
  180. package/test/hbConfig/accessories/.cachedAccessories.bak +1 -0
  181. package/test/hbConfig/accessories/cachedAccessories +1 -0
  182. package/test/hbConfig/accessories/uiAccessoriesLayout.json +1 -0
  183. package/test/hbConfig/auth.json +10 -0
  184. package/test/hbConfig/backups/config-backups/config.json.1767953686461 +25 -0
  185. package/test/hbConfig/backups/config-backups/config.json.1767953695236 +29 -0
  186. package/test/hbConfig/backups/config-backups/config.json.1767953814763 +29 -0
  187. package/test/hbConfig/backups/config-backups/config.json.1767953823101 +29 -0
  188. package/test/hbConfig/backups/config-backups/config.json.1767954822835 +29 -0
  189. package/test/hbConfig/backups/config-backups/config.json.1767954859218 +29 -0
  190. package/test/hbConfig/config.json +33 -0
  191. package/test/hbConfig/daikin-cloud-certs/server.crt +22 -0
  192. package/test/hbConfig/daikin-cloud-certs/server.key +28 -0
  193. package/test/hbConfig/persist/AccessoryInfo.1E4A432551BA.json +1 -0
  194. package/test/hbConfig/persist/IdentifierCache.1E4A432551BA.json +1 -0
  195. package/test/integration/air-conditioning.test.ts +396 -0
  196. package/test/integration/altherma.test.ts +288 -0
  197. package/test/integration/platform.test.ts +101 -0
  198. package/test/mocks/index.ts +27 -0
  199. package/test/unit/api/__snapshots__/daikinCloud.test.ts.snap +1323 -0
  200. package/test/unit/api/daikinCloud.test.ts +12 -0
  201. package/test/unit/device/daikin-device.test.ts +29 -0
  202. package/test/unit/services/hot-water-tank.service.test.ts +107 -0
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCs/AmLOm9PmFfu
3
+ clbD8MevmxDQAryG7PdyEhQ0xnl+JaZ98mRbIxgzY9DuVjV/if9DYTKBNfEbZwzd
4
+ cst1RdvCbV87hqDfcE9FxOtNSINXbJ64KXTFv/TqPGmh2NgZ/UZ5sKd14i8dIV59
5
+ 7rJcWqk/CYCQgBwd3O3wN4DbOWAkYtpnR+Xifj4/gXBrx8RJloCD6wzCoGs23qgf
6
+ et1ry0thL8UssNFurdlRdzZPXQc9ICOLYQ6Fdok2WJgKYYRoxcIWW+zShwAjf8Vm
7
+ JF+Rr2SNzPrVF8WYgmkLTHLsB5ezIrQ0CHKLRVcjJO8P6A0weRHzNsij8mywhYaJ
8
+ jhT373lJAgMBAAECggEAF0rOnC0vnMeWG3jQ3wxWTvpxvpiHuyFARl9R0jNhW4+F
9
+ RhMz2SO2GAFaOiVoibZSpUd6rfRN9VMgY9cXt0BDUYA5oQHFOqDcQ7g6uMrJSKXL
10
+ D2AhpZjtyPZ+gLj6jDFS4oLbYZ+lmWYLW6ie4pmgjWjho1Nktc6wSTaoBpzIqc1e
11
+ siHOh0N8xMwE7yW4EmJsjbmfrRRjRiTLO7qDDzAn8as0GPJZkSBnWxmPRtllePOy
12
+ p6b4L2luC/LIYCDYvbuT/J9jIpCsNKNjCSqCrG565/qK87sqpOiwpuFFlg0MmXIQ
13
+ JqLLFx03GdkZ4IniPCmWKKoPKo51I9DyQrpzofY7CQKBgQDr0ODikcGpmy50l5oD
14
+ a5toppe0vOQjkyNQ3Qo3JxXfTkKyw3AmIZrpSz20m0DGsQBewYtO5V7+w5tL6SUp
15
+ UVdx2l0qd5s+NplaXAoHhx3AkyP3nauTuSX9UGqcY1J50Dagt28AgjJTDwHGX+PU
16
+ rcPmTc6MIT+rLW0rSgMeUy6dfQKBgQC7ymrhkxUW8nvPC/1jGnPdPsetaGlfg5Yq
17
+ /UmJFBEiRvdKTzBDdb8+bJMqhCbNcIQY4PAb5UNnxSXPwF1M9hbIkAbUv7ybsgzh
18
+ ae/C/SWy0aucaT5+MizfFjkLInFb9Cn7IH5qeyIfvO1PQKOUfGN/ZCDGWU/L7uxf
19
+ 9RFQPnBEvQKBgDVfTFbbaHqrvcLzwQ7/Huh7tCBbFEOc/MRDkxlShlfJTb1KEKsA
20
+ tiARQIENFoch7pSDt7T+oxaETTTMKvYEDAefxbBj68YT83eJF1gG08wPQXe8vuWr
21
+ ZRbFSavlqvgZERQlEEGMNjmoTt2IPHeZcJpCh/odWFy05l2C3dvSNd29AoGBAIa5
22
+ JE6qv4GT+wDCQEneC2uZg5VDh/1PIOe8iQn/zH8D3JuCDkUHb2lwaXAiGNhgNVTH
23
+ 41qP8vi6dnMCNa1mC1heA5iT6dLlPNpmruz7whT02SJAWuYcRxbREaGMVzk6BPg2
24
+ CpuHtSaB2tp1rCV1y8fz5JOINXg/83KwFXi1IsQdAoGBAIl4PI8jqDWbd+SWG3Vx
25
+ yqes/uaTlPnODCyxtqjA4V8xgEErG6prVOc7hTN1dKzAj5qaAKgOtQ5/T6+vXOPe
26
+ a+UUSWF4udMKJMRxuv8zhzfz04eRJ3ChKysJsRFIn11FcFUd+aAE5GCHvlnHbKGa
27
+ ofNrO9Hr8WHSpXvKJvS3TD4D
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1 @@
1
+ {"displayName":"DaikinTestBridge 7CDB","category":2,"pincode":"936-00-764","signSk":"c7c0e694c8017fbfa3cccdc6443357e8c83bb68e06c62e91c2abc0eb74e3f8bd5b8f4b79d502b500a1df747c84a3e47552bdc74602bbad0e9fe2d36cf2da050f","signPk":"5b8f4b79d502b500a1df747c84a3e47552bdc74602bbad0e9fe2d36cf2da050f","pairedClients":{},"pairedClientsPermission":{},"configVersion":3,"configHash":"6c01b7fe4cecf93a8c540ec885f11bd5d281af9b","setupID":"RQNF","lastFirmwareVersion":"0.12.2"}
@@ -0,0 +1 @@
1
+ {"cache":{"f6f986a8-ae40-4f38-aa34-4b232ed91fca|nextIID":10,"f6f986a8-ae40-4f38-aa34-4b232ed91fca|0000003E-0000-1000-8000-0026BB765291|00000014-0000-1000-8000-0026BB765291":2,"f6f986a8-ae40-4f38-aa34-4b232ed91fca|0000003E-0000-1000-8000-0026BB765291|00000020-0000-1000-8000-0026BB765291":3,"f6f986a8-ae40-4f38-aa34-4b232ed91fca|0000003E-0000-1000-8000-0026BB765291|00000021-0000-1000-8000-0026BB765291":4,"f6f986a8-ae40-4f38-aa34-4b232ed91fca|0000003E-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":5,"f6f986a8-ae40-4f38-aa34-4b232ed91fca|0000003E-0000-1000-8000-0026BB765291|00000030-0000-1000-8000-0026BB765291":6,"f6f986a8-ae40-4f38-aa34-4b232ed91fca|0000003E-0000-1000-8000-0026BB765291|00000052-0000-1000-8000-0026BB765291":7,"f6f986a8-ae40-4f38-aa34-4b232ed91fca|000000A2-0000-1000-8000-0026BB765291":8,"f6f986a8-ae40-4f38-aa34-4b232ed91fca|000000A2-0000-1000-8000-0026BB765291|00000037-0000-1000-8000-0026BB765291":9,"|nextAID":6,"806f062f-5756-49cc-b1ef-196c1d818e5d":2,"806f062f-5756-49cc-b1ef-196c1d818e5d|nextIID":18,"806f062f-5756-49cc-b1ef-196c1d818e5d|0000003E-0000-1000-8000-0026BB765291|00000014-0000-1000-8000-0026BB765291":2,"806f062f-5756-49cc-b1ef-196c1d818e5d|0000003E-0000-1000-8000-0026BB765291|00000020-0000-1000-8000-0026BB765291":3,"806f062f-5756-49cc-b1ef-196c1d818e5d|0000003E-0000-1000-8000-0026BB765291|00000021-0000-1000-8000-0026BB765291":4,"806f062f-5756-49cc-b1ef-196c1d818e5d|0000003E-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":5,"806f062f-5756-49cc-b1ef-196c1d818e5d|0000003E-0000-1000-8000-0026BB765291|00000030-0000-1000-8000-0026BB765291":6,"806f062f-5756-49cc-b1ef-196c1d818e5d|0000003E-0000-1000-8000-0026BB765291|00000052-0000-1000-8000-0026BB765291":7,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291":8,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|000000B0-0000-1000-8000-0026BB765291":9,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|000000B1-0000-1000-8000-0026BB765291":10,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|000000B2-0000-1000-8000-0026BB765291":11,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|00000011-0000-1000-8000-0026BB765291":12,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":13,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|0000000D-0000-1000-8000-0026BB765291":14,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|00000012-0000-1000-8000-0026BB765291":15,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|00000029-0000-1000-8000-0026BB765291":16,"806f062f-5756-49cc-b1ef-196c1d818e5d|000000BC-0000-1000-8000-0026BB765291|000000B6-0000-1000-8000-0026BB765291":17,"205e47f6-e67d-4124-874e-b9522551e572":3,"205e47f6-e67d-4124-874e-b9522551e572|nextIID":18,"205e47f6-e67d-4124-874e-b9522551e572|0000003E-0000-1000-8000-0026BB765291|00000014-0000-1000-8000-0026BB765291":2,"205e47f6-e67d-4124-874e-b9522551e572|0000003E-0000-1000-8000-0026BB765291|00000020-0000-1000-8000-0026BB765291":3,"205e47f6-e67d-4124-874e-b9522551e572|0000003E-0000-1000-8000-0026BB765291|00000021-0000-1000-8000-0026BB765291":4,"205e47f6-e67d-4124-874e-b9522551e572|0000003E-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":5,"205e47f6-e67d-4124-874e-b9522551e572|0000003E-0000-1000-8000-0026BB765291|00000030-0000-1000-8000-0026BB765291":6,"205e47f6-e67d-4124-874e-b9522551e572|0000003E-0000-1000-8000-0026BB765291|00000052-0000-1000-8000-0026BB765291":7,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291":8,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|000000B0-0000-1000-8000-0026BB765291":9,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|000000B1-0000-1000-8000-0026BB765291":10,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|000000B2-0000-1000-8000-0026BB765291":11,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|00000011-0000-1000-8000-0026BB765291":12,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":13,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|0000000D-0000-1000-8000-0026BB765291":14,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|00000012-0000-1000-8000-0026BB765291":15,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|00000029-0000-1000-8000-0026BB765291":16,"205e47f6-e67d-4124-874e-b9522551e572|000000BC-0000-1000-8000-0026BB765291|000000B6-0000-1000-8000-0026BB765291":17,"4234b216-1ede-412a-b0d7-864ef82fadf9":4,"4234b216-1ede-412a-b0d7-864ef82fadf9|nextIID":18,"4234b216-1ede-412a-b0d7-864ef82fadf9|0000003E-0000-1000-8000-0026BB765291|00000014-0000-1000-8000-0026BB765291":2,"4234b216-1ede-412a-b0d7-864ef82fadf9|0000003E-0000-1000-8000-0026BB765291|00000020-0000-1000-8000-0026BB765291":3,"4234b216-1ede-412a-b0d7-864ef82fadf9|0000003E-0000-1000-8000-0026BB765291|00000021-0000-1000-8000-0026BB765291":4,"4234b216-1ede-412a-b0d7-864ef82fadf9|0000003E-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":5,"4234b216-1ede-412a-b0d7-864ef82fadf9|0000003E-0000-1000-8000-0026BB765291|00000030-0000-1000-8000-0026BB765291":6,"4234b216-1ede-412a-b0d7-864ef82fadf9|0000003E-0000-1000-8000-0026BB765291|00000052-0000-1000-8000-0026BB765291":7,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291":8,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|000000B0-0000-1000-8000-0026BB765291":9,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|000000B1-0000-1000-8000-0026BB765291":10,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|000000B2-0000-1000-8000-0026BB765291":11,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|00000011-0000-1000-8000-0026BB765291":12,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":13,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|0000000D-0000-1000-8000-0026BB765291":14,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|00000012-0000-1000-8000-0026BB765291":15,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|00000029-0000-1000-8000-0026BB765291":16,"4234b216-1ede-412a-b0d7-864ef82fadf9|000000BC-0000-1000-8000-0026BB765291|000000B6-0000-1000-8000-0026BB765291":17,"85cbb851-34e0-479f-8184-810d1e8579e7":5,"85cbb851-34e0-479f-8184-810d1e8579e7|nextIID":18,"85cbb851-34e0-479f-8184-810d1e8579e7|0000003E-0000-1000-8000-0026BB765291|00000014-0000-1000-8000-0026BB765291":2,"85cbb851-34e0-479f-8184-810d1e8579e7|0000003E-0000-1000-8000-0026BB765291|00000020-0000-1000-8000-0026BB765291":3,"85cbb851-34e0-479f-8184-810d1e8579e7|0000003E-0000-1000-8000-0026BB765291|00000021-0000-1000-8000-0026BB765291":4,"85cbb851-34e0-479f-8184-810d1e8579e7|0000003E-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":5,"85cbb851-34e0-479f-8184-810d1e8579e7|0000003E-0000-1000-8000-0026BB765291|00000030-0000-1000-8000-0026BB765291":6,"85cbb851-34e0-479f-8184-810d1e8579e7|0000003E-0000-1000-8000-0026BB765291|00000052-0000-1000-8000-0026BB765291":7,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291":8,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|000000B0-0000-1000-8000-0026BB765291":9,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|000000B1-0000-1000-8000-0026BB765291":10,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|000000B2-0000-1000-8000-0026BB765291":11,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|00000011-0000-1000-8000-0026BB765291":12,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|00000023-0000-1000-8000-0026BB765291":13,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|0000000D-0000-1000-8000-0026BB765291":14,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|00000012-0000-1000-8000-0026BB765291":15,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|00000029-0000-1000-8000-0026BB765291":16,"85cbb851-34e0-479f-8184-810d1e8579e7|000000BC-0000-1000-8000-0026BB765291|000000B6-0000-1000-8000-0026BB765291":17}}
@@ -0,0 +1,396 @@
1
+ import {PlatformAccessory} from 'homebridge/lib/platformAccessory';
2
+ import {DaikinCloudAccessoryContext, DaikinCloudPlatform} from '../../src/platform';
3
+ import {MockPlatformConfig} from '../mocks';
4
+ import {AirConditioningAccessory} from '../../src/accessories';
5
+ import {DaikinCloudDevice} from 'daikin-controller-cloud/dist/device';
6
+ import {DaikinCloudController} from 'daikin-controller-cloud/dist/index.js';
7
+ import {OnectaClient} from 'daikin-controller-cloud/dist/onecta/oidc-client';
8
+ import {unknownJan} from '../fixtures/unknown-jan';
9
+ import {unknownKitchenGuests} from '../fixtures/unknown-kitchen-guests';
10
+ import {dx23Airco} from '../fixtures/dx23-airco';
11
+ import {dx4Airco} from '../fixtures/dx4-airco';
12
+ import {dx23Airco2} from '../fixtures/dx23-airco-2';
13
+
14
+ import {HomebridgeAPI} from 'homebridge/lib/api.js';
15
+ import {Logger} from 'homebridge/lib/logger.js';
16
+ import {
17
+ PowerfulModeFeature,
18
+ EconoModeFeature,
19
+ StreamerModeFeature,
20
+ OutdoorSilentModeFeature,
21
+ IndoorSilentModeFeature,
22
+ DryOperationModeFeature,
23
+ FanOnlyOperationModeFeature,
24
+ } from '../../src/features';
25
+
26
+ type DeviceState = {
27
+ activeState: boolean;
28
+ currentTemperature: number;
29
+ targetHeaterCoolerState: string;
30
+ coolingThresholdTemperature: number;
31
+ heatingThresholdTemperature: number;
32
+ rotationSpeed: number;
33
+ swingMode: number;
34
+ powerfulMode: number;
35
+ econoMode: number;
36
+ streamerMode: number;
37
+ outdoorSilentMode: number;
38
+ indoorSilentMode: number;
39
+ dryOperationMode: number;
40
+ fanOnlyOperationMode: number;
41
+ };
42
+
43
+ test.each<Array<string | string | any | DeviceState>>([
44
+ [
45
+ 'dx4',
46
+ 'climateControl',
47
+ dx4Airco,
48
+ {
49
+ activeState: true,
50
+ currentTemperature: 25,
51
+ targetHeaterCoolerState: 1,
52
+ coolingThresholdTemperature: 25,
53
+ heatingThresholdTemperature: 22,
54
+ rotationSpeed: 2,
55
+ swingMode: 0,
56
+ powerfulMode: false,
57
+ econoMode: false,
58
+ streamerMode: false,
59
+ outdoorSilentMode: false,
60
+ indoorSilentMode: false,
61
+ dryOperationMode: false,
62
+ fanOnlyOperationMode: false,
63
+ },
64
+ ],
65
+ [
66
+ 'dx23',
67
+ 'climateControl',
68
+ dx23Airco,
69
+ {
70
+ activeState: false,
71
+ currentTemperature: 27,
72
+ targetHeaterCoolerState: 2,
73
+ coolingThresholdTemperature: 17,
74
+ heatingThresholdTemperature: 17,
75
+ rotationSpeed: 3,
76
+ swingMode: 1,
77
+ powerfulMode: undefined,
78
+ econoMode: undefined,
79
+ streamerMode: undefined,
80
+ outdoorSilentMode: undefined,
81
+ indoorSilentMode: undefined,
82
+ dryOperationMode: false,
83
+ fanOnlyOperationMode: false,
84
+ },
85
+ ],
86
+ [
87
+ 'dx23-2',
88
+ 'climateControl',
89
+ dx23Airco2,
90
+ {
91
+ activeState: true,
92
+ currentTemperature: 19,
93
+ targetHeaterCoolerState: 1,
94
+ coolingThresholdTemperature: 25,
95
+ heatingThresholdTemperature: 13,
96
+ rotationSpeed: 4,
97
+ swingMode: 0,
98
+ powerfulMode: false,
99
+ econoMode: undefined,
100
+ streamerMode: undefined,
101
+ outdoorSilentMode: undefined,
102
+ indoorSilentMode: false,
103
+ dryOperationMode: false,
104
+ fanOnlyOperationMode: false,
105
+ },
106
+ ],
107
+ [
108
+ 'unknown',
109
+ 'climateControl',
110
+ unknownKitchenGuests,
111
+ {
112
+ activeState: false,
113
+ currentTemperature: 30.1,
114
+ targetHeaterCoolerState: 2,
115
+ coolingThresholdTemperature: 23.5,
116
+ heatingThresholdTemperature: undefined,
117
+ rotationSpeed: 1,
118
+ swingMode: 1,
119
+ powerfulMode: undefined,
120
+ econoMode: undefined,
121
+ streamerMode: undefined,
122
+ outdoorSilentMode: undefined,
123
+ indoorSilentMode: undefined,
124
+ dryOperationMode: false,
125
+ fanOnlyOperationMode: false,
126
+ },
127
+ ],
128
+ [
129
+ 'unknown2',
130
+ 'climateControl',
131
+ unknownJan,
132
+ {
133
+ activeState: false,
134
+ currentTemperature: 27,
135
+ targetHeaterCoolerState: 2,
136
+ coolingThresholdTemperature: 26.1,
137
+ heatingThresholdTemperature: undefined,
138
+ rotationSpeed: 1,
139
+ swingMode: 1,
140
+ powerfulMode: undefined,
141
+ econoMode: undefined,
142
+ streamerMode: undefined,
143
+ outdoorSilentMode: undefined,
144
+ indoorSilentMode: undefined,
145
+ dryOperationMode: false,
146
+ fanOnlyOperationMode: false,
147
+ },
148
+ ],
149
+ ])('Create DaikinCloudAirConditioningAccessory with %s device', async (name: string, climateControlEmbeddedId: string, deviceJson, state: DeviceState) => {
150
+ const device = new DaikinCloudDevice(deviceJson, undefined as unknown as OnectaClient);
151
+
152
+ jest.spyOn(DaikinCloudController.prototype, 'getCloudDevices').mockImplementation(async () => {
153
+ return [device];
154
+ });
155
+
156
+ const config = new MockPlatformConfig(true);
157
+ const api = new HomebridgeAPI();
158
+
159
+ const uuid = api.hap.uuid.generate(device.getId());
160
+ const accessory = new api.platformAccessory("NAME_FOR_TEST", uuid);
161
+ accessory.context['device'] = device;
162
+
163
+ expect(() => {
164
+ new AirConditioningAccessory(new DaikinCloudPlatform(new Logger(), config, api), accessory as unknown as PlatformAccessory<DaikinCloudAccessoryContext>);
165
+ }).not.toThrow();
166
+
167
+ const homebridgeAccessory = new AirConditioningAccessory(new DaikinCloudPlatform(new Logger(), config, api), accessory as unknown as PlatformAccessory<DaikinCloudAccessoryContext>);
168
+
169
+ if (typeof state.activeState !== 'undefined') {
170
+ expect(await homebridgeAccessory.service.handleActiveStateGet()).toBe(state.activeState);
171
+ expect(async () => {
172
+ await homebridgeAccessory.service.handleActiveStateSet(1);
173
+ }).not.toThrow();
174
+ expect(async () => {
175
+ await homebridgeAccessory.service.handleActiveStateSet(0);
176
+ }).not.toThrow();
177
+ }
178
+
179
+ expect(await homebridgeAccessory.service.handleCurrentTemperatureGet()).toBe(state.currentTemperature);
180
+
181
+ if (typeof state.coolingThresholdTemperature !== 'undefined') {
182
+ expect(await homebridgeAccessory.service.handleCoolingThresholdTemperatureGet()).toBe(state.coolingThresholdTemperature);
183
+ expect(async () => {
184
+ await homebridgeAccessory.service.handleCoolingThresholdTemperatureSet(21);
185
+ }).not.toThrow();
186
+ }
187
+
188
+ if (typeof state.heatingThresholdTemperature !== 'undefined') {
189
+ expect(await homebridgeAccessory.service.handleHeatingThresholdTemperatureGet()).toBe(state.heatingThresholdTemperature);
190
+ expect(async () => {
191
+ await homebridgeAccessory.service.handleHeatingThresholdTemperatureSet(25);
192
+ }).not.toThrow();
193
+ }
194
+
195
+ if (typeof state.rotationSpeed !== 'undefined') {
196
+ expect(await homebridgeAccessory.service.handleRotationSpeedGet()).toBe(state.rotationSpeed);
197
+ expect(async () => {
198
+ await homebridgeAccessory.service.handleRotationSpeedSet(50);
199
+ }).not.toThrow();
200
+ }
201
+
202
+ if (typeof state.targetHeaterCoolerState !== 'undefined') {
203
+ expect(await homebridgeAccessory.service.handleTargetHeaterCoolerStateGet()).toBe(state.targetHeaterCoolerState);
204
+ expect(async () => {
205
+ await homebridgeAccessory.service.handleTargetHeaterCoolerStateSet(1);
206
+ }).not.toThrow();
207
+ }
208
+
209
+ if (typeof state.swingMode !== 'undefined') {
210
+ expect(await homebridgeAccessory.service.handleSwingModeGet()).toBe(state.swingMode);
211
+ expect(async () => {
212
+ await homebridgeAccessory.service.handleSwingModeSet(1);
213
+ }).not.toThrow();
214
+ }
215
+
216
+ if (typeof state.powerfulMode !== 'undefined') {
217
+ const feature = homebridgeAccessory.service.featureManager.getFeature(PowerfulModeFeature);
218
+ expect(feature).toBeDefined();
219
+ expect(await feature!.handleGet()).toBe(state.powerfulMode);
220
+ }
221
+
222
+ if (typeof state.econoMode !== 'undefined') {
223
+ const feature = homebridgeAccessory.service.featureManager.getFeature(EconoModeFeature);
224
+ expect(feature).toBeDefined();
225
+ expect(await feature!.handleGet()).toBe(state.econoMode);
226
+ }
227
+
228
+ if (typeof state.streamerMode !== 'undefined') {
229
+ const feature = homebridgeAccessory.service.featureManager.getFeature(StreamerModeFeature);
230
+ expect(feature).toBeDefined();
231
+ expect(await feature!.handleGet()).toBe(state.streamerMode);
232
+ }
233
+
234
+ if (typeof state.outdoorSilentMode !== 'undefined') {
235
+ const feature = homebridgeAccessory.service.featureManager.getFeature(OutdoorSilentModeFeature);
236
+ expect(feature).toBeDefined();
237
+ expect(await feature!.handleGet()).toBe(state.outdoorSilentMode);
238
+ }
239
+
240
+ if (typeof state.indoorSilentMode !== 'undefined') {
241
+ const feature = homebridgeAccessory.service.featureManager.getFeature(IndoorSilentModeFeature);
242
+ expect(feature).toBeDefined();
243
+ expect(await feature!.handleGet()).toBe(state.indoorSilentMode);
244
+ }
245
+
246
+ if (typeof state.dryOperationMode !== 'undefined') {
247
+ const feature = homebridgeAccessory.service.featureManager.getFeature(DryOperationModeFeature);
248
+ expect(feature).toBeDefined();
249
+ expect(await feature!.handleGet()).toBe(state.dryOperationMode);
250
+ }
251
+
252
+ if (typeof state.fanOnlyOperationMode !== 'undefined') {
253
+ const feature = homebridgeAccessory.service.featureManager.getFeature(FanOnlyOperationModeFeature);
254
+ expect(feature).toBeDefined();
255
+ expect(await feature!.handleGet()).toBe(state.fanOnlyOperationMode);
256
+ }
257
+ });
258
+
259
+ test.each<Array<string | string | any>>([
260
+ ['dx4', 'climateControl', dx4Airco],
261
+ ['dx23', 'climateControl', dx23Airco],
262
+ ])('Create DaikinCloudAirConditioningAccessory with %s device, showExtraFeatures disabled', async (name, climateControlEmbeddedId, deviceJson) => {
263
+ const device = new DaikinCloudDevice(deviceJson, undefined as unknown as OnectaClient);
264
+
265
+ jest.spyOn(DaikinCloudController.prototype, 'getCloudDevices').mockImplementation(async () => {
266
+ return [device];
267
+ });
268
+
269
+
270
+ const config = new MockPlatformConfig(false);
271
+ const api = new HomebridgeAPI();
272
+
273
+ const uuid = api.hap.uuid.generate(device.getId());
274
+ const accessory = new api.platformAccessory("NAME_FOR_TEST", uuid);
275
+
276
+ accessory.addService(api.hap.Service.Switch, 'Powerful mode', 'Powerful_Mode');
277
+ accessory.addService(api.hap.Service.Switch, 'Econo mode', 'Econo_Mode');
278
+ accessory.addService(api.hap.Service.Switch, 'Streamer mode', 'Streamer_Mode');
279
+ accessory.addService(api.hap.Service.Switch, 'Outdoor silent mode', 'Outdoor_Silent_Mode');
280
+ accessory.addService(api.hap.Service.Switch, 'Indoor silent mode', 'Indoor_Silent_Mode');
281
+ accessory.context['device'] = device;
282
+
283
+ const removeServiceSpy = jest.spyOn(accessory, 'removeService').mockImplementation();
284
+
285
+ const homebridgeAccessory = new AirConditioningAccessory(new DaikinCloudPlatform(new Logger(), config, api), accessory as unknown as PlatformAccessory<DaikinCloudAccessoryContext>);
286
+
287
+
288
+ expect(removeServiceSpy).toHaveBeenNthCalledWith(1, expect.objectContaining({ displayName: 'Powerful mode', subtype: 'Powerful_Mode' }));
289
+ expect(removeServiceSpy).toHaveBeenNthCalledWith(2, expect.objectContaining({ displayName: 'Econo mode', subtype: 'Econo_Mode' }));
290
+ expect(removeServiceSpy).toHaveBeenNthCalledWith(3, expect.objectContaining({ displayName: 'Streamer mode', subtype: 'Streamer_Mode' }));
291
+ expect(removeServiceSpy).toHaveBeenNthCalledWith(4, expect.objectContaining({ displayName: 'Outdoor silent mode', subtype: 'Outdoor_Silent_Mode' }));
292
+ expect(removeServiceSpy).toHaveBeenNthCalledWith(5, expect.objectContaining({ displayName: 'Indoor silent mode', subtype: 'Indoor_Silent_Mode' }));
293
+
294
+ });
295
+
296
+ test('DaikinCloudAirConditioningAccessory Getters', async () => {
297
+ const device = new DaikinCloudDevice(dx4Airco, undefined as unknown as OnectaClient);
298
+
299
+ jest.spyOn(DaikinCloudController.prototype, 'getCloudDevices').mockImplementation(async () => {
300
+ return [device];
301
+ });
302
+
303
+ const config = new MockPlatformConfig(false);
304
+ const api = new HomebridgeAPI();
305
+
306
+ const uuid = api.hap.uuid.generate(device.getId());
307
+ const accessory = new api.platformAccessory(device.getData('climateControl', 'name', undefined).value, uuid);
308
+ accessory.context['device'] = device;
309
+
310
+ const homebridgeAccessory = new AirConditioningAccessory(new DaikinCloudPlatform(new Logger(), config, api), accessory as unknown as PlatformAccessory<DaikinCloudAccessoryContext>);
311
+
312
+ expect(await homebridgeAccessory.service.handleActiveStateGet()).toEqual(true);
313
+ expect(await homebridgeAccessory.service.handleCurrentTemperatureGet()).toEqual(25);
314
+ expect(await homebridgeAccessory.service.handleCoolingThresholdTemperatureGet()).toEqual(25);
315
+ expect(await homebridgeAccessory.service.handleRotationSpeedGet()).toEqual(2);
316
+ expect(await homebridgeAccessory.service.handleHeatingThresholdTemperatureGet()).toEqual(22);
317
+ expect(await homebridgeAccessory.service.handleTargetHeaterCoolerStateGet()).toEqual(1);
318
+ expect(await homebridgeAccessory.service.handleSwingModeGet()).toEqual(0);
319
+
320
+ // Feature-based getters via FeatureManager
321
+ const powerfulFeature = homebridgeAccessory.service.featureManager.getFeature(PowerfulModeFeature);
322
+ expect(await powerfulFeature!.handleGet()).toEqual(false);
323
+ const econoFeature = homebridgeAccessory.service.featureManager.getFeature(EconoModeFeature);
324
+ expect(await econoFeature!.handleGet()).toEqual(false);
325
+ const streamerFeature = homebridgeAccessory.service.featureManager.getFeature(StreamerModeFeature);
326
+ expect(await streamerFeature!.handleGet()).toEqual(false);
327
+ const outdoorSilentFeature = homebridgeAccessory.service.featureManager.getFeature(OutdoorSilentModeFeature);
328
+ expect(await outdoorSilentFeature!.handleGet()).toEqual(false);
329
+ const indoorSilentFeature = homebridgeAccessory.service.featureManager.getFeature(IndoorSilentModeFeature);
330
+ expect(await indoorSilentFeature!.handleGet()).toEqual(false);
331
+ });
332
+
333
+ test('DaikinCloudAirConditioningAccessory Setters', async () => {
334
+ const device = new DaikinCloudDevice(dx4Airco, undefined as unknown as OnectaClient);
335
+
336
+ jest.spyOn(DaikinCloudController.prototype, 'getCloudDevices').mockImplementation(async () => {
337
+ return [device];
338
+ });
339
+
340
+ const setDataSpy = jest.spyOn(DaikinCloudDevice.prototype, 'setData').mockImplementation();
341
+
342
+ const config = new MockPlatformConfig(false);
343
+ const api = new HomebridgeAPI();
344
+
345
+ const uuid = api.hap.uuid.generate(device.getId());
346
+ const accessory = new api.platformAccessory(device.getData('climateControl', 'name', undefined).value, uuid);
347
+ // device.updateData = () => jest.fn();
348
+ accessory.context['device'] = device;
349
+
350
+ const homebridgeAccessory = new AirConditioningAccessory(new DaikinCloudPlatform(new Logger(), config, api), accessory as unknown as PlatformAccessory<DaikinCloudAccessoryContext>);
351
+
352
+ await homebridgeAccessory.service.handleActiveStateSet(1);
353
+ expect(setDataSpy).toHaveBeenNthCalledWith(1, 'climateControl', 'onOffMode', 'on', undefined);
354
+
355
+ await homebridgeAccessory.service.handleActiveStateSet(0);
356
+ expect(setDataSpy).toHaveBeenNthCalledWith(2, 'climateControl', 'onOffMode', 'off', undefined);
357
+
358
+ await homebridgeAccessory.service.handleCoolingThresholdTemperatureSet(21);
359
+ expect(setDataSpy).toHaveBeenNthCalledWith(3, 'climateControl', 'temperatureControl', '/operationModes/cooling/setpoints/roomTemperature', 21);
360
+
361
+ await homebridgeAccessory.service.handleRotationSpeedSet(50);
362
+ expect(setDataSpy).toHaveBeenNthCalledWith(4, 'climateControl', 'fanControl', '/operationModes/heating/fanSpeed/currentMode', 'fixed');
363
+ expect(setDataSpy).toHaveBeenNthCalledWith(5, 'climateControl', 'fanControl', '/operationModes/heating/fanSpeed/modes/fixed', 50);
364
+
365
+ await homebridgeAccessory.service.handleHeatingThresholdTemperatureSet(25);
366
+ expect(setDataSpy).toHaveBeenNthCalledWith(6, 'climateControl', 'temperatureControl', '/operationModes/heating/setpoints/roomTemperature', 25);
367
+
368
+ await homebridgeAccessory.service.handleTargetHeaterCoolerStateSet(1);
369
+ expect(setDataSpy).toHaveBeenNthCalledWith(7, 'climateControl', 'operationMode', 'heating', undefined);
370
+ expect(setDataSpy).toHaveBeenNthCalledWith(8, 'climateControl', 'onOffMode', 'on', undefined);
371
+
372
+ await homebridgeAccessory.service.handleSwingModeSet(1);
373
+ expect(setDataSpy).toHaveBeenNthCalledWith(9, 'climateControl', 'fanControl', '/operationModes/heating/fanDirection/horizontal/currentMode', 'swing');
374
+ expect(setDataSpy).toHaveBeenNthCalledWith(10, 'climateControl', 'fanControl', '/operationModes/heating/fanDirection/vertical/currentMode', 'swing');
375
+
376
+ // Feature-based setters via FeatureManager
377
+ const powerfulFeature = homebridgeAccessory.service.featureManager.getFeature(PowerfulModeFeature);
378
+ await powerfulFeature!.handleSet(true);
379
+ expect(setDataSpy).toHaveBeenNthCalledWith(11, 'climateControl', 'powerfulMode', 'on', undefined);
380
+
381
+ const econoFeature = homebridgeAccessory.service.featureManager.getFeature(EconoModeFeature);
382
+ await econoFeature!.handleSet(true);
383
+ expect(setDataSpy).toHaveBeenNthCalledWith(12, 'climateControl', 'econoMode', 'on', undefined);
384
+
385
+ const streamerFeature = homebridgeAccessory.service.featureManager.getFeature(StreamerModeFeature);
386
+ await streamerFeature!.handleSet(true);
387
+ expect(setDataSpy).toHaveBeenNthCalledWith(13, 'climateControl', 'streamerMode', 'on', undefined);
388
+
389
+ const outdoorSilentFeature = homebridgeAccessory.service.featureManager.getFeature(OutdoorSilentModeFeature);
390
+ await outdoorSilentFeature!.handleSet(true);
391
+ expect(setDataSpy).toHaveBeenNthCalledWith(14, 'climateControl', 'outdoorSilentMode', 'on', undefined);
392
+
393
+ const indoorSilentFeature = homebridgeAccessory.service.featureManager.getFeature(IndoorSilentModeFeature);
394
+ await indoorSilentFeature!.handleSet(true);
395
+ expect(setDataSpy).toHaveBeenNthCalledWith(15, 'climateControl', 'fanControl', '/operationModes/heating/fanSpeed/currentMode', 'quiet');
396
+ });