tsvesync 1.3.13 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/fans/airBaseV2.d.ts +8 -0
- package/dist/lib/fans/airBaseV2.js +71 -8
- package/dist/lib/fans/airBypass.d.ts +1 -1
- package/dist/lib/fans/airBypass.js +37 -10
- package/dist/lib/vesyncFan.d.ts +30 -10
- package/dist/lib/vesyncFan.js +209 -64
- package/package.json +2 -1
- package/src/lib/fans/airBaseV2.ts +74 -8
- package/src/lib/fans/airBypass.ts +41 -10
- package/src/lib/vesyncFan.ts +231 -74
|
@@ -7,7 +7,9 @@ import { logger } from '../logger';
|
|
|
7
7
|
* VeSync Air Purifier with Bypass
|
|
8
8
|
*/
|
|
9
9
|
export class VeSyncAirBypass extends VeSyncFan {
|
|
10
|
-
protected
|
|
10
|
+
protected get modes(): ReadonlyArray<string> {
|
|
11
|
+
return this.getConfigModes(['auto', 'manual', 'sleep']);
|
|
12
|
+
}
|
|
11
13
|
protected readonly displayModes = ['on', 'off'] as const;
|
|
12
14
|
protected readonly childLockModes = ['on', 'off'] as const;
|
|
13
15
|
|
|
@@ -77,17 +79,33 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
77
79
|
}
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
// Parse air quality with fallback support for multiple API response formats
|
|
83
|
+
// Some devices (like Core 400S) may use PascalCase (AQLevel, PM25)
|
|
84
|
+
// while others use snake_case (air_quality, air_quality_value)
|
|
85
|
+
const airQualityLevel = result.air_quality || result.AQLevel || 0;
|
|
86
|
+
const airQualityValue = result.air_quality_value || result.PM25 || 0;
|
|
87
|
+
|
|
88
|
+
// Debug logging to diagnose air quality field availability
|
|
89
|
+
logger.debug(`${this.deviceName}: Air quality API response fields:`, {
|
|
90
|
+
air_quality: result.air_quality,
|
|
91
|
+
AQLevel: result.AQLevel,
|
|
92
|
+
air_quality_value: result.air_quality_value,
|
|
93
|
+
PM25: result.PM25,
|
|
94
|
+
parsed_level: airQualityLevel,
|
|
95
|
+
parsed_value: airQualityValue
|
|
96
|
+
});
|
|
97
|
+
|
|
80
98
|
this.details = {
|
|
81
99
|
mode: result.mode || '',
|
|
82
100
|
speed: result.level || 0,
|
|
83
101
|
filter_life: filterLife,
|
|
84
102
|
screen_status: result.display ? 'on' : 'off',
|
|
85
103
|
child_lock: result.child_lock || false,
|
|
86
|
-
air_quality:
|
|
87
|
-
air_quality_value:
|
|
104
|
+
air_quality: airQualityLevel,
|
|
105
|
+
air_quality_value: airQualityValue
|
|
88
106
|
};
|
|
89
107
|
|
|
90
|
-
const normalizedAirQuality = Helpers.normalizeAirQuality(
|
|
108
|
+
const normalizedAirQuality = Helpers.normalizeAirQuality(airQualityLevel);
|
|
91
109
|
if (normalizedAirQuality.level >= 1) {
|
|
92
110
|
this.details.air_quality_level = normalizedAirQuality.level;
|
|
93
111
|
}
|
|
@@ -98,6 +116,15 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
98
116
|
if ('PM10' in result) this.details.pm10 = result.PM10;
|
|
99
117
|
if ('AQPercent' in result) this.details.aq_percent = result.AQPercent;
|
|
100
118
|
|
|
119
|
+
// Debug log additional air quality fields for diagnostics
|
|
120
|
+
if (result.PM1 !== undefined || result.PM10 !== undefined || result.AQPercent !== undefined) {
|
|
121
|
+
logger.debug(`${this.deviceName}: Additional air quality data:`, {
|
|
122
|
+
PM1: result.PM1,
|
|
123
|
+
PM10: result.PM10,
|
|
124
|
+
AQPercent: result.AQPercent
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
101
128
|
// Don't overwrite config as it contains features array
|
|
102
129
|
if (result.configuration) {
|
|
103
130
|
this.details.configuration = result.configuration;
|
|
@@ -216,16 +243,20 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
216
243
|
* Set device mode
|
|
217
244
|
*/
|
|
218
245
|
async setMode(mode: string): Promise<boolean> {
|
|
219
|
-
|
|
246
|
+
const requested = mode.toLowerCase();
|
|
247
|
+
const supported = this.modes.map(m => m.toLowerCase());
|
|
248
|
+
const allowsCore200AutoFallback = this.deviceType.includes('Core200S') && requested === 'auto';
|
|
249
|
+
|
|
250
|
+
if (!supported.includes(requested) && !allowsCore200AutoFallback) {
|
|
220
251
|
const error = `Invalid mode: ${mode}. Must be one of: ${this.modes.join(', ')}`;
|
|
221
252
|
logger.error(`${error} for device: ${this.deviceName}`);
|
|
222
253
|
throw new Error(error);
|
|
223
254
|
}
|
|
224
255
|
|
|
225
|
-
logger.debug(`Setting mode to ${
|
|
256
|
+
logger.debug(`Setting mode to ${requested} for device: ${this.deviceName}`);
|
|
226
257
|
|
|
227
258
|
// Special handling for Core200S auto mode
|
|
228
|
-
if (
|
|
259
|
+
if (allowsCore200AutoFallback) {
|
|
229
260
|
// Core200S doesn't support auto mode, so we'll set it to manual mode
|
|
230
261
|
logger.warn(`Auto mode not supported for ${this.deviceType}, using manual mode instead`);
|
|
231
262
|
return this.setMode('manual');
|
|
@@ -241,7 +272,7 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
241
272
|
configModule: this.configModule,
|
|
242
273
|
payload: {
|
|
243
274
|
data: {
|
|
244
|
-
mode
|
|
275
|
+
mode: requested
|
|
245
276
|
},
|
|
246
277
|
method: 'setPurifierMode',
|
|
247
278
|
source: 'APP'
|
|
@@ -252,10 +283,10 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
252
283
|
|
|
253
284
|
const success = this.checkResponse([response, status], 'setMode');
|
|
254
285
|
if (success) {
|
|
255
|
-
this.details.mode =
|
|
286
|
+
this.details.mode = requested;
|
|
256
287
|
return true;
|
|
257
288
|
} else {
|
|
258
|
-
logger.error(`Failed to set mode to ${
|
|
289
|
+
logger.error(`Failed to set mode to ${requested} for device: ${this.deviceName}`);
|
|
259
290
|
return false;
|
|
260
291
|
}
|
|
261
292
|
}
|
package/src/lib/vesyncFan.ts
CHANGED
|
@@ -7,12 +7,16 @@ import { VeSync } from './vesync';
|
|
|
7
7
|
import { logger } from './logger';
|
|
8
8
|
import { Helpers } from './helpers';
|
|
9
9
|
|
|
10
|
+
interface FanConfigEntry {
|
|
11
|
+
module: 'VeSyncAirBypass' | 'VeSyncHumidifier' | 'VeSyncWarmHumidifier' | 'VeSyncTowerFan' | 'VeSyncAirBaseV2' | 'VeSyncSuperior6000S' | 'VeSyncHumid1000S' | 'VeSyncHumid200S' | 'VeSyncAir131';
|
|
12
|
+
features: string[];
|
|
13
|
+
levels?: number[];
|
|
14
|
+
modes?: ReadonlyArray<string>;
|
|
15
|
+
autoPreferences?: ReadonlyArray<string>;
|
|
16
|
+
}
|
|
17
|
+
|
|
10
18
|
interface FanConfig {
|
|
11
|
-
[key: string]:
|
|
12
|
-
module: 'VeSyncAirBypass' | 'VeSyncHumidifier' | 'VeSyncWarmHumidifier' | 'VeSyncTowerFan' | 'VeSyncAirBaseV2' | 'VeSyncSuperior6000S' | 'VeSyncHumid1000S' | 'VeSyncHumid200S' | 'VeSyncAir131';
|
|
13
|
-
features: string[];
|
|
14
|
-
levels?: number[];
|
|
15
|
-
};
|
|
19
|
+
[key: string]: FanConfigEntry;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
// Fan configuration
|
|
@@ -21,159 +25,218 @@ export const fanConfig: FanConfig = {
|
|
|
21
25
|
'Core200S': {
|
|
22
26
|
module: 'VeSyncAirBypass',
|
|
23
27
|
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'sleep_mode', 'filter_life'],
|
|
24
|
-
levels: [1, 2, 3, 4] // 4 levels including sleep mode, matching reference plugin
|
|
28
|
+
levels: [1, 2, 3, 4], // 4 levels including sleep mode, matching reference plugin
|
|
29
|
+
modes: ['sleep', 'manual']
|
|
25
30
|
},
|
|
26
31
|
'Core300S': {
|
|
27
32
|
module: 'VeSyncAirBypass',
|
|
28
33
|
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
29
|
-
levels: [1, 2, 3, 4]
|
|
34
|
+
levels: [1, 2, 3, 4],
|
|
35
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
36
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
30
37
|
},
|
|
31
38
|
'Core400S': {
|
|
32
39
|
module: 'VeSyncAirBypass',
|
|
33
40
|
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
34
|
-
levels: [1, 2, 3, 4]
|
|
41
|
+
levels: [1, 2, 3, 4],
|
|
42
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
43
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
35
44
|
},
|
|
36
45
|
'Core600S': {
|
|
37
46
|
module: 'VeSyncAirBypass',
|
|
38
47
|
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
39
|
-
levels: [1, 2, 3, 4]
|
|
48
|
+
levels: [1, 2, 3, 4],
|
|
49
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
50
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
40
51
|
},
|
|
41
52
|
|
|
42
53
|
// LAP Series
|
|
43
54
|
'LAP-C201S-AUSR': {
|
|
44
55
|
module: 'VeSyncAirBypass',
|
|
45
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', '
|
|
46
|
-
levels: [1, 2, 3]
|
|
56
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'sleep_mode', 'filter_life'],
|
|
57
|
+
levels: [1, 2, 3],
|
|
58
|
+
modes: ['sleep', 'manual']
|
|
47
59
|
},
|
|
48
60
|
'LAP-C202S-WUSR': {
|
|
49
61
|
module: 'VeSyncAirBypass',
|
|
50
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', '
|
|
51
|
-
levels: [1, 2, 3]
|
|
62
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'sleep_mode', 'filter_life'],
|
|
63
|
+
levels: [1, 2, 3],
|
|
64
|
+
modes: ['sleep', 'manual']
|
|
52
65
|
},
|
|
53
66
|
'LAP-C301S-WJP': {
|
|
54
67
|
module: 'VeSyncAirBypass',
|
|
55
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
56
|
-
levels: [1, 2, 3, 4]
|
|
68
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
69
|
+
levels: [1, 2, 3, 4],
|
|
70
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
71
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
57
72
|
},
|
|
58
73
|
'LAP-C302S-WUSB': {
|
|
59
74
|
module: 'VeSyncAirBypass',
|
|
60
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
61
|
-
levels: [1, 2, 3, 4]
|
|
75
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
76
|
+
levels: [1, 2, 3, 4],
|
|
77
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
78
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
62
79
|
},
|
|
63
80
|
'LAP-C301S-WAAA': {
|
|
64
81
|
module: 'VeSyncAirBypass',
|
|
65
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
66
|
-
levels: [1, 2, 3, 4]
|
|
82
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
83
|
+
levels: [1, 2, 3, 4],
|
|
84
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
85
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
67
86
|
},
|
|
68
87
|
'LAP-C401S-WJP': {
|
|
69
88
|
module: 'VeSyncAirBypass',
|
|
70
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
71
|
-
levels: [1, 2, 3, 4]
|
|
89
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
90
|
+
levels: [1, 2, 3, 4],
|
|
91
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
92
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
72
93
|
},
|
|
73
94
|
'LAP-C401S-WUSR': {
|
|
74
95
|
module: 'VeSyncAirBypass',
|
|
75
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
76
|
-
levels: [1, 2, 3, 4]
|
|
96
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
97
|
+
levels: [1, 2, 3, 4],
|
|
98
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
99
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
77
100
|
},
|
|
78
101
|
'LAP-C401S-WAAA': {
|
|
79
102
|
module: 'VeSyncAirBypass',
|
|
80
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
81
|
-
levels: [1, 2, 3, 4]
|
|
103
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
104
|
+
levels: [1, 2, 3, 4],
|
|
105
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
106
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
82
107
|
},
|
|
83
108
|
'LAP-C601S-WUS': {
|
|
84
109
|
module: 'VeSyncAirBypass',
|
|
85
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
86
|
-
levels: [1, 2, 3, 4]
|
|
110
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
111
|
+
levels: [1, 2, 3, 4],
|
|
112
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
113
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
87
114
|
},
|
|
88
115
|
'LAP-C601S-WUSR': {
|
|
89
116
|
module: 'VeSyncAirBypass',
|
|
90
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
91
|
-
levels: [1, 2, 3, 4]
|
|
117
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
118
|
+
levels: [1, 2, 3, 4],
|
|
119
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
120
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
92
121
|
},
|
|
93
122
|
'LAP-C601S-WEU': {
|
|
94
123
|
module: 'VeSyncAirBypass',
|
|
95
|
-
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
96
|
-
levels: [1, 2, 3, 4]
|
|
124
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
|
|
125
|
+
levels: [1, 2, 3, 4],
|
|
126
|
+
modes: ['sleep', 'manual', 'auto'],
|
|
127
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
97
128
|
},
|
|
98
129
|
'LAP-V102S-AASR': {
|
|
99
130
|
module: 'VeSyncAirBaseV2',
|
|
100
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
101
|
-
levels: [1, 2, 3, 4]
|
|
131
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
132
|
+
levels: [1, 2, 3, 4],
|
|
133
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
134
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
102
135
|
},
|
|
103
136
|
'LAP-V102S-WUS': {
|
|
104
137
|
module: 'VeSyncAirBaseV2',
|
|
105
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
106
|
-
levels: [1, 2, 3, 4]
|
|
138
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
139
|
+
levels: [1, 2, 3, 4],
|
|
140
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
141
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
107
142
|
},
|
|
108
143
|
'LAP-V102S-WEU': {
|
|
109
144
|
module: 'VeSyncAirBaseV2',
|
|
110
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
111
|
-
levels: [1, 2, 3, 4]
|
|
145
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
146
|
+
levels: [1, 2, 3, 4],
|
|
147
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
148
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
112
149
|
},
|
|
113
150
|
'LAP-V102S-AUSR': {
|
|
114
151
|
module: 'VeSyncAirBaseV2',
|
|
115
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
116
|
-
levels: [1, 2, 3, 4]
|
|
152
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
153
|
+
levels: [1, 2, 3, 4],
|
|
154
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
155
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
117
156
|
},
|
|
118
157
|
'LAP-V102S-WJP': {
|
|
119
158
|
module: 'VeSyncAirBaseV2',
|
|
120
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
121
|
-
levels: [1, 2, 3, 4]
|
|
159
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
160
|
+
levels: [1, 2, 3, 4],
|
|
161
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
162
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
122
163
|
},
|
|
123
164
|
'LAP-V201S-AASR': {
|
|
124
165
|
module: 'VeSyncAirBaseV2',
|
|
125
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
126
|
-
levels: [1, 2, 3, 4]
|
|
166
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
167
|
+
levels: [1, 2, 3, 4],
|
|
168
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
169
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
127
170
|
},
|
|
128
171
|
'LAP-V201S-WJP': {
|
|
129
172
|
module: 'VeSyncAirBaseV2',
|
|
130
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
131
|
-
levels: [1, 2, 3, 4]
|
|
173
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
174
|
+
levels: [1, 2, 3, 4],
|
|
175
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
176
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
132
177
|
},
|
|
133
178
|
'LAP-V201S-WEU': {
|
|
134
179
|
module: 'VeSyncAirBaseV2',
|
|
135
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
136
|
-
levels: [1, 2, 3, 4]
|
|
180
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
181
|
+
levels: [1, 2, 3, 4],
|
|
182
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
183
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
137
184
|
},
|
|
138
185
|
'LAP-V201S-WUS': {
|
|
139
186
|
module: 'VeSyncAirBaseV2',
|
|
140
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
141
|
-
levels: [1, 2, 3, 4]
|
|
187
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
188
|
+
levels: [1, 2, 3, 4],
|
|
189
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
190
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
142
191
|
},
|
|
143
192
|
'LAP-V201-AUSR': {
|
|
144
193
|
module: 'VeSyncAirBaseV2',
|
|
145
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
146
|
-
levels: [1, 2, 3, 4]
|
|
194
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
195
|
+
levels: [1, 2, 3, 4],
|
|
196
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
197
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
147
198
|
},
|
|
148
199
|
'LAP-V201S-AUSR': {
|
|
149
200
|
module: 'VeSyncAirBaseV2',
|
|
150
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
151
|
-
levels: [1, 2, 3, 4]
|
|
201
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
202
|
+
levels: [1, 2, 3, 4],
|
|
203
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
204
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
152
205
|
},
|
|
153
206
|
'LAP-V201S-AEUR': {
|
|
154
207
|
module: 'VeSyncAirBaseV2',
|
|
155
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
156
|
-
levels: [1, 2, 3, 4]
|
|
208
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'sleep_mode', 'pet_mode', 'filter_life'],
|
|
209
|
+
levels: [1, 2, 3, 4],
|
|
210
|
+
modes: ['sleep', 'manual', 'auto', 'pet'],
|
|
211
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
157
212
|
},
|
|
158
213
|
'LAP-EL551S-AUS': {
|
|
159
214
|
module: 'VeSyncAirBaseV2',
|
|
160
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
161
|
-
levels: [1, 2, 3]
|
|
215
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'sleep_mode', 'turbo_mode', 'light_detection', 'filter_life'],
|
|
216
|
+
levels: [1, 2, 3],
|
|
217
|
+
modes: ['sleep', 'manual', 'auto', 'turbo'],
|
|
218
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
162
219
|
},
|
|
163
220
|
'LAP-EL551S-AEUR': {
|
|
164
221
|
module: 'VeSyncAirBaseV2',
|
|
165
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
166
|
-
levels: [1, 2, 3]
|
|
222
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'sleep_mode', 'turbo_mode', 'light_detection', 'filter_life'],
|
|
223
|
+
levels: [1, 2, 3],
|
|
224
|
+
modes: ['sleep', 'manual', 'auto', 'turbo'],
|
|
225
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
167
226
|
},
|
|
168
227
|
'LAP-EL551S-WEU': {
|
|
169
228
|
module: 'VeSyncAirBaseV2',
|
|
170
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
171
|
-
levels: [1, 2, 3]
|
|
229
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'sleep_mode', 'turbo_mode', 'light_detection', 'filter_life'],
|
|
230
|
+
levels: [1, 2, 3],
|
|
231
|
+
modes: ['sleep', 'manual', 'auto', 'turbo'],
|
|
232
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
172
233
|
},
|
|
173
234
|
'LAP-EL551S-WUS': {
|
|
174
235
|
module: 'VeSyncAirBaseV2',
|
|
175
|
-
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
|
|
176
|
-
levels: [1, 2, 3]
|
|
236
|
+
features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'sleep_mode', 'turbo_mode', 'light_detection', 'filter_life'],
|
|
237
|
+
levels: [1, 2, 3],
|
|
238
|
+
modes: ['sleep', 'manual', 'auto', 'turbo'],
|
|
239
|
+
autoPreferences: ['default', 'efficient', 'quiet']
|
|
177
240
|
},
|
|
178
241
|
|
|
179
242
|
// LTF Series
|
|
@@ -342,20 +405,77 @@ export abstract class VeSyncFan extends VeSyncBaseDevice {
|
|
|
342
405
|
protected mode_dict: Record<string, any> = {};
|
|
343
406
|
protected speed_dict: Record<string, any> = {};
|
|
344
407
|
protected _timer: number | { duration: number; action: string } | null = null;
|
|
345
|
-
protected config:
|
|
346
|
-
module: 'VeSyncAirBypass' | 'VeSyncHumidifier' | 'VeSyncWarmHumidifier' | 'VeSyncTowerFan' | 'VeSyncAirBaseV2' | 'VeSyncSuperior6000S' | 'VeSyncHumid1000S' | 'VeSyncHumid200S' | 'VeSyncAir131';
|
|
347
|
-
features: string[];
|
|
348
|
-
levels?: number[];
|
|
349
|
-
};
|
|
408
|
+
protected config: FanConfigEntry;
|
|
350
409
|
|
|
351
410
|
constructor(details: Record<string, any>, manager: VeSync) {
|
|
352
411
|
super(details, manager);
|
|
353
412
|
this.details = details;
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
413
|
+
|
|
414
|
+
// Try exact match first
|
|
415
|
+
let entry: FanConfigEntry | undefined = fanConfig[this.deviceType];
|
|
416
|
+
|
|
417
|
+
// If no exact match, try substring matching for LAP variants
|
|
418
|
+
// This handles cases where device reports as "LAP-C401S-WUSR" but we only have "Core400S" config
|
|
419
|
+
if (!entry) {
|
|
420
|
+
entry = this.findConfigBySubstring(this.deviceType);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (entry) {
|
|
424
|
+
this.config = {
|
|
425
|
+
...entry,
|
|
426
|
+
features: [...entry.features],
|
|
427
|
+
levels: entry.levels ? [...entry.levels] : undefined,
|
|
428
|
+
modes: entry.modes ? [...entry.modes] : undefined,
|
|
429
|
+
autoPreferences: entry.autoPreferences ? [...entry.autoPreferences] : undefined
|
|
430
|
+
};
|
|
431
|
+
} else {
|
|
432
|
+
this.config = {
|
|
433
|
+
module: 'VeSyncAirBypass',
|
|
434
|
+
features: [],
|
|
435
|
+
levels: [],
|
|
436
|
+
modes: [],
|
|
437
|
+
autoPreferences: []
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Find config entry by substring matching for variant device types
|
|
444
|
+
* Maps LAP variants to their base model configs (e.g., LAP-C401S-WUSR → Core400S)
|
|
445
|
+
*/
|
|
446
|
+
private findConfigBySubstring(deviceType: string): FanConfigEntry | undefined {
|
|
447
|
+
// Define model number mappings
|
|
448
|
+
const modelMappings: Array<{ patterns: string[]; configKey: string }> = [
|
|
449
|
+
// Core series air purifiers
|
|
450
|
+
{ patterns: ['Core300S', '301S', '302S'], configKey: 'Core300S' },
|
|
451
|
+
{ patterns: ['Core400S', '401S'], configKey: 'Core400S' },
|
|
452
|
+
{ patterns: ['Core600S', '601S', '602S'], configKey: 'Core600S' },
|
|
453
|
+
{ patterns: ['Core200S', '201S', '202S'], configKey: 'Core200S' },
|
|
454
|
+
|
|
455
|
+
// Vital series
|
|
456
|
+
{ patterns: ['V102S'], configKey: 'LAP-V102S-AASR' },
|
|
457
|
+
{ patterns: ['V201S'], configKey: 'LAP-V201S-AASR' },
|
|
458
|
+
|
|
459
|
+
// LV-PUR series
|
|
460
|
+
{ patterns: ['LV-PUR131S', 'LV-RH131S'], configKey: 'LV-PUR131S' },
|
|
461
|
+
|
|
462
|
+
// Everest series
|
|
463
|
+
{ patterns: ['LAP-EL551S'], configKey: 'LAP-EL551S-AUS' },
|
|
464
|
+
];
|
|
465
|
+
|
|
466
|
+
// Check each mapping
|
|
467
|
+
for (const mapping of modelMappings) {
|
|
468
|
+
// If device type contains any of the patterns, use the config key
|
|
469
|
+
if (mapping.patterns.some(pattern => deviceType.includes(pattern))) {
|
|
470
|
+
const config = fanConfig[mapping.configKey];
|
|
471
|
+
if (config) {
|
|
472
|
+
logger.debug(`${deviceType}: Using fallback config from ${mapping.configKey} via substring match`);
|
|
473
|
+
return config;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return undefined;
|
|
359
479
|
}
|
|
360
480
|
|
|
361
481
|
/**
|
|
@@ -365,6 +485,40 @@ export abstract class VeSyncFan extends VeSyncBaseDevice {
|
|
|
365
485
|
return this.config.features.includes(feature);
|
|
366
486
|
}
|
|
367
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Get configured modes for the device, falling back to provided defaults.
|
|
490
|
+
*/
|
|
491
|
+
protected getConfigModes(defaultModes: ReadonlyArray<string> = []): ReadonlyArray<string> {
|
|
492
|
+
if (Array.isArray(this.config.modes) && this.config.modes.length > 0) {
|
|
493
|
+
return this.config.modes;
|
|
494
|
+
}
|
|
495
|
+
return defaultModes;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Get configured auto preferences for the device, falling back to provided defaults.
|
|
500
|
+
*/
|
|
501
|
+
protected getConfigAutoPreferences(defaultPreferences: ReadonlyArray<string> = []): ReadonlyArray<string> {
|
|
502
|
+
if (Array.isArray(this.config.autoPreferences) && this.config.autoPreferences.length > 0) {
|
|
503
|
+
return this.config.autoPreferences;
|
|
504
|
+
}
|
|
505
|
+
return defaultPreferences;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Public accessor for supported modes for consumers that need to inspect capability metadata.
|
|
510
|
+
*/
|
|
511
|
+
public getSupportedModes(defaultModes: ReadonlyArray<string> = []): ReadonlyArray<string> {
|
|
512
|
+
return this.getConfigModes(defaultModes);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Public accessor for supported auto preference profiles.
|
|
517
|
+
*/
|
|
518
|
+
public getSupportedAutoPreferences(defaultPreferences: ReadonlyArray<string> = []): ReadonlyArray<string> {
|
|
519
|
+
return this.getConfigAutoPreferences(defaultPreferences);
|
|
520
|
+
}
|
|
521
|
+
|
|
368
522
|
/**
|
|
369
523
|
* Check if feature is supported in current mode
|
|
370
524
|
*/
|
|
@@ -403,7 +557,10 @@ export abstract class VeSyncFan extends VeSyncBaseDevice {
|
|
|
403
557
|
* Get maximum fan speed level
|
|
404
558
|
*/
|
|
405
559
|
getMaxFanSpeed(): number {
|
|
406
|
-
|
|
560
|
+
if (this.config.levels && this.config.levels.length > 0) {
|
|
561
|
+
return Math.max(...this.config.levels);
|
|
562
|
+
}
|
|
563
|
+
return 3;
|
|
407
564
|
}
|
|
408
565
|
|
|
409
566
|
/**
|