tsvesync 1.0.36 → 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/README.md CHANGED
@@ -121,6 +121,10 @@ A TypeScript library for interacting with VeSync smart home devices. This librar
121
121
  - Power monitoring
122
122
  - Energy usage tracking (daily/weekly/monthly/yearly)
123
123
  - Voltage monitoring
124
+ - 10A Outlet (ESW10-USA)
125
+ - Power monitoring
126
+ - Energy usage tracking (daily/weekly/monthly/yearly)
127
+ - Voltage monitoring
124
128
  - 7A Outlet (wifi-switch-1.3)
125
129
  - Energy usage tracking (daily/weekly/monthly/yearly)
126
130
 
@@ -0,0 +1,156 @@
1
+ get_monthly_energy:
2
+ headers:
3
+ accept-language: en
4
+ accountId: sample_id
5
+ appVersion: 2.8.6
6
+ content-type: application/json
7
+ tk: sample_tk
8
+ tz: America/New_York
9
+ json_object:
10
+ acceptLanguage: en
11
+ accountID: sample_id
12
+ appVersion: 2.8.6
13
+ method: energymonth
14
+ mobileId: '1234567890123456'
15
+ phoneBrand: SM N9005
16
+ phoneOS: Android
17
+ timeZone: America/New_York
18
+ token: sample_tk
19
+ traceId: TRACE_ID
20
+ uuid: ESW10-USA-UUID
21
+ method: post
22
+ url: /15a/v1/device/energymonth
23
+ get_weekly_energy:
24
+ headers:
25
+ accept-language: en
26
+ accountId: sample_id
27
+ appVersion: 2.8.6
28
+ content-type: application/json
29
+ tk: sample_tk
30
+ tz: America/New_York
31
+ json_object:
32
+ acceptLanguage: en
33
+ accountID: sample_id
34
+ appVersion: 2.8.6
35
+ method: energyweek
36
+ mobileId: '1234567890123456'
37
+ phoneBrand: SM N9005
38
+ phoneOS: Android
39
+ timeZone: America/New_York
40
+ token: sample_tk
41
+ traceId: TRACE_ID
42
+ uuid: ESW10-USA-UUID
43
+ method: post
44
+ url: /15a/v1/device/energyweek
45
+ get_yearly_energy:
46
+ headers:
47
+ accept-language: en
48
+ accountId: sample_id
49
+ appVersion: 2.8.6
50
+ content-type: application/json
51
+ tk: sample_tk
52
+ tz: America/New_York
53
+ json_object:
54
+ acceptLanguage: en
55
+ accountID: sample_id
56
+ appVersion: 2.8.6
57
+ method: energyyear
58
+ mobileId: '1234567890123456'
59
+ phoneBrand: SM N9005
60
+ phoneOS: Android
61
+ timeZone: America/New_York
62
+ token: sample_tk
63
+ traceId: TRACE_ID
64
+ uuid: ESW10-USA-UUID
65
+ method: post
66
+ url: /15a/v1/device/energyyear
67
+ turn_off:
68
+ headers:
69
+ accept-language: en
70
+ accountId: sample_id
71
+ appVersion: 2.8.6
72
+ content-type: application/json
73
+ tk: sample_tk
74
+ tz: America/New_York
75
+ json_object:
76
+ acceptLanguage: en
77
+ accountID: sample_id
78
+ status: 'off'
79
+ timeZone: America/New_York
80
+ token: sample_tk
81
+ uuid: ESW10-USA-UUID
82
+ method: put
83
+ url: /15a/v1/device/devicestatus
84
+ turn_off_nightlight:
85
+ headers:
86
+ accept-language: en
87
+ accountId: sample_id
88
+ appVersion: 2.8.6
89
+ content-type: application/json
90
+ tk: sample_tk
91
+ tz: America/New_York
92
+ json_object:
93
+ acceptLanguage: en
94
+ accountID: sample_id
95
+ mode: manual
96
+ timeZone: America/New_York
97
+ token: sample_tk
98
+ uuid: ESW10-USA-UUID
99
+ method: put
100
+ url: /15a/v1/device/nightlightstatus
101
+ turn_on:
102
+ headers:
103
+ accept-language: en
104
+ accountId: sample_id
105
+ appVersion: 2.8.6
106
+ content-type: application/json
107
+ tk: sample_tk
108
+ tz: America/New_York
109
+ json_object:
110
+ acceptLanguage: en
111
+ accountID: sample_id
112
+ status: 'on'
113
+ timeZone: America/New_York
114
+ token: sample_tk
115
+ uuid: ESW10-USA-UUID
116
+ method: put
117
+ url: /15a/v1/device/devicestatus
118
+ turn_on_nightlight:
119
+ headers:
120
+ accept-language: en
121
+ accountId: sample_id
122
+ appVersion: 2.8.6
123
+ content-type: application/json
124
+ tk: sample_tk
125
+ tz: America/New_York
126
+ json_object:
127
+ acceptLanguage: en
128
+ accountID: sample_id
129
+ mode: auto
130
+ timeZone: America/New_York
131
+ token: sample_tk
132
+ uuid: ESW10-USA-UUID
133
+ method: put
134
+ url: /15a/v1/device/nightlightstatus
135
+ update:
136
+ headers:
137
+ accept-language: en
138
+ accountId: sample_id
139
+ appVersion: 2.8.6
140
+ content-type: application/json
141
+ tk: sample_tk
142
+ tz: America/New_York
143
+ json_object:
144
+ acceptLanguage: en
145
+ accountID: sample_id
146
+ appVersion: 2.8.6
147
+ method: devicedetail
148
+ mobileId: '1234567890123456'
149
+ phoneBrand: SM N9005
150
+ phoneOS: Android
151
+ timeZone: America/New_York
152
+ token: sample_tk
153
+ traceId: TRACE_ID
154
+ uuid: ESW10-USA-UUID
155
+ method: post
156
+ url: /15a/v1/device/devicedetail
@@ -52,6 +52,7 @@ function objectFactory(details, manager) {
52
52
  'wifi-switch': 'outlets',
53
53
  'ESW03': 'outlets',
54
54
  'ESW01': 'outlets',
55
+ 'ESW10': 'outlets',
55
56
  'ESW15': 'outlets',
56
57
  'ESO': 'outlets',
57
58
  // Switches
@@ -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
  }
@@ -136,20 +136,20 @@ exports.fanConfig = {
136
136
  },
137
137
  // LTF Series
138
138
  'LTF-F422S-KEU': {
139
- module: 'VeSyncAirBypass',
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: 'VeSyncAirBypass',
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: 'VeSyncAirBypass',
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: 'VeSyncAirBypass',
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': VeSyncAirBypass,
1067
- 'LTF-F422S-WUSR': VeSyncAirBypass,
1068
- 'LTF-F422_WJP': VeSyncAirBypass,
1069
- 'LTF-F422S-WUS': VeSyncAirBypass,
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,
@@ -21,6 +21,10 @@ exports.outletConfig = {
21
21
  module: 'VeSyncOutlet10A',
22
22
  features: ['energy']
23
23
  },
24
+ 'ESW10-USA': {
25
+ module: 'VeSyncOutlet10A',
26
+ features: ['energy']
27
+ },
24
28
  'ESW15-USA': {
25
29
  module: 'VeSyncOutlet15A',
26
30
  features: ['energy', 'nightlight']
@@ -60,7 +64,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
60
64
  else if (this.deviceType.startsWith('ESW15')) {
61
65
  url = '/15a/v1/device/devicedetail';
62
66
  }
63
- else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01')) {
67
+ else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
64
68
  url = '/10a/v1/device/devicedetail';
65
69
  }
66
70
  else {
@@ -147,7 +151,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
147
151
  else if (this.deviceType.startsWith('ESW15')) {
148
152
  url = '/15a/v1/device/energy';
149
153
  }
150
- else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01')) {
154
+ else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
151
155
  url = '/10a/v1/device/energy';
152
156
  }
153
157
  else {
@@ -233,7 +237,7 @@ class VeSyncOutlet extends vesyncBaseDevice_1.VeSyncBaseDevice {
233
237
  else if (this.deviceType.startsWith('ESW15') || this.deviceType.startsWith('ESO15')) {
234
238
  return '15a/v1/device';
235
239
  }
236
- else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01')) {
240
+ else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
237
241
  return '10a/v1/device';
238
242
  }
239
243
  return 'v1/device';
@@ -242,6 +242,7 @@ exports.outletModules = {
242
242
  'wifi-switch-1.3': VeSyncOutlet7A,
243
243
  'ESW03-USA': VeSyncOutlet10A,
244
244
  'ESW01-EU': VeSyncOutlet10A,
245
+ 'ESW10-USA': VeSyncOutlet10A,
245
246
  'ESW15-USA': VeSyncOutlet15A,
246
247
  'ESO15-TB': VeSyncOutdoorPlug
247
248
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsvesync",
3
- "version": "1.0.36",
3
+ "version": "1.0.38",
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",
package/src/lib/vesync.ts CHANGED
@@ -67,6 +67,7 @@ function objectFactory(details: Record<string, any>, manager: VeSync): [string,
67
67
  'wifi-switch': 'outlets',
68
68
  'ESW03': 'outlets',
69
69
  'ESW01': 'outlets',
70
+ 'ESW10': 'outlets',
70
71
  'ESW15': 'outlets',
71
72
  'ESO': 'outlets',
72
73
  // Switches
@@ -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: 'VeSyncAirBypass',
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: 'VeSyncAirBypass',
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: 'VeSyncAirBypass',
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: 'VeSyncAirBypass',
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
@@ -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': VeSyncAirBypass,
1296
- 'LTF-F422S-WUSR': VeSyncAirBypass,
1297
- 'LTF-F422_WJP': VeSyncAirBypass,
1298
- 'LTF-F422S-WUS': VeSyncAirBypass,
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,
@@ -28,6 +28,10 @@ export const outletConfig: OutletConfig = {
28
28
  module: 'VeSyncOutlet10A',
29
29
  features: ['energy']
30
30
  },
31
+ 'ESW10-USA': {
32
+ module: 'VeSyncOutlet10A',
33
+ features: ['energy']
34
+ },
31
35
  'ESW15-USA': {
32
36
  module: 'VeSyncOutlet15A',
33
37
  features: ['energy', 'nightlight']
@@ -71,7 +75,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
71
75
  url = '/outdoorsocket15a/v1/device/devicedetail';
72
76
  } else if (this.deviceType.startsWith('ESW15')) {
73
77
  url = '/15a/v1/device/devicedetail';
74
- } else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01')) {
78
+ } else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
75
79
  url = '/10a/v1/device/devicedetail';
76
80
  } else {
77
81
  url = '/v1/device/devicedetail';
@@ -168,7 +172,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
168
172
  url = '/outdoorsocket15a/v1/device/energy';
169
173
  } else if (this.deviceType.startsWith('ESW15')) {
170
174
  url = '/15a/v1/device/energy';
171
- } else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01')) {
175
+ } else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
172
176
  url = '/10a/v1/device/energy';
173
177
  } else {
174
178
  url = '/v1/device/energy';
@@ -261,7 +265,7 @@ export abstract class VeSyncOutlet extends VeSyncBaseDevice {
261
265
  return `v1/device/${this.deviceType}-${this.cid}`;
262
266
  } else if (this.deviceType.startsWith('ESW15') || this.deviceType.startsWith('ESO15')) {
263
267
  return '15a/v1/device';
264
- } else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01')) {
268
+ } else if (this.deviceType.startsWith('ESW03') || this.deviceType.startsWith('ESW01') || this.deviceType.startsWith('ESW10')) {
265
269
  return '10a/v1/device';
266
270
  }
267
271
  return 'v1/device';
@@ -325,6 +325,7 @@ export const outletModules: Record<string, new (details: Record<string, any>, ma
325
325
  'wifi-switch-1.3': VeSyncOutlet7A,
326
326
  'ESW03-USA': VeSyncOutlet10A,
327
327
  'ESW01-EU': VeSyncOutlet10A,
328
+ 'ESW10-USA': VeSyncOutlet10A,
328
329
  'ESW15-USA': VeSyncOutlet15A,
329
330
  'ESO15-TB': VeSyncOutdoorPlug
330
331
  };