@fastybird/smart-panel-backend 1.1.0-alpha.3 → 1.1.0-alpha.30

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 (412) hide show
  1. package/dist/app.module.js +8 -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/dataSource.js +1 -0
  15. package/dist/dataSource.js.map +1 -1
  16. package/dist/main.js +2 -7
  17. package/dist/main.js.map +1 -1
  18. package/dist/migrations/1000000000026-AddHardwareInputCategories.d.ts +7 -0
  19. package/dist/migrations/1000000000026-AddHardwareInputCategories.js +364 -0
  20. package/dist/migrations/1000000000026-AddHardwareInputCategories.js.map +1 -0
  21. package/dist/modules/devices/controllers/channels.controller.d.ts +5 -1
  22. package/dist/modules/devices/controllers/channels.controller.js +34 -2
  23. package/dist/modules/devices/controllers/channels.controller.js.map +1 -1
  24. package/dist/modules/devices/controllers/channels.properties.controller.js +21 -4
  25. package/dist/modules/devices/controllers/channels.properties.controller.js.map +1 -1
  26. package/dist/modules/devices/controllers/devices.channels.controller.d.ts +5 -1
  27. package/dist/modules/devices/controllers/devices.channels.controller.js +38 -2
  28. package/dist/modules/devices/controllers/devices.channels.controller.js.map +1 -1
  29. package/dist/modules/devices/controllers/devices.channels.properties.controller.js +21 -4
  30. package/dist/modules/devices/controllers/devices.channels.properties.controller.js.map +1 -1
  31. package/dist/modules/devices/devices.constants.d.ts +6 -0
  32. package/dist/modules/devices/devices.constants.js +6 -0
  33. package/dist/modules/devices/devices.constants.js.map +1 -1
  34. package/dist/modules/devices/devices.module.js +20 -0
  35. package/dist/modules/devices/devices.module.js.map +1 -1
  36. package/dist/modules/devices/devices.openapi.d.ts +3 -1
  37. package/dist/modules/devices/devices.openapi.js +7 -0
  38. package/dist/modules/devices/devices.openapi.js.map +1 -1
  39. package/dist/modules/devices/dto/channel-input-occurrence.dto.d.ts +10 -0
  40. package/dist/modules/devices/dto/channel-input-occurrence.dto.js +99 -0
  41. package/dist/modules/devices/dto/channel-input-occurrence.dto.js.map +1 -0
  42. package/dist/modules/devices/models/channel-input-capabilities.model.d.ts +20 -0
  43. package/dist/modules/devices/models/channel-input-capabilities.model.js +111 -0
  44. package/dist/modules/devices/models/channel-input-capabilities.model.js.map +1 -0
  45. package/dist/modules/devices/models/channel-input-occurrence.model.d.ts +22 -0
  46. package/dist/modules/devices/models/channel-input-occurrence.model.js +154 -0
  47. package/dist/modules/devices/models/channel-input-occurrence.model.js.map +1 -0
  48. package/dist/modules/devices/services/channel-input-deduplication.service.d.ts +17 -0
  49. package/dist/modules/devices/services/channel-input-deduplication.service.js +88 -0
  50. package/dist/modules/devices/services/channel-input-deduplication.service.js.map +1 -0
  51. package/dist/modules/devices/services/channel-input-occurrences.service.d.ts +21 -0
  52. package/dist/modules/devices/services/channel-input-occurrences.service.js +163 -0
  53. package/dist/modules/devices/services/channel-input-occurrences.service.js.map +1 -0
  54. package/dist/modules/devices/services/channels.properties.service.d.ts +31 -3
  55. package/dist/modules/devices/services/channels.properties.service.js +346 -51
  56. package/dist/modules/devices/services/channels.properties.service.js.map +1 -1
  57. package/dist/modules/devices/services/channels.service.js +42 -38
  58. package/dist/modules/devices/services/channels.service.js.map +1 -1
  59. package/dist/modules/devices/services/command-latency-trace-collector.service.d.ts +101 -0
  60. package/dist/modules/devices/services/command-latency-trace-collector.service.js +451 -0
  61. package/dist/modules/devices/services/command-latency-trace-collector.service.js.map +1 -0
  62. package/dist/modules/devices/services/device-structure-lock.service.d.ts +10 -2
  63. package/dist/modules/devices/services/device-structure-lock.service.js +86 -7
  64. package/dist/modules/devices/services/device-structure-lock.service.js.map +1 -1
  65. package/dist/modules/devices/services/devices.service.js +37 -33
  66. package/dist/modules/devices/services/devices.service.js.map +1 -1
  67. package/dist/modules/devices/services/module-reset.service.d.ts +3 -1
  68. package/dist/modules/devices/services/module-reset.service.js +21 -16
  69. package/dist/modules/devices/services/module-reset.service.js.map +1 -1
  70. package/dist/modules/devices/services/property-command-dispatch.service.d.ts +45 -0
  71. package/dist/modules/devices/services/property-command-dispatch.service.js +227 -0
  72. package/dist/modules/devices/services/property-command-dispatch.service.js.map +1 -0
  73. package/dist/modules/devices/services/property-command-window.service.d.ts +71 -0
  74. package/dist/modules/devices/services/property-command-window.service.js +206 -0
  75. package/dist/modules/devices/services/property-command-window.service.js.map +1 -0
  76. package/dist/modules/devices/services/property-command.service.d.ts +20 -3
  77. package/dist/modules/devices/services/property-command.service.js +56 -10
  78. package/dist/modules/devices/services/property-command.service.js.map +1 -1
  79. package/dist/modules/devices/services/property-metadata.service.d.ts +31 -0
  80. package/dist/modules/devices/services/property-metadata.service.js +160 -0
  81. package/dist/modules/devices/services/property-metadata.service.js.map +1 -0
  82. package/dist/modules/devices/services/property-state-coordinator.service.d.ts +4 -0
  83. package/dist/modules/devices/services/property-state-coordinator.service.js +35 -0
  84. package/dist/modules/devices/services/property-state-coordinator.service.js.map +1 -0
  85. package/dist/modules/devices/services/property-value-lock.service.d.ts +3 -1
  86. package/dist/modules/devices/services/property-value-lock.service.js +13 -2
  87. package/dist/modules/devices/services/property-value-lock.service.js.map +1 -1
  88. package/dist/modules/devices/services/property-value.service.d.ts +1 -0
  89. package/dist/modules/devices/services/property-value.service.js +4 -0
  90. package/dist/modules/devices/services/property-value.service.js.map +1 -1
  91. package/dist/modules/devices/utils/schema.utils.js +1 -1
  92. package/dist/modules/devices/utils/schema.utils.js.map +1 -1
  93. package/dist/modules/platform/platforms/raspberry.platform.js +5 -10
  94. package/dist/modules/platform/platforms/raspberry.platform.js.map +1 -1
  95. package/dist/modules/platform/services/platform.service.d.ts +13 -4
  96. package/dist/modules/platform/services/platform.service.js +57 -35
  97. package/dist/modules/platform/services/platform.service.js.map +1 -1
  98. package/dist/modules/remote-access/dto/update-config.dto.js +5 -0
  99. package/dist/modules/remote-access/dto/update-config.dto.js.map +1 -1
  100. package/dist/modules/remote-access/validators/is-remote-access-url.validator.js +5 -2
  101. package/dist/modules/remote-access/validators/is-remote-access-url.validator.js.map +1 -1
  102. package/dist/modules/system/scripts/update-worker.sh +1168 -61
  103. package/dist/modules/system/services/privileged-worker.service.d.ts +13 -0
  104. package/dist/modules/system/services/privileged-worker.service.js +192 -31
  105. package/dist/modules/system/services/privileged-worker.service.js.map +1 -1
  106. package/dist/modules/system/services/system.service.d.ts +2 -0
  107. package/dist/modules/system/services/system.service.js +22 -1
  108. package/dist/modules/system/services/system.service.js.map +1 -1
  109. package/dist/modules/system/services/update-executor.service.d.ts +20 -2
  110. package/dist/modules/system/services/update-executor.service.js +272 -26
  111. package/dist/modules/system/services/update-executor.service.js.map +1 -1
  112. package/dist/modules/websocket/gateway/websocket.gateway.d.ts +4 -1
  113. package/dist/modules/websocket/gateway/websocket.gateway.js +28 -5
  114. package/dist/modules/websocket/gateway/websocket.gateway.js.map +1 -1
  115. package/dist/modules/websocket/services/command-acknowledgement-trace.service.d.ts +143 -0
  116. package/dist/modules/websocket/services/command-acknowledgement-trace.service.js +523 -0
  117. package/dist/modules/websocket/services/command-acknowledgement-trace.service.js.map +1 -0
  118. package/dist/modules/websocket/websocket.module.js +9 -1
  119. package/dist/modules/websocket/websocket.module.js.map +1 -1
  120. package/dist/plugins/devices-home-assistant/devices-home-assistant.openapi.d.ts +2 -2
  121. package/dist/plugins/devices-home-assistant/devices-home-assistant.plugin.d.ts +6 -1
  122. package/dist/plugins/devices-home-assistant/devices-home-assistant.plugin.js +16 -1
  123. package/dist/plugins/devices-home-assistant/devices-home-assistant.plugin.js.map +1 -1
  124. package/dist/plugins/devices-home-assistant/dto/mapping-preview.dto.d.ts +1 -0
  125. package/dist/plugins/devices-home-assistant/dto/mapping-preview.dto.js +11 -0
  126. package/dist/plugins/devices-home-assistant/dto/mapping-preview.dto.js.map +1 -1
  127. package/dist/plugins/devices-home-assistant/mappers/button.entity.mapper.service.d.ts +19 -0
  128. package/dist/plugins/devices-home-assistant/mappers/button.entity.mapper.service.js +51 -0
  129. package/dist/plugins/devices-home-assistant/mappers/button.entity.mapper.service.js.map +1 -0
  130. package/dist/plugins/devices-home-assistant/mappings/definitions/entity-mappings.yaml +56 -7
  131. package/dist/plugins/devices-home-assistant/models/mapping-preview.model.d.ts +1 -0
  132. package/dist/plugins/devices-home-assistant/models/mapping-preview.model.js +11 -0
  133. package/dist/plugins/devices-home-assistant/models/mapping-preview.model.js.map +1 -1
  134. package/dist/plugins/devices-home-assistant/services/device-adoption.service.js +17 -0
  135. package/dist/plugins/devices-home-assistant/services/device-adoption.service.js.map +1 -1
  136. package/dist/plugins/devices-home-assistant/services/home-assistant-raw-event.service.d.ts +27 -0
  137. package/dist/plugins/devices-home-assistant/services/home-assistant-raw-event.service.js +271 -0
  138. package/dist/plugins/devices-home-assistant/services/home-assistant-raw-event.service.js.map +1 -0
  139. package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.d.ts +2 -2
  140. package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.js +33 -14
  141. package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.js.map +1 -1
  142. package/dist/plugins/devices-home-assistant/services/mapping-preview.service.js +24 -4
  143. package/dist/plugins/devices-home-assistant/services/mapping-preview.service.js.map +1 -1
  144. package/dist/plugins/devices-home-assistant/services/state-changed.event.service.d.ts +4 -1
  145. package/dist/plugins/devices-home-assistant/services/state-changed.event.service.js +84 -5
  146. package/dist/plugins/devices-home-assistant/services/state-changed.event.service.js.map +1 -1
  147. package/dist/plugins/devices-home-assistant/services/wizard.service.js +1 -0
  148. package/dist/plugins/devices-home-assistant/services/wizard.service.js.map +1 -1
  149. package/dist/plugins/devices-home-assistant/utils/ha-event.utils.d.ts +2 -0
  150. package/dist/plugins/devices-home-assistant/utils/ha-event.utils.js +50 -0
  151. package/dist/plugins/devices-home-assistant/utils/ha-event.utils.js.map +1 -0
  152. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.d.ts +4 -1
  153. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.js +39 -4
  154. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.js.map +1 -1
  155. package/dist/plugins/devices-homekit/mappers/base.mapper.js +30 -6
  156. package/dist/plugins/devices-homekit/mappers/base.mapper.js.map +1 -1
  157. package/dist/plugins/devices-homekit/mappers/button.mapper.d.ts +15 -0
  158. package/dist/plugins/devices-homekit/mappers/button.mapper.js +143 -0
  159. package/dist/plugins/devices-homekit/mappers/button.mapper.js.map +1 -0
  160. package/dist/plugins/devices-homekit/mappers/characteristic-write.d.ts +2 -0
  161. package/dist/plugins/devices-homekit/mappers/characteristic-write.js +17 -0
  162. package/dist/plugins/devices-homekit/mappers/characteristic-write.js.map +1 -0
  163. package/dist/plugins/devices-homekit/mappers/homekit-mapper.interface.d.ts +17 -1
  164. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.d.ts +7 -0
  165. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.js +96 -84
  166. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.js.map +1 -1
  167. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.d.ts +5 -1
  168. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.js +42 -0
  169. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.js.map +1 -1
  170. package/dist/plugins/devices-homey/mappings/definitions/channels.yaml +50 -0
  171. package/dist/plugins/devices-homey/mappings/definitions/devices.yaml +18 -0
  172. package/dist/plugins/devices-homey/mappings/definitions/properties.yaml +55 -0
  173. package/dist/plugins/devices-homey/mappings/device-support.js +10 -0
  174. package/dist/plugins/devices-homey/mappings/device-support.js.map +1 -1
  175. package/dist/plugins/devices-homey/mappings/mapping-loader.service.d.ts +1 -0
  176. package/dist/plugins/devices-homey/mappings/mapping-loader.service.js +66 -8
  177. package/dist/plugins/devices-homey/mappings/mapping-loader.service.js.map +1 -1
  178. package/dist/plugins/devices-homey/models/inventory.model.d.ts +2 -1
  179. package/dist/plugins/devices-homey/models/inventory.model.js +1 -0
  180. package/dist/plugins/devices-homey/models/inventory.model.js.map +1 -1
  181. package/dist/plugins/devices-homey/models/mapping-preview.model.d.ts +1 -0
  182. package/dist/plugins/devices-homey/models/mapping-preview.model.js +1 -0
  183. package/dist/plugins/devices-homey/models/mapping-preview.model.js.map +1 -1
  184. package/dist/plugins/devices-homey/services/homey-mapping-preview.service.js +7 -0
  185. package/dist/plugins/devices-homey/services/homey-mapping-preview.service.js.map +1 -1
  186. package/dist/plugins/devices-homey/services/homey-synchronizer.service.d.ts +3 -1
  187. package/dist/plugins/devices-homey/services/homey-synchronizer.service.js +37 -6
  188. package/dist/plugins/devices-homey/services/homey-synchronizer.service.js.map +1 -1
  189. package/dist/plugins/devices-reterminal/services/reterminal-button.service.d.ts +7 -3
  190. package/dist/plugins/devices-reterminal/services/reterminal-button.service.js +63 -17
  191. package/dist/plugins/devices-reterminal/services/reterminal-button.service.js.map +1 -1
  192. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.d.ts +36 -3
  193. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js +707 -42
  194. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js.map +1 -1
  195. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.d.ts +11 -1
  196. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js +100 -10
  197. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js.map +1 -1
  198. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.constants.js +9 -11
  199. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.constants.js.map +1 -1
  200. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.plugin.js +2 -0
  201. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.plugin.js.map +1 -1
  202. package/dist/plugins/devices-shelly-ng/mappings/definitions/inputs.yaml +80 -0
  203. package/dist/plugins/devices-shelly-ng/mappings/mapping-loader.service.js +7 -1
  204. package/dist/plugins/devices-shelly-ng/mappings/mapping-loader.service.js.map +1 -1
  205. package/dist/plugins/devices-shelly-ng/mappings/mapping.types.d.ts +6 -3
  206. package/dist/plugins/devices-shelly-ng/mappings/schema/mapping-schema.json +5 -0
  207. package/dist/plugins/devices-shelly-ng/services/device-manager.service.js +153 -8
  208. package/dist/plugins/devices-shelly-ng/services/device-manager.service.js.map +1 -1
  209. package/dist/plugins/devices-shelly-ng/services/poll-placement-diagnostics.service.d.ts +51 -0
  210. package/dist/plugins/devices-shelly-ng/services/poll-placement-diagnostics.service.js +549 -0
  211. package/dist/plugins/devices-shelly-ng/services/poll-placement-diagnostics.service.js.map +1 -0
  212. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.d.ts +14 -2
  213. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js +134 -35
  214. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js.map +1 -1
  215. package/dist/plugins/devices-shelly-ng/services/shelly-rpc-client.service.js +3 -0
  216. package/dist/plugins/devices-shelly-ng/services/shelly-rpc-client.service.js.map +1 -1
  217. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.d.ts +1 -0
  218. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.js +14 -4
  219. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.js.map +1 -1
  220. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.d.ts +2 -0
  221. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.js +66 -4
  222. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.js.map +1 -1
  223. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.plugin.js +2 -0
  224. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.plugin.js.map +1 -1
  225. package/dist/plugins/devices-shelly-v1/platforms/shelly-v1.device.platform.js +7 -0
  226. package/dist/plugins/devices-shelly-v1/platforms/shelly-v1.device.platform.js.map +1 -1
  227. package/dist/plugins/devices-shelly-v1/services/device-mapper.service.d.ts +3 -1
  228. package/dist/plugins/devices-shelly-v1/services/device-mapper.service.js +20 -2
  229. package/dist/plugins/devices-shelly-v1/services/device-mapper.service.js.map +1 -1
  230. package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.d.ts +16 -0
  231. package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.js +107 -0
  232. package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.js.map +1 -0
  233. package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.d.ts +7 -1
  234. package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.js +98 -3
  235. package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.js.map +1 -1
  236. package/dist/plugins/devices-third-party/controllers/third-party-inputs.controller.d.ts +17 -0
  237. package/dist/plugins/devices-third-party/controllers/third-party-inputs.controller.js +205 -0
  238. package/dist/plugins/devices-third-party/controllers/third-party-inputs.controller.js.map +1 -0
  239. package/dist/plugins/devices-third-party/devices-third-party.openapi.d.ts +1 -1
  240. package/dist/plugins/devices-third-party/devices-third-party.plugin.js +2 -1
  241. package/dist/plugins/devices-third-party/devices-third-party.plugin.js.map +1 -1
  242. package/dist/plugins/devices-third-party/dto/report-input-occurrence-response.dto.d.ts +5 -0
  243. package/dist/plugins/devices-third-party/dto/report-input-occurrence-response.dto.js +50 -0
  244. package/dist/plugins/devices-third-party/dto/report-input-occurrence-response.dto.js.map +1 -0
  245. package/dist/plugins/devices-third-party/dto/report-input-occurrence.dto.d.ts +8 -0
  246. package/dist/plugins/devices-third-party/dto/report-input-occurrence.dto.js +81 -0
  247. package/dist/plugins/devices-third-party/dto/report-input-occurrence.dto.js.map +1 -0
  248. package/dist/plugins/devices-third-party/platforms/third-party-device.platform.js +19 -4
  249. package/dist/plugins/devices-third-party/platforms/third-party-device.platform.js.map +1 -1
  250. package/dist/plugins/devices-virtual/listeners/virtual-projection.listener.d.ts +2 -0
  251. package/dist/plugins/devices-virtual/listeners/virtual-projection.listener.js +57 -0
  252. package/dist/plugins/devices-virtual/listeners/virtual-projection.listener.js.map +1 -1
  253. package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.d.ts +3 -0
  254. package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.js +41 -5
  255. package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.js.map +1 -1
  256. package/dist/plugins/devices-zigbee2mqtt/interfaces/zigbee2mqtt.interface.d.ts +7 -1
  257. package/dist/plugins/devices-zigbee2mqtt/mappings/config-driven.converter.js +16 -15
  258. package/dist/plugins/devices-zigbee2mqtt/mappings/config-driven.converter.js.map +1 -1
  259. package/dist/plugins/devices-zigbee2mqtt/mappings/definitions/remotes.yaml +505 -74
  260. package/dist/plugins/devices-zigbee2mqtt/mappings/schema/mapping-schema.json +3 -3
  261. package/dist/plugins/devices-zigbee2mqtt/mappings/transformers/transformer.types.d.ts +1 -1
  262. package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.d.ts +8 -2
  263. package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.js +6 -5
  264. package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.js.map +1 -1
  265. package/dist/plugins/devices-zigbee2mqtt/services/device-adoption.service.js +18 -11
  266. package/dist/plugins/devices-zigbee2mqtt/services/device-adoption.service.js.map +1 -1
  267. package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.d.ts +9 -3
  268. package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.js +166 -3
  269. package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.js.map +1 -1
  270. package/dist/plugins/devices-zigbee2mqtt/services/mqtt-client-adapter.service.js +5 -2
  271. package/dist/plugins/devices-zigbee2mqtt/services/mqtt-client-adapter.service.js.map +1 -1
  272. package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.d.ts +1 -0
  273. package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.js +44 -4
  274. package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.js.map +1 -1
  275. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.d.ts +17 -0
  276. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.js +147 -0
  277. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.js.map +1 -0
  278. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.d.ts +15 -0
  279. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.js +98 -0
  280. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.js.map +1 -0
  281. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.d.ts +9 -0
  282. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.js +94 -0
  283. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.js.map +1 -0
  284. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.d.ts +9 -0
  285. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.js +92 -0
  286. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.js.map +1 -0
  287. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.d.ts +7 -0
  288. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.js +48 -0
  289. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.js.map +1 -0
  290. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.d.ts +42 -0
  291. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.js +352 -0
  292. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.js.map +1 -0
  293. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.d.ts +24 -0
  294. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.js +27 -0
  295. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.js.map +1 -0
  296. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.d.ts +8 -0
  297. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.js +19 -0
  298. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.js.map +1 -0
  299. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.d.ts +4 -0
  300. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.js +20 -0
  301. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.js.map +1 -0
  302. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.d.ts +21 -0
  303. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.js +135 -0
  304. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.js.map +1 -0
  305. package/dist/plugins/remote-access-cloudflare-tunnel/scripts/cloudflared-setup.sh +185 -0
  306. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.d.ts +82 -0
  307. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.js +507 -0
  308. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.js.map +1 -0
  309. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.d.ts +10 -0
  310. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.js +37 -0
  311. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.js.map +1 -0
  312. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.d.ts +38 -0
  313. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.js +147 -0
  314. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.js.map +1 -0
  315. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.d.ts +15 -0
  316. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.js +67 -0
  317. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.js.map +1 -0
  318. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.d.ts +8 -0
  319. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.js +46 -0
  320. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.js.map +1 -0
  321. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.d.ts +27 -0
  322. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.js +139 -0
  323. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.js.map +1 -0
  324. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.d.ts +1 -0
  325. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.js +26 -10
  326. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.js.map +1 -1
  327. package/dist/plugins/remote-access-tailscale/controllers/status.controller.d.ts +6 -1
  328. package/dist/plugins/remote-access-tailscale/controllers/status.controller.js +28 -3
  329. package/dist/plugins/remote-access-tailscale/controllers/status.controller.js.map +1 -1
  330. package/dist/plugins/remote-access-tailscale/models/status.model.d.ts +19 -0
  331. package/dist/plugins/remote-access-tailscale/models/status.model.js +158 -1
  332. package/dist/plugins/remote-access-tailscale/models/status.model.js.map +1 -1
  333. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.d.ts +3 -0
  334. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.js +4 -1
  335. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.js.map +1 -1
  336. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.d.ts +13 -0
  337. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.js +27 -0
  338. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.js.map +1 -0
  339. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.d.ts +2 -2
  340. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.js +2 -0
  341. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.js.map +1 -1
  342. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.plugin.js +1 -1
  343. package/dist/plugins/remote-access-tailscale/scripts/tailscale-setup.sh +61 -0
  344. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.d.ts +9 -0
  345. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.js +12 -0
  346. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.js.map +1 -1
  347. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.d.ts +1 -0
  348. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.js +27 -2
  349. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.js.map +1 -1
  350. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.d.ts +31 -1
  351. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.js +316 -30
  352. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.js.map +1 -1
  353. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.d.ts +8 -3
  354. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.js +39 -12
  355. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.js.map +1 -1
  356. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.d.ts +14 -5
  357. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.js +51 -16
  358. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.js.map +1 -1
  359. package/dist/plugins/scenes-local/platforms/local-scene.platform.d.ts +3 -1
  360. package/dist/plugins/scenes-local/platforms/local-scene.platform.js +12 -7
  361. package/dist/plugins/scenes-local/platforms/local-scene.platform.js.map +1 -1
  362. package/dist/plugins/simulator/controllers/simulator.controller.d.ts +8 -2
  363. package/dist/plugins/simulator/controllers/simulator.controller.js +102 -2
  364. package/dist/plugins/simulator/controllers/simulator.controller.js.map +1 -1
  365. package/dist/plugins/simulator/dto/simulate-occurrence.dto.d.ts +12 -0
  366. package/dist/plugins/simulator/dto/simulate-occurrence.dto.js +122 -0
  367. package/dist/plugins/simulator/dto/simulate-occurrence.dto.js.map +1 -0
  368. package/dist/plugins/simulator/models/simulator-response.model.d.ts +12 -0
  369. package/dist/plugins/simulator/models/simulator-response.model.js +84 -1
  370. package/dist/plugins/simulator/models/simulator-response.model.js.map +1 -1
  371. package/dist/plugins/simulator/scenarios/definitions/small-apartment.yaml +78 -0
  372. package/dist/plugins/simulator/services/scenario-executor.service.js +3 -1
  373. package/dist/plugins/simulator/services/scenario-executor.service.js.map +1 -1
  374. package/dist/plugins/simulator/services/simulation.service.js +10 -1
  375. package/dist/plugins/simulator/services/simulation.service.js.map +1 -1
  376. package/dist/plugins/simulator/simulator.openapi.d.ts +3 -2
  377. package/dist/plugins/simulator/simulator.openapi.js +5 -0
  378. package/dist/plugins/simulator/simulator.openapi.js.map +1 -1
  379. package/dist/plugins/simulator/simulators/device-simulator.interface.d.ts +2 -0
  380. package/dist/plugins/simulator/simulators/device-simulator.interface.js +83 -0
  381. package/dist/plugins/simulator/simulators/device-simulator.interface.js.map +1 -1
  382. package/dist/plugins/simulator/simulators/index.d.ts +1 -0
  383. package/dist/plugins/simulator/simulators/index.js +1 -0
  384. package/dist/plugins/simulator/simulators/index.js.map +1 -1
  385. package/dist/plugins/simulator/simulators/input-controller.simulator.d.ts +10 -0
  386. package/dist/plugins/simulator/simulators/input-controller.simulator.js +57 -0
  387. package/dist/plugins/simulator/simulators/input-controller.simulator.js.map +1 -0
  388. package/dist/plugins/simulator/simulators/lighting.simulator.js +1 -0
  389. package/dist/plugins/simulator/simulators/lighting.simulator.js.map +1 -1
  390. package/dist/plugins/spaces-home-control/services/climate-intent.service.d.ts +3 -1
  391. package/dist/plugins/spaces-home-control/services/climate-intent.service.js +6 -3
  392. package/dist/plugins/spaces-home-control/services/climate-intent.service.js.map +1 -1
  393. package/dist/plugins/spaces-home-control/services/covers-intent.service.d.ts +3 -1
  394. package/dist/plugins/spaces-home-control/services/covers-intent.service.js +6 -3
  395. package/dist/plugins/spaces-home-control/services/covers-intent.service.js.map +1 -1
  396. package/dist/plugins/spaces-home-control/services/lighting-intent.service.d.ts +3 -1
  397. package/dist/plugins/spaces-home-control/services/lighting-intent.service.js +7 -4
  398. package/dist/plugins/spaces-home-control/services/lighting-intent.service.js.map +1 -1
  399. package/dist/plugins/spaces-home-control/services/space-media-activity.service.d.ts +3 -1
  400. package/dist/plugins/spaces-home-control/services/space-media-activity.service.js +11 -5
  401. package/dist/plugins/spaces-home-control/services/space-media-activity.service.js.map +1 -1
  402. package/dist/plugins/spaces-home-control/services/space-undo-history.service.d.ts +3 -1
  403. package/dist/plugins/spaces-home-control/services/space-undo-history.service.js +8 -5
  404. package/dist/plugins/spaces-home-control/services/space-undo-history.service.js.map +1 -1
  405. package/dist/spec/channels.d.ts +51 -1
  406. package/dist/spec/channels.js +64 -1
  407. package/dist/spec/channels.js.map +1 -1
  408. package/dist/spec/devices.d.ts +155 -2
  409. package/dist/spec/devices.js +161 -2
  410. package/dist/spec/devices.js.map +1 -1
  411. package/dist/tsconfig.build.tsbuildinfo +1 -1
  412. package/package.json +3 -3
@@ -8,16 +8,20 @@ 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
  var DelegatesManagerService_1;
12
15
  Object.defineProperty(exports, "__esModule", { value: true });
13
16
  exports.DelegatesManagerService = void 0;
14
- const class_transformer_1 = require("class-transformer");
15
17
  const common_1 = require("@nestjs/common");
16
18
  const logger_1 = require("../../../common/logger");
17
19
  const transform_utils_1 = require("../../../common/utils/transform.utils");
18
20
  const devices_constants_1 = require("../../../modules/devices/devices.constants");
21
+ const channel_input_occurrences_service_1 = require("../../../modules/devices/services/channel-input-occurrences.service");
19
22
  const channels_properties_service_1 = require("../../../modules/devices/services/channels.properties.service");
20
23
  const channels_service_1 = require("../../../modules/devices/services/channels.service");
24
+ const command_latency_trace_collector_service_1 = require("../../../modules/devices/services/command-latency-trace-collector.service");
21
25
  const device_connectivity_service_1 = require("../../../modules/devices/services/device-connectivity.service");
22
26
  const devices_service_1 = require("../../../modules/devices/services/devices.service");
23
27
  const devices_shelly_ng_constants_1 = require("../devices-shelly-ng.constants");
@@ -27,10 +31,20 @@ const mappings_1 = require("../mappings");
27
31
  const transformers_1 = require("../mappings/transformers/transformers");
28
32
  const device_address_service_1 = require("../services/device-address.service");
29
33
  const device_manager_service_1 = require("../services/device-manager.service");
34
+ const poll_placement_diagnostics_service_1 = require("../services/poll-placement-diagnostics.service");
30
35
  const transform_utils_2 = require("../utils/transform.utils");
31
36
  const shelly_device_delegate_1 = require("./shelly-device.delegate");
37
+ const SHELLY_TO_PANEL_EVENT_MAP = {
38
+ single_push: 'press',
39
+ double_push: 'double_press',
40
+ triple_push: 'triple_press',
41
+ triple_press: 'triple_press',
42
+ long_push: 'long_press',
43
+ btn_down: 'down',
44
+ btn_up: 'up',
45
+ };
32
46
  let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManagerService {
33
- constructor(devicesService, channelsService, channelsPropertiesService, deviceConnectivityService, deviceManagerService, deviceAddressService, propertyMappingStorage, transformerRegistry) {
47
+ constructor(devicesService, channelsService, channelsPropertiesService, deviceConnectivityService, deviceManagerService, deviceAddressService, propertyMappingStorage, transformerRegistry, commandLatencyTraceCollector = new command_latency_trace_collector_service_1.CommandLatencyTraceCollectorService(), pollPlacementDiagnostics = new poll_placement_diagnostics_service_1.PollPlacementDiagnosticsService(), channelInputOccurrencesService) {
34
48
  this.devicesService = devicesService;
35
49
  this.channelsService = channelsService;
36
50
  this.channelsPropertiesService = channelsPropertiesService;
@@ -39,14 +53,28 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
39
53
  this.deviceAddressService = deviceAddressService;
40
54
  this.propertyMappingStorage = propertyMappingStorage;
41
55
  this.transformerRegistry = transformerRegistry;
56
+ this.commandLatencyTraceCollector = commandLatencyTraceCollector;
57
+ this.pollPlacementDiagnostics = pollPlacementDiagnostics;
58
+ this.channelInputOccurrencesService = channelInputOccurrencesService;
42
59
  this.logger = (0, logger_1.createExtensionLogger)(devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_PLUGIN_NAME, 'DelegatesManagerService');
43
60
  this.delegates = new Map();
44
61
  this.delegateValueHandlers = new Map();
45
62
  this.delegateConnectionHandlers = new Map();
63
+ this.delegateEventHandlers = new Map();
64
+ this.delegateEventQueues = new Map();
65
+ this.delegateEventGenerations = new Map();
46
66
  this.changeHandlers = new Map();
47
67
  this.setChannelsHandlers = new Map();
48
68
  this.setPropertiesHandlers = new Map();
49
69
  this.pendingWrites = new Map();
70
+ this.delegatePendingWrites = new Map();
71
+ this.delegateActiveWrites = new Map();
72
+ this.pendingPollWrites = new Map();
73
+ this.activePollWrites = new Map();
74
+ this.activePollDrainPromises = new Map();
75
+ this.delegatePollDeviceIds = new Map();
76
+ this.delegatePollGenerations = new Map();
77
+ this.currentValueUpdateContext = null;
50
78
  this.propertiesMap = new Map();
51
79
  this.delegateDeviceIds = new Map();
52
80
  this.delegateToIdentifier = new Map();
@@ -67,7 +95,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
67
95
  async performInsert(shelly, force = false) {
68
96
  if (this.delegates.has(shelly.id)) {
69
97
  if (force) {
70
- this.performRemove(shelly.id);
98
+ await this.performRemove(shelly.id);
71
99
  }
72
100
  else {
73
101
  return this.delegates.get(shelly.id);
@@ -75,6 +103,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
75
103
  }
76
104
  const generation = (this.insertGeneration.get(shelly.id) ?? 0) + 1;
77
105
  this.insertGeneration.set(shelly.id, generation);
106
+ this.delegatePollGenerations.set(shelly.id, (this.delegatePollGenerations.get(shelly.id) ?? 0) + 1);
78
107
  const delegate = new shelly_device_delegate_1.ShellyDeviceDelegate(shelly);
79
108
  this.delegates.set(shelly.id, delegate);
80
109
  const wifiIp = shelly.wifi?.sta_ip ?? null;
@@ -120,6 +149,12 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
120
149
  let device = resolvedDevice;
121
150
  this.delegateDeviceIds.set(delegate.id, device.id);
122
151
  this.delegateToIdentifier.set(delegate.id, device.identifier);
152
+ this.pollPlacementDiagnostics.observeDelegate({
153
+ delegateId: delegate.id,
154
+ sourceDeviceId: device.id,
155
+ connected: delegate.connected,
156
+ generation,
157
+ });
123
158
  const delegateSet = this.identifierToDelegates.get(device.identifier) ?? new Set();
124
159
  delegateSet.add(delegate.id);
125
160
  this.identifierToDelegates.set(device.identifier, delegateSet);
@@ -808,12 +843,80 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
808
843
  }
809
844
  if (this.insertGeneration.get(shelly.id) !== generation)
810
845
  return delegate;
811
- const valueHandler = (compKey, attr, val) => {
846
+ for (const comp of delegate.inputs.values()) {
847
+ const channel = await this.channelsService.findOneBy('identifier', `input:${comp.id}`, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
848
+ if (channel === null) {
849
+ continue;
850
+ }
851
+ if (channel.category === devices_constants_1.ChannelCategory.BUTTON) {
852
+ const detectedProp = await this.channelsPropertiesService.findOneBy('category', devices_constants_1.PropertyCategory.DETECTED, channel.id);
853
+ if (detectedProp) {
854
+ await this.setDefaultPropertyValue(device.id, detectedProp, Boolean(comp.state));
855
+ this.changeHandlers.set(`${delegate.id}|${comp.key}|state`, (val) => {
856
+ if (typeof val === 'boolean') {
857
+ this.handleChange(detectedProp, val, false).catch((err) => {
858
+ this.logger.error(`Failed to update detected for ${detectedProp.id}: ${err.message}`);
859
+ });
860
+ }
861
+ });
862
+ }
863
+ }
864
+ else if (channel.category === devices_constants_1.ChannelCategory.BINARY_INPUT) {
865
+ const stateProp = await this.channelsPropertiesService.findOneBy('category', devices_constants_1.PropertyCategory.STATE, channel.id);
866
+ if (stateProp) {
867
+ await this.setDefaultPropertyValue(device.id, stateProp, Boolean(comp.state));
868
+ this.changeHandlers.set(`${delegate.id}|${comp.key}|state`, (val) => {
869
+ if (typeof val === 'boolean') {
870
+ this.handleChange(stateProp, val, false).catch((err) => {
871
+ this.logger.error(`Failed to update state for ${stateProp.id}: ${err.message}`);
872
+ });
873
+ }
874
+ });
875
+ }
876
+ }
877
+ else if (channel.category === devices_constants_1.ChannelCategory.ANALOG_INPUT) {
878
+ const valueProp = await this.channelsPropertiesService.findOneBy('category', devices_constants_1.PropertyCategory.VALUE, channel.id);
879
+ if (valueProp) {
880
+ const hasExtendedPercent = typeof comp.xpercent === 'number';
881
+ const hasExtendedCount = typeof comp.counts?.xtotal === 'number';
882
+ let initialVal;
883
+ if (comp.counts !== undefined) {
884
+ initialVal = hasExtendedCount ? comp.counts.xtotal : (comp.counts.total ?? 0);
885
+ }
886
+ else {
887
+ initialVal = hasExtendedPercent ? comp.xpercent : (comp.percent ?? 0);
888
+ }
889
+ await this.setDefaultPropertyValue(device.id, valueProp, initialVal);
890
+ const percentAttr = hasExtendedPercent ? 'xpercent' : 'percent';
891
+ this.changeHandlers.set(`${delegate.id}|${comp.key}|${percentAttr}`, (val) => {
892
+ const n = (0, transform_utils_1.coerceNumberSafe)(val);
893
+ if (n !== null) {
894
+ this.handleChange(valueProp, n, false).catch((err) => {
895
+ this.logger.error(`Failed to update value for ${valueProp.id}: ${err.message}`);
896
+ });
897
+ }
898
+ });
899
+ const countAttr = hasExtendedCount ? 'counts.xtotal' : 'counts.total';
900
+ this.changeHandlers.set(`${delegate.id}|${comp.key}|${countAttr}`, (val) => {
901
+ const n = (0, transform_utils_1.coerceNumberSafe)(val);
902
+ if (n !== null) {
903
+ this.handleChange(valueProp, n, false).catch((err) => {
904
+ this.logger.error(`Failed to update counts for ${valueProp.id}: ${err.message}`);
905
+ });
906
+ }
907
+ });
908
+ }
909
+ }
910
+ }
911
+ if (this.insertGeneration.get(shelly.id) !== generation)
912
+ return delegate;
913
+ const valueHandler = (compKey, attr, val, origin = 'notify') => {
812
914
  const handler = this.changeHandlers.get(`${delegate.id}|${compKey}|${attr}`);
813
915
  if (!handler) {
814
916
  return;
815
917
  }
816
918
  try {
919
+ this.currentValueUpdateContext = { delegateId: delegate.id, deviceId: device.id, origin };
817
920
  handler(val);
818
921
  }
819
922
  catch (error) {
@@ -824,6 +927,9 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
824
927
  stack: err.stack,
825
928
  });
826
929
  }
930
+ finally {
931
+ this.currentValueUpdateContext = null;
932
+ }
827
933
  };
828
934
  delegate.on('value', valueHandler);
829
935
  this.delegateValueHandlers.set(delegate.id, valueHandler);
@@ -834,6 +940,12 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
834
940
  if (wasConnected)
835
941
  return;
836
942
  this.delegateConnectedState.set(delegate.id, true);
943
+ this.pollPlacementDiagnostics.observeDelegate({
944
+ delegateId: delegate.id,
945
+ sourceDeviceId: device.id,
946
+ connected: true,
947
+ generation,
948
+ });
837
949
  const pendingTimer = this.disconnectTimers.get(deviceDbId);
838
950
  if (pendingTimer) {
839
951
  clearTimeout(pendingTimer);
@@ -855,6 +967,12 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
855
967
  if (!wasConnected)
856
968
  return;
857
969
  this.delegateConnectedState.set(delegate.id, false);
970
+ this.pollPlacementDiagnostics.observeDelegate({
971
+ delegateId: delegate.id,
972
+ sourceDeviceId: device.id,
973
+ connected: false,
974
+ generation,
975
+ });
858
976
  const count = Math.max(0, (this.connectedDelegatesPerDevice.get(deviceDbId) ?? 1) - 1);
859
977
  this.connectedDelegatesPerDevice.set(deviceDbId, count);
860
978
  if (count === 0) {
@@ -922,6 +1040,34 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
922
1040
  };
923
1041
  delegate.on('connected', connectionHandler);
924
1042
  this.delegateConnectionHandlers.set(delegate.id, connectionHandler);
1043
+ const eventGeneration = (this.delegateEventGenerations.get(delegate.id) ?? 0) + 1;
1044
+ this.delegateEventGenerations.set(delegate.id, eventGeneration);
1045
+ const eventHandler = (params) => {
1046
+ const previousPromise = this.delegateEventQueues.get(delegate.id) ?? Promise.resolve();
1047
+ const nextPromise = previousPromise
1048
+ .then(async () => {
1049
+ if (this.delegateEventGenerations.get(delegate.id) !== eventGeneration) {
1050
+ return;
1051
+ }
1052
+ await this.handleDeviceEvent(delegate, device, params, eventGeneration);
1053
+ })
1054
+ .catch((error) => {
1055
+ const err = error;
1056
+ this.logger.error(`Shelly event error for device=${device.id}`, {
1057
+ resource: device.id,
1058
+ message: err.message,
1059
+ stack: err.stack,
1060
+ });
1061
+ })
1062
+ .finally(() => {
1063
+ if (this.delegateEventQueues.get(delegate.id) === nextPromise) {
1064
+ this.delegateEventQueues.delete(delegate.id);
1065
+ }
1066
+ });
1067
+ this.delegateEventQueues.set(delegate.id, nextPromise);
1068
+ };
1069
+ delegate.on('event', eventHandler);
1070
+ this.delegateEventHandlers.set(delegate.id, eventHandler);
925
1071
  if (delegate.connected) {
926
1072
  connectionHandler(true);
927
1073
  }
@@ -929,17 +1075,45 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
929
1075
  return delegate;
930
1076
  }
931
1077
  remove(deviceId) {
932
- return this.withDeviceLock(deviceId, () => {
933
- this.performRemove(deviceId);
934
- return Promise.resolve();
935
- });
1078
+ return this.withDeviceLock(deviceId, () => this.performRemove(deviceId));
1079
+ }
1080
+ async teardownDelegateEvents(delegate) {
1081
+ const eventHandler = this.delegateEventHandlers.get(delegate.id);
1082
+ if (eventHandler) {
1083
+ delegate.off('event', eventHandler);
1084
+ }
1085
+ const pendingQueue = this.delegateEventQueues.get(delegate.id);
1086
+ this.delegateEventHandlers.delete(delegate.id);
1087
+ this.delegateEventQueues.delete(delegate.id);
1088
+ this.delegateEventGenerations.set(delegate.id, (this.delegateEventGenerations.get(delegate.id) ?? 0) + 1);
1089
+ if (pendingQueue !== undefined) {
1090
+ try {
1091
+ await pendingQueue;
1092
+ }
1093
+ catch (err) {
1094
+ this.logger.error(`Error while awaiting event queue teardown for delegate=${delegate.id}`, {
1095
+ message: err.message,
1096
+ stack: err.stack,
1097
+ });
1098
+ }
1099
+ }
936
1100
  }
937
- performRemove(deviceId) {
1101
+ async performRemove(deviceId) {
938
1102
  const delegate = this.delegates.get(deviceId);
939
1103
  if (!delegate) {
940
1104
  return;
941
1105
  }
942
1106
  const valueHandler = this.delegateValueHandlers.get(delegate.id);
1107
+ if (valueHandler) {
1108
+ delegate.off('value', valueHandler);
1109
+ this.delegateValueHandlers.delete(delegate.id);
1110
+ }
1111
+ this.delegatePollGenerations.set(deviceId, (this.delegatePollGenerations.get(deviceId) ?? 0) + 1);
1112
+ this.cancelPollWritesForDelegate(deviceId);
1113
+ this.cancelPendingWritesForDelegate(deviceId);
1114
+ await this.teardownDelegateEvents(delegate);
1115
+ await this.awaitActiveWritesForDelegate(deviceId);
1116
+ await this.awaitActivePollDrainsForDelegate(deviceId);
943
1117
  const connectionHandler = this.delegateConnectionHandlers.get(delegate.id);
944
1118
  if (connectionHandler) {
945
1119
  connectionHandler(null);
@@ -962,14 +1136,10 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
962
1136
  });
963
1137
  }
964
1138
  }
965
- if (valueHandler) {
966
- delegate.off('value', valueHandler);
967
- }
968
1139
  if (connectionHandler) {
969
1140
  delegate.off('connected', connectionHandler);
1141
+ this.delegateConnectionHandlers.delete(delegate.id);
970
1142
  }
971
- this.delegateValueHandlers.delete(delegate.id);
972
- this.delegateConnectionHandlers.delete(delegate.id);
973
1143
  for (const key of Array.from(this.changeHandlers.keys())) {
974
1144
  if (key.startsWith(`${deviceId}|`)) {
975
1145
  this.changeHandlers.delete(key);
@@ -1009,7 +1179,12 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1009
1179
  }
1010
1180
  this.delegateDeviceIds.delete(deviceId);
1011
1181
  this.delegateToIdentifier.delete(deviceId);
1182
+ this.pollPlacementDiagnostics.removeDelegate(deviceId);
1012
1183
  this.insertGeneration.delete(deviceId);
1184
+ this.delegatePendingWrites.delete(deviceId);
1185
+ this.delegateActiveWrites.delete(deviceId);
1186
+ this.delegatePollGenerations.delete(deviceId);
1187
+ this.delegatePollDeviceIds.delete(deviceId);
1013
1188
  this.delegates.delete(deviceId);
1014
1189
  this.logger.log(`Detached Shelly device=${deviceId}`, { resource: deviceId });
1015
1190
  }
@@ -1074,12 +1249,149 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1074
1249
  return value;
1075
1250
  }
1076
1251
  }
1077
- async handleChange(property, value, immediately = true) {
1252
+ async handleDeviceEvent(delegate, device, params, generation) {
1253
+ if (this.delegateEventGenerations.get(delegate.id) !== generation) {
1254
+ return;
1255
+ }
1256
+ if (typeof params !== 'object' || params === null) {
1257
+ return;
1258
+ }
1259
+ const eventPayload = params;
1260
+ const rawEvents = Array.isArray(eventPayload.events) ? eventPayload.events : [eventPayload];
1261
+ for (const rawItem of rawEvents) {
1262
+ if (this.delegateEventGenerations.get(delegate.id) !== generation) {
1263
+ return;
1264
+ }
1265
+ if (typeof rawItem !== 'object' || rawItem === null) {
1266
+ continue;
1267
+ }
1268
+ const item = rawItem;
1269
+ const rawEvent = typeof item.event === 'string' ? item.event : undefined;
1270
+ if (!rawEvent) {
1271
+ continue;
1272
+ }
1273
+ const mappedEvent = SHELLY_TO_PANEL_EVENT_MAP[rawEvent];
1274
+ if (!mappedEvent) {
1275
+ this.logger.debug(`Unknown Shelly event=${rawEvent} from device=${device.id}`);
1276
+ continue;
1277
+ }
1278
+ let channelIdentifier;
1279
+ if (typeof item.component === 'string' && item.component.length > 0) {
1280
+ channelIdentifier = item.component;
1281
+ }
1282
+ else if (typeof item.id === 'number' || typeof item.id === 'string') {
1283
+ channelIdentifier = `input:${item.id}`;
1284
+ }
1285
+ else {
1286
+ continue;
1287
+ }
1288
+ const channel = await this.channelsService.findOneBy('identifier', channelIdentifier, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
1289
+ if (this.delegateEventGenerations.get(delegate.id) !== generation) {
1290
+ return;
1291
+ }
1292
+ if (!channel) {
1293
+ this.logger.debug(`No channel found for ${channelIdentifier} on device=${device.id}`);
1294
+ continue;
1295
+ }
1296
+ if (rawEvent === 'btn_down' || rawEvent === 'btn_up') {
1297
+ try {
1298
+ const detectedProp = await this.channelsPropertiesService.findOneBy('category', devices_constants_1.PropertyCategory.DETECTED, channel.id);
1299
+ if (this.delegateEventGenerations.get(delegate.id) !== generation) {
1300
+ return;
1301
+ }
1302
+ if (detectedProp) {
1303
+ await this.handleChange(detectedProp, rawEvent === 'btn_down', true);
1304
+ }
1305
+ }
1306
+ catch (err) {
1307
+ this.logger.error(`Failed to update DETECTED property for channel=${channel.id} on device=${device.id}: ${err.message}`);
1308
+ }
1309
+ }
1310
+ if (this.delegateEventGenerations.get(delegate.id) !== generation) {
1311
+ return;
1312
+ }
1313
+ const eventProp = await this.channelsPropertiesService.findOneBy('category', devices_constants_1.PropertyCategory.EVENT, channel.id);
1314
+ if (this.delegateEventGenerations.get(delegate.id) !== generation) {
1315
+ return;
1316
+ }
1317
+ if (!eventProp) {
1318
+ this.logger.debug(`No EVENT property on channel=${channel.id} for device=${device.id}`);
1319
+ continue;
1320
+ }
1321
+ if (this.channelInputOccurrencesService) {
1322
+ const ts = typeof item.ts === 'number' ? item.ts : typeof eventPayload.ts === 'number' ? eventPayload.ts : undefined;
1323
+ const timestamp = ts !== undefined ? new Date(ts < 1e11 ? Math.round(ts * 1000) : Math.round(ts)) : new Date();
1324
+ const sourceOccurrenceId = `${channel.id}:${rawEvent}:${ts ?? timestamp.getTime()}`;
1325
+ try {
1326
+ if (this.delegateEventGenerations.get(delegate.id) !== generation) {
1327
+ return;
1328
+ }
1329
+ await this.channelInputOccurrencesService.publishOccurrence({
1330
+ deviceId: device.id,
1331
+ channelId: channel.id,
1332
+ propertyId: eventProp.id,
1333
+ event: mappedEvent,
1334
+ nativeEventType: rawEvent,
1335
+ sourceTimestamp: timestamp.toISOString(),
1336
+ sourceOccurrenceId,
1337
+ });
1338
+ }
1339
+ catch (err) {
1340
+ this.logger.error(`Failed to publish occurrence for channel=${channel.id} on device=${device.id}: ${err.message}`);
1341
+ }
1342
+ }
1343
+ }
1344
+ }
1345
+ async handleChange(property, value, immediately = true, delegateId) {
1346
+ const context = this.currentValueUpdateContext;
1347
+ const effectiveDelegateId = delegateId ?? context?.delegateId;
1348
+ if (context !== null) {
1349
+ this.commandLatencyTraceCollector.recordProviderReceipt(property.id, value, context.origin, {
1350
+ delegateId: context.delegateId,
1351
+ deviceId: context.deviceId,
1352
+ });
1353
+ }
1354
+ if (context?.origin === 'poll') {
1355
+ this.commandLatencyTraceCollector.recordPollActivity(property.id, 'poll-coalescer-admission', {
1356
+ delegateId: context.delegateId,
1357
+ deviceId: context.deviceId,
1358
+ });
1359
+ this.schedulePollWrite(context, property, value);
1360
+ return;
1361
+ }
1078
1362
  if (immediately) {
1079
- await this.writeValueToProperty(property, value);
1363
+ this.cancelScheduledWrite(property.id);
1364
+ this.cancelPollWrite(property.id);
1365
+ if (effectiveDelegateId) {
1366
+ let active = this.delegateActiveWrites.get(effectiveDelegateId);
1367
+ if (!active) {
1368
+ active = new Set();
1369
+ this.delegateActiveWrites.set(effectiveDelegateId, active);
1370
+ }
1371
+ const writePromise = (async () => {
1372
+ await this.writeValueToProperty(property, value);
1373
+ })();
1374
+ void writePromise.catch(() => { });
1375
+ active.add(writePromise);
1376
+ try {
1377
+ await writePromise;
1378
+ }
1379
+ finally {
1380
+ const currentActive = this.delegateActiveWrites.get(effectiveDelegateId);
1381
+ if (currentActive) {
1382
+ currentActive.delete(writePromise);
1383
+ if (currentActive.size === 0) {
1384
+ this.delegateActiveWrites.delete(effectiveDelegateId);
1385
+ }
1386
+ }
1387
+ }
1388
+ }
1389
+ else {
1390
+ await this.writeValueToProperty(property, value);
1391
+ }
1080
1392
  }
1081
1393
  else {
1082
- this.scheduleWrite(property, value);
1394
+ this.scheduleWrite(property, value, effectiveDelegateId);
1083
1395
  }
1084
1396
  }
1085
1397
  async setDefaultPropertyValue(deviceId, property, value) {
@@ -1217,10 +1529,21 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1217
1529
  });
1218
1530
  });
1219
1531
  }
1220
- scheduleWrite(property, value) {
1532
+ scheduleWrite(property, value, delegateId) {
1221
1533
  const existing = this.pendingWrites.get(property.id);
1222
1534
  if (existing) {
1223
1535
  clearTimeout(existing);
1536
+ for (const set of this.delegatePendingWrites.values()) {
1537
+ set.delete(property.id);
1538
+ }
1539
+ }
1540
+ if (delegateId) {
1541
+ let set = this.delegatePendingWrites.get(delegateId);
1542
+ if (!set) {
1543
+ set = new Set();
1544
+ this.delegatePendingWrites.set(delegateId, set);
1545
+ }
1546
+ set.add(property.id);
1224
1547
  }
1225
1548
  const t = setTimeout(() => {
1226
1549
  const current = this.pendingWrites.get(property.id);
@@ -1228,15 +1551,301 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1228
1551
  clearTimeout(current);
1229
1552
  this.pendingWrites.delete(property.id);
1230
1553
  }
1231
- this.writeValueToProperty(property, value).catch((err) => {
1232
- this.logger.error(`Failed to process scheduled write of value=${(0, transform_utils_1.safeToString)(value)} to property=${property.id}`, { message: err.message, stack: err.stack });
1233
- });
1554
+ if (delegateId) {
1555
+ const set = this.delegatePendingWrites.get(delegateId);
1556
+ if (set) {
1557
+ set.delete(property.id);
1558
+ if (set.size === 0) {
1559
+ this.delegatePendingWrites.delete(delegateId);
1560
+ }
1561
+ }
1562
+ if (!this.delegates.has(delegateId)) {
1563
+ return;
1564
+ }
1565
+ }
1566
+ const writePromise = (async () => {
1567
+ try {
1568
+ await this.writeValueToProperty(property, value);
1569
+ }
1570
+ catch (err) {
1571
+ this.logger.error(`Failed to process scheduled write of value=${(0, transform_utils_1.safeToString)(value)} to property=${property.id}`, { message: err.message, stack: err.stack });
1572
+ }
1573
+ })();
1574
+ if (delegateId) {
1575
+ let active = this.delegateActiveWrites.get(delegateId);
1576
+ if (!active) {
1577
+ active = new Set();
1578
+ this.delegateActiveWrites.set(delegateId, active);
1579
+ }
1580
+ active.add(writePromise);
1581
+ void writePromise.finally(() => {
1582
+ const currentActive = this.delegateActiveWrites.get(delegateId);
1583
+ if (currentActive) {
1584
+ currentActive.delete(writePromise);
1585
+ if (currentActive.size === 0) {
1586
+ this.delegateActiveWrites.delete(delegateId);
1587
+ }
1588
+ }
1589
+ });
1590
+ }
1234
1591
  }, 250);
1235
1592
  this.pendingWrites.set(property.id, t);
1236
1593
  }
1594
+ schedulePollWrite(context, property, value) {
1595
+ let tracked = this.delegatePollDeviceIds.get(context.delegateId);
1596
+ if (!tracked) {
1597
+ tracked = new Set();
1598
+ this.delegatePollDeviceIds.set(context.delegateId, tracked);
1599
+ }
1600
+ tracked.add(context.deviceId);
1601
+ let bucket = this.pendingPollWrites.get(context.deviceId);
1602
+ if (!bucket) {
1603
+ const values = new Map();
1604
+ const timer = setTimeout(() => {
1605
+ void this.flushPollWrites(context.deviceId);
1606
+ }, 250);
1607
+ bucket = { timer, values };
1608
+ this.pendingPollWrites.set(context.deviceId, bucket);
1609
+ }
1610
+ bucket.values.set(property.id, {
1611
+ delegateId: context.delegateId,
1612
+ delegateGeneration: this.delegatePollGenerations.get(context.delegateId) ?? 0,
1613
+ property,
1614
+ value,
1615
+ });
1616
+ }
1617
+ async flushPollWrites(deviceId) {
1618
+ const bucket = this.pendingPollWrites.get(deviceId);
1619
+ if (!bucket) {
1620
+ return;
1621
+ }
1622
+ this.pendingPollWrites.delete(deviceId);
1623
+ clearTimeout(bucket.timer);
1624
+ let activeBuckets = this.activePollWrites.get(deviceId);
1625
+ if (activeBuckets === undefined) {
1626
+ activeBuckets = new Set();
1627
+ this.activePollWrites.set(deviceId, activeBuckets);
1628
+ }
1629
+ activeBuckets.add(bucket);
1630
+ const drainPromise = (async () => {
1631
+ try {
1632
+ for (const [propertyId, pending] of [...bucket.values.entries()]) {
1633
+ if (bucket.values.get(propertyId) !== pending) {
1634
+ continue;
1635
+ }
1636
+ if (!this.delegates.has(pending.delegateId) ||
1637
+ (this.delegatePollGenerations.get(pending.delegateId) ?? 0) !== pending.delegateGeneration) {
1638
+ continue;
1639
+ }
1640
+ try {
1641
+ this.commandLatencyTraceCollector.recordPollActivity(pending.property.id, 'poll-drain', {
1642
+ delegateId: pending.delegateId,
1643
+ deviceId,
1644
+ });
1645
+ await this.writeValueToProperty(pending.property, pending.value);
1646
+ }
1647
+ catch (error) {
1648
+ const err = error;
1649
+ this.logger.error(`Failed to process poll write of value=${(0, transform_utils_1.safeToString)(pending.value)} to property=${pending.property.id}`, { message: err.message, stack: err.stack });
1650
+ }
1651
+ }
1652
+ }
1653
+ finally {
1654
+ activeBuckets.delete(bucket);
1655
+ if (activeBuckets.size === 0 && this.activePollWrites.get(deviceId) === activeBuckets) {
1656
+ this.activePollWrites.delete(deviceId);
1657
+ }
1658
+ }
1659
+ })();
1660
+ void drainPromise.catch(() => { });
1661
+ let drains = this.activePollDrainPromises.get(deviceId);
1662
+ if (!drains) {
1663
+ drains = new Set();
1664
+ this.activePollDrainPromises.set(deviceId, drains);
1665
+ }
1666
+ drains.add(drainPromise);
1667
+ try {
1668
+ await drainPromise;
1669
+ }
1670
+ finally {
1671
+ const currentDrains = this.activePollDrainPromises.get(deviceId);
1672
+ if (currentDrains) {
1673
+ currentDrains.delete(drainPromise);
1674
+ if (currentDrains.size === 0) {
1675
+ this.activePollDrainPromises.delete(deviceId);
1676
+ }
1677
+ }
1678
+ }
1679
+ }
1680
+ cancelScheduledWrite(propertyId) {
1681
+ const timer = this.pendingWrites.get(propertyId);
1682
+ if (timer) {
1683
+ clearTimeout(timer);
1684
+ this.pendingWrites.delete(propertyId);
1685
+ }
1686
+ for (const [delegateId, set] of this.delegatePendingWrites.entries()) {
1687
+ set.delete(propertyId);
1688
+ if (set.size === 0) {
1689
+ this.delegatePendingWrites.delete(delegateId);
1690
+ }
1691
+ }
1692
+ }
1693
+ cancelPendingWritesForDelegate(delegateId) {
1694
+ const pendingPropertyIds = this.delegatePendingWrites.get(delegateId);
1695
+ if (pendingPropertyIds) {
1696
+ for (const propertyId of pendingPropertyIds) {
1697
+ const timer = this.pendingWrites.get(propertyId);
1698
+ if (timer) {
1699
+ clearTimeout(timer);
1700
+ this.pendingWrites.delete(propertyId);
1701
+ }
1702
+ }
1703
+ this.delegatePendingWrites.delete(delegateId);
1704
+ }
1705
+ }
1706
+ async awaitActiveWritesForDelegate(delegateId) {
1707
+ while (true) {
1708
+ const activeWrites = this.delegateActiveWrites.get(delegateId);
1709
+ if (!activeWrites || activeWrites.size === 0) {
1710
+ break;
1711
+ }
1712
+ const toAwait = Array.from(activeWrites);
1713
+ await Promise.allSettled(toAwait);
1714
+ for (const p of toAwait) {
1715
+ activeWrites.delete(p);
1716
+ }
1717
+ }
1718
+ this.delegateActiveWrites.delete(delegateId);
1719
+ }
1720
+ async awaitAllActiveWrites() {
1721
+ while (true) {
1722
+ const allPromises = [];
1723
+ for (const activeWrites of this.delegateActiveWrites.values()) {
1724
+ allPromises.push(...activeWrites);
1725
+ }
1726
+ if (allPromises.length === 0) {
1727
+ break;
1728
+ }
1729
+ await Promise.allSettled(allPromises);
1730
+ for (const activeWrites of this.delegateActiveWrites.values()) {
1731
+ for (const p of allPromises) {
1732
+ activeWrites.delete(p);
1733
+ }
1734
+ }
1735
+ }
1736
+ this.delegateActiveWrites.clear();
1737
+ }
1738
+ async awaitActivePollDrainsForDelegate(delegateId) {
1739
+ const deviceDbId = this.delegateDeviceIds.get(delegateId);
1740
+ const relevantDeviceIds = new Set([delegateId]);
1741
+ if (deviceDbId) {
1742
+ relevantDeviceIds.add(deviceDbId);
1743
+ }
1744
+ const trackedPollDeviceIds = this.delegatePollDeviceIds.get(delegateId);
1745
+ if (trackedPollDeviceIds) {
1746
+ for (const devId of trackedPollDeviceIds) {
1747
+ relevantDeviceIds.add(devId);
1748
+ }
1749
+ }
1750
+ for (const [devId, buckets] of this.activePollWrites.entries()) {
1751
+ for (const bucket of buckets) {
1752
+ for (const pending of bucket.values.values()) {
1753
+ if (pending.delegateId === delegateId) {
1754
+ relevantDeviceIds.add(devId);
1755
+ }
1756
+ }
1757
+ }
1758
+ }
1759
+ while (true) {
1760
+ const promises = [];
1761
+ for (const devId of relevantDeviceIds) {
1762
+ const drains = this.activePollDrainPromises.get(devId);
1763
+ if (drains && drains.size > 0) {
1764
+ promises.push(...drains);
1765
+ }
1766
+ }
1767
+ if (promises.length === 0) {
1768
+ break;
1769
+ }
1770
+ await Promise.allSettled(promises);
1771
+ for (const devId of relevantDeviceIds) {
1772
+ const drains = this.activePollDrainPromises.get(devId);
1773
+ if (drains) {
1774
+ for (const p of promises) {
1775
+ drains.delete(p);
1776
+ }
1777
+ }
1778
+ }
1779
+ }
1780
+ }
1781
+ async awaitAllActivePollDrains() {
1782
+ while (true) {
1783
+ const allPromises = [];
1784
+ for (const drains of this.activePollDrainPromises.values()) {
1785
+ allPromises.push(...drains);
1786
+ }
1787
+ if (allPromises.length === 0) {
1788
+ break;
1789
+ }
1790
+ await Promise.allSettled(allPromises);
1791
+ for (const drains of this.activePollDrainPromises.values()) {
1792
+ for (const p of allPromises) {
1793
+ drains.delete(p);
1794
+ }
1795
+ }
1796
+ }
1797
+ }
1798
+ cancelPollWrite(propertyId) {
1799
+ for (const [deviceId, bucket] of this.pendingPollWrites.entries()) {
1800
+ bucket.values.delete(propertyId);
1801
+ if (bucket.values.size === 0) {
1802
+ clearTimeout(bucket.timer);
1803
+ this.pendingPollWrites.delete(deviceId);
1804
+ }
1805
+ }
1806
+ for (const buckets of this.activePollWrites.values()) {
1807
+ for (const bucket of buckets) {
1808
+ bucket.values.delete(propertyId);
1809
+ }
1810
+ }
1811
+ }
1812
+ cancelPollWritesForDelegate(delegateId) {
1813
+ for (const [deviceId, bucket] of this.pendingPollWrites.entries()) {
1814
+ for (const [propertyId, pending] of bucket.values.entries()) {
1815
+ if (pending.delegateId === delegateId) {
1816
+ bucket.values.delete(propertyId);
1817
+ }
1818
+ }
1819
+ if (bucket.values.size === 0) {
1820
+ clearTimeout(bucket.timer);
1821
+ this.pendingPollWrites.delete(deviceId);
1822
+ }
1823
+ }
1824
+ for (const buckets of this.activePollWrites.values()) {
1825
+ for (const bucket of buckets) {
1826
+ for (const [propertyId, pending] of bucket.values.entries()) {
1827
+ if (pending.delegateId === delegateId) {
1828
+ bucket.values.delete(propertyId);
1829
+ }
1830
+ }
1831
+ }
1832
+ }
1833
+ }
1834
+ clearPollWrites() {
1835
+ for (const bucket of this.pendingPollWrites.values()) {
1836
+ clearTimeout(bucket.timer);
1837
+ }
1838
+ this.pendingPollWrites.clear();
1839
+ for (const buckets of this.activePollWrites.values()) {
1840
+ for (const bucket of buckets) {
1841
+ bucket.values.clear();
1842
+ }
1843
+ }
1844
+ this.activePollWrites.clear();
1845
+ }
1237
1846
  async writeValueToProperty(property, value) {
1238
1847
  return await this.channelsPropertiesService.update(property.id, (0, transform_utils_1.toInstance)(update_channel_property_dto_1.UpdateShellyNgChannelPropertyDto, {
1239
- ...(0, class_transformer_1.instanceToPlain)(property),
1848
+ type: devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE,
1240
1849
  value,
1241
1850
  }));
1242
1851
  }
@@ -1270,7 +1879,8 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1270
1879
  }
1271
1880
  return fallback;
1272
1881
  }
1273
- detach() {
1882
+ async detach() {
1883
+ const teardownPromises = [];
1274
1884
  for (const [, delegate] of this.delegates.entries()) {
1275
1885
  const valueHandler = this.delegateValueHandlers.get(delegate.id);
1276
1886
  const connectionHandler = this.delegateConnectionHandlers.get(delegate.id);
@@ -1280,19 +1890,41 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1280
1890
  if (connectionHandler) {
1281
1891
  delegate.off('connected', connectionHandler);
1282
1892
  }
1893
+ teardownPromises.push(this.teardownDelegateEvents(delegate));
1283
1894
  }
1895
+ for (const pendingWrite of this.pendingWrites.values()) {
1896
+ clearTimeout(pendingWrite);
1897
+ }
1898
+ this.pendingWrites.clear();
1899
+ this.delegatePendingWrites.clear();
1900
+ for (const bucket of this.pendingPollWrites.values()) {
1901
+ clearTimeout(bucket.timer);
1902
+ }
1903
+ this.pendingPollWrites.clear();
1904
+ for (const buckets of this.activePollWrites.values()) {
1905
+ for (const bucket of buckets) {
1906
+ bucket.values.clear();
1907
+ }
1908
+ }
1909
+ await Promise.all(teardownPromises);
1910
+ await this.awaitAllActiveWrites();
1911
+ await this.awaitAllActivePollDrains();
1912
+ this.activePollWrites.clear();
1913
+ this.activePollDrainPromises.clear();
1914
+ this.delegatePollDeviceIds.clear();
1284
1915
  this.delegates.clear();
1285
1916
  this.delegateValueHandlers.clear();
1286
1917
  this.delegateConnectionHandlers.clear();
1918
+ this.delegateEventHandlers.clear();
1919
+ this.delegateEventQueues.clear();
1920
+ this.delegateEventGenerations.clear();
1287
1921
  this.delegateDeviceIds.clear();
1288
1922
  this.changeHandlers.clear();
1289
1923
  this.setPropertiesHandlers.clear();
1290
1924
  this.setChannelsHandlers.clear();
1291
1925
  this.propertiesMap.clear();
1292
- for (const pendingWrite of this.pendingWrites.values()) {
1293
- clearTimeout(pendingWrite);
1294
- }
1295
- this.pendingWrites.clear();
1926
+ this.delegatePollGenerations.clear();
1927
+ this.currentValueUpdateContext = null;
1296
1928
  this.deviceLocks.clear();
1297
1929
  this.canonicalMacLocks.clear();
1298
1930
  this.connectedDelegatesPerDevice.clear();
@@ -1305,8 +1937,8 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1305
1937
  this.delegateConnectedState.clear();
1306
1938
  this.insertGeneration.clear();
1307
1939
  }
1308
- destroy() {
1309
- this.detach();
1940
+ async destroy() {
1941
+ await this.detach();
1310
1942
  }
1311
1943
  async checkHealth(pingTimeoutMs = 5_000) {
1312
1944
  const CONCURRENCY = 10;
@@ -1336,20 +1968,47 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1336
1968
  await Promise.all(tasks.slice(i, i + CONCURRENCY).map((fn) => fn()));
1337
1969
  }
1338
1970
  }
1339
- async pollAllDevices(timeoutMs = 10_000) {
1340
- const CONCURRENCY = 10;
1341
- const tasks = [];
1342
- for (const [id, delegate] of this.delegates.entries()) {
1343
- if (!delegate.connected) {
1344
- continue;
1345
- }
1346
- tasks.push(async () => {
1347
- const ok = await delegate.pollStatus(timeoutMs);
1348
- if (!ok) {
1349
- this.logger.warn(`Status poll failed for device=${id}`);
1350
- }
1971
+ getConnectedDelegateIds() {
1972
+ return Array.from(this.delegates.entries())
1973
+ .filter(([, delegate]) => delegate.connected)
1974
+ .map(([id]) => id)
1975
+ .sort();
1976
+ }
1977
+ invalidateStatusPolls() {
1978
+ for (const delegateId of this.delegates.keys()) {
1979
+ this.delegatePollGenerations.set(delegateId, (this.delegatePollGenerations.get(delegateId) ?? 0) + 1);
1980
+ }
1981
+ this.clearPollWrites();
1982
+ }
1983
+ async pollDevice(deviceId, timeoutMs = 10_000) {
1984
+ const delegate = this.delegates.get(deviceId);
1985
+ if (!delegate || !delegate.connected) {
1986
+ return;
1987
+ }
1988
+ const generation = this.delegatePollGenerations.get(deviceId) ?? 0;
1989
+ const traceDeviceId = this.delegateDeviceIds.get(deviceId) ?? deviceId;
1990
+ this.commandLatencyTraceCollector.recordPollRpc(traceDeviceId, 'poll-rpc-start', { timeoutMs });
1991
+ let ok;
1992
+ try {
1993
+ ok = await delegate.pollStatus(timeoutMs, () => this.delegates.get(deviceId) === delegate &&
1994
+ delegate.connected &&
1995
+ this.delegatePollGenerations.get(deviceId) === generation);
1996
+ }
1997
+ catch (error) {
1998
+ this.commandLatencyTraceCollector.recordPollRpc(traceDeviceId, 'poll-rpc-complete', {
1999
+ ok: false,
2000
+ error: error instanceof Error ? error.message : 'unknown failure',
1351
2001
  });
2002
+ throw error;
2003
+ }
2004
+ this.commandLatencyTraceCollector.recordPollRpc(traceDeviceId, 'poll-rpc-complete', { ok });
2005
+ if (!ok && this.delegates.get(deviceId) === delegate && this.delegatePollGenerations.get(deviceId) === generation) {
2006
+ this.logger.warn(`Status poll failed for device=${deviceId}`);
1352
2007
  }
2008
+ }
2009
+ async pollAllDevices(timeoutMs = 10_000) {
2010
+ const CONCURRENCY = 10;
2011
+ const tasks = this.getConnectedDelegateIds().map((id) => () => this.pollDevice(id, timeoutMs));
1353
2012
  for (let i = 0; i < tasks.length; i += CONCURRENCY) {
1354
2013
  await Promise.all(tasks.slice(i, i + CONCURRENCY).map((fn) => fn()));
1355
2014
  }
@@ -1398,6 +2057,9 @@ exports.DelegatesManagerService = DelegatesManagerService;
1398
2057
  DelegatesManagerService.DISCONNECT_GRACE_MS = 15_000;
1399
2058
  exports.DelegatesManagerService = DelegatesManagerService = DelegatesManagerService_1 = __decorate([
1400
2059
  (0, common_1.Injectable)(),
2060
+ __param(8, (0, common_1.Optional)()),
2061
+ __param(9, (0, common_1.Optional)()),
2062
+ __param(10, (0, common_1.Optional)()),
1401
2063
  __metadata("design:paramtypes", [devices_service_1.DevicesService,
1402
2064
  channels_service_1.ChannelsService,
1403
2065
  channels_properties_service_1.ChannelsPropertiesService,
@@ -1405,6 +2067,9 @@ exports.DelegatesManagerService = DelegatesManagerService = DelegatesManagerServ
1405
2067
  device_manager_service_1.DeviceManagerService,
1406
2068
  device_address_service_1.DeviceAddressService,
1407
2069
  mappings_1.PropertyMappingStorageService,
1408
- mappings_1.TransformerRegistry])
2070
+ mappings_1.TransformerRegistry,
2071
+ command_latency_trace_collector_service_1.CommandLatencyTraceCollectorService,
2072
+ poll_placement_diagnostics_service_1.PollPlacementDiagnosticsService,
2073
+ channel_input_occurrences_service_1.ChannelInputOccurrencesService])
1409
2074
  ], DelegatesManagerService);
1410
2075
  //# sourceMappingURL=delegates-manager.service.js.map