@fastybird/smart-panel-backend 1.1.0-alpha.12 → 1.1.0-alpha.13
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.
- package/dist/migrations/1000000000026-AddHardwareInputCategories.d.ts +7 -0
- package/dist/migrations/1000000000026-AddHardwareInputCategories.js +364 -0
- package/dist/migrations/1000000000026-AddHardwareInputCategories.js.map +1 -0
- package/dist/modules/devices/controllers/channels.controller.d.ts +5 -1
- package/dist/modules/devices/controllers/channels.controller.js +34 -2
- package/dist/modules/devices/controllers/channels.controller.js.map +1 -1
- package/dist/modules/devices/controllers/channels.properties.controller.js +5 -0
- package/dist/modules/devices/controllers/channels.properties.controller.js.map +1 -1
- package/dist/modules/devices/controllers/devices.channels.controller.d.ts +5 -1
- package/dist/modules/devices/controllers/devices.channels.controller.js +38 -2
- package/dist/modules/devices/controllers/devices.channels.controller.js.map +1 -1
- package/dist/modules/devices/controllers/devices.channels.properties.controller.js +5 -0
- package/dist/modules/devices/controllers/devices.channels.properties.controller.js.map +1 -1
- package/dist/modules/devices/devices.constants.d.ts +6 -0
- package/dist/modules/devices/devices.constants.js +6 -0
- package/dist/modules/devices/devices.constants.js.map +1 -1
- package/dist/modules/devices/devices.module.js +6 -0
- package/dist/modules/devices/devices.module.js.map +1 -1
- package/dist/modules/devices/devices.openapi.d.ts +3 -1
- package/dist/modules/devices/devices.openapi.js +7 -0
- package/dist/modules/devices/devices.openapi.js.map +1 -1
- package/dist/modules/devices/dto/channel-input-occurrence.dto.d.ts +10 -0
- package/dist/modules/devices/dto/channel-input-occurrence.dto.js +99 -0
- package/dist/modules/devices/dto/channel-input-occurrence.dto.js.map +1 -0
- package/dist/modules/devices/models/channel-input-capabilities.model.d.ts +20 -0
- package/dist/modules/devices/models/channel-input-capabilities.model.js +111 -0
- package/dist/modules/devices/models/channel-input-capabilities.model.js.map +1 -0
- package/dist/modules/devices/models/channel-input-occurrence.model.d.ts +22 -0
- package/dist/modules/devices/models/channel-input-occurrence.model.js +154 -0
- package/dist/modules/devices/models/channel-input-occurrence.model.js.map +1 -0
- package/dist/modules/devices/services/channel-input-deduplication.service.d.ts +17 -0
- package/dist/modules/devices/services/channel-input-deduplication.service.js +88 -0
- package/dist/modules/devices/services/channel-input-deduplication.service.js.map +1 -0
- package/dist/modules/devices/services/channel-input-occurrences.service.d.ts +21 -0
- package/dist/modules/devices/services/channel-input-occurrences.service.js +163 -0
- package/dist/modules/devices/services/channel-input-occurrences.service.js.map +1 -0
- package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.d.ts +19 -3
- package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js +514 -50
- package/dist/plugins/devices-shelly-ng/delegates/delegates-manager.service.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.d.ts +2 -0
- package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js +10 -2
- package/dist/plugins/devices-shelly-ng/delegates/shelly-device.delegate.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/devices-shelly-ng.constants.js +3 -2
- package/dist/plugins/devices-shelly-ng/devices-shelly-ng.constants.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/mappings/definitions/inputs.yaml +80 -0
- package/dist/plugins/devices-shelly-ng/mappings/mapping-loader.service.js +7 -1
- package/dist/plugins/devices-shelly-ng/mappings/mapping-loader.service.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/mappings/mapping.types.d.ts +6 -3
- package/dist/plugins/devices-shelly-ng/mappings/schema/mapping-schema.json +5 -0
- package/dist/plugins/devices-shelly-ng/services/device-manager.service.js +130 -7
- package/dist/plugins/devices-shelly-ng/services/device-manager.service.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/services/poll-placement-diagnostics.service.js +3 -2
- package/dist/plugins/devices-shelly-ng/services/poll-placement-diagnostics.service.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js +1 -1
- package/dist/plugins/devices-shelly-ng/services/shelly-ng.service.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/services/shelly-rpc-client.service.js +3 -0
- package/dist/plugins/devices-shelly-ng/services/shelly-rpc-client.service.js.map +1 -1
- package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.d.ts +1 -0
- package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.js +13 -1
- package/dist/plugins/devices-shelly-ng/services/shelly-ws-server.service.js.map +1 -1
- package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.d.ts +2 -0
- package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.js +66 -4
- package/dist/plugins/devices-shelly-v1/devices-shelly-v1.constants.js.map +1 -1
- package/dist/plugins/devices-shelly-v1/devices-shelly-v1.plugin.js +2 -0
- package/dist/plugins/devices-shelly-v1/devices-shelly-v1.plugin.js.map +1 -1
- package/dist/plugins/devices-shelly-v1/platforms/shelly-v1.device.platform.js +7 -0
- package/dist/plugins/devices-shelly-v1/platforms/shelly-v1.device.platform.js.map +1 -1
- package/dist/plugins/devices-shelly-v1/services/device-mapper.service.d.ts +3 -1
- package/dist/plugins/devices-shelly-v1/services/device-mapper.service.js +20 -2
- package/dist/plugins/devices-shelly-v1/services/device-mapper.service.js.map +1 -1
- package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.d.ts +16 -0
- package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.js +107 -0
- package/dist/plugins/devices-shelly-v1/services/shelly-v1-input-tracker.service.js.map +1 -0
- package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.d.ts +7 -1
- package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.js +98 -3
- package/dist/plugins/devices-shelly-v1/services/shelly-v1.service.js.map +1 -1
- package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.d.ts +3 -0
- package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.js +41 -5
- package/dist/plugins/devices-zigbee2mqtt/devices-zigbee2mqtt.constants.js.map +1 -1
- package/dist/plugins/devices-zigbee2mqtt/interfaces/zigbee2mqtt.interface.d.ts +7 -1
- package/dist/plugins/devices-zigbee2mqtt/mappings/config-driven.converter.js +16 -15
- package/dist/plugins/devices-zigbee2mqtt/mappings/config-driven.converter.js.map +1 -1
- package/dist/plugins/devices-zigbee2mqtt/mappings/definitions/remotes.yaml +505 -74
- package/dist/plugins/devices-zigbee2mqtt/mappings/schema/mapping-schema.json +3 -3
- package/dist/plugins/devices-zigbee2mqtt/mappings/transformers/transformer.types.d.ts +1 -1
- package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.d.ts +8 -2
- package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.js +6 -5
- package/dist/plugins/devices-zigbee2mqtt/services/base-client-adapter.js.map +1 -1
- package/dist/plugins/devices-zigbee2mqtt/services/device-adoption.service.js +18 -11
- package/dist/plugins/devices-zigbee2mqtt/services/device-adoption.service.js.map +1 -1
- package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.d.ts +9 -3
- package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.js +166 -3
- package/dist/plugins/devices-zigbee2mqtt/services/device-mapper.service.js.map +1 -1
- package/dist/plugins/devices-zigbee2mqtt/services/mqtt-client-adapter.service.js +5 -2
- package/dist/plugins/devices-zigbee2mqtt/services/mqtt-client-adapter.service.js.map +1 -1
- package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.d.ts +1 -0
- package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.js +44 -4
- package/dist/plugins/devices-zigbee2mqtt/services/zigbee2mqtt.service.js.map +1 -1
- package/dist/spec/channels.d.ts +51 -1
- package/dist/spec/channels.js +64 -1
- package/dist/spec/channels.js.map +1 -1
- package/dist/spec/devices.d.ts +155 -2
- package/dist/spec/devices.js +161 -2
- package/dist/spec/devices.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -18,6 +18,7 @@ const common_1 = require("@nestjs/common");
|
|
|
18
18
|
const logger_1 = require("../../../common/logger");
|
|
19
19
|
const transform_utils_1 = require("../../../common/utils/transform.utils");
|
|
20
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");
|
|
21
22
|
const channels_properties_service_1 = require("../../../modules/devices/services/channels.properties.service");
|
|
22
23
|
const channels_service_1 = require("../../../modules/devices/services/channels.service");
|
|
23
24
|
const command_latency_trace_collector_service_1 = require("../../../modules/devices/services/command-latency-trace-collector.service");
|
|
@@ -33,8 +34,17 @@ const device_manager_service_1 = require("../services/device-manager.service");
|
|
|
33
34
|
const poll_placement_diagnostics_service_1 = require("../services/poll-placement-diagnostics.service");
|
|
34
35
|
const transform_utils_2 = require("../utils/transform.utils");
|
|
35
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
|
+
};
|
|
36
46
|
let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManagerService {
|
|
37
|
-
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()) {
|
|
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) {
|
|
38
48
|
this.devicesService = devicesService;
|
|
39
49
|
this.channelsService = channelsService;
|
|
40
50
|
this.channelsPropertiesService = channelsPropertiesService;
|
|
@@ -45,16 +55,24 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
45
55
|
this.transformerRegistry = transformerRegistry;
|
|
46
56
|
this.commandLatencyTraceCollector = commandLatencyTraceCollector;
|
|
47
57
|
this.pollPlacementDiagnostics = pollPlacementDiagnostics;
|
|
58
|
+
this.channelInputOccurrencesService = channelInputOccurrencesService;
|
|
48
59
|
this.logger = (0, logger_1.createExtensionLogger)(devices_shelly_ng_constants_1.DEVICES_SHELLY_NG_PLUGIN_NAME, 'DelegatesManagerService');
|
|
49
60
|
this.delegates = new Map();
|
|
50
61
|
this.delegateValueHandlers = new Map();
|
|
51
62
|
this.delegateConnectionHandlers = new Map();
|
|
63
|
+
this.delegateEventHandlers = new Map();
|
|
64
|
+
this.delegateEventQueues = new Map();
|
|
65
|
+
this.delegateEventGenerations = new Map();
|
|
52
66
|
this.changeHandlers = new Map();
|
|
53
67
|
this.setChannelsHandlers = new Map();
|
|
54
68
|
this.setPropertiesHandlers = new Map();
|
|
55
69
|
this.pendingWrites = new Map();
|
|
70
|
+
this.delegatePendingWrites = new Map();
|
|
71
|
+
this.delegateActiveWrites = new Map();
|
|
56
72
|
this.pendingPollWrites = new Map();
|
|
57
73
|
this.activePollWrites = new Map();
|
|
74
|
+
this.activePollDrainPromises = new Map();
|
|
75
|
+
this.delegatePollDeviceIds = new Map();
|
|
58
76
|
this.delegatePollGenerations = new Map();
|
|
59
77
|
this.currentValueUpdateContext = null;
|
|
60
78
|
this.propertiesMap = new Map();
|
|
@@ -77,7 +95,7 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
77
95
|
async performInsert(shelly, force = false) {
|
|
78
96
|
if (this.delegates.has(shelly.id)) {
|
|
79
97
|
if (force) {
|
|
80
|
-
this.performRemove(shelly.id);
|
|
98
|
+
await this.performRemove(shelly.id);
|
|
81
99
|
}
|
|
82
100
|
else {
|
|
83
101
|
return this.delegates.get(shelly.id);
|
|
@@ -823,6 +841,73 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
823
841
|
await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, 'total_act_energy', 'total_act_energy', comp.total_act_energy, false);
|
|
824
842
|
await this.wireMeterProperty(delegate, device, comp.key, channelIdentifier, 'total_act_ret_energy', 'total_act_ret_energy', comp.total_act_ret_energy, false);
|
|
825
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) {
|
|
849
|
+
continue;
|
|
850
|
+
}
|
|
851
|
+
if (channel.category === devices_constants_1.ChannelCategory.BUTTON) {
|
|
852
|
+
const detectedProp = await this.channelsPropertiesService.findOneBy('category', devices_constants_1.PropertyCategory.DETECTED, channel.id);
|
|
853
|
+
if (detectedProp) {
|
|
854
|
+
await this.setDefaultPropertyValue(device.id, detectedProp, Boolean(comp.state));
|
|
855
|
+
this.changeHandlers.set(`${delegate.id}|${comp.key}|state`, (val) => {
|
|
856
|
+
if (typeof val === 'boolean') {
|
|
857
|
+
this.handleChange(detectedProp, val, false).catch((err) => {
|
|
858
|
+
this.logger.error(`Failed to update detected for ${detectedProp.id}: ${err.message}`);
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
else if (channel.category === devices_constants_1.ChannelCategory.BINARY_INPUT) {
|
|
865
|
+
const stateProp = await this.channelsPropertiesService.findOneBy('category', devices_constants_1.PropertyCategory.STATE, channel.id);
|
|
866
|
+
if (stateProp) {
|
|
867
|
+
await this.setDefaultPropertyValue(device.id, stateProp, Boolean(comp.state));
|
|
868
|
+
this.changeHandlers.set(`${delegate.id}|${comp.key}|state`, (val) => {
|
|
869
|
+
if (typeof val === 'boolean') {
|
|
870
|
+
this.handleChange(stateProp, val, false).catch((err) => {
|
|
871
|
+
this.logger.error(`Failed to update state for ${stateProp.id}: ${err.message}`);
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
else if (channel.category === devices_constants_1.ChannelCategory.ANALOG_INPUT) {
|
|
878
|
+
const valueProp = await this.channelsPropertiesService.findOneBy('category', devices_constants_1.PropertyCategory.VALUE, channel.id);
|
|
879
|
+
if (valueProp) {
|
|
880
|
+
const hasExtendedPercent = typeof comp.xpercent === 'number';
|
|
881
|
+
const hasExtendedCount = typeof comp.counts?.xtotal === 'number';
|
|
882
|
+
let initialVal;
|
|
883
|
+
if (comp.counts !== undefined) {
|
|
884
|
+
initialVal = hasExtendedCount ? comp.counts.xtotal : (comp.counts.total ?? 0);
|
|
885
|
+
}
|
|
886
|
+
else {
|
|
887
|
+
initialVal = hasExtendedPercent ? comp.xpercent : (comp.percent ?? 0);
|
|
888
|
+
}
|
|
889
|
+
await this.setDefaultPropertyValue(device.id, valueProp, initialVal);
|
|
890
|
+
const percentAttr = hasExtendedPercent ? 'xpercent' : 'percent';
|
|
891
|
+
this.changeHandlers.set(`${delegate.id}|${comp.key}|${percentAttr}`, (val) => {
|
|
892
|
+
const n = (0, transform_utils_1.coerceNumberSafe)(val);
|
|
893
|
+
if (n !== null) {
|
|
894
|
+
this.handleChange(valueProp, n, false).catch((err) => {
|
|
895
|
+
this.logger.error(`Failed to update value for ${valueProp.id}: ${err.message}`);
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
const countAttr = hasExtendedCount ? 'counts.xtotal' : 'counts.total';
|
|
900
|
+
this.changeHandlers.set(`${delegate.id}|${comp.key}|${countAttr}`, (val) => {
|
|
901
|
+
const n = (0, transform_utils_1.coerceNumberSafe)(val);
|
|
902
|
+
if (n !== null) {
|
|
903
|
+
this.handleChange(valueProp, n, false).catch((err) => {
|
|
904
|
+
this.logger.error(`Failed to update counts for ${valueProp.id}: ${err.message}`);
|
|
905
|
+
});
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
826
911
|
if (this.insertGeneration.get(shelly.id) !== generation)
|
|
827
912
|
return delegate;
|
|
828
913
|
const valueHandler = (compKey, attr, val, origin = 'notify') => {
|
|
@@ -955,6 +1040,34 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
955
1040
|
};
|
|
956
1041
|
delegate.on('connected', connectionHandler);
|
|
957
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);
|
|
958
1071
|
if (delegate.connected) {
|
|
959
1072
|
connectionHandler(true);
|
|
960
1073
|
}
|
|
@@ -962,19 +1075,45 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
962
1075
|
return delegate;
|
|
963
1076
|
}
|
|
964
1077
|
remove(deviceId) {
|
|
965
|
-
return this.withDeviceLock(deviceId, () =>
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
1078
|
+
return this.withDeviceLock(deviceId, () => this.performRemove(deviceId));
|
|
1079
|
+
}
|
|
1080
|
+
async teardownDelegateEvents(delegate) {
|
|
1081
|
+
const eventHandler = this.delegateEventHandlers.get(delegate.id);
|
|
1082
|
+
if (eventHandler) {
|
|
1083
|
+
delegate.off('event', eventHandler);
|
|
1084
|
+
}
|
|
1085
|
+
const pendingQueue = this.delegateEventQueues.get(delegate.id);
|
|
1086
|
+
this.delegateEventHandlers.delete(delegate.id);
|
|
1087
|
+
this.delegateEventQueues.delete(delegate.id);
|
|
1088
|
+
this.delegateEventGenerations.set(delegate.id, (this.delegateEventGenerations.get(delegate.id) ?? 0) + 1);
|
|
1089
|
+
if (pendingQueue !== undefined) {
|
|
1090
|
+
try {
|
|
1091
|
+
await pendingQueue;
|
|
1092
|
+
}
|
|
1093
|
+
catch (err) {
|
|
1094
|
+
this.logger.error(`Error while awaiting event queue teardown for delegate=${delegate.id}`, {
|
|
1095
|
+
message: err.message,
|
|
1096
|
+
stack: err.stack,
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
969
1100
|
}
|
|
970
|
-
performRemove(deviceId) {
|
|
1101
|
+
async performRemove(deviceId) {
|
|
971
1102
|
const delegate = this.delegates.get(deviceId);
|
|
972
1103
|
if (!delegate) {
|
|
973
1104
|
return;
|
|
974
1105
|
}
|
|
1106
|
+
const valueHandler = this.delegateValueHandlers.get(delegate.id);
|
|
1107
|
+
if (valueHandler) {
|
|
1108
|
+
delegate.off('value', valueHandler);
|
|
1109
|
+
this.delegateValueHandlers.delete(delegate.id);
|
|
1110
|
+
}
|
|
975
1111
|
this.delegatePollGenerations.set(deviceId, (this.delegatePollGenerations.get(deviceId) ?? 0) + 1);
|
|
976
1112
|
this.cancelPollWritesForDelegate(deviceId);
|
|
977
|
-
|
|
1113
|
+
this.cancelPendingWritesForDelegate(deviceId);
|
|
1114
|
+
await this.teardownDelegateEvents(delegate);
|
|
1115
|
+
await this.awaitActiveWritesForDelegate(deviceId);
|
|
1116
|
+
await this.awaitActivePollDrainsForDelegate(deviceId);
|
|
978
1117
|
const connectionHandler = this.delegateConnectionHandlers.get(delegate.id);
|
|
979
1118
|
if (connectionHandler) {
|
|
980
1119
|
connectionHandler(null);
|
|
@@ -997,14 +1136,10 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
997
1136
|
});
|
|
998
1137
|
}
|
|
999
1138
|
}
|
|
1000
|
-
if (valueHandler) {
|
|
1001
|
-
delegate.off('value', valueHandler);
|
|
1002
|
-
}
|
|
1003
1139
|
if (connectionHandler) {
|
|
1004
1140
|
delegate.off('connected', connectionHandler);
|
|
1141
|
+
this.delegateConnectionHandlers.delete(delegate.id);
|
|
1005
1142
|
}
|
|
1006
|
-
this.delegateValueHandlers.delete(delegate.id);
|
|
1007
|
-
this.delegateConnectionHandlers.delete(delegate.id);
|
|
1008
1143
|
for (const key of Array.from(this.changeHandlers.keys())) {
|
|
1009
1144
|
if (key.startsWith(`${deviceId}|`)) {
|
|
1010
1145
|
this.changeHandlers.delete(key);
|
|
@@ -1046,6 +1181,10 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1046
1181
|
this.delegateToIdentifier.delete(deviceId);
|
|
1047
1182
|
this.pollPlacementDiagnostics.removeDelegate(deviceId);
|
|
1048
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);
|
|
1049
1188
|
this.delegates.delete(deviceId);
|
|
1050
1189
|
this.logger.log(`Detached Shelly device=${deviceId}`, { resource: deviceId });
|
|
1051
1190
|
}
|
|
@@ -1110,8 +1249,102 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1110
1249
|
return value;
|
|
1111
1250
|
}
|
|
1112
1251
|
}
|
|
1113
|
-
async
|
|
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) {
|
|
1114
1346
|
const context = this.currentValueUpdateContext;
|
|
1347
|
+
const effectiveDelegateId = delegateId ?? context?.delegateId;
|
|
1115
1348
|
if (context !== null) {
|
|
1116
1349
|
this.commandLatencyTraceCollector.recordProviderReceipt(property.id, value, context.origin, {
|
|
1117
1350
|
delegateId: context.delegateId,
|
|
@@ -1129,10 +1362,36 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1129
1362
|
if (immediately) {
|
|
1130
1363
|
this.cancelScheduledWrite(property.id);
|
|
1131
1364
|
this.cancelPollWrite(property.id);
|
|
1132
|
-
|
|
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
|
+
}
|
|
1133
1392
|
}
|
|
1134
1393
|
else {
|
|
1135
|
-
this.scheduleWrite(property, value);
|
|
1394
|
+
this.scheduleWrite(property, value, effectiveDelegateId);
|
|
1136
1395
|
}
|
|
1137
1396
|
}
|
|
1138
1397
|
async setDefaultPropertyValue(deviceId, property, value) {
|
|
@@ -1270,10 +1529,21 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1270
1529
|
});
|
|
1271
1530
|
});
|
|
1272
1531
|
}
|
|
1273
|
-
scheduleWrite(property, value) {
|
|
1532
|
+
scheduleWrite(property, value, delegateId) {
|
|
1274
1533
|
const existing = this.pendingWrites.get(property.id);
|
|
1275
1534
|
if (existing) {
|
|
1276
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);
|
|
1277
1547
|
}
|
|
1278
1548
|
const t = setTimeout(() => {
|
|
1279
1549
|
const current = this.pendingWrites.get(property.id);
|
|
@@ -1281,13 +1551,53 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1281
1551
|
clearTimeout(current);
|
|
1282
1552
|
this.pendingWrites.delete(property.id);
|
|
1283
1553
|
}
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
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
|
+
}
|
|
1287
1591
|
}, 250);
|
|
1288
1592
|
this.pendingWrites.set(property.id, t);
|
|
1289
1593
|
}
|
|
1290
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);
|
|
1291
1601
|
let bucket = this.pendingPollWrites.get(context.deviceId);
|
|
1292
1602
|
if (!bucket) {
|
|
1293
1603
|
const values = new Map();
|
|
@@ -1317,32 +1627,53 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1317
1627
|
this.activePollWrites.set(deviceId, activeBuckets);
|
|
1318
1628
|
}
|
|
1319
1629
|
activeBuckets.add(bucket);
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
(this.
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
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
|
+
}
|
|
1335
1651
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1652
|
+
}
|
|
1653
|
+
finally {
|
|
1654
|
+
activeBuckets.delete(bucket);
|
|
1655
|
+
if (activeBuckets.size === 0 && this.activePollWrites.get(deviceId) === activeBuckets) {
|
|
1656
|
+
this.activePollWrites.delete(deviceId);
|
|
1339
1657
|
}
|
|
1340
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;
|
|
1341
1669
|
}
|
|
1342
1670
|
finally {
|
|
1343
|
-
|
|
1344
|
-
if (
|
|
1345
|
-
|
|
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
|
+
}
|
|
1346
1677
|
}
|
|
1347
1678
|
}
|
|
1348
1679
|
}
|
|
@@ -1352,6 +1683,117 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1352
1683
|
clearTimeout(timer);
|
|
1353
1684
|
this.pendingWrites.delete(propertyId);
|
|
1354
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
|
+
}
|
|
1355
1797
|
}
|
|
1356
1798
|
cancelPollWrite(propertyId) {
|
|
1357
1799
|
for (const [deviceId, bucket] of this.pendingPollWrites.entries()) {
|
|
@@ -1437,7 +1879,8 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1437
1879
|
}
|
|
1438
1880
|
return fallback;
|
|
1439
1881
|
}
|
|
1440
|
-
detach() {
|
|
1882
|
+
async detach() {
|
|
1883
|
+
const teardownPromises = [];
|
|
1441
1884
|
for (const [, delegate] of this.delegates.entries()) {
|
|
1442
1885
|
const valueHandler = this.delegateValueHandlers.get(delegate.id);
|
|
1443
1886
|
const connectionHandler = this.delegateConnectionHandlers.get(delegate.id);
|
|
@@ -1447,20 +1890,39 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1447
1890
|
if (connectionHandler) {
|
|
1448
1891
|
delegate.off('connected', connectionHandler);
|
|
1449
1892
|
}
|
|
1893
|
+
teardownPromises.push(this.teardownDelegateEvents(delegate));
|
|
1894
|
+
}
|
|
1895
|
+
for (const pendingWrite of this.pendingWrites.values()) {
|
|
1896
|
+
clearTimeout(pendingWrite);
|
|
1897
|
+
}
|
|
1898
|
+
this.pendingWrites.clear();
|
|
1899
|
+
this.delegatePendingWrites.clear();
|
|
1900
|
+
for (const bucket of this.pendingPollWrites.values()) {
|
|
1901
|
+
clearTimeout(bucket.timer);
|
|
1450
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();
|
|
1451
1915
|
this.delegates.clear();
|
|
1452
1916
|
this.delegateValueHandlers.clear();
|
|
1453
1917
|
this.delegateConnectionHandlers.clear();
|
|
1918
|
+
this.delegateEventHandlers.clear();
|
|
1919
|
+
this.delegateEventQueues.clear();
|
|
1920
|
+
this.delegateEventGenerations.clear();
|
|
1454
1921
|
this.delegateDeviceIds.clear();
|
|
1455
1922
|
this.changeHandlers.clear();
|
|
1456
1923
|
this.setPropertiesHandlers.clear();
|
|
1457
1924
|
this.setChannelsHandlers.clear();
|
|
1458
1925
|
this.propertiesMap.clear();
|
|
1459
|
-
for (const pendingWrite of this.pendingWrites.values()) {
|
|
1460
|
-
clearTimeout(pendingWrite);
|
|
1461
|
-
}
|
|
1462
|
-
this.pendingWrites.clear();
|
|
1463
|
-
this.clearPollWrites();
|
|
1464
1926
|
this.delegatePollGenerations.clear();
|
|
1465
1927
|
this.currentValueUpdateContext = null;
|
|
1466
1928
|
this.deviceLocks.clear();
|
|
@@ -1475,8 +1937,8 @@ let DelegatesManagerService = DelegatesManagerService_1 = class DelegatesManager
|
|
|
1475
1937
|
this.delegateConnectedState.clear();
|
|
1476
1938
|
this.insertGeneration.clear();
|
|
1477
1939
|
}
|
|
1478
|
-
destroy() {
|
|
1479
|
-
this.detach();
|
|
1940
|
+
async destroy() {
|
|
1941
|
+
await this.detach();
|
|
1480
1942
|
}
|
|
1481
1943
|
async checkHealth(pingTimeoutMs = 5_000) {
|
|
1482
1944
|
const CONCURRENCY = 10;
|
|
@@ -1597,6 +2059,7 @@ exports.DelegatesManagerService = DelegatesManagerService = DelegatesManagerServ
|
|
|
1597
2059
|
(0, common_1.Injectable)(),
|
|
1598
2060
|
__param(8, (0, common_1.Optional)()),
|
|
1599
2061
|
__param(9, (0, common_1.Optional)()),
|
|
2062
|
+
__param(10, (0, common_1.Optional)()),
|
|
1600
2063
|
__metadata("design:paramtypes", [devices_service_1.DevicesService,
|
|
1601
2064
|
channels_service_1.ChannelsService,
|
|
1602
2065
|
channels_properties_service_1.ChannelsPropertiesService,
|
|
@@ -1606,6 +2069,7 @@ exports.DelegatesManagerService = DelegatesManagerService = DelegatesManagerServ
|
|
|
1606
2069
|
mappings_1.PropertyMappingStorageService,
|
|
1607
2070
|
mappings_1.TransformerRegistry,
|
|
1608
2071
|
command_latency_trace_collector_service_1.CommandLatencyTraceCollectorService,
|
|
1609
|
-
poll_placement_diagnostics_service_1.PollPlacementDiagnosticsService
|
|
2072
|
+
poll_placement_diagnostics_service_1.PollPlacementDiagnosticsService,
|
|
2073
|
+
channel_input_occurrences_service_1.ChannelInputOccurrencesService])
|
|
1610
2074
|
], DelegatesManagerService);
|
|
1611
2075
|
//# sourceMappingURL=delegates-manager.service.js.map
|