tsvesync 1.0.18 → 1.0.20
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/lib/helpers.js +2 -0
- package/dist/lib/vesync.d.ts +2 -2
- package/dist/lib/vesync.js +56 -52
- package/dist/lib/vesyncBulb.js +5 -5
- package/dist/lib/vesyncBulbImpl.js +6 -6
- package/dist/lib/vesyncOutlet.js +26 -9
- package/dist/lib/vesyncOutletImpl.d.ts +3 -0
- package/dist/lib/vesyncOutletImpl.js +29 -18
- package/package.json +1 -1
- package/src/lib/helpers.ts +2 -0
- package/src/lib/vesync.ts +59 -58
- package/src/lib/vesyncBulb.ts +5 -5
- package/src/lib/vesyncBulbImpl.ts +6 -6
- package/src/lib/vesyncOutlet.ts +30 -11
- package/src/lib/vesyncOutletImpl.ts +37 -20
package/dist/lib/helpers.js
CHANGED
|
@@ -45,6 +45,8 @@ class Helpers {
|
|
|
45
45
|
throw new Error('Manager accountId and token must be set');
|
|
46
46
|
}
|
|
47
47
|
return {
|
|
48
|
+
'Content-Type': 'application/json; charset=UTF-8',
|
|
49
|
+
'User-Agent': exports.BYPASS_HEADER_UA,
|
|
48
50
|
'accept-language': 'en',
|
|
49
51
|
'accountId': manager.accountId,
|
|
50
52
|
'appVersion': exports.APP_VERSION,
|
package/dist/lib/vesync.d.ts
CHANGED
|
@@ -71,9 +71,9 @@ export declare class VeSync {
|
|
|
71
71
|
*/
|
|
72
72
|
static setDevId(devices: any[]): any[];
|
|
73
73
|
/**
|
|
74
|
-
* Process
|
|
74
|
+
* Process devices from API response
|
|
75
75
|
*/
|
|
76
|
-
processDevices
|
|
76
|
+
private processDevices;
|
|
77
77
|
/**
|
|
78
78
|
* Get list of VeSync devices
|
|
79
79
|
*/
|
package/dist/lib/vesync.js
CHANGED
|
@@ -84,8 +84,31 @@ function objectFactory(details, manager) {
|
|
|
84
84
|
try {
|
|
85
85
|
// Add category to device details
|
|
86
86
|
details.deviceCategory = category;
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
// Handle outdoor plug sub-devices
|
|
88
|
+
if (deviceType === 'ESO15-TB' && details.subDevices) {
|
|
89
|
+
const devices = [];
|
|
90
|
+
// Create a device instance for each sub-device
|
|
91
|
+
details.subDevices.forEach((subDevice) => {
|
|
92
|
+
const subDeviceDetails = {
|
|
93
|
+
...details,
|
|
94
|
+
deviceName: subDevice.subDeviceName,
|
|
95
|
+
deviceStatus: subDevice.subDeviceStatus,
|
|
96
|
+
subDeviceNo: subDevice.subDeviceNo,
|
|
97
|
+
isSubDevice: true,
|
|
98
|
+
parentCid: details.cid,
|
|
99
|
+
// Generate a unique CID for the sub-device
|
|
100
|
+
cid: `${details.cid}_${subDevice.subDeviceNo}`
|
|
101
|
+
};
|
|
102
|
+
const device = new DeviceClass(subDeviceDetails, manager);
|
|
103
|
+
devices.push([category, device]);
|
|
104
|
+
});
|
|
105
|
+
// Return array of sub-devices
|
|
106
|
+
return devices[0]; // Return first device, manager will handle adding all devices
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
const device = new DeviceClass(details, manager);
|
|
110
|
+
return [category, device];
|
|
111
|
+
}
|
|
89
112
|
}
|
|
90
113
|
catch (error) {
|
|
91
114
|
logger_1.logger.error(`Error creating device instance for ${deviceType}:`, error);
|
|
@@ -265,57 +288,40 @@ class VeSync {
|
|
|
265
288
|
return devices;
|
|
266
289
|
}
|
|
267
290
|
/**
|
|
268
|
-
* Process
|
|
291
|
+
* Process devices from API response
|
|
269
292
|
*/
|
|
270
|
-
processDevices(
|
|
271
|
-
//
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
let numDevices = 0;
|
|
275
|
-
for (const deviceList of Object.values(this._devList)) {
|
|
276
|
-
numDevices += deviceList.length;
|
|
277
|
-
}
|
|
278
|
-
if (!devices || devices.length === 0) {
|
|
279
|
-
logger_1.logger.warn('No devices found in api return');
|
|
280
|
-
return false;
|
|
281
|
-
}
|
|
282
|
-
// Initialize new device list or remove old devices
|
|
283
|
-
if (numDevices === 0) {
|
|
284
|
-
logger_1.logger.debug('New device list initialized');
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
this.removeOldDevices(devices);
|
|
293
|
+
processDevices(deviceList) {
|
|
294
|
+
// Clear existing devices
|
|
295
|
+
for (const category of Object.keys(this._devList)) {
|
|
296
|
+
this._devList[category].length = 0;
|
|
288
297
|
}
|
|
289
|
-
//
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
else if (category === 'unknown') {
|
|
310
|
-
logger_1.logger.debug(`Unknown device type: ${devType}`);
|
|
311
|
-
}
|
|
298
|
+
// Process each device
|
|
299
|
+
deviceList.forEach(dev => {
|
|
300
|
+
const [category, device] = objectFactory(dev, this);
|
|
301
|
+
// Handle outdoor plug sub-devices
|
|
302
|
+
if (dev.deviceType === 'ESO15-TB' && dev.subDevices) {
|
|
303
|
+
dev.subDevices.forEach((subDev) => {
|
|
304
|
+
const subDeviceDetails = {
|
|
305
|
+
...dev,
|
|
306
|
+
deviceName: subDev.subDeviceName,
|
|
307
|
+
deviceStatus: subDev.subDeviceStatus,
|
|
308
|
+
subDeviceNo: subDev.subDeviceNo,
|
|
309
|
+
isSubDevice: true,
|
|
310
|
+
parentCid: dev.cid,
|
|
311
|
+
cid: `${dev.cid}_${subDev.subDeviceNo}`
|
|
312
|
+
};
|
|
313
|
+
const [subCategory, subDevice] = objectFactory(subDeviceDetails, this);
|
|
314
|
+
if (subDevice && subCategory in this._devList) {
|
|
315
|
+
this._devList[subCategory].push(subDevice);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
312
318
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
continue;
|
|
319
|
+
else if (device && category in this._devList) {
|
|
320
|
+
this._devList[category].push(device);
|
|
316
321
|
}
|
|
317
|
-
}
|
|
318
|
-
|
|
322
|
+
});
|
|
323
|
+
// Update device list reference
|
|
324
|
+
this.devices = Object.values(this._devList).flat();
|
|
319
325
|
}
|
|
320
326
|
/**
|
|
321
327
|
* Get list of VeSync devices
|
|
@@ -332,9 +338,7 @@ class VeSync {
|
|
|
332
338
|
const [response] = await helpers_1.Helpers.callApi('/cloud/v2/deviceManaged/devices', 'post', helpers_1.Helpers.reqBody(this, 'devicelist'), helpers_1.Helpers.reqHeaders(this));
|
|
333
339
|
if ((_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.list) {
|
|
334
340
|
const deviceList = response.result.list;
|
|
335
|
-
|
|
336
|
-
// Update the main devices array with all devices
|
|
337
|
-
this.devices = Object.values(this._devList).flat();
|
|
341
|
+
this.processDevices(deviceList);
|
|
338
342
|
// Log device discovery results
|
|
339
343
|
logger_1.logger.debug('\n=== Device Discovery Summary ===');
|
|
340
344
|
logger_1.logger.debug(`Total devices processed: ${deviceList.length}`);
|
package/dist/lib/vesyncBulb.js
CHANGED
|
@@ -95,7 +95,7 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
95
95
|
this.colorValue = response.result.value || this.colorValue;
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
-
logger_1.logger.
|
|
98
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully retrieved bulb details`);
|
|
99
99
|
}
|
|
100
100
|
else {
|
|
101
101
|
logger_1.logger.error(`[${this.deviceName}] Failed to get bulb details: ${JSON.stringify(response)}`);
|
|
@@ -107,7 +107,7 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
107
107
|
async update() {
|
|
108
108
|
logger_1.logger.debug(`[${this.deviceName}] Updating bulb information`);
|
|
109
109
|
await this.getDetails();
|
|
110
|
-
logger_1.logger.
|
|
110
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully updated bulb information`);
|
|
111
111
|
}
|
|
112
112
|
/**
|
|
113
113
|
* Turn bulb on
|
|
@@ -141,7 +141,7 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
141
141
|
const [response] = await helpers_1.Helpers.callApi(endpoint, 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
142
142
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
143
143
|
this.deviceStatus = 'on';
|
|
144
|
-
logger_1.logger.
|
|
144
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned bulb on`);
|
|
145
145
|
return true;
|
|
146
146
|
}
|
|
147
147
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn bulb on: ${JSON.stringify(response)}`);
|
|
@@ -179,7 +179,7 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
179
179
|
const [response] = await helpers_1.Helpers.callApi(endpoint, 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
180
180
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
181
181
|
this.deviceStatus = 'off';
|
|
182
|
-
logger_1.logger.
|
|
182
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned bulb off`);
|
|
183
183
|
return true;
|
|
184
184
|
}
|
|
185
185
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn bulb off: ${JSON.stringify(response)}`);
|
|
@@ -226,7 +226,7 @@ class VeSyncBulb extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
226
226
|
const [response] = await helpers_1.Helpers.callApi(endpoint, 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
227
227
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
228
228
|
this.brightness = brightness;
|
|
229
|
-
logger_1.logger.
|
|
229
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully set brightness to ${brightness}`);
|
|
230
230
|
return true;
|
|
231
231
|
}
|
|
232
232
|
logger_1.logger.error(`[${this.deviceName}] Failed to set brightness: ${JSON.stringify(response)}`);
|
|
@@ -46,7 +46,7 @@ class VeSyncBulbESL100CW extends vesyncBulb_1.VeSyncBulb {
|
|
|
46
46
|
const [response] = await helpers_1.Helpers.callApi('/cloud/v1/deviceManaged/bypass', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
47
47
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
48
48
|
this.colorTemp = colorTemp;
|
|
49
|
-
logger_1.logger.
|
|
49
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully set color temperature to ${colorTemp}`);
|
|
50
50
|
return true;
|
|
51
51
|
}
|
|
52
52
|
logger_1.logger.error(`[${this.deviceName}] Failed to set color temperature: ${JSON.stringify(response)}`);
|
|
@@ -88,7 +88,7 @@ class VeSyncBulbXYD0001 extends vesyncBulb_1.VeSyncBulb {
|
|
|
88
88
|
const [response] = await helpers_1.Helpers.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
89
89
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
90
90
|
this.colorTemp = colorTemp;
|
|
91
|
-
logger_1.logger.
|
|
91
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully set color temperature to ${colorTemp}`);
|
|
92
92
|
return true;
|
|
93
93
|
}
|
|
94
94
|
logger_1.logger.error(`[${this.deviceName}] Failed to set color temperature: ${JSON.stringify(response)}`);
|
|
@@ -123,7 +123,7 @@ class VeSyncBulbXYD0001 extends vesyncBulb_1.VeSyncBulb {
|
|
|
123
123
|
this.colorHue = hue;
|
|
124
124
|
this.colorSaturation = saturation;
|
|
125
125
|
this.colorValue = value;
|
|
126
|
-
logger_1.logger.
|
|
126
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully set HSV color`);
|
|
127
127
|
return true;
|
|
128
128
|
}
|
|
129
129
|
logger_1.logger.error(`[${this.deviceName}] Failed to set HSV color: ${JSON.stringify(response)}`);
|
|
@@ -152,7 +152,7 @@ class VeSyncBulbXYD0001 extends vesyncBulb_1.VeSyncBulb {
|
|
|
152
152
|
const [response] = await helpers_1.Helpers.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
153
153
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
154
154
|
this.colorMode = 'white';
|
|
155
|
-
logger_1.logger.
|
|
155
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully enabled white mode`);
|
|
156
156
|
return true;
|
|
157
157
|
}
|
|
158
158
|
logger_1.logger.error(`[${this.deviceName}] Failed to enable white mode: ${JSON.stringify(response)}`);
|
|
@@ -192,7 +192,7 @@ class VeSyncBulbESL100MC extends vesyncBulb_1.VeSyncBulb {
|
|
|
192
192
|
const [response] = await helpers_1.Helpers.callApi('/cloud/v1/deviceManaged/bypass', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
193
193
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
194
194
|
this.rgbValues = { red, green, blue };
|
|
195
|
-
logger_1.logger.
|
|
195
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully set RGB color`);
|
|
196
196
|
return true;
|
|
197
197
|
}
|
|
198
198
|
logger_1.logger.error(`[${this.deviceName}] Failed to set RGB color: ${JSON.stringify(response)}`);
|
|
@@ -213,7 +213,7 @@ class VeSyncBulbESL100MC extends vesyncBulb_1.VeSyncBulb {
|
|
|
213
213
|
const [response] = await helpers_1.Helpers.callApi('/cloud/v1/deviceManaged/bypass', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
214
214
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
215
215
|
this.colorMode = 'white';
|
|
216
|
-
logger_1.logger.
|
|
216
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully enabled white mode`);
|
|
217
217
|
return true;
|
|
218
218
|
}
|
|
219
219
|
logger_1.logger.error(`[${this.deviceName}] Failed to enable white mode: ${JSON.stringify(response)}`);
|
package/dist/lib/vesyncOutlet.js
CHANGED
|
@@ -81,10 +81,27 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
81
81
|
this.details = response;
|
|
82
82
|
// Handle outdoor plugs with subdevices
|
|
83
83
|
if (response.subDevices) {
|
|
84
|
-
const subDevice = response.subDevices.find((dev) =>
|
|
84
|
+
const subDevice = response.subDevices.find((dev) => {
|
|
85
|
+
// Match by name (primary identifier)
|
|
86
|
+
if (dev.subDeviceName === this.deviceName) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
// Match by subDeviceNo if available
|
|
90
|
+
if ('subDeviceNo' in this && this.subDeviceNo === dev.subDeviceNo) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
// Match by cid/uuid if available (cid might be in format parentCid_subDeviceNo)
|
|
94
|
+
if (this.cid && this.cid.includes('_')) {
|
|
95
|
+
const [_, subId] = this.cid.split('_');
|
|
96
|
+
if (subId && dev.subDeviceNo === parseInt(subId)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
});
|
|
85
102
|
if (subDevice) {
|
|
86
103
|
this.deviceStatus = subDevice.subDeviceStatus;
|
|
87
|
-
logger_1.logger.
|
|
104
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully retrieved sub-device status: ${this.deviceStatus}`);
|
|
88
105
|
return;
|
|
89
106
|
}
|
|
90
107
|
}
|
|
@@ -102,7 +119,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
102
119
|
logger_1.logger.debug(`[${this.deviceName}] Device status not found in response: ${JSON.stringify(response)}`);
|
|
103
120
|
return;
|
|
104
121
|
}
|
|
105
|
-
logger_1.logger.
|
|
122
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully retrieved outlet details`);
|
|
106
123
|
}
|
|
107
124
|
else {
|
|
108
125
|
logger_1.logger.debug(`[${this.deviceName}] Failed to get outlet details: ${JSON.stringify(response)}`);
|
|
@@ -142,7 +159,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
142
159
|
// Handle different response formats
|
|
143
160
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0 && response.result) {
|
|
144
161
|
this.energy = response.result;
|
|
145
|
-
logger_1.logger.
|
|
162
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully updated energy data`);
|
|
146
163
|
}
|
|
147
164
|
else if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
148
165
|
// Some devices return data directly in response
|
|
@@ -155,7 +172,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
155
172
|
energyMonth: response.energy || '0',
|
|
156
173
|
energyYear: response.energy || '0'
|
|
157
174
|
};
|
|
158
|
-
logger_1.logger.
|
|
175
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully updated energy data`);
|
|
159
176
|
}
|
|
160
177
|
else {
|
|
161
178
|
// For error responses, set defaults but don't log as error
|
|
@@ -236,7 +253,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
236
253
|
const [response] = await helpers_1.Helpers.callApi(isLegacyDevice ? `/${this.getApiPrefix()}/energy/week` : `/${this.getApiPrefix()}/energyweek`, isLegacyDevice ? 'get' : 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
237
254
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
238
255
|
this.energy.week = response.result || response.energyWeek || '0';
|
|
239
|
-
logger_1.logger.
|
|
256
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully retrieved weekly energy data`);
|
|
240
257
|
}
|
|
241
258
|
else {
|
|
242
259
|
this.energy.week = '0';
|
|
@@ -260,7 +277,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
260
277
|
const [response] = await helpers_1.Helpers.callApi(isLegacyDevice ? `/${this.getApiPrefix()}/energy/month` : `/${this.getApiPrefix()}/energymonth`, isLegacyDevice ? 'get' : 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
261
278
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
262
279
|
this.energy.month = response.result || response.energyMonth || '0';
|
|
263
|
-
logger_1.logger.
|
|
280
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully retrieved monthly energy data`);
|
|
264
281
|
}
|
|
265
282
|
else {
|
|
266
283
|
this.energy.month = '0';
|
|
@@ -284,7 +301,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
284
301
|
const [response] = await helpers_1.Helpers.callApi(isLegacyDevice ? `/${this.getApiPrefix()}/energy/year` : `/${this.getApiPrefix()}/energyyear`, isLegacyDevice ? 'get' : 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
285
302
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
286
303
|
this.energy.year = response.result || response.energyYear || '0';
|
|
287
|
-
logger_1.logger.
|
|
304
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully retrieved yearly energy data`);
|
|
288
305
|
}
|
|
289
306
|
else {
|
|
290
307
|
this.energy.year = '0';
|
|
@@ -300,7 +317,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
300
317
|
if (this.features.includes('energy')) {
|
|
301
318
|
await this.updateEnergy();
|
|
302
319
|
}
|
|
303
|
-
logger_1.logger.
|
|
320
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully updated outlet information`);
|
|
304
321
|
}
|
|
305
322
|
/**
|
|
306
323
|
* Check if outlet has nightlight feature
|
|
@@ -57,6 +57,9 @@ export declare class VeSyncOutlet15A extends VeSyncOutlet {
|
|
|
57
57
|
* VeSync Outdoor Plug
|
|
58
58
|
*/
|
|
59
59
|
export declare class VeSyncOutdoorPlug extends VeSyncOutlet {
|
|
60
|
+
protected subDeviceNo?: number;
|
|
61
|
+
protected isSubDevice: boolean;
|
|
62
|
+
protected parentCid?: string;
|
|
60
63
|
constructor(details: Record<string, any>, manager: VeSync);
|
|
61
64
|
/**
|
|
62
65
|
* Turn outlet on
|
|
@@ -19,11 +19,11 @@ class VeSyncOutlet7A extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
19
19
|
*/
|
|
20
20
|
async turnOn() {
|
|
21
21
|
logger_1.logger.debug(`[${this.deviceName}] Turning outlet on`);
|
|
22
|
-
const url = `/v1/wifi-switch-1.3
|
|
23
|
-
const [response] = await helpers_1.Helpers.callApi(url, 'put',
|
|
24
|
-
if (
|
|
22
|
+
const url = `/v1/wifi-switch-1.3/${this.cid}/status/on`;
|
|
23
|
+
const [response, statusCode] = await helpers_1.Helpers.callApi(url, 'put', {}, helpers_1.Helpers.reqHeaders(this.manager));
|
|
24
|
+
if (statusCode === 200) {
|
|
25
25
|
this.deviceStatus = 'on';
|
|
26
|
-
logger_1.logger.
|
|
26
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned outlet on`);
|
|
27
27
|
return true;
|
|
28
28
|
}
|
|
29
29
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn outlet on: ${JSON.stringify(response)}`);
|
|
@@ -34,11 +34,11 @@ class VeSyncOutlet7A extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
34
34
|
*/
|
|
35
35
|
async turnOff() {
|
|
36
36
|
logger_1.logger.debug(`[${this.deviceName}] Turning outlet off`);
|
|
37
|
-
const url = `/v1/wifi-switch-1.3
|
|
38
|
-
const [response] = await helpers_1.Helpers.callApi(url, 'put',
|
|
39
|
-
if (
|
|
37
|
+
const url = `/v1/wifi-switch-1.3/${this.cid}/status/off`;
|
|
38
|
+
const [response, statusCode] = await helpers_1.Helpers.callApi(url, 'put', {}, helpers_1.Helpers.reqHeaders(this.manager));
|
|
39
|
+
if (statusCode === 200) {
|
|
40
40
|
this.deviceStatus = 'off';
|
|
41
|
-
logger_1.logger.
|
|
41
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned outlet off`);
|
|
42
42
|
return true;
|
|
43
43
|
}
|
|
44
44
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn outlet off: ${JSON.stringify(response)}`);
|
|
@@ -66,7 +66,7 @@ class VeSyncOutlet10A extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
66
66
|
const [response] = await helpers_1.Helpers.callApi('/10a/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
67
67
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
68
68
|
this.deviceStatus = 'on';
|
|
69
|
-
logger_1.logger.
|
|
69
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned outlet on`);
|
|
70
70
|
return true;
|
|
71
71
|
}
|
|
72
72
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn outlet on: ${JSON.stringify(response)}`);
|
|
@@ -85,7 +85,7 @@ class VeSyncOutlet10A extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
85
85
|
const [response] = await helpers_1.Helpers.callApi('/10a/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
86
86
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
87
87
|
this.deviceStatus = 'off';
|
|
88
|
-
logger_1.logger.
|
|
88
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned outlet off`);
|
|
89
89
|
return true;
|
|
90
90
|
}
|
|
91
91
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn outlet off: ${JSON.stringify(response)}`);
|
|
@@ -113,7 +113,7 @@ class VeSyncOutlet15A extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
113
113
|
const [response] = await helpers_1.Helpers.callApi('/15a/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
114
114
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
115
115
|
this.deviceStatus = 'on';
|
|
116
|
-
logger_1.logger.
|
|
116
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned outlet on`);
|
|
117
117
|
return true;
|
|
118
118
|
}
|
|
119
119
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn outlet on: ${JSON.stringify(response)}`);
|
|
@@ -132,7 +132,7 @@ class VeSyncOutlet15A extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
132
132
|
const [response] = await helpers_1.Helpers.callApi('/15a/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
133
133
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
134
134
|
this.deviceStatus = 'off';
|
|
135
|
-
logger_1.logger.
|
|
135
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned outlet off`);
|
|
136
136
|
return true;
|
|
137
137
|
}
|
|
138
138
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn outlet off: ${JSON.stringify(response)}`);
|
|
@@ -155,7 +155,7 @@ class VeSyncOutlet15A extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
155
155
|
const [response] = await helpers_1.Helpers.callApi('/15a/v1/device/nightlightstatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
156
156
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
157
157
|
this.details.nightLightStatus = 'on';
|
|
158
|
-
logger_1.logger.
|
|
158
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned nightlight on`);
|
|
159
159
|
return true;
|
|
160
160
|
}
|
|
161
161
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn nightlight on: ${JSON.stringify(response)}`);
|
|
@@ -178,7 +178,7 @@ class VeSyncOutlet15A extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
178
178
|
const [response] = await helpers_1.Helpers.callApi('/15a/v1/device/nightlightstatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
179
179
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
180
180
|
this.details.nightLightStatus = 'off';
|
|
181
|
-
logger_1.logger.
|
|
181
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned nightlight off`);
|
|
182
182
|
return true;
|
|
183
183
|
}
|
|
184
184
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn nightlight off: ${JSON.stringify(response)}`);
|
|
@@ -192,22 +192,29 @@ exports.VeSyncOutlet15A = VeSyncOutlet15A;
|
|
|
192
192
|
class VeSyncOutdoorPlug extends vesyncOutlet_1.VeSyncOutlet {
|
|
193
193
|
constructor(details, manager) {
|
|
194
194
|
super(details, manager);
|
|
195
|
+
this.isSubDevice = details.isSubDevice || false;
|
|
196
|
+
this.subDeviceNo = details.subDeviceNo;
|
|
197
|
+
this.parentCid = details.parentCid;
|
|
195
198
|
}
|
|
196
199
|
/**
|
|
197
200
|
* Turn outlet on
|
|
198
201
|
*/
|
|
199
202
|
async turnOn() {
|
|
203
|
+
if (!this.isSubDevice) {
|
|
204
|
+
logger_1.logger.error(`[${this.deviceName}] Cannot control parent device directly`);
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
200
207
|
logger_1.logger.debug(`[${this.deviceName}] Turning outlet on`);
|
|
201
208
|
const body = {
|
|
202
209
|
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
203
210
|
uuid: this.uuid,
|
|
204
211
|
status: 'on',
|
|
205
|
-
switchNo:
|
|
212
|
+
switchNo: this.subDeviceNo
|
|
206
213
|
};
|
|
207
214
|
const [response] = await helpers_1.Helpers.callApi('/outdoorsocket15a/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
208
215
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
209
216
|
this.deviceStatus = 'on';
|
|
210
|
-
logger_1.logger.
|
|
217
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned outlet on`);
|
|
211
218
|
return true;
|
|
212
219
|
}
|
|
213
220
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn outlet on: ${JSON.stringify(response)}`);
|
|
@@ -217,17 +224,21 @@ class VeSyncOutdoorPlug extends vesyncOutlet_1.VeSyncOutlet {
|
|
|
217
224
|
* Turn outlet off
|
|
218
225
|
*/
|
|
219
226
|
async turnOff() {
|
|
227
|
+
if (!this.isSubDevice) {
|
|
228
|
+
logger_1.logger.error(`[${this.deviceName}] Cannot control parent device directly`);
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
220
231
|
logger_1.logger.debug(`[${this.deviceName}] Turning outlet off`);
|
|
221
232
|
const body = {
|
|
222
233
|
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
223
234
|
uuid: this.uuid,
|
|
224
235
|
status: 'off',
|
|
225
|
-
switchNo:
|
|
236
|
+
switchNo: this.subDeviceNo
|
|
226
237
|
};
|
|
227
238
|
const [response] = await helpers_1.Helpers.callApi('/outdoorsocket15a/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
228
239
|
if ((response === null || response === void 0 ? void 0 : response.code) === 0) {
|
|
229
240
|
this.deviceStatus = 'off';
|
|
230
|
-
logger_1.logger.
|
|
241
|
+
logger_1.logger.info(`[${this.deviceName}] Successfully turned outlet off`);
|
|
231
242
|
return true;
|
|
232
243
|
}
|
|
233
244
|
logger_1.logger.error(`[${this.deviceName}] Failed to turn outlet off: ${JSON.stringify(response)}`);
|
package/package.json
CHANGED
package/src/lib/helpers.ts
CHANGED
|
@@ -70,6 +70,8 @@ export class Helpers {
|
|
|
70
70
|
throw new Error('Manager accountId and token must be set');
|
|
71
71
|
}
|
|
72
72
|
return {
|
|
73
|
+
'Content-Type': 'application/json; charset=UTF-8',
|
|
74
|
+
'User-Agent': BYPASS_HEADER_UA,
|
|
73
75
|
'accept-language': 'en',
|
|
74
76
|
'accountId': manager.accountId,
|
|
75
77
|
'appVersion': APP_VERSION,
|
package/src/lib/vesync.ts
CHANGED
|
@@ -103,8 +103,33 @@ function objectFactory(details: Record<string, any>, manager: VeSync): [string,
|
|
|
103
103
|
try {
|
|
104
104
|
// Add category to device details
|
|
105
105
|
details.deviceCategory = category;
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
|
|
107
|
+
// Handle outdoor plug sub-devices
|
|
108
|
+
if (deviceType === 'ESO15-TB' && details.subDevices) {
|
|
109
|
+
const devices: [string, VeSyncBaseDevice | null][] = [];
|
|
110
|
+
|
|
111
|
+
// Create a device instance for each sub-device
|
|
112
|
+
details.subDevices.forEach((subDevice: any) => {
|
|
113
|
+
const subDeviceDetails = {
|
|
114
|
+
...details,
|
|
115
|
+
deviceName: subDevice.subDeviceName,
|
|
116
|
+
deviceStatus: subDevice.subDeviceStatus,
|
|
117
|
+
subDeviceNo: subDevice.subDeviceNo,
|
|
118
|
+
isSubDevice: true,
|
|
119
|
+
parentCid: details.cid,
|
|
120
|
+
// Generate a unique CID for the sub-device
|
|
121
|
+
cid: `${details.cid}_${subDevice.subDeviceNo}`
|
|
122
|
+
};
|
|
123
|
+
const device = new DeviceClass(subDeviceDetails, manager);
|
|
124
|
+
devices.push([category, device]);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Return array of sub-devices
|
|
128
|
+
return devices[0]; // Return first device, manager will handle adding all devices
|
|
129
|
+
} else {
|
|
130
|
+
const device = new DeviceClass(details, manager);
|
|
131
|
+
return [category, device];
|
|
132
|
+
}
|
|
108
133
|
} catch (error) {
|
|
109
134
|
logger.error(`Error creating device instance for ${deviceType}:`, error);
|
|
110
135
|
return [category, null];
|
|
@@ -331,63 +356,42 @@ export class VeSync {
|
|
|
331
356
|
}
|
|
332
357
|
|
|
333
358
|
/**
|
|
334
|
-
* Process
|
|
359
|
+
* Process devices from API response
|
|
335
360
|
*/
|
|
336
|
-
processDevices(
|
|
337
|
-
//
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
// Count current devices
|
|
341
|
-
let numDevices = 0;
|
|
342
|
-
for (const deviceList of Object.values(this._devList)) {
|
|
343
|
-
numDevices += deviceList.length;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
if (!devices || devices.length === 0) {
|
|
347
|
-
logger.warn('No devices found in api return');
|
|
348
|
-
return false;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Initialize new device list or remove old devices
|
|
352
|
-
if (numDevices === 0) {
|
|
353
|
-
logger.debug('New device list initialized');
|
|
354
|
-
} else {
|
|
355
|
-
this.removeOldDevices(devices);
|
|
361
|
+
private processDevices(deviceList: any[]): void {
|
|
362
|
+
// Clear existing devices
|
|
363
|
+
for (const category of Object.keys(this._devList)) {
|
|
364
|
+
this._devList[category].length = 0;
|
|
356
365
|
}
|
|
357
366
|
|
|
358
|
-
//
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
} else if (category === 'unknown') {
|
|
382
|
-
logger.debug(`Unknown device type: ${devType}`);
|
|
383
|
-
}
|
|
384
|
-
} catch (err) {
|
|
385
|
-
logger.error(`Error creating device ${devType}:`, err);
|
|
386
|
-
continue;
|
|
367
|
+
// Process each device
|
|
368
|
+
deviceList.forEach(dev => {
|
|
369
|
+
const [category, device] = objectFactory(dev, this);
|
|
370
|
+
|
|
371
|
+
// Handle outdoor plug sub-devices
|
|
372
|
+
if (dev.deviceType === 'ESO15-TB' && dev.subDevices) {
|
|
373
|
+
dev.subDevices.forEach((subDev: any) => {
|
|
374
|
+
const subDeviceDetails = {
|
|
375
|
+
...dev,
|
|
376
|
+
deviceName: subDev.subDeviceName,
|
|
377
|
+
deviceStatus: subDev.subDeviceStatus,
|
|
378
|
+
subDeviceNo: subDev.subDeviceNo,
|
|
379
|
+
isSubDevice: true,
|
|
380
|
+
parentCid: dev.cid,
|
|
381
|
+
cid: `${dev.cid}_${subDev.subDeviceNo}`
|
|
382
|
+
};
|
|
383
|
+
const [subCategory, subDevice] = objectFactory(subDeviceDetails, this);
|
|
384
|
+
if (subDevice && subCategory in this._devList) {
|
|
385
|
+
this._devList[subCategory].push(subDevice);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
} else if (device && category in this._devList) {
|
|
389
|
+
this._devList[category].push(device);
|
|
387
390
|
}
|
|
388
|
-
}
|
|
391
|
+
});
|
|
389
392
|
|
|
390
|
-
|
|
393
|
+
// Update device list reference
|
|
394
|
+
this.devices = Object.values(this._devList).flat();
|
|
391
395
|
}
|
|
392
396
|
|
|
393
397
|
/**
|
|
@@ -412,10 +416,7 @@ export class VeSync {
|
|
|
412
416
|
|
|
413
417
|
if (response?.result?.list) {
|
|
414
418
|
const deviceList = response.result.list;
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
// Update the main devices array with all devices
|
|
418
|
-
this.devices = Object.values(this._devList).flat();
|
|
419
|
+
this.processDevices(deviceList);
|
|
419
420
|
|
|
420
421
|
// Log device discovery results
|
|
421
422
|
logger.debug('\n=== Device Discovery Summary ===');
|
package/src/lib/vesyncBulb.ts
CHANGED
|
@@ -120,7 +120,7 @@ export abstract class VeSyncBulb extends VeSyncBaseDevice {
|
|
|
120
120
|
this.colorValue = response.result.value || this.colorValue;
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
-
logger.
|
|
123
|
+
logger.info(`[${this.deviceName}] Successfully retrieved bulb details`);
|
|
124
124
|
} else {
|
|
125
125
|
logger.error(`[${this.deviceName}] Failed to get bulb details: ${JSON.stringify(response)}`);
|
|
126
126
|
}
|
|
@@ -132,7 +132,7 @@ export abstract class VeSyncBulb extends VeSyncBaseDevice {
|
|
|
132
132
|
async update(): Promise<void> {
|
|
133
133
|
logger.debug(`[${this.deviceName}] Updating bulb information`);
|
|
134
134
|
await this.getDetails();
|
|
135
|
-
logger.
|
|
135
|
+
logger.info(`[${this.deviceName}] Successfully updated bulb information`);
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
/**
|
|
@@ -175,7 +175,7 @@ export abstract class VeSyncBulb extends VeSyncBaseDevice {
|
|
|
175
175
|
|
|
176
176
|
if (response?.code === 0) {
|
|
177
177
|
this.deviceStatus = 'on';
|
|
178
|
-
logger.
|
|
178
|
+
logger.info(`[${this.deviceName}] Successfully turned bulb on`);
|
|
179
179
|
return true;
|
|
180
180
|
}
|
|
181
181
|
logger.error(`[${this.deviceName}] Failed to turn bulb on: ${JSON.stringify(response)}`);
|
|
@@ -222,7 +222,7 @@ export abstract class VeSyncBulb extends VeSyncBaseDevice {
|
|
|
222
222
|
|
|
223
223
|
if (response?.code === 0) {
|
|
224
224
|
this.deviceStatus = 'off';
|
|
225
|
-
logger.
|
|
225
|
+
logger.info(`[${this.deviceName}] Successfully turned bulb off`);
|
|
226
226
|
return true;
|
|
227
227
|
}
|
|
228
228
|
logger.error(`[${this.deviceName}] Failed to turn bulb off: ${JSON.stringify(response)}`);
|
|
@@ -279,7 +279,7 @@ export abstract class VeSyncBulb extends VeSyncBaseDevice {
|
|
|
279
279
|
|
|
280
280
|
if (response?.code === 0) {
|
|
281
281
|
this.brightness = brightness;
|
|
282
|
-
logger.
|
|
282
|
+
logger.info(`[${this.deviceName}] Successfully set brightness to ${brightness}`);
|
|
283
283
|
return true;
|
|
284
284
|
}
|
|
285
285
|
logger.error(`[${this.deviceName}] Failed to set brightness: ${JSON.stringify(response)}`);
|
|
@@ -56,7 +56,7 @@ export class VeSyncBulbESL100CW extends VeSyncBulb {
|
|
|
56
56
|
|
|
57
57
|
if (response?.code === 0) {
|
|
58
58
|
this.colorTemp = colorTemp;
|
|
59
|
-
logger.
|
|
59
|
+
logger.info(`[${this.deviceName}] Successfully set color temperature to ${colorTemp}`);
|
|
60
60
|
return true;
|
|
61
61
|
}
|
|
62
62
|
logger.error(`[${this.deviceName}] Failed to set color temperature: ${JSON.stringify(response)}`);
|
|
@@ -107,7 +107,7 @@ export class VeSyncBulbXYD0001 extends VeSyncBulb {
|
|
|
107
107
|
|
|
108
108
|
if (response?.code === 0) {
|
|
109
109
|
this.colorTemp = colorTemp;
|
|
110
|
-
logger.
|
|
110
|
+
logger.info(`[${this.deviceName}] Successfully set color temperature to ${colorTemp}`);
|
|
111
111
|
return true;
|
|
112
112
|
}
|
|
113
113
|
logger.error(`[${this.deviceName}] Failed to set color temperature: ${JSON.stringify(response)}`);
|
|
@@ -151,7 +151,7 @@ export class VeSyncBulbXYD0001 extends VeSyncBulb {
|
|
|
151
151
|
this.colorHue = hue;
|
|
152
152
|
this.colorSaturation = saturation;
|
|
153
153
|
this.colorValue = value;
|
|
154
|
-
logger.
|
|
154
|
+
logger.info(`[${this.deviceName}] Successfully set HSV color`);
|
|
155
155
|
return true;
|
|
156
156
|
}
|
|
157
157
|
logger.error(`[${this.deviceName}] Failed to set HSV color: ${JSON.stringify(response)}`);
|
|
@@ -188,7 +188,7 @@ export class VeSyncBulbXYD0001 extends VeSyncBulb {
|
|
|
188
188
|
|
|
189
189
|
if (response?.code === 0) {
|
|
190
190
|
this.colorMode = 'white';
|
|
191
|
-
logger.
|
|
191
|
+
logger.info(`[${this.deviceName}] Successfully enabled white mode`);
|
|
192
192
|
return true;
|
|
193
193
|
}
|
|
194
194
|
logger.error(`[${this.deviceName}] Failed to enable white mode: ${JSON.stringify(response)}`);
|
|
@@ -238,7 +238,7 @@ export class VeSyncBulbESL100MC extends VeSyncBulb {
|
|
|
238
238
|
|
|
239
239
|
if (response?.code === 0) {
|
|
240
240
|
this.rgbValues = { red, green, blue };
|
|
241
|
-
logger.
|
|
241
|
+
logger.info(`[${this.deviceName}] Successfully set RGB color`);
|
|
242
242
|
return true;
|
|
243
243
|
}
|
|
244
244
|
logger.error(`[${this.deviceName}] Failed to set RGB color: ${JSON.stringify(response)}`);
|
|
@@ -267,7 +267,7 @@ export class VeSyncBulbESL100MC extends VeSyncBulb {
|
|
|
267
267
|
|
|
268
268
|
if (response?.code === 0) {
|
|
269
269
|
this.colorMode = 'white';
|
|
270
|
-
logger.
|
|
270
|
+
logger.info(`[${this.deviceName}] Successfully enabled white mode`);
|
|
271
271
|
return true;
|
|
272
272
|
}
|
|
273
273
|
logger.error(`[${this.deviceName}] Failed to enable white mode: ${JSON.stringify(response)}`);
|
package/src/lib/vesyncOutlet.ts
CHANGED
|
@@ -101,12 +101,31 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
|
|
|
101
101
|
|
|
102
102
|
// Handle outdoor plugs with subdevices
|
|
103
103
|
if (response.subDevices) {
|
|
104
|
-
const subDevice = response.subDevices.find(
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
const subDevice = response.subDevices.find((dev: any) => {
|
|
105
|
+
// Match by name (primary identifier)
|
|
106
|
+
if (dev.subDeviceName === this.deviceName) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Match by subDeviceNo if available
|
|
111
|
+
if ('subDeviceNo' in this && (this as any).subDeviceNo === dev.subDeviceNo) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Match by cid/uuid if available (cid might be in format parentCid_subDeviceNo)
|
|
116
|
+
if (this.cid && this.cid.includes('_')) {
|
|
117
|
+
const [_, subId] = this.cid.split('_');
|
|
118
|
+
if (subId && dev.subDeviceNo === parseInt(subId)) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return false;
|
|
124
|
+
});
|
|
125
|
+
|
|
107
126
|
if (subDevice) {
|
|
108
127
|
this.deviceStatus = subDevice.subDeviceStatus;
|
|
109
|
-
logger.
|
|
128
|
+
logger.info(`[${this.deviceName}] Successfully retrieved sub-device status: ${this.deviceStatus}`);
|
|
110
129
|
return;
|
|
111
130
|
}
|
|
112
131
|
}
|
|
@@ -122,7 +141,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
|
|
|
122
141
|
logger.debug(`[${this.deviceName}] Device status not found in response: ${JSON.stringify(response)}`);
|
|
123
142
|
return;
|
|
124
143
|
}
|
|
125
|
-
logger.
|
|
144
|
+
logger.info(`[${this.deviceName}] Successfully retrieved outlet details`);
|
|
126
145
|
} else {
|
|
127
146
|
logger.debug(`[${this.deviceName}] Failed to get outlet details: ${JSON.stringify(response)}`);
|
|
128
147
|
}
|
|
@@ -168,7 +187,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
|
|
|
168
187
|
// Handle different response formats
|
|
169
188
|
if (response?.code === 0 && response.result) {
|
|
170
189
|
this.energy = response.result;
|
|
171
|
-
logger.
|
|
190
|
+
logger.info(`[${this.deviceName}] Successfully updated energy data`);
|
|
172
191
|
} else if (response?.code === 0) {
|
|
173
192
|
// Some devices return data directly in response
|
|
174
193
|
this.energy = {
|
|
@@ -180,7 +199,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
|
|
|
180
199
|
energyMonth: response.energy || '0',
|
|
181
200
|
energyYear: response.energy || '0'
|
|
182
201
|
};
|
|
183
|
-
logger.
|
|
202
|
+
logger.info(`[${this.deviceName}] Successfully updated energy data`);
|
|
184
203
|
} else {
|
|
185
204
|
// For error responses, set defaults but don't log as error
|
|
186
205
|
this.energy = {
|
|
@@ -271,7 +290,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
|
|
|
271
290
|
|
|
272
291
|
if (response?.code === 0) {
|
|
273
292
|
this.energy.week = response.result || response.energyWeek || '0';
|
|
274
|
-
logger.
|
|
293
|
+
logger.info(`[${this.deviceName}] Successfully retrieved weekly energy data`);
|
|
275
294
|
} else {
|
|
276
295
|
this.energy.week = '0';
|
|
277
296
|
logger.debug(`[${this.deviceName}] Failed to get weekly energy data: ${JSON.stringify(response)}`);
|
|
@@ -303,7 +322,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
|
|
|
303
322
|
|
|
304
323
|
if (response?.code === 0) {
|
|
305
324
|
this.energy.month = response.result || response.energyMonth || '0';
|
|
306
|
-
logger.
|
|
325
|
+
logger.info(`[${this.deviceName}] Successfully retrieved monthly energy data`);
|
|
307
326
|
} else {
|
|
308
327
|
this.energy.month = '0';
|
|
309
328
|
logger.debug(`[${this.deviceName}] Failed to get monthly energy data: ${JSON.stringify(response)}`);
|
|
@@ -335,7 +354,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
|
|
|
335
354
|
|
|
336
355
|
if (response?.code === 0) {
|
|
337
356
|
this.energy.year = response.result || response.energyYear || '0';
|
|
338
|
-
logger.
|
|
357
|
+
logger.info(`[${this.deviceName}] Successfully retrieved yearly energy data`);
|
|
339
358
|
} else {
|
|
340
359
|
this.energy.year = '0';
|
|
341
360
|
logger.debug(`[${this.deviceName}] Failed to get yearly energy data: ${JSON.stringify(response)}`);
|
|
@@ -351,7 +370,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
|
|
|
351
370
|
if (this.features.includes('energy')) {
|
|
352
371
|
await this.updateEnergy();
|
|
353
372
|
}
|
|
354
|
-
logger.
|
|
373
|
+
logger.info(`[${this.deviceName}] Successfully updated outlet information`);
|
|
355
374
|
}
|
|
356
375
|
|
|
357
376
|
/**
|
|
@@ -20,17 +20,17 @@ export class VeSyncOutlet7A extends VeSyncOutlet {
|
|
|
20
20
|
*/
|
|
21
21
|
async turnOn(): Promise<boolean> {
|
|
22
22
|
logger.debug(`[${this.deviceName}] Turning outlet on`);
|
|
23
|
-
const url = `/v1/wifi-switch-1.3
|
|
24
|
-
const [response] = await Helpers.callApi(
|
|
23
|
+
const url = `/v1/wifi-switch-1.3/${this.cid}/status/on`;
|
|
24
|
+
const [response, statusCode] = await Helpers.callApi(
|
|
25
25
|
url,
|
|
26
26
|
'put',
|
|
27
|
-
|
|
27
|
+
{},
|
|
28
28
|
Helpers.reqHeaders(this.manager)
|
|
29
29
|
);
|
|
30
30
|
|
|
31
|
-
if (
|
|
31
|
+
if (statusCode === 200) {
|
|
32
32
|
this.deviceStatus = 'on';
|
|
33
|
-
logger.
|
|
33
|
+
logger.info(`[${this.deviceName}] Successfully turned outlet on`);
|
|
34
34
|
return true;
|
|
35
35
|
}
|
|
36
36
|
logger.error(`[${this.deviceName}] Failed to turn outlet on: ${JSON.stringify(response)}`);
|
|
@@ -42,17 +42,17 @@ export class VeSyncOutlet7A extends VeSyncOutlet {
|
|
|
42
42
|
*/
|
|
43
43
|
async turnOff(): Promise<boolean> {
|
|
44
44
|
logger.debug(`[${this.deviceName}] Turning outlet off`);
|
|
45
|
-
const url = `/v1/wifi-switch-1.3
|
|
46
|
-
const [response] = await Helpers.callApi(
|
|
45
|
+
const url = `/v1/wifi-switch-1.3/${this.cid}/status/off`;
|
|
46
|
+
const [response, statusCode] = await Helpers.callApi(
|
|
47
47
|
url,
|
|
48
48
|
'put',
|
|
49
|
-
|
|
49
|
+
{},
|
|
50
50
|
Helpers.reqHeaders(this.manager)
|
|
51
51
|
);
|
|
52
52
|
|
|
53
|
-
if (
|
|
53
|
+
if (statusCode === 200) {
|
|
54
54
|
this.deviceStatus = 'off';
|
|
55
|
-
logger.
|
|
55
|
+
logger.info(`[${this.deviceName}] Successfully turned outlet off`);
|
|
56
56
|
return true;
|
|
57
57
|
}
|
|
58
58
|
logger.error(`[${this.deviceName}] Failed to turn outlet off: ${JSON.stringify(response)}`);
|
|
@@ -88,7 +88,7 @@ export class VeSyncOutlet10A extends VeSyncOutlet {
|
|
|
88
88
|
|
|
89
89
|
if (response?.code === 0) {
|
|
90
90
|
this.deviceStatus = 'on';
|
|
91
|
-
logger.
|
|
91
|
+
logger.info(`[${this.deviceName}] Successfully turned outlet on`);
|
|
92
92
|
return true;
|
|
93
93
|
}
|
|
94
94
|
logger.error(`[${this.deviceName}] Failed to turn outlet on: ${JSON.stringify(response)}`);
|
|
@@ -115,7 +115,7 @@ export class VeSyncOutlet10A extends VeSyncOutlet {
|
|
|
115
115
|
|
|
116
116
|
if (response?.code === 0) {
|
|
117
117
|
this.deviceStatus = 'off';
|
|
118
|
-
logger.
|
|
118
|
+
logger.info(`[${this.deviceName}] Successfully turned outlet off`);
|
|
119
119
|
return true;
|
|
120
120
|
}
|
|
121
121
|
logger.error(`[${this.deviceName}] Failed to turn outlet off: ${JSON.stringify(response)}`);
|
|
@@ -151,7 +151,7 @@ export class VeSyncOutlet15A extends VeSyncOutlet {
|
|
|
151
151
|
|
|
152
152
|
if (response?.code === 0) {
|
|
153
153
|
this.deviceStatus = 'on';
|
|
154
|
-
logger.
|
|
154
|
+
logger.info(`[${this.deviceName}] Successfully turned outlet on`);
|
|
155
155
|
return true;
|
|
156
156
|
}
|
|
157
157
|
logger.error(`[${this.deviceName}] Failed to turn outlet on: ${JSON.stringify(response)}`);
|
|
@@ -178,7 +178,7 @@ export class VeSyncOutlet15A extends VeSyncOutlet {
|
|
|
178
178
|
|
|
179
179
|
if (response?.code === 0) {
|
|
180
180
|
this.deviceStatus = 'off';
|
|
181
|
-
logger.
|
|
181
|
+
logger.info(`[${this.deviceName}] Successfully turned outlet off`);
|
|
182
182
|
return true;
|
|
183
183
|
}
|
|
184
184
|
logger.error(`[${this.deviceName}] Failed to turn outlet off: ${JSON.stringify(response)}`);
|
|
@@ -210,7 +210,7 @@ export class VeSyncOutlet15A extends VeSyncOutlet {
|
|
|
210
210
|
|
|
211
211
|
if (response?.code === 0) {
|
|
212
212
|
this.details.nightLightStatus = 'on';
|
|
213
|
-
logger.
|
|
213
|
+
logger.info(`[${this.deviceName}] Successfully turned nightlight on`);
|
|
214
214
|
return true;
|
|
215
215
|
}
|
|
216
216
|
logger.error(`[${this.deviceName}] Failed to turn nightlight on: ${JSON.stringify(response)}`);
|
|
@@ -242,7 +242,7 @@ export class VeSyncOutlet15A extends VeSyncOutlet {
|
|
|
242
242
|
|
|
243
243
|
if (response?.code === 0) {
|
|
244
244
|
this.details.nightLightStatus = 'off';
|
|
245
|
-
logger.
|
|
245
|
+
logger.info(`[${this.deviceName}] Successfully turned nightlight off`);
|
|
246
246
|
return true;
|
|
247
247
|
}
|
|
248
248
|
logger.error(`[${this.deviceName}] Failed to turn nightlight off: ${JSON.stringify(response)}`);
|
|
@@ -254,20 +254,32 @@ export class VeSyncOutlet15A extends VeSyncOutlet {
|
|
|
254
254
|
* VeSync Outdoor Plug
|
|
255
255
|
*/
|
|
256
256
|
export class VeSyncOutdoorPlug extends VeSyncOutlet {
|
|
257
|
+
protected subDeviceNo?: number;
|
|
258
|
+
protected isSubDevice: boolean;
|
|
259
|
+
protected parentCid?: string;
|
|
260
|
+
|
|
257
261
|
constructor(details: Record<string, any>, manager: VeSync) {
|
|
258
262
|
super(details, manager);
|
|
263
|
+
this.isSubDevice = details.isSubDevice || false;
|
|
264
|
+
this.subDeviceNo = details.subDeviceNo;
|
|
265
|
+
this.parentCid = details.parentCid;
|
|
259
266
|
}
|
|
260
267
|
|
|
261
268
|
/**
|
|
262
269
|
* Turn outlet on
|
|
263
270
|
*/
|
|
264
271
|
async turnOn(): Promise<boolean> {
|
|
272
|
+
if (!this.isSubDevice) {
|
|
273
|
+
logger.error(`[${this.deviceName}] Cannot control parent device directly`);
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
|
|
265
277
|
logger.debug(`[${this.deviceName}] Turning outlet on`);
|
|
266
278
|
const body = {
|
|
267
279
|
...Helpers.reqBody(this.manager, 'devicestatus'),
|
|
268
280
|
uuid: this.uuid,
|
|
269
281
|
status: 'on',
|
|
270
|
-
switchNo:
|
|
282
|
+
switchNo: this.subDeviceNo
|
|
271
283
|
};
|
|
272
284
|
|
|
273
285
|
const [response] = await Helpers.callApi(
|
|
@@ -279,7 +291,7 @@ export class VeSyncOutdoorPlug extends VeSyncOutlet {
|
|
|
279
291
|
|
|
280
292
|
if (response?.code === 0) {
|
|
281
293
|
this.deviceStatus = 'on';
|
|
282
|
-
logger.
|
|
294
|
+
logger.info(`[${this.deviceName}] Successfully turned outlet on`);
|
|
283
295
|
return true;
|
|
284
296
|
}
|
|
285
297
|
logger.error(`[${this.deviceName}] Failed to turn outlet on: ${JSON.stringify(response)}`);
|
|
@@ -290,12 +302,17 @@ export class VeSyncOutdoorPlug extends VeSyncOutlet {
|
|
|
290
302
|
* Turn outlet off
|
|
291
303
|
*/
|
|
292
304
|
async turnOff(): Promise<boolean> {
|
|
305
|
+
if (!this.isSubDevice) {
|
|
306
|
+
logger.error(`[${this.deviceName}] Cannot control parent device directly`);
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
|
|
293
310
|
logger.debug(`[${this.deviceName}] Turning outlet off`);
|
|
294
311
|
const body = {
|
|
295
312
|
...Helpers.reqBody(this.manager, 'devicestatus'),
|
|
296
313
|
uuid: this.uuid,
|
|
297
314
|
status: 'off',
|
|
298
|
-
switchNo:
|
|
315
|
+
switchNo: this.subDeviceNo
|
|
299
316
|
};
|
|
300
317
|
|
|
301
318
|
const [response] = await Helpers.callApi(
|
|
@@ -307,7 +324,7 @@ export class VeSyncOutdoorPlug extends VeSyncOutlet {
|
|
|
307
324
|
|
|
308
325
|
if (response?.code === 0) {
|
|
309
326
|
this.deviceStatus = 'off';
|
|
310
|
-
logger.
|
|
327
|
+
logger.info(`[${this.deviceName}] Successfully turned outlet off`);
|
|
311
328
|
return true;
|
|
312
329
|
}
|
|
313
330
|
logger.error(`[${this.deviceName}] Failed to turn outlet off: ${JSON.stringify(response)}`);
|