@fastybird/smart-panel-backend 1.1.0-alpha.0 → 1.1.0-alpha.10

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 (315) hide show
  1. package/dist/app.module.js +14 -0
  2. package/dist/app.module.js.map +1 -1
  3. package/dist/common/filters/conflict-exception.filter.d.ts +6 -0
  4. package/dist/common/filters/conflict-exception.filter.js +59 -0
  5. package/dist/common/filters/conflict-exception.filter.js.map +1 -0
  6. package/dist/common/filters/global-error.filter.js +1 -4
  7. package/dist/common/filters/global-error.filter.js.map +1 -1
  8. package/dist/common/filters/global-filters.d.ts +3 -0
  9. package/dist/common/filters/global-filters.js +22 -0
  10. package/dist/common/filters/global-filters.js.map +1 -0
  11. package/dist/common/filters/unprocessable-entity-exception.filter.d.ts +1 -0
  12. package/dist/common/filters/unprocessable-entity-exception.filter.js +15 -3
  13. package/dist/common/filters/unprocessable-entity-exception.filter.js.map +1 -1
  14. package/dist/common/utils/transform.utils.js +3 -0
  15. package/dist/common/utils/transform.utils.js.map +1 -1
  16. package/dist/main.js +2 -7
  17. package/dist/main.js.map +1 -1
  18. package/dist/modules/devices/controllers/channels.properties.controller.js +16 -4
  19. package/dist/modules/devices/controllers/channels.properties.controller.js.map +1 -1
  20. package/dist/modules/devices/controllers/devices.channels.properties.controller.js +16 -4
  21. package/dist/modules/devices/controllers/devices.channels.properties.controller.js.map +1 -1
  22. package/dist/modules/devices/devices.module.js +12 -0
  23. package/dist/modules/devices/devices.module.js.map +1 -1
  24. package/dist/modules/devices/services/channels.properties.service.d.ts +27 -3
  25. package/dist/modules/devices/services/channels.properties.service.js +304 -28
  26. package/dist/modules/devices/services/channels.properties.service.js.map +1 -1
  27. package/dist/modules/devices/services/channels.service.js +42 -38
  28. package/dist/modules/devices/services/channels.service.js.map +1 -1
  29. package/dist/modules/devices/services/command-latency-trace-collector.service.d.ts +101 -0
  30. package/dist/modules/devices/services/command-latency-trace-collector.service.js +451 -0
  31. package/dist/modules/devices/services/command-latency-trace-collector.service.js.map +1 -0
  32. package/dist/modules/devices/services/device-structure-lock.service.d.ts +10 -2
  33. package/dist/modules/devices/services/device-structure-lock.service.js +86 -7
  34. package/dist/modules/devices/services/device-structure-lock.service.js.map +1 -1
  35. package/dist/modules/devices/services/devices.service.js +37 -33
  36. package/dist/modules/devices/services/devices.service.js.map +1 -1
  37. package/dist/modules/devices/services/module-reset.service.d.ts +3 -1
  38. package/dist/modules/devices/services/module-reset.service.js +21 -16
  39. package/dist/modules/devices/services/module-reset.service.js.map +1 -1
  40. package/dist/modules/devices/services/property-command-dispatch.service.d.ts +45 -0
  41. package/dist/modules/devices/services/property-command-dispatch.service.js +227 -0
  42. package/dist/modules/devices/services/property-command-dispatch.service.js.map +1 -0
  43. package/dist/modules/devices/services/property-command-window.service.d.ts +71 -0
  44. package/dist/modules/devices/services/property-command-window.service.js +204 -0
  45. package/dist/modules/devices/services/property-command-window.service.js.map +1 -0
  46. package/dist/modules/devices/services/property-command.service.d.ts +28 -3
  47. package/dist/modules/devices/services/property-command.service.js +171 -10
  48. package/dist/modules/devices/services/property-command.service.js.map +1 -1
  49. package/dist/modules/devices/services/property-state-coordinator.service.d.ts +4 -0
  50. package/dist/modules/devices/services/property-state-coordinator.service.js +35 -0
  51. package/dist/modules/devices/services/property-state-coordinator.service.js.map +1 -0
  52. package/dist/modules/devices/services/property-value.service.d.ts +1 -0
  53. package/dist/modules/devices/services/property-value.service.js +4 -0
  54. package/dist/modules/devices/services/property-value.service.js.map +1 -1
  55. package/dist/modules/mcp/oauth/mcp-oauth-provider.factory.js.map +1 -1
  56. package/dist/modules/platform/services/platform.service.d.ts +13 -4
  57. package/dist/modules/platform/services/platform.service.js +57 -35
  58. package/dist/modules/platform/services/platform.service.js.map +1 -1
  59. package/dist/modules/remote-access/dto/update-config.dto.js +5 -0
  60. package/dist/modules/remote-access/dto/update-config.dto.js.map +1 -1
  61. package/dist/modules/remote-access/services/remote-access-proxy-contribution.service.js +4 -0
  62. package/dist/modules/remote-access/services/remote-access-proxy-contribution.service.js.map +1 -1
  63. package/dist/modules/remote-access/services/remote-access-status.service.d.ts +5 -1
  64. package/dist/modules/remote-access/services/remote-access-status.service.js +38 -4
  65. package/dist/modules/remote-access/services/remote-access-status.service.js.map +1 -1
  66. package/dist/modules/remote-access/services/remote-access-url.service.js +4 -0
  67. package/dist/modules/remote-access/services/remote-access-url.service.js.map +1 -1
  68. package/dist/modules/remote-access/validators/is-remote-access-url.validator.js +5 -2
  69. package/dist/modules/remote-access/validators/is-remote-access-url.validator.js.map +1 -1
  70. package/dist/modules/system/commands/command.utils.d.ts +2 -0
  71. package/dist/modules/system/commands/command.utils.js +14 -0
  72. package/dist/modules/system/commands/command.utils.js.map +1 -1
  73. package/dist/modules/system/commands/update-check.command.js +2 -3
  74. package/dist/modules/system/commands/update-check.command.js.map +1 -1
  75. package/dist/modules/system/commands/update-panel.command.js +2 -2
  76. package/dist/modules/system/commands/update-panel.command.js.map +1 -1
  77. package/dist/modules/system/commands/update-server.command.d.ts +1 -0
  78. package/dist/modules/system/commands/update-server.command.js +36 -11
  79. package/dist/modules/system/commands/update-server.command.js.map +1 -1
  80. package/dist/modules/system/dto/update-config.dto.d.ts +2 -1
  81. package/dist/modules/system/dto/update-config.dto.js +15 -0
  82. package/dist/modules/system/dto/update-config.dto.js.map +1 -1
  83. package/dist/modules/system/models/config.model.d.ts +2 -1
  84. package/dist/modules/system/models/config.model.js +13 -0
  85. package/dist/modules/system/models/config.model.js.map +1 -1
  86. package/dist/modules/system/services/privileged-worker.service.d.ts +10 -0
  87. package/dist/modules/system/services/privileged-worker.service.js +137 -11
  88. package/dist/modules/system/services/privileged-worker.service.js.map +1 -1
  89. package/dist/modules/system/services/update.service.d.ts +11 -1
  90. package/dist/modules/system/services/update.service.js +97 -35
  91. package/dist/modules/system/services/update.service.js.map +1 -1
  92. package/dist/modules/system/system.constants.d.ts +6 -0
  93. package/dist/modules/system/system.constants.js +8 -1
  94. package/dist/modules/system/system.constants.js.map +1 -1
  95. package/dist/modules/websocket/gateway/websocket.gateway.d.ts +7 -1
  96. package/dist/modules/websocket/gateway/websocket.gateway.js +67 -9
  97. package/dist/modules/websocket/gateway/websocket.gateway.js.map +1 -1
  98. package/dist/modules/websocket/services/command-acknowledgement-trace.service.d.ts +143 -0
  99. package/dist/modules/websocket/services/command-acknowledgement-trace.service.js +523 -0
  100. package/dist/modules/websocket/services/command-acknowledgement-trace.service.js.map +1 -0
  101. package/dist/modules/websocket/websocket.module.js +9 -1
  102. package/dist/modules/websocket/websocket.module.js.map +1 -1
  103. package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.js +2 -1
  104. package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.js.map +1 -1
  105. package/dist/plugins/devices-home-assistant/services/state-changed.event.service.js +2 -3
  106. package/dist/plugins/devices-home-assistant/services/state-changed.event.service.js.map +1 -1
  107. package/dist/plugins/devices-homekit/controllers/homekit-bridge.controller.d.ts +14 -0
  108. package/dist/plugins/devices-homekit/controllers/homekit-bridge.controller.js +125 -0
  109. package/dist/plugins/devices-homekit/controllers/homekit-bridge.controller.js.map +1 -0
  110. package/dist/plugins/devices-homekit/devices-homekit.constants.d.ts +16 -0
  111. package/dist/plugins/devices-homekit/devices-homekit.constants.js +57 -0
  112. package/dist/plugins/devices-homekit/devices-homekit.constants.js.map +1 -0
  113. package/dist/plugins/devices-homekit/devices-homekit.exceptions.d.ts +12 -0
  114. package/dist/plugins/devices-homekit/devices-homekit.exceptions.js +32 -0
  115. package/dist/plugins/devices-homekit/devices-homekit.exceptions.js.map +1 -0
  116. package/dist/plugins/devices-homekit/devices-homekit.openapi.d.ts +6 -0
  117. package/dist/plugins/devices-homekit/devices-homekit.openapi.js +19 -0
  118. package/dist/plugins/devices-homekit/devices-homekit.openapi.js.map +1 -0
  119. package/dist/plugins/devices-homekit/devices-homekit.plugin.d.ts +24 -0
  120. package/dist/plugins/devices-homekit/devices-homekit.plugin.js +183 -0
  121. package/dist/plugins/devices-homekit/devices-homekit.plugin.js.map +1 -0
  122. package/dist/plugins/devices-homekit/dto/bridge-map.dto.d.ts +6 -0
  123. package/dist/plugins/devices-homekit/dto/bridge-map.dto.js +50 -0
  124. package/dist/plugins/devices-homekit/dto/bridge-map.dto.js.map +1 -0
  125. package/dist/plugins/devices-homekit/dto/update-config.dto.d.ts +11 -0
  126. package/dist/plugins/devices-homekit/dto/update-config.dto.js +138 -0
  127. package/dist/plugins/devices-homekit/dto/update-config.dto.js.map +1 -0
  128. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.d.ts +8 -0
  129. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.js +77 -0
  130. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.js.map +1 -0
  131. package/dist/plugins/devices-homekit/mappers/base.mapper.d.ts +15 -0
  132. package/dist/plugins/devices-homekit/mappers/base.mapper.js +97 -0
  133. package/dist/plugins/devices-homekit/mappers/base.mapper.js.map +1 -0
  134. package/dist/plugins/devices-homekit/mappers/battery.mapper.d.ts +6 -0
  135. package/dist/plugins/devices-homekit/mappers/battery.mapper.js +130 -0
  136. package/dist/plugins/devices-homekit/mappers/battery.mapper.js.map +1 -0
  137. package/dist/plugins/devices-homekit/mappers/homekit-mapper.interface.d.ts +36 -0
  138. package/dist/plugins/devices-homekit/mappers/homekit-mapper.interface.js +3 -0
  139. package/dist/plugins/devices-homekit/mappers/homekit-mapper.interface.js.map +1 -0
  140. package/dist/plugins/devices-homekit/mappers/lightbulb.mapper.d.ts +9 -0
  141. package/dist/plugins/devices-homekit/mappers/lightbulb.mapper.js +115 -0
  142. package/dist/plugins/devices-homekit/mappers/lightbulb.mapper.js.map +1 -0
  143. package/dist/plugins/devices-homekit/mappers/lock.mapper.d.ts +10 -0
  144. package/dist/plugins/devices-homekit/mappers/lock.mapper.js +59 -0
  145. package/dist/plugins/devices-homekit/mappers/lock.mapper.js.map +1 -0
  146. package/dist/plugins/devices-homekit/mappers/outlet.mapper.d.ts +9 -0
  147. package/dist/plugins/devices-homekit/mappers/outlet.mapper.js +44 -0
  148. package/dist/plugins/devices-homekit/mappers/outlet.mapper.js.map +1 -0
  149. package/dist/plugins/devices-homekit/mappers/sensor.mapper.d.ts +10 -0
  150. package/dist/plugins/devices-homekit/mappers/sensor.mapper.js +168 -0
  151. package/dist/plugins/devices-homekit/mappers/sensor.mapper.js.map +1 -0
  152. package/dist/plugins/devices-homekit/mappers/switch.mapper.d.ts +9 -0
  153. package/dist/plugins/devices-homekit/mappers/switch.mapper.js +35 -0
  154. package/dist/plugins/devices-homekit/mappers/switch.mapper.js.map +1 -0
  155. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.d.ts +50 -0
  156. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.js +441 -0
  157. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.js.map +1 -0
  158. package/dist/plugins/devices-homekit/mappers/thermostat.mapper.d.ts +11 -0
  159. package/dist/plugins/devices-homekit/mappers/thermostat.mapper.js +97 -0
  160. package/dist/plugins/devices-homekit/mappers/thermostat.mapper.js.map +1 -0
  161. package/dist/plugins/devices-homekit/mappers/window-covering.mapper.d.ts +10 -0
  162. package/dist/plugins/devices-homekit/mappers/window-covering.mapper.js +94 -0
  163. package/dist/plugins/devices-homekit/mappers/window-covering.mapper.js.map +1 -0
  164. package/dist/plugins/devices-homekit/models/bridge-candidate.model.d.ts +15 -0
  165. package/dist/plugins/devices-homekit/models/bridge-candidate.model.js +150 -0
  166. package/dist/plugins/devices-homekit/models/bridge-candidate.model.js.map +1 -0
  167. package/dist/plugins/devices-homekit/models/bridge-status.model.d.ts +16 -0
  168. package/dist/plugins/devices-homekit/models/bridge-status.model.js +156 -0
  169. package/dist/plugins/devices-homekit/models/bridge-status.model.js.map +1 -0
  170. package/dist/plugins/devices-homekit/models/config.model.d.ts +12 -0
  171. package/dist/plugins/devices-homekit/models/config.model.js +134 -0
  172. package/dist/plugins/devices-homekit/models/config.model.js.map +1 -0
  173. package/dist/plugins/devices-homekit/services/homekit-actions.service.d.ts +14 -0
  174. package/dist/plugins/devices-homekit/services/homekit-actions.service.js +92 -0
  175. package/dist/plugins/devices-homekit/services/homekit-actions.service.js.map +1 -0
  176. package/dist/plugins/devices-homekit/services/homekit-bridge.service.d.ts +43 -0
  177. package/dist/plugins/devices-homekit/services/homekit-bridge.service.js +497 -0
  178. package/dist/plugins/devices-homekit/services/homekit-bridge.service.js.map +1 -0
  179. package/dist/plugins/devices-homekit/services/homekit-command.dispatcher.d.ts +11 -0
  180. package/dist/plugins/devices-homekit/services/homekit-command.dispatcher.js +68 -0
  181. package/dist/plugins/devices-homekit/services/homekit-command.dispatcher.js.map +1 -0
  182. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.d.ts +34 -0
  183. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.js +179 -0
  184. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.js.map +1 -0
  185. package/dist/plugins/devices-homekit/services/homekit-wizard.service.d.ts +15 -0
  186. package/dist/plugins/devices-homekit/services/homekit-wizard.service.js +75 -0
  187. package/dist/plugins/devices-homekit/services/homekit-wizard.service.js.map +1 -0
  188. package/dist/plugins/devices-homekit/validators/is-not-forbidden-homekit-pin.validator.d.ts +2 -0
  189. package/dist/plugins/devices-homekit/validators/is-not-forbidden-homekit-pin.validator.js +30 -0
  190. package/dist/plugins/devices-homekit/validators/is-not-forbidden-homekit-pin.validator.js.map +1 -0
  191. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.d.ts +18 -1
  192. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js +338 -119
  193. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js.map +1 -1
  194. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.d.ts +13 -1
  195. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js +109 -10
  196. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js.map +1 -1
  197. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.constants.js +8 -11
  198. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.constants.js.map +1 -1
  199. package/dist/plugins/devices-shelly-ng/mappings/mapping-loader.service.js +4 -0
  200. package/dist/plugins/devices-shelly-ng/mappings/mapping-loader.service.js.map +1 -1
  201. package/dist/plugins/devices-shelly-ng/services/device-manager.service.js +5 -0
  202. package/dist/plugins/devices-shelly-ng/services/device-manager.service.js.map +1 -1
  203. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.d.ts +9 -1
  204. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js +59 -24
  205. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js.map +1 -1
  206. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.d.ts +0 -1
  207. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.js +5 -12
  208. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.js.map +1 -1
  209. package/dist/plugins/devices-shelly-ng/utils/transform.utils.d.ts +2 -0
  210. package/dist/plugins/devices-shelly-ng/utils/transform.utils.js +14 -1
  211. package/dist/plugins/devices-shelly-ng/utils/transform.utils.js.map +1 -1
  212. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.d.ts +17 -0
  213. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.js +147 -0
  214. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.js.map +1 -0
  215. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.d.ts +15 -0
  216. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.js +98 -0
  217. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.js.map +1 -0
  218. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.d.ts +9 -0
  219. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.js +94 -0
  220. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.js.map +1 -0
  221. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.d.ts +9 -0
  222. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.js +92 -0
  223. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.js.map +1 -0
  224. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.d.ts +7 -0
  225. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.js +48 -0
  226. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.js.map +1 -0
  227. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.d.ts +42 -0
  228. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.js +352 -0
  229. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.js.map +1 -0
  230. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.d.ts +24 -0
  231. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.js +27 -0
  232. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.js.map +1 -0
  233. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.d.ts +8 -0
  234. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.js +19 -0
  235. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.js.map +1 -0
  236. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.d.ts +4 -0
  237. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.js +20 -0
  238. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.js.map +1 -0
  239. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.d.ts +21 -0
  240. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.js +135 -0
  241. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.js.map +1 -0
  242. package/dist/plugins/remote-access-cloudflare-tunnel/scripts/cloudflared-setup.sh +185 -0
  243. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.d.ts +82 -0
  244. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.js +507 -0
  245. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.js.map +1 -0
  246. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.d.ts +10 -0
  247. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.js +37 -0
  248. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.js.map +1 -0
  249. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.d.ts +38 -0
  250. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.js +147 -0
  251. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.js.map +1 -0
  252. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.d.ts +15 -0
  253. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.js +67 -0
  254. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.js.map +1 -0
  255. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.d.ts +8 -0
  256. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.js +46 -0
  257. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.js.map +1 -0
  258. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.d.ts +27 -0
  259. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.js +139 -0
  260. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.js.map +1 -0
  261. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.d.ts +1 -0
  262. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.js +26 -10
  263. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.js.map +1 -1
  264. package/dist/plugins/remote-access-tailscale/controllers/status.controller.d.ts +6 -1
  265. package/dist/plugins/remote-access-tailscale/controllers/status.controller.js +28 -3
  266. package/dist/plugins/remote-access-tailscale/controllers/status.controller.js.map +1 -1
  267. package/dist/plugins/remote-access-tailscale/models/status.model.d.ts +19 -0
  268. package/dist/plugins/remote-access-tailscale/models/status.model.js +158 -1
  269. package/dist/plugins/remote-access-tailscale/models/status.model.js.map +1 -1
  270. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.d.ts +2 -0
  271. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.js +3 -1
  272. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.js.map +1 -1
  273. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.d.ts +13 -0
  274. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.js +27 -0
  275. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.js.map +1 -0
  276. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.d.ts +2 -2
  277. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.js +2 -0
  278. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.js.map +1 -1
  279. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.plugin.js +1 -1
  280. package/dist/plugins/remote-access-tailscale/scripts/tailscale-setup.sh +61 -0
  281. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.d.ts +9 -0
  282. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.js +12 -0
  283. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.js.map +1 -1
  284. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.d.ts +1 -0
  285. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.js +27 -2
  286. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.js.map +1 -1
  287. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.d.ts +30 -1
  288. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.js +300 -30
  289. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.js.map +1 -1
  290. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.d.ts +8 -3
  291. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.js +39 -12
  292. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.js.map +1 -1
  293. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.d.ts +14 -5
  294. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.js +51 -16
  295. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.js.map +1 -1
  296. package/dist/plugins/scenes-local/platforms/local-scene.platform.d.ts +3 -1
  297. package/dist/plugins/scenes-local/platforms/local-scene.platform.js +12 -7
  298. package/dist/plugins/scenes-local/platforms/local-scene.platform.js.map +1 -1
  299. package/dist/plugins/spaces-home-control/services/climate-intent.service.d.ts +3 -1
  300. package/dist/plugins/spaces-home-control/services/climate-intent.service.js +6 -3
  301. package/dist/plugins/spaces-home-control/services/climate-intent.service.js.map +1 -1
  302. package/dist/plugins/spaces-home-control/services/covers-intent.service.d.ts +3 -1
  303. package/dist/plugins/spaces-home-control/services/covers-intent.service.js +6 -3
  304. package/dist/plugins/spaces-home-control/services/covers-intent.service.js.map +1 -1
  305. package/dist/plugins/spaces-home-control/services/lighting-intent.service.d.ts +3 -1
  306. package/dist/plugins/spaces-home-control/services/lighting-intent.service.js +7 -4
  307. package/dist/plugins/spaces-home-control/services/lighting-intent.service.js.map +1 -1
  308. package/dist/plugins/spaces-home-control/services/space-media-activity.service.d.ts +3 -1
  309. package/dist/plugins/spaces-home-control/services/space-media-activity.service.js +11 -5
  310. package/dist/plugins/spaces-home-control/services/space-media-activity.service.js.map +1 -1
  311. package/dist/plugins/spaces-home-control/services/space-undo-history.service.d.ts +3 -1
  312. package/dist/plugins/spaces-home-control/services/space-undo-history.service.js +8 -5
  313. package/dist/plugins/spaces-home-control/services/space-undo-history.service.js.map +1 -1
  314. package/dist/tsconfig.build.tsbuildinfo +1 -1
  315. package/package.json +5 -2
@@ -0,0 +1,71 @@
1
+ import { PropertyValueState } from '../models/property-value-state.model';
2
+ import { PropertyCommandValue } from '../utils/property-command-value.utils';
3
+ export declare const PROPERTY_COMMAND_CONFIRMATION_GRACE_MS = 1500;
4
+ export type PropertyCommandWindowState = 'pending' | 'confirmed_grace';
5
+ export interface PropertyCommandWindowTarget {
6
+ readonly deviceId: string;
7
+ readonly channelId: string;
8
+ readonly propertyId: string;
9
+ }
10
+ export interface PropertyCommandWindowHandle {
11
+ readonly canonicalPropertyId: string;
12
+ readonly generation: string;
13
+ }
14
+ export interface PropertyCommandReceipt {
15
+ readonly value: PropertyCommandValue;
16
+ readonly receivedAt: number;
17
+ }
18
+ export interface PropertyCommandPatchReceipt {
19
+ readonly baseline: PropertyValueState;
20
+ readonly optimisticState: PropertyValueState;
21
+ }
22
+ export interface PropertyCommandWindow {
23
+ readonly canonicalTarget: PropertyCommandWindowTarget;
24
+ readonly requestedTargets: readonly PropertyCommandWindowTarget[];
25
+ readonly generation: string;
26
+ readonly intentId: string | null;
27
+ readonly commandedValue: PropertyCommandValue;
28
+ readonly previousValue: PropertyCommandValue | null;
29
+ readonly lastReceipt: PropertyCommandReceipt | null;
30
+ readonly heldReceipt: PropertyCommandReceipt | null;
31
+ readonly recoveryReceipt: PropertyCommandReceipt | null;
32
+ readonly rollbackBaseline: PropertyValueState | null;
33
+ readonly patchReceipt: PropertyCommandPatchReceipt | null;
34
+ readonly openedAt: number;
35
+ readonly expiresAt: number;
36
+ readonly state: PropertyCommandWindowState;
37
+ readonly confirmedAt: number | null;
38
+ readonly confirmationExpiresAt: number | null;
39
+ }
40
+ export interface OpenPropertyCommandWindowInput {
41
+ readonly canonicalTarget: PropertyCommandWindowTarget;
42
+ readonly requestedTargets: readonly PropertyCommandWindowTarget[];
43
+ readonly intentId?: string;
44
+ readonly commandedValue: PropertyCommandValue;
45
+ readonly previousValue: PropertyCommandValue | null;
46
+ readonly ttlMs: number;
47
+ }
48
+ export declare class PropertyCommandWindowService {
49
+ private readonly windows;
50
+ private readonly recoveries;
51
+ open(input: OpenPropertyCommandWindowInput): PropertyCommandWindowHandle;
52
+ get(canonicalPropertyId: string): PropertyCommandWindow | null;
53
+ peekGeneration(canonicalPropertyId: string): string | undefined;
54
+ confirm(handle: PropertyCommandWindowHandle, receipt: PropertyCommandReceipt): PropertyCommandWindow | null;
55
+ attachPatchReceipt(handle: PropertyCommandWindowHandle, receipt: PropertyCommandPatchReceipt): boolean;
56
+ hold(handle: PropertyCommandWindowHandle, receipt: PropertyCommandReceipt): PropertyCommandWindow | null;
57
+ close(handle: PropertyCommandWindowHandle): boolean;
58
+ fail(handle: PropertyCommandWindowHandle): boolean;
59
+ sweep(): readonly PropertyCommandWindowHandle[];
60
+ expire(canonicalPropertyId: string): PropertyCommandWindowHandle | null;
61
+ getRecovery(handle: PropertyCommandWindowHandle): PropertyCommandWindow | null;
62
+ completeRecovery(handle: PropertyCommandWindowHandle): boolean;
63
+ cancelRecovery(canonicalPropertyId: string): void;
64
+ cancel(canonicalPropertyId: string): void;
65
+ clear(): void;
66
+ private getCurrent;
67
+ private isExpired;
68
+ private detach;
69
+ private pruneRecoveries;
70
+ private toSnapshot;
71
+ }
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.PropertyCommandWindowService = exports.PROPERTY_COMMAND_CONFIRMATION_GRACE_MS = void 0;
10
+ const node_crypto_1 = require("node:crypto");
11
+ const common_1 = require("@nestjs/common");
12
+ const property_value_state_model_1 = require("../models/property-value-state.model");
13
+ exports.PROPERTY_COMMAND_CONFIRMATION_GRACE_MS = 1_500;
14
+ let PropertyCommandWindowService = class PropertyCommandWindowService {
15
+ constructor() {
16
+ this.windows = new Map();
17
+ this.recoveries = new Map();
18
+ }
19
+ open(input) {
20
+ const now = Date.now();
21
+ const canonicalPropertyId = input.canonicalTarget.propertyId;
22
+ const current = this.getCurrent(canonicalPropertyId, now);
23
+ const ttlMs = Number.isFinite(input.ttlMs) && input.ttlMs > 0 ? input.ttlMs : 3_000;
24
+ const generation = (0, node_crypto_1.randomUUID)();
25
+ const previousValue = current?.commandedValue ?? input.previousValue;
26
+ this.recoveries.delete(canonicalPropertyId);
27
+ this.windows.set(canonicalPropertyId, {
28
+ canonicalTarget: freezeTarget(input.canonicalTarget),
29
+ requestedTargets: input.requestedTargets.map(freezeTarget),
30
+ generation,
31
+ intentId: input.intentId ?? null,
32
+ commandedValue: input.commandedValue,
33
+ previousValue,
34
+ lastReceipt: null,
35
+ heldReceipt: null,
36
+ recoveryReceipt: null,
37
+ rollbackBaseline: current?.rollbackBaseline ?? current?.patchReceipt?.baseline ?? null,
38
+ patchReceipt: null,
39
+ openedAt: now,
40
+ expiresAt: now + ttlMs,
41
+ state: 'pending',
42
+ confirmedAt: null,
43
+ confirmationExpiresAt: null,
44
+ });
45
+ return Object.freeze({ canonicalPropertyId, generation });
46
+ }
47
+ get(canonicalPropertyId) {
48
+ return this.toSnapshot(this.getCurrent(canonicalPropertyId, Date.now()));
49
+ }
50
+ peekGeneration(canonicalPropertyId) {
51
+ const current = this.windows.get(canonicalPropertyId);
52
+ return current !== undefined && current.expiresAt > Date.now() ? current.generation : undefined;
53
+ }
54
+ confirm(handle, receipt) {
55
+ const current = this.getCurrent(handle.canonicalPropertyId, Date.now());
56
+ if (current === undefined || current.generation !== handle.generation) {
57
+ return null;
58
+ }
59
+ if (current.state === 'pending') {
60
+ current.state = 'confirmed_grace';
61
+ current.confirmedAt = receipt.receivedAt;
62
+ current.confirmationExpiresAt = receipt.receivedAt + exports.PROPERTY_COMMAND_CONFIRMATION_GRACE_MS;
63
+ current.lastReceipt = freezeReceipt(receipt);
64
+ current.heldReceipt = null;
65
+ current.rollbackBaseline = null;
66
+ current.patchReceipt = null;
67
+ }
68
+ return this.toSnapshot(current);
69
+ }
70
+ attachPatchReceipt(handle, receipt) {
71
+ const current = this.getCurrent(handle.canonicalPropertyId, Date.now());
72
+ if (current === undefined || current.generation !== handle.generation || current.state !== 'pending') {
73
+ return false;
74
+ }
75
+ const baseline = current.rollbackBaseline ?? receipt.baseline;
76
+ current.rollbackBaseline = freezeValueState(baseline);
77
+ current.patchReceipt = freezePatchReceipt({
78
+ baseline,
79
+ optimisticState: receipt.optimisticState,
80
+ });
81
+ return true;
82
+ }
83
+ hold(handle, receipt) {
84
+ const current = this.getCurrent(handle.canonicalPropertyId, Date.now());
85
+ if (current === undefined || current.generation !== handle.generation || current.state !== 'pending') {
86
+ return null;
87
+ }
88
+ current.heldReceipt = freezeReceipt(receipt);
89
+ return this.toSnapshot(current);
90
+ }
91
+ close(handle) {
92
+ const current = this.windows.get(handle.canonicalPropertyId);
93
+ if (current !== undefined && current.generation === handle.generation) {
94
+ this.windows.delete(handle.canonicalPropertyId);
95
+ return true;
96
+ }
97
+ return false;
98
+ }
99
+ fail(handle) {
100
+ const current = this.getCurrent(handle.canonicalPropertyId, Date.now());
101
+ if (current === undefined || current.generation !== handle.generation || current.state !== 'pending') {
102
+ return false;
103
+ }
104
+ this.detach(handle.canonicalPropertyId, current);
105
+ return true;
106
+ }
107
+ sweep() {
108
+ const now = Date.now();
109
+ for (const [canonicalPropertyId, window] of this.windows) {
110
+ if (!this.isExpired(window, now)) {
111
+ continue;
112
+ }
113
+ this.detach(canonicalPropertyId, window);
114
+ }
115
+ this.pruneRecoveries(now);
116
+ return Object.freeze([...this.recoveries.entries()].map(([canonicalPropertyId, recovery]) => Object.freeze({ canonicalPropertyId, generation: recovery.window.generation })));
117
+ }
118
+ expire(canonicalPropertyId) {
119
+ const current = this.windows.get(canonicalPropertyId);
120
+ if (current === undefined || !this.isExpired(current, Date.now())) {
121
+ return null;
122
+ }
123
+ this.detach(canonicalPropertyId, current);
124
+ return Object.freeze({ canonicalPropertyId, generation: current.generation });
125
+ }
126
+ getRecovery(handle) {
127
+ this.pruneRecoveries(Date.now());
128
+ const recovery = this.recoveries.get(handle.canonicalPropertyId);
129
+ return recovery?.window.generation === handle.generation ? this.toSnapshot(recovery.window) : null;
130
+ }
131
+ completeRecovery(handle) {
132
+ const recovery = this.recoveries.get(handle.canonicalPropertyId);
133
+ if (recovery === undefined || recovery.window.generation !== handle.generation) {
134
+ return false;
135
+ }
136
+ this.recoveries.delete(handle.canonicalPropertyId);
137
+ return true;
138
+ }
139
+ cancelRecovery(canonicalPropertyId) {
140
+ this.recoveries.delete(canonicalPropertyId);
141
+ }
142
+ cancel(canonicalPropertyId) {
143
+ this.windows.delete(canonicalPropertyId);
144
+ this.recoveries.delete(canonicalPropertyId);
145
+ }
146
+ clear() {
147
+ this.windows.clear();
148
+ this.recoveries.clear();
149
+ }
150
+ getCurrent(canonicalPropertyId, now) {
151
+ const current = this.windows.get(canonicalPropertyId);
152
+ if (current !== undefined && this.isExpired(current, now)) {
153
+ this.detach(canonicalPropertyId, current);
154
+ return undefined;
155
+ }
156
+ return current;
157
+ }
158
+ isExpired(window, now) {
159
+ return now >= (window.confirmationExpiresAt ?? window.expiresAt);
160
+ }
161
+ detach(canonicalPropertyId, window, now = Date.now()) {
162
+ this.windows.delete(canonicalPropertyId);
163
+ if (window.state === 'pending' && (window.heldReceipt !== null || window.patchReceipt !== null)) {
164
+ this.recoveries.set(canonicalPropertyId, {
165
+ window,
166
+ deadlineAt: now + (window.expiresAt - window.openedAt),
167
+ });
168
+ }
169
+ }
170
+ pruneRecoveries(now) {
171
+ for (const [canonicalPropertyId, recovery] of this.recoveries) {
172
+ if (now >= recovery.deadlineAt) {
173
+ this.recoveries.delete(canonicalPropertyId);
174
+ }
175
+ }
176
+ }
177
+ toSnapshot(window) {
178
+ if (window === undefined) {
179
+ return null;
180
+ }
181
+ return Object.freeze({
182
+ ...window,
183
+ canonicalTarget: freezeTarget(window.canonicalTarget),
184
+ requestedTargets: Object.freeze(window.requestedTargets.map(freezeTarget)),
185
+ lastReceipt: window.lastReceipt === null ? null : freezeReceipt(window.lastReceipt),
186
+ heldReceipt: window.heldReceipt === null ? null : freezeReceipt(window.heldReceipt),
187
+ recoveryReceipt: window.recoveryReceipt === null ? null : freezeReceipt(window.recoveryReceipt),
188
+ rollbackBaseline: window.rollbackBaseline === null ? null : freezeValueState(window.rollbackBaseline),
189
+ patchReceipt: window.patchReceipt === null ? null : freezePatchReceipt(window.patchReceipt),
190
+ });
191
+ }
192
+ };
193
+ exports.PropertyCommandWindowService = PropertyCommandWindowService;
194
+ exports.PropertyCommandWindowService = PropertyCommandWindowService = __decorate([
195
+ (0, common_1.Injectable)()
196
+ ], PropertyCommandWindowService);
197
+ const freezeTarget = (target) => Object.freeze({ ...target });
198
+ const freezeReceipt = (receipt) => Object.freeze({ ...receipt });
199
+ const freezePatchReceipt = (receipt) => Object.freeze({
200
+ baseline: freezeValueState(receipt.baseline),
201
+ optimisticState: freezeValueState(receipt.optimisticState),
202
+ });
203
+ const freezeValueState = (state) => Object.freeze(new property_value_state_model_1.PropertyValueState(state.value, state.lastUpdated, state.trend));
204
+ //# sourceMappingURL=property-command-window.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-command-window.service.js","sourceRoot":"","sources":["../../../../src/modules/devices/services/property-command-window.service.ts"],"names":[],"mappings":"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"}
@@ -2,15 +2,27 @@ import { IntentContext } from '../../intents/models/intent.model';
2
2
  import { IntentsService } from '../../intents/services/intents.service';
3
3
  import { ClientUserDto } from '../../websocket/dto/client-user.dto';
4
4
  import { UpdateChannelPropertyDto } from '../dto/update-channel-property.dto';
5
- import { ChannelPropertyEntity, DeviceEntity } from '../entities/devices.entity';
5
+ import { ChannelEntity, ChannelPropertyEntity, DeviceEntity } from '../entities/devices.entity';
6
+ import { PropertyValueState } from '../models/property-value-state.model';
6
7
  import { PropertyCommandValue } from '../utils/property-command-value.utils';
7
8
  import { ChannelsPropertiesService } from './channels.properties.service';
8
9
  import { ChannelsService } from './channels.service';
10
+ import { CommandLatencyTraceCollectorService } from './command-latency-trace-collector.service';
9
11
  import { DevicesService } from './devices.service';
10
12
  import { PlatformRegistryService } from './platform.registry.service';
13
+ import { PropertyCommandDispatchService } from './property-command-dispatch.service';
14
+ import { PropertyCommandWindowHandle, PropertyCommandWindowService } from './property-command-window.service';
11
15
  export interface PropertyCommandExecutionOptions {
12
16
  requestId?: string;
13
17
  context?: IntentContext;
18
+ apiReceipt?: ApiPropertyCommandReceipt;
19
+ }
20
+ export interface ApiPropertyCommandReceipt {
21
+ readonly handle: PropertyCommandWindowHandle;
22
+ readonly canonicalPropertyId: string;
23
+ readonly baseline: PropertyValueState | null;
24
+ readonly optimisticEligible: boolean;
25
+ readonly ttlMs: number;
14
26
  }
15
27
  export interface DevicePropertyCommandResult {
16
28
  device: string;
@@ -23,14 +35,21 @@ export interface SinglePropertyCommandResult extends DevicePropertyCommandResult
23
35
  property?: string;
24
36
  value?: PropertyCommandValue;
25
37
  }
38
+ export interface PropertyBatchCommandResult {
39
+ success: boolean;
40
+ results: SinglePropertyCommandResult[];
41
+ }
26
42
  export declare class PropertyCommandService {
27
43
  private readonly devicesService;
28
44
  private readonly channelsService;
29
45
  private readonly channelsPropertiesService;
30
46
  private readonly platformRegistryService;
31
47
  private readonly intentsService;
48
+ private readonly propertyCommandDispatchService;
49
+ private readonly propertyCommandWindowService;
50
+ private readonly commandLatencyTraceCollector;
32
51
  private readonly logger;
33
- constructor(devicesService: DevicesService, channelsService: ChannelsService, channelsPropertiesService: ChannelsPropertiesService, platformRegistryService: PlatformRegistryService, intentsService: IntentsService);
52
+ constructor(devicesService: DevicesService, channelsService: ChannelsService, channelsPropertiesService: ChannelsPropertiesService, platformRegistryService: PlatformRegistryService, intentsService: IntentsService, propertyCommandDispatchService: PropertyCommandDispatchService, propertyCommandWindowService: PropertyCommandWindowService, commandLatencyTraceCollector?: CommandLatencyTraceCollectorService);
34
53
  handleInternal(user: ClientUserDto, payload?: object): Promise<{
35
54
  success: boolean;
36
55
  results: Array<{
@@ -40,9 +59,15 @@ export declare class PropertyCommandService {
40
59
  }> | string;
41
60
  }>;
42
61
  executePropertyCommandById(propertyId: string, rawValue: unknown, options?: PropertyCommandExecutionOptions): Promise<SinglePropertyCommandResult>;
62
+ executePropertyCommands(commands: Array<{
63
+ propertyId: string;
64
+ value: unknown;
65
+ }>, options?: PropertyCommandExecutionOptions): Promise<PropertyBatchCommandResult>;
43
66
  private executeCommands;
44
67
  private resolveCommandIntentTtlMs;
45
68
  private processDeviceCommands;
46
- processApiPropertyCommand(deviceId: string, channelId: string, propertyId: string, value: string | number | boolean): Promise<void>;
69
+ processApiPropertyCommand(deviceId: string, channelId: string, propertyId: string, value: string | number | boolean, receipt?: ApiPropertyCommandReceipt): Promise<void>;
70
+ prepareApiPropertyCommand(device: DeviceEntity | string, channel: ChannelEntity, property: ChannelPropertyEntity, value: string | number | boolean): Promise<ApiPropertyCommandReceipt | null>;
71
+ failApiPropertyCommandReceipt(receipt: ApiPropertyCommandReceipt): void;
47
72
  usesAuthoritativePropertyReadback(device: DeviceEntity | string, property: ChannelPropertyEntity, update?: UpdateChannelPropertyDto): Promise<boolean>;
48
73
  }
@@ -8,6 +8,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.PropertyCommandService = void 0;
13
16
  const class_validator_1 = require("class-validator");
@@ -24,15 +27,21 @@ const property_command_dto_1 = require("../dto/property-command.dto");
24
27
  const property_command_value_utils_1 = require("../utils/property-command-value.utils");
25
28
  const channels_properties_service_1 = require("./channels.properties.service");
26
29
  const channels_service_1 = require("./channels.service");
30
+ const command_latency_trace_collector_service_1 = require("./command-latency-trace-collector.service");
27
31
  const devices_service_1 = require("./devices.service");
28
32
  const platform_registry_service_1 = require("./platform.registry.service");
33
+ const property_command_dispatch_service_1 = require("./property-command-dispatch.service");
34
+ const property_command_window_service_1 = require("./property-command-window.service");
29
35
  let PropertyCommandService = class PropertyCommandService {
30
- constructor(devicesService, channelsService, channelsPropertiesService, platformRegistryService, intentsService) {
36
+ constructor(devicesService, channelsService, channelsPropertiesService, platformRegistryService, intentsService, propertyCommandDispatchService, propertyCommandWindowService, commandLatencyTraceCollector = new command_latency_trace_collector_service_1.CommandLatencyTraceCollectorService()) {
31
37
  this.devicesService = devicesService;
32
38
  this.channelsService = channelsService;
33
39
  this.channelsPropertiesService = channelsPropertiesService;
34
40
  this.platformRegistryService = platformRegistryService;
35
41
  this.intentsService = intentsService;
42
+ this.propertyCommandDispatchService = propertyCommandDispatchService;
43
+ this.propertyCommandWindowService = propertyCommandWindowService;
44
+ this.commandLatencyTraceCollector = commandLatencyTraceCollector;
36
45
  this.logger = (0, extension_logger_service_1.createExtensionLogger)(devices_constants_1.DEVICES_MODULE_NAME, 'PropertyCommandService');
37
46
  }
38
47
  async handleInternal(user, payload) {
@@ -129,6 +138,121 @@ let PropertyCommandService = class PropertyCommandService {
129
138
  reason: result?.reason ?? (typeof execution.results === 'string' ? execution.results : undefined),
130
139
  };
131
140
  }
141
+ async executePropertyCommands(commands, options = {}) {
142
+ if (commands.length === 0) {
143
+ return { success: true, results: [] };
144
+ }
145
+ const resolved = [];
146
+ let targetDeviceId = null;
147
+ for (const cmd of commands) {
148
+ const property = await this.channelsPropertiesService.findOne(cmd.propertyId);
149
+ if (!property) {
150
+ return {
151
+ success: false,
152
+ results: commands.map((c) => ({
153
+ device: '',
154
+ success: false,
155
+ property: c.propertyId,
156
+ reason: c.propertyId === cmd.propertyId ? 'Property not found' : 'Batch aborted due to invalid property',
157
+ })),
158
+ };
159
+ }
160
+ const propertyChannel = property.channel;
161
+ const channel = typeof propertyChannel === 'string' ? await this.channelsService.findOne(propertyChannel) : propertyChannel;
162
+ if (!channel) {
163
+ return {
164
+ success: false,
165
+ results: commands.map((c) => ({
166
+ device: '',
167
+ success: false,
168
+ property: c.propertyId,
169
+ reason: c.propertyId === cmd.propertyId ? 'Channel not found' : 'Batch aborted due to invalid channel',
170
+ })),
171
+ };
172
+ }
173
+ const channelDevice = channel.device;
174
+ const device = typeof channelDevice === 'string' ? await this.devicesService.findOne(channelDevice) : channelDevice;
175
+ if (!device) {
176
+ return {
177
+ success: false,
178
+ results: commands.map((c) => ({
179
+ device: '',
180
+ success: false,
181
+ property: c.propertyId,
182
+ reason: c.propertyId === cmd.propertyId ? 'Device not found' : 'Batch aborted due to invalid device',
183
+ })),
184
+ };
185
+ }
186
+ if (targetDeviceId === null) {
187
+ targetDeviceId = device.id;
188
+ }
189
+ else if (targetDeviceId !== device.id) {
190
+ return {
191
+ success: false,
192
+ results: commands.map((c) => ({
193
+ device: device.id,
194
+ success: false,
195
+ property: c.propertyId,
196
+ reason: `Single-device batch execution violation: properties belong to multiple devices (${targetDeviceId} vs ${device.id})`,
197
+ })),
198
+ };
199
+ }
200
+ if (!property.permissions.some((permission) => [devices_constants_1.PermissionType.READ_WRITE, devices_constants_1.PermissionType.WRITE_ONLY].includes(permission))) {
201
+ return {
202
+ success: false,
203
+ results: commands.map((c) => ({
204
+ device: device.id,
205
+ success: false,
206
+ property: c.propertyId,
207
+ reason: c.propertyId === cmd.propertyId ? 'Property is not writable' : 'Batch aborted: property not writable',
208
+ })),
209
+ };
210
+ }
211
+ const validation = (0, property_command_value_utils_1.validatePropertyCommandValue)(property, cmd.value);
212
+ if (!validation.valid || validation.value === undefined) {
213
+ return {
214
+ success: false,
215
+ results: commands.map((c) => ({
216
+ device: device.id,
217
+ success: false,
218
+ property: c.propertyId,
219
+ reason: c.propertyId === cmd.propertyId
220
+ ? (validation.reason ?? 'Invalid property value')
221
+ : 'Batch aborted: invalid value',
222
+ })),
223
+ };
224
+ }
225
+ resolved.push({
226
+ propertyId: cmd.propertyId,
227
+ property,
228
+ channel,
229
+ device,
230
+ value: validation.value,
231
+ });
232
+ }
233
+ const propertyCommandDtos = resolved.map((r) => ({
234
+ device: r.device.id,
235
+ channel: r.channel.id,
236
+ property: r.property.id,
237
+ value: r.value,
238
+ }));
239
+ const execution = await this.executeCommands(propertyCommandDtos, options);
240
+ const deviceResult = Array.isArray(execution.results) ? execution.results[0] : undefined;
241
+ const executionSuccess = execution.success && (deviceResult?.success ?? false);
242
+ const results = resolved.map((r) => ({
243
+ device: r.device.id,
244
+ deviceName: r.device.name,
245
+ channel: r.channel.id,
246
+ property: r.property.id,
247
+ value: r.value,
248
+ success: executionSuccess,
249
+ reason: deviceResult?.reason ?? (typeof execution.results === 'string' ? execution.results : undefined),
250
+ }));
251
+ return {
252
+ success: executionSuccess,
253
+ results,
254
+ };
255
+ }
132
256
  async executeCommands(commands, options) {
133
257
  const targets = commands.map((command) => ({
134
258
  deviceId: command.device,
@@ -146,19 +270,29 @@ let PropertyCommandService = class PropertyCommandService {
146
270
  }
147
271
  groupedProperties[prop.device].push(prop);
148
272
  });
273
+ const ttlMs = options.apiReceipt?.ttlMs ?? (await this.resolveCommandIntentTtlMs(groupedProperties));
149
274
  const intent = this.intentsService.createIntent({
150
275
  requestId: options.requestId,
151
276
  type: intents_constants_1.IntentType.DEVICE_SET_PROPERTY,
152
277
  context: options.context,
153
278
  targets,
154
279
  value: valueMap,
155
- ttlMs: await this.resolveCommandIntentTtlMs(groupedProperties),
280
+ ttlMs,
156
281
  });
157
282
  this.logger.log(`Created intent ${intent.id} for ${targets.length} target(s)${options.requestId ? ` requestId=${options.requestId}` : ''}`);
283
+ this.commandLatencyTraceCollector.observeCommand({
284
+ requestId: options.requestId,
285
+ intentId: intent.id,
286
+ properties: commands,
287
+ });
158
288
  const results = [];
159
289
  try {
160
290
  for (const deviceId of Object.keys(groupedProperties)) {
161
- const result = await this.processDeviceCommands(deviceId, groupedProperties[deviceId]);
291
+ const result = await this.processDeviceCommands(deviceId, groupedProperties[deviceId], {
292
+ intentId: intent.id,
293
+ ttlMs,
294
+ windowHandles: options.apiReceipt === undefined ? undefined : [options.apiReceipt.handle],
295
+ });
162
296
  results.push(result);
163
297
  }
164
298
  const intentResults = [];
@@ -206,7 +340,7 @@ let PropertyCommandService = class PropertyCommandService {
206
340
  }
207
341
  return this.platformRegistryService.getCommandTtlMs(executions, intents_constants_1.DEFAULT_TTL_DEVICE_COMMAND);
208
342
  }
209
- async processDeviceCommands(deviceId, commands) {
343
+ async processDeviceCommands(deviceId, commands, dispatchOptions) {
210
344
  const device = await this.devicesService.findOne(deviceId);
211
345
  if (!device) {
212
346
  this.logger.warn(`Device not found id=${deviceId}`);
@@ -246,22 +380,45 @@ let PropertyCommandService = class PropertyCommandService {
246
380
  propertyUpdates.push({ device, channel, property, value: validation.value });
247
381
  }
248
382
  this.logger.log(`Processing batch of ${propertyUpdates.length} commands for deviceId=${device.id}`);
249
- const success = await platform.processBatch(propertyUpdates);
250
- if (!success) {
383
+ const dispatch = await this.propertyCommandDispatchService.dispatchBatch(propertyUpdates, dispatchOptions);
384
+ if (!dispatch.success) {
251
385
  this.logger.error(`Batch command execution failed for deviceId=${device.id}`);
252
- return { device: deviceId, success: false, reason: 'Execution failed' };
386
+ return { device: deviceId, success: false, reason: dispatch.reason ?? 'Execution failed' };
253
387
  }
254
388
  this.logger.log(`Successfully executed batch command for deviceId=${device.id}`);
255
389
  return { device: deviceId, success: true };
256
390
  }
257
- async processApiPropertyCommand(deviceId, channelId, propertyId, value) {
258
- const execution = await this.executeCommands([{ device: deviceId, channel: channelId, property: propertyId, value }], { context: { origin: 'api' } });
391
+ async processApiPropertyCommand(deviceId, channelId, propertyId, value, receipt) {
392
+ const execution = await this.executeCommands([{ device: deviceId, channel: channelId, property: propertyId, value }], { context: { origin: 'api' }, apiReceipt: receipt });
259
393
  const result = Array.isArray(execution.results) ? execution.results[0] : undefined;
260
394
  if (!execution.success) {
395
+ if (receipt !== undefined) {
396
+ this.propertyCommandWindowService.fail(receipt.handle);
397
+ }
261
398
  const reason = result?.reason ?? (typeof execution.results === 'string' ? execution.results : 'Execution failed');
262
399
  this.logger.warn(`[API Command] Failed for deviceId=${deviceId}: ${reason}`);
263
400
  }
264
401
  }
402
+ async prepareApiPropertyCommand(device, channel, property, value) {
403
+ try {
404
+ const resolvedDevice = typeof device === 'string' ? await this.devicesService.findOne(device) : device;
405
+ if (resolvedDevice === null) {
406
+ return null;
407
+ }
408
+ const ttlMs = await this.resolveCommandIntentTtlMs({
409
+ [resolvedDevice.id]: [{ device: resolvedDevice.id, channel: channel.id, property: property.id, value }],
410
+ });
411
+ const prepared = await this.propertyCommandDispatchService.prepareApiCommand({ device: resolvedDevice, channel, property, value }, ttlMs);
412
+ return prepared === null ? null : { ...prepared, ttlMs };
413
+ }
414
+ catch (error) {
415
+ this.logger.warn(`[API Command] Could not prepare optimistic receipt for propertyId=${property.id}: ${error instanceof Error ? error.message : String(error)}`);
416
+ return null;
417
+ }
418
+ }
419
+ failApiPropertyCommandReceipt(receipt) {
420
+ this.propertyCommandWindowService.fail(receipt.handle);
421
+ }
265
422
  async usesAuthoritativePropertyReadback(device, property, update) {
266
423
  const resolvedDevice = typeof device === 'string' ? await this.devicesService.findOne(device) : device;
267
424
  const effectiveProperty = update
@@ -274,10 +431,14 @@ let PropertyCommandService = class PropertyCommandService {
274
431
  exports.PropertyCommandService = PropertyCommandService;
275
432
  exports.PropertyCommandService = PropertyCommandService = __decorate([
276
433
  (0, common_1.Injectable)(),
434
+ __param(7, (0, common_1.Optional)()),
277
435
  __metadata("design:paramtypes", [devices_service_1.DevicesService,
278
436
  channels_service_1.ChannelsService,
279
437
  channels_properties_service_1.ChannelsPropertiesService,
280
438
  platform_registry_service_1.PlatformRegistryService,
281
- intents_service_1.IntentsService])
439
+ intents_service_1.IntentsService,
440
+ property_command_dispatch_service_1.PropertyCommandDispatchService,
441
+ property_command_window_service_1.PropertyCommandWindowService,
442
+ command_latency_trace_collector_service_1.CommandLatencyTraceCollectorService])
282
443
  ], PropertyCommandService);
283
444
  //# sourceMappingURL=property-command.service.js.map