dt-common-device 9.1.8 → 9.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44,7 +44,7 @@ class CronicleService {
44
44
  });
45
45
  }
46
46
  catch (error) {
47
- (0, config_1.getConfig)().LOGGER.error(`Failed to create device: ${error.message}`);
47
+ (0, config_1.getConfig)().LOGGER.error(`Failed to create Cronicle job: ${error.message}`);
48
48
  }
49
49
  }
50
50
  async getJob(jobId) {
@@ -2,6 +2,7 @@ import { IAccessGroup, IUser, IZone, IZoneAccessGroup } from "./IAdmin";
2
2
  export declare class AdminRepository {
3
3
  private readonly deviceRepository;
4
4
  private readonly postgres;
5
+ private readonly localDeviceService;
5
6
  constructor();
6
7
  getZonesByAccessGroupIds(accessGroupIds: string[]): Promise<any[]>;
7
8
  getZonesByAccessGroups(accessGroupIds: string[]): Promise<any[]>;
@@ -9,4 +10,5 @@ export declare class AdminRepository {
9
10
  getZoneAccessGroupByZoneId(zoneId: string): Promise<IZoneAccessGroup[] | null>;
10
11
  getZone(zoneId: string): Promise<IZone | null>;
11
12
  getUser(userId: string): Promise<IUser | null>;
13
+ getZoneByDeviceId(deviceId: string): Promise<IZone | null>;
12
14
  }
@@ -77,6 +77,7 @@ const utils_1 = require("../../utils");
77
77
  const Device_repository_1 = require("../device/local/repository/Device.repository");
78
78
  const db_1 = require("../../db/db");
79
79
  const interfaces_1 = require("../device/cloud/interfaces");
80
+ const services_1 = require("../device/local/services");
80
81
  let AdminRepository = (() => {
81
82
  let _classDecorators = [(0, typedi_1.Service)()];
82
83
  let _classDescriptor;
@@ -86,6 +87,7 @@ let AdminRepository = (() => {
86
87
  constructor() {
87
88
  this.deviceRepository = typedi_1.default.get(Device_repository_1.DeviceRepository);
88
89
  this.postgres = (0, db_1.getPostgresClient)();
90
+ this.localDeviceService = typedi_1.default.get(services_1.LocalDeviceService);
89
91
  }
90
92
  async getZonesByAccessGroupIds(accessGroupIds) {
91
93
  // // Get propertyId from any of the accessGroupIds
@@ -106,10 +108,19 @@ let AdminRepository = (() => {
106
108
  // return JSON.parse(cachedResult);
107
109
  // }
108
110
  // If not cached, get the result from the database
109
- const result = await this.postgres.query(`SELECT "zc".*, "z"."id", "z"."name"
110
- FROM "dt_zones_collection_map" "zc"
111
- INNER JOIN "dt_zones" "z" ON "zc"."zoneId" = "z"."id"
112
- WHERE "zc"."collectionId" = ANY($1)`, [accessGroupIds]);
111
+ const result = await this.postgres.query(`SELECT
112
+ "zc"."id" AS "zoneCollectionMapId",
113
+ "zc"."collectionId",
114
+ "zc"."zoneId",
115
+ "z"."id" AS "zoneId",
116
+ "z"."name" AS "zoneName",
117
+ "z"."zoneTypeId",
118
+ "zt"."name" AS "zoneTypeName"
119
+ FROM "dt_zones_collection_map" AS "zc"
120
+ INNER JOIN "dt_zones" AS "z" ON "zc"."zoneId" = "z"."id"
121
+ LEFT JOIN "dt_zoneTypes" AS "zt" ON "z"."zoneTypeId" = "zt"."id"
122
+ WHERE "zc"."collectionId" = ANY($1)
123
+ ORDER BY "zc"."id" ASC`, [accessGroupIds]);
113
124
  const response = result.rows;
114
125
  const _zones = (nestedZones, allZones = []) => {
115
126
  nestedZones.forEach((z) => {
@@ -167,6 +178,7 @@ let AdminRepository = (() => {
167
178
  const _collectionZone = collectionZone.map((e) => {
168
179
  const zones = e.zoneIds;
169
180
  let devices = [];
181
+ let zonesData = [];
170
182
  zones.forEach((element) => {
171
183
  const device = deviceDetails.filter((d) => d.zoneId == element);
172
184
  // Add collectionId to each device
@@ -175,8 +187,18 @@ let AdminRepository = (() => {
175
187
  });
176
188
  const _devices = devices.concat(device);
177
189
  devices = _devices;
190
+ // Create zone data for each zone
191
+ const zoneInfo = response.find((r) => r.zoneId === element);
192
+ const zoneData = {
193
+ zoneId: element,
194
+ deviceIds: device?.map((d) => d.deviceId), // Get first device ID if available
195
+ zoneName: zoneInfo?.zoneName || "",
196
+ zoneType: zoneInfo?.zoneTypeName || null,
197
+ };
198
+ zonesData.push(zoneData);
178
199
  });
179
200
  e.devices = devices;
201
+ e.zones = zonesData;
180
202
  e.parentZone = response;
181
203
  return e;
182
204
  });
@@ -249,6 +271,7 @@ let AdminRepository = (() => {
249
271
  if (zone.rows.length > 0) {
250
272
  const zoneData = zone.rows[0];
251
273
  const zoneType = await this.postgres.query(`SELECT * FROM "dt_zoneTypes" WHERE "id" = $1`, [zoneData.zoneTypeId]);
274
+ zoneData.zoneType = {};
252
275
  zoneData.zoneType = {
253
276
  id: zoneType.rows[0].id,
254
277
  name: zoneType.rows[0].name,
@@ -269,6 +292,16 @@ let AdminRepository = (() => {
269
292
  }
270
293
  return null;
271
294
  }
295
+ async getZoneByDeviceId(deviceId) {
296
+ try {
297
+ const device = await this.localDeviceService.getDevice(deviceId);
298
+ return await this.getZone(device.zoneId);
299
+ }
300
+ catch (error) {
301
+ console.error("Error in getZoneByDeviceId:", error);
302
+ throw new Error("Failed to get zone by device ID");
303
+ }
304
+ }
272
305
  };
273
306
  __setFunctionName(_classThis, "AdminRepository");
274
307
  (() => {
@@ -9,4 +9,5 @@ export declare class AdminService {
9
9
  getAccessGroupByZoneId(zoneId: string): Promise<IAccessGroup[] | []>;
10
10
  getZone(zoneId: string): Promise<IZone | null>;
11
11
  getUser(userId: string): Promise<IUser | null>;
12
+ getZoneByDeviceId(deviceId: string): Promise<IZone | null>;
12
13
  }
@@ -147,6 +147,15 @@ let AdminService = (() => {
147
147
  return null;
148
148
  return user;
149
149
  }
150
+ async getZoneByDeviceId(deviceId) {
151
+ if (!deviceId) {
152
+ throw new Error("Device ID is required");
153
+ }
154
+ const zone = await this.adminRepository.getZoneByDeviceId(deviceId);
155
+ if (!zone)
156
+ return null;
157
+ return zone;
158
+ }
150
159
  };
151
160
  __setFunctionName(_classThis, "AdminService");
152
161
  (() => {
@@ -294,43 +294,52 @@ let LocalDeviceService = (() => {
294
294
  }
295
295
  }
296
296
  async handleOfflineStatus(device, oldStatus, newStatus, source, auditBody, reason, currentTime) {
297
+ // if deviceProfile is active, only then use baseline for the device, if its calibrating or inactive mark device offline immediately
298
+ const preferences = await this.localPropertyService.getPropertyPreferences(device.propertyId, ["deviceProfile"]);
299
+ const deviceProfile = preferences?.settings?.deviceProfile?.value || "calibrating";
297
300
  currentTime = currentTime ?? new Date().toISOString();
298
301
  const isExistingStatusOnline = oldStatus?.liveStatus === "ONLINE";
299
302
  const isExistingStatusOffline = oldStatus?.liveStatus === "OFFLINE";
300
- if (isExistingStatusOnline) {
301
- // Existing status is Online
302
- newStatus.online = true;
303
- newStatus.liveStatus = "OFFLINE";
304
- newStatus.lastUpdated = currentTime;
305
- newStatus.error = {
306
- type: "offline",
307
- message: reason || "Device went offline",
308
- default: {},
309
- };
310
- await this.deviceRepository.setStatus(device.deviceId, newStatus);
311
- await this.eventHandler.onStatusChange(device.deviceId, newStatus, auditBody, constants_1.DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE);
312
- }
313
- else if (isExistingStatusOffline) {
314
- // Existing status is Offline
315
- const timeLapsed = oldStatus?.lastUpdated
316
- ? Date.now() - new Date(oldStatus.lastUpdated).getTime()
317
- : 0;
318
- const baselineTime = await this.getDeviceBaseline(device.deviceId);
319
- if (timeLapsed > baselineTime) {
320
- // When the time lapsed is higher than the baseline time
321
- newStatus.online = false;
303
+ if (deviceProfile === "active") {
304
+ if (isExistingStatusOnline) {
305
+ // Existing status is Online
306
+ newStatus.online = true;
322
307
  newStatus.liveStatus = "OFFLINE";
323
308
  newStatus.lastUpdated = currentTime;
324
309
  newStatus.error = {
325
310
  type: "offline",
326
- message: reason || "Device has been offline for longer than baseline",
311
+ message: reason || "Device went offline",
327
312
  default: {},
328
313
  };
329
314
  await this.deviceRepository.setStatus(device.deviceId, newStatus);
330
315
  await this.eventHandler.onStatusChange(device.deviceId, newStatus, auditBody, constants_1.DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE);
331
- // Raise issue when the device goes offline if longer than the baseline (OPERATIONAL only)
332
- await this.issueService.createDeviceOfflineIssue(device, source, reason);
333
316
  }
317
+ else if (isExistingStatusOffline) {
318
+ // Existing status is Offline
319
+ const timeLapsed = oldStatus?.lastUpdated
320
+ ? Date.now() - new Date(oldStatus.lastUpdated).getTime()
321
+ : 0;
322
+ const baselineTime = await this.getDeviceBaseline(device.deviceId);
323
+ if (timeLapsed > baselineTime) {
324
+ // When the time lapsed is higher than the baseline time
325
+ newStatus.online = false;
326
+ newStatus.liveStatus = "OFFLINE";
327
+ newStatus.lastUpdated = currentTime;
328
+ newStatus.error = {
329
+ type: "offline",
330
+ message: reason || "Device has been offline for longer than baseline",
331
+ default: {},
332
+ };
333
+ await this.deviceRepository.setStatus(device.deviceId, newStatus);
334
+ await this.eventHandler.onStatusChange(device.deviceId, newStatus, auditBody, constants_1.DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE);
335
+ // Raise issue when the device goes offline if longer than the baseline (OPERATIONAL only)
336
+ await this.issueService.createDeviceOfflineIssue(device, source, reason);
337
+ }
338
+ }
339
+ }
340
+ else {
341
+ await this.deviceRepository.setStatus(device.deviceId, newStatus);
342
+ await this.eventHandler.onStatusChange(device.deviceId, newStatus, auditBody, constants_1.DT_EVENT_TYPES.DEVICE.STATUS.OFFLINE);
334
343
  }
335
344
  }
336
345
  async handleOnlineStatus(device, oldStatus, newStatus, source, auditBody, reason, currentTime) {
@@ -2,4 +2,5 @@ export interface IRateLimitConfig {
2
2
  maxRequests: number;
3
3
  windowMs: number;
4
4
  provider: string;
5
+ maxTimeoutWindowMs?: number;
5
6
  }
@@ -37,61 +37,73 @@ class RateLimitUtils {
37
37
  maxRequests: 10,
38
38
  windowMs: 10000, // 10 seconds
39
39
  provider: constants_1.CONNECTION_PROVIDERS.SENSIBO,
40
+ maxTimeoutWindowMs: 120000,
40
41
  });
41
42
  configs.set(constants_1.CONNECTION_PROVIDERS.CLOUDBEDS, {
42
43
  maxRequests: 8,
43
44
  windowMs: 1000, // 1 second - CloudBed allows 10 requests per second
44
45
  provider: constants_1.CONNECTION_PROVIDERS.CLOUDBEDS,
46
+ maxTimeoutWindowMs: 1800000,
45
47
  });
46
48
  configs.set(constants_1.CONNECTION_PROVIDERS.STAYNTOUCH, {
47
49
  maxRequests: 10,
48
50
  windowMs: 10000, // 10 seconds
49
51
  provider: constants_1.CONNECTION_PROVIDERS.STAYNTOUCH,
52
+ maxTimeoutWindowMs: 120000,
50
53
  });
51
54
  configs.set(constants_1.CONNECTION_PROVIDERS.HOTELKEY, {
52
55
  maxRequests: 10,
53
56
  windowMs: 10000, // 10 seconds
54
57
  provider: constants_1.CONNECTION_PROVIDERS.HOTELKEY,
58
+ maxTimeoutWindowMs: 120000,
55
59
  });
56
60
  configs.set(constants_1.CONNECTION_PROVIDERS.TTLOCK, {
57
61
  maxRequests: 15,
58
62
  windowMs: 60000, // 1 minute
59
63
  provider: constants_1.CONNECTION_PROVIDERS.TTLOCK,
64
+ maxTimeoutWindowMs: 120000,
60
65
  });
61
66
  configs.set(constants_1.CONNECTION_PROVIDERS.LOCKLY, {
62
67
  maxRequests: 10,
63
68
  windowMs: 60000, // 1 minute
64
69
  provider: constants_1.CONNECTION_PROVIDERS.LOCKLY,
70
+ maxTimeoutWindowMs: 120000,
65
71
  });
66
72
  configs.set(constants_1.CONNECTION_PROVIDERS.SCHLAGE, {
67
73
  maxRequests: 120,
68
74
  windowMs: 60000, // 1 minute
69
75
  provider: constants_1.CONNECTION_PROVIDERS.SCHLAGE,
76
+ maxTimeoutWindowMs: 120000,
70
77
  });
71
78
  configs.set(constants_1.CONNECTION_PROVIDERS.SMARTTHINGS, {
72
79
  maxRequests: 12,
73
80
  windowMs: 60000, // 1 minute
74
81
  provider: constants_1.CONNECTION_PROVIDERS.SMARTTHINGS,
82
+ maxTimeoutWindowMs: 120000,
75
83
  });
76
84
  configs.set(constants_1.CONNECTION_PROVIDERS.YALEWIFI, {
77
85
  maxRequests: 5,
78
86
  windowMs: 60000,
79
87
  provider: constants_1.CONNECTION_PROVIDERS.YALEWIFI,
88
+ maxTimeoutWindowMs: 120000,
80
89
  });
81
90
  configs.set(constants_1.CONNECTION_PROVIDERS.TUYA, {
82
91
  maxRequests: 5,
83
92
  windowMs: 1000,
84
93
  provider: constants_1.CONNECTION_PROVIDERS.TUYA,
94
+ maxTimeoutWindowMs: 120000,
85
95
  });
86
96
  configs.set(constants_1.CONNECTION_PROVIDERS.SALTOKS, {
87
97
  maxRequests: 5,
88
98
  windowMs: 60000,
89
99
  provider: constants_1.CONNECTION_PROVIDERS.SALTOKS,
100
+ maxTimeoutWindowMs: 120000,
90
101
  });
91
102
  configs.set(constants_1.CONNECTION_PROVIDERS.VERDANT, {
92
103
  maxRequests: 5,
93
104
  windowMs: 60000,
94
105
  provider: constants_1.CONNECTION_PROVIDERS.VERDANT,
106
+ maxTimeoutWindowMs: 120000,
95
107
  });
96
108
  return configs;
97
109
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dt-common-device",
3
- "version": "9.1.8",
3
+ "version": "9.1.10",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [