tsvesync 1.0.59 → 1.0.61
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/vesyncBaseDevice.d.ts +0 -5
- package/dist/lib/vesyncBaseDevice.js +1 -29
- package/dist/lib/vesyncFan.js +24 -58
- package/dist/lib/vesyncFanImpl.d.ts +0 -29
- package/dist/lib/vesyncFanImpl.js +40 -135
- package/package.json +1 -1
- package/src/lib/vesyncBaseDevice.ts +1 -33
- package/src/lib/vesyncFan.ts +24 -62
- package/src/lib/vesyncFanImpl.ts +39 -147
|
@@ -16,11 +16,6 @@ export declare abstract class VeSyncBaseDevice {
|
|
|
16
16
|
deviceCategory: string;
|
|
17
17
|
connectionStatus: string;
|
|
18
18
|
constructor(details: Record<string, any>, manager: VeSync);
|
|
19
|
-
/**
|
|
20
|
-
* Normalize device type to match configuration keys
|
|
21
|
-
* This handles variations in device type strings from the API
|
|
22
|
-
*/
|
|
23
|
-
protected normalizeDeviceType(deviceType: string): string;
|
|
24
19
|
/**
|
|
25
20
|
* Return formatted device info to stdout
|
|
26
21
|
*/
|
|
@@ -13,7 +13,7 @@ class VeSyncBaseDevice {
|
|
|
13
13
|
this.cid = details.cid || '';
|
|
14
14
|
this.deviceName = details.deviceName || '';
|
|
15
15
|
this.deviceStatus = details.deviceStatus || 'off';
|
|
16
|
-
this.deviceType =
|
|
16
|
+
this.deviceType = details.deviceType || '';
|
|
17
17
|
this.deviceRegion = details.deviceRegion || '';
|
|
18
18
|
this.uuid = details.uuid || '';
|
|
19
19
|
this.configModule = details.configModule || '';
|
|
@@ -21,34 +21,6 @@ class VeSyncBaseDevice {
|
|
|
21
21
|
this.deviceCategory = details.deviceCategory || '';
|
|
22
22
|
this.connectionStatus = details.connectionStatus || 'offline';
|
|
23
23
|
}
|
|
24
|
-
/**
|
|
25
|
-
* Normalize device type to match configuration keys
|
|
26
|
-
* This handles variations in device type strings from the API
|
|
27
|
-
*/
|
|
28
|
-
normalizeDeviceType(deviceType) {
|
|
29
|
-
// Remove any region suffixes (e.g. -USA, -EU)
|
|
30
|
-
const baseType = deviceType.split('-')[0];
|
|
31
|
-
// Handle known prefix mappings
|
|
32
|
-
const prefixMap = {
|
|
33
|
-
'Core': 'Core',
|
|
34
|
-
'LAP': 'LAP',
|
|
35
|
-
'LTF': 'LTF',
|
|
36
|
-
'Classic': 'Classic',
|
|
37
|
-
'Dual': 'Dual',
|
|
38
|
-
'LUH': 'LUH',
|
|
39
|
-
'LEH': 'LEH',
|
|
40
|
-
'LV-PUR': 'LV-PUR',
|
|
41
|
-
'LV-RH': 'LV-RH'
|
|
42
|
-
};
|
|
43
|
-
// Check if the device type starts with any known prefix
|
|
44
|
-
for (const [prefix, normalized] of Object.entries(prefixMap)) {
|
|
45
|
-
if (deviceType.startsWith(prefix)) {
|
|
46
|
-
return deviceType; // Keep the full device type for exact matches
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
// If no prefix match, return the base type
|
|
50
|
-
return baseType;
|
|
51
|
-
}
|
|
52
24
|
/**
|
|
53
25
|
* Return formatted device info to stdout
|
|
54
26
|
*/
|
package/dist/lib/vesyncFan.js
CHANGED
|
@@ -189,121 +189,98 @@ exports.fanConfig = {
|
|
|
189
189
|
// Classic Series
|
|
190
190
|
'Classic300S': {
|
|
191
191
|
module: 'VeSyncHumidifier',
|
|
192
|
-
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
193
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
192
|
+
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
194
193
|
},
|
|
195
194
|
'Classic200S': {
|
|
196
195
|
module: 'VeSyncHumidifier',
|
|
197
|
-
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
198
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
196
|
+
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
199
197
|
},
|
|
200
198
|
// Dual Series
|
|
201
199
|
'Dual200S': {
|
|
202
200
|
module: 'VeSyncHumidifier',
|
|
203
|
-
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
204
|
-
levels: [1, 2]
|
|
201
|
+
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
205
202
|
},
|
|
206
203
|
// LUH Series
|
|
207
204
|
'LUH-A601S-WUSB': {
|
|
208
205
|
module: 'VeSyncWarmHumidifier',
|
|
209
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
210
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
206
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
211
207
|
},
|
|
212
208
|
'LUH-A601S-AUSW': {
|
|
213
209
|
module: 'VeSyncWarmHumidifier',
|
|
214
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
215
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
210
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
216
211
|
},
|
|
217
212
|
'LUH-D301S-WUSR': {
|
|
218
213
|
module: 'VeSyncWarmHumidifier',
|
|
219
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
220
|
-
levels: [1, 2]
|
|
214
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
221
215
|
},
|
|
222
216
|
'LUH-D301S-WJP': {
|
|
223
217
|
module: 'VeSyncWarmHumidifier',
|
|
224
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
225
|
-
levels: [1, 2]
|
|
218
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
226
219
|
},
|
|
227
220
|
'LUH-D301S-WEU': {
|
|
228
221
|
module: 'VeSyncWarmHumidifier',
|
|
229
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
230
|
-
levels: [1, 2]
|
|
222
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
231
223
|
},
|
|
232
224
|
'LUH-A602S-WUSR': {
|
|
233
225
|
module: 'VeSyncWarmHumidifier',
|
|
234
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
235
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
226
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
236
227
|
},
|
|
237
228
|
'LUH-A602S-WUS': {
|
|
238
229
|
module: 'VeSyncWarmHumidifier',
|
|
239
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
240
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
230
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
241
231
|
},
|
|
242
232
|
'LUH-A602S-WEUR': {
|
|
243
233
|
module: 'VeSyncWarmHumidifier',
|
|
244
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
245
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
234
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
246
235
|
},
|
|
247
236
|
'LUH-A602S-WEU': {
|
|
248
237
|
module: 'VeSyncWarmHumidifier',
|
|
249
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
250
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
238
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
251
239
|
},
|
|
252
240
|
'LUH-A602S-WJP': {
|
|
253
241
|
module: 'VeSyncWarmHumidifier',
|
|
254
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
255
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
242
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
256
243
|
},
|
|
257
244
|
'LUH-A602S-WUSC': {
|
|
258
245
|
module: 'VeSyncWarmHumidifier',
|
|
259
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
260
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
246
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
261
247
|
},
|
|
262
248
|
'LUH-O451S-WEU': {
|
|
263
249
|
module: 'VeSyncWarmHumidifier',
|
|
264
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
265
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
250
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
266
251
|
},
|
|
267
252
|
'LUH-O451S-WUS': {
|
|
268
253
|
module: 'VeSyncWarmHumidifier',
|
|
269
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
270
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
254
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
271
255
|
},
|
|
272
256
|
'LUH-O451S-WUSR': {
|
|
273
257
|
module: 'VeSyncWarmHumidifier',
|
|
274
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
275
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
258
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
276
259
|
},
|
|
277
260
|
'LUH-O601S-WUS': {
|
|
278
261
|
module: 'VeSyncWarmHumidifier',
|
|
279
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
280
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
262
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
281
263
|
},
|
|
282
264
|
'LUH-O601S-KUS': {
|
|
283
265
|
module: 'VeSyncWarmHumidifier',
|
|
284
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
285
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
266
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
286
267
|
},
|
|
287
268
|
'LUH-M101S-WUS': {
|
|
288
269
|
module: 'VeSyncWarmHumidifier',
|
|
289
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
290
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
270
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
291
271
|
},
|
|
292
272
|
'LUH-M101S-WEUR': {
|
|
293
273
|
module: 'VeSyncWarmHumidifier',
|
|
294
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
295
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
274
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
296
275
|
},
|
|
297
276
|
// LEH Series
|
|
298
277
|
'LEH-S601S-WUS': {
|
|
299
278
|
module: 'VeSyncWarmHumidifier',
|
|
300
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
|
|
301
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
279
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
|
|
302
280
|
},
|
|
303
281
|
'LEH-S601S-WUSR': {
|
|
304
282
|
module: 'VeSyncWarmHumidifier',
|
|
305
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
|
|
306
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
283
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
|
|
307
284
|
},
|
|
308
285
|
// LV Series
|
|
309
286
|
'LV-PUR131S': {
|
|
@@ -328,22 +305,11 @@ class VeSyncFan extends vesyncBaseDevice_1.VeSyncBaseDevice {
|
|
|
328
305
|
this.speed_dict = {};
|
|
329
306
|
this._timer = null;
|
|
330
307
|
this.details = details;
|
|
331
|
-
|
|
332
|
-
let config = exports.fanConfig[this.deviceType];
|
|
333
|
-
// If no exact match, try base type
|
|
334
|
-
if (!config) {
|
|
335
|
-
const baseType = this.deviceType.split('-')[0];
|
|
336
|
-
config = exports.fanConfig[baseType];
|
|
337
|
-
}
|
|
338
|
-
// If still no match, use default
|
|
339
|
-
this.config = config || {
|
|
308
|
+
this.config = exports.fanConfig[this.deviceType] || {
|
|
340
309
|
module: 'VeSyncAirBypass',
|
|
341
310
|
features: [],
|
|
342
311
|
levels: []
|
|
343
312
|
};
|
|
344
|
-
if (!config) {
|
|
345
|
-
logger_1.logger.debug(`No configuration found for device type: ${this.deviceType}`);
|
|
346
|
-
}
|
|
347
313
|
}
|
|
348
314
|
/**
|
|
349
315
|
* Check if feature is supported
|
|
@@ -91,40 +91,11 @@ export declare class VeSyncHumidifier extends VeSyncFan {
|
|
|
91
91
|
min: number;
|
|
92
92
|
max: number;
|
|
93
93
|
};
|
|
94
|
-
protected readonly states: readonly ["inactive", "idle", "humidifying"];
|
|
95
94
|
constructor(details: Record<string, any>, manager: VeSync);
|
|
96
|
-
/**
|
|
97
|
-
* Get current operational state
|
|
98
|
-
*/
|
|
99
|
-
get currentState(): string;
|
|
100
|
-
/**
|
|
101
|
-
* Get water level percentage
|
|
102
|
-
*/
|
|
103
|
-
get waterLevel(): number;
|
|
104
|
-
/**
|
|
105
|
-
* Get water tank status
|
|
106
|
-
*/
|
|
107
|
-
get waterTankLifted(): boolean;
|
|
108
|
-
/**
|
|
109
|
-
* Get oscillation state
|
|
110
|
-
*/
|
|
111
|
-
get oscillationEnabled(): boolean;
|
|
112
|
-
/**
|
|
113
|
-
* Set oscillation state
|
|
114
|
-
*/
|
|
115
|
-
setOscillation(enabled: boolean): Promise<boolean>;
|
|
116
95
|
/**
|
|
117
96
|
* Get device details
|
|
118
97
|
*/
|
|
119
98
|
getDetails(): Promise<Boolean>;
|
|
120
|
-
/**
|
|
121
|
-
* Display device info
|
|
122
|
-
*/
|
|
123
|
-
display(): void;
|
|
124
|
-
/**
|
|
125
|
-
* Return JSON details
|
|
126
|
-
*/
|
|
127
|
-
displayJSON(): string;
|
|
128
99
|
/**
|
|
129
100
|
* Turn device on
|
|
130
101
|
*/
|
|
@@ -26,7 +26,6 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
26
26
|
const body = {
|
|
27
27
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
28
28
|
cid: this.cid,
|
|
29
|
-
deviceId: this.cid, // Add deviceId to match YAML spec
|
|
30
29
|
configModule: this.configModule,
|
|
31
30
|
payload: {
|
|
32
31
|
method,
|
|
@@ -210,12 +209,9 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
210
209
|
* Change fan speed
|
|
211
210
|
*/
|
|
212
211
|
async changeFanSpeed(speed) {
|
|
213
|
-
var _a;
|
|
214
|
-
logger_1.logger.debug(`Attempting to change fan speed to ${speed} for device: ${this.deviceName}`);
|
|
215
|
-
logger_1.logger.debug(`Available speeds: ${(_a = this.config.levels) === null || _a === void 0 ? void 0 : _a.join(', ')}`);
|
|
216
212
|
// const speeds = this.config.levels ?? [];
|
|
217
213
|
// if (!speeds.includes(speed)) {
|
|
218
|
-
// logger.
|
|
214
|
+
// logger.error(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')} for device: ${this.deviceName}`);
|
|
219
215
|
// return false;
|
|
220
216
|
// }
|
|
221
217
|
logger_1.logger.info(`Changing fan speed to ${speed} for device: ${this.deviceName}`);
|
|
@@ -244,11 +240,10 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
244
240
|
* Set device mode
|
|
245
241
|
*/
|
|
246
242
|
async setMode(mode) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
logger_1.logger.
|
|
250
|
-
|
|
251
|
-
return false;
|
|
243
|
+
if (!this.modes.includes(mode)) {
|
|
244
|
+
const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
|
|
245
|
+
logger_1.logger.error(`${error} for device: ${this.deviceName}`);
|
|
246
|
+
throw new Error(error);
|
|
252
247
|
}
|
|
253
248
|
logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
|
|
254
249
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
@@ -257,15 +252,15 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
257
252
|
configModule: this.configModule,
|
|
258
253
|
payload: {
|
|
259
254
|
data: {
|
|
260
|
-
|
|
255
|
+
mode
|
|
261
256
|
},
|
|
262
|
-
method: '
|
|
257
|
+
method: 'setPurifierMode',
|
|
263
258
|
source: 'APP'
|
|
264
259
|
}
|
|
265
260
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
266
261
|
const success = this.checkResponse([response, status], 'setMode');
|
|
267
262
|
if (!success) {
|
|
268
|
-
logger_1.logger.
|
|
263
|
+
logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
269
264
|
}
|
|
270
265
|
return success;
|
|
271
266
|
}
|
|
@@ -492,7 +487,6 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
492
487
|
this.modes = ['auto', 'manual', 'sleep'];
|
|
493
488
|
this.displayModes = ['on', 'off'];
|
|
494
489
|
this.humidityRange = { min: 30, max: 80 };
|
|
495
|
-
this.states = ['inactive', 'idle', 'humidifying'];
|
|
496
490
|
// Set mist levels based on model
|
|
497
491
|
switch (this.deviceType) {
|
|
498
492
|
case 'Dual200S':
|
|
@@ -507,66 +501,6 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
507
501
|
}
|
|
508
502
|
logger_1.logger.debug(`Initialized VeSyncHumidifier device: ${this.deviceName}`);
|
|
509
503
|
}
|
|
510
|
-
/**
|
|
511
|
-
* Get current operational state
|
|
512
|
-
*/
|
|
513
|
-
get currentState() {
|
|
514
|
-
if (this.deviceStatus === 'off') {
|
|
515
|
-
return 'inactive';
|
|
516
|
-
}
|
|
517
|
-
if (this.details.water_lacks) {
|
|
518
|
-
return 'idle';
|
|
519
|
-
}
|
|
520
|
-
return 'humidifying';
|
|
521
|
-
}
|
|
522
|
-
/**
|
|
523
|
-
* Get water level percentage
|
|
524
|
-
*/
|
|
525
|
-
get waterLevel() {
|
|
526
|
-
var _a;
|
|
527
|
-
return (_a = this.details.water_level) !== null && _a !== void 0 ? _a : 0;
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* Get water tank status
|
|
531
|
-
*/
|
|
532
|
-
get waterTankLifted() {
|
|
533
|
-
var _a;
|
|
534
|
-
return (_a = this.details.water_tank_lifted) !== null && _a !== void 0 ? _a : false;
|
|
535
|
-
}
|
|
536
|
-
/**
|
|
537
|
-
* Get oscillation state
|
|
538
|
-
*/
|
|
539
|
-
get oscillationEnabled() {
|
|
540
|
-
var _a;
|
|
541
|
-
return (_a = this.details.oscillation_enabled) !== null && _a !== void 0 ? _a : false;
|
|
542
|
-
}
|
|
543
|
-
/**
|
|
544
|
-
* Set oscillation state
|
|
545
|
-
*/
|
|
546
|
-
async setOscillation(enabled) {
|
|
547
|
-
if (!this.hasFeature('oscillation')) {
|
|
548
|
-
logger_1.logger.debug('Oscillation not supported');
|
|
549
|
-
return false;
|
|
550
|
-
}
|
|
551
|
-
logger_1.logger.debug(`Setting oscillation to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
552
|
-
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
553
|
-
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
554
|
-
cid: this.cid,
|
|
555
|
-
configModule: this.configModule,
|
|
556
|
-
payload: {
|
|
557
|
-
data: {
|
|
558
|
-
oscillationEnabled: enabled
|
|
559
|
-
},
|
|
560
|
-
method: 'setSwing',
|
|
561
|
-
source: 'APP'
|
|
562
|
-
}
|
|
563
|
-
}, helpers_1.Helpers.reqHeaderBypass());
|
|
564
|
-
const success = this.checkResponse([response, status], 'setOscillation');
|
|
565
|
-
if (!success) {
|
|
566
|
-
logger_1.logger.debug('Error setting oscillation');
|
|
567
|
-
}
|
|
568
|
-
return success;
|
|
569
|
-
}
|
|
570
504
|
/**
|
|
571
505
|
* Get device details
|
|
572
506
|
*/
|
|
@@ -598,13 +532,12 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
598
532
|
humidity: result.humidity || 0,
|
|
599
533
|
mist_level: result.mistLevel || 0,
|
|
600
534
|
mist_virtual_level: result.virtualLevel || 0,
|
|
535
|
+
warm_level: result.warmLevel || 0,
|
|
601
536
|
water_lacks: result.waterLacks || false,
|
|
602
|
-
water_level: result.waterLevel || 0,
|
|
603
|
-
water_tank_lifted: result.waterTankLifted || false,
|
|
604
537
|
humidity_high: result.humidityHigh || false,
|
|
538
|
+
water_tank_lifted: result.waterTankLifted || false,
|
|
605
539
|
display: result.display || false,
|
|
606
540
|
automatic_stop: result.automaticStop || false,
|
|
607
|
-
oscillation_enabled: result.oscillationEnabled || false,
|
|
608
541
|
configuration: result.configuration || {},
|
|
609
542
|
connection_status: result.connectionStatus || null
|
|
610
543
|
};
|
|
@@ -612,34 +545,6 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
612
545
|
}
|
|
613
546
|
return success;
|
|
614
547
|
}
|
|
615
|
-
/**
|
|
616
|
-
* Display device info
|
|
617
|
-
*/
|
|
618
|
-
display() {
|
|
619
|
-
super.display();
|
|
620
|
-
const info = [
|
|
621
|
-
['Current State: ', this.currentState],
|
|
622
|
-
['Water Level: ', this.waterLevel, '%'],
|
|
623
|
-
['Water Tank: ', this.waterTankLifted ? 'Lifted' : 'Seated'],
|
|
624
|
-
['Oscillation: ', this.oscillationEnabled ? 'On' : 'Off']
|
|
625
|
-
];
|
|
626
|
-
for (const [key, value, unit = ''] of info) {
|
|
627
|
-
logger_1.logger.info(`${key.toString().padEnd(30, '.')} ${value}${unit}`);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* Return JSON details
|
|
632
|
-
*/
|
|
633
|
-
displayJSON() {
|
|
634
|
-
const baseInfo = JSON.parse(super.displayJSON());
|
|
635
|
-
return JSON.stringify({
|
|
636
|
-
...baseInfo,
|
|
637
|
-
'Current State': this.currentState,
|
|
638
|
-
'Water Level': this.waterLevel,
|
|
639
|
-
'Water Tank': this.waterTankLifted ? 'Lifted' : 'Seated',
|
|
640
|
-
'Oscillation': this.oscillationEnabled ? 'On' : 'Off'
|
|
641
|
-
}, null, 4);
|
|
642
|
-
}
|
|
643
548
|
/**
|
|
644
549
|
* Turn device on
|
|
645
550
|
*/
|
|
@@ -704,9 +609,9 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
704
609
|
*/
|
|
705
610
|
async setMistLevel(level) {
|
|
706
611
|
if (!this.mistLevels.includes(level)) {
|
|
707
|
-
|
|
708
|
-
logger_1.logger.
|
|
709
|
-
|
|
612
|
+
const error = `Invalid mist level: ${level}. Must be one of: ${this.mistLevels.join(', ')}`;
|
|
613
|
+
logger_1.logger.error(`${error} for device: ${this.deviceName}`);
|
|
614
|
+
throw new Error(error);
|
|
710
615
|
}
|
|
711
616
|
logger_1.logger.info(`Setting mist level to ${level} for device: ${this.deviceName}`);
|
|
712
617
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
@@ -715,9 +620,9 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
715
620
|
configModule: this.configModule,
|
|
716
621
|
payload: {
|
|
717
622
|
data: {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
623
|
+
id: 0,
|
|
624
|
+
level: level,
|
|
625
|
+
type: 'mist'
|
|
721
626
|
},
|
|
722
627
|
method: 'setVirtualLevel',
|
|
723
628
|
source: 'APP'
|
|
@@ -725,7 +630,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
725
630
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
726
631
|
const success = this.checkResponse([response, status], 'setMistLevel');
|
|
727
632
|
if (!success) {
|
|
728
|
-
logger_1.logger.
|
|
633
|
+
logger_1.logger.error(`Failed to set mist level to ${level} for device: ${this.deviceName}`);
|
|
729
634
|
}
|
|
730
635
|
return success;
|
|
731
636
|
}
|
|
@@ -740,11 +645,10 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
740
645
|
* Set device mode
|
|
741
646
|
*/
|
|
742
647
|
async setMode(mode) {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
logger_1.logger.
|
|
746
|
-
|
|
747
|
-
return false;
|
|
648
|
+
if (!this.modes.includes(mode)) {
|
|
649
|
+
const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
|
|
650
|
+
logger_1.logger.error(`${error} for device: ${this.deviceName}`);
|
|
651
|
+
throw new Error(error);
|
|
748
652
|
}
|
|
749
653
|
logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
|
|
750
654
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
@@ -753,7 +657,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
753
657
|
configModule: this.configModule,
|
|
754
658
|
payload: {
|
|
755
659
|
data: {
|
|
756
|
-
|
|
660
|
+
mode
|
|
757
661
|
},
|
|
758
662
|
method: 'setHumidifierMode',
|
|
759
663
|
source: 'APP'
|
|
@@ -761,7 +665,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
761
665
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
762
666
|
const success = this.checkResponse([response, status], 'setMode');
|
|
763
667
|
if (!success) {
|
|
764
|
-
logger_1.logger.
|
|
668
|
+
logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
765
669
|
}
|
|
766
670
|
return success;
|
|
767
671
|
}
|
|
@@ -1011,11 +915,10 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1011
915
|
* Set device mode
|
|
1012
916
|
*/
|
|
1013
917
|
async setMode(mode) {
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
logger_1.logger.
|
|
1017
|
-
|
|
1018
|
-
return false;
|
|
918
|
+
if (!this.modes.includes(mode)) {
|
|
919
|
+
const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
|
|
920
|
+
logger_1.logger.error(`${error} for device: ${this.deviceName}`);
|
|
921
|
+
throw new Error(error);
|
|
1019
922
|
}
|
|
1020
923
|
logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
|
|
1021
924
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
@@ -1024,15 +927,18 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1024
927
|
configModule: this.configModule,
|
|
1025
928
|
payload: {
|
|
1026
929
|
data: {
|
|
1027
|
-
|
|
930
|
+
mode
|
|
1028
931
|
},
|
|
1029
932
|
method: 'setHumidifierMode',
|
|
1030
933
|
source: 'APP'
|
|
1031
934
|
}
|
|
1032
935
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
1033
936
|
const success = this.checkResponse([response, status], 'setMode');
|
|
1034
|
-
if (
|
|
1035
|
-
|
|
937
|
+
if (success) {
|
|
938
|
+
this.details.mode = mode;
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
1036
942
|
}
|
|
1037
943
|
return success;
|
|
1038
944
|
}
|
|
@@ -1041,13 +947,14 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1041
947
|
*/
|
|
1042
948
|
async setWarmLevel(level) {
|
|
1043
949
|
if (!this.hasFeature('warm')) {
|
|
1044
|
-
|
|
1045
|
-
|
|
950
|
+
const error = 'Warm mist control not supported';
|
|
951
|
+
logger_1.logger.error(`${error} for device: ${this.deviceName}`);
|
|
952
|
+
throw new Error(error);
|
|
1046
953
|
}
|
|
1047
954
|
if (!this.warmLevels.includes(level)) {
|
|
1048
|
-
|
|
1049
|
-
logger_1.logger.
|
|
1050
|
-
|
|
955
|
+
const error = `Invalid warm level: ${level}. Must be one of: ${this.warmLevels.join(', ')}`;
|
|
956
|
+
logger_1.logger.error(`${error} for device: ${this.deviceName}`);
|
|
957
|
+
throw new Error(error);
|
|
1051
958
|
}
|
|
1052
959
|
logger_1.logger.debug(`Setting warm level to ${level} for device: ${this.deviceName}`);
|
|
1053
960
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
@@ -1186,7 +1093,6 @@ class VeSyncAirBaseV2 extends VeSyncAirBypass {
|
|
|
1186
1093
|
const body = {
|
|
1187
1094
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
1188
1095
|
cid: this.cid,
|
|
1189
|
-
deviceId: this.cid, // Add deviceId to match YAML spec
|
|
1190
1096
|
configModule: this.configModule,
|
|
1191
1097
|
payload: {
|
|
1192
1098
|
method,
|
|
@@ -1594,7 +1500,6 @@ class VeSyncTowerFan extends VeSyncAirBaseV2 {
|
|
|
1594
1500
|
const body = {
|
|
1595
1501
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
1596
1502
|
cid: this.cid,
|
|
1597
|
-
deviceId: this.cid, // Add deviceId to match YAML spec
|
|
1598
1503
|
configModule: this.configModule,
|
|
1599
1504
|
payload: {
|
|
1600
1505
|
method,
|
|
@@ -1714,7 +1619,7 @@ class VeSyncTowerFan extends VeSyncAirBaseV2 {
|
|
|
1714
1619
|
async changeFanSpeed(speed) {
|
|
1715
1620
|
// const speeds = this.config.levels ?? [];
|
|
1716
1621
|
// if (!speeds.includes(speed)) {
|
|
1717
|
-
// logger.
|
|
1622
|
+
// logger.debug(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')}`);
|
|
1718
1623
|
// return false;
|
|
1719
1624
|
// }
|
|
1720
1625
|
const [head, body] = this.buildApiDict('setLevel');
|
package/package.json
CHANGED
|
@@ -26,7 +26,7 @@ export abstract class VeSyncBaseDevice {
|
|
|
26
26
|
this.cid = details.cid || '';
|
|
27
27
|
this.deviceName = details.deviceName || '';
|
|
28
28
|
this.deviceStatus = details.deviceStatus || 'off';
|
|
29
|
-
this.deviceType =
|
|
29
|
+
this.deviceType = details.deviceType || '';
|
|
30
30
|
this.deviceRegion = details.deviceRegion || '';
|
|
31
31
|
this.uuid = details.uuid || '';
|
|
32
32
|
this.configModule = details.configModule || '';
|
|
@@ -35,38 +35,6 @@ export abstract class VeSyncBaseDevice {
|
|
|
35
35
|
this.connectionStatus = details.connectionStatus || 'offline';
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/**
|
|
39
|
-
* Normalize device type to match configuration keys
|
|
40
|
-
* This handles variations in device type strings from the API
|
|
41
|
-
*/
|
|
42
|
-
protected normalizeDeviceType(deviceType: string): string {
|
|
43
|
-
// Remove any region suffixes (e.g. -USA, -EU)
|
|
44
|
-
const baseType = deviceType.split('-')[0];
|
|
45
|
-
|
|
46
|
-
// Handle known prefix mappings
|
|
47
|
-
const prefixMap: Record<string, string> = {
|
|
48
|
-
'Core': 'Core',
|
|
49
|
-
'LAP': 'LAP',
|
|
50
|
-
'LTF': 'LTF',
|
|
51
|
-
'Classic': 'Classic',
|
|
52
|
-
'Dual': 'Dual',
|
|
53
|
-
'LUH': 'LUH',
|
|
54
|
-
'LEH': 'LEH',
|
|
55
|
-
'LV-PUR': 'LV-PUR',
|
|
56
|
-
'LV-RH': 'LV-RH'
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
// Check if the device type starts with any known prefix
|
|
60
|
-
for (const [prefix, normalized] of Object.entries(prefixMap)) {
|
|
61
|
-
if (deviceType.startsWith(prefix)) {
|
|
62
|
-
return deviceType; // Keep the full device type for exact matches
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// If no prefix match, return the base type
|
|
67
|
-
return baseType;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
38
|
/**
|
|
71
39
|
* Return formatted device info to stdout
|
|
72
40
|
*/
|
package/src/lib/vesyncFan.ts
CHANGED
|
@@ -200,124 +200,101 @@ export const fanConfig: FanConfig = {
|
|
|
200
200
|
// Classic Series
|
|
201
201
|
'Classic300S': {
|
|
202
202
|
module: 'VeSyncHumidifier',
|
|
203
|
-
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
204
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
203
|
+
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
205
204
|
},
|
|
206
205
|
'Classic200S': {
|
|
207
206
|
module: 'VeSyncHumidifier',
|
|
208
|
-
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
209
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
207
|
+
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
210
208
|
},
|
|
211
209
|
|
|
212
210
|
// Dual Series
|
|
213
211
|
'Dual200S': {
|
|
214
212
|
module: 'VeSyncHumidifier',
|
|
215
|
-
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
216
|
-
levels: [1, 2]
|
|
213
|
+
features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
|
|
217
214
|
},
|
|
218
215
|
|
|
219
216
|
// LUH Series
|
|
220
217
|
'LUH-A601S-WUSB': {
|
|
221
218
|
module: 'VeSyncWarmHumidifier',
|
|
222
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
223
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
219
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
224
220
|
},
|
|
225
221
|
'LUH-A601S-AUSW': {
|
|
226
222
|
module: 'VeSyncWarmHumidifier',
|
|
227
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
228
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
223
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
229
224
|
},
|
|
230
225
|
'LUH-D301S-WUSR': {
|
|
231
226
|
module: 'VeSyncWarmHumidifier',
|
|
232
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
233
|
-
levels: [1, 2]
|
|
227
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
234
228
|
},
|
|
235
229
|
'LUH-D301S-WJP': {
|
|
236
230
|
module: 'VeSyncWarmHumidifier',
|
|
237
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
238
|
-
levels: [1, 2]
|
|
231
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
239
232
|
},
|
|
240
233
|
'LUH-D301S-WEU': {
|
|
241
234
|
module: 'VeSyncWarmHumidifier',
|
|
242
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
243
|
-
levels: [1, 2]
|
|
235
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
244
236
|
},
|
|
245
237
|
'LUH-A602S-WUSR': {
|
|
246
238
|
module: 'VeSyncWarmHumidifier',
|
|
247
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
248
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
239
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
249
240
|
},
|
|
250
241
|
'LUH-A602S-WUS': {
|
|
251
242
|
module: 'VeSyncWarmHumidifier',
|
|
252
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
253
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
243
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
254
244
|
},
|
|
255
245
|
'LUH-A602S-WEUR': {
|
|
256
246
|
module: 'VeSyncWarmHumidifier',
|
|
257
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
258
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
247
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
259
248
|
},
|
|
260
249
|
'LUH-A602S-WEU': {
|
|
261
250
|
module: 'VeSyncWarmHumidifier',
|
|
262
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
263
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
251
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
264
252
|
},
|
|
265
253
|
'LUH-A602S-WJP': {
|
|
266
254
|
module: 'VeSyncWarmHumidifier',
|
|
267
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
268
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
255
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
269
256
|
},
|
|
270
257
|
'LUH-A602S-WUSC': {
|
|
271
258
|
module: 'VeSyncWarmHumidifier',
|
|
272
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
273
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
259
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
274
260
|
},
|
|
275
261
|
'LUH-O451S-WEU': {
|
|
276
262
|
module: 'VeSyncWarmHumidifier',
|
|
277
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
278
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
263
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
279
264
|
},
|
|
280
265
|
'LUH-O451S-WUS': {
|
|
281
266
|
module: 'VeSyncWarmHumidifier',
|
|
282
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
283
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
267
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
284
268
|
},
|
|
285
269
|
'LUH-O451S-WUSR': {
|
|
286
270
|
module: 'VeSyncWarmHumidifier',
|
|
287
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
288
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
271
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
289
272
|
},
|
|
290
273
|
'LUH-O601S-WUS': {
|
|
291
274
|
module: 'VeSyncWarmHumidifier',
|
|
292
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
293
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
275
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
294
276
|
},
|
|
295
277
|
'LUH-O601S-KUS': {
|
|
296
278
|
module: 'VeSyncWarmHumidifier',
|
|
297
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
298
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
279
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
299
280
|
},
|
|
300
281
|
'LUH-M101S-WUS': {
|
|
301
282
|
module: 'VeSyncWarmHumidifier',
|
|
302
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
303
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
283
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
304
284
|
},
|
|
305
285
|
'LUH-M101S-WEUR': {
|
|
306
286
|
module: 'VeSyncWarmHumidifier',
|
|
307
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
308
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
287
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
|
|
309
288
|
},
|
|
310
289
|
|
|
311
290
|
// LEH Series
|
|
312
291
|
'LEH-S601S-WUS': {
|
|
313
292
|
module: 'VeSyncWarmHumidifier',
|
|
314
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
|
|
315
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
293
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
|
|
316
294
|
},
|
|
317
295
|
'LEH-S601S-WUSR': {
|
|
318
296
|
module: 'VeSyncWarmHumidifier',
|
|
319
|
-
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
|
|
320
|
-
levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
297
|
+
features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
|
|
321
298
|
},
|
|
322
299
|
|
|
323
300
|
// LV Series
|
|
@@ -362,26 +339,11 @@ export abstract class VeSyncFan extends VeSyncBaseDevice {
|
|
|
362
339
|
constructor(details: Record<string, any>, manager: VeSync) {
|
|
363
340
|
super(details, manager);
|
|
364
341
|
this.details = details;
|
|
365
|
-
|
|
366
|
-
// Try exact match first
|
|
367
|
-
let config = fanConfig[this.deviceType];
|
|
368
|
-
|
|
369
|
-
// If no exact match, try base type
|
|
370
|
-
if (!config) {
|
|
371
|
-
const baseType = this.deviceType.split('-')[0];
|
|
372
|
-
config = fanConfig[baseType];
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// If still no match, use default
|
|
376
|
-
this.config = config || {
|
|
342
|
+
this.config = fanConfig[this.deviceType] || {
|
|
377
343
|
module: 'VeSyncAirBypass',
|
|
378
344
|
features: [],
|
|
379
345
|
levels: []
|
|
380
346
|
};
|
|
381
|
-
|
|
382
|
-
if (!config) {
|
|
383
|
-
logger.debug(`No configuration found for device type: ${this.deviceType}`);
|
|
384
|
-
}
|
|
385
347
|
}
|
|
386
348
|
|
|
387
349
|
/**
|
package/src/lib/vesyncFanImpl.ts
CHANGED
|
@@ -28,7 +28,6 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
28
28
|
const body = {
|
|
29
29
|
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
30
30
|
cid: this.cid,
|
|
31
|
-
deviceId: this.cid, // Add deviceId to match YAML spec
|
|
32
31
|
configModule: this.configModule,
|
|
33
32
|
payload: {
|
|
34
33
|
method,
|
|
@@ -258,12 +257,9 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
258
257
|
* Change fan speed
|
|
259
258
|
*/
|
|
260
259
|
async changeFanSpeed(speed: number): Promise<boolean> {
|
|
261
|
-
logger.debug(`Attempting to change fan speed to ${speed} for device: ${this.deviceName}`);
|
|
262
|
-
logger.debug(`Available speeds: ${this.config.levels?.join(', ')}`);
|
|
263
|
-
|
|
264
260
|
// const speeds = this.config.levels ?? [];
|
|
265
261
|
// if (!speeds.includes(speed)) {
|
|
266
|
-
// logger.
|
|
262
|
+
// logger.error(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')} for device: ${this.deviceName}`);
|
|
267
263
|
// return false;
|
|
268
264
|
// }
|
|
269
265
|
|
|
@@ -300,11 +296,10 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
300
296
|
* Set device mode
|
|
301
297
|
*/
|
|
302
298
|
async setMode(mode: string): Promise<boolean> {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
logger.
|
|
306
|
-
|
|
307
|
-
return false;
|
|
299
|
+
if (!this.modes.includes(mode as any)) {
|
|
300
|
+
const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
|
|
301
|
+
logger.error(`${error} for device: ${this.deviceName}`);
|
|
302
|
+
throw new Error(error);
|
|
308
303
|
}
|
|
309
304
|
|
|
310
305
|
logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
|
|
@@ -317,9 +312,9 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
317
312
|
configModule: this.configModule,
|
|
318
313
|
payload: {
|
|
319
314
|
data: {
|
|
320
|
-
|
|
315
|
+
mode
|
|
321
316
|
},
|
|
322
|
-
method: '
|
|
317
|
+
method: 'setPurifierMode',
|
|
323
318
|
source: 'APP'
|
|
324
319
|
}
|
|
325
320
|
},
|
|
@@ -328,7 +323,7 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
328
323
|
|
|
329
324
|
const success = this.checkResponse([response, status], 'setMode');
|
|
330
325
|
if (!success) {
|
|
331
|
-
logger.
|
|
326
|
+
logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
332
327
|
}
|
|
333
328
|
return success;
|
|
334
329
|
}
|
|
@@ -605,7 +600,6 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
605
600
|
protected readonly mistLevels: number[];
|
|
606
601
|
protected readonly displayModes = ['on', 'off'] as const;
|
|
607
602
|
protected readonly humidityRange = { min: 30, max: 80 };
|
|
608
|
-
protected readonly states = ['inactive', 'idle', 'humidifying'] as const;
|
|
609
603
|
|
|
610
604
|
constructor(details: Record<string, any>, manager: VeSync) {
|
|
611
605
|
super(details, manager);
|
|
@@ -624,75 +618,6 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
624
618
|
logger.debug(`Initialized VeSyncHumidifier device: ${this.deviceName}`);
|
|
625
619
|
}
|
|
626
620
|
|
|
627
|
-
/**
|
|
628
|
-
* Get current operational state
|
|
629
|
-
*/
|
|
630
|
-
get currentState(): string {
|
|
631
|
-
if (this.deviceStatus === 'off') {
|
|
632
|
-
return 'inactive';
|
|
633
|
-
}
|
|
634
|
-
if (this.details.water_lacks) {
|
|
635
|
-
return 'idle';
|
|
636
|
-
}
|
|
637
|
-
return 'humidifying';
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
/**
|
|
641
|
-
* Get water level percentage
|
|
642
|
-
*/
|
|
643
|
-
get waterLevel(): number {
|
|
644
|
-
return this.details.water_level ?? 0;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
/**
|
|
648
|
-
* Get water tank status
|
|
649
|
-
*/
|
|
650
|
-
get waterTankLifted(): boolean {
|
|
651
|
-
return this.details.water_tank_lifted ?? false;
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
* Get oscillation state
|
|
656
|
-
*/
|
|
657
|
-
get oscillationEnabled(): boolean {
|
|
658
|
-
return this.details.oscillation_enabled ?? false;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
/**
|
|
662
|
-
* Set oscillation state
|
|
663
|
-
*/
|
|
664
|
-
async setOscillation(enabled: boolean): Promise<boolean> {
|
|
665
|
-
if (!this.hasFeature('oscillation')) {
|
|
666
|
-
logger.debug('Oscillation not supported');
|
|
667
|
-
return false;
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
logger.debug(`Setting oscillation to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
671
|
-
const [response, status] = await this.callApi(
|
|
672
|
-
'/cloud/v2/deviceManaged/bypassV2',
|
|
673
|
-
'post',
|
|
674
|
-
{
|
|
675
|
-
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
676
|
-
cid: this.cid,
|
|
677
|
-
configModule: this.configModule,
|
|
678
|
-
payload: {
|
|
679
|
-
data: {
|
|
680
|
-
oscillationEnabled: enabled
|
|
681
|
-
},
|
|
682
|
-
method: 'setSwing',
|
|
683
|
-
source: 'APP'
|
|
684
|
-
}
|
|
685
|
-
},
|
|
686
|
-
Helpers.reqHeaderBypass()
|
|
687
|
-
);
|
|
688
|
-
|
|
689
|
-
const success = this.checkResponse([response, status], 'setOscillation');
|
|
690
|
-
if (!success) {
|
|
691
|
-
logger.debug('Error setting oscillation');
|
|
692
|
-
}
|
|
693
|
-
return success;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
621
|
/**
|
|
697
622
|
* Get device details
|
|
698
623
|
*/
|
|
@@ -730,13 +655,12 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
730
655
|
humidity: result.humidity || 0,
|
|
731
656
|
mist_level: result.mistLevel || 0,
|
|
732
657
|
mist_virtual_level: result.virtualLevel || 0,
|
|
658
|
+
warm_level: result.warmLevel || 0,
|
|
733
659
|
water_lacks: result.waterLacks || false,
|
|
734
|
-
water_level: result.waterLevel || 0,
|
|
735
|
-
water_tank_lifted: result.waterTankLifted || false,
|
|
736
660
|
humidity_high: result.humidityHigh || false,
|
|
661
|
+
water_tank_lifted: result.waterTankLifted || false,
|
|
737
662
|
display: result.display || false,
|
|
738
663
|
automatic_stop: result.automaticStop || false,
|
|
739
|
-
oscillation_enabled: result.oscillationEnabled || false,
|
|
740
664
|
configuration: result.configuration || {},
|
|
741
665
|
connection_status: result.connectionStatus || null
|
|
742
666
|
};
|
|
@@ -745,37 +669,6 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
745
669
|
return success;
|
|
746
670
|
}
|
|
747
671
|
|
|
748
|
-
/**
|
|
749
|
-
* Display device info
|
|
750
|
-
*/
|
|
751
|
-
override display(): void {
|
|
752
|
-
super.display();
|
|
753
|
-
const info = [
|
|
754
|
-
['Current State: ', this.currentState],
|
|
755
|
-
['Water Level: ', this.waterLevel, '%'],
|
|
756
|
-
['Water Tank: ', this.waterTankLifted ? 'Lifted' : 'Seated'],
|
|
757
|
-
['Oscillation: ', this.oscillationEnabled ? 'On' : 'Off']
|
|
758
|
-
];
|
|
759
|
-
|
|
760
|
-
for (const [key, value, unit = ''] of info) {
|
|
761
|
-
logger.info(`${key.toString().padEnd(30, '.')} ${value}${unit}`);
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
/**
|
|
766
|
-
* Return JSON details
|
|
767
|
-
*/
|
|
768
|
-
override displayJSON(): string {
|
|
769
|
-
const baseInfo = JSON.parse(super.displayJSON());
|
|
770
|
-
return JSON.stringify({
|
|
771
|
-
...baseInfo,
|
|
772
|
-
'Current State': this.currentState,
|
|
773
|
-
'Water Level': this.waterLevel,
|
|
774
|
-
'Water Tank': this.waterTankLifted ? 'Lifted' : 'Seated',
|
|
775
|
-
'Oscillation': this.oscillationEnabled ? 'On' : 'Off'
|
|
776
|
-
}, null, 4);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
672
|
/**
|
|
780
673
|
* Turn device on
|
|
781
674
|
*/
|
|
@@ -847,9 +740,9 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
847
740
|
*/
|
|
848
741
|
async setMistLevel(level: number): Promise<boolean> {
|
|
849
742
|
if (!this.mistLevels.includes(level)) {
|
|
850
|
-
|
|
851
|
-
logger.
|
|
852
|
-
|
|
743
|
+
const error = `Invalid mist level: ${level}. Must be one of: ${this.mistLevels.join(', ')}`;
|
|
744
|
+
logger.error(`${error} for device: ${this.deviceName}`);
|
|
745
|
+
throw new Error(error);
|
|
853
746
|
}
|
|
854
747
|
|
|
855
748
|
logger.info(`Setting mist level to ${level} for device: ${this.deviceName}`);
|
|
@@ -862,9 +755,9 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
862
755
|
configModule: this.configModule,
|
|
863
756
|
payload: {
|
|
864
757
|
data: {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
758
|
+
id: 0,
|
|
759
|
+
level: level,
|
|
760
|
+
type: 'mist'
|
|
868
761
|
},
|
|
869
762
|
method: 'setVirtualLevel',
|
|
870
763
|
source: 'APP'
|
|
@@ -875,7 +768,7 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
875
768
|
|
|
876
769
|
const success = this.checkResponse([response, status], 'setMistLevel');
|
|
877
770
|
if (!success) {
|
|
878
|
-
logger.
|
|
771
|
+
logger.error(`Failed to set mist level to ${level} for device: ${this.deviceName}`);
|
|
879
772
|
}
|
|
880
773
|
return success;
|
|
881
774
|
}
|
|
@@ -892,11 +785,10 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
892
785
|
* Set device mode
|
|
893
786
|
*/
|
|
894
787
|
async setMode(mode: string): Promise<boolean> {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
logger.
|
|
898
|
-
|
|
899
|
-
return false;
|
|
788
|
+
if (!this.modes.includes(mode as any)) {
|
|
789
|
+
const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
|
|
790
|
+
logger.error(`${error} for device: ${this.deviceName}`);
|
|
791
|
+
throw new Error(error);
|
|
900
792
|
}
|
|
901
793
|
|
|
902
794
|
logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
|
|
@@ -909,7 +801,7 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
909
801
|
configModule: this.configModule,
|
|
910
802
|
payload: {
|
|
911
803
|
data: {
|
|
912
|
-
|
|
804
|
+
mode
|
|
913
805
|
},
|
|
914
806
|
method: 'setHumidifierMode',
|
|
915
807
|
source: 'APP'
|
|
@@ -920,7 +812,7 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
920
812
|
|
|
921
813
|
const success = this.checkResponse([response, status], 'setMode');
|
|
922
814
|
if (!success) {
|
|
923
|
-
logger.
|
|
815
|
+
logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
924
816
|
}
|
|
925
817
|
return success;
|
|
926
818
|
}
|
|
@@ -1225,11 +1117,10 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1225
1117
|
* Set device mode
|
|
1226
1118
|
*/
|
|
1227
1119
|
async setMode(mode: string): Promise<boolean> {
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
logger.
|
|
1231
|
-
|
|
1232
|
-
return false;
|
|
1120
|
+
if (!this.modes.includes(mode as any)) {
|
|
1121
|
+
const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
|
|
1122
|
+
logger.error(`${error} for device: ${this.deviceName}`);
|
|
1123
|
+
throw new Error(error);
|
|
1233
1124
|
}
|
|
1234
1125
|
|
|
1235
1126
|
logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
|
|
@@ -1242,7 +1133,7 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1242
1133
|
configModule: this.configModule,
|
|
1243
1134
|
payload: {
|
|
1244
1135
|
data: {
|
|
1245
|
-
|
|
1136
|
+
mode
|
|
1246
1137
|
},
|
|
1247
1138
|
method: 'setHumidifierMode',
|
|
1248
1139
|
source: 'APP'
|
|
@@ -1252,8 +1143,10 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1252
1143
|
);
|
|
1253
1144
|
|
|
1254
1145
|
const success = this.checkResponse([response, status], 'setMode');
|
|
1255
|
-
if (
|
|
1256
|
-
|
|
1146
|
+
if (success) {
|
|
1147
|
+
this.details.mode = mode;
|
|
1148
|
+
} else {
|
|
1149
|
+
logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
1257
1150
|
}
|
|
1258
1151
|
return success;
|
|
1259
1152
|
}
|
|
@@ -1263,14 +1156,15 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1263
1156
|
*/
|
|
1264
1157
|
async setWarmLevel(level: number): Promise<boolean> {
|
|
1265
1158
|
if (!this.hasFeature('warm')) {
|
|
1266
|
-
|
|
1267
|
-
|
|
1159
|
+
const error = 'Warm mist control not supported';
|
|
1160
|
+
logger.error(`${error} for device: ${this.deviceName}`);
|
|
1161
|
+
throw new Error(error);
|
|
1268
1162
|
}
|
|
1269
1163
|
|
|
1270
1164
|
if (!this.warmLevels.includes(level)) {
|
|
1271
|
-
|
|
1272
|
-
logger.
|
|
1273
|
-
|
|
1165
|
+
const error = `Invalid warm level: ${level}. Must be one of: ${this.warmLevels.join(', ')}`;
|
|
1166
|
+
logger.error(`${error} for device: ${this.deviceName}`);
|
|
1167
|
+
throw new Error(error);
|
|
1274
1168
|
}
|
|
1275
1169
|
|
|
1276
1170
|
logger.debug(`Setting warm level to ${level} for device: ${this.deviceName}`);
|
|
@@ -1436,7 +1330,6 @@ export class VeSyncAirBaseV2 extends VeSyncAirBypass {
|
|
|
1436
1330
|
const body = {
|
|
1437
1331
|
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
1438
1332
|
cid: this.cid,
|
|
1439
|
-
deviceId: this.cid, // Add deviceId to match YAML spec
|
|
1440
1333
|
configModule: this.configModule,
|
|
1441
1334
|
payload: {
|
|
1442
1335
|
method,
|
|
@@ -1957,7 +1850,6 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
|
|
|
1957
1850
|
const body = {
|
|
1958
1851
|
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
1959
1852
|
cid: this.cid,
|
|
1960
|
-
deviceId: this.cid, // Add deviceId to match YAML spec
|
|
1961
1853
|
configModule: this.configModule,
|
|
1962
1854
|
payload: {
|
|
1963
1855
|
method,
|
|
@@ -2108,7 +2000,7 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
|
|
|
2108
2000
|
async changeFanSpeed(speed: number): Promise<boolean> {
|
|
2109
2001
|
// const speeds = this.config.levels ?? [];
|
|
2110
2002
|
// if (!speeds.includes(speed)) {
|
|
2111
|
-
// logger.
|
|
2003
|
+
// logger.debug(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')}`);
|
|
2112
2004
|
// return false;
|
|
2113
2005
|
// }
|
|
2114
2006
|
|