@homebridge-plugins/homebridge-eufy-security 4.7.2 → 5.0.0-beta.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 (471) hide show
  1. package/AUTHORS +4 -0
  2. package/CODE_OF_CONDUCT.md +30 -0
  3. package/CONTRIBUTING.md +77 -0
  4. package/README.md +152 -49
  5. package/SECURITY.md +30 -0
  6. package/config.schema.json +92 -3
  7. package/dist/account/ownership.js +290 -0
  8. package/dist/account/ownership.js.map +1 -0
  9. package/dist/account/persistence.js +274 -0
  10. package/dist/account/persistence.js.map +1 -0
  11. package/dist/account/temporary-authentication.js +348 -0
  12. package/dist/account/temporary-authentication.js.map +1 -0
  13. package/dist/configuration.js +167 -0
  14. package/dist/configuration.js.map +1 -0
  15. package/dist/device/member-evidence.js +66 -0
  16. package/dist/device/member-evidence.js.map +1 -0
  17. package/dist/device/member-trust.js +114 -0
  18. package/dist/device/member-trust.js.map +1 -0
  19. package/dist/device/snapshot.js +190 -0
  20. package/dist/device/snapshot.js.map +1 -0
  21. package/dist/diagnostics.js +2218 -0
  22. package/dist/diagnostics.js.map +1 -0
  23. package/dist/homekit/adapter.js +2 -0
  24. package/dist/homekit/adapter.js.map +1 -0
  25. package/dist/homekit/adapters/battery.js +208 -0
  26. package/dist/homekit/adapters/battery.js.map +1 -0
  27. package/dist/homekit/adapters/camera-controls.js +527 -0
  28. package/dist/homekit/adapters/camera-controls.js.map +1 -0
  29. package/dist/homekit/adapters/camera-streaming.js +1515 -0
  30. package/dist/homekit/adapters/camera-streaming.js.map +1 -0
  31. package/dist/homekit/adapters/contact.js +138 -0
  32. package/dist/homekit/adapters/contact.js.map +1 -0
  33. package/dist/homekit/adapters/doorbell.js +57 -0
  34. package/dist/homekit/adapters/doorbell.js.map +1 -0
  35. package/dist/homekit/adapters/information.js +55 -0
  36. package/dist/homekit/adapters/information.js.map +1 -0
  37. package/dist/homekit/adapters/lock.js +489 -0
  38. package/dist/homekit/adapters/lock.js.map +1 -0
  39. package/dist/homekit/adapters/motion.js +100 -0
  40. package/dist/homekit/adapters/motion.js.map +1 -0
  41. package/dist/homekit/adapters/registry.js +26 -0
  42. package/dist/homekit/adapters/registry.js.map +1 -0
  43. package/dist/homekit/adapters/security-system.js +425 -0
  44. package/dist/homekit/adapters/security-system.js.map +1 -0
  45. package/dist/homekit/adapters/siren.js +136 -0
  46. package/dist/homekit/adapters/siren.js.map +1 -0
  47. package/dist/homekit/adapters/smart-light.js +662 -0
  48. package/dist/homekit/adapters/smart-light.js.map +1 -0
  49. package/dist/homekit/coverage-matrix.js +119 -0
  50. package/dist/homekit/coverage-matrix.js.map +1 -0
  51. package/dist/homekit/device-control.js +175 -0
  52. package/dist/homekit/device-control.js.map +1 -0
  53. package/dist/homekit/reconciler.js +319 -0
  54. package/dist/homekit/reconciler.js.map +1 -0
  55. package/dist/homekit/representation.js +23 -0
  56. package/dist/homekit/representation.js.map +1 -0
  57. package/dist/index.js +4 -9
  58. package/dist/index.js.map +1 -1
  59. package/dist/media/contracts.js +2 -0
  60. package/dist/media/contracts.js.map +1 -0
  61. package/dist/media/last-successful-image.js +208 -0
  62. package/dist/media/last-successful-image.js.map +1 -0
  63. package/dist/media/live-stream.js +1003 -0
  64. package/dist/media/live-stream.js.map +1 -0
  65. package/dist/media/recording.js +560 -0
  66. package/dist/media/recording.js.map +1 -0
  67. package/dist/media/session-budget.js +39 -0
  68. package/dist/media/session-budget.js.map +1 -0
  69. package/dist/media/snapshot.js +406 -0
  70. package/dist/media/snapshot.js.map +1 -0
  71. package/dist/media/station-live-sessions.js +101 -0
  72. package/dist/media/station-live-sessions.js.map +1 -0
  73. package/dist/platform.js +97 -809
  74. package/dist/platform.js.map +1 -1
  75. package/dist/runtime/channel.js +375 -0
  76. package/dist/runtime/channel.js.map +1 -0
  77. package/dist/runtime/owner.js +682 -0
  78. package/dist/runtime/owner.js.map +1 -0
  79. package/dist/runtime/sdk-client.js +211 -0
  80. package/dist/runtime/sdk-client.js.map +1 -0
  81. package/dist/runtime/tracker.js +211 -0
  82. package/dist/runtime/tracker.js.map +1 -0
  83. package/dist/settings.js +1 -43
  84. package/dist/settings.js.map +1 -1
  85. package/dist/storage.js +59 -0
  86. package/dist/storage.js.map +1 -0
  87. package/dist/ui/dashboard.js +181 -0
  88. package/dist/ui/dashboard.js.map +1 -0
  89. package/dist/ui/device-image.js +22 -0
  90. package/dist/ui/device-image.js.map +1 -0
  91. package/dist/ui/runtime-channel-client.js +305 -0
  92. package/dist/ui/runtime-channel-client.js.map +1 -0
  93. package/dist/ui/server.js +259 -0
  94. package/dist/ui/server.js.map +1 -0
  95. package/homebridge-ui/public/app.css +1902 -0
  96. package/homebridge-ui/public/assets/devices/clean/clean-T1250.webp +0 -0
  97. package/homebridge-ui/public/assets/devices/clean/clean-T2070.webp +0 -0
  98. package/homebridge-ui/public/assets/devices/clean/clean-T2080.webp +0 -0
  99. package/homebridge-ui/public/assets/devices/clean/clean-T2081.webp +0 -0
  100. package/homebridge-ui/public/assets/devices/clean/clean-T2103.webp +0 -0
  101. package/homebridge-ui/public/assets/devices/clean/clean-T2117.webp +0 -0
  102. package/homebridge-ui/public/assets/devices/clean/clean-T2118.webp +0 -0
  103. package/homebridge-ui/public/assets/devices/clean/clean-T2119.webp +0 -0
  104. package/homebridge-ui/public/assets/devices/clean/clean-T211A.webp +0 -0
  105. package/homebridge-ui/public/assets/devices/clean/clean-T2120.webp +0 -0
  106. package/homebridge-ui/public/assets/devices/clean/clean-T2123.webp +0 -0
  107. package/homebridge-ui/public/assets/devices/clean/clean-T2128.webp +0 -0
  108. package/homebridge-ui/public/assets/devices/clean/clean-T2130.webp +0 -0
  109. package/homebridge-ui/public/assets/devices/clean/clean-T2132.webp +0 -0
  110. package/homebridge-ui/public/assets/devices/clean/clean-T2150.webp +0 -0
  111. package/homebridge-ui/public/assets/devices/clean/clean-T2181.webp +0 -0
  112. package/homebridge-ui/public/assets/devices/clean/clean-T2182.webp +0 -0
  113. package/homebridge-ui/public/assets/devices/clean/clean-T2190.webp +0 -0
  114. package/homebridge-ui/public/assets/devices/clean/clean-T2192.webp +0 -0
  115. package/homebridge-ui/public/assets/devices/clean/clean-T2193.webp +0 -0
  116. package/homebridge-ui/public/assets/devices/clean/clean-T2194.webp +0 -0
  117. package/homebridge-ui/public/assets/devices/clean/clean-T2210.webp +0 -0
  118. package/homebridge-ui/public/assets/devices/clean/clean-T2250.webp +0 -0
  119. package/homebridge-ui/public/assets/devices/clean/clean-T2251.webp +0 -0
  120. package/homebridge-ui/public/assets/devices/clean/clean-T2252.webp +0 -0
  121. package/homebridge-ui/public/assets/devices/clean/clean-T2253.webp +0 -0
  122. package/homebridge-ui/public/assets/devices/clean/clean-T2254.webp +0 -0
  123. package/homebridge-ui/public/assets/devices/clean/clean-T2255.webp +0 -0
  124. package/homebridge-ui/public/assets/devices/clean/clean-T2256.webp +0 -0
  125. package/homebridge-ui/public/assets/devices/clean/clean-T2257.webp +0 -0
  126. package/homebridge-ui/public/assets/devices/clean/clean-T2258.webp +0 -0
  127. package/homebridge-ui/public/assets/devices/clean/clean-T2259.webp +0 -0
  128. package/homebridge-ui/public/assets/devices/clean/clean-T2261.webp +0 -0
  129. package/homebridge-ui/public/assets/devices/clean/clean-T2262.webp +0 -0
  130. package/homebridge-ui/public/assets/devices/clean/clean-T2266.webp +0 -0
  131. package/homebridge-ui/public/assets/devices/clean/clean-T2267.webp +0 -0
  132. package/homebridge-ui/public/assets/devices/clean/clean-T2268.webp +0 -0
  133. package/homebridge-ui/public/assets/devices/clean/clean-T2270.webp +0 -0
  134. package/homebridge-ui/public/assets/devices/clean/clean-T2272.webp +0 -0
  135. package/homebridge-ui/public/assets/devices/clean/clean-T2273.webp +0 -0
  136. package/homebridge-ui/public/assets/devices/clean/clean-T2276.webp +0 -0
  137. package/homebridge-ui/public/assets/devices/clean/clean-T2277.webp +0 -0
  138. package/homebridge-ui/public/assets/devices/clean/clean-T2278.webp +0 -0
  139. package/homebridge-ui/public/assets/devices/clean/clean-T2280.webp +0 -0
  140. package/homebridge-ui/public/assets/devices/clean/clean-T2292.webp +0 -0
  141. package/homebridge-ui/public/assets/devices/clean/clean-T2320.webp +0 -0
  142. package/homebridge-ui/public/assets/devices/clean/clean-T2351.webp +0 -0
  143. package/homebridge-ui/public/assets/devices/clean/clean-T2352.webp +0 -0
  144. package/homebridge-ui/public/assets/devices/clean/clean-T2353.webp +0 -0
  145. package/homebridge-ui/public/assets/devices/life/life-T8L00.webp +0 -0
  146. package/homebridge-ui/public/assets/devices/life/life-T8L01.webp +0 -0
  147. package/homebridge-ui/public/assets/devices/life/life-T8L02.webp +0 -0
  148. package/homebridge-ui/public/assets/devices/life/life-T8L04.webp +0 -0
  149. package/homebridge-ui/public/assets/devices/life/life-T8L10.webp +0 -0
  150. package/homebridge-ui/public/assets/devices/life/life-T8L20.webp +0 -0
  151. package/homebridge-ui/public/assets/devices/life/life-T8L30.webp +0 -0
  152. package/homebridge-ui/public/assets/devices/life/life-T8L40.webp +0 -0
  153. package/homebridge-ui/public/assets/devices/mower/mower-T2801.webp +0 -0
  154. package/homebridge-ui/public/assets/devices/mower/mower-T280B.webp +0 -0
  155. package/homebridge-ui/public/assets/devices/mower/mower-T2880.webp +0 -0
  156. package/homebridge-ui/public/assets/devices/security/security-T7400.webp +0 -0
  157. package/homebridge-ui/public/assets/devices/security/security-T7401.webp +0 -0
  158. package/homebridge-ui/public/assets/devices/security/security-T8001.webp +0 -0
  159. package/homebridge-ui/public/assets/devices/security/security-T8002.webp +0 -0
  160. package/homebridge-ui/public/assets/devices/security/security-T8010.webp +0 -0
  161. package/homebridge-ui/public/assets/devices/security/security-T8021.webp +0 -0
  162. package/homebridge-ui/public/assets/devices/security/security-T8023.webp +0 -0
  163. package/homebridge-ui/public/assets/devices/security/security-T8025.webp +0 -0
  164. package/homebridge-ui/public/assets/devices/security/security-T8030.webp +0 -0
  165. package/homebridge-ui/public/assets/devices/security/security-T8110.webp +0 -0
  166. package/homebridge-ui/public/assets/devices/security/security-T8111.webp +0 -0
  167. package/homebridge-ui/public/assets/devices/security/security-T8112.webp +0 -0
  168. package/homebridge-ui/public/assets/devices/security/security-T8113.webp +0 -0
  169. package/homebridge-ui/public/assets/devices/security/security-T8114.webp +0 -0
  170. package/homebridge-ui/public/assets/devices/security/security-T8122.webp +0 -0
  171. package/homebridge-ui/public/assets/devices/security/security-T8123.webp +0 -0
  172. package/homebridge-ui/public/assets/devices/security/security-T8124.webp +0 -0
  173. package/homebridge-ui/public/assets/devices/security/security-T8130.webp +0 -0
  174. package/homebridge-ui/public/assets/devices/security/security-T8131.webp +0 -0
  175. package/homebridge-ui/public/assets/devices/security/security-T8134.webp +0 -0
  176. package/homebridge-ui/public/assets/devices/security/security-T8140.webp +0 -0
  177. package/homebridge-ui/public/assets/devices/security/security-T8141.webp +0 -0
  178. package/homebridge-ui/public/assets/devices/security/security-T8150.webp +0 -0
  179. package/homebridge-ui/public/assets/devices/security/security-T8151.webp +0 -0
  180. package/homebridge-ui/public/assets/devices/security/security-T8152.webp +0 -0
  181. package/homebridge-ui/public/assets/devices/security/security-T8153.webp +0 -0
  182. package/homebridge-ui/public/assets/devices/security/security-T8160.webp +0 -0
  183. package/homebridge-ui/public/assets/devices/security/security-T8161.webp +0 -0
  184. package/homebridge-ui/public/assets/devices/security/security-T8162.webp +0 -0
  185. package/homebridge-ui/public/assets/devices/security/security-T8170.webp +0 -0
  186. package/homebridge-ui/public/assets/devices/security/security-T8171.webp +0 -0
  187. package/homebridge-ui/public/assets/devices/security/security-T8172.webp +0 -0
  188. package/homebridge-ui/public/assets/devices/security/security-T8173.webp +0 -0
  189. package/homebridge-ui/public/assets/devices/security/security-T8200.webp +0 -0
  190. package/homebridge-ui/public/assets/devices/security/security-T8200X.webp +0 -0
  191. package/homebridge-ui/public/assets/devices/security/security-T8201.webp +0 -0
  192. package/homebridge-ui/public/assets/devices/security/security-T8203.webp +0 -0
  193. package/homebridge-ui/public/assets/devices/security/security-T8210.webp +0 -0
  194. package/homebridge-ui/public/assets/devices/security/security-T8213.webp +0 -0
  195. package/homebridge-ui/public/assets/devices/security/security-T8214.webp +0 -0
  196. package/homebridge-ui/public/assets/devices/security/security-T8222.webp +0 -0
  197. package/homebridge-ui/public/assets/devices/security/security-T8400.webp +0 -0
  198. package/homebridge-ui/public/assets/devices/security/security-T8401.webp +0 -0
  199. package/homebridge-ui/public/assets/devices/security/security-T8410.webp +0 -0
  200. package/homebridge-ui/public/assets/devices/security/security-T8411.webp +0 -0
  201. package/homebridge-ui/public/assets/devices/security/security-T8414.webp +0 -0
  202. package/homebridge-ui/public/assets/devices/security/security-T8416.webp +0 -0
  203. package/homebridge-ui/public/assets/devices/security/security-T8417.webp +0 -0
  204. package/homebridge-ui/public/assets/devices/security/security-T8419.webp +0 -0
  205. package/homebridge-ui/public/assets/devices/security/security-T8419N.webp +0 -0
  206. package/homebridge-ui/public/assets/devices/security/security-T8420.webp +0 -0
  207. package/homebridge-ui/public/assets/devices/security/security-T8420X.webp +0 -0
  208. package/homebridge-ui/public/assets/devices/security/security-T8422.webp +0 -0
  209. package/homebridge-ui/public/assets/devices/security/security-T8423.webp +0 -0
  210. package/homebridge-ui/public/assets/devices/security/security-T8424.webp +0 -0
  211. package/homebridge-ui/public/assets/devices/security/security-T8425.webp +0 -0
  212. package/homebridge-ui/public/assets/devices/security/security-T8441.webp +0 -0
  213. package/homebridge-ui/public/assets/devices/security/security-T8442.webp +0 -0
  214. package/homebridge-ui/public/assets/devices/security/security-T8452.webp +0 -0
  215. package/homebridge-ui/public/assets/devices/security/security-T84A0.webp +0 -0
  216. package/homebridge-ui/public/assets/devices/security/security-T84A1.webp +0 -0
  217. package/homebridge-ui/public/assets/devices/security/security-T8500.webp +0 -0
  218. package/homebridge-ui/public/assets/devices/security/security-T8502.webp +0 -0
  219. package/homebridge-ui/public/assets/devices/security/security-T8503.webp +0 -0
  220. package/homebridge-ui/public/assets/devices/security/security-T8504.webp +0 -0
  221. package/homebridge-ui/public/assets/devices/security/security-T8506.webp +0 -0
  222. package/homebridge-ui/public/assets/devices/security/security-T8510.webp +0 -0
  223. package/homebridge-ui/public/assets/devices/security/security-T8510P.webp +0 -0
  224. package/homebridge-ui/public/assets/devices/security/security-T8520.webp +0 -0
  225. package/homebridge-ui/public/assets/devices/security/security-T8520P.webp +0 -0
  226. package/homebridge-ui/public/assets/devices/security/security-T8530.webp +0 -0
  227. package/homebridge-ui/public/assets/devices/security/security-T8531.webp +0 -0
  228. package/homebridge-ui/public/assets/devices/security/security-T85D0.webp +0 -0
  229. package/homebridge-ui/public/assets/devices/security/security-T85L0.webp +0 -0
  230. package/homebridge-ui/public/assets/devices/security/security-T85P0.webp +0 -0
  231. package/homebridge-ui/public/assets/devices/security/security-T85V0.webp +0 -0
  232. package/homebridge-ui/public/assets/devices/security/security-T8600.webp +0 -0
  233. package/homebridge-ui/public/assets/devices/security/security-T86P2.webp +0 -0
  234. package/homebridge-ui/public/assets/devices/security/security-T8790.webp +0 -0
  235. package/homebridge-ui/public/assets/devices/security/security-T87B0.webp +0 -0
  236. package/homebridge-ui/public/assets/devices/security/security-T87B2.webp +0 -0
  237. package/homebridge-ui/public/assets/devices/security/security-T8900.webp +0 -0
  238. package/homebridge-ui/public/assets/devices/security/security-T8910.webp +0 -0
  239. package/homebridge-ui/public/assets/devices/security/security-T8920.webp +0 -0
  240. package/homebridge-ui/public/assets/devices/security/security-T8960.webp +0 -0
  241. package/homebridge-ui/public/assets/devices/security/security-T8B0.webp +0 -0
  242. package/homebridge-ui/public/assets/devices/security/security-T8E00.webp +0 -0
  243. package/homebridge-ui/public/assets/devices/security/security-T8N00.webp +0 -0
  244. package/homebridge-ui/public/assets/devices/security/security-T8W11C.webp +0 -0
  245. package/homebridge-ui/public/assets/devices/security/security-T90F0.webp +0 -0
  246. package/homebridge-ui/public/assets/devices/security/security-T90M0.webp +0 -0
  247. package/homebridge-ui/public/assets/devices/security/security-T90R0.webp +0 -0
  248. package/homebridge-ui/public/assets/devices/security/security-T90S0.webp +0 -0
  249. package/homebridge-ui/public/assets/icons/inventory.svg +1 -1
  250. package/homebridge-ui/public/assets/icons/troubleshoot.svg +1 -0
  251. package/homebridge-ui/public/assets/icons/warning.svg +1 -1
  252. package/homebridge-ui/public/assets/logo-dark.svg +10 -0
  253. package/homebridge-ui/public/assets/logo.svg +10 -0
  254. package/homebridge-ui/public/i18n/en.json +218 -0
  255. package/homebridge-ui/public/i18n/fr.json +218 -0
  256. package/homebridge-ui/public/index.html +377 -28
  257. package/homebridge-ui/public/js/app.js +1065 -0
  258. package/homebridge-ui/public/js/dashboard.js +385 -0
  259. package/homebridge-ui/public/js/legacy-settings.js +37 -0
  260. package/homebridge-ui/public/js/profile-wizard.js +68 -0
  261. package/homebridge-ui/server.js +2 -1393
  262. package/i18n/runtime/en.json +100 -0
  263. package/media/Snapshot-Unavailable.jpg +0 -0
  264. package/media/Snapshot-black.jpg +0 -0
  265. package/media/camera-disabled.jpg +0 -0
  266. package/media/camera-offline.jpg +0 -0
  267. package/package.json +29 -24
  268. package/.claude/CLAUDE.md +0 -175
  269. package/.claude/PRD.md +0 -241
  270. package/.claude/docs/debug-recording-lessons.md +0 -91
  271. package/.claude/docs/hksv-recording-fix.md +0 -160
  272. package/.claude/skills/architect/SKILL.md +0 -76
  273. package/.claude/skills/developer/SKILL.md +0 -59
  274. package/.claude/skills/new-device-support/SKILL.md +0 -212
  275. package/.claude/skills/new-device-support/check-device.mjs +0 -363
  276. package/.claude/skills/new-device-support/map-properties.mjs +0 -450
  277. package/.claude/skills/new-device-support/verify-device.mjs +0 -272
  278. package/.claude/skills/planner/SKILL.md +0 -100
  279. package/.claude/skills/qa/SKILL.md +0 -79
  280. package/.claude/skills/support/SKILL.md +0 -175
  281. package/.prettierignore +0 -7
  282. package/.prettierrc.json +0 -7
  283. package/FUNDING.yml +0 -1
  284. package/dist/accessories/AutoSyncStationAccessory.js +0 -157
  285. package/dist/accessories/AutoSyncStationAccessory.js.map +0 -1
  286. package/dist/accessories/BaseAccessory.js +0 -261
  287. package/dist/accessories/BaseAccessory.js.map +0 -1
  288. package/dist/accessories/CameraAccessory.js +0 -459
  289. package/dist/accessories/CameraAccessory.js.map +0 -1
  290. package/dist/accessories/Device.js +0 -65
  291. package/dist/accessories/Device.js.map +0 -1
  292. package/dist/accessories/EntrySensorAccessory.js +0 -48
  293. package/dist/accessories/EntrySensorAccessory.js.map +0 -1
  294. package/dist/accessories/GarageDoorAccessory.js +0 -160
  295. package/dist/accessories/GarageDoorAccessory.js.map +0 -1
  296. package/dist/accessories/LockAccessory.js +0 -142
  297. package/dist/accessories/LockAccessory.js.map +0 -1
  298. package/dist/accessories/MotionSensorAccessory.js +0 -48
  299. package/dist/accessories/MotionSensorAccessory.js.map +0 -1
  300. package/dist/accessories/SmartDropAccessory.js +0 -141
  301. package/dist/accessories/SmartDropAccessory.js.map +0 -1
  302. package/dist/accessories/StationAccessory.js +0 -373
  303. package/dist/accessories/StationAccessory.js.map +0 -1
  304. package/dist/config.js +0 -26
  305. package/dist/config.js.map +0 -1
  306. package/dist/controller/DebugRecordingManager.js +0 -402
  307. package/dist/controller/DebugRecordingManager.js.map +0 -1
  308. package/dist/controller/LocalLivestreamManager.js +0 -371
  309. package/dist/controller/LocalLivestreamManager.js.map +0 -1
  310. package/dist/controller/recordingDelegate.js +0 -252
  311. package/dist/controller/recordingDelegate.js.map +0 -1
  312. package/dist/controller/snapshotDelegate.js +0 -348
  313. package/dist/controller/snapshotDelegate.js.map +0 -1
  314. package/dist/controller/streamingDelegate.js +0 -389
  315. package/dist/controller/streamingDelegate.js.map +0 -1
  316. package/dist/interfaces.js +0 -2
  317. package/dist/interfaces.js.map +0 -1
  318. package/dist/media/Snapshot-Unavailable.png +0 -0
  319. package/dist/media/Snapshot-Unavailable.xcf +0 -0
  320. package/dist/media/Snapshot-black.png +0 -0
  321. package/dist/media/camera-disabled.png +0 -0
  322. package/dist/media/camera-offline.png +0 -0
  323. package/dist/media/media/Snapshot-Unavailable.png +0 -0
  324. package/dist/media/media/Snapshot-Unavailable.xcf +0 -0
  325. package/dist/media/media/Snapshot-black.png +0 -0
  326. package/dist/media/media/camera-disabled.png +0 -0
  327. package/dist/media/media/camera-offline.png +0 -0
  328. package/dist/utils/Talkback.js +0 -162
  329. package/dist/utils/Talkback.js.map +0 -1
  330. package/dist/utils/accessoriesStore.js +0 -210
  331. package/dist/utils/accessoriesStore.js.map +0 -1
  332. package/dist/utils/configTypes.js +0 -38
  333. package/dist/utils/configTypes.js.map +0 -1
  334. package/dist/utils/ffmpeg.js +0 -1111
  335. package/dist/utils/ffmpeg.js.map +0 -1
  336. package/dist/utils/interfaces.js +0 -8
  337. package/dist/utils/interfaces.js.map +0 -1
  338. package/dist/utils/utils.js +0 -224
  339. package/dist/utils/utils.js.map +0 -1
  340. package/dist/version.js +0 -2
  341. package/dist/version.js.map +0 -1
  342. package/homebridge-eufy-security.png +0 -0
  343. package/homebridge-ui/diagnosticsCrypto.js +0 -112
  344. package/homebridge-ui/public/app.js +0 -237
  345. package/homebridge-ui/public/assets/devices/4g_lte_cam_s330_large.png +0 -0
  346. package/homebridge-ui/public/assets/devices/4g_lte_starlight_large.jpg +0 -0
  347. package/homebridge-ui/public/assets/devices/BATTERY_DOORBELL_C30.png +0 -0
  348. package/homebridge-ui/public/assets/devices/BATTERY_DOORBELL_C31.png +0 -0
  349. package/homebridge-ui/public/assets/devices/batterydoorbell1080p_large.jpg +0 -0
  350. package/homebridge-ui/public/assets/devices/batterydoorbell2k_large.png +0 -0
  351. package/homebridge-ui/public/assets/devices/batterydoorbell2kdual_large.jpg +0 -0
  352. package/homebridge-ui/public/assets/devices/batterydoorbell_e340_large.png +0 -0
  353. package/homebridge-ui/public/assets/devices/eufy-security-client.png +0 -0
  354. package/homebridge-ui/public/assets/devices/eufyCamS4_large.png +0 -0
  355. package/homebridge-ui/public/assets/devices/eufycam2_large.png +0 -0
  356. package/homebridge-ui/public/assets/devices/eufycam2c_large.jpg +0 -0
  357. package/homebridge-ui/public/assets/devices/eufycam2cpro_large.jpg +0 -0
  358. package/homebridge-ui/public/assets/devices/eufycam2pro_large.jpg +0 -0
  359. package/homebridge-ui/public/assets/devices/eufycam3_large.jpg +0 -0
  360. package/homebridge-ui/public/assets/devices/eufycam3c_large.jpg +0 -0
  361. package/homebridge-ui/public/assets/devices/eufycam3pro_large.png +0 -0
  362. package/homebridge-ui/public/assets/devices/eufycam_large.jpg +0 -0
  363. package/homebridge-ui/public/assets/devices/eufycame330_large.jpg +0 -0
  364. package/homebridge-ui/public/assets/devices/flood_freeze_sensor_e20_t90F0_large.png +0 -0
  365. package/homebridge-ui/public/assets/devices/floodlight2_large.jpg +0 -0
  366. package/homebridge-ui/public/assets/devices/floodlight2pro_large.jpg +0 -0
  367. package/homebridge-ui/public/assets/devices/floodlight_large.jpg +0 -0
  368. package/homebridge-ui/public/assets/devices/floodlightcame340_large.jpg +0 -0
  369. package/homebridge-ui/public/assets/devices/garage_camera_t8452_large.png +0 -0
  370. package/homebridge-ui/public/assets/devices/homebase2_large.png +0 -0
  371. package/homebridge-ui/public/assets/devices/homebase3_large.png +0 -0
  372. package/homebridge-ui/public/assets/devices/homebase_large.jpg +0 -0
  373. package/homebridge-ui/public/assets/devices/homebasemini_large.png +0 -0
  374. package/homebridge-ui/public/assets/devices/indoorcamC210_large.png +0 -0
  375. package/homebridge-ui/public/assets/devices/indoorcamC220_large.png +0 -0
  376. package/homebridge-ui/public/assets/devices/indoorcamC220_t8419N_large.png +0 -0
  377. package/homebridge-ui/public/assets/devices/indoorcamE30_large.png +0 -0
  378. package/homebridge-ui/public/assets/devices/indoorcamc120_large.png +0 -0
  379. package/homebridge-ui/public/assets/devices/indoorcammini_large.jpg +0 -0
  380. package/homebridge-ui/public/assets/devices/indoorcamp24_large.png +0 -0
  381. package/homebridge-ui/public/assets/devices/indoorcams350_large.png +0 -0
  382. package/homebridge-ui/public/assets/devices/keypad_large.png +0 -0
  383. package/homebridge-ui/public/assets/devices/minibase_chime_T8023_large.jpg +0 -0
  384. package/homebridge-ui/public/assets/devices/motionsensor_large.png +0 -0
  385. package/homebridge-ui/public/assets/devices/nvr_s4_max_T8N00_large.png +0 -0
  386. package/homebridge-ui/public/assets/devices/pir_sensor_e20_large.png +0 -0
  387. package/homebridge-ui/public/assets/devices/poe_bullet_ptz_cam_s4_T8E00_large.png +0 -0
  388. package/homebridge-ui/public/assets/devices/sensor_large.png +0 -0
  389. package/homebridge-ui/public/assets/devices/siren_sensor_e20_large.png +0 -0
  390. package/homebridge-ui/public/assets/devices/smartdrop_t8790_large.png +0 -0
  391. package/homebridge-ui/public/assets/devices/smartlock_t8500_large.png +0 -0
  392. package/homebridge-ui/public/assets/devices/smartlock_t8500_wifibridge_large.jpg +0 -0
  393. package/homebridge-ui/public/assets/devices/smartlock_t8503_large.png +0 -0
  394. package/homebridge-ui/public/assets/devices/smartlock_t8504_large.jpg +0 -0
  395. package/homebridge-ui/public/assets/devices/smartlock_t8510P_t8520P_large.png +0 -0
  396. package/homebridge-ui/public/assets/devices/smartlock_t85D0_large.png +0 -0
  397. package/homebridge-ui/public/assets/devices/smartlock_t85L0_large.png +0 -0
  398. package/homebridge-ui/public/assets/devices/smartlock_t85P0_large.png +0 -0
  399. package/homebridge-ui/public/assets/devices/smartlock_t85V0_large.png +0 -0
  400. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8502_large.png +0 -0
  401. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8506_large.png +0 -0
  402. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8520_large.png +0 -0
  403. package/homebridge-ui/public/assets/devices/smartlock_touch_t8510_large.png +0 -0
  404. package/homebridge-ui/public/assets/devices/smartlock_touch_t8510_wifibridge_large.jpg +0 -0
  405. package/homebridge-ui/public/assets/devices/smartlock_video_t8530_large.png +0 -0
  406. package/homebridge-ui/public/assets/devices/smartlock_video_t8531_large.png +0 -0
  407. package/homebridge-ui/public/assets/devices/smartlockwifibridge_t8021_large.jpg +0 -0
  408. package/homebridge-ui/public/assets/devices/smartsafe_s10_t7400_large.png +0 -0
  409. package/homebridge-ui/public/assets/devices/smartsafe_s12_t7401_large.png +0 -0
  410. package/homebridge-ui/public/assets/devices/smarttrack_card_t87B2_large.png +0 -0
  411. package/homebridge-ui/public/assets/devices/smarttrack_link_t87B0_large.png +0 -0
  412. package/homebridge-ui/public/assets/devices/smoke_alarm_e10_t90S0_large.png +0 -0
  413. package/homebridge-ui/public/assets/devices/solocamc210_large.jpg +0 -0
  414. package/homebridge-ui/public/assets/devices/solocamc35_large.png +0 -0
  415. package/homebridge-ui/public/assets/devices/solocame20_large.jpg +0 -0
  416. package/homebridge-ui/public/assets/devices/solocame30_large.png +0 -0
  417. package/homebridge-ui/public/assets/devices/solocame40_large.jpg +0 -0
  418. package/homebridge-ui/public/assets/devices/solocame42_large.png +0 -0
  419. package/homebridge-ui/public/assets/devices/solocaml20_large.jpg +0 -0
  420. package/homebridge-ui/public/assets/devices/solocams220_large.jpg +0 -0
  421. package/homebridge-ui/public/assets/devices/solocams340_large.png +0 -0
  422. package/homebridge-ui/public/assets/devices/solocams40_large.jpg +0 -0
  423. package/homebridge-ui/public/assets/devices/soloindoorcamc24_large.jpg +0 -0
  424. package/homebridge-ui/public/assets/devices/solooutdoorcamc22_large.png +0 -0
  425. package/homebridge-ui/public/assets/devices/solooutdoorcamc24_large.jpg +0 -0
  426. package/homebridge-ui/public/assets/devices/unknown.png +0 -0
  427. package/homebridge-ui/public/assets/devices/walllight_s100_large.png +0 -0
  428. package/homebridge-ui/public/assets/devices/walllight_s120_large.png +0 -0
  429. package/homebridge-ui/public/assets/devices/water_freeze_sensor_t8920_large.png +0 -0
  430. package/homebridge-ui/public/assets/devices/wireddoorbell1080p_large.jpg +0 -0
  431. package/homebridge-ui/public/assets/devices/wireddoorbell2k_large.png +0 -0
  432. package/homebridge-ui/public/assets/devices/wireddoorbelldual_large.jpg +0 -0
  433. package/homebridge-ui/public/assets/icons/attach.svg +0 -1
  434. package/homebridge-ui/public/assets/icons/battery_0.svg +0 -1
  435. package/homebridge-ui/public/assets/icons/battery_1.svg +0 -1
  436. package/homebridge-ui/public/assets/icons/battery_2.svg +0 -1
  437. package/homebridge-ui/public/assets/icons/battery_3.svg +0 -1
  438. package/homebridge-ui/public/assets/icons/battery_4.svg +0 -1
  439. package/homebridge-ui/public/assets/icons/battery_5.svg +0 -1
  440. package/homebridge-ui/public/assets/icons/battery_6.svg +0 -1
  441. package/homebridge-ui/public/assets/icons/copy.svg +0 -1
  442. package/homebridge-ui/public/assets/icons/delete.svg +0 -1
  443. package/homebridge-ui/public/assets/icons/download.svg +0 -1
  444. package/homebridge-ui/public/assets/icons/info.svg +0 -1
  445. package/homebridge-ui/public/assets/icons/refresh.svg +0 -1
  446. package/homebridge-ui/public/assets/icons/satellite_alt.svg +0 -1
  447. package/homebridge-ui/public/assets/icons/solar_power.svg +0 -1
  448. package/homebridge-ui/public/components/device-card.js +0 -174
  449. package/homebridge-ui/public/components/guard-modes.js +0 -88
  450. package/homebridge-ui/public/components/number-input.js +0 -121
  451. package/homebridge-ui/public/components/select.js +0 -73
  452. package/homebridge-ui/public/components/toggle.js +0 -68
  453. package/homebridge-ui/public/services/api.js +0 -250
  454. package/homebridge-ui/public/services/config.js +0 -144
  455. package/homebridge-ui/public/style.css +0 -818
  456. package/homebridge-ui/public/utils/countries.js +0 -73
  457. package/homebridge-ui/public/utils/device-images.js +0 -102
  458. package/homebridge-ui/public/utils/helpers.js +0 -115
  459. package/homebridge-ui/public/views/dashboard.js +0 -226
  460. package/homebridge-ui/public/views/device-detail.js +0 -654
  461. package/homebridge-ui/public/views/diagnostics.js +0 -402
  462. package/homebridge-ui/public/views/login.js +0 -650
  463. package/homebridge-ui/public/views/recordings.js +0 -319
  464. package/homebridge-ui/public/views/settings.js +0 -197
  465. package/homebridge-ui/public/views/unsupported-detail.js +0 -296
  466. package/media/Snapshot-Unavailable.png +0 -0
  467. package/media/Snapshot-Unavailable.xcf +0 -0
  468. package/media/Snapshot-black.png +0 -0
  469. package/media/camera-disabled.png +0 -0
  470. package/media/camera-offline.png +0 -0
  471. package/scripts/decrypt-diagnostics.mjs +0 -257
@@ -0,0 +1,662 @@
1
+ import { CapabilityNotSupportedError, } from '@mega-yfue/eufy-sdk';
2
+ export const SMART_LIGHT_ADAPTER_KEY = 'smart-light.lightbulb';
3
+ const SMART_LIGHT_POWER_READ = {
4
+ id: 'smart_light.power.read',
5
+ kind: 'read',
6
+ type: 'bool',
7
+ writable: true,
8
+ };
9
+ const SMART_LIGHT_POWER_WRITE = {
10
+ id: 'smart_light.power.persistent-operation',
11
+ kind: 'persistent-operation',
12
+ };
13
+ const SMART_LIGHT_BRIGHTNESS_READ = {
14
+ id: 'smart_light.brightness.read',
15
+ kind: 'read',
16
+ type: 'number',
17
+ writable: true,
18
+ };
19
+ const SMART_LIGHT_BRIGHTNESS_WRITE = {
20
+ id: 'smart_light.brightness.persistent-operation',
21
+ kind: 'persistent-operation',
22
+ };
23
+ const SMART_LIGHT_STATE_EVENT = {
24
+ id: 'smart_light.smartLightState.event',
25
+ kind: 'event',
26
+ };
27
+ const SMART_LIGHT_COLOR_WRITE = {
28
+ id: 'smart_light.setColor.momentary-action',
29
+ kind: 'momentary-action',
30
+ };
31
+ const SMART_LIGHT_STATES = new WeakMap();
32
+ const OPERATION_DEADLINE_MS = 8_000;
33
+ const RECONCILIATION_WINDOW_MS = 60_000;
34
+ /** Coalesces HomeKit's split color characteristics into one RGB publication and retains its acknowledgement. */
35
+ class AcknowledgedColorWrites {
36
+ issue;
37
+ communicationFailure;
38
+ incompleteColor;
39
+ acknowledge;
40
+ diagnose;
41
+ pending;
42
+ active;
43
+ scheduled;
44
+ acknowledged;
45
+ detached = false;
46
+ constructor(acknowledged, issue, communicationFailure, incompleteColor, acknowledge, diagnose) {
47
+ this.issue = issue;
48
+ this.communicationFailure = communicationFailure;
49
+ this.incompleteColor = incompleteColor;
50
+ this.acknowledge = acknowledge;
51
+ this.diagnose = diagnose;
52
+ this.acknowledged = acknowledged;
53
+ }
54
+ read(component) {
55
+ return this.acknowledged?.[component];
56
+ }
57
+ request(component, value) {
58
+ return new Promise((resolve, reject) => {
59
+ const request = {
60
+ settled: false,
61
+ deadline: undefined,
62
+ resolve,
63
+ reject,
64
+ };
65
+ request.deadline = setTimeout(() => this.timeout(request), OPERATION_DEADLINE_MS);
66
+ this.pending ??= { requests: [] };
67
+ this.pending[component] = value;
68
+ this.pending.requests.push(request);
69
+ this.schedule();
70
+ });
71
+ }
72
+ detach() {
73
+ this.detached = true;
74
+ if (this.scheduled) {
75
+ clearTimeout(this.scheduled);
76
+ }
77
+ for (const request of [...(this.active?.requests ?? []), ...(this.pending?.requests ?? [])]) {
78
+ this.settle(request, 'reject', this.communicationFailure());
79
+ }
80
+ this.active = undefined;
81
+ this.pending = undefined;
82
+ this.scheduled = undefined;
83
+ }
84
+ schedule() {
85
+ if (this.detached || this.active || this.scheduled) {
86
+ return;
87
+ }
88
+ this.scheduled = setTimeout(() => {
89
+ this.scheduled = undefined;
90
+ this.flush();
91
+ }, 0);
92
+ }
93
+ flush() {
94
+ const batch = this.pending;
95
+ this.pending = undefined;
96
+ if (!batch) {
97
+ return;
98
+ }
99
+ const color = {
100
+ hue: batch.hue ?? this.acknowledged?.hue,
101
+ saturation: batch.saturation ?? this.acknowledged?.saturation,
102
+ };
103
+ if (color.hue === undefined || color.saturation === undefined) {
104
+ for (const request of batch.requests) {
105
+ this.settle(request, 'reject', this.incompleteColor());
106
+ }
107
+ this.schedule();
108
+ return;
109
+ }
110
+ const acknowledgedColor = { hue: color.hue, saturation: color.saturation };
111
+ this.active = batch;
112
+ Promise.resolve()
113
+ .then(() => this.issue(hsvToRgb(acknowledgedColor.hue, acknowledgedColor.saturation)))
114
+ .then(() => this.complete(batch, acknowledgedColor), () => this.fail(batch));
115
+ }
116
+ complete(batch, color) {
117
+ if (this.active !== batch) {
118
+ return;
119
+ }
120
+ this.acknowledged = color;
121
+ this.acknowledge(color);
122
+ this.diagnose(false, 'recovered');
123
+ for (const request of batch.requests) {
124
+ this.settle(request, 'resolve');
125
+ }
126
+ this.active = undefined;
127
+ this.schedule();
128
+ }
129
+ fail(batch) {
130
+ if (this.active !== batch) {
131
+ return;
132
+ }
133
+ const error = this.communicationFailure();
134
+ for (const request of batch.requests) {
135
+ this.settle(request, 'reject', error);
136
+ }
137
+ this.diagnose(true, 'operation-failure');
138
+ this.active = undefined;
139
+ this.schedule();
140
+ }
141
+ timeout(request) {
142
+ if (request.settled) {
143
+ return;
144
+ }
145
+ this.settle(request, 'reject', this.communicationFailure());
146
+ this.diagnose(true, 'timeout');
147
+ if (this.pending) {
148
+ this.pending.requests = this.pending.requests.filter(({ settled }) => !settled);
149
+ if (this.pending.requests.length === 0) {
150
+ this.pending = undefined;
151
+ }
152
+ }
153
+ }
154
+ settle(request, result, error) {
155
+ if (request.settled) {
156
+ return;
157
+ }
158
+ request.settled = true;
159
+ clearTimeout(request.deadline);
160
+ if (result === 'resolve') {
161
+ request.resolve();
162
+ }
163
+ else {
164
+ request.reject(error);
165
+ }
166
+ }
167
+ }
168
+ /** Convert HomeKit hue/saturation to full-value RGB while configured device brightness remains independent. */
169
+ function hsvToRgb(hue, saturation) {
170
+ const h = hue === 360 ? 0 : hue / 60;
171
+ const s = saturation / 100;
172
+ const chroma = s;
173
+ const x = chroma * (1 - Math.abs((h % 2) - 1));
174
+ const [red, green, blue] = h < 1
175
+ ? [chroma, x, 0]
176
+ : h < 2
177
+ ? [x, chroma, 0]
178
+ : h < 3
179
+ ? [0, chroma, x]
180
+ : h < 4
181
+ ? [0, x, chroma]
182
+ : h < 5
183
+ ? [x, 0, chroma]
184
+ : [chroma, 0, x];
185
+ const match = 1 - chroma;
186
+ return {
187
+ red: Math.round((red + match) * 255),
188
+ green: Math.round((green + match) * 255),
189
+ blue: Math.round((blue + match) * 255),
190
+ };
191
+ }
192
+ /** Serializes one persistent member while keeping operation acknowledgement separate from observation. */
193
+ class PersistentMemberWrites {
194
+ issue;
195
+ communicationFailure;
196
+ operationFailure;
197
+ isNonRetryable;
198
+ diagnose;
199
+ restore;
200
+ generation = 0;
201
+ active;
202
+ queued;
203
+ reconciliation;
204
+ blockedError;
205
+ detached = false;
206
+ constructor(issue, communicationFailure, operationFailure, isNonRetryable, diagnose, restore) {
207
+ this.issue = issue;
208
+ this.communicationFailure = communicationFailure;
209
+ this.operationFailure = operationFailure;
210
+ this.isNonRetryable = isNonRetryable;
211
+ this.diagnose = diagnose;
212
+ this.restore = restore;
213
+ }
214
+ request(value) {
215
+ if (this.blockedError) {
216
+ return Promise.reject(this.blockedError);
217
+ }
218
+ const generation = ++this.generation;
219
+ return new Promise((resolve, reject) => {
220
+ const request = {
221
+ generation,
222
+ value,
223
+ settled: false,
224
+ deadline: undefined,
225
+ resolve,
226
+ reject,
227
+ };
228
+ request.deadline = setTimeout(() => this.timeout(request), OPERATION_DEADLINE_MS);
229
+ if (!this.active) {
230
+ this.start({ generation, value, requests: [request], reconciled: false });
231
+ return;
232
+ }
233
+ if (this.queued) {
234
+ this.queued.generation = generation;
235
+ this.queued.value = value;
236
+ this.queued.reconciled = false;
237
+ this.queued.requests.push(request);
238
+ }
239
+ else {
240
+ this.queued = { generation, value, requests: [request], reconciled: false };
241
+ }
242
+ });
243
+ }
244
+ observe() {
245
+ if (this.active) {
246
+ this.active.reconciled = true;
247
+ }
248
+ if (this.queued) {
249
+ this.queued.reconciled = true;
250
+ }
251
+ if (this.reconciliation) {
252
+ clearTimeout(this.reconciliation);
253
+ this.reconciliation = undefined;
254
+ }
255
+ if (!this.blockedError) {
256
+ this.diagnose('operation', false, 'recovered');
257
+ }
258
+ this.diagnose('reconciliation', false, 'recovered');
259
+ }
260
+ detach() {
261
+ this.detached = true;
262
+ if (this.reconciliation) {
263
+ clearTimeout(this.reconciliation);
264
+ }
265
+ for (const request of [...(this.active?.requests ?? []), ...(this.queued?.requests ?? [])]) {
266
+ this.settle(request, 'reject', this.communicationFailure());
267
+ }
268
+ this.active = undefined;
269
+ this.queued = undefined;
270
+ this.reconciliation = undefined;
271
+ }
272
+ start(batch) {
273
+ if (this.detached) {
274
+ return;
275
+ }
276
+ if (this.reconciliation) {
277
+ clearTimeout(this.reconciliation);
278
+ this.reconciliation = undefined;
279
+ }
280
+ this.active = batch;
281
+ Promise.resolve()
282
+ .then(() => this.issue(batch.value))
283
+ .then(() => this.complete(batch), (error) => this.fail(batch, error));
284
+ }
285
+ complete(batch) {
286
+ if (this.active !== batch) {
287
+ return;
288
+ }
289
+ for (const request of batch.requests) {
290
+ this.settle(request, 'resolve');
291
+ }
292
+ this.diagnose('operation', false, 'recovered');
293
+ if (!batch.reconciled) {
294
+ this.reconciliation = setTimeout(() => {
295
+ this.reconciliation = undefined;
296
+ this.diagnose('reconciliation', true, 'expired');
297
+ }, RECONCILIATION_WINDOW_MS);
298
+ }
299
+ this.active = undefined;
300
+ queueMicrotask(this.restore);
301
+ this.startQueued();
302
+ }
303
+ fail(batch, cause) {
304
+ if (this.active !== batch) {
305
+ return;
306
+ }
307
+ const error = this.operationFailure(cause);
308
+ for (const request of batch.requests) {
309
+ this.settle(request, 'reject', error);
310
+ }
311
+ const nonRetryable = this.isNonRetryable(cause);
312
+ if (nonRetryable) {
313
+ this.blockedError = error;
314
+ for (const request of this.queued?.requests ?? []) {
315
+ this.settle(request, 'reject', error);
316
+ }
317
+ this.queued = undefined;
318
+ }
319
+ this.diagnose('operation', true, nonRetryable ? 'capability-not-supported' : 'operation-failure');
320
+ this.active = undefined;
321
+ queueMicrotask(this.restore);
322
+ this.startQueued();
323
+ }
324
+ timeout(request) {
325
+ if (request.settled) {
326
+ return;
327
+ }
328
+ this.settle(request, 'reject', this.communicationFailure());
329
+ this.diagnose('operation', true, 'timeout');
330
+ if (this.active?.requests.every(({ settled }) => settled)) {
331
+ this.active = undefined;
332
+ queueMicrotask(this.restore);
333
+ this.startQueued();
334
+ return;
335
+ }
336
+ if (this.queued) {
337
+ this.queued.requests = this.queued.requests.filter(({ settled }) => !settled);
338
+ if (this.queued.requests.length === 0) {
339
+ this.queued = undefined;
340
+ }
341
+ else {
342
+ const newest = this.queued.requests.at(-1);
343
+ this.queued.generation = newest.generation;
344
+ this.queued.value = newest.value;
345
+ }
346
+ }
347
+ }
348
+ startQueued() {
349
+ const queued = this.queued;
350
+ this.queued = undefined;
351
+ if (!queued) {
352
+ return;
353
+ }
354
+ queued.requests = queued.requests.filter(({ settled }) => !settled);
355
+ if (queued.requests.length > 0) {
356
+ const newest = queued.requests.at(-1);
357
+ queued.generation = newest.generation;
358
+ queued.value = newest.value;
359
+ this.start(queued);
360
+ }
361
+ }
362
+ settle(request, result, error) {
363
+ if (request.settled) {
364
+ return;
365
+ }
366
+ request.settled = true;
367
+ clearTimeout(request.deadline);
368
+ if (result === 'resolve') {
369
+ request.resolve();
370
+ }
371
+ else {
372
+ request.reject(error);
373
+ }
374
+ }
375
+ }
376
+ const COVERAGE = [
377
+ SMART_LIGHT_POWER_READ,
378
+ SMART_LIGHT_POWER_WRITE,
379
+ SMART_LIGHT_BRIGHTNESS_READ,
380
+ SMART_LIGHT_BRIGHTNESS_WRITE,
381
+ SMART_LIGHT_STATE_EVENT,
382
+ SMART_LIGHT_COLOR_WRITE,
383
+ ].map(({ id }) => id);
384
+ /** Complete HomeKit policy for evidenced Life smart-light power, brightness, and acknowledged color. */
385
+ export const SMART_LIGHT_ADAPTER = {
386
+ key: SMART_LIGHT_ADAPTER_KEY,
387
+ role: 'primary-purpose',
388
+ requires: [
389
+ SMART_LIGHT_POWER_READ,
390
+ SMART_LIGHT_POWER_WRITE,
391
+ SMART_LIGHT_BRIGHTNESS_READ,
392
+ SMART_LIGHT_BRIGHTNESS_WRITE,
393
+ SMART_LIGHT_STATE_EVENT,
394
+ ],
395
+ coverage: COVERAGE,
396
+ attach: attachSmartLight,
397
+ };
398
+ /** Attaches authoritative power and configured brightness to one official Lightbulb service. */
399
+ function attachSmartLight(context) {
400
+ const { accessory, hap } = context;
401
+ const device = context.device;
402
+ let light;
403
+ try {
404
+ light = device.smartLight?.();
405
+ }
406
+ catch {
407
+ context.diagnose({
408
+ code: 'smart-light-capability-unavailable',
409
+ capability: 'smart_light',
410
+ member: 'power',
411
+ active: true,
412
+ reason: 'sdk-fault',
413
+ });
414
+ return undefined;
415
+ }
416
+ if (!light || typeof light.set !== 'function' || typeof light.setBrightness !== 'function') {
417
+ context.diagnose({
418
+ code: 'smart-light-capability-unavailable',
419
+ capability: 'smart_light',
420
+ member: !light || typeof light.set !== 'function' ? 'power' : 'brightness',
421
+ active: true,
422
+ reason: 'missing',
423
+ });
424
+ return undefined;
425
+ }
426
+ const service = accessory.getServiceById(hap.Service.Lightbulb, SMART_LIGHT_ADAPTER_KEY) ??
427
+ accessory.addService(hap.Service.Lightbulb, accessory.displayName, SMART_LIGHT_ADAPTER_KEY);
428
+ const previousState = SMART_LIGHT_STATES.get(service);
429
+ for (const member of ['power', 'brightness']) {
430
+ context.diagnose({
431
+ code: 'smart-light-capability-unavailable',
432
+ capability: 'smart_light',
433
+ member,
434
+ active: false,
435
+ reason: 'recovered',
436
+ });
437
+ const codes = previousState?.[member === 'power' ? 'powerBlocked' : 'brightnessBlocked']
438
+ ? ['smart-light-reconciliation-expired']
439
+ : ['smart-light-operation-failed', 'smart-light-reconciliation-expired'];
440
+ for (const code of codes) {
441
+ context.diagnose({
442
+ code,
443
+ capability: 'smart_light',
444
+ member,
445
+ active: false,
446
+ reason: 'recovered',
447
+ });
448
+ context.observed(code);
449
+ }
450
+ }
451
+ service.addOptionalCharacteristic(hap.Characteristic.Brightness);
452
+ const state = {
453
+ owner: Symbol('smart-light-owner'),
454
+ invalidPower: false,
455
+ invalidBrightness: false,
456
+ powerBlocked: previousState?.powerBlocked ?? false,
457
+ brightnessBlocked: previousState?.brightnessBlocked ?? false,
458
+ };
459
+ SMART_LIGHT_STATES.set(service, state);
460
+ const power = service.getCharacteristic(hap.Characteristic.On);
461
+ const brightness = service.getCharacteristic(hap.Characteristic.Brightness);
462
+ const colorEvidence = context.evidence.has(SMART_LIGHT_COLOR_WRITE.id) && typeof light.setColor === 'function';
463
+ const accessoryContext = (accessory.context ?? {});
464
+ accessory.context = accessoryContext;
465
+ const storedColor = accessoryContext.homebridgeEufySmartLightColor;
466
+ const acknowledgedColor = storedColor?.version === 1 &&
467
+ Number.isFinite(storedColor.hue) &&
468
+ storedColor.hue >= 0 &&
469
+ storedColor.hue <= 360 &&
470
+ Number.isFinite(storedColor.saturation) &&
471
+ storedColor.saturation >= 0 &&
472
+ storedColor.saturation <= 100
473
+ ? { hue: storedColor.hue, saturation: storedColor.saturation }
474
+ : undefined;
475
+ if (!colorEvidence) {
476
+ delete accessoryContext.homebridgeEufySmartLightColor;
477
+ for (const characteristicType of [hap.Characteristic.Hue, hap.Characteristic.Saturation]) {
478
+ if (service.testCharacteristic(characteristicType)) {
479
+ service.removeCharacteristic(service.getCharacteristic(characteristicType));
480
+ }
481
+ }
482
+ }
483
+ const diagnoseObservation = (member, active, reason) => {
484
+ context.diagnose({
485
+ code: 'invalid-smart-light-observation',
486
+ capability: 'smart_light',
487
+ member,
488
+ active,
489
+ reason,
490
+ });
491
+ if (!active) {
492
+ context.observed('invalid-smart-light-observation');
493
+ }
494
+ };
495
+ const read = (member) => {
496
+ let value;
497
+ try {
498
+ value = state[member] ?? light[member];
499
+ }
500
+ catch {
501
+ diagnoseObservation(member, true, 'sdk-fault');
502
+ throw new hap.HapStatusError(hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
503
+ }
504
+ const valid = member === 'power'
505
+ ? typeof value === 'boolean'
506
+ : typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 100;
507
+ if (state[member === 'power' ? 'invalidPower' : 'invalidBrightness'] || !valid) {
508
+ diagnoseObservation(member, true, value === undefined ? 'missing' : 'malformed');
509
+ throw new hap.HapStatusError(hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
510
+ }
511
+ diagnoseObservation(member, false, 'recovered');
512
+ return value;
513
+ };
514
+ power.onGet(() => read('power'));
515
+ brightness.onGet(() => read('brightness'));
516
+ if (colorEvidence) {
517
+ service.addOptionalCharacteristic(hap.Characteristic.Hue);
518
+ service.addOptionalCharacteristic(hap.Characteristic.Saturation);
519
+ const hue = service.getCharacteristic(hap.Characteristic.Hue);
520
+ const saturation = service.getCharacteristic(hap.Characteristic.Saturation);
521
+ const readColor = (component) => {
522
+ const value = state.colorWrites?.read(component);
523
+ if (value === undefined) {
524
+ throw new hap.HapStatusError(hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
525
+ }
526
+ return value;
527
+ };
528
+ state.colorWrites = new AcknowledgedColorWrites(acknowledgedColor, (color) => light.setColor(color), () => new hap.HapStatusError(hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE), () => new hap.HapStatusError(hap.HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE), (color) => {
529
+ accessoryContext.homebridgeEufySmartLightColor = { version: 1, ...color };
530
+ hue.updateValue(color.hue);
531
+ saturation.updateValue(color.saturation);
532
+ context.persist();
533
+ }, (active, reason) => {
534
+ context.diagnose({
535
+ code: 'smart-light-operation-failed',
536
+ capability: 'smart_light',
537
+ member: 'color',
538
+ active,
539
+ reason,
540
+ });
541
+ if (!active) {
542
+ context.observed('smart-light-operation-failed');
543
+ }
544
+ });
545
+ hue.onGet(() => readColor('hue'));
546
+ saturation.onGet(() => readColor('saturation'));
547
+ hue.onSet((value) => {
548
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 360) {
549
+ throw new hap.HapStatusError(hap.HAPStatus.INVALID_VALUE_IN_REQUEST);
550
+ }
551
+ return state.colorWrites.request('hue', value);
552
+ });
553
+ saturation.onSet((value) => {
554
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 100) {
555
+ throw new hap.HapStatusError(hap.HAPStatus.INVALID_VALUE_IN_REQUEST);
556
+ }
557
+ return state.colorWrites.request('saturation', value);
558
+ });
559
+ }
560
+ const writes = (member, issue, restore) => new PersistentMemberWrites(issue, () => new hap.HapStatusError(hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE), (error) => new hap.HapStatusError(error instanceof CapabilityNotSupportedError
561
+ ? hap.HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE
562
+ : hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE), (error) => error instanceof CapabilityNotSupportedError, (condition, active, reason) => {
563
+ const code = condition === 'reconciliation' ? 'smart-light-reconciliation-expired' : 'smart-light-operation-failed';
564
+ if (condition === 'operation') {
565
+ const blocked = member === 'power' ? 'powerBlocked' : 'brightnessBlocked';
566
+ if (active && reason === 'capability-not-supported') {
567
+ state[blocked] = true;
568
+ }
569
+ else if (!active) {
570
+ state[blocked] = false;
571
+ }
572
+ }
573
+ context.diagnose({ code, capability: 'smart_light', member, active, reason });
574
+ if (!active) {
575
+ context.observed(code);
576
+ }
577
+ }, restore);
578
+ state.powerWrites = writes('power', (value) => light.set(value), () => {
579
+ try {
580
+ power.updateValue(read('power'));
581
+ }
582
+ catch { }
583
+ });
584
+ state.brightnessWrites = writes('brightness', (value) => light.setBrightness(value), () => {
585
+ try {
586
+ brightness.updateValue(read('brightness'));
587
+ }
588
+ catch { }
589
+ });
590
+ power.onSet((value) => {
591
+ if (typeof value !== 'boolean') {
592
+ throw new hap.HapStatusError(hap.HAPStatus.INVALID_VALUE_IN_REQUEST);
593
+ }
594
+ if (state.powerBlocked) {
595
+ throw new hap.HapStatusError(hap.HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE);
596
+ }
597
+ return state.powerWrites.request(value);
598
+ });
599
+ brightness.onSet((value) => {
600
+ if (typeof value !== 'number' || !Number.isInteger(value) || value < 0 || value > 100) {
601
+ throw new hap.HapStatusError(hap.HAPStatus.INVALID_VALUE_IN_REQUEST);
602
+ }
603
+ if (state.brightnessBlocked) {
604
+ throw new hap.HapStatusError(hap.HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE);
605
+ }
606
+ return state.brightnessWrites.request(value);
607
+ });
608
+ return {
609
+ event(event) {
610
+ if (event.eventName !== 'smartLightState') {
611
+ return undefined;
612
+ }
613
+ let valid = false;
614
+ let malformed = false;
615
+ if (event.power !== undefined) {
616
+ if (typeof event.power === 'boolean') {
617
+ state.power = event.power;
618
+ state.invalidPower = false;
619
+ state.powerWrites?.observe();
620
+ power.updateValue(event.power);
621
+ diagnoseObservation('power', false, 'recovered');
622
+ valid = true;
623
+ }
624
+ else {
625
+ state.invalidPower = true;
626
+ diagnoseObservation('power', true, 'malformed');
627
+ malformed = true;
628
+ }
629
+ }
630
+ if (event.brightness !== undefined) {
631
+ if (typeof event.brightness === 'number' &&
632
+ Number.isInteger(event.brightness) &&
633
+ event.brightness >= 0 &&
634
+ event.brightness <= 100) {
635
+ state.brightness = event.brightness;
636
+ state.invalidBrightness = false;
637
+ state.brightnessWrites?.observe();
638
+ brightness.updateValue(event.brightness);
639
+ diagnoseObservation('brightness', false, 'recovered');
640
+ valid = true;
641
+ }
642
+ else {
643
+ state.invalidBrightness = true;
644
+ diagnoseObservation('brightness', true, 'malformed');
645
+ malformed = true;
646
+ }
647
+ }
648
+ return { event: 'smart-light-state', observation: malformed ? 'malformed' : valid ? 'valid' : 'missing' };
649
+ },
650
+ detach() {
651
+ if (SMART_LIGHT_STATES.get(service)?.owner !== state.owner) {
652
+ return;
653
+ }
654
+ state.powerWrites?.detach();
655
+ state.brightnessWrites?.detach();
656
+ state.colorWrites?.detach();
657
+ SMART_LIGHT_STATES.delete(service);
658
+ accessory.removeService(service);
659
+ },
660
+ };
661
+ }
662
+ //# sourceMappingURL=smart-light.js.map