dt-common-device 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. package/TROUBLESHOOTING.md +184 -0
  2. package/dist/config/config.d.ts +9 -2
  3. package/dist/config/config.js +97 -14
  4. package/dist/constants/Event.d.ts +75 -0
  5. package/dist/constants/Event.js +78 -0
  6. package/dist/db/db.d.ts +1 -0
  7. package/dist/db/db.js +18 -2
  8. package/dist/device/local/entities/AlertBuilder.d.ts +87 -0
  9. package/dist/device/local/entities/AlertBuilder.example.d.ts +11 -0
  10. package/dist/device/local/entities/AlertBuilder.example.js +117 -0
  11. package/dist/device/local/entities/AlertBuilder.js +179 -0
  12. package/dist/device/local/entities/IssueBuilder.d.ts +109 -0
  13. package/dist/device/local/entities/IssueBuilder.example.d.ts +16 -0
  14. package/dist/device/local/entities/IssueBuilder.example.js +196 -0
  15. package/dist/device/local/entities/IssueBuilder.js +237 -0
  16. package/dist/device/local/entities/index.d.ts +2 -0
  17. package/dist/device/local/entities/index.js +7 -0
  18. package/dist/device/local/interfaces/IDevice.d.ts +10 -9
  19. package/dist/device/local/interfaces/IDevice.js +7 -0
  20. package/dist/device/local/models/Alert.model.d.ts +28 -0
  21. package/dist/device/local/models/Alert.model.js +222 -0
  22. package/dist/device/local/models/Issue.model.d.ts +28 -0
  23. package/dist/device/local/models/Issue.model.js +260 -0
  24. package/dist/device/local/repository/Alert.repository.d.ts +106 -0
  25. package/dist/device/local/repository/Alert.repository.js +374 -0
  26. package/dist/device/local/repository/Device.repository.d.ts +10 -2
  27. package/dist/device/local/repository/Device.repository.js +153 -30
  28. package/dist/device/local/repository/Hub.repository.d.ts +1 -1
  29. package/dist/device/local/repository/Hub.repository.js +60 -18
  30. package/dist/device/local/repository/Issue.repository.d.ts +113 -0
  31. package/dist/device/local/repository/Issue.repository.js +401 -0
  32. package/dist/device/local/repository/Schedule.repository.d.ts +1 -1
  33. package/dist/device/local/repository/Schedule.repository.js +14 -18
  34. package/dist/device/local/services/Alert.service.d.ts +135 -5
  35. package/dist/device/local/services/Alert.service.js +471 -7
  36. package/dist/device/local/services/AlertService.example.d.ts +55 -0
  37. package/dist/device/local/services/AlertService.example.js +148 -0
  38. package/dist/device/local/services/Device.service.d.ts +8 -5
  39. package/dist/device/local/services/Device.service.js +58 -40
  40. package/dist/device/local/services/Issue.service.d.ts +168 -0
  41. package/dist/device/local/services/Issue.service.js +642 -0
  42. package/dist/device/local/services/IssueService.example.d.ts +68 -0
  43. package/dist/device/local/services/IssueService.example.js +177 -0
  44. package/dist/device/local/services/index.d.ts +7 -5
  45. package/dist/device/local/services/index.js +21 -11
  46. package/dist/events/BaseEventHandler.d.ts +43 -0
  47. package/dist/events/BaseEventHandler.js +111 -0
  48. package/dist/events/BaseEventTransformer.d.ts +26 -0
  49. package/dist/events/BaseEventTransformer.js +72 -0
  50. package/dist/events/DeviceEventHandler.d.ts +15 -0
  51. package/dist/events/DeviceEventHandler.js +152 -0
  52. package/dist/events/DeviceEventTransformerFactory.d.ts +27 -0
  53. package/dist/events/DeviceEventTransformerFactory.js +116 -0
  54. package/dist/events/EventHandler.d.ts +11 -0
  55. package/dist/events/EventHandler.js +106 -0
  56. package/dist/events/EventHandlerOrchestrator.d.ts +35 -0
  57. package/dist/events/EventHandlerOrchestrator.js +141 -0
  58. package/dist/events/EventProcessingService.d.ts +43 -0
  59. package/dist/events/EventProcessingService.js +243 -0
  60. package/dist/events/InternalEventSubscription.d.ts +44 -0
  61. package/dist/events/InternalEventSubscription.js +152 -0
  62. package/dist/events/index.d.ts +9 -0
  63. package/dist/events/index.js +21 -0
  64. package/dist/events/interfaces/DeviceEvent.d.ts +48 -0
  65. package/dist/events/interfaces/DeviceEvent.js +2 -0
  66. package/dist/events/interfaces/IEventHandler.d.ts +23 -0
  67. package/dist/events/interfaces/IEventHandler.js +2 -0
  68. package/dist/events/interfaces/IEventTransformer.d.ts +7 -0
  69. package/dist/events/interfaces/IEventTransformer.js +2 -0
  70. package/dist/events/interfaces/IInternalEvent.d.ts +42 -0
  71. package/dist/events/interfaces/IInternalEvent.js +2 -0
  72. package/dist/events/interfaces/index.d.ts +4 -0
  73. package/dist/events/interfaces/index.js +20 -0
  74. package/dist/index.d.ts +6 -2
  75. package/dist/index.js +9 -2
  76. package/dist/types/alert.types.d.ts +57 -0
  77. package/dist/types/alert.types.js +22 -0
  78. package/dist/types/config.types.d.ts +15 -4
  79. package/dist/types/index.d.ts +2 -0
  80. package/dist/types/index.js +2 -0
  81. package/dist/types/issue.types.d.ts +90 -0
  82. package/dist/types/issue.types.js +40 -0
  83. package/dist/utils/http-utils.d.ts +13 -0
  84. package/dist/utils/http-utils.js +117 -0
  85. package/package.json +2 -1
  86. package/src/config/config.ts +117 -14
  87. package/src/{device/local/events/Events.ts → constants/Event.ts} +34 -13
  88. package/src/db/db.ts +14 -5
  89. package/src/device/local/entities/AlertBuilder.example.ts +126 -0
  90. package/src/device/local/entities/AlertBuilder.ts +202 -0
  91. package/src/device/local/entities/IssueBuilder.example.ts +210 -0
  92. package/src/device/local/entities/IssueBuilder.ts +263 -0
  93. package/src/device/local/entities/README.md +173 -0
  94. package/src/device/local/entities/index.ts +2 -0
  95. package/src/device/local/interfaces/IDevice.ts +11 -9
  96. package/src/device/local/models/Alert.model.md +319 -0
  97. package/src/device/local/models/Alert.model.ts +283 -0
  98. package/src/device/local/models/Issue.model.md +386 -0
  99. package/src/device/local/models/Issue.model.ts +350 -0
  100. package/src/device/local/models/README.md +312 -0
  101. package/src/device/local/repository/Alert.repository.ts +465 -0
  102. package/src/device/local/repository/Device.repository.ts +241 -32
  103. package/src/device/local/repository/Hub.repository.ts +74 -18
  104. package/src/device/local/repository/Issue.repository.ts +517 -0
  105. package/src/device/local/repository/Schedule.repository.ts +28 -22
  106. package/src/device/local/services/Alert.service.ts +617 -5
  107. package/src/device/local/services/AlertService.example.ts +229 -0
  108. package/src/device/local/services/Device.service.ts +70 -50
  109. package/src/device/local/services/Issue.service.ts +872 -0
  110. package/src/device/local/services/IssueService.example.ts +307 -0
  111. package/src/device/local/services/index.ts +7 -5
  112. package/src/events/BaseEventHandler.ts +145 -0
  113. package/src/events/BaseEventTransformer.ts +97 -0
  114. package/src/events/DeviceEventHandler.ts +211 -0
  115. package/src/events/DeviceEventTransformerFactory.ts +77 -0
  116. package/src/{device/local/events → events}/EventHandler.ts +19 -15
  117. package/src/events/EventHandlerOrchestrator.ts +119 -0
  118. package/src/events/EventProcessingService.ts +248 -0
  119. package/src/events/InternalEventSubscription.ts +219 -0
  120. package/src/events/index.ts +9 -0
  121. package/src/events/interfaces/DeviceEvent.ts +56 -0
  122. package/src/events/interfaces/IEventHandler.ts +28 -0
  123. package/src/events/interfaces/IEventTransformer.ts +8 -0
  124. package/src/events/interfaces/IInternalEvent.ts +47 -0
  125. package/src/events/interfaces/index.ts +4 -0
  126. package/src/index.ts +9 -2
  127. package/src/types/alert.types.ts +64 -0
  128. package/src/types/config.types.ts +17 -4
  129. package/src/types/index.ts +2 -0
  130. package/src/types/issue.types.ts +98 -0
  131. package/src/utils/http-utils.ts +143 -0
  132. package/src/device/local/events/index.ts +0 -2
@@ -0,0 +1,211 @@
1
+ import { DT_EVENT_TYPES } from "../constants/Event";
2
+ import { IDevice } from "../device/local/interfaces";
3
+ import { LocalHubService } from "../device/local/services";
4
+ import { BaseEventHandler } from "./BaseEventHandler";
5
+ import {
6
+ DeviceEvent,
7
+ DeviceEventEntity,
8
+ EventConstructionOptions,
9
+ } from "./interfaces/DeviceEvent";
10
+
11
+ export class DeviceEventHandler extends BaseEventHandler {
12
+ private readonly localHubService: LocalHubService;
13
+ constructor() {
14
+ super(
15
+ [
16
+ DT_EVENT_TYPES.DEVICE.STATUS.ONLINE,
17
+ DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE,
18
+ DT_EVENT_TYPES.DEVICE.STATUS.CHANGED,
19
+ DT_EVENT_TYPES.DEVICE.BATTERY.CRITICAL,
20
+ DT_EVENT_TYPES.DEVICE.BATTERY.LOW,
21
+ DT_EVENT_TYPES.DEVICE.BATTERY.CHANGED,
22
+ ],
23
+ 100
24
+ );
25
+ this.localHubService = new LocalHubService();
26
+ }
27
+
28
+ async onEvent(event: DeviceEvent): Promise<void> {
29
+ this.logger.info("[DT | CDL]:[DeviceEventHandler]: Processing event", {
30
+ eventName: event.eventName,
31
+ });
32
+
33
+ try {
34
+ const device: IDevice = await this.localDeviceService.getDevice(
35
+ event.deviceId
36
+ );
37
+ if (!device?.deviceId) {
38
+ throw new Error(
39
+ "[DT | CDL]:[DeviceEventHandler]: deviceId does not exist"
40
+ );
41
+ }
42
+ await this.updateDeviceEventData(device, event);
43
+ // Update relevant tables based on event type
44
+ await this.updateTablesBasedOnEventType(event, device);
45
+
46
+ // Save event logs
47
+ await this.dumpToEventOperation(event, device);
48
+ } catch (error) {
49
+ this.logger.error(
50
+ "[DT | CDL]:[DeviceEventHandler]: Error processing event",
51
+ error
52
+ );
53
+ throw error;
54
+ }
55
+ }
56
+
57
+ async updateDeviceEventData(
58
+ deviceData: IDevice,
59
+ event: DeviceEvent
60
+ ): Promise<void> {
61
+ switch (event.eventName) {
62
+ case DT_EVENT_TYPES.DEVICE.STATUS.ONLINE:
63
+ case DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE:
64
+ await this.localDeviceService.setState(deviceData.deviceId, {
65
+ status: {
66
+ online: event.eventName === DT_EVENT_TYPES.DEVICE.STATUS.ONLINE,
67
+ lastUpdated: new Date().toISOString(),
68
+ error: {
69
+ type:
70
+ event.eventName === DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE
71
+ ? "offline"
72
+ : "",
73
+ message:
74
+ event.eventName === DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE
75
+ ? "Device is offline"
76
+ : "",
77
+ default: {},
78
+ },
79
+ },
80
+ });
81
+ break;
82
+ case DT_EVENT_TYPES.DEVICE.BATTERY.CHANGED:
83
+ await this.localDeviceService.setBatteryLevel(
84
+ deviceData.deviceId,
85
+ event?.data?.batteryLevel ?? 0
86
+ );
87
+ break;
88
+ }
89
+ }
90
+
91
+ async extractHubDetails(device: IDevice): Promise<any[]> {
92
+ const hubIds = device?.hubId;
93
+ const hubDetails: any[] = [];
94
+
95
+ if (hubIds) {
96
+ for (const hubId of hubIds) {
97
+ const hubDetail: IDevice = await this.localHubService.getHub(hubId);
98
+ hubDetails.push({
99
+ id: hubDetail?.deviceId,
100
+ name: hubDetail?.name,
101
+ type: hubDetail?.deviceType?.type,
102
+ brand: hubDetail?.specifications?.manufacturer,
103
+ model: hubDetail?.specifications?.model,
104
+ status: hubDetail?.status?.online ? "ONLINE" : "OFFLINE",
105
+ });
106
+ }
107
+ }
108
+
109
+ return hubDetails;
110
+ }
111
+
112
+ constructDeviceEventEntity(
113
+ eventData: any,
114
+ device: IDevice,
115
+ hubDetails: any[],
116
+ options: EventConstructionOptions = {}
117
+ ): DeviceEventEntity {
118
+ return {
119
+ event: {
120
+ eventId: options.eventId || eventData?.eventId || "",
121
+ eventName: options.eventName || eventData?.eventName || "",
122
+ status: options.status || eventData?.status || "",
123
+ mode: options.mode || eventData?.data?.mode,
124
+ userName: options.userName || eventData?.userName || "",
125
+ userId: options.userId || eventData?.userId || "",
126
+ userType: options.userType || eventData?.userType || "",
127
+ raw_event: options.rawEvent || eventData?.rawData || {},
128
+ batteryLevel:
129
+ options.batteryLevel || eventData?.data?.batteryLevel || "",
130
+ reason: options.reason || eventData?.data?.reason || "",
131
+ eventDescription: options.eventDescription || eventData?.event || "",
132
+ },
133
+ device: {
134
+ id: eventData?.deviceId || "",
135
+ name: device?.name || "",
136
+ type: device?.deviceType?.type || "",
137
+ brand: device?.specifications?.manufacturer || "",
138
+ model: device?.specifications?.model || "",
139
+ },
140
+ hub: hubDetails,
141
+ property: {
142
+ id: eventData?.property?.id || "",
143
+ name: eventData?.property?.name || "",
144
+ location: eventData?.property?.apartment || "",
145
+ },
146
+ };
147
+ }
148
+
149
+ async dumpToEventOperation(data: any, device: IDevice): Promise<void> {
150
+ try {
151
+ const hubDetails = await this.extractHubDetails(device);
152
+
153
+ const eventData: DeviceEventEntity = this.constructDeviceEventEntity(
154
+ data,
155
+ device,
156
+ hubDetails,
157
+ {
158
+ status: data.eventName === "lock.unlock" ? "UNLOCKED" : "LOCKED",
159
+ rawEvent: data.rawData,
160
+ }
161
+ );
162
+ this.logger.info(
163
+ "[DT | CDL]:[DeviceEventHandler]: Event data dumped to event operation",
164
+ { eventData }
165
+ );
166
+ } catch (error) {
167
+ this.logger.error(
168
+ "[DT | CDL]:[DeviceEventHandler]: Error dumping to event operation",
169
+ error
170
+ );
171
+ }
172
+ }
173
+
174
+ async updateTablesBasedOnEventType(
175
+ eventData: any,
176
+ device: IDevice
177
+ ): Promise<void> {
178
+ switch (eventData.eventName) {
179
+ case DT_EVENT_TYPES.DEVICE.STATUS.ONLINE:
180
+ case DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE:
181
+ case DT_EVENT_TYPES.DEVICE.STATUS.CHANGED:
182
+ this.updateDeviceStatus(eventData, device);
183
+ break;
184
+ case DT_EVENT_TYPES.DEVICE.BATTERY.CHANGED:
185
+ case DT_EVENT_TYPES.DEVICE.BATTERY.CRITICAL:
186
+ case DT_EVENT_TYPES.DEVICE.BATTERY.LOW:
187
+ this.updateDeviceBattery(eventData, device);
188
+ break;
189
+ }
190
+ }
191
+
192
+ async updateDeviceStatus(data: any, device: IDevice) {
193
+ this.logger.info(
194
+ "[DT | CDL]:[DeviceEventHandler]: Updating device status",
195
+ {
196
+ data,
197
+ device,
198
+ }
199
+ );
200
+ }
201
+
202
+ async updateDeviceBattery(data: any, device: IDevice) {
203
+ this.logger.info(
204
+ "[DT | CDL]:[DeviceEventHandler]: Updating device battery",
205
+ {
206
+ data,
207
+ device,
208
+ }
209
+ );
210
+ }
211
+ }
@@ -0,0 +1,77 @@
1
+ import { Service } from 'typedi';
2
+ import { IEventTransformer } from './interfaces/IEventTransformer';
3
+
4
+ /**
5
+ * Abstract base factory for creating device event transformers
6
+ * This class can be moved to dt-common-device and extended by specific device type factories
7
+ */
8
+ @Service()
9
+ export abstract class DeviceEventTransformerFactory {
10
+ /**
11
+ * Create the appropriate event transformer based on device type
12
+ * This method should be implemented by subclasses to handle specific device types
13
+ */
14
+ public abstract createTransformer(deviceType: string, rawData: any): IEventTransformer | null;
15
+
16
+ /**
17
+ * Create a default transformer for unsupported or generic device types
18
+ * This method can be overridden by subclasses to provide device-specific default behavior
19
+ */
20
+ protected createDefaultTransformer(deviceType: string, rawData: any): IEventTransformer {
21
+ return new (class implements IEventTransformer {
22
+ private readonly deviceType: string;
23
+ private readonly rawData: any;
24
+
25
+ constructor(deviceType: string, rawData: any) {
26
+ this.deviceType = deviceType;
27
+ this.rawData = rawData;
28
+ }
29
+
30
+ parseData(rawData: any): any {
31
+ // Default parsing - return as-is
32
+ return rawData;
33
+ }
34
+
35
+ transform(parsedData: any): any {
36
+ // Default transformation - return as-is
37
+ return parsedData;
38
+ }
39
+
40
+ validate(transformedEvent: any): boolean {
41
+ // Default validation - always return true
42
+ return true;
43
+ }
44
+
45
+ executeTransformation(): any[] {
46
+ try {
47
+ const parsedData = this.parseData(this.rawData);
48
+ const transformedResult = this.transform(parsedData);
49
+ const events = Array.isArray(transformedResult) ? transformedResult : [transformedResult];
50
+ return events.filter((event) => this.validate(event));
51
+ } catch (error) {
52
+ console.error(`Error in default transformer for device type ${this.deviceType}:`, error);
53
+ return [];
54
+ }
55
+ }
56
+ })(deviceType, rawData);
57
+ }
58
+
59
+
60
+ /**
61
+ * Handle unsupported device types
62
+ * This method can be overridden by subclasses to provide custom handling
63
+ */
64
+ protected handleUnsupportedDeviceType(deviceType: string): IEventTransformer | null {
65
+ console.warn(`Unsupported device type: ${deviceType}`);
66
+ return null;
67
+ }
68
+
69
+ /**
70
+ * Handle errors during transformer creation
71
+ * This method can be overridden by subclasses to provide custom error handling
72
+ */
73
+ protected handleTransformerCreationError(deviceType: string, error: any): IEventTransformer | null {
74
+ console.error(`Error creating transformer for device type ${deviceType}:`, error);
75
+ return null;
76
+ }
77
+ }
@@ -1,6 +1,6 @@
1
1
  import { eventDispatcher } from "dt-pub-sub";
2
2
  import { publishAudit } from "dt-audit-library";
3
- import { DT_EVENT_TYPES } from "./Events";
3
+ import { DT_EVENT_TYPES } from "../constants/Event";
4
4
 
5
5
  export class EventHandler {
6
6
  private readonly source: string;
@@ -10,12 +10,12 @@ export class EventHandler {
10
10
 
11
11
  async onDeviceCreate(body: any) {
12
12
  await eventDispatcher.publishEvent(
13
- DT_EVENT_TYPES.DEVICE.DEVICE.CREATED,
13
+ DT_EVENT_TYPES.DEVICE.CREATE.SUCCESS,
14
14
  body,
15
15
  this.source
16
16
  );
17
17
  const payload = {
18
- eventType: DT_EVENT_TYPES.DEVICE.DEVICE.CREATED,
18
+ eventType: DT_EVENT_TYPES.DEVICE.CREATE.SUCCESS,
19
19
  properties: {
20
20
  ...body,
21
21
  },
@@ -25,12 +25,12 @@ export class EventHandler {
25
25
 
26
26
  async onDeviceUpdate(deviceId: string, body: any) {
27
27
  await eventDispatcher.publishEvent(
28
- DT_EVENT_TYPES.DEVICE.DEVICE.UPDATED,
28
+ DT_EVENT_TYPES.DEVICE.UPDATE.SUCCESS,
29
29
  { deviceId, body },
30
30
  this.source
31
31
  );
32
32
  const payload = {
33
- eventType: DT_EVENT_TYPES.DEVICE.DEVICE.UPDATED,
33
+ eventType: DT_EVENT_TYPES.DEVICE.UPDATE.SUCCESS,
34
34
  properties: {
35
35
  ...body,
36
36
  },
@@ -40,12 +40,12 @@ export class EventHandler {
40
40
 
41
41
  async onDeviceDelete(deviceId: string) {
42
42
  await eventDispatcher.publishEvent(
43
- DT_EVENT_TYPES.DEVICE.DEVICE.DELETED,
43
+ DT_EVENT_TYPES.DEVICE.DELETE.SUCCESS,
44
44
  { deviceId },
45
45
  this.source
46
46
  );
47
47
  const payload = {
48
- eventType: DT_EVENT_TYPES.DEVICE.DEVICE.DELETED,
48
+ eventType: DT_EVENT_TYPES.DEVICE.DELETE.SUCCESS,
49
49
  properties: {
50
50
  deviceId,
51
51
  },
@@ -54,11 +54,12 @@ export class EventHandler {
54
54
  }
55
55
 
56
56
  async onStateChange(deviceId: string, state: any) {
57
- await eventDispatcher.publishEvent(
57
+ // TODO: For Future Consumption
58
+ /* await eventDispatcher.publishEvent(
58
59
  DT_EVENT_TYPES.DEVICE.STATE.SET,
59
60
  { deviceId, state },
60
61
  this.source
61
- );
62
+ ); */
62
63
  const payload = {
63
64
  eventType: DT_EVENT_TYPES.DEVICE.STATE.SET,
64
65
  properties: {
@@ -70,11 +71,12 @@ export class EventHandler {
70
71
  }
71
72
 
72
73
  async onStatusChange(deviceId: string, status: any) {
73
- await eventDispatcher.publishEvent(
74
+ // TODO: For Future Consumption
75
+ /* await eventDispatcher.publishEvent(
74
76
  DT_EVENT_TYPES.DEVICE.STATUS.SET,
75
77
  { deviceId, status },
76
78
  this.source
77
- );
79
+ ); */
78
80
  const payload = {
79
81
  eventType: DT_EVENT_TYPES.DEVICE.STATUS.SET,
80
82
  properties: {
@@ -86,11 +88,12 @@ export class EventHandler {
86
88
  }
87
89
 
88
90
  async onBatteryLevelChange(deviceId: string, batteryLevel: number) {
89
- await eventDispatcher.publishEvent(
91
+ // TODO: For Future Consumption
92
+ /* await eventDispatcher.publishEvent(
90
93
  DT_EVENT_TYPES.DEVICE.BATTERY.SET,
91
94
  { deviceId, batteryLevel },
92
95
  this.source
93
- );
96
+ ); */
94
97
  const payload = {
95
98
  eventType: DT_EVENT_TYPES.DEVICE.BATTERY.SET,
96
99
  properties: {
@@ -102,11 +105,12 @@ export class EventHandler {
102
105
  }
103
106
 
104
107
  async onDeviceMetaChange(deviceId: string, metaData: Record<string, any>) {
105
- await eventDispatcher.publishEvent(
108
+ // TODO: For Future Consumption
109
+ /* await eventDispatcher.publishEvent(
106
110
  DT_EVENT_TYPES.DEVICE.META_DATA.SET,
107
111
  { deviceId, metaData },
108
112
  this.source
109
- );
113
+ ); */
110
114
  const payload = {
111
115
  eventType: DT_EVENT_TYPES.DEVICE.META_DATA.SET,
112
116
  properties: {
@@ -0,0 +1,119 @@
1
+ import { Service } from "typedi";
2
+ import { IEventHandler } from "./interfaces/IEventHandler";
3
+ import { DeviceEvent } from "./interfaces/DeviceEvent";
4
+ import { ILogger } from "../types/config.types";
5
+ import { getConfig } from "../config/config";
6
+
7
+ @Service()
8
+ export class EventHandlerOrchestrator {
9
+ private handlers: IEventHandler[] = [];
10
+ private readonly logger: ILogger;
11
+ constructor() {
12
+ this.logger = getConfig().LOGGER;
13
+ }
14
+ /**
15
+ * Register a handler with the orchestrator
16
+ */
17
+ registerHandler(handler: IEventHandler): void {
18
+ this.handlers.push(handler);
19
+ // Sort handlers by priority (lower numbers = higher priority)
20
+ this.handlers.sort((a, b) => a.getPriority() - b.getPriority());
21
+ this.logger.info(
22
+ `Registered handler: ${
23
+ handler.constructor.name
24
+ } with priority ${handler.getPriority()}`
25
+ );
26
+ }
27
+
28
+ /**
29
+ * Register multiple handlers
30
+ */
31
+ registerHandlers(handlers: IEventHandler[]): void {
32
+ handlers.forEach((handler) => this.registerHandler(handler));
33
+ }
34
+
35
+ /**
36
+ * Process a single event through the handler hierarchy
37
+ */
38
+ async processEvent(event: DeviceEvent): Promise<void> {
39
+ try {
40
+ this.logger.info(
41
+ `Processing event: ${event.eventName} for device: ${event.deviceId}`
42
+ );
43
+
44
+ const applicableHandlers = this.handlers.filter((handler) =>
45
+ handler.canHandle(event.eventName)
46
+ );
47
+
48
+ if (applicableHandlers.length === 0) {
49
+ this.logger.warn(
50
+ `No handlers found for event type: ${event.eventName}`
51
+ );
52
+ return;
53
+ }
54
+
55
+ this.logger.info(
56
+ `Found ${applicableHandlers.length} handlers for event: ${event.eventName}`
57
+ );
58
+
59
+ // Process with each applicable handler in priority order
60
+ for (const handler of applicableHandlers) {
61
+ try {
62
+ await handler.handleEvent(event);
63
+ this.logger.info(`Event processed by: ${handler.constructor.name}`);
64
+ } catch (error) {
65
+ this.logger.error(
66
+ `Error in handler ${handler.constructor.name}:`,
67
+ error
68
+ );
69
+ // Continue with other handlers even if one fails
70
+ }
71
+ }
72
+ } catch (error) {
73
+ this.logger.error(
74
+ "Error in EventHandlerOrchestrator.processEvent:",
75
+ error
76
+ );
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Process multiple events
82
+ */
83
+ async processEvents(events: DeviceEvent[]): Promise<void> {
84
+ try {
85
+ this.logger.info(`Processing ${events.length} events`);
86
+
87
+ for (const event of events) {
88
+ await this.processEvent(event);
89
+ }
90
+ } catch (error) {
91
+ this.logger.error(
92
+ "Error in EventHandlerOrchestrator.processEvents:",
93
+ error
94
+ );
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Get all registered handlers
100
+ */
101
+ getHandlers(): IEventHandler[] {
102
+ return [...this.handlers];
103
+ }
104
+
105
+ /**
106
+ * Get handlers that can handle a specific event type
107
+ */
108
+ getHandlersForEventType(eventType: string): IEventHandler[] {
109
+ return this.handlers.filter((handler) => handler.canHandle(eventType));
110
+ }
111
+
112
+ /**
113
+ * Clear all registered handlers
114
+ */
115
+ clearHandlers(): void {
116
+ this.handlers = [];
117
+ this.logger.info("All handlers cleared");
118
+ }
119
+ }