dt-common-device 1.0.12 → 1.0.14
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/README.md +15 -35
- package/dist/config/config.d.ts +13 -0
- package/dist/config/config.js +30 -0
- package/dist/db/db.d.ts +2 -0
- package/dist/db/db.js +15 -0
- package/dist/db/index.d.ts +2 -0
- package/dist/db/index.js +18 -0
- package/dist/db/redis.d.ts +2 -0
- package/dist/db/redis.js +22 -0
- package/dist/device/cloud/entities/CloudDevice.d.ts +15 -0
- package/dist/device/cloud/entities/CloudDevice.js +42 -0
- package/dist/device/cloud/entities/DeviceFactory.d.ts +6 -0
- package/dist/device/cloud/entities/DeviceFactory.js +13 -0
- package/dist/device/cloud/entities/index.d.ts +2 -0
- package/dist/device/cloud/entities/index.js +18 -0
- package/dist/device/cloud/interfaces/ICloudDevice.d.ts +9 -0
- package/dist/device/cloud/interfaces/ICloudDevice.js +2 -0
- package/dist/device/cloud/interfaces/ICloudDeviceService.d.ts +4 -0
- package/dist/device/cloud/interfaces/ICloudDeviceService.js +2 -0
- package/dist/device/cloud/interfaces/IConnectionService.js +0 -1
- package/dist/device/cloud/interfaces/index.d.ts +2 -0
- package/dist/device/cloud/interfaces/index.js +2 -0
- package/dist/device/cloud/services/CloudDevice.service.d.ts +5 -0
- package/dist/device/cloud/services/CloudDevice.service.js +6 -0
- package/dist/device/cloud/services/Connection.service.d.ts +1 -1
- package/dist/device/cloud/services/index.d.ts +2 -3
- package/dist/device/cloud/services/index.js +16 -8
- package/dist/device/cloud/types.d.ts +9 -68
- package/dist/device/cloud/types.js +0 -12
- package/dist/device/local/interfaces/IConnection.d.ts +16 -0
- package/dist/device/local/interfaces/IConnection.js +2 -0
- package/dist/device/local/interfaces/IDevice.d.ts +4 -0
- package/dist/device/local/services/Connection.service.d.ts +5 -0
- package/dist/device/local/services/Connection.service.js +14 -0
- package/dist/device/local/services/Device.service.d.ts +7 -3
- package/dist/device/local/services/Device.service.js +85 -31
- package/dist/device/local/services/index.d.ts +2 -1
- package/dist/device/local/services/index.js +4 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.js +8 -27
- package/package.json +7 -9
- package/src/config/config.ts +31 -0
- package/src/db/db.ts +15 -0
- package/src/db/index.ts +2 -0
- package/src/db/redis.ts +18 -0
- package/src/device/cloud/entities/CloudDevice.ts +56 -0
- package/src/device/cloud/entities/DeviceFactory.ts +14 -0
- package/src/device/cloud/entities/index.ts +2 -0
- package/src/device/cloud/interfaces/ICloudDevice.ts +15 -0
- package/src/device/cloud/interfaces/ICloudDeviceService.ts +6 -0
- package/src/device/cloud/interfaces/IConnectionService.ts +0 -2
- package/src/device/cloud/interfaces/index.ts +2 -0
- package/src/device/cloud/services/CloudDevice.service.ts +6 -0
- package/src/device/cloud/services/Connection.service.ts +1 -1
- package/src/device/cloud/services/index.ts +2 -5
- package/src/device/cloud/types.ts +9 -63
- package/src/device/local/interfaces/IConnection.ts +17 -0
- package/src/device/local/interfaces/IDevice.ts +4 -0
- package/src/device/local/interfaces/index.ts +1 -1
- package/src/device/local/services/Connection.service.ts +15 -0
- package/src/device/local/services/Device.service.ts +107 -31
- package/src/device/local/services/index.ts +2 -1
- package/src/index.ts +9 -5
- package/src/device/cloud/services/Device.service.ts +0 -41
- package/src/device/cloud/services/Hub.service.ts +0 -34
|
@@ -3,25 +3,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
//TODO: Import Redis
|
|
6
|
+
exports.LocalDeviceService = void 0;
|
|
8
7
|
const axios_1 = __importDefault(require("axios"));
|
|
9
8
|
const config_1 = require("../../../config/config");
|
|
10
9
|
const dt_pub_sub_1 = require("dt-pub-sub");
|
|
11
10
|
const dt_audit_library_1 = require("dt-audit-library");
|
|
12
11
|
const EventHandler_1 = require("../handler/EventHandler");
|
|
13
12
|
const lodash_1 = require("lodash");
|
|
14
|
-
|
|
13
|
+
const Alert_service_1 = require("./Alert.service");
|
|
14
|
+
const db_1 = require("../../../db");
|
|
15
|
+
class LocalDeviceService {
|
|
15
16
|
constructor() {
|
|
16
17
|
this.source = "dt-common-device";
|
|
17
18
|
const { DEVICE_SERVICE } = (0, config_1.getConfig)();
|
|
18
19
|
if (!DEVICE_SERVICE) {
|
|
19
20
|
throw new Error("DEVICE_SERVICE is not configured. Call initialize() first with DEVICE_SERVICE.");
|
|
20
21
|
}
|
|
22
|
+
this.redis = (0, db_1.getRedisClient)();
|
|
23
|
+
this.postgres = (0, db_1.getPostgresClient)();
|
|
21
24
|
this.baseUrl = DEVICE_SERVICE;
|
|
22
25
|
(0, config_1.checkAwsEnv)();
|
|
23
26
|
(0, config_1.ensureAuditInitialized)();
|
|
24
27
|
this.eventHandler = new EventHandler_1.EventHandler();
|
|
28
|
+
this.alertService = new Alert_service_1.AlertService();
|
|
25
29
|
}
|
|
26
30
|
async createDevice(body) {
|
|
27
31
|
await dt_pub_sub_1.eventDispatcher.publishEvent("device.created", body, this.source);
|
|
@@ -71,14 +75,11 @@ class DeviceService {
|
|
|
71
75
|
return await axios_1.default.get(`${this.baseUrl}/devices/${deviceId}/state`);
|
|
72
76
|
}
|
|
73
77
|
async setState(deviceId, state) {
|
|
74
|
-
// If old
|
|
78
|
+
// If old state and new state are different
|
|
75
79
|
const oldState = await this.getState(deviceId);
|
|
76
|
-
if (!(0, lodash_1.isEqual)(oldState, state)) {
|
|
77
|
-
this.eventHandler.onStateChange(deviceId, state);
|
|
80
|
+
if (!(0, lodash_1.isEqual)(oldState?.data?.state, state)) {
|
|
81
|
+
return await this.eventHandler.onStateChange(deviceId, state);
|
|
78
82
|
}
|
|
79
|
-
// If offline, check the time difference between the last offline status and current time
|
|
80
|
-
// Compare it with the baseline profile time of the device. If the difference is higher, then raise an operational alert
|
|
81
|
-
//deviceAlertService.raiseOperationalAlert();
|
|
82
83
|
}
|
|
83
84
|
async getStatus(deviceId) {
|
|
84
85
|
return await axios_1.default.get(`${this.baseUrl}/devices/${deviceId}/status`);
|
|
@@ -87,23 +88,38 @@ class DeviceService {
|
|
|
87
88
|
// If old status and new status are different
|
|
88
89
|
const oldStatus = await this.getStatus(deviceId);
|
|
89
90
|
if (!(0, lodash_1.isEqual)(oldStatus, status)) {
|
|
90
|
-
this.eventHandler.onStatusChange(deviceId, status);
|
|
91
|
+
return await this.eventHandler.onStatusChange(deviceId, status);
|
|
92
|
+
}
|
|
93
|
+
// If both old and new status are offline, check the time difference between the last offline status and current time
|
|
94
|
+
if (oldStatus?.data?.online === false &&
|
|
95
|
+
oldStatus?.data?.lastUpdated &&
|
|
96
|
+
status?.online === false) {
|
|
97
|
+
const lastOfflineTime = new Date(oldStatus?.data?.lastUpdated).getTime();
|
|
98
|
+
const currentTime = Date.now();
|
|
99
|
+
const timeDifference = currentTime - lastOfflineTime;
|
|
100
|
+
// Compare it with the baseline profile time of the device. If the difference is higher, then raise an operational alert
|
|
101
|
+
if (timeDifference > 1000 * 60 * 60 * 24) {
|
|
102
|
+
return await this.alertService.raiseOperationsAlert();
|
|
103
|
+
}
|
|
91
104
|
}
|
|
92
|
-
// If offline, check the time difference between the last offline status and current time
|
|
93
|
-
// Compare it with the baseline profile time of the device. If the difference is higher, then raise an operational alert
|
|
94
|
-
//deviceAlertService.raiseOperationalAlert();
|
|
95
105
|
}
|
|
96
106
|
async getBatteryLevel(deviceId) {
|
|
97
107
|
return await axios_1.default.get(`${this.baseUrl}/devices/${deviceId}/battery-level`);
|
|
98
108
|
}
|
|
99
109
|
async setBatteryLevel(deviceId, batteryLevel) {
|
|
100
|
-
// If old
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
|
|
110
|
+
// If old battery level and new battery level are different
|
|
111
|
+
const oldBatteryLevel = await this.getBatteryLevel(deviceId);
|
|
112
|
+
if (!(0, lodash_1.isEqual)(oldBatteryLevel?.data?.value, batteryLevel)) {
|
|
113
|
+
this.eventHandler.onBatteryLevelChange(deviceId, batteryLevel);
|
|
114
|
+
}
|
|
115
|
+
// If current battery level is less than 20% and lsat updated time is more than 8 hours, raise an energy alert
|
|
116
|
+
if (batteryLevel < 20 &&
|
|
117
|
+
oldBatteryLevel?.data?.value < 20 &&
|
|
118
|
+
new Date(oldBatteryLevel?.data?.lastUpdated).getTime() <
|
|
119
|
+
Date.now() - 1000 * 60 * 60 * 8) {
|
|
120
|
+
//TODO: Raise an energy alert
|
|
121
|
+
await this.alertService.raiseEnergyAlert();
|
|
122
|
+
}
|
|
107
123
|
}
|
|
108
124
|
async getMetaData(deviceId) {
|
|
109
125
|
return await axios_1.default.get(`${this.baseUrl}/devices/${deviceId}/metaData`);
|
|
@@ -121,11 +137,21 @@ class DeviceService {
|
|
|
121
137
|
}
|
|
122
138
|
async getDeviceByZone(zoneId) {
|
|
123
139
|
try {
|
|
124
|
-
//Step 1: Check if zone data available in
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
140
|
+
// Step 1: Check if zone data is available in Redis
|
|
141
|
+
let cached = await this.redis.get(`zone:${zoneId}`);
|
|
142
|
+
if (cached) {
|
|
143
|
+
// Parse if stored as JSON string
|
|
144
|
+
return typeof cached === "string" ? JSON.parse(cached) : cached;
|
|
145
|
+
}
|
|
146
|
+
// If not available, fetch from PostgreSQL DB
|
|
147
|
+
const result = await this.postgres.query("SELECT * FROM dt_devices WHERE zoneId = $1", [zoneId]);
|
|
148
|
+
if (result.rows.length > 0) {
|
|
149
|
+
// Store in Redis as JSON string
|
|
150
|
+
await this.redis.set(`zone:${zoneId}`, JSON.stringify(result.rows[0]));
|
|
151
|
+
return result.rows[0];
|
|
152
|
+
}
|
|
153
|
+
// If data is not available, return null
|
|
154
|
+
return null;
|
|
129
155
|
}
|
|
130
156
|
catch (error) {
|
|
131
157
|
console.log(error);
|
|
@@ -134,16 +160,44 @@ class DeviceService {
|
|
|
134
160
|
}
|
|
135
161
|
async getDevicesByAccessGroup(accessGroupId) {
|
|
136
162
|
try {
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
163
|
+
// Try to get from Redis
|
|
164
|
+
let cached = await this.redis.get(`accessGroup:${accessGroupId}`);
|
|
165
|
+
if (cached) {
|
|
166
|
+
return typeof cached === "string" ? JSON.parse(cached) : cached;
|
|
167
|
+
}
|
|
168
|
+
// Fetch from Postgres if not in cache
|
|
169
|
+
const result = await this.postgres.query("SELECT * FROM access_groups WHERE id = $1", [accessGroupId]);
|
|
170
|
+
if (result.rows.length > 0) {
|
|
171
|
+
// Cache in Redis as JSON string
|
|
172
|
+
await this.redis.set(`accessGroup:${accessGroupId}`, JSON.stringify(result.rows[0]));
|
|
173
|
+
return result.rows[0];
|
|
174
|
+
}
|
|
175
|
+
return null;
|
|
142
176
|
}
|
|
143
177
|
catch (error) {
|
|
144
178
|
console.log(error);
|
|
145
179
|
throw new Error("Failed to get devices by access group");
|
|
146
180
|
}
|
|
147
181
|
}
|
|
182
|
+
async getPropertyPreferences(propertyId) {
|
|
183
|
+
try {
|
|
184
|
+
const propertyPreferences = await this.redis.get(`propertyPreferences:${propertyId}`);
|
|
185
|
+
if (!propertyPreferences) {
|
|
186
|
+
const propertyPreferences = await this.postgres.query("SELECT * FROM property_preferences WHERE property_id = $1", [propertyId]);
|
|
187
|
+
if (propertyPreferences.rows.length > 0) {
|
|
188
|
+
await this.redis.set(`propertyPreferences:${propertyId}`, propertyPreferences.rows[0]);
|
|
189
|
+
return propertyPreferences.rows[0];
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
return propertyPreferences;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (error) {
|
|
198
|
+
console.log(error);
|
|
199
|
+
throw new Error("Failed to get property preferences");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
148
202
|
}
|
|
149
|
-
exports.
|
|
203
|
+
exports.LocalDeviceService = LocalDeviceService;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LocalHubService = exports.LocalDeviceService = void 0;
|
|
3
|
+
exports.ConnectionService = exports.LocalHubService = exports.LocalDeviceService = void 0;
|
|
4
4
|
var Device_service_1 = require("./Device.service");
|
|
5
|
-
Object.defineProperty(exports, "LocalDeviceService", { enumerable: true, get: function () { return Device_service_1.
|
|
5
|
+
Object.defineProperty(exports, "LocalDeviceService", { enumerable: true, get: function () { return Device_service_1.LocalDeviceService; } });
|
|
6
6
|
var Hub_service_1 = require("./Hub.service");
|
|
7
7
|
Object.defineProperty(exports, "LocalHubService", { enumerable: true, get: function () { return Hub_service_1.HubService; } });
|
|
8
|
+
var Connection_service_1 = require("./Connection.service");
|
|
9
|
+
Object.defineProperty(exports, "ConnectionService", { enumerable: true, get: function () { return Connection_service_1.ConnectionService; } });
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { CloudDeviceService,
|
|
2
|
-
export {
|
|
3
|
-
export
|
|
1
|
+
export { CloudDeviceService, ConnectionService as CloudConnectionService, } from "./device/cloud/services";
|
|
2
|
+
export { CloudDevice, DeviceFactory } from "./device/cloud/entities";
|
|
3
|
+
export { LocalDeviceService, LocalHubService, ConnectionService, } from "./device/local/services";
|
|
4
|
+
export * from "./device/cloud/interfaces";
|
|
4
5
|
export * from "./device/cloud/types";
|
|
5
|
-
export *
|
|
6
|
+
export * from "./device/local/interfaces";
|
|
6
7
|
export { initialize, getConfig } from "./config/config";
|
package/dist/index.js
CHANGED
|
@@ -11,45 +11,26 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
11
11
|
if (k2 === undefined) k2 = k;
|
|
12
12
|
o[k2] = m[k];
|
|
13
13
|
}));
|
|
14
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
-
}) : function(o, v) {
|
|
17
|
-
o["default"] = v;
|
|
18
|
-
});
|
|
19
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
-
var ownKeys = function(o) {
|
|
21
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
-
var ar = [];
|
|
23
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
-
return ar;
|
|
25
|
-
};
|
|
26
|
-
return ownKeys(o);
|
|
27
|
-
};
|
|
28
|
-
return function (mod) {
|
|
29
|
-
if (mod && mod.__esModule) return mod;
|
|
30
|
-
var result = {};
|
|
31
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
-
__setModuleDefault(result, mod);
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
})();
|
|
36
14
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
37
15
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
38
16
|
};
|
|
39
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
-
exports.getConfig = exports.initialize = exports.
|
|
18
|
+
exports.getConfig = exports.initialize = exports.ConnectionService = exports.LocalHubService = exports.LocalDeviceService = exports.DeviceFactory = exports.CloudDevice = exports.CloudConnectionService = exports.CloudDeviceService = void 0;
|
|
41
19
|
// Cloud exports
|
|
42
20
|
var services_1 = require("./device/cloud/services");
|
|
43
21
|
Object.defineProperty(exports, "CloudDeviceService", { enumerable: true, get: function () { return services_1.CloudDeviceService; } });
|
|
44
|
-
Object.defineProperty(exports, "
|
|
45
|
-
|
|
22
|
+
Object.defineProperty(exports, "CloudConnectionService", { enumerable: true, get: function () { return services_1.ConnectionService; } });
|
|
23
|
+
var entities_1 = require("./device/cloud/entities");
|
|
24
|
+
Object.defineProperty(exports, "CloudDevice", { enumerable: true, get: function () { return entities_1.CloudDevice; } });
|
|
25
|
+
Object.defineProperty(exports, "DeviceFactory", { enumerable: true, get: function () { return entities_1.DeviceFactory; } });
|
|
46
26
|
var services_2 = require("./device/local/services");
|
|
47
27
|
Object.defineProperty(exports, "LocalDeviceService", { enumerable: true, get: function () { return services_2.LocalDeviceService; } });
|
|
48
28
|
Object.defineProperty(exports, "LocalHubService", { enumerable: true, get: function () { return services_2.LocalHubService; } });
|
|
49
|
-
exports
|
|
29
|
+
Object.defineProperty(exports, "ConnectionService", { enumerable: true, get: function () { return services_2.ConnectionService; } });
|
|
30
|
+
__exportStar(require("./device/cloud/interfaces"), exports);
|
|
50
31
|
__exportStar(require("./device/cloud/types"), exports);
|
|
51
32
|
// Local exports
|
|
52
|
-
|
|
33
|
+
__exportStar(require("./device/local/interfaces"), exports);
|
|
53
34
|
//initialize export
|
|
54
35
|
var config_1 = require("./config/config");
|
|
55
36
|
Object.defineProperty(exports, "initialize", { enumerable: true, get: function () { return config_1.initialize; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dt-common-device",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -30,19 +30,17 @@
|
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/lodash": "^4.17.19",
|
|
32
32
|
"@types/node": "^20.0.0",
|
|
33
|
+
"@types/pg": "8.15.4",
|
|
33
34
|
"ts-node": "^10.9.2",
|
|
34
35
|
"typescript": "^5.8.3"
|
|
35
36
|
},
|
|
36
37
|
"dependencies": {
|
|
37
|
-
"axios": "
|
|
38
|
+
"axios": "1.10.0",
|
|
38
39
|
"dt-audit-library": "^1.0.3",
|
|
39
40
|
"dt-pub-sub": "^1.0.0",
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
},
|
|
45
|
-
"overrides": {
|
|
46
|
-
"axios": "^1.10.0"
|
|
41
|
+
"ioredis": "5.6.1",
|
|
42
|
+
"lodash": "^4.17.21",
|
|
43
|
+
"pg": "8.16.3",
|
|
44
|
+
"redis": "5.5.6"
|
|
47
45
|
}
|
|
48
46
|
}
|
package/src/config/config.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { DeviceConfig } from "../types";
|
|
2
2
|
import { initializeAudit } from "dt-audit-library";
|
|
3
|
+
import dotenv from "dotenv";
|
|
4
|
+
dotenv.config();
|
|
3
5
|
|
|
4
6
|
let config: DeviceConfig | null = null;
|
|
5
7
|
let auditInitialized = false;
|
|
@@ -61,3 +63,32 @@ export function ensureAuditInitialized() {
|
|
|
61
63
|
initializeAudit(apiKey, host);
|
|
62
64
|
auditInitialized = true;
|
|
63
65
|
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Returns the PostgreSQL DB URI from environment variables.
|
|
69
|
+
* Throws an error if not set.
|
|
70
|
+
*/
|
|
71
|
+
export function getPostgresDbUri(): string {
|
|
72
|
+
const uri = process.env.DATABASE_URL;
|
|
73
|
+
if (!uri) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
"dt-common-device: POSTGRESQL_DB_URI must be set in environment variables or .env file"
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
return uri;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns the Redis DB Host and port from environment variables.
|
|
83
|
+
* Throws an error if not set.
|
|
84
|
+
*/
|
|
85
|
+
export function getRedisDbHostAndPort(): { host: string; port: number } {
|
|
86
|
+
const host = process.env.REDIS_HOST;
|
|
87
|
+
const port = process.env.REDIS_PORT;
|
|
88
|
+
if (!host || !port) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
"dt-common-device: REDIS_HOST and REDIS_PORT must be set in environment variables"
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
return { host, port: Number(port) };
|
|
94
|
+
}
|
package/src/db/db.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Pool } from "pg";
|
|
2
|
+
import { getPostgresDbUri } from "../config/config";
|
|
3
|
+
|
|
4
|
+
const dbUri = getPostgresDbUri();
|
|
5
|
+
|
|
6
|
+
let pool: Pool | null = null;
|
|
7
|
+
|
|
8
|
+
export function getPostgresClient() {
|
|
9
|
+
if (!pool) {
|
|
10
|
+
pool = new Pool({
|
|
11
|
+
connectionString: dbUri,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return pool;
|
|
15
|
+
}
|
package/src/db/index.ts
ADDED
package/src/db/redis.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getRedisDbHostAndPort } from "../config/config";
|
|
2
|
+
import Redis from "ioredis";
|
|
3
|
+
|
|
4
|
+
let redisClient: Redis | null = null;
|
|
5
|
+
|
|
6
|
+
export function getRedisClient() {
|
|
7
|
+
if (!redisClient) {
|
|
8
|
+
const { host, port } = getRedisDbHostAndPort();
|
|
9
|
+
redisClient = new Redis({
|
|
10
|
+
host,
|
|
11
|
+
port,
|
|
12
|
+
});
|
|
13
|
+
redisClient.on("error", (error) => {
|
|
14
|
+
console.error("Redis error:", error);
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return redisClient;
|
|
18
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { IDevice } from "../../local/interfaces";
|
|
2
|
+
import { ICloudDevice } from "../interfaces/ICloudDevice";
|
|
3
|
+
import { ICloudDeviceService } from "../interfaces/ICloudDeviceService";
|
|
4
|
+
import { IConnection } from "../types";
|
|
5
|
+
|
|
6
|
+
export abstract class CloudDevice implements ICloudDevice {
|
|
7
|
+
deviceId: string;
|
|
8
|
+
localDevice?: IDevice;
|
|
9
|
+
connection?: IConnection;
|
|
10
|
+
cloudDeviceService: ICloudDeviceService;
|
|
11
|
+
|
|
12
|
+
constructor(device: IDevice, cloudDeviceService: ICloudDeviceService) {
|
|
13
|
+
this.deviceId = device.deviceId;
|
|
14
|
+
this.localDevice = device;
|
|
15
|
+
this.cloudDeviceService = cloudDeviceService;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async getDevice(
|
|
19
|
+
connectionId: string,
|
|
20
|
+
deviceId: string
|
|
21
|
+
): Promise<Record<string, any>> {
|
|
22
|
+
throw new Error("Method not implemented in Super Class.");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async getBattery(deviceId: string): Promise<number | string> {
|
|
26
|
+
throw new Error("Method not implemented in Super Class.");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async getState(deviceId: string): Promise<string> {
|
|
30
|
+
throw new Error("Method not implemented in Super Class.");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async getStatus(connectionId: string, deviceId: string): Promise<string> {
|
|
34
|
+
throw new Error("Method not implemented in Super Class.");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
Usage Example:
|
|
40
|
+
|
|
41
|
+
// When extending CloudDevice, you can now do:
|
|
42
|
+
class MyCloudDevice extends CloudDevice {
|
|
43
|
+
constructor(device: IDevice, cloudDeviceService: ICloudDeviceService) {
|
|
44
|
+
super(device, cloudDeviceService);
|
|
45
|
+
// Additional initialization if needed
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Create and initialize in one step:
|
|
50
|
+
const device = await MyCloudDevice.create(device, cloudDeviceService);
|
|
51
|
+
// The device is now fully initialized with connection and localDevice loaded
|
|
52
|
+
|
|
53
|
+
// Or if you need to create without auto-initialization:
|
|
54
|
+
const device = new MyCloudDevice(device, cloudDeviceService);
|
|
55
|
+
await device.initialize(); // Manual initialization
|
|
56
|
+
*/
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IDevice } from "../../local/interfaces";
|
|
2
|
+
import { LocalDeviceService } from "../../local/services/Device.service";
|
|
3
|
+
|
|
4
|
+
export class DeviceFactory {
|
|
5
|
+
private readonly localDeviceService: LocalDeviceService;
|
|
6
|
+
|
|
7
|
+
constructor() {
|
|
8
|
+
this.localDeviceService = new LocalDeviceService();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async getDevice(deviceId: string): Promise<IDevice> {
|
|
12
|
+
return await this.localDeviceService.getDevice(deviceId);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// CloudDevice interface
|
|
2
|
+
import { ICloudDeviceService } from "./ICloudDeviceService";
|
|
3
|
+
|
|
4
|
+
export interface ICloudDevice {
|
|
5
|
+
deviceId: string;
|
|
6
|
+
cloudDeviceService: ICloudDeviceService;
|
|
7
|
+
|
|
8
|
+
getDevice(
|
|
9
|
+
connectionId: string,
|
|
10
|
+
deviceId: string
|
|
11
|
+
): Promise<Record<string, any>>;
|
|
12
|
+
getBattery(deviceId: string): Promise<number | string>;
|
|
13
|
+
getState(deviceId: string): Promise<string>;
|
|
14
|
+
getStatus(connectionId: string, deviceId: string): Promise<string>;
|
|
15
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Device Cloud Service - Class Implementation
|
|
2
2
|
import { IConnectionService } from "../interfaces";
|
|
3
3
|
import {
|
|
4
|
-
IConnection,
|
|
5
4
|
IDeviceAccountResponse,
|
|
6
5
|
IConnectionConnectParams,
|
|
6
|
+
IConnection,
|
|
7
7
|
} from "../types";
|
|
8
8
|
|
|
9
9
|
export abstract class ConnectionService implements IConnectionService {
|
|
@@ -1,5 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export { DeviceService as CloudDeviceService } from "./Device.service";
|
|
4
|
-
export { ConnectionService as CloudConnectionService } from "./Connection.service";
|
|
5
|
-
export { HubService as CloudHubService } from "./Hub.service";
|
|
1
|
+
export * from "./CloudDevice.service";
|
|
2
|
+
export * from "./Connection.service";
|
|
@@ -25,60 +25,6 @@ export interface IConnectionPagination {
|
|
|
25
25
|
limit: number;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
/**
|
|
29
|
-
* Represents a device in the system.
|
|
30
|
-
* All date fields must be ISO 8601 strings.
|
|
31
|
-
*/
|
|
32
|
-
export interface IDevice {
|
|
33
|
-
deviceId: string;
|
|
34
|
-
propertyId: string;
|
|
35
|
-
name: string;
|
|
36
|
-
hubId: string[];
|
|
37
|
-
specifications?: {
|
|
38
|
-
manufacturer?: string;
|
|
39
|
-
model?: string;
|
|
40
|
-
firmware?: {
|
|
41
|
-
version?: string;
|
|
42
|
-
newVersionAvailable?: boolean;
|
|
43
|
-
newVersion?: string;
|
|
44
|
-
mandatoryUpdate?: boolean;
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
protocol?: {
|
|
48
|
-
location?: {
|
|
49
|
-
id?: string;
|
|
50
|
-
name?: string;
|
|
51
|
-
city?: string;
|
|
52
|
-
};
|
|
53
|
-
name?: string;
|
|
54
|
-
room?: {
|
|
55
|
-
id?: string;
|
|
56
|
-
name?: string;
|
|
57
|
-
};
|
|
58
|
-
accountId?: string;
|
|
59
|
-
};
|
|
60
|
-
deviceType: {
|
|
61
|
-
id: string;
|
|
62
|
-
type: string;
|
|
63
|
-
};
|
|
64
|
-
status: {
|
|
65
|
-
online: boolean;
|
|
66
|
-
error?: {
|
|
67
|
-
type?: string;
|
|
68
|
-
message?: string;
|
|
69
|
-
};
|
|
70
|
-
lastUpdated?: string;
|
|
71
|
-
};
|
|
72
|
-
state?: Record<string, any>;
|
|
73
|
-
metaData?: Record<string, any>;
|
|
74
|
-
createdAt?: Date;
|
|
75
|
-
updatedAt?: Date;
|
|
76
|
-
isDeleted?: boolean;
|
|
77
|
-
hubDeviceDetails?: IDevice[];
|
|
78
|
-
parentZones?: { id: string; name: string }[];
|
|
79
|
-
zone?: { id: string; name: string };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
28
|
/**
|
|
83
29
|
* Device account response from provider.
|
|
84
30
|
* WARNING: Do not log or expose connection_access_token.
|
|
@@ -99,13 +45,13 @@ export interface IConnectionConnectParams {
|
|
|
99
45
|
[key: string]: unknown;
|
|
100
46
|
}
|
|
101
47
|
|
|
102
|
-
export
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
48
|
+
export interface ConnectionProvider {
|
|
49
|
+
DEVICETHREAD: "Devicethread";
|
|
50
|
+
SMARTTHINGS: "Smartthings";
|
|
51
|
+
SALTOKS: "SaltoKS";
|
|
52
|
+
TUYA: "Tuya";
|
|
53
|
+
TTLOCK: "TTLock";
|
|
54
|
+
SCHLAGE: "Schlage";
|
|
55
|
+
YALEWIFI: "YaleWifi";
|
|
56
|
+
SENSIBO: "Sensibo";
|
|
111
57
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ConnectionProvider } from "../../cloud/types";
|
|
2
|
+
|
|
3
|
+
export interface IConnection {
|
|
4
|
+
id?: string;
|
|
5
|
+
createdAt?: Date;
|
|
6
|
+
updatedAt?: Date;
|
|
7
|
+
isDeleted?: boolean;
|
|
8
|
+
connectionName: string;
|
|
9
|
+
connectionRefId: string;
|
|
10
|
+
propertyId: string;
|
|
11
|
+
connectionProvider: ConnectionProvider;
|
|
12
|
+
accessToken?: string;
|
|
13
|
+
clientId?: string;
|
|
14
|
+
clientSecret?: string;
|
|
15
|
+
isActive?: boolean;
|
|
16
|
+
metaData?: any;
|
|
17
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from "./IDevice";
|
|
2
|
-
export * from "./IHub";
|
|
2
|
+
export * from "./IHub";
|