tsvesync 1.0.91 → 1.0.93

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.
@@ -53,10 +53,35 @@ class VeSyncAir131 extends vesyncFan_1.VeSyncFan {
53
53
  // Check if data is in response.result or directly in response
54
54
  const data = response.result || response;
55
55
  this.deviceStatus = data.deviceStatus === 'on' ? 'on' : 'off';
56
+ // Parse filter life with proper object/value handling
57
+ let filterLife = 0;
58
+ if (data.filterLife !== undefined) {
59
+ if (typeof data.filterLife === 'object' && data.filterLife !== null) {
60
+ // API returns object like {percent: 85}
61
+ filterLife = data.filterLife;
62
+ logger_1.logger.debug(`${this.deviceName}: Parsed filter life from filterLife object: ${JSON.stringify(data.filterLife)}`);
63
+ }
64
+ else if (typeof data.filterLife === 'number') {
65
+ // API returns direct number
66
+ filterLife = data.filterLife;
67
+ logger_1.logger.debug(`${this.deviceName}: Parsed filter life from filterLife number: ${data.filterLife}%`);
68
+ }
69
+ }
70
+ else if (data.filter_life !== undefined) {
71
+ // Fallback to filter_life field
72
+ filterLife = data.filter_life;
73
+ logger_1.logger.debug(`${this.deviceName}: Parsed filter life from filter_life fallback: ${data.filter_life}%`);
74
+ }
75
+ else {
76
+ logger_1.logger.debug(`${this.deviceName}: No filter life data found in API response`);
77
+ if (logger_1.logger.getLevel && logger_1.logger.getLevel() !== undefined && logger_1.logger.getLevel() <= 0) {
78
+ logger_1.logger.debug(`${this.deviceName}: API response structure:`, JSON.stringify(data, null, 2));
79
+ }
80
+ }
56
81
  this.details = {
57
82
  mode: data.mode || 'manual', // Default to manual if not specified
58
83
  speed: data.level || 0,
59
- filter_life: data.filterLife || data.filter_life || 0,
84
+ filter_life: filterLife,
60
85
  screen_status: data.screenStatus || 'off',
61
86
  child_lock: data.childLock || false,
62
87
  air_quality: data.airQuality || 'unknown',
@@ -127,7 +127,7 @@ class VeSyncAirBaseV2 extends airBypass_1.VeSyncAirBypass {
127
127
  * Build purifier dictionary
128
128
  */
129
129
  buildPurifierDict(devDict) {
130
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
130
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
131
131
  this.connectionStatus = 'online';
132
132
  const powerSwitch = Boolean((_a = devDict.powerSwitch) !== null && _a !== void 0 ? _a : 0);
133
133
  this.enabled = powerSwitch;
@@ -135,19 +135,35 @@ class VeSyncAirBaseV2 extends airBypass_1.VeSyncAirBypass {
135
135
  this.mode = (_b = devDict.workMode) !== null && _b !== void 0 ? _b : 'manual';
136
136
  this.speed = (_c = devDict.fanSpeedLevel) !== null && _c !== void 0 ? _c : 0;
137
137
  this.setSpeedLevel = (_d = devDict.manualSpeedLevel) !== null && _d !== void 0 ? _d : 1;
138
+ // Parse filter life with proper fallback handling and logging
139
+ let filterLife = 0;
140
+ if (devDict.filterLifePercent !== undefined) {
141
+ filterLife = devDict.filterLifePercent;
142
+ logger_1.logger.debug(`${this.deviceName}: Parsed filter life from filterLifePercent: ${filterLife}%`);
143
+ }
144
+ else if (devDict.filter_life !== undefined) {
145
+ filterLife = devDict.filter_life;
146
+ logger_1.logger.debug(`${this.deviceName}: Parsed filter life from filter_life fallback: ${filterLife}%`);
147
+ }
148
+ else {
149
+ logger_1.logger.debug(`${this.deviceName}: No filter life data found in API response`);
150
+ if (logger_1.logger.getLevel && logger_1.logger.getLevel() !== undefined && logger_1.logger.getLevel() <= 0) {
151
+ logger_1.logger.debug(`${this.deviceName}: Device dict structure:`, JSON.stringify(devDict, null, 2));
152
+ }
153
+ }
138
154
  this.details = {
139
155
  ...this.details,
140
- filter_life: (_e = devDict.filterLifePercent) !== null && _e !== void 0 ? _e : 0,
141
- child_lock: Boolean((_f = devDict.childLockSwitch) !== null && _f !== void 0 ? _f : 0),
142
- display: Boolean((_g = devDict.screenState) !== null && _g !== void 0 ? _g : 0),
143
- light_detection_switch: Boolean((_h = devDict.lightDetectionSwitch) !== null && _h !== void 0 ? _h : 0),
144
- environment_light_state: Boolean((_j = devDict.environmentLightState) !== null && _j !== void 0 ? _j : 0),
145
- screen_switch: Boolean((_k = devDict.screenSwitch) !== null && _k !== void 0 ? _k : 0),
146
- screenStatus: Boolean((_l = devDict.screenSwitch) !== null && _l !== void 0 ? _l : 0) ? 'on' : 'off'
156
+ filter_life: filterLife,
157
+ child_lock: Boolean((_e = devDict.childLockSwitch) !== null && _e !== void 0 ? _e : 0),
158
+ display: Boolean((_f = devDict.screenState) !== null && _f !== void 0 ? _f : 0),
159
+ light_detection_switch: Boolean((_g = devDict.lightDetectionSwitch) !== null && _g !== void 0 ? _g : 0),
160
+ environment_light_state: Boolean((_h = devDict.environmentLightState) !== null && _h !== void 0 ? _h : 0),
161
+ screen_switch: Boolean((_j = devDict.screenSwitch) !== null && _j !== void 0 ? _j : 0),
162
+ screenStatus: Boolean((_k = devDict.screenSwitch) !== null && _k !== void 0 ? _k : 0) ? 'on' : 'off'
147
163
  };
148
164
  if (this.hasFeature('air_quality')) {
149
- this.details.air_quality_value = (_m = devDict.PM25) !== null && _m !== void 0 ? _m : 0;
150
- this.details.air_quality = (_o = devDict.AQLevel) !== null && _o !== void 0 ? _o : 0;
165
+ this.details.air_quality_value = (_l = devDict.PM25) !== null && _l !== void 0 ? _l : 0;
166
+ this.details.air_quality = (_m = devDict.AQLevel) !== null && _m !== void 0 ? _m : 0;
151
167
  }
152
168
  if ('PM1' in devDict)
153
169
  this.details.pm1 = devDict.PM1;
@@ -159,11 +175,11 @@ class VeSyncAirBaseV2 extends airBypass_1.VeSyncAirBypass {
159
175
  this.details.fan_rotate_angle = devDict.fanRotateAngle;
160
176
  if ('filterOpenState' in devDict)
161
177
  this.details.filter_open_state = Boolean(devDict.filterOpenState);
162
- if (((_p = devDict.timerRemain) !== null && _p !== void 0 ? _p : 0) > 0) {
178
+ if (((_o = devDict.timerRemain) !== null && _o !== void 0 ? _o : 0) > 0) {
163
179
  this.timer = { duration: devDict.timerRemain, action: 'off' };
164
180
  }
165
181
  if (typeof devDict.autoPreference === 'object' && devDict.autoPreference) {
166
- this.details.auto_preference_type = (_r = (_q = devDict.autoPreference) === null || _q === void 0 ? void 0 : _q.autoPreferenceType) !== null && _r !== void 0 ? _r : 'default';
182
+ this.details.auto_preference_type = (_q = (_p = devDict.autoPreference) === null || _p === void 0 ? void 0 : _p.autoPreferenceType) !== null && _q !== void 0 ? _q : 'default';
167
183
  }
168
184
  else {
169
185
  this.details.auto_preference_type = null;
@@ -53,10 +53,26 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
53
53
  const result = (_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.result;
54
54
  if (result) {
55
55
  this.deviceStatus = result.enabled ? 'on' : 'off';
56
+ // Parse filter life with fallback handling
57
+ let filterLife = 0;
58
+ if (result.filterLifePercent !== undefined) {
59
+ filterLife = result.filterLifePercent;
60
+ logger_1.logger.debug(`${this.deviceName}: Parsed filter life from filterLifePercent: ${filterLife}%`);
61
+ }
62
+ else if (result.filter_life !== undefined) {
63
+ filterLife = result.filter_life;
64
+ logger_1.logger.debug(`${this.deviceName}: Parsed filter life from filter_life: ${filterLife}%`);
65
+ }
66
+ else {
67
+ logger_1.logger.debug(`${this.deviceName}: No filter life data found in API response`);
68
+ if (logger_1.logger.getLevel && logger_1.logger.getLevel() !== undefined && logger_1.logger.getLevel() <= 0) {
69
+ logger_1.logger.debug(`${this.deviceName}: API response structure:`, JSON.stringify(result, null, 2));
70
+ }
71
+ }
56
72
  this.details = {
57
73
  mode: result.mode || '',
58
74
  speed: result.level || 0,
59
- filter_life: result.filter_life || 0,
75
+ filter_life: filterLife,
60
76
  screen_status: result.display ? 'on' : 'off',
61
77
  child_lock: result.child_lock || false,
62
78
  air_quality: result.air_quality || 0,
@@ -11,158 +11,158 @@ exports.fanConfig = {
11
11
  // Core Series
12
12
  'Core200S': {
13
13
  module: 'VeSyncAirBypass',
14
- features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'sleep_mode'],
14
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'sleep_mode', 'filter_life'],
15
15
  levels: [1, 2, 3]
16
16
  },
17
17
  'Core300S': {
18
18
  module: 'VeSyncAirBypass',
19
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
19
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
20
20
  levels: [1, 2, 3, 4]
21
21
  },
22
22
  'Core400S': {
23
23
  module: 'VeSyncAirBypass',
24
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
24
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
25
25
  levels: [1, 2, 3, 4]
26
26
  },
27
27
  'Core600S': {
28
28
  module: 'VeSyncAirBypass',
29
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
29
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
30
30
  levels: [1, 2, 3, 4]
31
31
  },
32
32
  // LAP Series
33
33
  'LAP-C201S-AUSR': {
34
34
  module: 'VeSyncAirBypass',
35
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
35
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
36
36
  levels: [1, 2, 3]
37
37
  },
38
38
  'LAP-C202S-WUSR': {
39
39
  module: 'VeSyncAirBypass',
40
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
40
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
41
41
  levels: [1, 2, 3]
42
42
  },
43
43
  'LAP-C301S-WJP': {
44
44
  module: 'VeSyncAirBypass',
45
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
45
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
46
46
  levels: [1, 2, 3, 4]
47
47
  },
48
48
  'LAP-C302S-WUSB': {
49
49
  module: 'VeSyncAirBypass',
50
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
50
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
51
51
  levels: [1, 2, 3, 4]
52
52
  },
53
53
  'LAP-C301S-WAAA': {
54
54
  module: 'VeSyncAirBypass',
55
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
55
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
56
56
  levels: [1, 2, 3, 4]
57
57
  },
58
58
  'LAP-C401S-WJP': {
59
59
  module: 'VeSyncAirBypass',
60
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
60
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
61
61
  levels: [1, 2, 3, 4]
62
62
  },
63
63
  'LAP-C401S-WUSR': {
64
64
  module: 'VeSyncAirBypass',
65
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
65
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
66
66
  levels: [1, 2, 3, 4]
67
67
  },
68
68
  'LAP-C401S-WAAA': {
69
69
  module: 'VeSyncAirBypass',
70
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
70
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
71
71
  levels: [1, 2, 3, 4]
72
72
  },
73
73
  'LAP-C601S-WUS': {
74
74
  module: 'VeSyncAirBypass',
75
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
75
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
76
76
  levels: [1, 2, 3, 4]
77
77
  },
78
78
  'LAP-C601S-WUSR': {
79
79
  module: 'VeSyncAirBypass',
80
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
80
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
81
81
  levels: [1, 2, 3, 4]
82
82
  },
83
83
  'LAP-C601S-WEU': {
84
84
  module: 'VeSyncAirBypass',
85
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
85
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
86
86
  levels: [1, 2, 3, 4]
87
87
  },
88
88
  'LAP-V102S-AASR': {
89
89
  module: 'VeSyncAirBaseV2',
90
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
90
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
91
91
  levels: [1, 2, 3, 4]
92
92
  },
93
93
  'LAP-V102S-WUS': {
94
94
  module: 'VeSyncAirBaseV2',
95
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
95
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
96
96
  levels: [1, 2, 3, 4]
97
97
  },
98
98
  'LAP-V102S-WEU': {
99
99
  module: 'VeSyncAirBaseV2',
100
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
100
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
101
101
  levels: [1, 2, 3, 4]
102
102
  },
103
103
  'LAP-V102S-AUSR': {
104
104
  module: 'VeSyncAirBaseV2',
105
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
105
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
106
106
  levels: [1, 2, 3, 4]
107
107
  },
108
108
  'LAP-V102S-WJP': {
109
109
  module: 'VeSyncAirBaseV2',
110
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
110
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
111
111
  levels: [1, 2, 3, 4]
112
112
  },
113
113
  'LAP-V201S-AASR': {
114
114
  module: 'VeSyncAirBaseV2',
115
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
115
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
116
116
  levels: [1, 2, 3, 4]
117
117
  },
118
118
  'LAP-V201S-WJP': {
119
119
  module: 'VeSyncAirBaseV2',
120
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
120
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
121
121
  levels: [1, 2, 3, 4]
122
122
  },
123
123
  'LAP-V201S-WEU': {
124
124
  module: 'VeSyncAirBaseV2',
125
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
125
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
126
126
  levels: [1, 2, 3, 4]
127
127
  },
128
128
  'LAP-V201S-WUS': {
129
129
  module: 'VeSyncAirBaseV2',
130
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
130
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
131
131
  levels: [1, 2, 3, 4]
132
132
  },
133
133
  'LAP-V201-AUSR': {
134
134
  module: 'VeSyncAirBaseV2',
135
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
135
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
136
136
  levels: [1, 2, 3, 4]
137
137
  },
138
138
  'LAP-V201S-AUSR': {
139
139
  module: 'VeSyncAirBaseV2',
140
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
140
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
141
141
  levels: [1, 2, 3, 4]
142
142
  },
143
143
  'LAP-V201S-AEUR': {
144
144
  module: 'VeSyncAirBaseV2',
145
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
145
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
146
146
  levels: [1, 2, 3, 4]
147
147
  },
148
148
  'LAP-EL551S-AUS': {
149
149
  module: 'VeSyncAirBaseV2',
150
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
150
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
151
151
  levels: [1, 2, 3]
152
152
  },
153
153
  'LAP-EL551S-AEUR': {
154
154
  module: 'VeSyncAirBaseV2',
155
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
155
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
156
156
  levels: [1, 2, 3]
157
157
  },
158
158
  'LAP-EL551S-WEU': {
159
159
  module: 'VeSyncAirBaseV2',
160
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
160
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
161
161
  levels: [1, 2, 3]
162
162
  },
163
163
  'LAP-EL551S-WUS': {
164
164
  module: 'VeSyncAirBaseV2',
165
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
165
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
166
166
  levels: [1, 2, 3]
167
167
  },
168
168
  // LTF Series
@@ -290,12 +290,12 @@ exports.fanConfig = {
290
290
  // LV Series
291
291
  'LV-PUR131S': {
292
292
  module: 'VeSyncAir131',
293
- features: ['air_quality', 'display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode'],
293
+ features: ['air_quality', 'display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
294
294
  levels: [1, 2, 3]
295
295
  },
296
296
  'LV-RH131S': {
297
297
  module: 'VeSyncAir131',
298
- features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode'],
298
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
299
299
  levels: [1, 2, 3]
300
300
  }
301
301
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsvesync",
3
- "version": "1.0.91",
3
+ "version": "1.0.93",
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",
@@ -64,10 +64,34 @@ export class VeSyncAir131 extends VeSyncFan {
64
64
  const data = response.result || response;
65
65
 
66
66
  this.deviceStatus = data.deviceStatus === 'on' ? 'on' : 'off';
67
+
68
+ // Parse filter life with proper object/value handling
69
+ let filterLife: number | { percent: number } = 0;
70
+ if (data.filterLife !== undefined) {
71
+ if (typeof data.filterLife === 'object' && data.filterLife !== null) {
72
+ // API returns object like {percent: 85}
73
+ filterLife = data.filterLife;
74
+ logger.debug(`${this.deviceName}: Parsed filter life from filterLife object: ${JSON.stringify(data.filterLife)}`);
75
+ } else if (typeof data.filterLife === 'number') {
76
+ // API returns direct number
77
+ filterLife = data.filterLife;
78
+ logger.debug(`${this.deviceName}: Parsed filter life from filterLife number: ${data.filterLife}%`);
79
+ }
80
+ } else if (data.filter_life !== undefined) {
81
+ // Fallback to filter_life field
82
+ filterLife = data.filter_life;
83
+ logger.debug(`${this.deviceName}: Parsed filter life from filter_life fallback: ${data.filter_life}%`);
84
+ } else {
85
+ logger.debug(`${this.deviceName}: No filter life data found in API response`);
86
+ if (logger.getLevel && logger.getLevel() !== undefined && logger.getLevel()! <= 0) {
87
+ logger.debug(`${this.deviceName}: API response structure:`, JSON.stringify(data, null, 2));
88
+ }
89
+ }
90
+
67
91
  this.details = {
68
92
  mode: data.mode || 'manual', // Default to manual if not specified
69
93
  speed: data.level || 0,
70
- filter_life: data.filterLife || data.filter_life || 0,
94
+ filter_life: filterLife,
71
95
  screen_status: data.screenStatus || 'off',
72
96
  child_lock: data.childLock || false,
73
97
  air_quality: data.airQuality || 'unknown',
@@ -163,9 +163,24 @@ export class VeSyncAirBaseV2 extends VeSyncAirBypass {
163
163
  this.speed = devDict.fanSpeedLevel ?? 0;
164
164
  this.setSpeedLevel = devDict.manualSpeedLevel ?? 1;
165
165
 
166
+ // Parse filter life with proper fallback handling and logging
167
+ let filterLife = 0;
168
+ if (devDict.filterLifePercent !== undefined) {
169
+ filterLife = devDict.filterLifePercent;
170
+ logger.debug(`${this.deviceName}: Parsed filter life from filterLifePercent: ${filterLife}%`);
171
+ } else if (devDict.filter_life !== undefined) {
172
+ filterLife = devDict.filter_life;
173
+ logger.debug(`${this.deviceName}: Parsed filter life from filter_life fallback: ${filterLife}%`);
174
+ } else {
175
+ logger.debug(`${this.deviceName}: No filter life data found in API response`);
176
+ if (logger.getLevel && logger.getLevel() !== undefined && logger.getLevel()! <= 0) {
177
+ logger.debug(`${this.deviceName}: Device dict structure:`, JSON.stringify(devDict, null, 2));
178
+ }
179
+ }
180
+
166
181
  this.details = {
167
182
  ...this.details,
168
- filter_life: devDict.filterLifePercent ?? 0,
183
+ filter_life: filterLife,
169
184
  child_lock: Boolean(devDict.childLockSwitch ?? 0),
170
185
  display: Boolean(devDict.screenState ?? 0),
171
186
  light_detection_switch: Boolean(devDict.lightDetectionSwitch ?? 0),
@@ -61,10 +61,26 @@ export class VeSyncAirBypass extends VeSyncFan {
61
61
  const result = response?.result?.result;
62
62
  if (result) {
63
63
  this.deviceStatus = result.enabled ? 'on' : 'off';
64
+
65
+ // Parse filter life with fallback handling
66
+ let filterLife = 0;
67
+ if (result.filterLifePercent !== undefined) {
68
+ filterLife = result.filterLifePercent;
69
+ logger.debug(`${this.deviceName}: Parsed filter life from filterLifePercent: ${filterLife}%`);
70
+ } else if (result.filter_life !== undefined) {
71
+ filterLife = result.filter_life;
72
+ logger.debug(`${this.deviceName}: Parsed filter life from filter_life: ${filterLife}%`);
73
+ } else {
74
+ logger.debug(`${this.deviceName}: No filter life data found in API response`);
75
+ if (logger.getLevel && logger.getLevel() !== undefined && logger.getLevel()! <= 0) {
76
+ logger.debug(`${this.deviceName}: API response structure:`, JSON.stringify(result, null, 2));
77
+ }
78
+ }
79
+
64
80
  this.details = {
65
81
  mode: result.mode || '',
66
82
  speed: result.level || 0,
67
- filter_life: result.filter_life || 0,
83
+ filter_life: filterLife,
68
84
  screen_status: result.display ? 'on' : 'off',
69
85
  child_lock: result.child_lock || false,
70
86
  air_quality: result.air_quality || 0,
@@ -19,159 +19,159 @@ export const fanConfig: FanConfig = {
19
19
  // Core Series
20
20
  'Core200S': {
21
21
  module: 'VeSyncAirBypass',
22
- features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'sleep_mode'],
22
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'sleep_mode', 'filter_life'],
23
23
  levels: [1, 2, 3]
24
24
  },
25
25
  'Core300S': {
26
26
  module: 'VeSyncAirBypass',
27
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
27
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
28
28
  levels: [1, 2, 3, 4]
29
29
  },
30
30
  'Core400S': {
31
31
  module: 'VeSyncAirBypass',
32
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
32
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
33
33
  levels: [1, 2, 3, 4]
34
34
  },
35
35
  'Core600S': {
36
36
  module: 'VeSyncAirBypass',
37
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
37
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
38
38
  levels: [1, 2, 3, 4]
39
39
  },
40
40
 
41
41
  // LAP Series
42
42
  'LAP-C201S-AUSR': {
43
43
  module: 'VeSyncAirBypass',
44
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
44
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
45
45
  levels: [1, 2, 3]
46
46
  },
47
47
  'LAP-C202S-WUSR': {
48
48
  module: 'VeSyncAirBypass',
49
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
49
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
50
50
  levels: [1, 2, 3]
51
51
  },
52
52
  'LAP-C301S-WJP': {
53
53
  module: 'VeSyncAirBypass',
54
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
54
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
55
55
  levels: [1, 2, 3, 4]
56
56
  },
57
57
  'LAP-C302S-WUSB': {
58
58
  module: 'VeSyncAirBypass',
59
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
59
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
60
60
  levels: [1, 2, 3, 4]
61
61
  },
62
62
  'LAP-C301S-WAAA': {
63
63
  module: 'VeSyncAirBypass',
64
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
64
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
65
65
  levels: [1, 2, 3, 4]
66
66
  },
67
67
  'LAP-C401S-WJP': {
68
68
  module: 'VeSyncAirBypass',
69
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
69
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
70
70
  levels: [1, 2, 3, 4]
71
71
  },
72
72
  'LAP-C401S-WUSR': {
73
73
  module: 'VeSyncAirBypass',
74
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
74
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
75
75
  levels: [1, 2, 3, 4]
76
76
  },
77
77
  'LAP-C401S-WAAA': {
78
78
  module: 'VeSyncAirBypass',
79
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
79
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
80
80
  levels: [1, 2, 3, 4]
81
81
  },
82
82
  'LAP-C601S-WUS': {
83
83
  module: 'VeSyncAirBypass',
84
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
84
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
85
85
  levels: [1, 2, 3, 4]
86
86
  },
87
87
  'LAP-C601S-WUSR': {
88
88
  module: 'VeSyncAirBypass',
89
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
89
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
90
90
  levels: [1, 2, 3, 4]
91
91
  },
92
92
  'LAP-C601S-WEU': {
93
93
  module: 'VeSyncAirBypass',
94
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode'],
94
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'sleep_mode', 'filter_life'],
95
95
  levels: [1, 2, 3, 4]
96
96
  },
97
97
  'LAP-V102S-AASR': {
98
98
  module: 'VeSyncAirBaseV2',
99
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
99
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
100
100
  levels: [1, 2, 3, 4]
101
101
  },
102
102
  'LAP-V102S-WUS': {
103
103
  module: 'VeSyncAirBaseV2',
104
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
104
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
105
105
  levels: [1, 2, 3, 4]
106
106
  },
107
107
  'LAP-V102S-WEU': {
108
108
  module: 'VeSyncAirBaseV2',
109
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
109
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
110
110
  levels: [1, 2, 3, 4]
111
111
  },
112
112
  'LAP-V102S-AUSR': {
113
113
  module: 'VeSyncAirBaseV2',
114
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
114
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
115
115
  levels: [1, 2, 3, 4]
116
116
  },
117
117
  'LAP-V102S-WJP': {
118
118
  module: 'VeSyncAirBaseV2',
119
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode'],
119
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
120
120
  levels: [1, 2, 3, 4]
121
121
  },
122
122
  'LAP-V201S-AASR': {
123
123
  module: 'VeSyncAirBaseV2',
124
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
124
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
125
125
  levels: [1, 2, 3, 4]
126
126
  },
127
127
  'LAP-V201S-WJP': {
128
128
  module: 'VeSyncAirBaseV2',
129
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
129
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
130
130
  levels: [1, 2, 3, 4]
131
131
  },
132
132
  'LAP-V201S-WEU': {
133
133
  module: 'VeSyncAirBaseV2',
134
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
134
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
135
135
  levels: [1, 2, 3, 4]
136
136
  },
137
137
  'LAP-V201S-WUS': {
138
138
  module: 'VeSyncAirBaseV2',
139
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
139
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
140
140
  levels: [1, 2, 3, 4]
141
141
  },
142
142
  'LAP-V201-AUSR': {
143
143
  module: 'VeSyncAirBaseV2',
144
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
144
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
145
145
  levels: [1, 2, 3, 4]
146
146
  },
147
147
  'LAP-V201S-AUSR': {
148
148
  module: 'VeSyncAirBaseV2',
149
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
149
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
150
150
  levels: [1, 2, 3, 4]
151
151
  },
152
152
  'LAP-V201S-AEUR': {
153
153
  module: 'VeSyncAirBaseV2',
154
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode'],
154
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'light_detection', 'fan_speed', 'auto_mode', 'filter_life'],
155
155
  levels: [1, 2, 3, 4]
156
156
  },
157
157
  'LAP-EL551S-AUS': {
158
158
  module: 'VeSyncAirBaseV2',
159
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
159
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
160
160
  levels: [1, 2, 3]
161
161
  },
162
162
  'LAP-EL551S-AEUR': {
163
163
  module: 'VeSyncAirBaseV2',
164
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
164
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
165
165
  levels: [1, 2, 3]
166
166
  },
167
167
  'LAP-EL551S-WEU': {
168
168
  module: 'VeSyncAirBaseV2',
169
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
169
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
170
170
  levels: [1, 2, 3]
171
171
  },
172
172
  'LAP-EL551S-WUS': {
173
173
  module: 'VeSyncAirBaseV2',
174
- features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode'],
174
+ features: ['display', 'child_lock', 'night_light', 'air_quality', 'timer', 'fan_rotate', 'fan_speed', 'auto_mode', 'filter_life'],
175
175
  levels: [1, 2, 3]
176
176
  },
177
177
 
@@ -305,12 +305,12 @@ export const fanConfig: FanConfig = {
305
305
  // LV Series
306
306
  'LV-PUR131S': {
307
307
  module: 'VeSyncAir131',
308
- features: ['air_quality', 'display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode'],
308
+ features: ['air_quality', 'display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
309
309
  levels: [1, 2, 3]
310
310
  },
311
311
  'LV-RH131S': {
312
312
  module: 'VeSyncAir131',
313
- features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode'],
313
+ features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speed', 'auto_mode', 'filter_life'],
314
314
  levels: [1, 2, 3]
315
315
  }
316
316
  };