tsvesync 1.0.52 → 1.0.54

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.
@@ -189,98 +189,121 @@ exports.fanConfig = {
189
189
  // Classic Series
190
190
  'Classic300S': {
191
191
  module: 'VeSyncHumidifier',
192
- features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
192
+ features: ['display', 'humidity', 'mist', 'timer', 'auto_mode'],
193
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
193
194
  },
194
195
  'Classic200S': {
195
196
  module: 'VeSyncHumidifier',
196
- features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
197
+ features: ['display', 'humidity', 'mist', 'timer', 'auto_mode'],
198
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
197
199
  },
198
200
  // Dual Series
199
201
  'Dual200S': {
200
202
  module: 'VeSyncHumidifier',
201
- features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
203
+ features: ['display', 'humidity', 'mist', 'timer', 'auto_mode'],
204
+ levels: [1, 2]
202
205
  },
203
206
  // LUH Series
204
207
  'LUH-A601S-WUSB': {
205
208
  module: 'VeSyncWarmHumidifier',
206
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
209
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
210
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
207
211
  },
208
212
  'LUH-A601S-AUSW': {
209
213
  module: 'VeSyncWarmHumidifier',
210
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
214
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
215
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
211
216
  },
212
217
  'LUH-D301S-WUSR': {
213
218
  module: 'VeSyncWarmHumidifier',
214
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
219
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
220
+ levels: [1, 2]
215
221
  },
216
222
  'LUH-D301S-WJP': {
217
223
  module: 'VeSyncWarmHumidifier',
218
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
224
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
225
+ levels: [1, 2]
219
226
  },
220
227
  'LUH-D301S-WEU': {
221
228
  module: 'VeSyncWarmHumidifier',
222
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
229
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
230
+ levels: [1, 2]
223
231
  },
224
232
  'LUH-A602S-WUSR': {
225
233
  module: 'VeSyncWarmHumidifier',
226
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
234
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
235
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
227
236
  },
228
237
  'LUH-A602S-WUS': {
229
238
  module: 'VeSyncWarmHumidifier',
230
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
239
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
240
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
231
241
  },
232
242
  'LUH-A602S-WEUR': {
233
243
  module: 'VeSyncWarmHumidifier',
234
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
244
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
245
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
235
246
  },
236
247
  'LUH-A602S-WEU': {
237
248
  module: 'VeSyncWarmHumidifier',
238
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
249
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
250
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
239
251
  },
240
252
  'LUH-A602S-WJP': {
241
253
  module: 'VeSyncWarmHumidifier',
242
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
254
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
255
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
243
256
  },
244
257
  'LUH-A602S-WUSC': {
245
258
  module: 'VeSyncWarmHumidifier',
246
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
259
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
260
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
247
261
  },
248
262
  'LUH-O451S-WEU': {
249
263
  module: 'VeSyncWarmHumidifier',
250
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
264
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
265
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
251
266
  },
252
267
  'LUH-O451S-WUS': {
253
268
  module: 'VeSyncWarmHumidifier',
254
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
269
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
270
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
255
271
  },
256
272
  'LUH-O451S-WUSR': {
257
273
  module: 'VeSyncWarmHumidifier',
258
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
274
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
275
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
259
276
  },
260
277
  'LUH-O601S-WUS': {
261
278
  module: 'VeSyncWarmHumidifier',
262
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
279
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
280
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
263
281
  },
264
282
  'LUH-O601S-KUS': {
265
283
  module: 'VeSyncWarmHumidifier',
266
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
284
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
285
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
267
286
  },
268
287
  'LUH-M101S-WUS': {
269
288
  module: 'VeSyncWarmHumidifier',
270
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
289
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
290
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
271
291
  },
272
292
  'LUH-M101S-WEUR': {
273
293
  module: 'VeSyncWarmHumidifier',
274
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
294
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
295
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
275
296
  },
276
297
  // LEH Series
277
298
  'LEH-S601S-WUS': {
278
299
  module: 'VeSyncWarmHumidifier',
279
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
300
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying'],
301
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
280
302
  },
281
303
  'LEH-S601S-WUSR': {
282
304
  module: 'VeSyncWarmHumidifier',
283
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
305
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying'],
306
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
284
307
  },
285
308
  // LV Series
286
309
  'LV-PUR131S': {
@@ -91,11 +91,40 @@ export declare class VeSyncHumidifier extends VeSyncFan {
91
91
  min: number;
92
92
  max: number;
93
93
  };
94
+ protected readonly states: readonly ["inactive", "idle", "humidifying"];
94
95
  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>;
95
116
  /**
96
117
  * Get device details
97
118
  */
98
119
  getDetails(): Promise<Boolean>;
120
+ /**
121
+ * Display device info
122
+ */
123
+ display(): void;
124
+ /**
125
+ * Return JSON details
126
+ */
127
+ displayJSON(): string;
99
128
  /**
100
129
  * Turn device on
101
130
  */
@@ -16,7 +16,10 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
16
16
  this.modes = ['auto', 'manual', 'sleep'];
17
17
  this.displayModes = ['on', 'off'];
18
18
  this.childLockModes = ['on', 'off'];
19
- logger_1.logger.debug(`Initialized VeSyncAirBypass device: ${this.deviceName}`);
19
+ logger_1.logger.info(`Device Type: ${this.deviceType}`);
20
+ logger_1.logger.info(`Device Details: ${JSON.stringify(details)}`);
21
+ logger_1.logger.info(`Config: ${JSON.stringify(this.config)}`);
22
+ logger_1.logger.info(`Initialized VeSyncAirBypass device: ${this.deviceName}`);
20
23
  }
21
24
  /**
22
25
  * Build API dictionary
@@ -26,6 +29,7 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
26
29
  const body = {
27
30
  ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
28
31
  cid: this.cid,
32
+ deviceId: this.cid, // Add deviceId to match YAML spec
29
33
  configModule: this.configModule,
30
34
  payload: {
31
35
  method,
@@ -241,10 +245,11 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
241
245
  * Set device mode
242
246
  */
243
247
  async setMode(mode) {
244
- if (!this.modes.includes(mode)) {
245
- const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
246
- logger_1.logger.error(`${error} for device: ${this.deviceName}`);
247
- throw new Error(error);
248
+ const modeStr = mode.toLowerCase();
249
+ if (!this.modes.includes(modeStr)) {
250
+ logger_1.logger.debug(`Invalid humidity mode used - ${mode}`);
251
+ logger_1.logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
252
+ return false;
248
253
  }
249
254
  logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
250
255
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -253,15 +258,15 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
253
258
  configModule: this.configModule,
254
259
  payload: {
255
260
  data: {
256
- mode
261
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
257
262
  },
258
- method: 'setPurifierMode',
263
+ method: 'setHumidifierMode',
259
264
  source: 'APP'
260
265
  }
261
266
  }, helpers_1.Helpers.reqHeaderBypass());
262
267
  const success = this.checkResponse([response, status], 'setMode');
263
268
  if (!success) {
264
- logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
269
+ logger_1.logger.debug('Error setting humidity mode');
265
270
  }
266
271
  return success;
267
272
  }
@@ -488,6 +493,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
488
493
  this.modes = ['auto', 'manual', 'sleep'];
489
494
  this.displayModes = ['on', 'off'];
490
495
  this.humidityRange = { min: 30, max: 80 };
496
+ this.states = ['inactive', 'idle', 'humidifying'];
491
497
  // Set mist levels based on model
492
498
  switch (this.deviceType) {
493
499
  case 'Dual200S':
@@ -502,6 +508,66 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
502
508
  }
503
509
  logger_1.logger.debug(`Initialized VeSyncHumidifier device: ${this.deviceName}`);
504
510
  }
511
+ /**
512
+ * Get current operational state
513
+ */
514
+ get currentState() {
515
+ if (this.deviceStatus === 'off') {
516
+ return 'inactive';
517
+ }
518
+ if (this.details.water_lacks) {
519
+ return 'idle';
520
+ }
521
+ return 'humidifying';
522
+ }
523
+ /**
524
+ * Get water level percentage
525
+ */
526
+ get waterLevel() {
527
+ var _a;
528
+ return (_a = this.details.water_level) !== null && _a !== void 0 ? _a : 0;
529
+ }
530
+ /**
531
+ * Get water tank status
532
+ */
533
+ get waterTankLifted() {
534
+ var _a;
535
+ return (_a = this.details.water_tank_lifted) !== null && _a !== void 0 ? _a : false;
536
+ }
537
+ /**
538
+ * Get oscillation state
539
+ */
540
+ get oscillationEnabled() {
541
+ var _a;
542
+ return (_a = this.details.oscillation_enabled) !== null && _a !== void 0 ? _a : false;
543
+ }
544
+ /**
545
+ * Set oscillation state
546
+ */
547
+ async setOscillation(enabled) {
548
+ if (!this.hasFeature('oscillation')) {
549
+ logger_1.logger.debug('Oscillation not supported');
550
+ return false;
551
+ }
552
+ logger_1.logger.debug(`Setting oscillation to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
553
+ const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
554
+ ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
555
+ cid: this.cid,
556
+ configModule: this.configModule,
557
+ payload: {
558
+ data: {
559
+ oscillationEnabled: enabled
560
+ },
561
+ method: 'setSwing',
562
+ source: 'APP'
563
+ }
564
+ }, helpers_1.Helpers.reqHeaderBypass());
565
+ const success = this.checkResponse([response, status], 'setOscillation');
566
+ if (!success) {
567
+ logger_1.logger.debug('Error setting oscillation');
568
+ }
569
+ return success;
570
+ }
505
571
  /**
506
572
  * Get device details
507
573
  */
@@ -533,12 +599,13 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
533
599
  humidity: result.humidity || 0,
534
600
  mist_level: result.mistLevel || 0,
535
601
  mist_virtual_level: result.virtualLevel || 0,
536
- warm_level: result.warmLevel || 0,
537
602
  water_lacks: result.waterLacks || false,
538
- humidity_high: result.humidityHigh || false,
603
+ water_level: result.waterLevel || 0,
539
604
  water_tank_lifted: result.waterTankLifted || false,
605
+ humidity_high: result.humidityHigh || false,
540
606
  display: result.display || false,
541
607
  automatic_stop: result.automaticStop || false,
608
+ oscillation_enabled: result.oscillationEnabled || false,
542
609
  configuration: result.configuration || {},
543
610
  connection_status: result.connectionStatus || null
544
611
  };
@@ -546,6 +613,34 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
546
613
  }
547
614
  return success;
548
615
  }
616
+ /**
617
+ * Display device info
618
+ */
619
+ display() {
620
+ super.display();
621
+ const info = [
622
+ ['Current State: ', this.currentState],
623
+ ['Water Level: ', this.waterLevel, '%'],
624
+ ['Water Tank: ', this.waterTankLifted ? 'Lifted' : 'Seated'],
625
+ ['Oscillation: ', this.oscillationEnabled ? 'On' : 'Off']
626
+ ];
627
+ for (const [key, value, unit = ''] of info) {
628
+ logger_1.logger.info(`${key.toString().padEnd(30, '.')} ${value}${unit}`);
629
+ }
630
+ }
631
+ /**
632
+ * Return JSON details
633
+ */
634
+ displayJSON() {
635
+ const baseInfo = JSON.parse(super.displayJSON());
636
+ return JSON.stringify({
637
+ ...baseInfo,
638
+ 'Current State': this.currentState,
639
+ 'Water Level': this.waterLevel,
640
+ 'Water Tank': this.waterTankLifted ? 'Lifted' : 'Seated',
641
+ 'Oscillation': this.oscillationEnabled ? 'On' : 'Off'
642
+ }, null, 4);
643
+ }
549
644
  /**
550
645
  * Turn device on
551
646
  */
@@ -610,9 +705,9 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
610
705
  */
611
706
  async setMistLevel(level) {
612
707
  if (!this.mistLevels.includes(level)) {
613
- const error = `Invalid mist level: ${level}. Must be one of: ${this.mistLevels.join(', ')}`;
614
- logger_1.logger.error(`${error} for device: ${this.deviceName}`);
615
- throw new Error(error);
708
+ logger_1.logger.debug(`Invalid mist level: ${level} for device: ${this.deviceName}`);
709
+ logger_1.logger.debug(`Valid levels for ${this.deviceType}: ${this.mistLevels.join(', ')}`);
710
+ return false;
616
711
  }
617
712
  logger_1.logger.info(`Setting mist level to ${level} for device: ${this.deviceName}`);
618
713
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -621,9 +716,9 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
621
716
  configModule: this.configModule,
622
717
  payload: {
623
718
  data: {
624
- id: 0,
625
- level: level,
626
- type: 'mist'
719
+ levelIdx: 0,
720
+ virtualLevel: level,
721
+ levelType: 'mist'
627
722
  },
628
723
  method: 'setVirtualLevel',
629
724
  source: 'APP'
@@ -631,7 +726,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
631
726
  }, helpers_1.Helpers.reqHeaderBypass());
632
727
  const success = this.checkResponse([response, status], 'setMistLevel');
633
728
  if (!success) {
634
- logger_1.logger.error(`Failed to set mist level to ${level} for device: ${this.deviceName}`);
729
+ logger_1.logger.debug('Error setting mist level');
635
730
  }
636
731
  return success;
637
732
  }
@@ -646,10 +741,11 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
646
741
  * Set device mode
647
742
  */
648
743
  async setMode(mode) {
649
- if (!this.modes.includes(mode)) {
650
- const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
651
- logger_1.logger.error(`${error} for device: ${this.deviceName}`);
652
- throw new Error(error);
744
+ const modeStr = mode.toLowerCase();
745
+ if (!this.modes.includes(modeStr)) {
746
+ logger_1.logger.debug(`Invalid humidity mode used - ${mode}`);
747
+ logger_1.logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
748
+ return false;
653
749
  }
654
750
  logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
655
751
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -658,7 +754,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
658
754
  configModule: this.configModule,
659
755
  payload: {
660
756
  data: {
661
- mode
757
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
662
758
  },
663
759
  method: 'setHumidifierMode',
664
760
  source: 'APP'
@@ -666,7 +762,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
666
762
  }, helpers_1.Helpers.reqHeaderBypass());
667
763
  const success = this.checkResponse([response, status], 'setMode');
668
764
  if (!success) {
669
- logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
765
+ logger_1.logger.debug('Error setting humidity mode');
670
766
  }
671
767
  return success;
672
768
  }
@@ -916,10 +1012,11 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
916
1012
  * Set device mode
917
1013
  */
918
1014
  async setMode(mode) {
919
- if (!this.modes.includes(mode)) {
920
- const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
921
- logger_1.logger.error(`${error} for device: ${this.deviceName}`);
922
- throw new Error(error);
1015
+ const modeStr = mode.toLowerCase();
1016
+ if (!this.modes.includes(modeStr)) {
1017
+ logger_1.logger.debug(`Invalid humidity mode used - ${mode}`);
1018
+ logger_1.logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
1019
+ return false;
923
1020
  }
924
1021
  logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
925
1022
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -928,18 +1025,15 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
928
1025
  configModule: this.configModule,
929
1026
  payload: {
930
1027
  data: {
931
- mode
1028
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
932
1029
  },
933
1030
  method: 'setHumidifierMode',
934
1031
  source: 'APP'
935
1032
  }
936
1033
  }, helpers_1.Helpers.reqHeaderBypass());
937
1034
  const success = this.checkResponse([response, status], 'setMode');
938
- if (success) {
939
- this.details.mode = mode;
940
- }
941
- else {
942
- logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
1035
+ if (!success) {
1036
+ logger_1.logger.debug('Error setting humidity mode');
943
1037
  }
944
1038
  return success;
945
1039
  }
@@ -948,14 +1042,13 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
948
1042
  */
949
1043
  async setWarmLevel(level) {
950
1044
  if (!this.hasFeature('warm')) {
951
- const error = 'Warm mist control not supported';
952
- logger_1.logger.error(`${error} for device: ${this.deviceName}`);
953
- throw new Error(error);
1045
+ logger_1.logger.debug('Warm mist control not supported');
1046
+ return false;
954
1047
  }
955
1048
  if (!this.warmLevels.includes(level)) {
956
- const error = `Invalid warm level: ${level}. Must be one of: ${this.warmLevels.join(', ')}`;
957
- logger_1.logger.error(`${error} for device: ${this.deviceName}`);
958
- throw new Error(error);
1049
+ logger_1.logger.debug(`Invalid warm level: ${level} for device: ${this.deviceName}`);
1050
+ logger_1.logger.debug(`Valid levels for ${this.deviceType}: ${this.warmLevels.join(', ')}`);
1051
+ return false;
959
1052
  }
960
1053
  logger_1.logger.debug(`Setting warm level to ${level} for device: ${this.deviceName}`);
961
1054
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -1094,6 +1187,7 @@ class VeSyncAirBaseV2 extends VeSyncAirBypass {
1094
1187
  const body = {
1095
1188
  ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
1096
1189
  cid: this.cid,
1190
+ deviceId: this.cid, // Add deviceId to match YAML spec
1097
1191
  configModule: this.configModule,
1098
1192
  payload: {
1099
1193
  method,
@@ -1502,6 +1596,7 @@ class VeSyncTowerFan extends VeSyncAirBaseV2 {
1502
1596
  const body = {
1503
1597
  ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
1504
1598
  cid: this.cid,
1599
+ deviceId: this.cid, // Add deviceId to match YAML spec
1505
1600
  configModule: this.configModule,
1506
1601
  payload: {
1507
1602
  method,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsvesync",
3
- "version": "1.0.52",
3
+ "version": "1.0.54",
4
4
  "description": "A TypeScript library for interacting with VeSync smart home devices",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -200,101 +200,124 @@ export const fanConfig: FanConfig = {
200
200
  // Classic Series
201
201
  'Classic300S': {
202
202
  module: 'VeSyncHumidifier',
203
- features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
203
+ features: ['display', 'humidity', 'mist', 'timer', 'auto_mode'],
204
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
204
205
  },
205
206
  'Classic200S': {
206
207
  module: 'VeSyncHumidifier',
207
- features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
208
+ features: ['display', 'humidity', 'mist', 'timer', 'auto_mode'],
209
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
208
210
  },
209
211
 
210
212
  // Dual Series
211
213
  'Dual200S': {
212
214
  module: 'VeSyncHumidifier',
213
- features: ['display', 'humidity', 'mist', 'timer', 'auto_mode']
215
+ features: ['display', 'humidity', 'mist', 'timer', 'auto_mode'],
216
+ levels: [1, 2]
214
217
  },
215
218
 
216
219
  // LUH Series
217
220
  'LUH-A601S-WUSB': {
218
221
  module: 'VeSyncWarmHumidifier',
219
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
222
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
223
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
220
224
  },
221
225
  'LUH-A601S-AUSW': {
222
226
  module: 'VeSyncWarmHumidifier',
223
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
227
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
228
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
224
229
  },
225
230
  'LUH-D301S-WUSR': {
226
231
  module: 'VeSyncWarmHumidifier',
227
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
232
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
233
+ levels: [1, 2]
228
234
  },
229
235
  'LUH-D301S-WJP': {
230
236
  module: 'VeSyncWarmHumidifier',
231
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
237
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
238
+ levels: [1, 2]
232
239
  },
233
240
  'LUH-D301S-WEU': {
234
241
  module: 'VeSyncWarmHumidifier',
235
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
242
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
243
+ levels: [1, 2]
236
244
  },
237
245
  'LUH-A602S-WUSR': {
238
246
  module: 'VeSyncWarmHumidifier',
239
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
247
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
248
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
240
249
  },
241
250
  'LUH-A602S-WUS': {
242
251
  module: 'VeSyncWarmHumidifier',
243
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
252
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
253
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
244
254
  },
245
255
  'LUH-A602S-WEUR': {
246
256
  module: 'VeSyncWarmHumidifier',
247
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
257
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
258
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
248
259
  },
249
260
  'LUH-A602S-WEU': {
250
261
  module: 'VeSyncWarmHumidifier',
251
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
262
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
263
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
252
264
  },
253
265
  'LUH-A602S-WJP': {
254
266
  module: 'VeSyncWarmHumidifier',
255
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
267
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
268
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
256
269
  },
257
270
  'LUH-A602S-WUSC': {
258
271
  module: 'VeSyncWarmHumidifier',
259
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
272
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
273
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
260
274
  },
261
275
  'LUH-O451S-WEU': {
262
276
  module: 'VeSyncWarmHumidifier',
263
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
277
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
278
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
264
279
  },
265
280
  'LUH-O451S-WUS': {
266
281
  module: 'VeSyncWarmHumidifier',
267
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
282
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
283
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
268
284
  },
269
285
  'LUH-O451S-WUSR': {
270
286
  module: 'VeSyncWarmHumidifier',
271
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
287
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
288
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
272
289
  },
273
290
  'LUH-O601S-WUS': {
274
291
  module: 'VeSyncWarmHumidifier',
275
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
292
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
293
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
276
294
  },
277
295
  'LUH-O601S-KUS': {
278
296
  module: 'VeSyncWarmHumidifier',
279
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
297
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
298
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
280
299
  },
281
300
  'LUH-M101S-WUS': {
282
301
  module: 'VeSyncWarmHumidifier',
283
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
302
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
303
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
284
304
  },
285
305
  'LUH-M101S-WEUR': {
286
306
  module: 'VeSyncWarmHumidifier',
287
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode']
307
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode'],
308
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
288
309
  },
289
310
 
290
311
  // LEH Series
291
312
  'LEH-S601S-WUS': {
292
313
  module: 'VeSyncWarmHumidifier',
293
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
314
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying'],
315
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
294
316
  },
295
317
  'LEH-S601S-WUSR': {
296
318
  module: 'VeSyncWarmHumidifier',
297
- features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying']
319
+ features: ['display', 'humidity', 'mist', 'warm', 'timer', 'auto_mode', 'drying'],
320
+ levels: [1, 2, 3, 4, 5, 6, 7, 8, 9]
298
321
  },
299
322
 
300
323
  // LV Series
@@ -17,7 +17,10 @@ export class VeSyncAirBypass extends VeSyncFan {
17
17
 
18
18
  constructor(details: Record<string, any>, manager: VeSync) {
19
19
  super(details, manager);
20
- logger.debug(`Initialized VeSyncAirBypass device: ${this.deviceName}`);
20
+ logger.info(`Device Type: ${this.deviceType}`);
21
+ logger.info(`Device Details: ${JSON.stringify(details)}`);
22
+ logger.info(`Config: ${JSON.stringify(this.config)}`);
23
+ logger.info(`Initialized VeSyncAirBypass device: ${this.deviceName}`);
21
24
  }
22
25
 
23
26
  /**
@@ -28,6 +31,7 @@ export class VeSyncAirBypass extends VeSyncFan {
28
31
  const body = {
29
32
  ...Helpers.reqBody(this.manager, 'bypassV2'),
30
33
  cid: this.cid,
34
+ deviceId: this.cid, // Add deviceId to match YAML spec
31
35
  configModule: this.configModule,
32
36
  payload: {
33
37
  method,
@@ -296,10 +300,11 @@ export class VeSyncAirBypass extends VeSyncFan {
296
300
  * Set device mode
297
301
  */
298
302
  async setMode(mode: string): Promise<boolean> {
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);
303
+ const modeStr = mode.toLowerCase();
304
+ if (!this.modes.includes(modeStr as any)) {
305
+ logger.debug(`Invalid humidity mode used - ${mode}`);
306
+ logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
307
+ return false;
303
308
  }
304
309
 
305
310
  logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
@@ -312,9 +317,9 @@ export class VeSyncAirBypass extends VeSyncFan {
312
317
  configModule: this.configModule,
313
318
  payload: {
314
319
  data: {
315
- mode
320
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
316
321
  },
317
- method: 'setPurifierMode',
322
+ method: 'setHumidifierMode',
318
323
  source: 'APP'
319
324
  }
320
325
  },
@@ -323,7 +328,7 @@ export class VeSyncAirBypass extends VeSyncFan {
323
328
 
324
329
  const success = this.checkResponse([response, status], 'setMode');
325
330
  if (!success) {
326
- logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
331
+ logger.debug('Error setting humidity mode');
327
332
  }
328
333
  return success;
329
334
  }
@@ -600,6 +605,7 @@ export class VeSyncHumidifier extends VeSyncFan {
600
605
  protected readonly mistLevels: number[];
601
606
  protected readonly displayModes = ['on', 'off'] as const;
602
607
  protected readonly humidityRange = { min: 30, max: 80 };
608
+ protected readonly states = ['inactive', 'idle', 'humidifying'] as const;
603
609
 
604
610
  constructor(details: Record<string, any>, manager: VeSync) {
605
611
  super(details, manager);
@@ -618,6 +624,75 @@ export class VeSyncHumidifier extends VeSyncFan {
618
624
  logger.debug(`Initialized VeSyncHumidifier device: ${this.deviceName}`);
619
625
  }
620
626
 
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
+
621
696
  /**
622
697
  * Get device details
623
698
  */
@@ -655,12 +730,13 @@ export class VeSyncHumidifier extends VeSyncFan {
655
730
  humidity: result.humidity || 0,
656
731
  mist_level: result.mistLevel || 0,
657
732
  mist_virtual_level: result.virtualLevel || 0,
658
- warm_level: result.warmLevel || 0,
659
733
  water_lacks: result.waterLacks || false,
660
- humidity_high: result.humidityHigh || false,
734
+ water_level: result.waterLevel || 0,
661
735
  water_tank_lifted: result.waterTankLifted || false,
736
+ humidity_high: result.humidityHigh || false,
662
737
  display: result.display || false,
663
738
  automatic_stop: result.automaticStop || false,
739
+ oscillation_enabled: result.oscillationEnabled || false,
664
740
  configuration: result.configuration || {},
665
741
  connection_status: result.connectionStatus || null
666
742
  };
@@ -669,6 +745,37 @@ export class VeSyncHumidifier extends VeSyncFan {
669
745
  return success;
670
746
  }
671
747
 
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
+
672
779
  /**
673
780
  * Turn device on
674
781
  */
@@ -740,9 +847,9 @@ export class VeSyncHumidifier extends VeSyncFan {
740
847
  */
741
848
  async setMistLevel(level: number): Promise<boolean> {
742
849
  if (!this.mistLevels.includes(level)) {
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);
850
+ logger.debug(`Invalid mist level: ${level} for device: ${this.deviceName}`);
851
+ logger.debug(`Valid levels for ${this.deviceType}: ${this.mistLevels.join(', ')}`);
852
+ return false;
746
853
  }
747
854
 
748
855
  logger.info(`Setting mist level to ${level} for device: ${this.deviceName}`);
@@ -755,9 +862,9 @@ export class VeSyncHumidifier extends VeSyncFan {
755
862
  configModule: this.configModule,
756
863
  payload: {
757
864
  data: {
758
- id: 0,
759
- level: level,
760
- type: 'mist'
865
+ levelIdx: 0,
866
+ virtualLevel: level,
867
+ levelType: 'mist'
761
868
  },
762
869
  method: 'setVirtualLevel',
763
870
  source: 'APP'
@@ -768,7 +875,7 @@ export class VeSyncHumidifier extends VeSyncFan {
768
875
 
769
876
  const success = this.checkResponse([response, status], 'setMistLevel');
770
877
  if (!success) {
771
- logger.error(`Failed to set mist level to ${level} for device: ${this.deviceName}`);
878
+ logger.debug('Error setting mist level');
772
879
  }
773
880
  return success;
774
881
  }
@@ -785,10 +892,11 @@ export class VeSyncHumidifier extends VeSyncFan {
785
892
  * Set device mode
786
893
  */
787
894
  async setMode(mode: string): Promise<boolean> {
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);
895
+ const modeStr = mode.toLowerCase();
896
+ if (!this.modes.includes(modeStr as any)) {
897
+ logger.debug(`Invalid humidity mode used - ${mode}`);
898
+ logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
899
+ return false;
792
900
  }
793
901
 
794
902
  logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
@@ -801,7 +909,7 @@ export class VeSyncHumidifier extends VeSyncFan {
801
909
  configModule: this.configModule,
802
910
  payload: {
803
911
  data: {
804
- mode
912
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
805
913
  },
806
914
  method: 'setHumidifierMode',
807
915
  source: 'APP'
@@ -812,7 +920,7 @@ export class VeSyncHumidifier extends VeSyncFan {
812
920
 
813
921
  const success = this.checkResponse([response, status], 'setMode');
814
922
  if (!success) {
815
- logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
923
+ logger.debug('Error setting humidity mode');
816
924
  }
817
925
  return success;
818
926
  }
@@ -1117,10 +1225,11 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
1117
1225
  * Set device mode
1118
1226
  */
1119
1227
  async setMode(mode: string): Promise<boolean> {
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);
1228
+ const modeStr = mode.toLowerCase();
1229
+ if (!this.modes.includes(modeStr as any)) {
1230
+ logger.debug(`Invalid humidity mode used - ${mode}`);
1231
+ logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
1232
+ return false;
1124
1233
  }
1125
1234
 
1126
1235
  logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
@@ -1133,7 +1242,7 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
1133
1242
  configModule: this.configModule,
1134
1243
  payload: {
1135
1244
  data: {
1136
- mode
1245
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
1137
1246
  },
1138
1247
  method: 'setHumidifierMode',
1139
1248
  source: 'APP'
@@ -1143,10 +1252,8 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
1143
1252
  );
1144
1253
 
1145
1254
  const success = this.checkResponse([response, status], 'setMode');
1146
- if (success) {
1147
- this.details.mode = mode;
1148
- } else {
1149
- logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
1255
+ if (!success) {
1256
+ logger.debug('Error setting humidity mode');
1150
1257
  }
1151
1258
  return success;
1152
1259
  }
@@ -1156,15 +1263,14 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
1156
1263
  */
1157
1264
  async setWarmLevel(level: number): Promise<boolean> {
1158
1265
  if (!this.hasFeature('warm')) {
1159
- const error = 'Warm mist control not supported';
1160
- logger.error(`${error} for device: ${this.deviceName}`);
1161
- throw new Error(error);
1266
+ logger.debug('Warm mist control not supported');
1267
+ return false;
1162
1268
  }
1163
1269
 
1164
1270
  if (!this.warmLevels.includes(level)) {
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);
1271
+ logger.debug(`Invalid warm level: ${level} for device: ${this.deviceName}`);
1272
+ logger.debug(`Valid levels for ${this.deviceType}: ${this.warmLevels.join(', ')}`);
1273
+ return false;
1168
1274
  }
1169
1275
 
1170
1276
  logger.debug(`Setting warm level to ${level} for device: ${this.deviceName}`);
@@ -1330,6 +1436,7 @@ export class VeSyncAirBaseV2 extends VeSyncAirBypass {
1330
1436
  const body = {
1331
1437
  ...Helpers.reqBody(this.manager, 'bypassV2'),
1332
1438
  cid: this.cid,
1439
+ deviceId: this.cid, // Add deviceId to match YAML spec
1333
1440
  configModule: this.configModule,
1334
1441
  payload: {
1335
1442
  method,
@@ -1850,6 +1957,7 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
1850
1957
  const body = {
1851
1958
  ...Helpers.reqBody(this.manager, 'bypassV2'),
1852
1959
  cid: this.cid,
1960
+ deviceId: this.cid, // Add deviceId to match YAML spec
1853
1961
  configModule: this.configModule,
1854
1962
  payload: {
1855
1963
  method,