tsvesync 1.0.66 → 1.0.68
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/fans/airBypass.js +175 -0
- package/dist/lib/fans/humid200300S.d.ts +8 -0
- package/dist/lib/fans/humid200300S.js +49 -2
- package/dist/lib/vesyncFan.js +1 -1
- package/package.json +1 -1
- package/src/lib/fans/airBypass.ts +223 -0
- package/src/lib/fans/humid200300S.ts +57 -2
- package/src/lib/vesyncFan.ts +1 -1
|
@@ -213,6 +213,44 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
213
213
|
// return false;
|
|
214
214
|
// }
|
|
215
215
|
logger_1.logger.info(`Changing fan speed to ${speed} for device: ${this.deviceName}`);
|
|
216
|
+
// Special handling for LV series
|
|
217
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
218
|
+
// Check if device is in manual mode
|
|
219
|
+
if (this.details.mode !== 'manual') {
|
|
220
|
+
logger_1.logger.debug(`${this.deviceName} not in manual mode, cannot change speed`);
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
// Validate speed for LV series (1-3)
|
|
224
|
+
if (speed < 1 || speed > 3) {
|
|
225
|
+
logger_1.logger.error(`Invalid fan speed: ${speed}. Must be between 1 and 3 for device: ${this.deviceName}`);
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/updateSpeed', 'put', {
|
|
229
|
+
acceptLanguage: 'en',
|
|
230
|
+
accountID: this.manager.accountId,
|
|
231
|
+
level: speed,
|
|
232
|
+
timeZone: this.manager.timeZone,
|
|
233
|
+
token: this.manager.token,
|
|
234
|
+
uuid: this.uuid
|
|
235
|
+
}, {
|
|
236
|
+
'accept-language': 'en',
|
|
237
|
+
'accountId': this.manager.accountId,
|
|
238
|
+
'appVersion': '2.8.6',
|
|
239
|
+
'content-type': 'application/json',
|
|
240
|
+
'tk': this.manager.token,
|
|
241
|
+
'tz': this.manager.timeZone
|
|
242
|
+
});
|
|
243
|
+
const success = this.checkResponse([response, status], 'changeFanSpeed');
|
|
244
|
+
if (success) {
|
|
245
|
+
this.details.speed = speed;
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
logger_1.logger.error(`Failed to change fan speed to ${speed} for device: ${this.deviceName}`);
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Standard implementation for other devices
|
|
216
254
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
217
255
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
218
256
|
cid: this.cid,
|
|
@@ -244,6 +282,39 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
244
282
|
throw new Error(error);
|
|
245
283
|
}
|
|
246
284
|
logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
|
|
285
|
+
// Special handling for LV series
|
|
286
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
287
|
+
const payload = {
|
|
288
|
+
acceptLanguage: 'en',
|
|
289
|
+
accountID: this.manager.accountId,
|
|
290
|
+
mode: mode,
|
|
291
|
+
timeZone: this.manager.timeZone,
|
|
292
|
+
token: this.manager.token,
|
|
293
|
+
uuid: this.uuid
|
|
294
|
+
};
|
|
295
|
+
// For manual mode, we need to set the level
|
|
296
|
+
if (mode === 'manual') {
|
|
297
|
+
payload.level = this.details.speed || 1;
|
|
298
|
+
}
|
|
299
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/updateMode', 'put', payload, {
|
|
300
|
+
'accept-language': 'en',
|
|
301
|
+
'accountId': this.manager.accountId,
|
|
302
|
+
'appVersion': '2.8.6',
|
|
303
|
+
'content-type': 'application/json',
|
|
304
|
+
'tk': this.manager.token,
|
|
305
|
+
'tz': this.manager.timeZone
|
|
306
|
+
});
|
|
307
|
+
const success = this.checkResponse([response, status], 'setMode');
|
|
308
|
+
if (success) {
|
|
309
|
+
this.details.mode = mode;
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// Standard implementation for other devices
|
|
247
318
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
248
319
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
249
320
|
cid: this.cid,
|
|
@@ -272,6 +343,34 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
272
343
|
throw new Error(error);
|
|
273
344
|
}
|
|
274
345
|
logger_1.logger.debug(`Setting display to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
346
|
+
// Special handling for LV series
|
|
347
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
348
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/updateScreen', 'put', {
|
|
349
|
+
acceptLanguage: 'en',
|
|
350
|
+
accountID: this.manager.accountId,
|
|
351
|
+
status: enabled ? 'on' : 'off',
|
|
352
|
+
timeZone: this.manager.timeZone,
|
|
353
|
+
token: this.manager.token,
|
|
354
|
+
uuid: this.uuid
|
|
355
|
+
}, {
|
|
356
|
+
'accept-language': 'en',
|
|
357
|
+
'accountId': this.manager.accountId,
|
|
358
|
+
'appVersion': '2.8.6',
|
|
359
|
+
'content-type': 'application/json',
|
|
360
|
+
'tk': this.manager.token,
|
|
361
|
+
'tz': this.manager.timeZone
|
|
362
|
+
});
|
|
363
|
+
const success = this.checkResponse([response, status], 'setDisplay');
|
|
364
|
+
if (success) {
|
|
365
|
+
this.details.screenStatus = enabled ? 'on' : 'off';
|
|
366
|
+
return true;
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
logger_1.logger.error(`Failed to set display to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// Standard implementation for other devices
|
|
275
374
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
276
375
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
277
376
|
cid: this.cid,
|
|
@@ -303,6 +402,34 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
303
402
|
throw new Error(error);
|
|
304
403
|
}
|
|
305
404
|
logger_1.logger.debug(`Setting child lock to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
405
|
+
// Special handling for LV series
|
|
406
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
407
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/updateChildLock', 'put', {
|
|
408
|
+
acceptLanguage: 'en',
|
|
409
|
+
accountID: this.manager.accountId,
|
|
410
|
+
status: enabled ? 'on' : 'off',
|
|
411
|
+
timeZone: this.manager.timeZone,
|
|
412
|
+
token: this.manager.token,
|
|
413
|
+
uuid: this.uuid
|
|
414
|
+
}, {
|
|
415
|
+
'accept-language': 'en',
|
|
416
|
+
'accountId': this.manager.accountId,
|
|
417
|
+
'appVersion': '2.8.6',
|
|
418
|
+
'content-type': 'application/json',
|
|
419
|
+
'tk': this.manager.token,
|
|
420
|
+
'tz': this.manager.timeZone
|
|
421
|
+
});
|
|
422
|
+
const success = this.checkResponse([response, status], 'setChildLock');
|
|
423
|
+
if (success) {
|
|
424
|
+
this.details.childLock = enabled;
|
|
425
|
+
return true;
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
logger_1.logger.error(`Failed to set child lock to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
// Standard implementation for other devices
|
|
306
433
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
307
434
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
308
435
|
cid: this.cid,
|
|
@@ -334,6 +461,31 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
334
461
|
throw new Error(error);
|
|
335
462
|
}
|
|
336
463
|
logger_1.logger.debug(`Setting timer to ${hours} hours for device: ${this.deviceName}`);
|
|
464
|
+
// Special handling for LV series
|
|
465
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
466
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/updateTimer', 'put', {
|
|
467
|
+
acceptLanguage: 'en',
|
|
468
|
+
accountID: this.manager.accountId,
|
|
469
|
+
action: 'off',
|
|
470
|
+
duration: hours,
|
|
471
|
+
timeZone: this.manager.timeZone,
|
|
472
|
+
token: this.manager.token,
|
|
473
|
+
uuid: this.uuid
|
|
474
|
+
}, {
|
|
475
|
+
'accept-language': 'en',
|
|
476
|
+
'accountId': this.manager.accountId,
|
|
477
|
+
'appVersion': '2.8.6',
|
|
478
|
+
'content-type': 'application/json',
|
|
479
|
+
'tk': this.manager.token,
|
|
480
|
+
'tz': this.manager.timeZone
|
|
481
|
+
});
|
|
482
|
+
const success = this.checkResponse([response, status], 'setTimer');
|
|
483
|
+
if (!success) {
|
|
484
|
+
logger_1.logger.error(`Failed to set timer to ${hours} hours for device: ${this.deviceName}`);
|
|
485
|
+
}
|
|
486
|
+
return success;
|
|
487
|
+
}
|
|
488
|
+
// Standard implementation for other devices
|
|
337
489
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
338
490
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
339
491
|
cid: this.cid,
|
|
@@ -363,6 +515,29 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
363
515
|
throw new Error(error);
|
|
364
516
|
}
|
|
365
517
|
logger_1.logger.debug(`Clearing timer for device: ${this.deviceName}`);
|
|
518
|
+
// Special handling for LV series
|
|
519
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
520
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/cancelTimer', 'put', {
|
|
521
|
+
acceptLanguage: 'en',
|
|
522
|
+
accountID: this.manager.accountId,
|
|
523
|
+
timeZone: this.manager.timeZone,
|
|
524
|
+
token: this.manager.token,
|
|
525
|
+
uuid: this.uuid
|
|
526
|
+
}, {
|
|
527
|
+
'accept-language': 'en',
|
|
528
|
+
'accountId': this.manager.accountId,
|
|
529
|
+
'appVersion': '2.8.6',
|
|
530
|
+
'content-type': 'application/json',
|
|
531
|
+
'tk': this.manager.token,
|
|
532
|
+
'tz': this.manager.timeZone
|
|
533
|
+
});
|
|
534
|
+
const success = this.checkResponse([response, status], 'clearTimer');
|
|
535
|
+
if (!success) {
|
|
536
|
+
logger_1.logger.error(`Failed to clear timer for device: ${this.deviceName}`);
|
|
537
|
+
}
|
|
538
|
+
return success;
|
|
539
|
+
}
|
|
540
|
+
// Standard implementation for other devices
|
|
366
541
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
367
542
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
368
543
|
cid: this.cid,
|
|
@@ -38,4 +38,12 @@ export declare class VeSyncHumid200300S extends VeSyncHumidifier {
|
|
|
38
38
|
* Get automatic stop configuration
|
|
39
39
|
*/
|
|
40
40
|
get automaticStopConfigured(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Get night light brightness
|
|
43
|
+
*/
|
|
44
|
+
get nightLightBrightness(): number;
|
|
45
|
+
/**
|
|
46
|
+
* Set night light brightness
|
|
47
|
+
*/
|
|
48
|
+
setNightLightBrightness(brightness: number): Promise<boolean>;
|
|
41
49
|
}
|
|
@@ -11,7 +11,7 @@ class VeSyncHumid200300S extends humidifier_1.VeSyncHumidifier {
|
|
|
11
11
|
constructor(details, manager) {
|
|
12
12
|
super(details, manager);
|
|
13
13
|
this.modes = ['auto', 'manual', 'sleep'];
|
|
14
|
-
this.features = ['humidity', 'mist', 'display', 'timer', 'auto_mode'];
|
|
14
|
+
this.features = ['humidity', 'mist', 'display', 'timer', 'auto_mode', 'night_light'];
|
|
15
15
|
this.mistLevels = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
16
16
|
this.humidityRange = { min: 30, max: 80 };
|
|
17
17
|
logger_1.logger.debug(`Initialized VeSyncHumid200300S device: ${this.deviceName}`);
|
|
@@ -51,7 +51,8 @@ class VeSyncHumid200300S extends humidifier_1.VeSyncHumidifier {
|
|
|
51
51
|
automatic_stop_configured: ((_b = result.configuration) === null || _b === void 0 ? void 0 : _b.automatic_stop) || false,
|
|
52
52
|
auto_target_humidity: ((_c = result.configuration) === null || _c === void 0 ? void 0 : _c.auto_target_humidity) || 0,
|
|
53
53
|
configuration: result.configuration || {},
|
|
54
|
-
connection_status: result.connection_status || null
|
|
54
|
+
connection_status: result.connection_status || null,
|
|
55
|
+
night_light_brightness: result.night_light_brightness || 0
|
|
55
56
|
};
|
|
56
57
|
// Log raw response for debugging
|
|
57
58
|
logger_1.logger.debug(`Raw API Response: ${JSON.stringify(response)}`);
|
|
@@ -125,5 +126,51 @@ class VeSyncHumid200300S extends humidifier_1.VeSyncHumidifier {
|
|
|
125
126
|
get automaticStopConfigured() {
|
|
126
127
|
return this.details.automatic_stop_configured || false;
|
|
127
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Get night light brightness
|
|
131
|
+
*/
|
|
132
|
+
get nightLightBrightness() {
|
|
133
|
+
return this.details.night_light_brightness || 0;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Set night light brightness
|
|
137
|
+
*/
|
|
138
|
+
async setNightLightBrightness(brightness) {
|
|
139
|
+
var _a;
|
|
140
|
+
if (brightness < 0 || brightness > 100) {
|
|
141
|
+
const error = `Invalid brightness: ${brightness}. Must be between 0 and 100`;
|
|
142
|
+
logger_1.logger.error(`${error} for device: ${this.deviceName}`);
|
|
143
|
+
throw new Error(error);
|
|
144
|
+
}
|
|
145
|
+
logger_1.logger.debug(`Setting night light brightness to ${brightness} for device: ${this.deviceName}`);
|
|
146
|
+
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
147
|
+
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
148
|
+
cid: this.cid,
|
|
149
|
+
configModule: this.configModule,
|
|
150
|
+
payload: {
|
|
151
|
+
data: {
|
|
152
|
+
brightness
|
|
153
|
+
},
|
|
154
|
+
method: 'setNightLight',
|
|
155
|
+
source: 'APP'
|
|
156
|
+
}
|
|
157
|
+
}, helpers_1.Helpers.reqHeaderBypass());
|
|
158
|
+
// Check for error code 11000000 which indicates feature not supported
|
|
159
|
+
if (((_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.code) === 11000000) {
|
|
160
|
+
logger_1.logger.warn(`Night light control not supported by device: ${this.deviceName} (${this.deviceType})`);
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
const success = this.checkResponse([response, status], 'setNightLightBrightness');
|
|
164
|
+
if (success) {
|
|
165
|
+
this.details.night_light_brightness = brightness;
|
|
166
|
+
// Get latest state and log it
|
|
167
|
+
await this.getDetails();
|
|
168
|
+
logger_1.logger.debug(`Device state after night light brightness change: ${JSON.stringify(this.details)}`);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
logger_1.logger.error(`Failed to set night light brightness to ${brightness} for device: ${this.deviceName}`);
|
|
172
|
+
}
|
|
173
|
+
return success;
|
|
174
|
+
}
|
|
128
175
|
}
|
|
129
176
|
exports.VeSyncHumid200300S = VeSyncHumid200300S;
|
package/dist/lib/vesyncFan.js
CHANGED
|
@@ -203,7 +203,7 @@ exports.fanConfig = {
|
|
|
203
203
|
// LUH Series
|
|
204
204
|
'LUH-A601S-WUSB': {
|
|
205
205
|
module: 'VeSyncWarmHumidifier',
|
|
206
|
-
features: ['display', 'humidity', 'mist', '
|
|
206
|
+
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode', 'night_light']
|
|
207
207
|
},
|
|
208
208
|
'LUH-A601S-AUSW': {
|
|
209
209
|
module: 'VeSyncWarmHumidifier',
|
package/package.json
CHANGED
|
@@ -261,6 +261,53 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
261
261
|
// }
|
|
262
262
|
|
|
263
263
|
logger.info(`Changing fan speed to ${speed} for device: ${this.deviceName}`);
|
|
264
|
+
|
|
265
|
+
// Special handling for LV series
|
|
266
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
267
|
+
// Check if device is in manual mode
|
|
268
|
+
if (this.details.mode !== 'manual') {
|
|
269
|
+
logger.debug(`${this.deviceName} not in manual mode, cannot change speed`);
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Validate speed for LV series (1-3)
|
|
274
|
+
if (speed < 1 || speed > 3) {
|
|
275
|
+
logger.error(`Invalid fan speed: ${speed}. Must be between 1 and 3 for device: ${this.deviceName}`);
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const [response, status] = await this.callApi(
|
|
280
|
+
'/131airPurifier/v1/device/updateSpeed',
|
|
281
|
+
'put',
|
|
282
|
+
{
|
|
283
|
+
acceptLanguage: 'en',
|
|
284
|
+
accountID: this.manager.accountId!,
|
|
285
|
+
level: speed,
|
|
286
|
+
timeZone: this.manager.timeZone!,
|
|
287
|
+
token: this.manager.token!,
|
|
288
|
+
uuid: this.uuid
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
'accept-language': 'en',
|
|
292
|
+
'accountId': this.manager.accountId!,
|
|
293
|
+
'appVersion': '2.8.6',
|
|
294
|
+
'content-type': 'application/json',
|
|
295
|
+
'tk': this.manager.token!,
|
|
296
|
+
'tz': this.manager.timeZone!
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
const success = this.checkResponse([response, status], 'changeFanSpeed');
|
|
301
|
+
if (success) {
|
|
302
|
+
this.details.speed = speed;
|
|
303
|
+
return true;
|
|
304
|
+
} else {
|
|
305
|
+
logger.error(`Failed to change fan speed to ${speed} for device: ${this.deviceName}`);
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Standard implementation for other devices
|
|
264
311
|
const [response, status] = await this.callApi(
|
|
265
312
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
266
313
|
'post',
|
|
@@ -300,6 +347,48 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
300
347
|
}
|
|
301
348
|
|
|
302
349
|
logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
|
|
350
|
+
|
|
351
|
+
// Special handling for LV series
|
|
352
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
353
|
+
const payload: Record<string, any> = {
|
|
354
|
+
acceptLanguage: 'en',
|
|
355
|
+
accountID: this.manager.accountId!,
|
|
356
|
+
mode: mode,
|
|
357
|
+
timeZone: this.manager.timeZone!,
|
|
358
|
+
token: this.manager.token!,
|
|
359
|
+
uuid: this.uuid
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
// For manual mode, we need to set the level
|
|
363
|
+
if (mode === 'manual') {
|
|
364
|
+
payload.level = this.details.speed || 1;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const [response, status] = await this.callApi(
|
|
368
|
+
'/131airPurifier/v1/device/updateMode',
|
|
369
|
+
'put',
|
|
370
|
+
payload,
|
|
371
|
+
{
|
|
372
|
+
'accept-language': 'en',
|
|
373
|
+
'accountId': this.manager.accountId!,
|
|
374
|
+
'appVersion': '2.8.6',
|
|
375
|
+
'content-type': 'application/json',
|
|
376
|
+
'tk': this.manager.token!,
|
|
377
|
+
'tz': this.manager.timeZone!
|
|
378
|
+
}
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const success = this.checkResponse([response, status], 'setMode');
|
|
382
|
+
if (success) {
|
|
383
|
+
this.details.mode = mode;
|
|
384
|
+
return true;
|
|
385
|
+
} else {
|
|
386
|
+
logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Standard implementation for other devices
|
|
303
392
|
const [response, status] = await this.callApi(
|
|
304
393
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
305
394
|
'post',
|
|
@@ -336,6 +425,41 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
336
425
|
}
|
|
337
426
|
|
|
338
427
|
logger.debug(`Setting display to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
428
|
+
|
|
429
|
+
// Special handling for LV series
|
|
430
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
431
|
+
const [response, status] = await this.callApi(
|
|
432
|
+
'/131airPurifier/v1/device/updateScreen',
|
|
433
|
+
'put',
|
|
434
|
+
{
|
|
435
|
+
acceptLanguage: 'en',
|
|
436
|
+
accountID: this.manager.accountId!,
|
|
437
|
+
status: enabled ? 'on' : 'off',
|
|
438
|
+
timeZone: this.manager.timeZone!,
|
|
439
|
+
token: this.manager.token!,
|
|
440
|
+
uuid: this.uuid
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
'accept-language': 'en',
|
|
444
|
+
'accountId': this.manager.accountId!,
|
|
445
|
+
'appVersion': '2.8.6',
|
|
446
|
+
'content-type': 'application/json',
|
|
447
|
+
'tk': this.manager.token!,
|
|
448
|
+
'tz': this.manager.timeZone!
|
|
449
|
+
}
|
|
450
|
+
);
|
|
451
|
+
|
|
452
|
+
const success = this.checkResponse([response, status], 'setDisplay');
|
|
453
|
+
if (success) {
|
|
454
|
+
this.details.screenStatus = enabled ? 'on' : 'off';
|
|
455
|
+
return true;
|
|
456
|
+
} else {
|
|
457
|
+
logger.error(`Failed to set display to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// Standard implementation for other devices
|
|
339
463
|
const [response, status] = await this.callApi(
|
|
340
464
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
341
465
|
'post',
|
|
@@ -374,6 +498,41 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
374
498
|
}
|
|
375
499
|
|
|
376
500
|
logger.debug(`Setting child lock to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
501
|
+
|
|
502
|
+
// Special handling for LV series
|
|
503
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
504
|
+
const [response, status] = await this.callApi(
|
|
505
|
+
'/131airPurifier/v1/device/updateChildLock',
|
|
506
|
+
'put',
|
|
507
|
+
{
|
|
508
|
+
acceptLanguage: 'en',
|
|
509
|
+
accountID: this.manager.accountId!,
|
|
510
|
+
status: enabled ? 'on' : 'off',
|
|
511
|
+
timeZone: this.manager.timeZone!,
|
|
512
|
+
token: this.manager.token!,
|
|
513
|
+
uuid: this.uuid
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
'accept-language': 'en',
|
|
517
|
+
'accountId': this.manager.accountId!,
|
|
518
|
+
'appVersion': '2.8.6',
|
|
519
|
+
'content-type': 'application/json',
|
|
520
|
+
'tk': this.manager.token!,
|
|
521
|
+
'tz': this.manager.timeZone!
|
|
522
|
+
}
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
const success = this.checkResponse([response, status], 'setChildLock');
|
|
526
|
+
if (success) {
|
|
527
|
+
this.details.childLock = enabled;
|
|
528
|
+
return true;
|
|
529
|
+
} else {
|
|
530
|
+
logger.error(`Failed to set child lock to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Standard implementation for other devices
|
|
377
536
|
const [response, status] = await this.callApi(
|
|
378
537
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
379
538
|
'post',
|
|
@@ -412,6 +571,39 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
412
571
|
}
|
|
413
572
|
|
|
414
573
|
logger.debug(`Setting timer to ${hours} hours for device: ${this.deviceName}`);
|
|
574
|
+
|
|
575
|
+
// Special handling for LV series
|
|
576
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
577
|
+
const [response, status] = await this.callApi(
|
|
578
|
+
'/131airPurifier/v1/device/updateTimer',
|
|
579
|
+
'put',
|
|
580
|
+
{
|
|
581
|
+
acceptLanguage: 'en',
|
|
582
|
+
accountID: this.manager.accountId!,
|
|
583
|
+
action: 'off',
|
|
584
|
+
duration: hours,
|
|
585
|
+
timeZone: this.manager.timeZone!,
|
|
586
|
+
token: this.manager.token!,
|
|
587
|
+
uuid: this.uuid
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
'accept-language': 'en',
|
|
591
|
+
'accountId': this.manager.accountId!,
|
|
592
|
+
'appVersion': '2.8.6',
|
|
593
|
+
'content-type': 'application/json',
|
|
594
|
+
'tk': this.manager.token!,
|
|
595
|
+
'tz': this.manager.timeZone!
|
|
596
|
+
}
|
|
597
|
+
);
|
|
598
|
+
|
|
599
|
+
const success = this.checkResponse([response, status], 'setTimer');
|
|
600
|
+
if (!success) {
|
|
601
|
+
logger.error(`Failed to set timer to ${hours} hours for device: ${this.deviceName}`);
|
|
602
|
+
}
|
|
603
|
+
return success;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
// Standard implementation for other devices
|
|
415
607
|
const [response, status] = await this.callApi(
|
|
416
608
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
417
609
|
'post',
|
|
@@ -449,6 +641,37 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
449
641
|
}
|
|
450
642
|
|
|
451
643
|
logger.debug(`Clearing timer for device: ${this.deviceName}`);
|
|
644
|
+
|
|
645
|
+
// Special handling for LV series
|
|
646
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
647
|
+
const [response, status] = await this.callApi(
|
|
648
|
+
'/131airPurifier/v1/device/cancelTimer',
|
|
649
|
+
'put',
|
|
650
|
+
{
|
|
651
|
+
acceptLanguage: 'en',
|
|
652
|
+
accountID: this.manager.accountId!,
|
|
653
|
+
timeZone: this.manager.timeZone!,
|
|
654
|
+
token: this.manager.token!,
|
|
655
|
+
uuid: this.uuid
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
'accept-language': 'en',
|
|
659
|
+
'accountId': this.manager.accountId!,
|
|
660
|
+
'appVersion': '2.8.6',
|
|
661
|
+
'content-type': 'application/json',
|
|
662
|
+
'tk': this.manager.token!,
|
|
663
|
+
'tz': this.manager.timeZone!
|
|
664
|
+
}
|
|
665
|
+
);
|
|
666
|
+
|
|
667
|
+
const success = this.checkResponse([response, status], 'clearTimer');
|
|
668
|
+
if (!success) {
|
|
669
|
+
logger.error(`Failed to clear timer for device: ${this.deviceName}`);
|
|
670
|
+
}
|
|
671
|
+
return success;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
// Standard implementation for other devices
|
|
452
675
|
const [response, status] = await this.callApi(
|
|
453
676
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
454
677
|
'post',
|
|
@@ -8,7 +8,7 @@ import { logger } from '../logger';
|
|
|
8
8
|
*/
|
|
9
9
|
export class VeSyncHumid200300S extends VeSyncHumidifier {
|
|
10
10
|
protected readonly modes = ['auto', 'manual', 'sleep'] as const;
|
|
11
|
-
protected readonly features = ['humidity', 'mist', 'display', 'timer', 'auto_mode'];
|
|
11
|
+
protected readonly features = ['humidity', 'mist', 'display', 'timer', 'auto_mode', 'night_light'];
|
|
12
12
|
protected readonly mistLevels = [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
13
13
|
protected readonly humidityRange = { min: 30, max: 80 };
|
|
14
14
|
|
|
@@ -59,7 +59,8 @@ export class VeSyncHumid200300S extends VeSyncHumidifier {
|
|
|
59
59
|
automatic_stop_configured: result.configuration?.automatic_stop || false,
|
|
60
60
|
auto_target_humidity: result.configuration?.auto_target_humidity || 0,
|
|
61
61
|
configuration: result.configuration || {},
|
|
62
|
-
connection_status: result.connection_status || null
|
|
62
|
+
connection_status: result.connection_status || null,
|
|
63
|
+
night_light_brightness: result.night_light_brightness || 0
|
|
63
64
|
};
|
|
64
65
|
|
|
65
66
|
// Log raw response for debugging
|
|
@@ -145,4 +146,58 @@ export class VeSyncHumid200300S extends VeSyncHumidifier {
|
|
|
145
146
|
get automaticStopConfigured(): boolean {
|
|
146
147
|
return this.details.automatic_stop_configured || false;
|
|
147
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get night light brightness
|
|
152
|
+
*/
|
|
153
|
+
get nightLightBrightness(): number {
|
|
154
|
+
return this.details.night_light_brightness || 0;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Set night light brightness
|
|
159
|
+
*/
|
|
160
|
+
async setNightLightBrightness(brightness: number): Promise<boolean> {
|
|
161
|
+
if (brightness < 0 || brightness > 100) {
|
|
162
|
+
const error = `Invalid brightness: ${brightness}. Must be between 0 and 100`;
|
|
163
|
+
logger.error(`${error} for device: ${this.deviceName}`);
|
|
164
|
+
throw new Error(error);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
logger.debug(`Setting night light brightness to ${brightness} for device: ${this.deviceName}`);
|
|
168
|
+
const [response, status] = await this.callApi(
|
|
169
|
+
'/cloud/v2/deviceManaged/bypassV2',
|
|
170
|
+
'post',
|
|
171
|
+
{
|
|
172
|
+
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
173
|
+
cid: this.cid,
|
|
174
|
+
configModule: this.configModule,
|
|
175
|
+
payload: {
|
|
176
|
+
data: {
|
|
177
|
+
brightness
|
|
178
|
+
},
|
|
179
|
+
method: 'setNightLight',
|
|
180
|
+
source: 'APP'
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
Helpers.reqHeaderBypass()
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
// Check for error code 11000000 which indicates feature not supported
|
|
187
|
+
if (response?.result?.code === 11000000) {
|
|
188
|
+
logger.warn(`Night light control not supported by device: ${this.deviceName} (${this.deviceType})`);
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const success = this.checkResponse([response, status], 'setNightLightBrightness');
|
|
193
|
+
if (success) {
|
|
194
|
+
this.details.night_light_brightness = brightness;
|
|
195
|
+
// Get latest state and log it
|
|
196
|
+
await this.getDetails();
|
|
197
|
+
logger.debug(`Device state after night light brightness change: ${JSON.stringify(this.details)}`);
|
|
198
|
+
} else {
|
|
199
|
+
logger.error(`Failed to set night light brightness to ${brightness} for device: ${this.deviceName}`);
|
|
200
|
+
}
|
|
201
|
+
return success;
|
|
202
|
+
}
|
|
148
203
|
}
|
package/src/lib/vesyncFan.ts
CHANGED
|
@@ -216,7 +216,7 @@ export const fanConfig: FanConfig = {
|
|
|
216
216
|
// LUH Series
|
|
217
217
|
'LUH-A601S-WUSB': {
|
|
218
218
|
module: 'VeSyncWarmHumidifier',
|
|
219
|
-
features: ['display', 'humidity', 'mist', '
|
|
219
|
+
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode', 'night_light']
|
|
220
220
|
},
|
|
221
221
|
'LUH-A601S-AUSW': {
|
|
222
222
|
module: 'VeSyncWarmHumidifier',
|