tsvesync 1.0.52 → 1.0.55

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
  */
@@ -26,6 +26,7 @@ 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
29
30
  configModule: this.configModule,
30
31
  payload: {
31
32
  method,
@@ -209,10 +210,11 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
209
210
  * Change fan speed
210
211
  */
211
212
  async changeFanSpeed(speed) {
212
- var _a;
213
- const speeds = (_a = this.config.levels) !== null && _a !== void 0 ? _a : [];
214
- if (!speeds.includes(speed)) {
215
- logger_1.logger.error(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')} for device: ${this.deviceName}`);
213
+ var _a, _b, _c;
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
+ if (!((_b = this.config.levels) === null || _b === void 0 ? void 0 : _b.includes(speed))) {
217
+ logger_1.logger.error(`Invalid speed: ${speed}. Must be one of: ${(_c = this.config.levels) === null || _c === void 0 ? void 0 : _c.join(', ')} for device: ${this.deviceName}`);
216
218
  return false;
217
219
  }
218
220
  logger_1.logger.info(`Changing fan speed to ${speed} for device: ${this.deviceName}`);
@@ -241,10 +243,11 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
241
243
  * Set device mode
242
244
  */
243
245
  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);
246
+ const modeStr = mode.toLowerCase();
247
+ if (!this.modes.includes(modeStr)) {
248
+ logger_1.logger.debug(`Invalid humidity mode used - ${mode}`);
249
+ logger_1.logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
250
+ return false;
248
251
  }
249
252
  logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
250
253
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -253,15 +256,15 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
253
256
  configModule: this.configModule,
254
257
  payload: {
255
258
  data: {
256
- mode
259
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
257
260
  },
258
- method: 'setPurifierMode',
261
+ method: 'setHumidifierMode',
259
262
  source: 'APP'
260
263
  }
261
264
  }, helpers_1.Helpers.reqHeaderBypass());
262
265
  const success = this.checkResponse([response, status], 'setMode');
263
266
  if (!success) {
264
- logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
267
+ logger_1.logger.debug('Error setting humidity mode');
265
268
  }
266
269
  return success;
267
270
  }
@@ -488,6 +491,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
488
491
  this.modes = ['auto', 'manual', 'sleep'];
489
492
  this.displayModes = ['on', 'off'];
490
493
  this.humidityRange = { min: 30, max: 80 };
494
+ this.states = ['inactive', 'idle', 'humidifying'];
491
495
  // Set mist levels based on model
492
496
  switch (this.deviceType) {
493
497
  case 'Dual200S':
@@ -502,6 +506,66 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
502
506
  }
503
507
  logger_1.logger.debug(`Initialized VeSyncHumidifier device: ${this.deviceName}`);
504
508
  }
509
+ /**
510
+ * Get current operational state
511
+ */
512
+ get currentState() {
513
+ if (this.deviceStatus === 'off') {
514
+ return 'inactive';
515
+ }
516
+ if (this.details.water_lacks) {
517
+ return 'idle';
518
+ }
519
+ return 'humidifying';
520
+ }
521
+ /**
522
+ * Get water level percentage
523
+ */
524
+ get waterLevel() {
525
+ var _a;
526
+ return (_a = this.details.water_level) !== null && _a !== void 0 ? _a : 0;
527
+ }
528
+ /**
529
+ * Get water tank status
530
+ */
531
+ get waterTankLifted() {
532
+ var _a;
533
+ return (_a = this.details.water_tank_lifted) !== null && _a !== void 0 ? _a : false;
534
+ }
535
+ /**
536
+ * Get oscillation state
537
+ */
538
+ get oscillationEnabled() {
539
+ var _a;
540
+ return (_a = this.details.oscillation_enabled) !== null && _a !== void 0 ? _a : false;
541
+ }
542
+ /**
543
+ * Set oscillation state
544
+ */
545
+ async setOscillation(enabled) {
546
+ if (!this.hasFeature('oscillation')) {
547
+ logger_1.logger.debug('Oscillation not supported');
548
+ return false;
549
+ }
550
+ logger_1.logger.debug(`Setting oscillation to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
551
+ const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
552
+ ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
553
+ cid: this.cid,
554
+ configModule: this.configModule,
555
+ payload: {
556
+ data: {
557
+ oscillationEnabled: enabled
558
+ },
559
+ method: 'setSwing',
560
+ source: 'APP'
561
+ }
562
+ }, helpers_1.Helpers.reqHeaderBypass());
563
+ const success = this.checkResponse([response, status], 'setOscillation');
564
+ if (!success) {
565
+ logger_1.logger.debug('Error setting oscillation');
566
+ }
567
+ return success;
568
+ }
505
569
  /**
506
570
  * Get device details
507
571
  */
@@ -533,12 +597,13 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
533
597
  humidity: result.humidity || 0,
534
598
  mist_level: result.mistLevel || 0,
535
599
  mist_virtual_level: result.virtualLevel || 0,
536
- warm_level: result.warmLevel || 0,
537
600
  water_lacks: result.waterLacks || false,
538
- humidity_high: result.humidityHigh || false,
601
+ water_level: result.waterLevel || 0,
539
602
  water_tank_lifted: result.waterTankLifted || false,
603
+ humidity_high: result.humidityHigh || false,
540
604
  display: result.display || false,
541
605
  automatic_stop: result.automaticStop || false,
606
+ oscillation_enabled: result.oscillationEnabled || false,
542
607
  configuration: result.configuration || {},
543
608
  connection_status: result.connectionStatus || null
544
609
  };
@@ -546,6 +611,34 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
546
611
  }
547
612
  return success;
548
613
  }
614
+ /**
615
+ * Display device info
616
+ */
617
+ display() {
618
+ super.display();
619
+ const info = [
620
+ ['Current State: ', this.currentState],
621
+ ['Water Level: ', this.waterLevel, '%'],
622
+ ['Water Tank: ', this.waterTankLifted ? 'Lifted' : 'Seated'],
623
+ ['Oscillation: ', this.oscillationEnabled ? 'On' : 'Off']
624
+ ];
625
+ for (const [key, value, unit = ''] of info) {
626
+ logger_1.logger.info(`${key.toString().padEnd(30, '.')} ${value}${unit}`);
627
+ }
628
+ }
629
+ /**
630
+ * Return JSON details
631
+ */
632
+ displayJSON() {
633
+ const baseInfo = JSON.parse(super.displayJSON());
634
+ return JSON.stringify({
635
+ ...baseInfo,
636
+ 'Current State': this.currentState,
637
+ 'Water Level': this.waterLevel,
638
+ 'Water Tank': this.waterTankLifted ? 'Lifted' : 'Seated',
639
+ 'Oscillation': this.oscillationEnabled ? 'On' : 'Off'
640
+ }, null, 4);
641
+ }
549
642
  /**
550
643
  * Turn device on
551
644
  */
@@ -610,9 +703,9 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
610
703
  */
611
704
  async setMistLevel(level) {
612
705
  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);
706
+ logger_1.logger.debug(`Invalid mist level: ${level} for device: ${this.deviceName}`);
707
+ logger_1.logger.debug(`Valid levels for ${this.deviceType}: ${this.mistLevels.join(', ')}`);
708
+ return false;
616
709
  }
617
710
  logger_1.logger.info(`Setting mist level to ${level} for device: ${this.deviceName}`);
618
711
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -621,9 +714,9 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
621
714
  configModule: this.configModule,
622
715
  payload: {
623
716
  data: {
624
- id: 0,
625
- level: level,
626
- type: 'mist'
717
+ levelIdx: 0,
718
+ virtualLevel: level,
719
+ levelType: 'mist'
627
720
  },
628
721
  method: 'setVirtualLevel',
629
722
  source: 'APP'
@@ -631,7 +724,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
631
724
  }, helpers_1.Helpers.reqHeaderBypass());
632
725
  const success = this.checkResponse([response, status], 'setMistLevel');
633
726
  if (!success) {
634
- logger_1.logger.error(`Failed to set mist level to ${level} for device: ${this.deviceName}`);
727
+ logger_1.logger.debug('Error setting mist level');
635
728
  }
636
729
  return success;
637
730
  }
@@ -646,10 +739,11 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
646
739
  * Set device mode
647
740
  */
648
741
  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);
742
+ const modeStr = mode.toLowerCase();
743
+ if (!this.modes.includes(modeStr)) {
744
+ logger_1.logger.debug(`Invalid humidity mode used - ${mode}`);
745
+ logger_1.logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
746
+ return false;
653
747
  }
654
748
  logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
655
749
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -658,7 +752,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
658
752
  configModule: this.configModule,
659
753
  payload: {
660
754
  data: {
661
- mode
755
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
662
756
  },
663
757
  method: 'setHumidifierMode',
664
758
  source: 'APP'
@@ -666,7 +760,7 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
666
760
  }, helpers_1.Helpers.reqHeaderBypass());
667
761
  const success = this.checkResponse([response, status], 'setMode');
668
762
  if (!success) {
669
- logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
763
+ logger_1.logger.debug('Error setting humidity mode');
670
764
  }
671
765
  return success;
672
766
  }
@@ -916,10 +1010,11 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
916
1010
  * Set device mode
917
1011
  */
918
1012
  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);
1013
+ const modeStr = mode.toLowerCase();
1014
+ if (!this.modes.includes(modeStr)) {
1015
+ logger_1.logger.debug(`Invalid humidity mode used - ${mode}`);
1016
+ logger_1.logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
1017
+ return false;
923
1018
  }
924
1019
  logger_1.logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
925
1020
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -928,18 +1023,15 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
928
1023
  configModule: this.configModule,
929
1024
  payload: {
930
1025
  data: {
931
- mode
1026
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
932
1027
  },
933
1028
  method: 'setHumidifierMode',
934
1029
  source: 'APP'
935
1030
  }
936
1031
  }, helpers_1.Helpers.reqHeaderBypass());
937
1032
  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}`);
1033
+ if (!success) {
1034
+ logger_1.logger.debug('Error setting humidity mode');
943
1035
  }
944
1036
  return success;
945
1037
  }
@@ -948,14 +1040,13 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
948
1040
  */
949
1041
  async setWarmLevel(level) {
950
1042
  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);
1043
+ logger_1.logger.debug('Warm mist control not supported');
1044
+ return false;
954
1045
  }
955
1046
  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);
1047
+ logger_1.logger.debug(`Invalid warm level: ${level} for device: ${this.deviceName}`);
1048
+ logger_1.logger.debug(`Valid levels for ${this.deviceType}: ${this.warmLevels.join(', ')}`);
1049
+ return false;
959
1050
  }
960
1051
  logger_1.logger.debug(`Setting warm level to ${level} for device: ${this.deviceName}`);
961
1052
  const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
@@ -1094,6 +1185,7 @@ class VeSyncAirBaseV2 extends VeSyncAirBypass {
1094
1185
  const body = {
1095
1186
  ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
1096
1187
  cid: this.cid,
1188
+ deviceId: this.cid, // Add deviceId to match YAML spec
1097
1189
  configModule: this.configModule,
1098
1190
  payload: {
1099
1191
  method,
@@ -1502,6 +1594,7 @@ class VeSyncTowerFan extends VeSyncAirBaseV2 {
1502
1594
  const body = {
1503
1595
  ...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
1504
1596
  cid: this.cid,
1597
+ deviceId: this.cid, // Add deviceId to match YAML spec
1505
1598
  configModule: this.configModule,
1506
1599
  payload: {
1507
1600
  method,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsvesync",
3
- "version": "1.0.52",
3
+ "version": "1.0.55",
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
@@ -28,6 +28,7 @@ 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
31
32
  configModule: this.configModule,
32
33
  payload: {
33
34
  method,
@@ -257,9 +258,11 @@ export class VeSyncAirBypass extends VeSyncFan {
257
258
  * Change fan speed
258
259
  */
259
260
  async changeFanSpeed(speed: number): Promise<boolean> {
260
- const speeds = this.config.levels ?? [];
261
- if (!speeds.includes(speed)) {
262
- logger.error(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')} for device: ${this.deviceName}`);
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
+ if (!this.config.levels?.includes(speed)) {
265
+ logger.error(`Invalid speed: ${speed}. Must be one of: ${this.config.levels?.join(', ')} for device: ${this.deviceName}`);
263
266
  return false;
264
267
  }
265
268
 
@@ -296,10 +299,11 @@ export class VeSyncAirBypass extends VeSyncFan {
296
299
  * Set device mode
297
300
  */
298
301
  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);
302
+ const modeStr = mode.toLowerCase();
303
+ if (!this.modes.includes(modeStr as any)) {
304
+ logger.debug(`Invalid humidity mode used - ${mode}`);
305
+ logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
306
+ return false;
303
307
  }
304
308
 
305
309
  logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
@@ -312,9 +316,9 @@ export class VeSyncAirBypass extends VeSyncFan {
312
316
  configModule: this.configModule,
313
317
  payload: {
314
318
  data: {
315
- mode
319
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
316
320
  },
317
- method: 'setPurifierMode',
321
+ method: 'setHumidifierMode',
318
322
  source: 'APP'
319
323
  }
320
324
  },
@@ -323,7 +327,7 @@ export class VeSyncAirBypass extends VeSyncFan {
323
327
 
324
328
  const success = this.checkResponse([response, status], 'setMode');
325
329
  if (!success) {
326
- logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
330
+ logger.debug('Error setting humidity mode');
327
331
  }
328
332
  return success;
329
333
  }
@@ -600,6 +604,7 @@ export class VeSyncHumidifier extends VeSyncFan {
600
604
  protected readonly mistLevels: number[];
601
605
  protected readonly displayModes = ['on', 'off'] as const;
602
606
  protected readonly humidityRange = { min: 30, max: 80 };
607
+ protected readonly states = ['inactive', 'idle', 'humidifying'] as const;
603
608
 
604
609
  constructor(details: Record<string, any>, manager: VeSync) {
605
610
  super(details, manager);
@@ -618,6 +623,75 @@ export class VeSyncHumidifier extends VeSyncFan {
618
623
  logger.debug(`Initialized VeSyncHumidifier device: ${this.deviceName}`);
619
624
  }
620
625
 
626
+ /**
627
+ * Get current operational state
628
+ */
629
+ get currentState(): string {
630
+ if (this.deviceStatus === 'off') {
631
+ return 'inactive';
632
+ }
633
+ if (this.details.water_lacks) {
634
+ return 'idle';
635
+ }
636
+ return 'humidifying';
637
+ }
638
+
639
+ /**
640
+ * Get water level percentage
641
+ */
642
+ get waterLevel(): number {
643
+ return this.details.water_level ?? 0;
644
+ }
645
+
646
+ /**
647
+ * Get water tank status
648
+ */
649
+ get waterTankLifted(): boolean {
650
+ return this.details.water_tank_lifted ?? false;
651
+ }
652
+
653
+ /**
654
+ * Get oscillation state
655
+ */
656
+ get oscillationEnabled(): boolean {
657
+ return this.details.oscillation_enabled ?? false;
658
+ }
659
+
660
+ /**
661
+ * Set oscillation state
662
+ */
663
+ async setOscillation(enabled: boolean): Promise<boolean> {
664
+ if (!this.hasFeature('oscillation')) {
665
+ logger.debug('Oscillation not supported');
666
+ return false;
667
+ }
668
+
669
+ logger.debug(`Setting oscillation to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
670
+ const [response, status] = await this.callApi(
671
+ '/cloud/v2/deviceManaged/bypassV2',
672
+ 'post',
673
+ {
674
+ ...Helpers.reqBody(this.manager, 'bypassV2'),
675
+ cid: this.cid,
676
+ configModule: this.configModule,
677
+ payload: {
678
+ data: {
679
+ oscillationEnabled: enabled
680
+ },
681
+ method: 'setSwing',
682
+ source: 'APP'
683
+ }
684
+ },
685
+ Helpers.reqHeaderBypass()
686
+ );
687
+
688
+ const success = this.checkResponse([response, status], 'setOscillation');
689
+ if (!success) {
690
+ logger.debug('Error setting oscillation');
691
+ }
692
+ return success;
693
+ }
694
+
621
695
  /**
622
696
  * Get device details
623
697
  */
@@ -655,12 +729,13 @@ export class VeSyncHumidifier extends VeSyncFan {
655
729
  humidity: result.humidity || 0,
656
730
  mist_level: result.mistLevel || 0,
657
731
  mist_virtual_level: result.virtualLevel || 0,
658
- warm_level: result.warmLevel || 0,
659
732
  water_lacks: result.waterLacks || false,
660
- humidity_high: result.humidityHigh || false,
733
+ water_level: result.waterLevel || 0,
661
734
  water_tank_lifted: result.waterTankLifted || false,
735
+ humidity_high: result.humidityHigh || false,
662
736
  display: result.display || false,
663
737
  automatic_stop: result.automaticStop || false,
738
+ oscillation_enabled: result.oscillationEnabled || false,
664
739
  configuration: result.configuration || {},
665
740
  connection_status: result.connectionStatus || null
666
741
  };
@@ -669,6 +744,37 @@ export class VeSyncHumidifier extends VeSyncFan {
669
744
  return success;
670
745
  }
671
746
 
747
+ /**
748
+ * Display device info
749
+ */
750
+ override display(): void {
751
+ super.display();
752
+ const info = [
753
+ ['Current State: ', this.currentState],
754
+ ['Water Level: ', this.waterLevel, '%'],
755
+ ['Water Tank: ', this.waterTankLifted ? 'Lifted' : 'Seated'],
756
+ ['Oscillation: ', this.oscillationEnabled ? 'On' : 'Off']
757
+ ];
758
+
759
+ for (const [key, value, unit = ''] of info) {
760
+ logger.info(`${key.toString().padEnd(30, '.')} ${value}${unit}`);
761
+ }
762
+ }
763
+
764
+ /**
765
+ * Return JSON details
766
+ */
767
+ override displayJSON(): string {
768
+ const baseInfo = JSON.parse(super.displayJSON());
769
+ return JSON.stringify({
770
+ ...baseInfo,
771
+ 'Current State': this.currentState,
772
+ 'Water Level': this.waterLevel,
773
+ 'Water Tank': this.waterTankLifted ? 'Lifted' : 'Seated',
774
+ 'Oscillation': this.oscillationEnabled ? 'On' : 'Off'
775
+ }, null, 4);
776
+ }
777
+
672
778
  /**
673
779
  * Turn device on
674
780
  */
@@ -740,9 +846,9 @@ export class VeSyncHumidifier extends VeSyncFan {
740
846
  */
741
847
  async setMistLevel(level: number): Promise<boolean> {
742
848
  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);
849
+ logger.debug(`Invalid mist level: ${level} for device: ${this.deviceName}`);
850
+ logger.debug(`Valid levels for ${this.deviceType}: ${this.mistLevels.join(', ')}`);
851
+ return false;
746
852
  }
747
853
 
748
854
  logger.info(`Setting mist level to ${level} for device: ${this.deviceName}`);
@@ -755,9 +861,9 @@ export class VeSyncHumidifier extends VeSyncFan {
755
861
  configModule: this.configModule,
756
862
  payload: {
757
863
  data: {
758
- id: 0,
759
- level: level,
760
- type: 'mist'
864
+ levelIdx: 0,
865
+ virtualLevel: level,
866
+ levelType: 'mist'
761
867
  },
762
868
  method: 'setVirtualLevel',
763
869
  source: 'APP'
@@ -768,7 +874,7 @@ export class VeSyncHumidifier extends VeSyncFan {
768
874
 
769
875
  const success = this.checkResponse([response, status], 'setMistLevel');
770
876
  if (!success) {
771
- logger.error(`Failed to set mist level to ${level} for device: ${this.deviceName}`);
877
+ logger.debug('Error setting mist level');
772
878
  }
773
879
  return success;
774
880
  }
@@ -785,10 +891,11 @@ export class VeSyncHumidifier extends VeSyncFan {
785
891
  * Set device mode
786
892
  */
787
893
  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);
894
+ const modeStr = mode.toLowerCase();
895
+ if (!this.modes.includes(modeStr as any)) {
896
+ logger.debug(`Invalid humidity mode used - ${mode}`);
897
+ logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
898
+ return false;
792
899
  }
793
900
 
794
901
  logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
@@ -801,7 +908,7 @@ export class VeSyncHumidifier extends VeSyncFan {
801
908
  configModule: this.configModule,
802
909
  payload: {
803
910
  data: {
804
- mode
911
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
805
912
  },
806
913
  method: 'setHumidifierMode',
807
914
  source: 'APP'
@@ -812,7 +919,7 @@ export class VeSyncHumidifier extends VeSyncFan {
812
919
 
813
920
  const success = this.checkResponse([response, status], 'setMode');
814
921
  if (!success) {
815
- logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
922
+ logger.debug('Error setting humidity mode');
816
923
  }
817
924
  return success;
818
925
  }
@@ -1117,10 +1224,11 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
1117
1224
  * Set device mode
1118
1225
  */
1119
1226
  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);
1227
+ const modeStr = mode.toLowerCase();
1228
+ if (!this.modes.includes(modeStr as any)) {
1229
+ logger.debug(`Invalid humidity mode used - ${mode}`);
1230
+ logger.debug(`Proper modes for this device are - ${this.modes.join(', ')}`);
1231
+ return false;
1124
1232
  }
1125
1233
 
1126
1234
  logger.debug(`Setting mode to ${mode} for device: ${this.deviceName}`);
@@ -1133,7 +1241,7 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
1133
1241
  configModule: this.configModule,
1134
1242
  payload: {
1135
1243
  data: {
1136
- mode
1244
+ workMode: this.deviceType.startsWith('Superior') && modeStr === 'auto' ? 'autoPro' : modeStr
1137
1245
  },
1138
1246
  method: 'setHumidifierMode',
1139
1247
  source: 'APP'
@@ -1143,10 +1251,8 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
1143
1251
  );
1144
1252
 
1145
1253
  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}`);
1254
+ if (!success) {
1255
+ logger.debug('Error setting humidity mode');
1150
1256
  }
1151
1257
  return success;
1152
1258
  }
@@ -1156,15 +1262,14 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
1156
1262
  */
1157
1263
  async setWarmLevel(level: number): Promise<boolean> {
1158
1264
  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);
1265
+ logger.debug('Warm mist control not supported');
1266
+ return false;
1162
1267
  }
1163
1268
 
1164
1269
  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);
1270
+ logger.debug(`Invalid warm level: ${level} for device: ${this.deviceName}`);
1271
+ logger.debug(`Valid levels for ${this.deviceType}: ${this.warmLevels.join(', ')}`);
1272
+ return false;
1168
1273
  }
1169
1274
 
1170
1275
  logger.debug(`Setting warm level to ${level} for device: ${this.deviceName}`);
@@ -1330,6 +1435,7 @@ export class VeSyncAirBaseV2 extends VeSyncAirBypass {
1330
1435
  const body = {
1331
1436
  ...Helpers.reqBody(this.manager, 'bypassV2'),
1332
1437
  cid: this.cid,
1438
+ deviceId: this.cid, // Add deviceId to match YAML spec
1333
1439
  configModule: this.configModule,
1334
1440
  payload: {
1335
1441
  method,
@@ -1850,6 +1956,7 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
1850
1956
  const body = {
1851
1957
  ...Helpers.reqBody(this.manager, 'bypassV2'),
1852
1958
  cid: this.cid,
1959
+ deviceId: this.cid, // Add deviceId to match YAML spec
1853
1960
  configModule: this.configModule,
1854
1961
  payload: {
1855
1962
  method,