tsvesync 1.0.78 → 1.0.79

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.
@@ -4,7 +4,7 @@ import { VeSync } from '../vesync';
4
4
  * VeSync Tower Fan Implementation
5
5
  */
6
6
  export declare class VeSyncTowerFan extends VeSyncAirBaseV2 {
7
- protected readonly towerModes: readonly ["normal", "auto", "advancedSleep", "turbo", "off"];
7
+ protected readonly towerModes: readonly ["normal", "advancedSleep", "off"];
8
8
  constructor(details: Record<string, any>, manager: VeSync);
9
9
  /**
10
10
  * Get device details
@@ -25,7 +25,7 @@ export declare class VeSyncTowerFan extends VeSyncAirBaseV2 {
25
25
  /**
26
26
  * Set tower fan mode
27
27
  */
28
- modeToggle(mode: string): Promise<boolean>;
28
+ mode_toggle(mode: string): Promise<boolean>;
29
29
  /**
30
30
  * Change fan speed
31
31
  */
@@ -38,14 +38,6 @@ export declare class VeSyncTowerFan extends VeSyncAirBaseV2 {
38
38
  * Set manual mode - adapter to set mode to normal
39
39
  */
40
40
  manual_mode(): Promise<boolean>;
41
- /**
42
- * Set auto mode
43
- */
44
- auto_mode(): Promise<boolean>;
45
- /**
46
- * Set turbo mode
47
- */
48
- turbo_mode(): Promise<boolean>;
49
41
  /**
50
42
  * Set advanced sleep mode
51
43
  */
@@ -58,10 +50,6 @@ export declare class VeSyncTowerFan extends VeSyncAirBaseV2 {
58
50
  * Override setMode to handle tower fan specific modes
59
51
  */
60
52
  setMode(mode: string): Promise<boolean>;
61
- /**
62
- * Alias for modeToggle to match Python naming convention
63
- */
64
- mode_toggle(mode: string): Promise<boolean>;
65
53
  /**
66
54
  * Get current speed
67
55
  */
@@ -78,10 +66,6 @@ export declare class VeSyncTowerFan extends VeSyncAirBaseV2 {
78
66
  * Get mute status
79
67
  */
80
68
  get muteState(): boolean;
81
- /**
82
- * Get mute switch status
83
- */
84
- get muteSwitch(): boolean;
85
69
  /**
86
70
  * Get temperature (in tenths of a degree)
87
71
  */
@@ -106,10 +90,6 @@ export declare class VeSyncTowerFan extends VeSyncAirBaseV2 {
106
90
  * Get error code
107
91
  */
108
92
  get errorCode(): number;
109
- /**
110
- * Set oscillation state
111
- */
112
- setOscillation(state: boolean): Promise<boolean>;
113
93
  /**
114
94
  * Turn oscillation on
115
95
  */
@@ -9,7 +9,7 @@ const logger_1 = require("../logger");
9
9
  class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
10
10
  constructor(details, manager) {
11
11
  super(details, manager);
12
- this.towerModes = ['normal', 'auto', 'advancedSleep', 'turbo', 'off'];
12
+ this.towerModes = ['normal', 'advancedSleep', 'off'];
13
13
  logger_1.logger.debug(`Initialized VeSyncTowerFan device: ${this.deviceName}`);
14
14
  }
15
15
  /**
@@ -30,19 +30,26 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
30
30
  this.connectionStatus = 'offline';
31
31
  return false;
32
32
  }
33
- const innerResult = innerResponse.result;
34
- // Use the same methods as Python version
35
- if (innerResult) {
36
- this.buildPurifierDict(innerResult);
37
- }
38
- else {
39
- this.connectionStatus = 'offline';
40
- logger_1.logger.debug('error in inner result dict from tower fan');
41
- return false;
42
- }
43
- if (innerResult.configuration) {
44
- this.buildConfigDict(innerResult.configuration);
45
- }
33
+ const deviceData = innerResponse.result;
34
+ this.deviceStatus = deviceData.powerSwitch === 1 ? 'on' : 'off';
35
+ this.details = {
36
+ powerSwitch: deviceData.powerSwitch,
37
+ workMode: deviceData.workMode,
38
+ manualSpeedLevel: deviceData.manualSpeedLevel,
39
+ fanSpeedLevel: deviceData.fanSpeedLevel,
40
+ screenState: deviceData.screenState,
41
+ screenSwitch: deviceData.screenSwitch,
42
+ oscillationState: deviceData.oscillationState,
43
+ oscillationSwitch: deviceData.oscillationSwitch,
44
+ timerRemain: deviceData.timerRemain,
45
+ temperature: deviceData.temperature || 0,
46
+ humidity: deviceData.humidity || 0,
47
+ thermalComfort: deviceData.thermalComfort,
48
+ sleepPreference: deviceData.sleepPreference || {},
49
+ scheduleCount: deviceData.scheduleCount,
50
+ displayingType: deviceData.displayingType,
51
+ errorCode: deviceData.errorCode
52
+ };
46
53
  logger_1.logger.debug(`Successfully got details for device: ${this.deviceName}`);
47
54
  return true;
48
55
  }
@@ -86,7 +93,7 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
86
93
  /**
87
94
  * Set tower fan mode
88
95
  */
89
- async modeToggle(mode) {
96
+ async mode_toggle(mode) {
90
97
  if (!this.towerModes.includes(mode)) {
91
98
  logger_1.logger.debug(`Invalid mode: ${mode}. Must be one of: ${this.towerModes.join(', ')}`);
92
99
  return false;
@@ -113,12 +120,11 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
113
120
  * Change fan speed
114
121
  */
115
122
  async changeFanSpeed(speed) {
116
- var _a;
117
- const speeds = (_a = this.config.levels) !== null && _a !== void 0 ? _a : [];
118
- if (!speeds.includes(speed)) {
119
- logger_1.logger.debug(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')}`);
120
- return false;
121
- }
123
+ // const speeds = this.config.levels ?? [];
124
+ // if (!speeds.includes(speed)) {
125
+ // logger.debug(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')}`);
126
+ // return false;
127
+ // }
122
128
  const [head, body] = this.buildApiDict('setLevel');
123
129
  body.payload.data = {
124
130
  levelIdx: 0,
@@ -140,7 +146,7 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
140
146
  */
141
147
  async normal_mode() {
142
148
  logger_1.logger.debug(`Setting normal mode for device: ${this.deviceName}`);
143
- return this.modeToggle('normal');
149
+ return this.mode_toggle('normal');
144
150
  }
145
151
  /**
146
152
  * Set manual mode - adapter to set mode to normal
@@ -149,26 +155,12 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
149
155
  logger_1.logger.debug(`Setting manual mode for device: ${this.deviceName}`);
150
156
  return this.normal_mode();
151
157
  }
152
- /**
153
- * Set auto mode
154
- */
155
- async auto_mode() {
156
- logger_1.logger.debug(`Setting auto mode for device: ${this.deviceName}`);
157
- return this.modeToggle('auto');
158
- }
159
- /**
160
- * Set turbo mode
161
- */
162
- async turbo_mode() {
163
- logger_1.logger.debug(`Setting turbo mode for device: ${this.deviceName}`);
164
- return this.modeToggle('turbo');
165
- }
166
158
  /**
167
159
  * Set advanced sleep mode
168
160
  */
169
161
  async advanced_sleep_mode() {
170
162
  logger_1.logger.debug(`Setting advanced sleep mode for device: ${this.deviceName}`);
171
- return this.modeToggle('advancedSleep');
163
+ return this.mode_toggle('advancedSleep');
172
164
  }
173
165
  /**
174
166
  * Set sleep mode - adapter for advanced sleep mode
@@ -181,13 +173,7 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
181
173
  * Override setMode to handle tower fan specific modes
182
174
  */
183
175
  async setMode(mode) {
184
- return this.modeToggle(mode);
185
- }
186
- /**
187
- * Alias for modeToggle to match Python naming convention
188
- */
189
- async mode_toggle(mode) {
190
- return this.modeToggle(mode);
176
+ return this.mode_toggle(mode);
191
177
  }
192
178
  /**
193
179
  * Get current speed
@@ -213,12 +199,6 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
213
199
  get muteState() {
214
200
  return Boolean(this.details.muteState);
215
201
  }
216
- /**
217
- * Get mute switch status
218
- */
219
- get muteSwitch() {
220
- return Boolean(this.details.muteSwitch);
221
- }
222
202
  /**
223
203
  * Get temperature (in tenths of a degree)
224
204
  */
@@ -255,26 +235,6 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
255
235
  get errorCode() {
256
236
  return this.details.errorCode || 0;
257
237
  }
258
- /**
259
- * Set oscillation state
260
- */
261
- async setOscillation(state) {
262
- const [head, body] = this.buildApiDict('setSwitch');
263
- body.payload.data = {
264
- oscillationSwitch: state ? 1 : 0,
265
- switchIdx: 0
266
- };
267
- const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, head);
268
- const success = this.checkResponse([response, status], 'setOscillation');
269
- if (success) {
270
- this.details.oscillationSwitch = state ? 1 : 0;
271
- this.details.oscillationState = state ? 1 : 0;
272
- }
273
- else {
274
- logger_1.logger.debug('Error setting oscillation state');
275
- }
276
- return success;
277
- }
278
238
  /**
279
239
  * Turn oscillation on
280
240
  */
@@ -297,43 +257,20 @@ class VeSyncTowerFan extends airBaseV2_1.VeSyncAirBaseV2 {
297
257
  ['Speed: ', this.speed],
298
258
  ['Fan Speed Level: ', this.details.fanSpeedLevel || 0],
299
259
  ['Display: ', this.displayState],
260
+ ['Display Switch: ', this.details.screenSwitch],
300
261
  ['Oscillation: ', this.oscillationState],
301
- ['Timer: ', this.timer]
262
+ ['Oscillation Switch: ', this.details.oscillationSwitch],
263
+ ['Mute: ', this.muteState],
264
+ ['Mute Switch: ', this.details.muteSwitch],
265
+ ['Timer: ', this.timer],
266
+ ['Temperature: ', this.temperature / 10, '°C'],
267
+ ['Humidity: ', this.humidity, '%'],
268
+ ['Thermal Comfort: ', this.thermalComfort],
269
+ ['Sleep Preference: ', JSON.stringify(this.sleepPreference)],
270
+ ['Schedule Count: ', this.scheduleCount],
271
+ ['Displaying Type: ', this.details.displayingType],
272
+ ['Error Code: ', this.errorCode]
302
273
  ];
303
- // Add optional properties only if they exist
304
- if (this.details.screenSwitch !== undefined) {
305
- info.push(['Display Switch: ', this.details.screenSwitch]);
306
- }
307
- if (this.details.oscillationSwitch !== undefined) {
308
- info.push(['Oscillation Switch: ', this.details.oscillationSwitch]);
309
- }
310
- if (this.details.muteState !== undefined) {
311
- info.push(['Mute: ', this.muteState]);
312
- }
313
- if (this.details.muteSwitch !== undefined) {
314
- info.push(['Mute Switch: ', this.muteSwitch]);
315
- }
316
- if (this.temperature > 0) {
317
- info.push(['Temperature: ', this.temperature / 10, '°C']);
318
- }
319
- if (this.humidity > 0) {
320
- info.push(['Humidity: ', this.humidity, '%']);
321
- }
322
- if (this.thermalComfort > 0) {
323
- info.push(['Thermal Comfort: ', this.thermalComfort]);
324
- }
325
- if (this.sleepPreference && Object.keys(this.sleepPreference).length > 0) {
326
- info.push(['Sleep Preference: ', JSON.stringify(this.sleepPreference)]);
327
- }
328
- if (this.scheduleCount > 0) {
329
- info.push(['Schedule Count: ', this.scheduleCount]);
330
- }
331
- if (this.details.displayingType !== undefined) {
332
- info.push(['Displaying Type: ', this.details.displayingType]);
333
- }
334
- if (this.errorCode !== 0) {
335
- info.push(['Error Code: ', this.errorCode]);
336
- }
337
274
  for (const [key, value, unit = ''] of info) {
338
275
  logger_1.logger.info(`${key.toString().padEnd(30, '.')} ${value}${unit}`);
339
276
  }
@@ -165,25 +165,25 @@ exports.fanConfig = {
165
165
  features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
166
166
  levels: [1, 2, 3]
167
167
  },
168
- // LTF Series (Smart Tower Fan)
168
+ // LTF Series
169
169
  'LTF-F422S-KEU': {
170
170
  module: 'VeSyncTowerFan',
171
- features: ['fan_speed'],
171
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes'],
172
172
  levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
173
173
  },
174
174
  'LTF-F422S-WUSR': {
175
175
  module: 'VeSyncTowerFan',
176
- features: ['fan_speed'],
176
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes'],
177
177
  levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
178
178
  },
179
179
  'LTF-F422_WJP': {
180
180
  module: 'VeSyncTowerFan',
181
- features: ['fan_speed'],
181
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes'],
182
182
  levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
183
183
  },
184
184
  'LTF-F422S-WUS': {
185
185
  module: 'VeSyncTowerFan',
186
- features: ['fan_speed'],
186
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes'],
187
187
  levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
188
188
  },
189
189
  // Classic Series
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsvesync",
3
- "version": "1.0.78",
3
+ "version": "1.0.79",
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",
@@ -6,7 +6,7 @@ import { logger } from '../logger';
6
6
  * VeSync Tower Fan Implementation
7
7
  */
8
8
  export class VeSyncTowerFan extends VeSyncAirBaseV2 {
9
- protected readonly towerModes = ['normal', 'auto', 'advancedSleep', 'turbo', 'off'] as const;
9
+ protected readonly towerModes = ['normal', 'advancedSleep', 'off'] as const;
10
10
 
11
11
  constructor(details: Record<string, any>, manager: VeSync) {
12
12
  super(details, manager);
@@ -40,20 +40,26 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
40
40
  return false;
41
41
  }
42
42
 
43
- const innerResult = innerResponse.result;
44
-
45
- // Use the same methods as Python version
46
- if (innerResult) {
47
- this.buildPurifierDict(innerResult);
48
- } else {
49
- this.connectionStatus = 'offline';
50
- logger.debug('error in inner result dict from tower fan');
51
- return false;
52
- }
53
-
54
- if (innerResult.configuration) {
55
- this.buildConfigDict(innerResult.configuration);
56
- }
43
+ const deviceData = innerResponse.result;
44
+ this.deviceStatus = deviceData.powerSwitch === 1 ? 'on' : 'off';
45
+ this.details = {
46
+ powerSwitch: deviceData.powerSwitch,
47
+ workMode: deviceData.workMode,
48
+ manualSpeedLevel: deviceData.manualSpeedLevel,
49
+ fanSpeedLevel: deviceData.fanSpeedLevel,
50
+ screenState: deviceData.screenState,
51
+ screenSwitch: deviceData.screenSwitch,
52
+ oscillationState: deviceData.oscillationState,
53
+ oscillationSwitch: deviceData.oscillationSwitch,
54
+ timerRemain: deviceData.timerRemain,
55
+ temperature: deviceData.temperature || 0,
56
+ humidity: deviceData.humidity || 0,
57
+ thermalComfort: deviceData.thermalComfort,
58
+ sleepPreference: deviceData.sleepPreference || {},
59
+ scheduleCount: deviceData.scheduleCount,
60
+ displayingType: deviceData.displayingType,
61
+ errorCode: deviceData.errorCode
62
+ };
57
63
 
58
64
  logger.debug(`Successfully got details for device: ${this.deviceName}`);
59
65
  return true;
@@ -109,7 +115,7 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
109
115
  /**
110
116
  * Set tower fan mode
111
117
  */
112
- async modeToggle(mode: string): Promise<boolean> {
118
+ async mode_toggle(mode: string): Promise<boolean> {
113
119
  if (!this.towerModes.includes(mode as any)) {
114
120
  logger.debug(`Invalid mode: ${mode}. Must be one of: ${this.towerModes.join(', ')}`);
115
121
  return false;
@@ -145,11 +151,11 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
145
151
  * Change fan speed
146
152
  */
147
153
  async changeFanSpeed(speed: number): Promise<boolean> {
148
- const speeds = this.config.levels ?? [];
149
- if (!speeds.includes(speed)) {
150
- logger.debug(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')}`);
151
- return false;
152
- }
154
+ // const speeds = this.config.levels ?? [];
155
+ // if (!speeds.includes(speed)) {
156
+ // logger.debug(`Invalid speed: ${speed}. Must be one of: ${speeds.join(', ')}`);
157
+ // return false;
158
+ // }
153
159
 
154
160
  const [head, body] = this.buildApiDict('setLevel');
155
161
  body.payload.data = {
@@ -179,7 +185,7 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
179
185
  */
180
186
  async normal_mode(): Promise<boolean> {
181
187
  logger.debug(`Setting normal mode for device: ${this.deviceName}`);
182
- return this.modeToggle('normal');
188
+ return this.mode_toggle('normal');
183
189
  }
184
190
 
185
191
  /**
@@ -190,28 +196,12 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
190
196
  return this.normal_mode();
191
197
  }
192
198
 
193
- /**
194
- * Set auto mode
195
- */
196
- async auto_mode(): Promise<boolean> {
197
- logger.debug(`Setting auto mode for device: ${this.deviceName}`);
198
- return this.modeToggle('auto');
199
- }
200
-
201
- /**
202
- * Set turbo mode
203
- */
204
- async turbo_mode(): Promise<boolean> {
205
- logger.debug(`Setting turbo mode for device: ${this.deviceName}`);
206
- return this.modeToggle('turbo');
207
- }
208
-
209
199
  /**
210
200
  * Set advanced sleep mode
211
201
  */
212
202
  async advanced_sleep_mode(): Promise<boolean> {
213
203
  logger.debug(`Setting advanced sleep mode for device: ${this.deviceName}`);
214
- return this.modeToggle('advancedSleep');
204
+ return this.mode_toggle('advancedSleep');
215
205
  }
216
206
 
217
207
  /**
@@ -226,14 +216,7 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
226
216
  * Override setMode to handle tower fan specific modes
227
217
  */
228
218
  async setMode(mode: string): Promise<boolean> {
229
- return this.modeToggle(mode);
230
- }
231
-
232
- /**
233
- * Alias for modeToggle to match Python naming convention
234
- */
235
- async mode_toggle(mode: string): Promise<boolean> {
236
- return this.modeToggle(mode);
219
+ return this.mode_toggle(mode);
237
220
  }
238
221
 
239
222
  /**
@@ -264,13 +247,6 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
264
247
  return Boolean(this.details.muteState);
265
248
  }
266
249
 
267
- /**
268
- * Get mute switch status
269
- */
270
- get muteSwitch(): boolean {
271
- return Boolean(this.details.muteSwitch);
272
- }
273
-
274
250
  /**
275
251
  * Get temperature (in tenths of a degree)
276
252
  */
@@ -313,33 +289,6 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
313
289
  return this.details.errorCode || 0;
314
290
  }
315
291
 
316
- /**
317
- * Set oscillation state
318
- */
319
- async setOscillation(state: boolean): Promise<boolean> {
320
- const [head, body] = this.buildApiDict('setSwitch');
321
- body.payload.data = {
322
- oscillationSwitch: state ? 1 : 0,
323
- switchIdx: 0
324
- };
325
-
326
- const [response, status] = await this.callApi(
327
- '/cloud/v2/deviceManaged/bypassV2',
328
- 'post',
329
- body,
330
- head
331
- );
332
-
333
- const success = this.checkResponse([response, status], 'setOscillation');
334
- if (success) {
335
- this.details.oscillationSwitch = state ? 1 : 0;
336
- this.details.oscillationState = state ? 1 : 0;
337
- } else {
338
- logger.debug('Error setting oscillation state');
339
- }
340
- return success;
341
- }
342
-
343
292
  /**
344
293
  * Turn oscillation on
345
294
  */
@@ -359,50 +308,26 @@ export class VeSyncTowerFan extends VeSyncAirBaseV2 {
359
308
  */
360
309
  override display(): void {
361
310
  super.display();
362
- const info: Array<[string, any, string?]> = [
311
+ const info = [
363
312
  ['Mode: ', this.details.workMode || ''],
364
313
  ['Speed: ', this.speed],
365
314
  ['Fan Speed Level: ', this.details.fanSpeedLevel || 0],
366
315
  ['Display: ', this.displayState],
316
+ ['Display Switch: ', this.details.screenSwitch],
367
317
  ['Oscillation: ', this.oscillationState],
368
- ['Timer: ', this.timer]
318
+ ['Oscillation Switch: ', this.details.oscillationSwitch],
319
+ ['Mute: ', this.muteState],
320
+ ['Mute Switch: ', this.details.muteSwitch],
321
+ ['Timer: ', this.timer],
322
+ ['Temperature: ', this.temperature / 10, '°C'],
323
+ ['Humidity: ', this.humidity, '%'],
324
+ ['Thermal Comfort: ', this.thermalComfort],
325
+ ['Sleep Preference: ', JSON.stringify(this.sleepPreference)],
326
+ ['Schedule Count: ', this.scheduleCount],
327
+ ['Displaying Type: ', this.details.displayingType],
328
+ ['Error Code: ', this.errorCode]
369
329
  ];
370
330
 
371
- // Add optional properties only if they exist
372
- if (this.details.screenSwitch !== undefined) {
373
- info.push(['Display Switch: ', this.details.screenSwitch]);
374
- }
375
- if (this.details.oscillationSwitch !== undefined) {
376
- info.push(['Oscillation Switch: ', this.details.oscillationSwitch]);
377
- }
378
- if (this.details.muteState !== undefined) {
379
- info.push(['Mute: ', this.muteState]);
380
- }
381
- if (this.details.muteSwitch !== undefined) {
382
- info.push(['Mute Switch: ', this.muteSwitch]);
383
- }
384
- if (this.temperature > 0) {
385
- info.push(['Temperature: ', this.temperature / 10, '°C']);
386
- }
387
- if (this.humidity > 0) {
388
- info.push(['Humidity: ', this.humidity, '%']);
389
- }
390
- if (this.thermalComfort > 0) {
391
- info.push(['Thermal Comfort: ', this.thermalComfort]);
392
- }
393
- if (this.sleepPreference && Object.keys(this.sleepPreference).length > 0) {
394
- info.push(['Sleep Preference: ', JSON.stringify(this.sleepPreference)]);
395
- }
396
- if (this.scheduleCount > 0) {
397
- info.push(['Schedule Count: ', this.scheduleCount]);
398
- }
399
- if (this.details.displayingType !== undefined) {
400
- info.push(['Displaying Type: ', this.details.displayingType]);
401
- }
402
- if (this.errorCode !== 0) {
403
- info.push(['Error Code: ', this.errorCode]);
404
- }
405
-
406
331
  for (const [key, value, unit = ''] of info) {
407
332
  logger.info(`${key.toString().padEnd(30, '.')} ${value}${unit}`);
408
333
  }
@@ -175,25 +175,25 @@ export const fanConfig: FanConfig = {
175
175
  levels: [1, 2, 3]
176
176
  },
177
177
 
178
- // LTF Series (Smart Tower Fan)
178
+ // LTF Series
179
179
  'LTF-F422S-KEU': {
180
180
  module: 'VeSyncTowerFan',
181
- features: ['fan_speed'],
181
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes'],
182
182
  levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
183
183
  },
184
184
  'LTF-F422S-WUSR': {
185
185
  module: 'VeSyncTowerFan',
186
- features: ['fan_speed'],
186
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes'],
187
187
  levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
188
188
  },
189
189
  'LTF-F422_WJP': {
190
190
  module: 'VeSyncTowerFan',
191
- features: ['fan_speed'],
191
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes'],
192
192
  levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
193
193
  },
194
194
  'LTF-F422S-WUS': {
195
195
  module: 'VeSyncTowerFan',
196
- features: ['fan_speed'],
196
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes'],
197
197
  levels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
198
198
  },
199
199