tsvesync 1.0.11 → 1.0.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/index.d.ts +7 -0
- package/dist/index.js +25 -0
- package/dist/lib/helpers.d.ts +52 -51
- package/dist/lib/helpers.js +135 -112
- package/dist/lib/logger.d.ts +23 -0
- package/dist/lib/logger.js +54 -0
- package/dist/lib/vesync.d.ts +57 -15
- package/dist/lib/vesync.js +341 -217
- package/dist/lib/vesyncBaseDevice.d.ts +25 -50
- package/dist/lib/vesyncBaseDevice.js +63 -90
- package/dist/lib/vesyncBulb.d.ts +88 -0
- package/dist/lib/vesyncBulb.js +295 -1
- package/dist/lib/vesyncBulbImpl.d.ts +38 -0
- package/dist/lib/vesyncBulbImpl.js +230 -0
- package/dist/lib/vesyncFan.d.ts +55 -67
- package/dist/lib/vesyncFan.js +366 -213
- package/dist/lib/vesyncFanImpl.d.ts +173 -0
- package/dist/lib/vesyncFanImpl.js +909 -0
- package/dist/lib/vesyncOutlet.d.ts +70 -0
- package/dist/lib/vesyncOutlet.js +213 -1
- package/dist/lib/vesyncOutletImpl.d.ts +70 -0
- package/dist/lib/vesyncOutletImpl.js +245 -0
- package/dist/lib/vesyncSwitch.d.ts +45 -0
- package/dist/lib/vesyncSwitch.js +77 -1
- package/dist/lib/vesyncSwitchImpl.d.ts +82 -0
- package/dist/lib/vesyncSwitchImpl.js +344 -0
- package/package.json +1 -1
- package/src/index.ts +14 -0
- package/src/lib/helpers.ts +3 -2
- package/src/lib/logger.ts +60 -0
- package/src/lib/vesync.ts +42 -43
- package/src/lib/vesyncBaseDevice.ts +8 -7
- package/src/lib/vesyncBulb.ts +138 -30
- package/src/lib/vesyncBulbImpl.ts +113 -44
- package/src/lib/vesyncFan.ts +2 -4
- package/src/lib/vesyncFanImpl.ts +314 -42
- package/src/lib/vesyncOutlet.ts +140 -13
- package/src/lib/vesyncOutletImpl.ts +41 -0
- package/src/lib/vesyncSwitch.ts +3 -454
- package/src/lib/vesyncSwitchImpl.ts +66 -16
package/dist/lib/vesync.js
CHANGED
|
@@ -1,104 +1,116 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var _a;
|
|
36
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
exports.VeSync = void 0;
|
|
38
2
|
/**
|
|
39
3
|
* VeSync API Device Library
|
|
40
4
|
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.VeSync = void 0;
|
|
41
7
|
const helpers_1 = require("./helpers");
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
8
|
+
const vesyncFanImpl_1 = require("./vesyncFanImpl");
|
|
9
|
+
const vesyncOutletImpl_1 = require("./vesyncOutletImpl");
|
|
10
|
+
const vesyncSwitchImpl_1 = require("./vesyncSwitchImpl");
|
|
11
|
+
const vesyncBulbImpl_1 = require("./vesyncBulbImpl");
|
|
12
|
+
const logger_1 = require("./logger");
|
|
47
13
|
const DEFAULT_ENERGY_UPDATE_INTERVAL = 21600;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const bulbs = (devType, config, manager) => {
|
|
62
|
-
const bulbCls = bulbMods.bulbModules[devType];
|
|
63
|
-
return ['bulbs', new bulbCls(config, manager)];
|
|
64
|
-
};
|
|
65
|
-
const kitchen = (devType, config, manager) => {
|
|
66
|
-
const kitchenCls = kitchenMods.kitchenModules[devType];
|
|
67
|
-
return ['kitchen', new kitchenCls(config, manager)];
|
|
14
|
+
/**
|
|
15
|
+
* Create device instance based on type
|
|
16
|
+
*/
|
|
17
|
+
function objectFactory(details, manager) {
|
|
18
|
+
const deviceType = details.deviceType;
|
|
19
|
+
let DeviceClass = null;
|
|
20
|
+
let category = 'unknown';
|
|
21
|
+
// Map of device categories to their module dictionaries
|
|
22
|
+
const allModules = {
|
|
23
|
+
outlets: vesyncOutletImpl_1.outletModules,
|
|
24
|
+
fans: vesyncFanImpl_1.fanModules,
|
|
25
|
+
bulbs: vesyncBulbImpl_1.bulbModules,
|
|
26
|
+
switches: vesyncSwitchImpl_1.switchModules
|
|
68
27
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
28
|
+
// First try exact match in all modules
|
|
29
|
+
for (const [cat, modules] of Object.entries(allModules)) {
|
|
30
|
+
if (deviceType in modules) {
|
|
31
|
+
DeviceClass = modules[deviceType];
|
|
32
|
+
category = cat;
|
|
33
|
+
logger_1.logger.debug(`Found exact match for ${deviceType} in ${cat} modules`);
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
77
36
|
}
|
|
78
|
-
|
|
79
|
-
|
|
37
|
+
// If no exact match, try to find a base class
|
|
38
|
+
if (!DeviceClass) {
|
|
39
|
+
// Device type prefix mapping
|
|
40
|
+
const prefixMap = {
|
|
41
|
+
// Fans
|
|
42
|
+
'Core': 'fans',
|
|
43
|
+
'LAP': 'fans',
|
|
44
|
+
'LTF': 'fans',
|
|
45
|
+
'Classic': 'fans',
|
|
46
|
+
'Dual': 'fans',
|
|
47
|
+
'LUH': 'fans',
|
|
48
|
+
'LEH': 'fans',
|
|
49
|
+
'LV-PUR': 'fans',
|
|
50
|
+
'LV-RH': 'fans',
|
|
51
|
+
// Outlets
|
|
52
|
+
'wifi-switch': 'outlets',
|
|
53
|
+
'ESW03': 'outlets',
|
|
54
|
+
'ESW01': 'outlets',
|
|
55
|
+
'ESW15': 'outlets',
|
|
56
|
+
'ESO': 'outlets',
|
|
57
|
+
// Switches
|
|
58
|
+
'ESWL': 'switches',
|
|
59
|
+
'ESWD': 'switches',
|
|
60
|
+
// Bulbs
|
|
61
|
+
'ESL': 'bulbs',
|
|
62
|
+
'XYD': 'bulbs'
|
|
63
|
+
};
|
|
64
|
+
// Find category based on device type prefix
|
|
65
|
+
for (const [prefix, cat] of Object.entries(prefixMap)) {
|
|
66
|
+
if (deviceType.startsWith(prefix)) {
|
|
67
|
+
category = cat;
|
|
68
|
+
logger_1.logger.debug(`Device type ${deviceType} matched prefix ${prefix} -> category ${cat}`);
|
|
69
|
+
// Try to find a base class in this category's modules
|
|
70
|
+
const modules = allModules[cat];
|
|
71
|
+
for (const [moduleType, ModuleClass] of Object.entries(modules)) {
|
|
72
|
+
const baseType = moduleType.split('-')[0]; // e.g., ESL100 from ESL100-USA
|
|
73
|
+
if (deviceType.startsWith(baseType)) {
|
|
74
|
+
DeviceClass = ModuleClass;
|
|
75
|
+
logger_1.logger.debug(`Found base type match: ${deviceType} -> ${baseType}`);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
80
82
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
if (DeviceClass) {
|
|
84
|
+
try {
|
|
85
|
+
// Add category to device details
|
|
86
|
+
details.deviceCategory = category;
|
|
87
|
+
const device = new DeviceClass(details, manager);
|
|
88
|
+
return [category, device];
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
logger_1.logger.error(`Error creating device instance for ${deviceType}:`, error);
|
|
92
|
+
return [category, null];
|
|
93
|
+
}
|
|
83
94
|
}
|
|
84
95
|
else {
|
|
85
|
-
|
|
86
|
-
return [
|
|
96
|
+
logger_1.logger.warn(`No device class found for type: ${deviceType}`);
|
|
97
|
+
return [category, null];
|
|
87
98
|
}
|
|
88
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* VeSync Manager Class
|
|
102
|
+
*/
|
|
89
103
|
class VeSync {
|
|
104
|
+
/**
|
|
105
|
+
* Initialize VeSync Manager
|
|
106
|
+
*/
|
|
90
107
|
constructor(username, password, timeZone = helpers_1.DEFAULT_TZ, debug = false, redact = true) {
|
|
91
|
-
this.body = helpers_1.Helpers.reqBody(this, 'devicelist');
|
|
92
|
-
this[_a] = await helpers_1.Helpers.callApi('/cloud/v1/deviceManaged/devices', 'post', body, helpers_1.Helpers.reqHeaders(this));
|
|
93
108
|
this._debug = debug;
|
|
94
|
-
if (debug) {
|
|
95
|
-
// Set debug logging levels
|
|
96
|
-
console.debug('Debug logging enabled');
|
|
97
|
-
}
|
|
98
109
|
this._redact = redact;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
110
|
+
this._energyUpdateInterval = DEFAULT_ENERGY_UPDATE_INTERVAL;
|
|
111
|
+
this._energyCheck = true;
|
|
112
|
+
this._lastUpdateTs = null;
|
|
113
|
+
this._inProcess = false;
|
|
102
114
|
this.username = username;
|
|
103
115
|
this.password = password;
|
|
104
116
|
this.token = null;
|
|
@@ -107,29 +119,22 @@ class VeSync {
|
|
|
107
119
|
this.devices = null;
|
|
108
120
|
this.enabled = false;
|
|
109
121
|
this.updateInterval = helpers_1.API_RATE_LIMIT;
|
|
110
|
-
this.lastUpdateTs = null;
|
|
111
|
-
this.inProcess = false;
|
|
112
|
-
this._energyUpdateInterval = DEFAULT_ENERGY_UPDATE_INTERVAL;
|
|
113
|
-
this._energyCheck = true;
|
|
114
122
|
this.fans = [];
|
|
115
123
|
this.outlets = [];
|
|
116
124
|
this.switches = [];
|
|
117
125
|
this.bulbs = [];
|
|
118
126
|
this.scales = [];
|
|
119
|
-
this.kitchen = [];
|
|
120
127
|
this._devList = {
|
|
121
128
|
fans: this.fans,
|
|
122
129
|
outlets: this.outlets,
|
|
123
130
|
switches: this.switches,
|
|
124
|
-
bulbs: this.bulbs
|
|
125
|
-
kitchen: this.kitchen,
|
|
126
|
-
unknown: []
|
|
131
|
+
bulbs: this.bulbs
|
|
127
132
|
};
|
|
128
133
|
if (typeof timeZone === 'string' && timeZone) {
|
|
129
134
|
const regTest = /[^a-zA-Z/_]/;
|
|
130
135
|
if (regTest.test(timeZone)) {
|
|
131
136
|
this.timeZone = helpers_1.DEFAULT_TZ;
|
|
132
|
-
|
|
137
|
+
logger_1.logger.debug('Invalid characters in time zone - ', timeZone);
|
|
133
138
|
}
|
|
134
139
|
else {
|
|
135
140
|
this.timeZone = timeZone;
|
|
@@ -137,41 +142,47 @@ class VeSync {
|
|
|
137
142
|
}
|
|
138
143
|
else {
|
|
139
144
|
this.timeZone = helpers_1.DEFAULT_TZ;
|
|
140
|
-
|
|
145
|
+
logger_1.logger.debug('Time zone is not a string');
|
|
146
|
+
}
|
|
147
|
+
if (debug) {
|
|
148
|
+
this.debug = true;
|
|
149
|
+
}
|
|
150
|
+
if (redact) {
|
|
151
|
+
this.redact = true;
|
|
141
152
|
}
|
|
142
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* Get/Set debug mode
|
|
156
|
+
*/
|
|
143
157
|
get debug() {
|
|
144
158
|
return this._debug;
|
|
145
159
|
}
|
|
146
|
-
set debug(
|
|
147
|
-
this._debug =
|
|
148
|
-
// Set logging levels based on debug flag
|
|
149
|
-
if (newFlag) {
|
|
150
|
-
console.debug('Debug logging enabled');
|
|
151
|
-
}
|
|
160
|
+
set debug(flag) {
|
|
161
|
+
this._debug = flag;
|
|
152
162
|
}
|
|
163
|
+
/**
|
|
164
|
+
* Get/Set redact mode
|
|
165
|
+
*/
|
|
153
166
|
get redact() {
|
|
154
167
|
return this._redact;
|
|
155
168
|
}
|
|
156
|
-
set redact(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
helpers_1.Helpers.redact = false;
|
|
162
|
-
}
|
|
163
|
-
this._redact = newFlag;
|
|
169
|
+
set redact(flag) {
|
|
170
|
+
this._redact = flag;
|
|
171
|
+
helpers_1.Helpers.shouldRedact = flag;
|
|
164
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Get/Set energy update interval
|
|
175
|
+
*/
|
|
165
176
|
get energyUpdateInterval() {
|
|
166
177
|
return this._energyUpdateInterval;
|
|
167
178
|
}
|
|
168
|
-
set energyUpdateInterval(
|
|
169
|
-
if (
|
|
170
|
-
this._energyUpdateInterval =
|
|
179
|
+
set energyUpdateInterval(interval) {
|
|
180
|
+
if (interval > 0) {
|
|
181
|
+
this._energyUpdateInterval = interval;
|
|
171
182
|
}
|
|
172
183
|
}
|
|
173
184
|
/**
|
|
174
|
-
* Test if device should be removed
|
|
185
|
+
* Test if device should be removed
|
|
175
186
|
*/
|
|
176
187
|
static removeDevTest(device, newList) {
|
|
177
188
|
if (Array.isArray(newList) && device.cid) {
|
|
@@ -180,130 +191,243 @@ class VeSync {
|
|
|
180
191
|
return true;
|
|
181
192
|
}
|
|
182
193
|
}
|
|
194
|
+
logger_1.logger.debug(`Device removed - ${device.deviceName} - ${device.deviceType}`);
|
|
195
|
+
return false;
|
|
183
196
|
}
|
|
184
|
-
return
|
|
197
|
+
return true;
|
|
185
198
|
}
|
|
186
199
|
/**
|
|
187
|
-
*
|
|
200
|
+
* Test if new device should be added
|
|
188
201
|
*/
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
202
|
+
addDevTest(newDev) {
|
|
203
|
+
if ('cid' in newDev) {
|
|
204
|
+
for (const devices of Object.values(this._devList)) {
|
|
205
|
+
for (const dev of devices) {
|
|
206
|
+
if (dev.cid === newDev.cid) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
195
211
|
}
|
|
196
|
-
this.token = response.result.token;
|
|
197
|
-
this.accountId = response.result.accountID;
|
|
198
|
-
this.countryCode = response.result.countryCode;
|
|
199
|
-
this.enabled = true;
|
|
200
212
|
return true;
|
|
201
213
|
}
|
|
202
214
|
/**
|
|
203
|
-
*
|
|
215
|
+
* Remove devices not found in device list return
|
|
204
216
|
*/
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
217
|
+
removeOldDevices(devices) {
|
|
218
|
+
for (const [key, deviceList] of Object.entries(this._devList)) {
|
|
219
|
+
const before = deviceList.length;
|
|
220
|
+
this._devList[key] = deviceList.filter(device => VeSync.removeDevTest(device, devices));
|
|
221
|
+
const after = this._devList[key].length;
|
|
222
|
+
if (before !== after) {
|
|
223
|
+
logger_1.logger.debug(`${before - after} ${key} removed`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return true;
|
|
209
227
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
{
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
const deviceList = [...this.devices];
|
|
233
|
-
const toRemove = [];
|
|
234
|
-
// Build list of devices to remove
|
|
235
|
-
for (const devList of Object.values(this._devList)) {
|
|
236
|
-
for (const device of devList) {
|
|
237
|
-
if (!VeSync.removeDevTest(device, deviceList)) {
|
|
238
|
-
toRemove.push(device);
|
|
228
|
+
/**
|
|
229
|
+
* Correct devices without cid or uuid
|
|
230
|
+
*/
|
|
231
|
+
static setDevId(devices) {
|
|
232
|
+
const devRem = [];
|
|
233
|
+
devices.forEach((dev, index) => {
|
|
234
|
+
if (!dev.cid) {
|
|
235
|
+
if (dev.macID) {
|
|
236
|
+
dev.cid = dev.macID;
|
|
237
|
+
}
|
|
238
|
+
else if (dev.uuid) {
|
|
239
|
+
dev.cid = dev.uuid;
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
devRem.push(index);
|
|
243
|
+
logger_1.logger.warn(`Device with no ID - ${dev.deviceName || ''}`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
if (devRem.length > 0) {
|
|
248
|
+
return devices.filter((_, index) => !devRem.includes(index));
|
|
239
249
|
}
|
|
250
|
+
return devices;
|
|
240
251
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
252
|
+
/**
|
|
253
|
+
* Process device list and instantiate device objects
|
|
254
|
+
*/
|
|
255
|
+
processDevices(devList) {
|
|
256
|
+
// Ensure devices have proper IDs
|
|
257
|
+
const devices = VeSync.setDevId(devList);
|
|
258
|
+
// Count current devices
|
|
259
|
+
let numDevices = 0;
|
|
260
|
+
for (const deviceList of Object.values(this._devList)) {
|
|
261
|
+
numDevices += deviceList.length;
|
|
262
|
+
}
|
|
263
|
+
if (!devices || devices.length === 0) {
|
|
264
|
+
logger_1.logger.warn('No devices found in api return');
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
// Initialize new device list or remove old devices
|
|
268
|
+
if (numDevices === 0) {
|
|
269
|
+
logger_1.logger.debug('New device list initialized');
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
this.removeOldDevices(devices);
|
|
248
273
|
}
|
|
274
|
+
// Filter out devices that already exist
|
|
275
|
+
const newDevices = devices.filter(dev => this.addDevTest(dev));
|
|
276
|
+
// Required keys for device instantiation
|
|
277
|
+
const requiredKeys = ['deviceType', 'deviceName', 'deviceStatus', 'cid'];
|
|
278
|
+
// Process each new device
|
|
279
|
+
for (const dev of newDevices) {
|
|
280
|
+
// Verify required device properties
|
|
281
|
+
if (!requiredKeys.every(key => key in dev)) {
|
|
282
|
+
logger_1.logger.debug(`Error adding device - missing required properties: ${dev.deviceName || 'Unknown'}`);
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
const devType = dev.deviceType;
|
|
286
|
+
try {
|
|
287
|
+
// Create device instance using factory
|
|
288
|
+
const [category, deviceObj] = objectFactory(dev, this);
|
|
289
|
+
// Add device to appropriate category if valid
|
|
290
|
+
if (deviceObj && category in this._devList) {
|
|
291
|
+
this._devList[category].push(deviceObj);
|
|
292
|
+
logger_1.logger.debug(`Added ${devType} device to ${category} category`);
|
|
293
|
+
}
|
|
294
|
+
else if (category === 'unknown') {
|
|
295
|
+
logger_1.logger.debug(`Unknown device type: ${devType}`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
logger_1.logger.error(`Error creating device ${devType}:`, err);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
249
304
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
305
|
+
/**
|
|
306
|
+
* Get list of VeSync devices
|
|
307
|
+
*/
|
|
308
|
+
async getDevices() {
|
|
309
|
+
var _a, _b;
|
|
310
|
+
if (!this.enabled) {
|
|
311
|
+
logger_1.logger.error('Not logged in to VeSync');
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
this._inProcess = true;
|
|
315
|
+
let procReturn = false;
|
|
316
|
+
try {
|
|
317
|
+
const [response] = await helpers_1.Helpers.callApi('/cloud/v2/deviceManaged/devices', 'post', helpers_1.Helpers.reqBody(this, 'devicelist'), helpers_1.Helpers.reqHeaders(this));
|
|
318
|
+
if ((_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.list) {
|
|
319
|
+
const deviceList = response.result.list;
|
|
320
|
+
procReturn = this.processDevices(deviceList);
|
|
321
|
+
// Update the main devices array with all devices
|
|
322
|
+
this.devices = Object.values(this._devList).flat();
|
|
323
|
+
// Log device discovery results
|
|
324
|
+
logger_1.logger.debug('\n=== Device Discovery Summary ===');
|
|
325
|
+
logger_1.logger.debug(`Total devices processed: ${deviceList.length}`);
|
|
326
|
+
// Log device types found
|
|
327
|
+
const deviceTypes = deviceList.map((d) => d.deviceType);
|
|
328
|
+
logger_1.logger.debug('\nDevice types found:', deviceTypes);
|
|
329
|
+
// Log devices by category with details
|
|
330
|
+
logger_1.logger.debug('\nDevices by Category:');
|
|
331
|
+
logger_1.logger.debug('---------------------');
|
|
332
|
+
for (const [category, devices] of Object.entries(this._devList)) {
|
|
333
|
+
if (devices.length > 0) {
|
|
334
|
+
logger_1.logger.debug(`\n${category.toUpperCase()} (${devices.length} devices):`);
|
|
335
|
+
devices.forEach((d) => {
|
|
336
|
+
logger_1.logger.debug(` • ${d.deviceName}`);
|
|
337
|
+
logger_1.logger.debug(` Type: ${d.deviceType}`);
|
|
338
|
+
logger_1.logger.debug(` Status: ${d.deviceStatus}`);
|
|
339
|
+
logger_1.logger.debug(` ID: ${d.cid}`);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// Log summary statistics
|
|
344
|
+
logger_1.logger.debug('\nSummary Statistics:');
|
|
345
|
+
logger_1.logger.debug('-------------------');
|
|
346
|
+
logger_1.logger.debug(`Total Devices: ${((_b = this.devices) === null || _b === void 0 ? void 0 : _b.length) || 0}`);
|
|
347
|
+
for (const [category, devices] of Object.entries(this._devList)) {
|
|
348
|
+
logger_1.logger.debug(`${category}: ${devices.length} devices`);
|
|
349
|
+
}
|
|
350
|
+
logger_1.logger.debug('\n=== End of Device Discovery ===\n');
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
logger_1.logger.error('No devices found in response');
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
logger_1.logger.error('Unable to get device list:', error);
|
|
259
358
|
}
|
|
359
|
+
this._inProcess = false;
|
|
360
|
+
return procReturn;
|
|
260
361
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
362
|
+
/**
|
|
363
|
+
* Login to VeSync server
|
|
364
|
+
*/
|
|
365
|
+
async login() {
|
|
366
|
+
var _a;
|
|
367
|
+
const body = helpers_1.Helpers.reqBody(this, 'login');
|
|
368
|
+
logger_1.logger.debug('Login request:', {
|
|
369
|
+
url: `${process.env.VESYNC_API_URL}/cloud/v1/user/login`,
|
|
370
|
+
body
|
|
371
|
+
});
|
|
372
|
+
try {
|
|
373
|
+
const [response, status] = await helpers_1.Helpers.callApi('/cloud/v1/user/login', 'post', body);
|
|
374
|
+
logger_1.logger.debug('Login response:', { status, response });
|
|
375
|
+
if ((_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.token) {
|
|
376
|
+
this.token = response.result.token;
|
|
377
|
+
this.accountId = response.result.accountID;
|
|
378
|
+
this.countryCode = response.result.countryCode;
|
|
379
|
+
this.enabled = true;
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
logger_1.logger.error('Unable to login with supplied credentials');
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
logger_1.logger.error('Login error:', error);
|
|
387
|
+
return false;
|
|
266
388
|
}
|
|
267
389
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
const currentTime = Date.now();
|
|
286
|
-
if (this.lastUpdateTs &&
|
|
287
|
-
currentTime - this.lastUpdateTs < this.updateInterval * 1000) {
|
|
288
|
-
console.debug('Update rate limit - waiting %d seconds', this.updateInterval - (currentTime - this.lastUpdateTs) / 1000);
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
this.inProcess = true;
|
|
292
|
-
this.lastUpdateTs = currentTime;
|
|
293
|
-
try {
|
|
294
|
-
await this.getDevices();
|
|
295
|
-
this.processDevices();
|
|
296
|
-
const updatePromises = [];
|
|
297
|
-
for (const deviceList of Object.values(this._devList)) {
|
|
298
|
-
for (const device of deviceList) {
|
|
299
|
-
if ('update' in device && typeof device.update === 'function') {
|
|
300
|
-
updatePromises.push(device.update());
|
|
390
|
+
/**
|
|
391
|
+
* Test if update interval has been exceeded
|
|
392
|
+
*/
|
|
393
|
+
deviceTimeCheck() {
|
|
394
|
+
return (this._lastUpdateTs === null ||
|
|
395
|
+
(Date.now() - this._lastUpdateTs) / 1000 > this.updateInterval);
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Update device list and details
|
|
399
|
+
*/
|
|
400
|
+
async update() {
|
|
401
|
+
if (this.deviceTimeCheck()) {
|
|
402
|
+
if (!this.enabled) {
|
|
403
|
+
logger_1.logger.error('Not logged in to VeSync');
|
|
404
|
+
return;
|
|
301
405
|
}
|
|
406
|
+
await this.getDevices();
|
|
407
|
+
logger_1.logger.debug('Start updating the device details one by one');
|
|
408
|
+
for (const deviceList of Object.values(this._devList)) {
|
|
409
|
+
for (const device of deviceList) {
|
|
410
|
+
try {
|
|
411
|
+
await device.getDetails();
|
|
412
|
+
}
|
|
413
|
+
catch (error) {
|
|
414
|
+
logger_1.logger.error(`Error updating ${device.deviceName}:`, error);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
this._lastUpdateTs = Date.now();
|
|
302
419
|
}
|
|
303
420
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
421
|
+
/**
|
|
422
|
+
* Create device instance from details
|
|
423
|
+
*/
|
|
424
|
+
createDevice(details) {
|
|
425
|
+
const deviceType = details.deviceType;
|
|
426
|
+
const deviceClass = vesyncFanImpl_1.fanModules[deviceType];
|
|
427
|
+
if (deviceClass) {
|
|
428
|
+
return new deviceClass(details, this);
|
|
429
|
+
}
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
308
432
|
}
|
|
309
|
-
|
|
433
|
+
exports.VeSync = VeSync;
|