@homebridge-plugins/homebridge-eufy-security 4.7.1 → 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 (469) 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 -769
  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 -431
  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/LockAccessory.js +0 -142
  295. package/dist/accessories/LockAccessory.js.map +0 -1
  296. package/dist/accessories/MotionSensorAccessory.js +0 -48
  297. package/dist/accessories/MotionSensorAccessory.js.map +0 -1
  298. package/dist/accessories/SmartDropAccessory.js +0 -141
  299. package/dist/accessories/SmartDropAccessory.js.map +0 -1
  300. package/dist/accessories/StationAccessory.js +0 -373
  301. package/dist/accessories/StationAccessory.js.map +0 -1
  302. package/dist/config.js +0 -26
  303. package/dist/config.js.map +0 -1
  304. package/dist/controller/DebugRecordingManager.js +0 -402
  305. package/dist/controller/DebugRecordingManager.js.map +0 -1
  306. package/dist/controller/LocalLivestreamManager.js +0 -371
  307. package/dist/controller/LocalLivestreamManager.js.map +0 -1
  308. package/dist/controller/recordingDelegate.js +0 -252
  309. package/dist/controller/recordingDelegate.js.map +0 -1
  310. package/dist/controller/snapshotDelegate.js +0 -348
  311. package/dist/controller/snapshotDelegate.js.map +0 -1
  312. package/dist/controller/streamingDelegate.js +0 -389
  313. package/dist/controller/streamingDelegate.js.map +0 -1
  314. package/dist/interfaces.js +0 -2
  315. package/dist/interfaces.js.map +0 -1
  316. package/dist/media/Snapshot-Unavailable.png +0 -0
  317. package/dist/media/Snapshot-Unavailable.xcf +0 -0
  318. package/dist/media/Snapshot-black.png +0 -0
  319. package/dist/media/camera-disabled.png +0 -0
  320. package/dist/media/camera-offline.png +0 -0
  321. package/dist/media/media/Snapshot-Unavailable.png +0 -0
  322. package/dist/media/media/Snapshot-Unavailable.xcf +0 -0
  323. package/dist/media/media/Snapshot-black.png +0 -0
  324. package/dist/media/media/camera-disabled.png +0 -0
  325. package/dist/media/media/camera-offline.png +0 -0
  326. package/dist/utils/Talkback.js +0 -162
  327. package/dist/utils/Talkback.js.map +0 -1
  328. package/dist/utils/accessoriesStore.js +0 -207
  329. package/dist/utils/accessoriesStore.js.map +0 -1
  330. package/dist/utils/configTypes.js +0 -36
  331. package/dist/utils/configTypes.js.map +0 -1
  332. package/dist/utils/ffmpeg.js +0 -1111
  333. package/dist/utils/ffmpeg.js.map +0 -1
  334. package/dist/utils/interfaces.js +0 -8
  335. package/dist/utils/interfaces.js.map +0 -1
  336. package/dist/utils/utils.js +0 -224
  337. package/dist/utils/utils.js.map +0 -1
  338. package/dist/version.js +0 -2
  339. package/dist/version.js.map +0 -1
  340. package/homebridge-eufy-security.png +0 -0
  341. package/homebridge-ui/diagnosticsCrypto.js +0 -112
  342. package/homebridge-ui/public/app.js +0 -237
  343. package/homebridge-ui/public/assets/devices/4g_lte_cam_s330_large.png +0 -0
  344. package/homebridge-ui/public/assets/devices/4g_lte_starlight_large.jpg +0 -0
  345. package/homebridge-ui/public/assets/devices/BATTERY_DOORBELL_C30.png +0 -0
  346. package/homebridge-ui/public/assets/devices/BATTERY_DOORBELL_C31.png +0 -0
  347. package/homebridge-ui/public/assets/devices/batterydoorbell1080p_large.jpg +0 -0
  348. package/homebridge-ui/public/assets/devices/batterydoorbell2k_large.png +0 -0
  349. package/homebridge-ui/public/assets/devices/batterydoorbell2kdual_large.jpg +0 -0
  350. package/homebridge-ui/public/assets/devices/batterydoorbell_e340_large.png +0 -0
  351. package/homebridge-ui/public/assets/devices/eufy-security-client.png +0 -0
  352. package/homebridge-ui/public/assets/devices/eufyCamS4_large.png +0 -0
  353. package/homebridge-ui/public/assets/devices/eufycam2_large.png +0 -0
  354. package/homebridge-ui/public/assets/devices/eufycam2c_large.jpg +0 -0
  355. package/homebridge-ui/public/assets/devices/eufycam2cpro_large.jpg +0 -0
  356. package/homebridge-ui/public/assets/devices/eufycam2pro_large.jpg +0 -0
  357. package/homebridge-ui/public/assets/devices/eufycam3_large.jpg +0 -0
  358. package/homebridge-ui/public/assets/devices/eufycam3c_large.jpg +0 -0
  359. package/homebridge-ui/public/assets/devices/eufycam3pro_large.png +0 -0
  360. package/homebridge-ui/public/assets/devices/eufycam_large.jpg +0 -0
  361. package/homebridge-ui/public/assets/devices/eufycame330_large.jpg +0 -0
  362. package/homebridge-ui/public/assets/devices/flood_freeze_sensor_e20_t90F0_large.png +0 -0
  363. package/homebridge-ui/public/assets/devices/floodlight2_large.jpg +0 -0
  364. package/homebridge-ui/public/assets/devices/floodlight2pro_large.jpg +0 -0
  365. package/homebridge-ui/public/assets/devices/floodlight_large.jpg +0 -0
  366. package/homebridge-ui/public/assets/devices/floodlightcame340_large.jpg +0 -0
  367. package/homebridge-ui/public/assets/devices/garage_camera_t8452_large.png +0 -0
  368. package/homebridge-ui/public/assets/devices/homebase2_large.png +0 -0
  369. package/homebridge-ui/public/assets/devices/homebase3_large.png +0 -0
  370. package/homebridge-ui/public/assets/devices/homebase_large.jpg +0 -0
  371. package/homebridge-ui/public/assets/devices/homebasemini_large.png +0 -0
  372. package/homebridge-ui/public/assets/devices/indoorcamC210_large.png +0 -0
  373. package/homebridge-ui/public/assets/devices/indoorcamC220_large.png +0 -0
  374. package/homebridge-ui/public/assets/devices/indoorcamC220_t8419N_large.png +0 -0
  375. package/homebridge-ui/public/assets/devices/indoorcamE30_large.png +0 -0
  376. package/homebridge-ui/public/assets/devices/indoorcamc120_large.png +0 -0
  377. package/homebridge-ui/public/assets/devices/indoorcammini_large.jpg +0 -0
  378. package/homebridge-ui/public/assets/devices/indoorcamp24_large.png +0 -0
  379. package/homebridge-ui/public/assets/devices/indoorcams350_large.png +0 -0
  380. package/homebridge-ui/public/assets/devices/keypad_large.png +0 -0
  381. package/homebridge-ui/public/assets/devices/minibase_chime_T8023_large.jpg +0 -0
  382. package/homebridge-ui/public/assets/devices/motionsensor_large.png +0 -0
  383. package/homebridge-ui/public/assets/devices/nvr_s4_max_T8N00_large.png +0 -0
  384. package/homebridge-ui/public/assets/devices/pir_sensor_e20_large.png +0 -0
  385. package/homebridge-ui/public/assets/devices/poe_bullet_ptz_cam_s4_T8E00_large.png +0 -0
  386. package/homebridge-ui/public/assets/devices/sensor_large.png +0 -0
  387. package/homebridge-ui/public/assets/devices/siren_sensor_e20_large.png +0 -0
  388. package/homebridge-ui/public/assets/devices/smartdrop_t8790_large.png +0 -0
  389. package/homebridge-ui/public/assets/devices/smartlock_t8500_large.png +0 -0
  390. package/homebridge-ui/public/assets/devices/smartlock_t8500_wifibridge_large.jpg +0 -0
  391. package/homebridge-ui/public/assets/devices/smartlock_t8503_large.png +0 -0
  392. package/homebridge-ui/public/assets/devices/smartlock_t8504_large.jpg +0 -0
  393. package/homebridge-ui/public/assets/devices/smartlock_t8510P_t8520P_large.png +0 -0
  394. package/homebridge-ui/public/assets/devices/smartlock_t85D0_large.png +0 -0
  395. package/homebridge-ui/public/assets/devices/smartlock_t85L0_large.png +0 -0
  396. package/homebridge-ui/public/assets/devices/smartlock_t85P0_large.png +0 -0
  397. package/homebridge-ui/public/assets/devices/smartlock_t85V0_large.png +0 -0
  398. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8502_large.png +0 -0
  399. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8506_large.png +0 -0
  400. package/homebridge-ui/public/assets/devices/smartlock_touch_and_wifi_t8520_large.png +0 -0
  401. package/homebridge-ui/public/assets/devices/smartlock_touch_t8510_large.png +0 -0
  402. package/homebridge-ui/public/assets/devices/smartlock_touch_t8510_wifibridge_large.jpg +0 -0
  403. package/homebridge-ui/public/assets/devices/smartlock_video_t8530_large.png +0 -0
  404. package/homebridge-ui/public/assets/devices/smartlock_video_t8531_large.png +0 -0
  405. package/homebridge-ui/public/assets/devices/smartlockwifibridge_t8021_large.jpg +0 -0
  406. package/homebridge-ui/public/assets/devices/smartsafe_s10_t7400_large.png +0 -0
  407. package/homebridge-ui/public/assets/devices/smartsafe_s12_t7401_large.png +0 -0
  408. package/homebridge-ui/public/assets/devices/smarttrack_card_t87B2_large.png +0 -0
  409. package/homebridge-ui/public/assets/devices/smarttrack_link_t87B0_large.png +0 -0
  410. package/homebridge-ui/public/assets/devices/smoke_alarm_e10_t90S0_large.png +0 -0
  411. package/homebridge-ui/public/assets/devices/solocamc210_large.jpg +0 -0
  412. package/homebridge-ui/public/assets/devices/solocamc35_large.png +0 -0
  413. package/homebridge-ui/public/assets/devices/solocame20_large.jpg +0 -0
  414. package/homebridge-ui/public/assets/devices/solocame30_large.png +0 -0
  415. package/homebridge-ui/public/assets/devices/solocame40_large.jpg +0 -0
  416. package/homebridge-ui/public/assets/devices/solocame42_large.png +0 -0
  417. package/homebridge-ui/public/assets/devices/solocaml20_large.jpg +0 -0
  418. package/homebridge-ui/public/assets/devices/solocams220_large.jpg +0 -0
  419. package/homebridge-ui/public/assets/devices/solocams340_large.png +0 -0
  420. package/homebridge-ui/public/assets/devices/solocams40_large.jpg +0 -0
  421. package/homebridge-ui/public/assets/devices/soloindoorcamc24_large.jpg +0 -0
  422. package/homebridge-ui/public/assets/devices/solooutdoorcamc22_large.png +0 -0
  423. package/homebridge-ui/public/assets/devices/solooutdoorcamc24_large.jpg +0 -0
  424. package/homebridge-ui/public/assets/devices/unknown.png +0 -0
  425. package/homebridge-ui/public/assets/devices/walllight_s100_large.png +0 -0
  426. package/homebridge-ui/public/assets/devices/walllight_s120_large.png +0 -0
  427. package/homebridge-ui/public/assets/devices/water_freeze_sensor_t8920_large.png +0 -0
  428. package/homebridge-ui/public/assets/devices/wireddoorbell1080p_large.jpg +0 -0
  429. package/homebridge-ui/public/assets/devices/wireddoorbell2k_large.png +0 -0
  430. package/homebridge-ui/public/assets/devices/wireddoorbelldual_large.jpg +0 -0
  431. package/homebridge-ui/public/assets/icons/attach.svg +0 -1
  432. package/homebridge-ui/public/assets/icons/battery_0.svg +0 -1
  433. package/homebridge-ui/public/assets/icons/battery_1.svg +0 -1
  434. package/homebridge-ui/public/assets/icons/battery_2.svg +0 -1
  435. package/homebridge-ui/public/assets/icons/battery_3.svg +0 -1
  436. package/homebridge-ui/public/assets/icons/battery_4.svg +0 -1
  437. package/homebridge-ui/public/assets/icons/battery_5.svg +0 -1
  438. package/homebridge-ui/public/assets/icons/battery_6.svg +0 -1
  439. package/homebridge-ui/public/assets/icons/copy.svg +0 -1
  440. package/homebridge-ui/public/assets/icons/delete.svg +0 -1
  441. package/homebridge-ui/public/assets/icons/download.svg +0 -1
  442. package/homebridge-ui/public/assets/icons/info.svg +0 -1
  443. package/homebridge-ui/public/assets/icons/refresh.svg +0 -1
  444. package/homebridge-ui/public/assets/icons/satellite_alt.svg +0 -1
  445. package/homebridge-ui/public/assets/icons/solar_power.svg +0 -1
  446. package/homebridge-ui/public/components/device-card.js +0 -174
  447. package/homebridge-ui/public/components/guard-modes.js +0 -88
  448. package/homebridge-ui/public/components/number-input.js +0 -121
  449. package/homebridge-ui/public/components/select.js +0 -73
  450. package/homebridge-ui/public/components/toggle.js +0 -68
  451. package/homebridge-ui/public/services/api.js +0 -250
  452. package/homebridge-ui/public/services/config.js +0 -144
  453. package/homebridge-ui/public/style.css +0 -818
  454. package/homebridge-ui/public/utils/countries.js +0 -73
  455. package/homebridge-ui/public/utils/device-images.js +0 -102
  456. package/homebridge-ui/public/utils/helpers.js +0 -115
  457. package/homebridge-ui/public/views/dashboard.js +0 -226
  458. package/homebridge-ui/public/views/device-detail.js +0 -626
  459. package/homebridge-ui/public/views/diagnostics.js +0 -402
  460. package/homebridge-ui/public/views/login.js +0 -650
  461. package/homebridge-ui/public/views/recordings.js +0 -319
  462. package/homebridge-ui/public/views/settings.js +0 -197
  463. package/homebridge-ui/public/views/unsupported-detail.js +0 -296
  464. package/media/Snapshot-Unavailable.png +0 -0
  465. package/media/Snapshot-Unavailable.xcf +0 -0
  466. package/media/Snapshot-black.png +0 -0
  467. package/media/camera-disabled.png +0 -0
  468. package/media/camera-offline.png +0 -0
  469. package/scripts/decrypt-diagnostics.mjs +0 -257
@@ -1,450 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * map-properties.mjs
4
- *
5
- * Maps raw device param_type numbers from a device properties JSON dump
6
- * to the corresponding property constants in eufy-security-client.
7
- *
8
- * Usage:
9
- * node map-properties.mjs <raw-properties.json> [--closest]
10
- * cat raw.json | node map-properties.mjs [--closest]
11
- *
12
- * The input JSON should be the rawProperties object from a device dump,
13
- * e.g. { "1101": { "value": 100 }, "1013": { "value": 1 }, ... }
14
- * or an array of { "param_type": 1101, "param_value": "..." } objects.
15
- *
16
- * Options:
17
- * --closest Find the closest existing devices by Jaccard similarity
18
- * on resolved PropertyName overlap. Useful to identify which
19
- * existing device to base the DeviceProperties block on.
20
- *
21
- * Output: a table mapping each param_type to its CommandType/ParamType enum name
22
- * and all property constants that use that key.
23
- */
24
-
25
- import { readFileSync } from "fs";
26
- import { join, dirname } from "path";
27
- import { fileURLToPath } from "url";
28
-
29
- const __dirname = dirname(fileURLToPath(import.meta.url));
30
-
31
- // Paths relative to this script's location
32
- // eufy-security-client is a sibling repo at the same level as homebridge-eufy-security
33
- const CLIENT_ROOT = join(__dirname, "..", "..", "..", "..", "eufy-security-client");
34
- const TYPES_HTTP = join(CLIENT_ROOT, "src", "http", "types.ts");
35
- const TYPES_P2P = join(CLIENT_ROOT, "src", "p2p", "types.ts");
36
-
37
- // ── Step 1: Parse enum values from source ──────────────────────────────────
38
-
39
- function parseEnum(source, enumName) {
40
- const map = new Map(); // number → enum member name
41
- const re = new RegExp(`enum\\s+${enumName}\\s*\\{([\\s\\S]*?)\\}`, "m");
42
- const match = source.match(re);
43
- if (!match) return map;
44
-
45
- const body = match[1];
46
- for (const line of body.split("\n")) {
47
- const m = line.match(/^\s*(\w+)\s*=\s*(\d+)/);
48
- if (m) {
49
- map.set(Number(m[2]), `${enumName}.${m[1]}`);
50
- }
51
- }
52
- return map;
53
- }
54
-
55
- const httpSource = readFileSync(TYPES_HTTP, "utf-8");
56
- const p2pSource = readFileSync(TYPES_P2P, "utf-8");
57
-
58
- const paramTypeMap = parseEnum(httpSource, "ParamType");
59
- const commandTypeMap = parseEnum(p2pSource, "CommandType");
60
- const trackerCommandTypeMap = parseEnum(p2pSource, "TrackerCommandType");
61
-
62
- // Merge all enum maps (CommandType takes precedence as it's most commonly used)
63
- const allEnums = new Map();
64
- for (const [k, v] of paramTypeMap) allEnums.set(k, v);
65
- for (const [k, v] of trackerCommandTypeMap) allEnums.set(k, v);
66
- for (const [k, v] of commandTypeMap) allEnums.set(k, v);
67
-
68
- // ── Step 2: Parse property constants and their keys ────────────────────────
69
-
70
- // Match property constant definitions and extract their key field
71
- // Handles both direct keys and spread patterns
72
- function parsePropertyConstants(source) {
73
- const props = []; // { constName, key, keyRaw, propertyName }
74
-
75
- // Find each "export const XxxProperty" block
76
- const constRegex = /export\s+const\s+(\w+Property)\s*:\s*\w+\s*=\s*\{([\s\S]*?)\};/g;
77
- let m;
78
- while ((m = constRegex.exec(source)) !== null) {
79
- const constName = m[1];
80
- const body = m[2];
81
-
82
- // Extract key field
83
- let key = null;
84
- let keyRaw = null;
85
- const keyMatch = body.match(/key:\s*(.+?)(?:,|\n)/);
86
- if (keyMatch) {
87
- keyRaw = keyMatch[1].trim();
88
- // Resolve to numeric if it's an enum reference
89
- if (keyRaw.startsWith('"') || keyRaw.startsWith("'")) {
90
- key = keyRaw.replace(/['"]/g, ""); // string key
91
- } else {
92
- // It's an enum reference like CommandType.CMD_GET_BATTERY
93
- const parts = keyRaw.split(".");
94
- if (parts.length === 2) {
95
- const enumName = parts[0];
96
- let enumMap;
97
- if (enumName === "CommandType") enumMap = commandTypeMap;
98
- else if (enumName === "ParamType") enumMap = paramTypeMap;
99
- else if (enumName === "TrackerCommandType") enumMap = trackerCommandTypeMap;
100
-
101
- if (enumMap) {
102
- for (const [num, fullName] of enumMap) {
103
- if (fullName === keyRaw) {
104
- key = num;
105
- break;
106
- }
107
- }
108
- }
109
- }
110
- }
111
- }
112
-
113
- // Extract PropertyName
114
- let propertyName = null;
115
- const nameMatch = body.match(/name:\s*(PropertyName\.\w+)/);
116
- if (nameMatch) {
117
- propertyName = nameMatch[1];
118
- }
119
-
120
- // Handle spread: ...SomeOtherProperty (inherits key if not overridden)
121
- let spreadFrom = null;
122
- const spreadMatch = body.match(/\.\.\.(\w+Property)/);
123
- if (spreadMatch) {
124
- spreadFrom = spreadMatch[1];
125
- }
126
-
127
- props.push({ constName, key, keyRaw, propertyName, spreadFrom });
128
- }
129
-
130
- // Resolve spreads: inherit missing fields from parent property
131
- const byName = new Map(props.map((p) => [p.constName, p]));
132
- for (const prop of props) {
133
- if (prop.spreadFrom) {
134
- const parent = byName.get(prop.spreadFrom);
135
- if (parent) {
136
- if (prop.key === null) {
137
- prop.key = parent.key;
138
- if (!prop.keyRaw) prop.keyRaw = `(spread from ${prop.spreadFrom}) ${parent.keyRaw}`;
139
- }
140
- // Always inherit propertyName from parent when missing, even if key is overridden
141
- if (!prop.propertyName) prop.propertyName = parent.propertyName;
142
- }
143
- }
144
- }
145
-
146
- return props;
147
- }
148
-
149
- const allProps = parsePropertyConstants(httpSource);
150
-
151
- // Build lookup: numeric key → list of property constants
152
- const keyToProps = new Map(); // key (number|string) → [{ constName, propertyName }]
153
- for (const p of allProps) {
154
- if (p.key === null) continue;
155
- const k = p.key;
156
- if (!keyToProps.has(k)) keyToProps.set(k, []);
157
- keyToProps.get(k).push({ constName: p.constName, propertyName: p.propertyName });
158
- }
159
-
160
- // ── Step 3: Parse DeviceProperties blocks to see which constants are used ──
161
-
162
- function parseDevicePropertiesUsage(source) {
163
- // Find all [DeviceType.XXX]: { ... } blocks inside DeviceProperties
164
- const usage = new Map(); // constName → Set of DeviceType names that use it
165
- const dpRegex = /\[DeviceType\.(\w+)\]\s*:\s*\{([\s\S]*?)\}/g;
166
- // Only search within the DeviceProperties section
167
- const dpStart = source.indexOf("export const DeviceProperties");
168
- const dpEnd = source.indexOf("export const StationProperties");
169
- if (dpStart === -1) return usage;
170
-
171
- const dpSection = source.slice(dpStart, dpEnd === -1 ? undefined : dpEnd);
172
- let m;
173
- while ((m = dpRegex.exec(dpSection)) !== null) {
174
- const deviceType = m[1];
175
- const body = m[2];
176
- // Find all property constant references
177
- const refRegex = /:\s*(\w+Property)/g;
178
- let rm;
179
- while ((rm = refRegex.exec(body)) !== null) {
180
- const constName = rm[1];
181
- if (!usage.has(constName)) usage.set(constName, new Set());
182
- usage.get(constName).add(deviceType);
183
- }
184
- }
185
- return usage;
186
- }
187
-
188
- const propUsage = parseDevicePropertiesUsage(httpSource);
189
-
190
- // ── Step 4: Read and parse input JSON ──────────────────────────────────────
191
-
192
- let inputData;
193
- const inputFile = process.argv.slice(2).find((a) => !a.startsWith("-"));
194
- if (inputFile) {
195
- inputData = readFileSync(inputFile, "utf-8");
196
- } else {
197
- // Read from stdin
198
- inputData = readFileSync("/dev/stdin", "utf-8");
199
- }
200
-
201
- let rawParamTypes; // Set of numeric param_type values
202
- try {
203
- const parsed = JSON.parse(inputData);
204
-
205
- if (Array.isArray(parsed)) {
206
- // Array of { param_type: number, ... }
207
- rawParamTypes = new Set(parsed.map((item) => Number(item.param_type)));
208
- } else if (typeof parsed === "object") {
209
- // Check if it's a full device dump with rawProperties nested
210
- if (parsed.rawProperties && typeof parsed.rawProperties === "object") {
211
- rawParamTypes = new Set(Object.keys(parsed.rawProperties).map(Number));
212
- } else {
213
- // Direct { "1101": ..., "1013": ... } format
214
- rawParamTypes = new Set(Object.keys(parsed).map(Number));
215
- }
216
- }
217
- } catch {
218
- console.error("Error: Could not parse input JSON. Provide either:");
219
- console.error(' - A raw properties object: { "1101": {...}, "1013": {...}, ... }');
220
- console.error(' - An array: [{ "param_type": 1101, ... }, ...]');
221
- console.error(" - A device dump with rawProperties key");
222
- process.exit(1);
223
- }
224
-
225
- // Filter out NaN (from string keys in the input)
226
- rawParamTypes = new Set([...rawParamTypes].filter((n) => !isNaN(n)));
227
-
228
- // ── Step 5: Output results ─────────────────────────────────────────────────
229
-
230
- const COL1 = 12; // param_type
231
- const COL2 = 48; // enum name
232
- const COL3 = 50; // property constants
233
- // COL4 reserved for future use
234
-
235
- const header = [
236
- "param_type".padEnd(COL1),
237
- "Enum Name".padEnd(COL2),
238
- "Property Constant(s)".padEnd(COL3),
239
- "Used by DeviceTypes",
240
- ].join(" | ");
241
-
242
- console.log("=".repeat(header.length));
243
- console.log("Device Raw Properties → Property Constants Mapping");
244
- console.log(`Total raw param_types: ${rawParamTypes.size}`);
245
- console.log("=".repeat(header.length));
246
- console.log();
247
- console.log(header);
248
- console.log("-".repeat(header.length));
249
-
250
- const matched = [];
251
- const unmatched = [];
252
-
253
- for (const paramType of [...rawParamTypes].sort((a, b) => a - b)) {
254
- const enumName = allEnums.get(paramType) || "???";
255
- const props = keyToProps.get(paramType);
256
-
257
- if (props && props.length > 0) {
258
- const constNames = props.map((p) => p.constName);
259
- const propertyNames = [...new Set(props.map((p) => p.propertyName).filter(Boolean))];
260
- const usedBy = new Set();
261
- for (const cn of constNames) {
262
- const devices = propUsage.get(cn);
263
- if (devices) devices.forEach((d) => usedBy.add(d));
264
- }
265
-
266
- matched.push({
267
- paramType,
268
- enumName,
269
- constNames,
270
- propertyNames,
271
- usedBy: [...usedBy],
272
- });
273
-
274
- console.log(
275
- [
276
- String(paramType).padEnd(COL1),
277
- enumName.padEnd(COL2),
278
- constNames.join(", ").padEnd(COL3),
279
- [...usedBy].slice(0, 5).join(", ") + (usedBy.size > 5 ? "..." : ""),
280
- ].join(" | ")
281
- );
282
- } else {
283
- unmatched.push({ paramType, enumName });
284
- console.log(
285
- [
286
- String(paramType).padEnd(COL1),
287
- enumName.padEnd(COL2),
288
- "(no property constant found)".padEnd(COL3),
289
- "",
290
- ].join(" | ")
291
- );
292
- }
293
- }
294
-
295
- console.log();
296
- console.log("=".repeat(80));
297
- console.log(`MATCHED: ${matched.length} / ${rawParamTypes.size} param_types have property constants`);
298
- console.log(`UNMATCHED: ${unmatched.length} param_types have no known property constant`);
299
- console.log("=".repeat(80));
300
-
301
- if (unmatched.length > 0) {
302
- console.log();
303
- console.log("Unmatched param_types (may need new property constants or may be internal):");
304
- for (const u of unmatched) {
305
- console.log(` ${u.paramType} → ${u.enumName}`);
306
- }
307
- }
308
-
309
- // ── Step 6: Companion custom properties ─────────────────────────────────────
310
- // Some param_type-based properties require a companion custom (runtime) property
311
- // that never appears in raw device data. Define those pairings here so the
312
- // suggested block always includes both.
313
-
314
- const COMPANION_PROPERTIES = new Map([
315
- // DeviceRTSPStream (CMD_NAS_SWITCH) → DeviceRTSPStreamUrl (custom_rtspStreamUrl)
316
- ["PropertyName.DeviceRTSPStream", {
317
- propertyName: "PropertyName.DeviceRTSPStreamUrl",
318
- constName: "DeviceRTSPStreamUrlProperty",
319
- reason: "RTSP URL is set at runtime by the station — must accompany DeviceRTSPStream",
320
- }],
321
- // DeviceWifiRSSI → DeviceWifiSignalLevel (custom_wifiSignalLevel)
322
- ["PropertyName.DeviceWifiRSSI", {
323
- propertyName: "PropertyName.DeviceWifiSignalLevel",
324
- constName: "DeviceWifiSignalLevelProperty",
325
- reason: "WiFi signal level is derived at runtime from RSSI",
326
- }],
327
- // DeviceCellularRSSI → DeviceCellularSignalLevel (custom_cellularSignalLevel)
328
- ["PropertyName.DeviceCellularRSSI", {
329
- propertyName: "PropertyName.DeviceCellularSignalLevel",
330
- constName: "DeviceCellularSignalLevelProperty",
331
- reason: "Cellular signal level is derived at runtime from RSSI",
332
- }],
333
- ]);
334
-
335
- // Output a suggested PropertyName list for use in DeviceProperties block
336
- console.log();
337
- console.log("=".repeat(80));
338
- console.log("SUGGESTED DeviceProperties block entries:");
339
- console.log("=".repeat(80));
340
- const seen = new Set();
341
- const companionsAdded = [];
342
- for (const m of matched) {
343
- // Use original props lookup to get correct constName → propertyName mapping
344
- // (the deduplicated m.propertyNames array loses the index association with m.constNames)
345
- const propsForKey = keyToProps.get(m.paramType) || [];
346
- for (const prop of propsForKey) {
347
- const pn = prop.propertyName;
348
- const cn = prop.constName;
349
- if (pn && !seen.has(pn)) {
350
- seen.add(pn);
351
- console.log(` [${pn}]: ${cn},`);
352
-
353
- // Check if this property has a required companion
354
- const companion = COMPANION_PROPERTIES.get(pn);
355
- if (companion && !seen.has(companion.propertyName)) {
356
- seen.add(companion.propertyName);
357
- console.log(` [${companion.propertyName}]: ${companion.constName}, // ⚠ companion (custom/runtime)`);
358
- companionsAdded.push(companion);
359
- }
360
- }
361
- }
362
- }
363
-
364
- if (companionsAdded.length > 0) {
365
- console.log();
366
- console.log("=".repeat(80));
367
- console.log("⚠ COMPANION PROPERTIES (custom/runtime — not in raw device data):");
368
- console.log("=".repeat(80));
369
- for (const c of companionsAdded) {
370
- console.log(` ${c.constName}: ${c.reason}`);
371
- }
372
- }
373
-
374
- // ── Step 7: Closest device detection (--closest flag) ───────────────────────
375
-
376
- if (process.argv.includes("--closest")) {
377
- // Collect the set of PropertyName values from the matched raw properties
378
- const targetPropNames = new Set();
379
- for (const m of matched) {
380
- for (const pn of m.propertyNames) {
381
- if (pn) targetPropNames.add(pn);
382
- }
383
- }
384
-
385
- if (targetPropNames.size === 0) {
386
- console.log("\nCannot compute closest device — no PropertyName matches found.");
387
- } else {
388
- // Parse DeviceProperties blocks to get property sets per device type
389
- const dpStart = httpSource.indexOf("export const DeviceProperties");
390
- const dpEnd = httpSource.indexOf("export const StationProperties");
391
- if (dpStart !== -1) {
392
- const dpSection = httpSource.slice(dpStart, dpEnd === -1 ? undefined : dpEnd);
393
-
394
- const devicePropSets = new Map(); // DeviceType name → Set of PropertyName references
395
- const blockRegex = /\[DeviceType\.(\w+)\]\s*:\s*\{([\s\S]*?)\}/g;
396
- let bm;
397
- while ((bm = blockRegex.exec(dpSection)) !== null) {
398
- const dt = bm[1];
399
- const body = bm[2];
400
- const props = new Set();
401
- // Extract property constants used, then resolve to PropertyName
402
- const refRegex = /:\s*(\w+Property)/g;
403
- let rm;
404
- while ((rm = refRegex.exec(body)) !== null) {
405
- const constName = rm[1];
406
- const prop = allProps.find((p) => p.constName === constName);
407
- if (prop && prop.propertyName) props.add(prop.propertyName);
408
- }
409
- devicePropSets.set(dt, props);
410
- }
411
-
412
- // Jaccard similarity
413
- const similarities = [];
414
- for (const [dt, props] of devicePropSets) {
415
- const intersection = new Set([...targetPropNames].filter((p) => props.has(p)));
416
- const union = new Set([...targetPropNames, ...props]);
417
- const jaccard = union.size > 0 ? intersection.size / union.size : 0;
418
- if (jaccard > 0.2) {
419
- similarities.push({
420
- device: dt,
421
- jaccard: Math.round(jaccard * 100),
422
- shared: intersection.size,
423
- targetOnly: [...targetPropNames].filter((p) => !props.has(p)).length,
424
- otherOnly: [...props].filter((p) => !targetPropNames.has(p)).length,
425
- });
426
- }
427
- }
428
-
429
- similarities.sort((a, b) => b.jaccard - a.jaccard);
430
- const top = similarities.slice(0, 8);
431
-
432
- console.log();
433
- console.log("=".repeat(80));
434
- console.log("CLOSEST EXISTING DEVICES (by property overlap with raw data)");
435
- console.log("=".repeat(80));
436
- if (top.length === 0) {
437
- console.log(" No devices with >20% property overlap found.");
438
- } else {
439
- console.log(" " + "Device".padEnd(38) + "Similarity Shared Target-only Other-only");
440
- for (const d of top) {
441
- console.log(
442
- ` ${d.device.padEnd(38)} ${String(d.jaccard + "%").padEnd(11)} ${String(d.shared).padEnd(7)} ${String(d.targetOnly).padEnd(12)} ${d.otherOnly}`
443
- );
444
- }
445
- console.log();
446
- console.log(` Recommended base: ${top[0].device} (${top[0].jaccard}% overlap)`);
447
- }
448
- }
449
- }
450
- }