tsvesync 1.0.37 → 1.0.38
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/vesyncFan.d.ts +1 -1
- package/dist/lib/vesyncFan.js +8 -8
- package/dist/lib/vesyncFanImpl.d.ts +104 -0
- package/dist/lib/vesyncFanImpl.js +330 -5
- package/package.json +1 -1
- package/src/lib/vesyncFan.ts +9 -9
- package/src/lib/vesyncFanImpl.ts +411 -4
package/dist/lib/vesyncFan.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { VeSyncBaseDevice } from './vesyncBaseDevice';
|
|
|
5
5
|
import { VeSync } from './vesync';
|
|
6
6
|
interface FanConfig {
|
|
7
7
|
[key: string]: {
|
|
8
|
-
module: 'VeSyncAirBypass' | 'VeSyncHumidifier' | 'VeSyncWarmHumidifier';
|
|
8
|
+
module: 'VeSyncAirBypass' | 'VeSyncHumidifier' | 'VeSyncWarmHumidifier' | 'VeSyncTowerFan';
|
|
9
9
|
features: string[];
|
|
10
10
|
};
|
|
11
11
|
}
|
package/dist/lib/vesyncFan.js
CHANGED
|
@@ -136,20 +136,20 @@ exports.fanConfig = {
|
|
|
136
136
|
},
|
|
137
137
|
// LTF Series
|
|
138
138
|
'LTF-F422S-KEU': {
|
|
139
|
-
module: '
|
|
140
|
-
features: ['display', 'child_lock', 'night_light', 'timer']
|
|
139
|
+
module: 'VeSyncTowerFan',
|
|
140
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes']
|
|
141
141
|
},
|
|
142
142
|
'LTF-F422S-WUSR': {
|
|
143
|
-
module: '
|
|
144
|
-
features: ['display', 'child_lock', 'night_light', 'timer']
|
|
143
|
+
module: 'VeSyncTowerFan',
|
|
144
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes']
|
|
145
145
|
},
|
|
146
146
|
'LTF-F422_WJP': {
|
|
147
|
-
module: '
|
|
148
|
-
features: ['display', 'child_lock', 'night_light', 'timer']
|
|
147
|
+
module: 'VeSyncTowerFan',
|
|
148
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes']
|
|
149
149
|
},
|
|
150
150
|
'LTF-F422S-WUS': {
|
|
151
|
-
module: '
|
|
152
|
-
features: ['display', 'child_lock', 'night_light', 'timer']
|
|
151
|
+
module: 'VeSyncTowerFan',
|
|
152
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes']
|
|
153
153
|
},
|
|
154
154
|
// Classic Series
|
|
155
155
|
'Classic300S': {
|
|
@@ -209,4 +209,108 @@ export declare class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
209
209
|
*/
|
|
210
210
|
get dryingModeSecondsRemaining(): number;
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* VeSync Air Purifier with Bypass V2
|
|
214
|
+
*/
|
|
215
|
+
export declare class VeSyncAirBaseV2 extends VeSyncAirBypass {
|
|
216
|
+
protected _lightDetection: boolean;
|
|
217
|
+
protected _lightDetectionState: boolean;
|
|
218
|
+
constructor(details: Record<string, any>, manager: VeSync);
|
|
219
|
+
/**
|
|
220
|
+
* Build API dictionary
|
|
221
|
+
*/
|
|
222
|
+
protected buildApiDict(method: string): [Record<string, any>, Record<string, any>];
|
|
223
|
+
get lightDetection(): boolean;
|
|
224
|
+
set lightDetection(toggle: boolean);
|
|
225
|
+
get lightDetectionState(): boolean;
|
|
226
|
+
setLightDetection(toggle: boolean): Promise<boolean>;
|
|
227
|
+
setLightDetectionOn(): Promise<boolean>;
|
|
228
|
+
setLightDetectionOff(): Promise<boolean>;
|
|
229
|
+
turboMode(): Promise<boolean>;
|
|
230
|
+
petMode(): Promise<boolean>;
|
|
231
|
+
/**
|
|
232
|
+
* Build configuration dictionary
|
|
233
|
+
*/
|
|
234
|
+
protected buildConfigDict(configDict: Record<string, any>): void;
|
|
235
|
+
/**
|
|
236
|
+
* Set mode
|
|
237
|
+
*/
|
|
238
|
+
protected mode_toggle(mode: string): Promise<boolean>;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* VeSync Tower Fan Implementation
|
|
242
|
+
*/
|
|
243
|
+
export declare class VeSyncTowerFan extends VeSyncAirBaseV2 {
|
|
244
|
+
protected readonly towerModes: readonly ["normal", "advancedSleep", "off"];
|
|
245
|
+
protected readonly speeds: number[];
|
|
246
|
+
constructor(details: Record<string, any>, manager: VeSync);
|
|
247
|
+
/**
|
|
248
|
+
* Get device details
|
|
249
|
+
*/
|
|
250
|
+
getDetails(): Promise<Boolean>;
|
|
251
|
+
/**
|
|
252
|
+
* Change fan speed
|
|
253
|
+
*/
|
|
254
|
+
changeFanSpeed(speed: number): Promise<boolean>;
|
|
255
|
+
/**
|
|
256
|
+
* Toggle device power
|
|
257
|
+
*/
|
|
258
|
+
toggleSwitch(toggle: boolean): Promise<boolean>;
|
|
259
|
+
/**
|
|
260
|
+
* Turn device on
|
|
261
|
+
*/
|
|
262
|
+
turnOn(): Promise<boolean>;
|
|
263
|
+
/**
|
|
264
|
+
* Turn device off
|
|
265
|
+
*/
|
|
266
|
+
turnOff(): Promise<boolean>;
|
|
267
|
+
/**
|
|
268
|
+
* Set tower fan mode
|
|
269
|
+
*/
|
|
270
|
+
mode_toggle(mode: string): Promise<boolean>;
|
|
271
|
+
/**
|
|
272
|
+
* Set normal mode
|
|
273
|
+
*/
|
|
274
|
+
normal_mode(): Promise<boolean>;
|
|
275
|
+
/**
|
|
276
|
+
* Set manual mode - adapter to set mode to normal
|
|
277
|
+
*/
|
|
278
|
+
manual_mode(): Promise<boolean>;
|
|
279
|
+
/**
|
|
280
|
+
* Set advanced sleep mode
|
|
281
|
+
*/
|
|
282
|
+
advanced_sleep_mode(): Promise<boolean>;
|
|
283
|
+
/**
|
|
284
|
+
* Set sleep mode - adapter for advanced sleep mode
|
|
285
|
+
*/
|
|
286
|
+
sleep_mode(): Promise<boolean>;
|
|
287
|
+
/**
|
|
288
|
+
* Override setMode to handle tower fan specific modes
|
|
289
|
+
*/
|
|
290
|
+
setMode(mode: string): Promise<boolean>;
|
|
291
|
+
/**
|
|
292
|
+
* Get current speed
|
|
293
|
+
*/
|
|
294
|
+
get speed(): number;
|
|
295
|
+
/**
|
|
296
|
+
* Get display status
|
|
297
|
+
*/
|
|
298
|
+
get displayState(): boolean;
|
|
299
|
+
/**
|
|
300
|
+
* Get child lock status
|
|
301
|
+
*/
|
|
302
|
+
get childLock(): string;
|
|
303
|
+
/**
|
|
304
|
+
* Get night light status
|
|
305
|
+
*/
|
|
306
|
+
get nightLight(): string;
|
|
307
|
+
/**
|
|
308
|
+
* Get timer status
|
|
309
|
+
*/
|
|
310
|
+
get timer(): number;
|
|
311
|
+
/**
|
|
312
|
+
* Display device info
|
|
313
|
+
*/
|
|
314
|
+
display(): void;
|
|
315
|
+
}
|
|
212
316
|
export declare const fanModules: Record<string, new (details: Record<string, any>, manager: VeSync) => VeSyncFan>;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* VeSync Fan Implementations
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.fanModules = exports.VeSyncWarmHumidifier = exports.VeSyncHumidifier = exports.VeSyncAirBypass = void 0;
|
|
6
|
+
exports.fanModules = exports.VeSyncTowerFan = exports.VeSyncAirBaseV2 = exports.VeSyncWarmHumidifier = exports.VeSyncHumidifier = exports.VeSyncAirBypass = void 0;
|
|
7
7
|
const vesyncFan_1 = require("./vesyncFan");
|
|
8
8
|
const helpers_1 = require("./helpers");
|
|
9
9
|
const logger_1 = require("./logger");
|
|
@@ -1027,6 +1027,331 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1027
1027
|
}
|
|
1028
1028
|
}
|
|
1029
1029
|
exports.VeSyncWarmHumidifier = VeSyncWarmHumidifier;
|
|
1030
|
+
/**
|
|
1031
|
+
* VeSync Air Purifier with Bypass V2
|
|
1032
|
+
*/
|
|
1033
|
+
class VeSyncAirBaseV2 extends VeSyncAirBypass {
|
|
1034
|
+
constructor(details, manager) {
|
|
1035
|
+
super(details, manager);
|
|
1036
|
+
this._lightDetection = false;
|
|
1037
|
+
this._lightDetectionState = false;
|
|
1038
|
+
logger_1.logger.debug(`Initialized VeSyncAirBaseV2 device: ${this.deviceName}`);
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* Build API dictionary
|
|
1042
|
+
*/
|
|
1043
|
+
buildApiDict(method) {
|
|
1044
|
+
const head = helpers_1.Helpers.reqHeaderBypass();
|
|
1045
|
+
const body = {
|
|
1046
|
+
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
1047
|
+
deviceId: this.cid,
|
|
1048
|
+
configModule: this.configModule,
|
|
1049
|
+
payload: {
|
|
1050
|
+
method,
|
|
1051
|
+
source: 'APP',
|
|
1052
|
+
data: {}
|
|
1053
|
+
}
|
|
1054
|
+
};
|
|
1055
|
+
return [head, body];
|
|
1056
|
+
}
|
|
1057
|
+
get lightDetection() {
|
|
1058
|
+
return this._lightDetection;
|
|
1059
|
+
}
|
|
1060
|
+
set lightDetection(toggle) {
|
|
1061
|
+
this._lightDetection = toggle;
|
|
1062
|
+
}
|
|
1063
|
+
get lightDetectionState() {
|
|
1064
|
+
return this._lightDetectionState;
|
|
1065
|
+
}
|
|
1066
|
+
async setLightDetection(toggle) {
|
|
1067
|
+
const [head, body] = this.buildApiDict('setLightDetection');
|
|
1068
|
+
if (!head || !body) {
|
|
1069
|
+
return false;
|
|
1070
|
+
}
|
|
1071
|
+
body.payload.data = { enabled: toggle };
|
|
1072
|
+
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, head);
|
|
1073
|
+
const success = this.checkResponse([response, status], 'setLightDetection');
|
|
1074
|
+
if (success) {
|
|
1075
|
+
this._lightDetection = toggle;
|
|
1076
|
+
}
|
|
1077
|
+
return success;
|
|
1078
|
+
}
|
|
1079
|
+
async setLightDetectionOn() {
|
|
1080
|
+
return this.setLightDetection(true);
|
|
1081
|
+
}
|
|
1082
|
+
async setLightDetectionOff() {
|
|
1083
|
+
return this.setLightDetection(false);
|
|
1084
|
+
}
|
|
1085
|
+
async turboMode() {
|
|
1086
|
+
return this.mode_toggle('turbo');
|
|
1087
|
+
}
|
|
1088
|
+
async petMode() {
|
|
1089
|
+
return this.mode_toggle('pet');
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Build configuration dictionary
|
|
1093
|
+
*/
|
|
1094
|
+
buildConfigDict(configDict) {
|
|
1095
|
+
if (configDict) {
|
|
1096
|
+
this.config = configDict;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* Set mode
|
|
1101
|
+
*/
|
|
1102
|
+
async mode_toggle(mode) {
|
|
1103
|
+
const validModes = this.modes.map(m => m.toLowerCase());
|
|
1104
|
+
if (!validModes.includes(mode.toLowerCase())) {
|
|
1105
|
+
logger_1.logger.debug(`Invalid mode used - ${mode}`);
|
|
1106
|
+
return false;
|
|
1107
|
+
}
|
|
1108
|
+
const [head, body] = this.buildApiDict('setPurifierMode');
|
|
1109
|
+
if (!head || !body) {
|
|
1110
|
+
return false;
|
|
1111
|
+
}
|
|
1112
|
+
body.payload.data = {
|
|
1113
|
+
mode: mode
|
|
1114
|
+
};
|
|
1115
|
+
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, head);
|
|
1116
|
+
const success = this.checkResponse([response, status], 'mode_toggle');
|
|
1117
|
+
if (success) {
|
|
1118
|
+
this.details.mode = mode;
|
|
1119
|
+
}
|
|
1120
|
+
else {
|
|
1121
|
+
logger_1.logger.debug('Error setting mode');
|
|
1122
|
+
}
|
|
1123
|
+
return success;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
exports.VeSyncAirBaseV2 = VeSyncAirBaseV2;
|
|
1127
|
+
/**
|
|
1128
|
+
* VeSync Tower Fan Implementation
|
|
1129
|
+
*/
|
|
1130
|
+
class VeSyncTowerFan extends VeSyncAirBaseV2 {
|
|
1131
|
+
constructor(details, manager) {
|
|
1132
|
+
super(details, manager);
|
|
1133
|
+
this.towerModes = ['normal', 'advancedSleep', 'off'];
|
|
1134
|
+
this.speeds = Array.from({ length: 12 }, (_, i) => i + 1);
|
|
1135
|
+
logger_1.logger.debug(`Initialized VeSyncTowerFan device: ${this.deviceName}`);
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Get device details
|
|
1139
|
+
*/
|
|
1140
|
+
async getDetails() {
|
|
1141
|
+
var _a;
|
|
1142
|
+
logger_1.logger.debug(`Getting details for device: ${this.deviceName}`);
|
|
1143
|
+
const [head, body] = this.buildApiDict('getTowerFanStatus');
|
|
1144
|
+
if (!head || !body) {
|
|
1145
|
+
logger_1.logger.debug('Error building API request');
|
|
1146
|
+
return false;
|
|
1147
|
+
}
|
|
1148
|
+
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, head);
|
|
1149
|
+
if (!this.checkResponse([response, status], 'getDetails') || !response) {
|
|
1150
|
+
logger_1.logger.debug('Error getting purifier details');
|
|
1151
|
+
this.connectionStatus = 'offline';
|
|
1152
|
+
return false;
|
|
1153
|
+
}
|
|
1154
|
+
const innerResult = (_a = response.result) === null || _a === void 0 ? void 0 : _a.result;
|
|
1155
|
+
if (!innerResult) {
|
|
1156
|
+
this.connectionStatus = 'offline';
|
|
1157
|
+
logger_1.logger.debug('Error in inner result dict from purifier');
|
|
1158
|
+
return false;
|
|
1159
|
+
}
|
|
1160
|
+
this.deviceStatus = innerResult.enabled ? 'on' : 'off';
|
|
1161
|
+
this.details = {
|
|
1162
|
+
mode: innerResult.mode || '',
|
|
1163
|
+
speed: innerResult.speed || 0,
|
|
1164
|
+
display: innerResult.display || false,
|
|
1165
|
+
child_lock: innerResult.child_lock || false,
|
|
1166
|
+
night_light: innerResult.night_light || 'off',
|
|
1167
|
+
timer: innerResult.timer || 0,
|
|
1168
|
+
configuration: innerResult.configuration || {},
|
|
1169
|
+
light_detection: innerResult.light_detection || false,
|
|
1170
|
+
light_detection_state: innerResult.light_detection_state || false
|
|
1171
|
+
};
|
|
1172
|
+
if (innerResult.configuration) {
|
|
1173
|
+
this.buildConfigDict(innerResult.configuration);
|
|
1174
|
+
}
|
|
1175
|
+
this._lightDetection = innerResult.light_detection || false;
|
|
1176
|
+
this._lightDetectionState = innerResult.light_detection_state || false;
|
|
1177
|
+
logger_1.logger.debug(`Successfully got details for device: ${this.deviceName}`);
|
|
1178
|
+
return true;
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Change fan speed
|
|
1182
|
+
*/
|
|
1183
|
+
async changeFanSpeed(speed) {
|
|
1184
|
+
if (!this.speeds.includes(speed)) {
|
|
1185
|
+
logger_1.logger.debug(`Invalid speed: ${speed}. Must be one of: ${this.speeds.join(', ')}`);
|
|
1186
|
+
return false;
|
|
1187
|
+
}
|
|
1188
|
+
const [head, body] = this.buildApiDict('setLevel');
|
|
1189
|
+
if (!head || !body) {
|
|
1190
|
+
return false;
|
|
1191
|
+
}
|
|
1192
|
+
body.payload.data = {
|
|
1193
|
+
levelIdx: 0,
|
|
1194
|
+
levelType: 'wind',
|
|
1195
|
+
manualSpeedLevel: speed
|
|
1196
|
+
};
|
|
1197
|
+
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, head);
|
|
1198
|
+
const success = this.checkResponse([response, status], 'changeFanSpeed');
|
|
1199
|
+
if (success) {
|
|
1200
|
+
this.details.speed = speed;
|
|
1201
|
+
}
|
|
1202
|
+
else {
|
|
1203
|
+
logger_1.logger.debug('Error setting fan speed');
|
|
1204
|
+
}
|
|
1205
|
+
return success;
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Toggle device power
|
|
1209
|
+
*/
|
|
1210
|
+
async toggleSwitch(toggle) {
|
|
1211
|
+
const [head, body] = this.buildApiDict('setSwitch');
|
|
1212
|
+
if (!head || !body) {
|
|
1213
|
+
return false;
|
|
1214
|
+
}
|
|
1215
|
+
body.payload.data = {
|
|
1216
|
+
powerSwitch: toggle ? 1 : 0,
|
|
1217
|
+
switchIdx: 0
|
|
1218
|
+
};
|
|
1219
|
+
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, head);
|
|
1220
|
+
const success = this.checkResponse([response, status], 'toggleSwitch');
|
|
1221
|
+
if (success) {
|
|
1222
|
+
this.deviceStatus = toggle ? 'on' : 'off';
|
|
1223
|
+
}
|
|
1224
|
+
else {
|
|
1225
|
+
logger_1.logger.debug('Error toggling device power');
|
|
1226
|
+
}
|
|
1227
|
+
return success;
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Turn device on
|
|
1231
|
+
*/
|
|
1232
|
+
async turnOn() {
|
|
1233
|
+
logger_1.logger.debug(`Turning on device: ${this.deviceName}`);
|
|
1234
|
+
return this.toggleSwitch(true);
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Turn device off
|
|
1238
|
+
*/
|
|
1239
|
+
async turnOff() {
|
|
1240
|
+
logger_1.logger.debug(`Turning off device: ${this.deviceName}`);
|
|
1241
|
+
return this.toggleSwitch(false);
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Set tower fan mode
|
|
1245
|
+
*/
|
|
1246
|
+
async mode_toggle(mode) {
|
|
1247
|
+
const validModes = this.towerModes.map(m => m.toLowerCase());
|
|
1248
|
+
if (!validModes.includes(mode.toLowerCase())) {
|
|
1249
|
+
logger_1.logger.debug(`Invalid purifier mode used - ${mode}`);
|
|
1250
|
+
return false;
|
|
1251
|
+
}
|
|
1252
|
+
if (mode.toLowerCase() === 'off') {
|
|
1253
|
+
return this.turnOff();
|
|
1254
|
+
}
|
|
1255
|
+
const [head, body] = this.buildApiDict('setTowerFanMode');
|
|
1256
|
+
if (!head || !body) {
|
|
1257
|
+
return false;
|
|
1258
|
+
}
|
|
1259
|
+
body.deviceId = this.cid;
|
|
1260
|
+
body.payload.data = {
|
|
1261
|
+
workMode: mode
|
|
1262
|
+
};
|
|
1263
|
+
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', body, head);
|
|
1264
|
+
const success = this.checkResponse([response, status], 'mode_toggle');
|
|
1265
|
+
if (success) {
|
|
1266
|
+
this.details.mode = mode;
|
|
1267
|
+
}
|
|
1268
|
+
else {
|
|
1269
|
+
logger_1.logger.debug('Error setting purifier mode');
|
|
1270
|
+
}
|
|
1271
|
+
return success;
|
|
1272
|
+
}
|
|
1273
|
+
/**
|
|
1274
|
+
* Set normal mode
|
|
1275
|
+
*/
|
|
1276
|
+
async normal_mode() {
|
|
1277
|
+
logger_1.logger.debug(`Setting normal mode for device: ${this.deviceName}`);
|
|
1278
|
+
return this.mode_toggle('normal');
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* Set manual mode - adapter to set mode to normal
|
|
1282
|
+
*/
|
|
1283
|
+
async manual_mode() {
|
|
1284
|
+
logger_1.logger.debug(`Setting manual mode for device: ${this.deviceName}`);
|
|
1285
|
+
return this.normal_mode();
|
|
1286
|
+
}
|
|
1287
|
+
/**
|
|
1288
|
+
* Set advanced sleep mode
|
|
1289
|
+
*/
|
|
1290
|
+
async advanced_sleep_mode() {
|
|
1291
|
+
logger_1.logger.debug(`Setting advanced sleep mode for device: ${this.deviceName}`);
|
|
1292
|
+
return this.mode_toggle('advancedSleep');
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Set sleep mode - adapter for advanced sleep mode
|
|
1296
|
+
*/
|
|
1297
|
+
async sleep_mode() {
|
|
1298
|
+
logger_1.logger.debug(`Setting sleep mode for device: ${this.deviceName}`);
|
|
1299
|
+
return this.advanced_sleep_mode();
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* Override setMode to handle tower fan specific modes
|
|
1303
|
+
*/
|
|
1304
|
+
async setMode(mode) {
|
|
1305
|
+
return this.mode_toggle(mode);
|
|
1306
|
+
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Get current speed
|
|
1309
|
+
*/
|
|
1310
|
+
get speed() {
|
|
1311
|
+
return this.details.speed || 0;
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Get display status
|
|
1315
|
+
*/
|
|
1316
|
+
get displayState() {
|
|
1317
|
+
return this.details.display || false;
|
|
1318
|
+
}
|
|
1319
|
+
/**
|
|
1320
|
+
* Get child lock status
|
|
1321
|
+
*/
|
|
1322
|
+
get childLock() {
|
|
1323
|
+
return this.details.child_lock ? 'on' : 'off';
|
|
1324
|
+
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Get night light status
|
|
1327
|
+
*/
|
|
1328
|
+
get nightLight() {
|
|
1329
|
+
return this.details.night_light || 'off';
|
|
1330
|
+
}
|
|
1331
|
+
/**
|
|
1332
|
+
* Get timer status
|
|
1333
|
+
*/
|
|
1334
|
+
get timer() {
|
|
1335
|
+
return this.details.timer || 0;
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Display device info
|
|
1339
|
+
*/
|
|
1340
|
+
display() {
|
|
1341
|
+
super.display();
|
|
1342
|
+
const info = [
|
|
1343
|
+
['Speed: ', this.speed],
|
|
1344
|
+
['Display: ', this.displayState],
|
|
1345
|
+
['Child Lock: ', this.childLock],
|
|
1346
|
+
['Night Light: ', this.nightLight],
|
|
1347
|
+
['Timer: ', this.timer]
|
|
1348
|
+
];
|
|
1349
|
+
for (const [key, value] of info) {
|
|
1350
|
+
logger_1.logger.info(`${key.toString().padEnd(30, '.')} ${value}`);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
exports.VeSyncTowerFan = VeSyncTowerFan;
|
|
1030
1355
|
// Export fan modules dictionary
|
|
1031
1356
|
exports.fanModules = {
|
|
1032
1357
|
// Core Series
|
|
@@ -1063,10 +1388,10 @@ exports.fanModules = {
|
|
|
1063
1388
|
'LAP-EL551S-WEU': VeSyncAirBypass,
|
|
1064
1389
|
'LAP-EL551S-WUS': VeSyncAirBypass,
|
|
1065
1390
|
// LTF Series
|
|
1066
|
-
'LTF-F422S-KEU':
|
|
1067
|
-
'LTF-F422S-WUSR':
|
|
1068
|
-
'LTF-F422_WJP':
|
|
1069
|
-
'LTF-F422S-WUS':
|
|
1391
|
+
'LTF-F422S-KEU': VeSyncTowerFan,
|
|
1392
|
+
'LTF-F422S-WUSR': VeSyncTowerFan,
|
|
1393
|
+
'LTF-F422_WJP': VeSyncTowerFan,
|
|
1394
|
+
'LTF-F422S-WUS': VeSyncTowerFan,
|
|
1070
1395
|
// Classic Series
|
|
1071
1396
|
'Classic300S': VeSyncHumidifier,
|
|
1072
1397
|
'Classic200S': VeSyncHumidifier,
|
package/package.json
CHANGED
package/src/lib/vesyncFan.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { logger } from './logger';
|
|
|
8
8
|
|
|
9
9
|
interface FanConfig {
|
|
10
10
|
[key: string]: {
|
|
11
|
-
module: 'VeSyncAirBypass' | 'VeSyncHumidifier' | 'VeSyncWarmHumidifier';
|
|
11
|
+
module: 'VeSyncAirBypass' | 'VeSyncHumidifier' | 'VeSyncWarmHumidifier' | 'VeSyncTowerFan';
|
|
12
12
|
features: string[];
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -145,20 +145,20 @@ export const fanConfig: FanConfig = {
|
|
|
145
145
|
|
|
146
146
|
// LTF Series
|
|
147
147
|
'LTF-F422S-KEU': {
|
|
148
|
-
module: '
|
|
149
|
-
features: ['display', 'child_lock', 'night_light', 'timer']
|
|
148
|
+
module: 'VeSyncTowerFan',
|
|
149
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes']
|
|
150
150
|
},
|
|
151
151
|
'LTF-F422S-WUSR': {
|
|
152
|
-
module: '
|
|
153
|
-
features: ['display', 'child_lock', 'night_light', 'timer']
|
|
152
|
+
module: 'VeSyncTowerFan',
|
|
153
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes']
|
|
154
154
|
},
|
|
155
155
|
'LTF-F422_WJP': {
|
|
156
|
-
module: '
|
|
157
|
-
features: ['display', 'child_lock', 'night_light', 'timer']
|
|
156
|
+
module: 'VeSyncTowerFan',
|
|
157
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes']
|
|
158
158
|
},
|
|
159
159
|
'LTF-F422S-WUS': {
|
|
160
|
-
module: '
|
|
161
|
-
features: ['display', 'child_lock', 'night_light', 'timer']
|
|
160
|
+
module: 'VeSyncTowerFan',
|
|
161
|
+
features: ['display', 'child_lock', 'night_light', 'timer', 'fan_speeds', 'tower_modes']
|
|
162
162
|
},
|
|
163
163
|
|
|
164
164
|
// Classic Series
|
package/src/lib/vesyncFanImpl.ts
CHANGED
|
@@ -1254,6 +1254,413 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1254
1254
|
}
|
|
1255
1255
|
}
|
|
1256
1256
|
|
|
1257
|
+
/**
|
|
1258
|
+
* VeSync Air Purifier with Bypass V2
|
|
1259
|
+
*/
|
|
1260
|
+
export class VeSyncAirBaseV2 extends VeSyncAirBypass {
|
|
1261
|
+
protected _lightDetection: boolean = false;
|
|
1262
|
+
protected _lightDetectionState: boolean = false;
|
|
1263
|
+
|
|
1264
|
+
constructor(details: Record<string, any>, manager: VeSync) {
|
|
1265
|
+
super(details, manager);
|
|
1266
|
+
logger.debug(`Initialized VeSyncAirBaseV2 device: ${this.deviceName}`);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
/**
|
|
1270
|
+
* Build API dictionary
|
|
1271
|
+
*/
|
|
1272
|
+
protected buildApiDict(method: string): [Record<string, any>, Record<string, any>] {
|
|
1273
|
+
const head = Helpers.reqHeaderBypass();
|
|
1274
|
+
const body = {
|
|
1275
|
+
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
1276
|
+
deviceId: this.cid,
|
|
1277
|
+
configModule: this.configModule,
|
|
1278
|
+
payload: {
|
|
1279
|
+
method,
|
|
1280
|
+
source: 'APP',
|
|
1281
|
+
data: {}
|
|
1282
|
+
}
|
|
1283
|
+
};
|
|
1284
|
+
return [head, body];
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
get lightDetection(): boolean {
|
|
1288
|
+
return this._lightDetection;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
set lightDetection(toggle: boolean) {
|
|
1292
|
+
this._lightDetection = toggle;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
get lightDetectionState(): boolean {
|
|
1296
|
+
return this._lightDetectionState;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
async setLightDetection(toggle: boolean): Promise<boolean> {
|
|
1300
|
+
const [head, body] = this.buildApiDict('setLightDetection');
|
|
1301
|
+
if (!head || !body) {
|
|
1302
|
+
return false;
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
body.payload.data = { enabled: toggle };
|
|
1306
|
+
|
|
1307
|
+
const [response, status] = await this.callApi(
|
|
1308
|
+
'/cloud/v2/deviceManaged/bypassV2',
|
|
1309
|
+
'post',
|
|
1310
|
+
body,
|
|
1311
|
+
head
|
|
1312
|
+
);
|
|
1313
|
+
|
|
1314
|
+
const success = this.checkResponse([response, status], 'setLightDetection');
|
|
1315
|
+
if (success) {
|
|
1316
|
+
this._lightDetection = toggle;
|
|
1317
|
+
}
|
|
1318
|
+
return success;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
async setLightDetectionOn(): Promise<boolean> {
|
|
1322
|
+
return this.setLightDetection(true);
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
async setLightDetectionOff(): Promise<boolean> {
|
|
1326
|
+
return this.setLightDetection(false);
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
async turboMode(): Promise<boolean> {
|
|
1330
|
+
return this.mode_toggle('turbo');
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
async petMode(): Promise<boolean> {
|
|
1334
|
+
return this.mode_toggle('pet');
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
/**
|
|
1338
|
+
* Build configuration dictionary
|
|
1339
|
+
*/
|
|
1340
|
+
protected buildConfigDict(configDict: Record<string, any>): void {
|
|
1341
|
+
if (configDict) {
|
|
1342
|
+
this.config = configDict;
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
/**
|
|
1347
|
+
* Set mode
|
|
1348
|
+
*/
|
|
1349
|
+
protected async mode_toggle(mode: string): Promise<boolean> {
|
|
1350
|
+
const validModes = this.modes.map(m => m.toLowerCase());
|
|
1351
|
+
if (!validModes.includes(mode.toLowerCase())) {
|
|
1352
|
+
logger.debug(`Invalid mode used - ${mode}`);
|
|
1353
|
+
return false;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
const [head, body] = this.buildApiDict('setPurifierMode');
|
|
1357
|
+
if (!head || !body) {
|
|
1358
|
+
return false;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
body.payload.data = {
|
|
1362
|
+
mode: mode
|
|
1363
|
+
};
|
|
1364
|
+
|
|
1365
|
+
const [response, status] = await this.callApi(
|
|
1366
|
+
'/cloud/v2/deviceManaged/bypassV2',
|
|
1367
|
+
'post',
|
|
1368
|
+
body,
|
|
1369
|
+
head
|
|
1370
|
+
);
|
|
1371
|
+
|
|
1372
|
+
const success = this.checkResponse([response, status], 'mode_toggle');
|
|
1373
|
+
if (success) {
|
|
1374
|
+
this.details.mode = mode;
|
|
1375
|
+
} else {
|
|
1376
|
+
logger.debug('Error setting mode');
|
|
1377
|
+
}
|
|
1378
|
+
return success;
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* VeSync Tower Fan Implementation
|
|
1384
|
+
*/
|
|
1385
|
+
export class VeSyncTowerFan extends VeSyncAirBaseV2 {
|
|
1386
|
+
protected readonly towerModes = ['normal', 'advancedSleep', 'off'] as const;
|
|
1387
|
+
protected readonly speeds = Array.from({length: 12}, (_, i) => i + 1);
|
|
1388
|
+
|
|
1389
|
+
constructor(details: Record<string, any>, manager: VeSync) {
|
|
1390
|
+
super(details, manager);
|
|
1391
|
+
logger.debug(`Initialized VeSyncTowerFan device: ${this.deviceName}`);
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
/**
|
|
1395
|
+
* Get device details
|
|
1396
|
+
*/
|
|
1397
|
+
async getDetails(): Promise<Boolean> {
|
|
1398
|
+
logger.debug(`Getting details for device: ${this.deviceName}`);
|
|
1399
|
+
const [head, body] = this.buildApiDict('getTowerFanStatus');
|
|
1400
|
+
if (!head || !body) {
|
|
1401
|
+
logger.debug('Error building API request');
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
const [response, status] = await this.callApi(
|
|
1406
|
+
'/cloud/v2/deviceManaged/bypassV2',
|
|
1407
|
+
'post',
|
|
1408
|
+
body,
|
|
1409
|
+
head
|
|
1410
|
+
);
|
|
1411
|
+
|
|
1412
|
+
if (!this.checkResponse([response, status], 'getDetails') || !response) {
|
|
1413
|
+
logger.debug('Error getting purifier details');
|
|
1414
|
+
this.connectionStatus = 'offline';
|
|
1415
|
+
return false;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
const innerResult = response.result?.result;
|
|
1419
|
+
if (!innerResult) {
|
|
1420
|
+
this.connectionStatus = 'offline';
|
|
1421
|
+
logger.debug('Error in inner result dict from purifier');
|
|
1422
|
+
return false;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
this.deviceStatus = innerResult.enabled ? 'on' : 'off';
|
|
1426
|
+
this.details = {
|
|
1427
|
+
mode: innerResult.mode || '',
|
|
1428
|
+
speed: innerResult.speed || 0,
|
|
1429
|
+
display: innerResult.display || false,
|
|
1430
|
+
child_lock: innerResult.child_lock || false,
|
|
1431
|
+
night_light: innerResult.night_light || 'off',
|
|
1432
|
+
timer: innerResult.timer || 0,
|
|
1433
|
+
configuration: innerResult.configuration || {},
|
|
1434
|
+
light_detection: innerResult.light_detection || false,
|
|
1435
|
+
light_detection_state: innerResult.light_detection_state || false
|
|
1436
|
+
};
|
|
1437
|
+
|
|
1438
|
+
if (innerResult.configuration) {
|
|
1439
|
+
this.buildConfigDict(innerResult.configuration);
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
this._lightDetection = innerResult.light_detection || false;
|
|
1443
|
+
this._lightDetectionState = innerResult.light_detection_state || false;
|
|
1444
|
+
|
|
1445
|
+
logger.debug(`Successfully got details for device: ${this.deviceName}`);
|
|
1446
|
+
return true;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
/**
|
|
1450
|
+
* Change fan speed
|
|
1451
|
+
*/
|
|
1452
|
+
async changeFanSpeed(speed: number): Promise<boolean> {
|
|
1453
|
+
if (!this.speeds.includes(speed)) {
|
|
1454
|
+
logger.debug(`Invalid speed: ${speed}. Must be one of: ${this.speeds.join(', ')}`);
|
|
1455
|
+
return false;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
const [head, body] = this.buildApiDict('setLevel');
|
|
1459
|
+
if (!head || !body) {
|
|
1460
|
+
return false;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
body.payload.data = {
|
|
1464
|
+
levelIdx: 0,
|
|
1465
|
+
levelType: 'wind',
|
|
1466
|
+
manualSpeedLevel: speed
|
|
1467
|
+
};
|
|
1468
|
+
|
|
1469
|
+
const [response, status] = await this.callApi(
|
|
1470
|
+
'/cloud/v2/deviceManaged/bypassV2',
|
|
1471
|
+
'post',
|
|
1472
|
+
body,
|
|
1473
|
+
head
|
|
1474
|
+
);
|
|
1475
|
+
|
|
1476
|
+
const success = this.checkResponse([response, status], 'changeFanSpeed');
|
|
1477
|
+
if (success) {
|
|
1478
|
+
this.details.speed = speed;
|
|
1479
|
+
} else {
|
|
1480
|
+
logger.debug('Error setting fan speed');
|
|
1481
|
+
}
|
|
1482
|
+
return success;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
/**
|
|
1486
|
+
* Toggle device power
|
|
1487
|
+
*/
|
|
1488
|
+
async toggleSwitch(toggle: boolean): Promise<boolean> {
|
|
1489
|
+
const [head, body] = this.buildApiDict('setSwitch');
|
|
1490
|
+
if (!head || !body) {
|
|
1491
|
+
return false;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
body.payload.data = {
|
|
1495
|
+
powerSwitch: toggle ? 1 : 0,
|
|
1496
|
+
switchIdx: 0
|
|
1497
|
+
};
|
|
1498
|
+
|
|
1499
|
+
const [response, status] = await this.callApi(
|
|
1500
|
+
'/cloud/v2/deviceManaged/bypassV2',
|
|
1501
|
+
'post',
|
|
1502
|
+
body,
|
|
1503
|
+
head
|
|
1504
|
+
);
|
|
1505
|
+
|
|
1506
|
+
const success = this.checkResponse([response, status], 'toggleSwitch');
|
|
1507
|
+
if (success) {
|
|
1508
|
+
this.deviceStatus = toggle ? 'on' : 'off';
|
|
1509
|
+
} else {
|
|
1510
|
+
logger.debug('Error toggling device power');
|
|
1511
|
+
}
|
|
1512
|
+
return success;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
/**
|
|
1516
|
+
* Turn device on
|
|
1517
|
+
*/
|
|
1518
|
+
async turnOn(): Promise<boolean> {
|
|
1519
|
+
logger.debug(`Turning on device: ${this.deviceName}`);
|
|
1520
|
+
return this.toggleSwitch(true);
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
/**
|
|
1524
|
+
* Turn device off
|
|
1525
|
+
*/
|
|
1526
|
+
async turnOff(): Promise<boolean> {
|
|
1527
|
+
logger.debug(`Turning off device: ${this.deviceName}`);
|
|
1528
|
+
return this.toggleSwitch(false);
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
/**
|
|
1532
|
+
* Set tower fan mode
|
|
1533
|
+
*/
|
|
1534
|
+
async mode_toggle(mode: string): Promise<boolean> {
|
|
1535
|
+
const validModes = this.towerModes.map(m => m.toLowerCase());
|
|
1536
|
+
if (!validModes.includes(mode.toLowerCase())) {
|
|
1537
|
+
logger.debug(`Invalid purifier mode used - ${mode}`);
|
|
1538
|
+
return false;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
if (mode.toLowerCase() === 'off') {
|
|
1542
|
+
return this.turnOff();
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
const [head, body] = this.buildApiDict('setTowerFanMode');
|
|
1546
|
+
if (!head || !body) {
|
|
1547
|
+
return false;
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
body.deviceId = this.cid;
|
|
1551
|
+
body.payload.data = {
|
|
1552
|
+
workMode: mode
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
const [response, status] = await this.callApi(
|
|
1556
|
+
'/cloud/v2/deviceManaged/bypassV2',
|
|
1557
|
+
'post',
|
|
1558
|
+
body,
|
|
1559
|
+
head
|
|
1560
|
+
);
|
|
1561
|
+
|
|
1562
|
+
const success = this.checkResponse([response, status], 'mode_toggle');
|
|
1563
|
+
if (success) {
|
|
1564
|
+
this.details.mode = mode;
|
|
1565
|
+
} else {
|
|
1566
|
+
logger.debug('Error setting purifier mode');
|
|
1567
|
+
}
|
|
1568
|
+
return success;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
/**
|
|
1572
|
+
* Set normal mode
|
|
1573
|
+
*/
|
|
1574
|
+
async normal_mode(): Promise<boolean> {
|
|
1575
|
+
logger.debug(`Setting normal mode for device: ${this.deviceName}`);
|
|
1576
|
+
return this.mode_toggle('normal');
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
/**
|
|
1580
|
+
* Set manual mode - adapter to set mode to normal
|
|
1581
|
+
*/
|
|
1582
|
+
async manual_mode(): Promise<boolean> {
|
|
1583
|
+
logger.debug(`Setting manual mode for device: ${this.deviceName}`);
|
|
1584
|
+
return this.normal_mode();
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
/**
|
|
1588
|
+
* Set advanced sleep mode
|
|
1589
|
+
*/
|
|
1590
|
+
async advanced_sleep_mode(): Promise<boolean> {
|
|
1591
|
+
logger.debug(`Setting advanced sleep mode for device: ${this.deviceName}`);
|
|
1592
|
+
return this.mode_toggle('advancedSleep');
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
/**
|
|
1596
|
+
* Set sleep mode - adapter for advanced sleep mode
|
|
1597
|
+
*/
|
|
1598
|
+
async sleep_mode(): Promise<boolean> {
|
|
1599
|
+
logger.debug(`Setting sleep mode for device: ${this.deviceName}`);
|
|
1600
|
+
return this.advanced_sleep_mode();
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
/**
|
|
1604
|
+
* Override setMode to handle tower fan specific modes
|
|
1605
|
+
*/
|
|
1606
|
+
async setMode(mode: string): Promise<boolean> {
|
|
1607
|
+
return this.mode_toggle(mode);
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
/**
|
|
1611
|
+
* Get current speed
|
|
1612
|
+
*/
|
|
1613
|
+
get speed(): number {
|
|
1614
|
+
return this.details.speed || 0;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
/**
|
|
1618
|
+
* Get display status
|
|
1619
|
+
*/
|
|
1620
|
+
get displayState(): boolean {
|
|
1621
|
+
return this.details.display || false;
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
/**
|
|
1625
|
+
* Get child lock status
|
|
1626
|
+
*/
|
|
1627
|
+
override get childLock(): string {
|
|
1628
|
+
return this.details.child_lock ? 'on' : 'off';
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
/**
|
|
1632
|
+
* Get night light status
|
|
1633
|
+
*/
|
|
1634
|
+
get nightLight(): string {
|
|
1635
|
+
return this.details.night_light || 'off';
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
/**
|
|
1639
|
+
* Get timer status
|
|
1640
|
+
*/
|
|
1641
|
+
get timer(): number {
|
|
1642
|
+
return this.details.timer || 0;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
/**
|
|
1646
|
+
* Display device info
|
|
1647
|
+
*/
|
|
1648
|
+
override display(): void {
|
|
1649
|
+
super.display();
|
|
1650
|
+
const info = [
|
|
1651
|
+
['Speed: ', this.speed],
|
|
1652
|
+
['Display: ', this.displayState],
|
|
1653
|
+
['Child Lock: ', this.childLock],
|
|
1654
|
+
['Night Light: ', this.nightLight],
|
|
1655
|
+
['Timer: ', this.timer]
|
|
1656
|
+
];
|
|
1657
|
+
|
|
1658
|
+
for (const [key, value] of info) {
|
|
1659
|
+
logger.info(`${key.toString().padEnd(30, '.')} ${value}`);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1257
1664
|
// Export fan modules dictionary
|
|
1258
1665
|
export const fanModules: Record<string, new (details: Record<string, any>, manager: VeSync) => VeSyncFan> = {
|
|
1259
1666
|
// Core Series
|
|
@@ -1292,10 +1699,10 @@ export const fanModules: Record<string, new (details: Record<string, any>, manag
|
|
|
1292
1699
|
'LAP-EL551S-WUS': VeSyncAirBypass,
|
|
1293
1700
|
|
|
1294
1701
|
// LTF Series
|
|
1295
|
-
'LTF-F422S-KEU':
|
|
1296
|
-
'LTF-F422S-WUSR':
|
|
1297
|
-
'LTF-F422_WJP':
|
|
1298
|
-
'LTF-F422S-WUS':
|
|
1702
|
+
'LTF-F422S-KEU': VeSyncTowerFan,
|
|
1703
|
+
'LTF-F422S-WUSR': VeSyncTowerFan,
|
|
1704
|
+
'LTF-F422_WJP': VeSyncTowerFan,
|
|
1705
|
+
'LTF-F422S-WUS': VeSyncTowerFan,
|
|
1299
1706
|
|
|
1300
1707
|
// Classic Series
|
|
1301
1708
|
'Classic300S': VeSyncHumidifier,
|