@fastybird/smart-panel-backend 1.1.0-alpha.2 → 1.1.0-alpha.20

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 (403) 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/common/utils/transform.utils.js +3 -0
  15. package/dist/common/utils/transform.utils.js.map +1 -1
  16. package/dist/dataSource.js +1 -0
  17. package/dist/dataSource.js.map +1 -1
  18. package/dist/main.js +2 -7
  19. package/dist/main.js.map +1 -1
  20. package/dist/migrations/1000000000026-AddHardwareInputCategories.d.ts +7 -0
  21. package/dist/migrations/1000000000026-AddHardwareInputCategories.js +364 -0
  22. package/dist/migrations/1000000000026-AddHardwareInputCategories.js.map +1 -0
  23. package/dist/modules/devices/controllers/channels.controller.d.ts +5 -1
  24. package/dist/modules/devices/controllers/channels.controller.js +34 -2
  25. package/dist/modules/devices/controllers/channels.controller.js.map +1 -1
  26. package/dist/modules/devices/controllers/channels.properties.controller.js +21 -4
  27. package/dist/modules/devices/controllers/channels.properties.controller.js.map +1 -1
  28. package/dist/modules/devices/controllers/devices.channels.controller.d.ts +5 -1
  29. package/dist/modules/devices/controllers/devices.channels.controller.js +38 -2
  30. package/dist/modules/devices/controllers/devices.channels.controller.js.map +1 -1
  31. package/dist/modules/devices/controllers/devices.channels.properties.controller.js +21 -4
  32. package/dist/modules/devices/controllers/devices.channels.properties.controller.js.map +1 -1
  33. package/dist/modules/devices/devices.constants.d.ts +6 -0
  34. package/dist/modules/devices/devices.constants.js +6 -0
  35. package/dist/modules/devices/devices.constants.js.map +1 -1
  36. package/dist/modules/devices/devices.module.js +18 -0
  37. package/dist/modules/devices/devices.module.js.map +1 -1
  38. package/dist/modules/devices/devices.openapi.d.ts +3 -1
  39. package/dist/modules/devices/devices.openapi.js +7 -0
  40. package/dist/modules/devices/devices.openapi.js.map +1 -1
  41. package/dist/modules/devices/dto/channel-input-occurrence.dto.d.ts +10 -0
  42. package/dist/modules/devices/dto/channel-input-occurrence.dto.js +99 -0
  43. package/dist/modules/devices/dto/channel-input-occurrence.dto.js.map +1 -0
  44. package/dist/modules/devices/models/channel-input-capabilities.model.d.ts +20 -0
  45. package/dist/modules/devices/models/channel-input-capabilities.model.js +111 -0
  46. package/dist/modules/devices/models/channel-input-capabilities.model.js.map +1 -0
  47. package/dist/modules/devices/models/channel-input-occurrence.model.d.ts +22 -0
  48. package/dist/modules/devices/models/channel-input-occurrence.model.js +154 -0
  49. package/dist/modules/devices/models/channel-input-occurrence.model.js.map +1 -0
  50. package/dist/modules/devices/services/channel-input-deduplication.service.d.ts +17 -0
  51. package/dist/modules/devices/services/channel-input-deduplication.service.js +88 -0
  52. package/dist/modules/devices/services/channel-input-deduplication.service.js.map +1 -0
  53. package/dist/modules/devices/services/channel-input-occurrences.service.d.ts +21 -0
  54. package/dist/modules/devices/services/channel-input-occurrences.service.js +163 -0
  55. package/dist/modules/devices/services/channel-input-occurrences.service.js.map +1 -0
  56. package/dist/modules/devices/services/channels.properties.service.d.ts +27 -3
  57. package/dist/modules/devices/services/channels.properties.service.js +304 -28
  58. package/dist/modules/devices/services/channels.properties.service.js.map +1 -1
  59. package/dist/modules/devices/services/channels.service.js +42 -38
  60. package/dist/modules/devices/services/channels.service.js.map +1 -1
  61. package/dist/modules/devices/services/command-latency-trace-collector.service.d.ts +101 -0
  62. package/dist/modules/devices/services/command-latency-trace-collector.service.js +451 -0
  63. package/dist/modules/devices/services/command-latency-trace-collector.service.js.map +1 -0
  64. package/dist/modules/devices/services/device-structure-lock.service.d.ts +10 -2
  65. package/dist/modules/devices/services/device-structure-lock.service.js +86 -7
  66. package/dist/modules/devices/services/device-structure-lock.service.js.map +1 -1
  67. package/dist/modules/devices/services/devices.service.js +37 -33
  68. package/dist/modules/devices/services/devices.service.js.map +1 -1
  69. package/dist/modules/devices/services/module-reset.service.d.ts +3 -1
  70. package/dist/modules/devices/services/module-reset.service.js +21 -16
  71. package/dist/modules/devices/services/module-reset.service.js.map +1 -1
  72. package/dist/modules/devices/services/property-command-dispatch.service.d.ts +45 -0
  73. package/dist/modules/devices/services/property-command-dispatch.service.js +227 -0
  74. package/dist/modules/devices/services/property-command-dispatch.service.js.map +1 -0
  75. package/dist/modules/devices/services/property-command-window.service.d.ts +71 -0
  76. package/dist/modules/devices/services/property-command-window.service.js +204 -0
  77. package/dist/modules/devices/services/property-command-window.service.js.map +1 -0
  78. package/dist/modules/devices/services/property-command.service.d.ts +20 -3
  79. package/dist/modules/devices/services/property-command.service.js +56 -10
  80. package/dist/modules/devices/services/property-command.service.js.map +1 -1
  81. package/dist/modules/devices/services/property-state-coordinator.service.d.ts +4 -0
  82. package/dist/modules/devices/services/property-state-coordinator.service.js +35 -0
  83. package/dist/modules/devices/services/property-state-coordinator.service.js.map +1 -0
  84. package/dist/modules/devices/services/property-value.service.d.ts +1 -0
  85. package/dist/modules/devices/services/property-value.service.js +4 -0
  86. package/dist/modules/devices/services/property-value.service.js.map +1 -1
  87. package/dist/modules/devices/utils/schema.utils.js +1 -1
  88. package/dist/modules/devices/utils/schema.utils.js.map +1 -1
  89. package/dist/modules/platform/services/platform.service.d.ts +13 -4
  90. package/dist/modules/platform/services/platform.service.js +57 -35
  91. package/dist/modules/platform/services/platform.service.js.map +1 -1
  92. package/dist/modules/remote-access/dto/update-config.dto.js +5 -0
  93. package/dist/modules/remote-access/dto/update-config.dto.js.map +1 -1
  94. package/dist/modules/remote-access/validators/is-remote-access-url.validator.js +5 -2
  95. package/dist/modules/remote-access/validators/is-remote-access-url.validator.js.map +1 -1
  96. package/dist/modules/system/scripts/update-worker.sh +668 -59
  97. package/dist/modules/system/services/privileged-worker.service.d.ts +10 -0
  98. package/dist/modules/system/services/privileged-worker.service.js +137 -11
  99. package/dist/modules/system/services/privileged-worker.service.js.map +1 -1
  100. package/dist/modules/system/services/update-executor.service.d.ts +20 -2
  101. package/dist/modules/system/services/update-executor.service.js +256 -25
  102. package/dist/modules/system/services/update-executor.service.js.map +1 -1
  103. package/dist/modules/websocket/gateway/websocket.gateway.d.ts +4 -1
  104. package/dist/modules/websocket/gateway/websocket.gateway.js +28 -5
  105. package/dist/modules/websocket/gateway/websocket.gateway.js.map +1 -1
  106. package/dist/modules/websocket/services/command-acknowledgement-trace.service.d.ts +143 -0
  107. package/dist/modules/websocket/services/command-acknowledgement-trace.service.js +523 -0
  108. package/dist/modules/websocket/services/command-acknowledgement-trace.service.js.map +1 -0
  109. package/dist/modules/websocket/websocket.module.js +9 -1
  110. package/dist/modules/websocket/websocket.module.js.map +1 -1
  111. package/dist/plugins/devices-home-assistant/devices-home-assistant.openapi.d.ts +2 -2
  112. package/dist/plugins/devices-home-assistant/devices-home-assistant.plugin.d.ts +6 -1
  113. package/dist/plugins/devices-home-assistant/devices-home-assistant.plugin.js +16 -1
  114. package/dist/plugins/devices-home-assistant/devices-home-assistant.plugin.js.map +1 -1
  115. package/dist/plugins/devices-home-assistant/dto/mapping-preview.dto.d.ts +1 -0
  116. package/dist/plugins/devices-home-assistant/dto/mapping-preview.dto.js +11 -0
  117. package/dist/plugins/devices-home-assistant/dto/mapping-preview.dto.js.map +1 -1
  118. package/dist/plugins/devices-home-assistant/mappers/button.entity.mapper.service.d.ts +19 -0
  119. package/dist/plugins/devices-home-assistant/mappers/button.entity.mapper.service.js +51 -0
  120. package/dist/plugins/devices-home-assistant/mappers/button.entity.mapper.service.js.map +1 -0
  121. package/dist/plugins/devices-home-assistant/mappings/definitions/entity-mappings.yaml +56 -7
  122. package/dist/plugins/devices-home-assistant/models/mapping-preview.model.d.ts +1 -0
  123. package/dist/plugins/devices-home-assistant/models/mapping-preview.model.js +11 -0
  124. package/dist/plugins/devices-home-assistant/models/mapping-preview.model.js.map +1 -1
  125. package/dist/plugins/devices-home-assistant/services/device-adoption.service.js +17 -0
  126. package/dist/plugins/devices-home-assistant/services/device-adoption.service.js.map +1 -1
  127. package/dist/plugins/devices-home-assistant/services/home-assistant-raw-event.service.d.ts +27 -0
  128. package/dist/plugins/devices-home-assistant/services/home-assistant-raw-event.service.js +271 -0
  129. package/dist/plugins/devices-home-assistant/services/home-assistant-raw-event.service.js.map +1 -0
  130. package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.d.ts +2 -2
  131. package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.js +33 -14
  132. package/dist/plugins/devices-home-assistant/services/home-assistant.ws.service.js.map +1 -1
  133. package/dist/plugins/devices-home-assistant/services/mapping-preview.service.js +24 -4
  134. package/dist/plugins/devices-home-assistant/services/mapping-preview.service.js.map +1 -1
  135. package/dist/plugins/devices-home-assistant/services/state-changed.event.service.d.ts +4 -1
  136. package/dist/plugins/devices-home-assistant/services/state-changed.event.service.js +84 -5
  137. package/dist/plugins/devices-home-assistant/services/state-changed.event.service.js.map +1 -1
  138. package/dist/plugins/devices-home-assistant/services/wizard.service.js +1 -0
  139. package/dist/plugins/devices-home-assistant/services/wizard.service.js.map +1 -1
  140. package/dist/plugins/devices-home-assistant/utils/ha-event.utils.d.ts +2 -0
  141. package/dist/plugins/devices-home-assistant/utils/ha-event.utils.js +50 -0
  142. package/dist/plugins/devices-home-assistant/utils/ha-event.utils.js.map +1 -0
  143. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.d.ts +2 -0
  144. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.js +28 -1
  145. package/dist/plugins/devices-homekit/listeners/homekit-event.listener.js.map +1 -1
  146. package/dist/plugins/devices-homekit/mappers/base.mapper.js +27 -4
  147. package/dist/plugins/devices-homekit/mappers/base.mapper.js.map +1 -1
  148. package/dist/plugins/devices-homekit/mappers/button.mapper.d.ts +15 -0
  149. package/dist/plugins/devices-homekit/mappers/button.mapper.js +143 -0
  150. package/dist/plugins/devices-homekit/mappers/button.mapper.js.map +1 -0
  151. package/dist/plugins/devices-homekit/mappers/homekit-mapper.interface.d.ts +16 -0
  152. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.d.ts +7 -0
  153. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.js +84 -73
  154. package/dist/plugins/devices-homekit/mappers/thermostat-coordinator.js.map +1 -1
  155. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.d.ts +5 -1
  156. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.js +42 -0
  157. package/dist/plugins/devices-homekit/services/homekit-mapper-registry.service.js.map +1 -1
  158. package/dist/plugins/devices-homey/mappings/definitions/channels.yaml +50 -0
  159. package/dist/plugins/devices-homey/mappings/definitions/devices.yaml +18 -0
  160. package/dist/plugins/devices-homey/mappings/definitions/properties.yaml +55 -0
  161. package/dist/plugins/devices-homey/mappings/device-support.js +10 -0
  162. package/dist/plugins/devices-homey/mappings/device-support.js.map +1 -1
  163. package/dist/plugins/devices-homey/mappings/mapping-loader.service.d.ts +1 -0
  164. package/dist/plugins/devices-homey/mappings/mapping-loader.service.js +66 -8
  165. package/dist/plugins/devices-homey/mappings/mapping-loader.service.js.map +1 -1
  166. package/dist/plugins/devices-homey/models/inventory.model.d.ts +2 -1
  167. package/dist/plugins/devices-homey/models/inventory.model.js +1 -0
  168. package/dist/plugins/devices-homey/models/inventory.model.js.map +1 -1
  169. package/dist/plugins/devices-homey/models/mapping-preview.model.d.ts +1 -0
  170. package/dist/plugins/devices-homey/models/mapping-preview.model.js +1 -0
  171. package/dist/plugins/devices-homey/models/mapping-preview.model.js.map +1 -1
  172. package/dist/plugins/devices-homey/services/homey-mapping-preview.service.js +7 -0
  173. package/dist/plugins/devices-homey/services/homey-mapping-preview.service.js.map +1 -1
  174. package/dist/plugins/devices-homey/services/homey-synchronizer.service.d.ts +3 -1
  175. package/dist/plugins/devices-homey/services/homey-synchronizer.service.js +37 -6
  176. package/dist/plugins/devices-homey/services/homey-synchronizer.service.js.map +1 -1
  177. package/dist/plugins/devices-reterminal/services/reterminal-button.service.d.ts +7 -3
  178. package/dist/plugins/devices-reterminal/services/reterminal-button.service.js +63 -17
  179. package/dist/plugins/devices-reterminal/services/reterminal-button.service.js.map +1 -1
  180. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.d.ts +38 -3
  181. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js +840 -134
  182. package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js.map +1 -1
  183. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.d.ts +15 -1
  184. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js +117 -10
  185. package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js.map +1 -1
  186. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.constants.js +11 -13
  187. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.constants.js.map +1 -1
  188. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.plugin.js +2 -0
  189. package/dist/plugins/devices-shelly-ng/devices-shelly-ng.plugin.js.map +1 -1
  190. package/dist/plugins/devices-shelly-ng/mappings/definitions/inputs.yaml +80 -0
  191. package/dist/plugins/devices-shelly-ng/mappings/mapping-loader.service.js +11 -1
  192. package/dist/plugins/devices-shelly-ng/mappings/mapping-loader.service.js.map +1 -1
  193. package/dist/plugins/devices-shelly-ng/mappings/mapping.types.d.ts +6 -3
  194. package/dist/plugins/devices-shelly-ng/mappings/schema/mapping-schema.json +5 -0
  195. package/dist/plugins/devices-shelly-ng/services/device-manager.service.js +130 -7
  196. package/dist/plugins/devices-shelly-ng/services/device-manager.service.js.map +1 -1
  197. package/dist/plugins/devices-shelly-ng/services/poll-placement-diagnostics.service.d.ts +48 -0
  198. package/dist/plugins/devices-shelly-ng/services/poll-placement-diagnostics.service.js +457 -0
  199. package/dist/plugins/devices-shelly-ng/services/poll-placement-diagnostics.service.js.map +1 -0
  200. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.d.ts +12 -2
  201. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js +86 -28
  202. package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js.map +1 -1
  203. package/dist/plugins/devices-shelly-ng/services/shelly-rpc-client.service.js +3 -0
  204. package/dist/plugins/devices-shelly-ng/services/shelly-rpc-client.service.js.map +1 -1
  205. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.d.ts +1 -1
  206. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.js +18 -13
  207. package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.js.map +1 -1
  208. package/dist/plugins/devices-shelly-ng/utils/transform.utils.d.ts +2 -0
  209. package/dist/plugins/devices-shelly-ng/utils/transform.utils.js +14 -1
  210. package/dist/plugins/devices-shelly-ng/utils/transform.utils.js.map +1 -1
  211. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.d.ts +2 -0
  212. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.js +66 -4
  213. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.js.map +1 -1
  214. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.plugin.js +2 -0
  215. package/dist/plugins/devices-shelly-v1/devices-shelly-v1.plugin.js.map +1 -1
  216. package/dist/plugins/devices-shelly-v1/platforms/shelly-v1.device.platform.js +7 -0
  217. package/dist/plugins/devices-shelly-v1/platforms/shelly-v1.device.platform.js.map +1 -1
  218. package/dist/plugins/devices-shelly-v1/services/device-mapper.service.d.ts +3 -1
  219. package/dist/plugins/devices-shelly-v1/services/device-mapper.service.js +20 -2
  220. package/dist/plugins/devices-shelly-v1/services/device-mapper.service.js.map +1 -1
  221. package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.d.ts +16 -0
  222. package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.js +107 -0
  223. package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.js.map +1 -0
  224. package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.d.ts +7 -1
  225. package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.js +98 -3
  226. package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.js.map +1 -1
  227. package/dist/plugins/devices-third-party/controllers/third-party-inputs.controller.d.ts +17 -0
  228. package/dist/plugins/devices-third-party/controllers/third-party-inputs.controller.js +205 -0
  229. package/dist/plugins/devices-third-party/controllers/third-party-inputs.controller.js.map +1 -0
  230. package/dist/plugins/devices-third-party/devices-third-party.openapi.d.ts +1 -1
  231. package/dist/plugins/devices-third-party/devices-third-party.plugin.js +2 -1
  232. package/dist/plugins/devices-third-party/devices-third-party.plugin.js.map +1 -1
  233. package/dist/plugins/devices-third-party/dto/report-input-occurrence-response.dto.d.ts +5 -0
  234. package/dist/plugins/devices-third-party/dto/report-input-occurrence-response.dto.js +50 -0
  235. package/dist/plugins/devices-third-party/dto/report-input-occurrence-response.dto.js.map +1 -0
  236. package/dist/plugins/devices-third-party/dto/report-input-occurrence.dto.d.ts +8 -0
  237. package/dist/plugins/devices-third-party/dto/report-input-occurrence.dto.js +81 -0
  238. package/dist/plugins/devices-third-party/dto/report-input-occurrence.dto.js.map +1 -0
  239. package/dist/plugins/devices-third-party/platforms/third-party-device.platform.js +19 -4
  240. package/dist/plugins/devices-third-party/platforms/third-party-device.platform.js.map +1 -1
  241. package/dist/plugins/devices-virtual/listeners/virtual-projection.listener.d.ts +2 -0
  242. package/dist/plugins/devices-virtual/listeners/virtual-projection.listener.js +57 -0
  243. package/dist/plugins/devices-virtual/listeners/virtual-projection.listener.js.map +1 -1
  244. package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.d.ts +3 -0
  245. package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.js +41 -5
  246. package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.js.map +1 -1
  247. package/dist/plugins/devices-zigbee2mqtt/interfaces/zigbee2mqtt.interface.d.ts +7 -1
  248. package/dist/plugins/devices-zigbee2mqtt/mappings/config-driven.converter.js +16 -15
  249. package/dist/plugins/devices-zigbee2mqtt/mappings/config-driven.converter.js.map +1 -1
  250. package/dist/plugins/devices-zigbee2mqtt/mappings/definitions/remotes.yaml +505 -74
  251. package/dist/plugins/devices-zigbee2mqtt/mappings/schema/mapping-schema.json +3 -3
  252. package/dist/plugins/devices-zigbee2mqtt/mappings/transformers/transformer.types.d.ts +1 -1
  253. package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.d.ts +8 -2
  254. package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.js +6 -5
  255. package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.js.map +1 -1
  256. package/dist/plugins/devices-zigbee2mqtt/services/device-adoption.service.js +18 -11
  257. package/dist/plugins/devices-zigbee2mqtt/services/device-adoption.service.js.map +1 -1
  258. package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.d.ts +9 -3
  259. package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.js +166 -3
  260. package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.js.map +1 -1
  261. package/dist/plugins/devices-zigbee2mqtt/services/mqtt-client-adapter.service.js +5 -2
  262. package/dist/plugins/devices-zigbee2mqtt/services/mqtt-client-adapter.service.js.map +1 -1
  263. package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.d.ts +1 -0
  264. package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.js +44 -4
  265. package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.js.map +1 -1
  266. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.d.ts +17 -0
  267. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.js +147 -0
  268. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/setup.controller.js.map +1 -0
  269. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.d.ts +15 -0
  270. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.js +98 -0
  271. package/dist/plugins/remote-access-cloudflare-tunnel/controllers/status.controller.js.map +1 -0
  272. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.d.ts +9 -0
  273. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.js +94 -0
  274. package/dist/plugins/remote-access-cloudflare-tunnel/dto/update-config.dto.js.map +1 -0
  275. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.d.ts +9 -0
  276. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.js +92 -0
  277. package/dist/plugins/remote-access-cloudflare-tunnel/models/config.model.js.map +1 -0
  278. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.d.ts +7 -0
  279. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.js +48 -0
  280. package/dist/plugins/remote-access-cloudflare-tunnel/models/install.model.js.map +1 -0
  281. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.d.ts +42 -0
  282. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.js +352 -0
  283. package/dist/plugins/remote-access-cloudflare-tunnel/models/status.model.js.map +1 -0
  284. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.d.ts +24 -0
  285. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.js +27 -0
  286. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.constants.js.map +1 -0
  287. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.d.ts +8 -0
  288. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.js +19 -0
  289. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.exceptions.js.map +1 -0
  290. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.d.ts +4 -0
  291. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.js +20 -0
  292. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.openapi.js.map +1 -0
  293. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.d.ts +21 -0
  294. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.js +135 -0
  295. package/dist/plugins/remote-access-cloudflare-tunnel/remote-access-cloudflare-tunnel.plugin.js.map +1 -0
  296. package/dist/plugins/remote-access-cloudflare-tunnel/scripts/cloudflared-setup.sh +185 -0
  297. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.d.ts +82 -0
  298. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.js +507 -0
  299. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-managed.service.js.map +1 -0
  300. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.d.ts +10 -0
  301. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.js +37 -0
  302. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-provider.service.js.map +1 -0
  303. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.d.ts +38 -0
  304. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.js +147 -0
  305. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflare-tunnel-setup.service.js.map +1 -0
  306. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.d.ts +15 -0
  307. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.js +67 -0
  308. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-cli.service.js.map +1 -0
  309. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.d.ts +8 -0
  310. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.js +46 -0
  311. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-metrics.service.js.map +1 -0
  312. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.d.ts +27 -0
  313. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.js +139 -0
  314. package/dist/plugins/remote-access-cloudflare-tunnel/services/cloudflared-process.service.js.map +1 -0
  315. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.d.ts +1 -0
  316. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.js +26 -10
  317. package/dist/plugins/remote-access-tailscale/controllers/setup.controller.js.map +1 -1
  318. package/dist/plugins/remote-access-tailscale/controllers/status.controller.d.ts +6 -1
  319. package/dist/plugins/remote-access-tailscale/controllers/status.controller.js +28 -3
  320. package/dist/plugins/remote-access-tailscale/controllers/status.controller.js.map +1 -1
  321. package/dist/plugins/remote-access-tailscale/models/status.model.d.ts +19 -0
  322. package/dist/plugins/remote-access-tailscale/models/status.model.js +158 -1
  323. package/dist/plugins/remote-access-tailscale/models/status.model.js.map +1 -1
  324. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.d.ts +3 -0
  325. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.js +4 -1
  326. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.constants.js.map +1 -1
  327. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.d.ts +13 -0
  328. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.js +27 -0
  329. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.exceptions.js.map +1 -0
  330. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.d.ts +2 -2
  331. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.js +2 -0
  332. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.openapi.js.map +1 -1
  333. package/dist/plugins/remote-access-tailscale/remote-access-tailscale.plugin.js +1 -1
  334. package/dist/plugins/remote-access-tailscale/scripts/tailscale-setup.sh +61 -0
  335. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.d.ts +9 -0
  336. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.js +12 -0
  337. package/dist/plugins/remote-access-tailscale/services/tailscale-cli.service.js.map +1 -1
  338. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.d.ts +1 -0
  339. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.js +27 -2
  340. package/dist/plugins/remote-access-tailscale/services/tailscale-login.service.js.map +1 -1
  341. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.d.ts +31 -1
  342. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.js +316 -30
  343. package/dist/plugins/remote-access-tailscale/services/tailscale-node-managed.service.js.map +1 -1
  344. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.d.ts +8 -3
  345. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.js +39 -12
  346. package/dist/plugins/remote-access-tailscale/services/tailscale-serve.service.js.map +1 -1
  347. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.d.ts +14 -5
  348. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.js +51 -16
  349. package/dist/plugins/remote-access-tailscale/services/tailscale-setup.service.js.map +1 -1
  350. package/dist/plugins/scenes-local/platforms/local-scene.platform.d.ts +3 -1
  351. package/dist/plugins/scenes-local/platforms/local-scene.platform.js +12 -7
  352. package/dist/plugins/scenes-local/platforms/local-scene.platform.js.map +1 -1
  353. package/dist/plugins/simulator/controllers/simulator.controller.d.ts +8 -2
  354. package/dist/plugins/simulator/controllers/simulator.controller.js +102 -2
  355. package/dist/plugins/simulator/controllers/simulator.controller.js.map +1 -1
  356. package/dist/plugins/simulator/dto/simulate-occurrence.dto.d.ts +12 -0
  357. package/dist/plugins/simulator/dto/simulate-occurrence.dto.js +122 -0
  358. package/dist/plugins/simulator/dto/simulate-occurrence.dto.js.map +1 -0
  359. package/dist/plugins/simulator/models/simulator-response.model.d.ts +12 -0
  360. package/dist/plugins/simulator/models/simulator-response.model.js +84 -1
  361. package/dist/plugins/simulator/models/simulator-response.model.js.map +1 -1
  362. package/dist/plugins/simulator/scenarios/definitions/small-apartment.yaml +78 -0
  363. package/dist/plugins/simulator/services/scenario-executor.service.js +3 -1
  364. package/dist/plugins/simulator/services/scenario-executor.service.js.map +1 -1
  365. package/dist/plugins/simulator/services/simulation.service.js +10 -1
  366. package/dist/plugins/simulator/services/simulation.service.js.map +1 -1
  367. package/dist/plugins/simulator/simulator.openapi.d.ts +3 -2
  368. package/dist/plugins/simulator/simulator.openapi.js +5 -0
  369. package/dist/plugins/simulator/simulator.openapi.js.map +1 -1
  370. package/dist/plugins/simulator/simulators/device-simulator.interface.d.ts +2 -0
  371. package/dist/plugins/simulator/simulators/device-simulator.interface.js +83 -0
  372. package/dist/plugins/simulator/simulators/device-simulator.interface.js.map +1 -1
  373. package/dist/plugins/simulator/simulators/index.d.ts +1 -0
  374. package/dist/plugins/simulator/simulators/index.js +1 -0
  375. package/dist/plugins/simulator/simulators/index.js.map +1 -1
  376. package/dist/plugins/simulator/simulators/input-controller.simulator.d.ts +10 -0
  377. package/dist/plugins/simulator/simulators/input-controller.simulator.js +57 -0
  378. package/dist/plugins/simulator/simulators/input-controller.simulator.js.map +1 -0
  379. package/dist/plugins/simulator/simulators/lighting.simulator.js +1 -0
  380. package/dist/plugins/simulator/simulators/lighting.simulator.js.map +1 -1
  381. package/dist/plugins/spaces-home-control/services/climate-intent.service.d.ts +3 -1
  382. package/dist/plugins/spaces-home-control/services/climate-intent.service.js +6 -3
  383. package/dist/plugins/spaces-home-control/services/climate-intent.service.js.map +1 -1
  384. package/dist/plugins/spaces-home-control/services/covers-intent.service.d.ts +3 -1
  385. package/dist/plugins/spaces-home-control/services/covers-intent.service.js +6 -3
  386. package/dist/plugins/spaces-home-control/services/covers-intent.service.js.map +1 -1
  387. package/dist/plugins/spaces-home-control/services/lighting-intent.service.d.ts +3 -1
  388. package/dist/plugins/spaces-home-control/services/lighting-intent.service.js +7 -4
  389. package/dist/plugins/spaces-home-control/services/lighting-intent.service.js.map +1 -1
  390. package/dist/plugins/spaces-home-control/services/space-media-activity.service.d.ts +3 -1
  391. package/dist/plugins/spaces-home-control/services/space-media-activity.service.js +11 -5
  392. package/dist/plugins/spaces-home-control/services/space-media-activity.service.js.map +1 -1
  393. package/dist/plugins/spaces-home-control/services/space-undo-history.service.d.ts +3 -1
  394. package/dist/plugins/spaces-home-control/services/space-undo-history.service.js +8 -5
  395. package/dist/plugins/spaces-home-control/services/space-undo-history.service.js.map +1 -1
  396. package/dist/spec/channels.d.ts +51 -1
  397. package/dist/spec/channels.js +64 -1
  398. package/dist/spec/channels.js.map +1 -1
  399. package/dist/spec/devices.d.ts +155 -2
  400. package/dist/spec/devices.js +161 -2
  401. package/dist/spec/devices.js.map +1 -1
  402. package/dist/tsconfig.build.tsbuildinfo +1 -1
  403. package/package.json +2 -2
@@ -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);
@@ -199,60 +234,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
199
234
  await comp.set(val);
200
235
  return true;
201
236
  });
202
- if (typeof comp.aenergy !== 'undefined') {
203
- const electricalEnergy = await this.channelsService.findOneBy('identifier', `energy:${comp.id}`, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
204
- if (electricalEnergy === null) {
205
- }
206
- else {
207
- const consumption = await this.channelsPropertiesService.findOneBy('identifier', 'aenergy', electricalEnergy.id);
208
- if (consumption === null) {
209
- }
210
- else {
211
- await this.setDefaultPropertyValue(device.id, consumption, (0, transform_utils_2.toEnergy)(comp.aenergy));
212
- this.changeHandlers.set(`${delegate.id}|${comp.key}|aenergy`, (val) => {
213
- this.handleNumericChange(comp.key, 'aenergy', consumption.id, val, (n) => this.handleChange(consumption, (0, transform_utils_2.toEnergy)(n), false));
214
- });
215
- }
216
- }
217
- }
218
- if (typeof comp.apower !== 'undefined') {
219
- const electricalPower = await this.channelsService.findOneBy('identifier', `power:${comp.id}`, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
220
- if (electricalPower === null) {
221
- }
222
- else {
223
- const power = await this.channelsPropertiesService.findOneBy('identifier', 'apower', electricalPower.id);
224
- if (power === null) {
225
- }
226
- else {
227
- await this.setDefaultPropertyValue(device.id, power, Math.max(0, comp.apower));
228
- this.changeHandlers.set(`${delegate.id}|${comp.key}|apower`, (val) => {
229
- this.handleNumericChange(comp.key, 'apower', power.id, val, (n) => this.handleChange(power, Math.max(0, n), false));
230
- });
231
- if (typeof comp.voltage !== 'undefined') {
232
- const voltage = await this.channelsPropertiesService.findOneBy('identifier', 'voltage', electricalPower.id);
233
- if (voltage === null) {
234
- }
235
- else {
236
- await this.setDefaultPropertyValue(device.id, voltage, comp.voltage);
237
- this.changeHandlers.set(`${delegate.id}|${comp.key}|voltage`, (val) => {
238
- this.handleNumericChange(comp.key, 'voltage', voltage.id, val, (n) => this.handleChange(voltage, n, false));
239
- });
240
- }
241
- }
242
- if (typeof comp.current !== 'undefined') {
243
- const current = await this.channelsPropertiesService.findOneBy('identifier', 'current', electricalPower.id);
244
- if (current === null) {
245
- }
246
- else {
247
- await this.setDefaultPropertyValue(device.id, current, comp.current);
248
- this.changeHandlers.set(`${delegate.id}|${comp.key}|current`, (val) => {
249
- this.handleNumericChange(comp.key, 'current', current.id, val, (n) => this.handleChange(current, n, false));
250
- });
251
- }
252
- }
253
- }
254
- }
255
- }
237
+ await this.wireElectricalChannels(delegate, device, comp);
256
238
  }
257
239
  if (this.insertGeneration.get(shelly.id) !== generation)
258
240
  return delegate;
@@ -314,6 +296,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
314
296
  await comp.stop();
315
297
  return true;
316
298
  });
299
+ await this.wireElectricalChannels(delegate, device, comp);
317
300
  }
318
301
  if (this.insertGeneration.get(shelly.id) !== generation)
319
302
  return delegate;
@@ -362,6 +345,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
362
345
  return true;
363
346
  });
364
347
  }
348
+ await this.wireElectricalChannels(delegate, device, comp);
365
349
  }
366
350
  if (this.insertGeneration.get(shelly.id) !== generation)
367
351
  return delegate;
@@ -495,6 +479,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
495
479
  ]);
496
480
  return true;
497
481
  });
482
+ await this.wireElectricalChannels(delegate, device, comp);
498
483
  }
499
484
  if (this.insertGeneration.get(shelly.id) !== generation)
500
485
  return delegate;
@@ -653,6 +638,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
653
638
  ], Math.round((0, transform_utils_1.clampNumber)(whiteValue, 0, 255)));
654
639
  return true;
655
640
  });
641
+ await this.wireElectricalChannels(delegate, device, comp);
656
642
  }
657
643
  if (this.insertGeneration.get(shelly.id) !== generation)
658
644
  return delegate;
@@ -746,6 +732,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
746
732
  await comp.set(outputValue, Math.round((0, transform_utils_1.clampNumber)(brightnessValue, 0, 100)), Math.round((0, transform_utils_1.clampNumber)(ctValue, 2_700, 6_500)));
747
733
  return true;
748
734
  });
735
+ await this.wireElectricalChannels(delegate, device, comp);
749
736
  }
750
737
  if (this.insertGeneration.get(shelly.id) !== generation)
751
738
  return delegate;
@@ -800,63 +787,136 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
800
787
  if (this.insertGeneration.get(shelly.id) !== generation)
801
788
  return delegate;
802
789
  for (const comp of delegate.pm1.values()) {
803
- const electricalPower = await this.channelsService.findOneBy('identifier', `power:${comp.id}`, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
804
- if (electricalPower === null) {
790
+ await this.wireElectricalChannels(delegate, device, comp);
791
+ }
792
+ if (this.insertGeneration.get(shelly.id) !== generation)
793
+ return delegate;
794
+ for (const comp of delegate.em.values()) {
795
+ const phases = [
796
+ { id: 'a', power: comp.a_act_power, voltage: comp.a_voltage, current: comp.a_current, freq: comp.a_freq },
797
+ { id: 'b', power: comp.b_act_power, voltage: comp.b_voltage, current: comp.b_current, freq: comp.b_freq },
798
+ { id: 'c', power: comp.c_act_power, voltage: comp.c_voltage, current: comp.c_current, freq: comp.c_freq },
799
+ ];
800
+ for (const phase of phases) {
801
+ const channelIdentifier = `power:${comp.id}:${phase.id}`;
802
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, `${phase.id}_act_power`, `${phase.id}_act_power`, phase.power, true);
803
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, `${phase.id}_voltage`, `${phase.id}_voltage`, phase.voltage, true);
804
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, `${phase.id}_current`, `${phase.id}_current`, phase.current, true);
805
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, `${phase.id}_freq`, `${phase.id}_freq`, phase.freq, true);
806
+ }
807
+ const totalChannelIdentifier = `power:${comp.id}:total`;
808
+ await this.wireMeterProperty(delegate, device, comp.key, totalChannelIdentifier, 'total_act_power', 'total_act_power', comp.total_act_power, true);
809
+ await this.wireMeterProperty(delegate, device, comp.key, totalChannelIdentifier, 'total_current', 'total_current', comp.total_current, true);
810
+ }
811
+ if (this.insertGeneration.get(shelly.id) !== generation)
812
+ return delegate;
813
+ for (const comp of delegate.emData.values()) {
814
+ const phases = [
815
+ { id: 'a', energy: comp.a_total_act_energy, returned: comp.a_total_act_ret_energy },
816
+ { id: 'b', energy: comp.b_total_act_energy, returned: comp.b_total_act_ret_energy },
817
+ { id: 'c', energy: comp.c_total_act_energy, returned: comp.c_total_act_ret_energy },
818
+ ];
819
+ for (const phase of phases) {
820
+ const channelIdentifier = `energy:${comp.id}:${phase.id}`;
821
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, `${phase.id}_total_act_energy`, `${phase.id}_total_act_energy`, phase.energy, false);
822
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, `${phase.id}_total_act_ret_energy`, `${phase.id}_total_act_ret_energy`, phase.returned, false);
823
+ }
824
+ const totalChannelIdentifier = `energy:${comp.id}:total`;
825
+ await this.wireMeterProperty(delegate, device, comp.key, totalChannelIdentifier, 'total_act', 'total_act', comp.total_act, false);
826
+ await this.wireMeterProperty(delegate, device, comp.key, totalChannelIdentifier, 'total_act_ret', 'total_act_ret', comp.total_act_ret, false);
827
+ }
828
+ if (this.insertGeneration.get(shelly.id) !== generation)
829
+ return delegate;
830
+ for (const comp of delegate.em1.values()) {
831
+ const channelIdentifier = `power:${comp.id}`;
832
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, 'act_power', 'act_power', comp.act_power, true);
833
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, 'voltage', 'voltage', comp.voltage, true);
834
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, 'current', 'current', comp.current, true);
835
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, 'freq', 'freq', comp.freq, true);
836
+ }
837
+ if (this.insertGeneration.get(shelly.id) !== generation)
838
+ return delegate;
839
+ for (const comp of delegate.em1Data.values()) {
840
+ const channelIdentifier = `energy:${comp.id}`;
841
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, 'total_act_energy', 'total_act_energy', comp.total_act_energy, false);
842
+ await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, 'total_act_ret_energy', 'total_act_ret_energy', comp.total_act_ret_energy, false);
843
+ }
844
+ if (this.insertGeneration.get(shelly.id) !== generation)
845
+ return delegate;
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) {
805
849
  continue;
806
850
  }
807
- const power = await this.channelsPropertiesService.findOneBy('identifier', 'apower', electricalPower.id);
808
- if (power === null) {
809
- throw new devices_shelly_ng_exceptions_1.DevicesShellyNgNotFoundException('Failed to load electrical power channel property');
810
- }
811
- await this.setDefaultPropertyValue(device.id, power, Math.max(0, comp.apower));
812
- this.changeHandlers.set(`${delegate.id}|${comp.key}|apower`, (val) => {
813
- this.handleNumericChange(comp.key, 'apower', power.id, val, (n) => this.handleChange(power, Math.max(0, n), false));
814
- });
815
- if (typeof comp.voltage !== 'undefined') {
816
- const voltage = await this.channelsPropertiesService.findOneBy('identifier', 'voltage', electricalPower.id);
817
- if (voltage === null) {
818
- throw new devices_shelly_ng_exceptions_1.DevicesShellyNgNotFoundException('Failed to load electrical power voltage channel property');
819
- }
820
- await this.setDefaultPropertyValue(device.id, voltage, comp.voltage);
821
- this.changeHandlers.set(`${delegate.id}|${comp.key}|voltage`, (val) => {
822
- this.handleNumericChange(comp.key, 'voltage', voltage.id, val, (n) => this.handleChange(voltage, n, false));
823
- });
824
- }
825
- if (typeof comp.current !== 'undefined') {
826
- const current = await this.channelsPropertiesService.findOneBy('identifier', 'current', electricalPower.id);
827
- if (current === null) {
828
- throw new devices_shelly_ng_exceptions_1.DevicesShellyNgNotFoundException('Failed to load electrical power current channel property');
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
+ });
829
862
  }
830
- await this.setDefaultPropertyValue(device.id, current, comp.current);
831
- this.changeHandlers.set(`${delegate.id}|${comp.key}|current`, (val) => {
832
- this.handleNumericChange(comp.key, 'current', current.id, val, (n) => this.handleChange(current, n, false));
833
- });
834
863
  }
835
- if (typeof comp.aenergy !== 'undefined') {
836
- const electricalEnergy = await this.channelsService.findOneBy('identifier', `energy:${comp.id}`, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
837
- if (electricalEnergy === null) {
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
+ });
838
875
  }
839
- else {
840
- const consumption = await this.channelsPropertiesService.findOneBy('identifier', 'aenergy', electricalEnergy.id);
841
- if (consumption === null) {
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);
842
885
  }
843
886
  else {
844
- await this.setDefaultPropertyValue(device.id, consumption, (0, transform_utils_2.toEnergy)(comp.aenergy));
845
- this.changeHandlers.set(`${delegate.id}|${comp.key}|aenergy`, (val) => {
846
- this.handleNumericChange(comp.key, 'aenergy', consumption.id, val, (n) => this.handleChange(consumption, (0, transform_utils_2.toEnergy)(n), false));
847
- });
887
+ initialVal = hasExtendedPercent ? comp.xpercent : (comp.percent ?? 0);
848
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
+ });
849
908
  }
850
909
  }
851
910
  }
852
911
  if (this.insertGeneration.get(shelly.id) !== generation)
853
912
  return delegate;
854
- const valueHandler = (compKey, attr, val) => {
913
+ const valueHandler = (compKey, attr, val, origin = 'notify') => {
855
914
  const handler = this.changeHandlers.get(`${delegate.id}|${compKey}|${attr}`);
856
915
  if (!handler) {
857
916
  return;
858
917
  }
859
918
  try {
919
+ this.currentValueUpdateContext = { delegateId: delegate.id, deviceId: device.id, origin };
860
920
  handler(val);
861
921
  }
862
922
  catch (error) {
@@ -867,6 +927,9 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
867
927
  stack: err.stack,
868
928
  });
869
929
  }
930
+ finally {
931
+ this.currentValueUpdateContext = null;
932
+ }
870
933
  };
871
934
  delegate.on('value', valueHandler);
872
935
  this.delegateValueHandlers.set(delegate.id, valueHandler);
@@ -877,6 +940,12 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
877
940
  if (wasConnected)
878
941
  return;
879
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
+ });
880
949
  const pendingTimer = this.disconnectTimers.get(deviceDbId);
881
950
  if (pendingTimer) {
882
951
  clearTimeout(pendingTimer);
@@ -898,6 +967,12 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
898
967
  if (!wasConnected)
899
968
  return;
900
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
+ });
901
976
  const count = Math.max(0, (this.connectedDelegatesPerDevice.get(deviceDbId) ?? 1) - 1);
902
977
  this.connectedDelegatesPerDevice.set(deviceDbId, count);
903
978
  if (count === 0) {
@@ -965,6 +1040,34 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
965
1040
  };
966
1041
  delegate.on('connected', connectionHandler);
967
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);
968
1071
  if (delegate.connected) {
969
1072
  connectionHandler(true);
970
1073
  }
@@ -972,17 +1075,45 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
972
1075
  return delegate;
973
1076
  }
974
1077
  remove(deviceId) {
975
- return this.withDeviceLock(deviceId, () => {
976
- this.performRemove(deviceId);
977
- return Promise.resolve();
978
- });
1078
+ return this.withDeviceLock(deviceId, () => this.performRemove(deviceId));
979
1079
  }
980
- performRemove(deviceId) {
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
+ }
1100
+ }
1101
+ async performRemove(deviceId) {
981
1102
  const delegate = this.delegates.get(deviceId);
982
1103
  if (!delegate) {
983
1104
  return;
984
1105
  }
985
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);
986
1117
  const connectionHandler = this.delegateConnectionHandlers.get(delegate.id);
987
1118
  if (connectionHandler) {
988
1119
  connectionHandler(null);
@@ -1005,14 +1136,10 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1005
1136
  });
1006
1137
  }
1007
1138
  }
1008
- if (valueHandler) {
1009
- delegate.off('value', valueHandler);
1010
- }
1011
1139
  if (connectionHandler) {
1012
1140
  delegate.off('connected', connectionHandler);
1141
+ this.delegateConnectionHandlers.delete(delegate.id);
1013
1142
  }
1014
- this.delegateValueHandlers.delete(delegate.id);
1015
- this.delegateConnectionHandlers.delete(delegate.id);
1016
1143
  for (const key of Array.from(this.changeHandlers.keys())) {
1017
1144
  if (key.startsWith(`${deviceId}|`)) {
1018
1145
  this.changeHandlers.delete(key);
@@ -1052,7 +1179,12 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1052
1179
  }
1053
1180
  this.delegateDeviceIds.delete(deviceId);
1054
1181
  this.delegateToIdentifier.delete(deviceId);
1182
+ this.pollPlacementDiagnostics.removeDelegate(deviceId);
1055
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);
1056
1188
  this.delegates.delete(deviceId);
1057
1189
  this.logger.log(`Detached Shelly device=${deviceId}`, { resource: deviceId });
1058
1190
  }
@@ -1117,12 +1249,149 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1117
1249
  return value;
1118
1250
  }
1119
1251
  }
1120
- 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
+ }
1121
1362
  if (immediately) {
1122
- 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
+ }
1123
1392
  }
1124
1393
  else {
1125
- this.scheduleWrite(property, value);
1394
+ this.scheduleWrite(property, value, effectiveDelegateId);
1126
1395
  }
1127
1396
  }
1128
1397
  async setDefaultPropertyValue(deviceId, property, value) {
@@ -1142,6 +1411,87 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1142
1411
  }
1143
1412
  set.add(property.id);
1144
1413
  }
1414
+ async wireElectricalChannels(delegate, device, comp) {
1415
+ if (typeof comp.aenergy !== 'undefined') {
1416
+ const electricalEnergy = await this.channelsService.findOneBy('identifier', `energy:${comp.id}`, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
1417
+ if (electricalEnergy === null) {
1418
+ }
1419
+ else {
1420
+ const consumption = await this.channelsPropertiesService.findOneBy('identifier', 'aenergy', electricalEnergy.id);
1421
+ if (consumption === null) {
1422
+ }
1423
+ else {
1424
+ await this.setDefaultPropertyValue(device.id, consumption, (0, transform_utils_2.toEnergy)(comp.aenergy));
1425
+ this.changeHandlers.set(`${delegate.id}|${comp.key}|aenergy.total`, (val) => {
1426
+ this.handleNumericChange(comp.key, 'aenergy.total', consumption.id, val, (n) => this.handleChange(consumption, (0, transform_utils_2.toEnergy)(n), false));
1427
+ });
1428
+ }
1429
+ }
1430
+ }
1431
+ if (typeof comp.apower !== 'undefined' ||
1432
+ typeof comp.voltage !== 'undefined' ||
1433
+ typeof comp.current !== 'undefined') {
1434
+ const electricalPower = await this.channelsService.findOneBy('identifier', `power:${comp.id}`, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
1435
+ if (electricalPower === null) {
1436
+ }
1437
+ else {
1438
+ if (typeof comp.apower !== 'undefined') {
1439
+ const power = await this.channelsPropertiesService.findOneBy('identifier', 'apower', electricalPower.id);
1440
+ if (power === null) {
1441
+ }
1442
+ else {
1443
+ await this.setDefaultPropertyValue(device.id, power, Math.max(0, comp.apower));
1444
+ this.changeHandlers.set(`${delegate.id}|${comp.key}|apower`, (val) => {
1445
+ this.handleNumericChange(comp.key, 'apower', power.id, val, (n) => this.handleChange(power, Math.max(0, n), false));
1446
+ });
1447
+ }
1448
+ }
1449
+ if (typeof comp.voltage !== 'undefined') {
1450
+ const voltage = await this.channelsPropertiesService.findOneBy('identifier', 'voltage', electricalPower.id);
1451
+ if (voltage === null) {
1452
+ }
1453
+ else {
1454
+ await this.setDefaultPropertyValue(device.id, voltage, comp.voltage);
1455
+ this.changeHandlers.set(`${delegate.id}|${comp.key}|voltage`, (val) => {
1456
+ this.handleNumericChange(comp.key, 'voltage', voltage.id, val, (n) => this.handleChange(voltage, n, false));
1457
+ });
1458
+ }
1459
+ }
1460
+ if (typeof comp.current !== 'undefined') {
1461
+ const current = await this.channelsPropertiesService.findOneBy('identifier', 'current', electricalPower.id);
1462
+ if (current === null) {
1463
+ }
1464
+ else {
1465
+ await this.setDefaultPropertyValue(device.id, current, comp.current);
1466
+ this.changeHandlers.set(`${delegate.id}|${comp.key}|current`, (val) => {
1467
+ this.handleNumericChange(comp.key, 'current', current.id, val, (n) => this.handleChange(current, n, false));
1468
+ });
1469
+ }
1470
+ }
1471
+ }
1472
+ }
1473
+ }
1474
+ async wireMeterProperty(delegate, device, compKey, channelIdentifier, attr, propertyIdentifier, value, allowNull) {
1475
+ if (typeof value === 'undefined') {
1476
+ return;
1477
+ }
1478
+ const channel = await this.channelsService.findOneBy('identifier', channelIdentifier, device.id, devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE);
1479
+ if (channel === null) {
1480
+ return;
1481
+ }
1482
+ const property = await this.channelsPropertiesService.findOneBy('identifier', propertyIdentifier, channel.id);
1483
+ if (property === null) {
1484
+ return;
1485
+ }
1486
+ if (value !== null) {
1487
+ await this.setDefaultPropertyValue(device.id, property, value);
1488
+ }
1489
+ this.changeHandlers.set(`${delegate.id}|${compKey}|${attr}`, (val) => {
1490
+ this.handleNumericChange(compKey, attr, property.id, val, (n) => this.handleChange(property, n, false), {
1491
+ allowNull,
1492
+ });
1493
+ });
1494
+ }
1145
1495
  determineCategory(delegate) {
1146
1496
  if (delegate.descriptor && delegate.descriptor.categories.length > 0) {
1147
1497
  return delegate.descriptor.categories[0];
@@ -1164,6 +1514,9 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1164
1514
  return devices_constants_1.DeviceCategory.GENERIC;
1165
1515
  }
1166
1516
  handleNumericChange(compKey, attr, propertyId, val, write, opts) {
1517
+ if (val === null && opts?.allowNull) {
1518
+ return;
1519
+ }
1167
1520
  const n = (0, transform_utils_1.coerceNumberSafe)(val, opts);
1168
1521
  if (n === null || Number.isNaN(n)) {
1169
1522
  this.logger.warn(`Dropping invalid numeric update for ${compKey}.${attr} -> ${(0, transform_utils_1.safeToString)(val)} (property=${propertyId})`);
@@ -1176,10 +1529,21 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1176
1529
  });
1177
1530
  });
1178
1531
  }
1179
- scheduleWrite(property, value) {
1532
+ scheduleWrite(property, value, delegateId) {
1180
1533
  const existing = this.pendingWrites.get(property.id);
1181
1534
  if (existing) {
1182
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);
1183
1547
  }
1184
1548
  const t = setTimeout(() => {
1185
1549
  const current = this.pendingWrites.get(property.id);
@@ -1187,15 +1551,301 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1187
1551
  clearTimeout(current);
1188
1552
  this.pendingWrites.delete(property.id);
1189
1553
  }
1190
- this.writeValueToProperty(property, value).catch((err) => {
1191
- 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 });
1192
- });
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
+ }
1193
1591
  }, 250);
1194
1592
  this.pendingWrites.set(property.id, t);
1195
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
+ }
1196
1846
  async writeValueToProperty(property, value) {
1197
1847
  return await this.channelsPropertiesService.update(property.id, (0, transform_utils_1.toInstance)(update_channel_property_dto_1.UpdateShellyNgChannelPropertyDto, {
1198
- ...(0, class_transformer_1.instanceToPlain)(property),
1848
+ type: devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_TYPE,
1199
1849
  value,
1200
1850
  }));
1201
1851
  }
@@ -1229,7 +1879,8 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1229
1879
  }
1230
1880
  return fallback;
1231
1881
  }
1232
- detach() {
1882
+ async detach() {
1883
+ const teardownPromises = [];
1233
1884
  for (const [, delegate] of this.delegates.entries()) {
1234
1885
  const valueHandler = this.delegateValueHandlers.get(delegate.id);
1235
1886
  const connectionHandler = this.delegateConnectionHandlers.get(delegate.id);
@@ -1239,19 +1890,41 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1239
1890
  if (connectionHandler) {
1240
1891
  delegate.off('connected', connectionHandler);
1241
1892
  }
1893
+ teardownPromises.push(this.teardownDelegateEvents(delegate));
1894
+ }
1895
+ for (const pendingWrite of this.pendingWrites.values()) {
1896
+ clearTimeout(pendingWrite);
1242
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();
1243
1915
  this.delegates.clear();
1244
1916
  this.delegateValueHandlers.clear();
1245
1917
  this.delegateConnectionHandlers.clear();
1918
+ this.delegateEventHandlers.clear();
1919
+ this.delegateEventQueues.clear();
1920
+ this.delegateEventGenerations.clear();
1246
1921
  this.delegateDeviceIds.clear();
1247
1922
  this.changeHandlers.clear();
1248
1923
  this.setPropertiesHandlers.clear();
1249
1924
  this.setChannelsHandlers.clear();
1250
1925
  this.propertiesMap.clear();
1251
- for (const pendingWrite of this.pendingWrites.values()) {
1252
- clearTimeout(pendingWrite);
1253
- }
1254
- this.pendingWrites.clear();
1926
+ this.delegatePollGenerations.clear();
1927
+ this.currentValueUpdateContext = null;
1255
1928
  this.deviceLocks.clear();
1256
1929
  this.canonicalMacLocks.clear();
1257
1930
  this.connectedDelegatesPerDevice.clear();
@@ -1264,8 +1937,8 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1264
1937
  this.delegateConnectedState.clear();
1265
1938
  this.insertGeneration.clear();
1266
1939
  }
1267
- destroy() {
1268
- this.detach();
1940
+ async destroy() {
1941
+ await this.detach();
1269
1942
  }
1270
1943
  async checkHealth(pingTimeoutMs = 5_000) {
1271
1944
  const CONCURRENCY = 10;
@@ -1295,20 +1968,47 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
1295
1968
  await Promise.all(tasks.slice(i, i + CONCURRENCY).map((fn) => fn()));
1296
1969
  }
1297
1970
  }
1298
- async pollAllDevices(timeoutMs = 10_000) {
1299
- const CONCURRENCY = 10;
1300
- const tasks = [];
1301
- for (const [id, delegate] of this.delegates.entries()) {
1302
- if (!delegate.connected) {
1303
- continue;
1304
- }
1305
- tasks.push(async () => {
1306
- const ok = await delegate.pollStatus(timeoutMs);
1307
- if (!ok) {
1308
- this.logger.warn(`Status poll failed for device=${id}`);
1309
- }
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',
1310
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}`);
1311
2007
  }
2008
+ }
2009
+ async pollAllDevices(timeoutMs = 10_000) {
2010
+ const CONCURRENCY = 10;
2011
+ const tasks = this.getConnectedDelegateIds().map((id) => () => this.pollDevice(id, timeoutMs));
1312
2012
  for (let i = 0; i < tasks.length; i += CONCURRENCY) {
1313
2013
  await Promise.all(tasks.slice(i, i + CONCURRENCY).map((fn) => fn()));
1314
2014
  }
@@ -1357,6 +2057,9 @@ exports.DelegatesManagerService = DelegatesManagerService;
1357
2057
  DelegatesManagerService.DISCONNECT_GRACE_MS = 15_000;
1358
2058
  exports.DelegatesManagerService = DelegatesManagerService = DelegatesManagerService_1 = __decorate([
1359
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)()),
1360
2063
  __metadata("design:paramtypes", [devices_service_1.DevicesService,
1361
2064
  channels_service_1.ChannelsService,
1362
2065
  channels_properties_service_1.ChannelsPropertiesService,
@@ -1364,6 +2067,9 @@ exports.DelegatesManagerService = DelegatesManagerService = DelegatesManagerServ
1364
2067
  device_manager_service_1.DeviceManagerService,
1365
2068
  device_address_service_1.DeviceAddressService,
1366
2069
  mappings_1.PropertyMappingStorageService,
1367
- 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])
1368
2074
  ], DelegatesManagerService);
1369
2075
  //# sourceMappingURL=delegates-manager.service.js.map