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.
- package/dist/cronicle/Cronicle.service.js +1 -1
- package/dist/entities/admin/Admin.repository.d.ts +2 -0
- package/dist/entities/admin/Admin.repository.js +37 -4
- package/dist/entities/admin/Admin.service.d.ts +1 -0
- package/dist/entities/admin/Admin.service.js +9 -0
- package/dist/entities/device/local/services/Device.service.js +34 -25
- package/dist/queue/interfaces/IRateLimitConfig.d.ts +1 -0
- package/dist/queue/utils/rateLimit.utils.js +12 -0
- package/package.json +1 -1
|
@@ -44,7 +44,7 @@ class CronicleService {
|
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
46
|
catch (error) {
|
|
47
|
-
(0, config_1.getConfig)().LOGGER.error(`Failed to create
|
|
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
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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 (
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
|
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) {
|
|
@@ -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
|
}
|