tsvesync 1.0.35 → 1.0.37
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 +4 -0
- package/api/vesyncoutlet/ESW10-USA.yaml +156 -0
- package/dist/lib/vesync.js +1 -0
- package/dist/lib/vesyncFanImpl.d.ts +40 -8
- package/dist/lib/vesyncFanImpl.js +230 -57
- package/dist/lib/vesyncOutlet.js +7 -3
- package/dist/lib/vesyncOutletImpl.js +1 -0
- package/package.json +1 -1
- package/src/lib/vesync.ts +1 -0
- package/src/lib/vesyncFanImpl.ts +263 -70
- package/src/lib/vesyncOutlet.ts +7 -3
- package/src/lib/vesyncOutletImpl.ts +1 -0
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
|
package/dist/lib/vesync.js
CHANGED
|
@@ -93,6 +93,22 @@ export declare class VeSyncHumidifier extends VeSyncFan {
|
|
|
93
93
|
* Get device details
|
|
94
94
|
*/
|
|
95
95
|
getDetails(): Promise<Boolean>;
|
|
96
|
+
/**
|
|
97
|
+
* Turn device on
|
|
98
|
+
*/
|
|
99
|
+
turnOn(): Promise<boolean>;
|
|
100
|
+
/**
|
|
101
|
+
* Turn device off
|
|
102
|
+
*/
|
|
103
|
+
turnOff(): Promise<boolean>;
|
|
104
|
+
/**
|
|
105
|
+
* Get model-specific toggle payload
|
|
106
|
+
*/
|
|
107
|
+
protected getTogglePayload(enabled: boolean): Record<string, any>;
|
|
108
|
+
/**
|
|
109
|
+
* Toggle device power
|
|
110
|
+
*/
|
|
111
|
+
toggleSwitch(enabled: boolean): Promise<boolean>;
|
|
96
112
|
/**
|
|
97
113
|
* Set mist level
|
|
98
114
|
*/
|
|
@@ -105,14 +121,6 @@ export declare class VeSyncHumidifier extends VeSyncFan {
|
|
|
105
121
|
* Set device mode
|
|
106
122
|
*/
|
|
107
123
|
setMode(mode: string): Promise<boolean>;
|
|
108
|
-
/**
|
|
109
|
-
* Turn device on
|
|
110
|
-
*/
|
|
111
|
-
turnOn(): Promise<boolean>;
|
|
112
|
-
/**
|
|
113
|
-
* Turn device off
|
|
114
|
-
*/
|
|
115
|
-
turnOff(): Promise<boolean>;
|
|
116
124
|
/**
|
|
117
125
|
* Set target humidity
|
|
118
126
|
*/
|
|
@@ -160,6 +168,10 @@ export declare class VeSyncHumidifier extends VeSyncFan {
|
|
|
160
168
|
export declare class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
161
169
|
protected readonly warmLevels: number[];
|
|
162
170
|
constructor(details: Record<string, any>, manager: VeSync);
|
|
171
|
+
/**
|
|
172
|
+
* Get device details
|
|
173
|
+
*/
|
|
174
|
+
getDetails(): Promise<Boolean>;
|
|
163
175
|
/**
|
|
164
176
|
* Change fan speed - Implemented to satisfy interface but redirects to setMistLevel
|
|
165
177
|
*/
|
|
@@ -176,5 +188,25 @@ export declare class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
176
188
|
* Set drying mode enabled
|
|
177
189
|
*/
|
|
178
190
|
setDryingModeEnabled(enabled: boolean): Promise<boolean>;
|
|
191
|
+
/**
|
|
192
|
+
* Get warm mist enabled status
|
|
193
|
+
*/
|
|
194
|
+
get warmMistEnabled(): boolean;
|
|
195
|
+
/**
|
|
196
|
+
* Get drying mode enabled status
|
|
197
|
+
*/
|
|
198
|
+
get dryingModeEnabled(): boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Get drying mode state
|
|
201
|
+
*/
|
|
202
|
+
get dryingModeState(): string;
|
|
203
|
+
/**
|
|
204
|
+
* Get drying mode level
|
|
205
|
+
*/
|
|
206
|
+
get dryingModeLevel(): number;
|
|
207
|
+
/**
|
|
208
|
+
* Get drying mode seconds remaining
|
|
209
|
+
*/
|
|
210
|
+
get dryingModeSecondsRemaining(): number;
|
|
179
211
|
}
|
|
180
212
|
export declare const fanModules: Record<string, new (details: Record<string, any>, manager: VeSync) => VeSyncFan>;
|
|
@@ -23,8 +23,45 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
23
23
|
* Get device details
|
|
24
24
|
*/
|
|
25
25
|
async getDetails() {
|
|
26
|
-
var _a;
|
|
26
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
27
27
|
logger_1.logger.debug(`Getting details for device: ${this.deviceName}`);
|
|
28
|
+
// Special handling for LV series
|
|
29
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
30
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/devicedetail', 'post', {
|
|
31
|
+
acceptLanguage: 'en',
|
|
32
|
+
accountID: this.manager.accountId,
|
|
33
|
+
appVersion: '2.8.6',
|
|
34
|
+
method: 'devicedetail',
|
|
35
|
+
mobileId: '1234567890123456',
|
|
36
|
+
phoneBrand: 'SM N9005',
|
|
37
|
+
phoneOS: 'Android',
|
|
38
|
+
timeZone: this.manager.timeZone,
|
|
39
|
+
token: this.manager.token,
|
|
40
|
+
uuid: this.uuid
|
|
41
|
+
}, {
|
|
42
|
+
'accept-language': 'en',
|
|
43
|
+
'accountId': this.manager.accountId,
|
|
44
|
+
'appVersion': '2.8.6',
|
|
45
|
+
'content-type': 'application/json',
|
|
46
|
+
'tk': this.manager.token,
|
|
47
|
+
'tz': this.manager.timeZone
|
|
48
|
+
});
|
|
49
|
+
const success = this.checkResponse([response, status], 'getDetails');
|
|
50
|
+
if (success && response) {
|
|
51
|
+
this.deviceStatus = ((_b = (_a = response.result) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.deviceStatus) === 'on' ? 'on' : 'off';
|
|
52
|
+
this.details = {
|
|
53
|
+
mode: ((_d = (_c = response.result) === null || _c === void 0 ? void 0 : _c.result) === null || _d === void 0 ? void 0 : _d.mode) || '',
|
|
54
|
+
speed: ((_f = (_e = response.result) === null || _e === void 0 ? void 0 : _e.result) === null || _f === void 0 ? void 0 : _f.level) || 0,
|
|
55
|
+
filterLife: ((_h = (_g = response.result) === null || _g === void 0 ? void 0 : _g.result) === null || _h === void 0 ? void 0 : _h.filterLife) || 0,
|
|
56
|
+
screenStatus: ((_k = (_j = response.result) === null || _j === void 0 ? void 0 : _j.result) === null || _k === void 0 ? void 0 : _k.display) || false,
|
|
57
|
+
childLock: ((_m = (_l = response.result) === null || _l === void 0 ? void 0 : _l.result) === null || _m === void 0 ? void 0 : _m.childLock) || false,
|
|
58
|
+
airQuality: ((_p = (_o = response.result) === null || _o === void 0 ? void 0 : _o.result) === null || _p === void 0 ? void 0 : _p.airQuality) || 0
|
|
59
|
+
};
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
// Original implementation for other devices
|
|
28
65
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
29
66
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
30
67
|
cid: this.cid,
|
|
@@ -37,11 +74,9 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
37
74
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
38
75
|
const success = this.checkResponse([response, status], 'getDetails');
|
|
39
76
|
if (success) {
|
|
40
|
-
const result = (
|
|
77
|
+
const result = (_q = response === null || response === void 0 ? void 0 : response.result) === null || _q === void 0 ? void 0 : _q.result;
|
|
41
78
|
if (result) {
|
|
42
|
-
// Update device status
|
|
43
79
|
this.deviceStatus = result.enabled ? 'on' : 'off';
|
|
44
|
-
// Store device settings
|
|
45
80
|
this.details = {
|
|
46
81
|
mode: result.mode || '',
|
|
47
82
|
speed: result.level || 0,
|
|
@@ -50,7 +85,6 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
50
85
|
childLock: result.child_lock || false,
|
|
51
86
|
airQuality: result.air_quality || 0
|
|
52
87
|
};
|
|
53
|
-
// Store configuration if available
|
|
54
88
|
if (result.configuration) {
|
|
55
89
|
this.config = result.configuration;
|
|
56
90
|
}
|
|
@@ -64,6 +98,30 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
64
98
|
*/
|
|
65
99
|
async turnOn() {
|
|
66
100
|
logger_1.logger.info(`Turning on device: ${this.deviceName}`);
|
|
101
|
+
// Special handling for LV series
|
|
102
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
103
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/deviceStatus', 'put', {
|
|
104
|
+
acceptLanguage: 'en',
|
|
105
|
+
accountID: this.manager.accountId,
|
|
106
|
+
status: 'on',
|
|
107
|
+
timeZone: this.manager.timeZone,
|
|
108
|
+
token: this.manager.token,
|
|
109
|
+
uuid: this.uuid
|
|
110
|
+
}, {
|
|
111
|
+
'accept-language': 'en',
|
|
112
|
+
'accountId': this.manager.accountId,
|
|
113
|
+
'appVersion': '2.8.6',
|
|
114
|
+
'content-type': 'application/json',
|
|
115
|
+
'tk': this.manager.token,
|
|
116
|
+
'tz': this.manager.timeZone
|
|
117
|
+
});
|
|
118
|
+
const success = this.checkResponse([response, status], 'turnOn');
|
|
119
|
+
if (!success) {
|
|
120
|
+
logger_1.logger.error(`Failed to turn on device: ${this.deviceName}`);
|
|
121
|
+
}
|
|
122
|
+
return success;
|
|
123
|
+
}
|
|
124
|
+
// Original implementation for other devices
|
|
67
125
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
68
126
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
69
127
|
cid: this.cid,
|
|
@@ -88,6 +146,30 @@ class VeSyncAirBypass extends vesyncFan_1.VeSyncFan {
|
|
|
88
146
|
*/
|
|
89
147
|
async turnOff() {
|
|
90
148
|
logger_1.logger.info(`Turning off device: ${this.deviceName}`);
|
|
149
|
+
// Special handling for LV series
|
|
150
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
151
|
+
const [response, status] = await this.callApi('/131airPurifier/v1/device/deviceStatus', 'put', {
|
|
152
|
+
acceptLanguage: 'en',
|
|
153
|
+
accountID: this.manager.accountId,
|
|
154
|
+
status: 'off',
|
|
155
|
+
timeZone: this.manager.timeZone,
|
|
156
|
+
token: this.manager.token,
|
|
157
|
+
uuid: this.uuid
|
|
158
|
+
}, {
|
|
159
|
+
'accept-language': 'en',
|
|
160
|
+
'accountId': this.manager.accountId,
|
|
161
|
+
'appVersion': '2.8.6',
|
|
162
|
+
'content-type': 'application/json',
|
|
163
|
+
'tk': this.manager.token,
|
|
164
|
+
'tz': this.manager.timeZone
|
|
165
|
+
});
|
|
166
|
+
const success = this.checkResponse([response, status], 'turnOff');
|
|
167
|
+
if (!success) {
|
|
168
|
+
logger_1.logger.error(`Failed to turn off device: ${this.deviceName}`);
|
|
169
|
+
}
|
|
170
|
+
return success;
|
|
171
|
+
}
|
|
172
|
+
// Original implementation for other devices
|
|
91
173
|
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
92
174
|
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
93
175
|
cid: this.cid,
|
|
@@ -421,11 +503,91 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
421
503
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
422
504
|
const success = this.checkResponse([response, status], 'getDetails');
|
|
423
505
|
if (success && ((_a = response === null || response === void 0 ? void 0 : response.result) === null || _a === void 0 ? void 0 : _a.result)) {
|
|
424
|
-
|
|
506
|
+
const result = response.result.result;
|
|
507
|
+
// Handle model-specific status fields
|
|
508
|
+
if (this.deviceType.startsWith('Classic') || this.deviceType === 'Dual200S') {
|
|
509
|
+
this.deviceStatus = result.enabled ? 'on' : 'off';
|
|
510
|
+
}
|
|
511
|
+
else {
|
|
512
|
+
this.deviceStatus = result.powerSwitch === 1 ? 'on' : 'off';
|
|
513
|
+
}
|
|
514
|
+
this.details = {
|
|
515
|
+
mode: result.mode || '',
|
|
516
|
+
humidity: result.humidity || 0,
|
|
517
|
+
mist_level: result.mistLevel || 0,
|
|
518
|
+
mist_virtual_level: result.virtualLevel || 0,
|
|
519
|
+
warm_level: result.warmLevel || 0,
|
|
520
|
+
water_lacks: result.waterLacks || false,
|
|
521
|
+
humidity_high: result.humidityHigh || false,
|
|
522
|
+
water_tank_lifted: result.waterTankLifted || false,
|
|
523
|
+
display: result.display || false,
|
|
524
|
+
automatic_stop: result.automaticStop || false,
|
|
525
|
+
configuration: result.configuration || {},
|
|
526
|
+
connection_status: result.connectionStatus || null
|
|
527
|
+
};
|
|
425
528
|
logger_1.logger.debug(`Successfully got details for device: ${this.deviceName}`);
|
|
426
529
|
}
|
|
427
530
|
return success;
|
|
428
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* Turn device on
|
|
534
|
+
*/
|
|
535
|
+
async turnOn() {
|
|
536
|
+
return this.toggleSwitch(true);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Turn device off
|
|
540
|
+
*/
|
|
541
|
+
async turnOff() {
|
|
542
|
+
return this.toggleSwitch(false);
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Get model-specific toggle payload
|
|
546
|
+
*/
|
|
547
|
+
getTogglePayload(enabled) {
|
|
548
|
+
// Model-specific toggle payload based on PyVeSync implementation
|
|
549
|
+
if (this.deviceType.startsWith('Classic') || this.deviceType === 'Dual200S') {
|
|
550
|
+
return {
|
|
551
|
+
enabled: enabled,
|
|
552
|
+
id: 0
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
else if (this.deviceType.startsWith('Superior')) {
|
|
556
|
+
return {
|
|
557
|
+
powerSwitch: enabled ? 1 : 0,
|
|
558
|
+
switchIdx: 0
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
return {
|
|
563
|
+
powerSwitch: enabled ? 1 : 0
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Toggle device power
|
|
569
|
+
*/
|
|
570
|
+
async toggleSwitch(enabled) {
|
|
571
|
+
logger_1.logger.info(`Setting device power to ${enabled ? 'on' : 'off'}: ${this.deviceName}`);
|
|
572
|
+
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
573
|
+
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
574
|
+
cid: this.cid,
|
|
575
|
+
configModule: this.configModule,
|
|
576
|
+
payload: {
|
|
577
|
+
data: this.getTogglePayload(enabled),
|
|
578
|
+
method: 'setSwitch',
|
|
579
|
+
source: 'APP'
|
|
580
|
+
}
|
|
581
|
+
}, helpers_1.Helpers.reqHeaderBypass());
|
|
582
|
+
const success = this.checkResponse([response, status], 'toggleSwitch');
|
|
583
|
+
if (success) {
|
|
584
|
+
this.deviceStatus = enabled ? 'on' : 'off';
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
logger_1.logger.error(`Failed to set device power to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
588
|
+
}
|
|
589
|
+
return success;
|
|
590
|
+
}
|
|
429
591
|
/**
|
|
430
592
|
* Set mist level
|
|
431
593
|
*/
|
|
@@ -491,54 +653,6 @@ class VeSyncHumidifier extends vesyncFan_1.VeSyncFan {
|
|
|
491
653
|
}
|
|
492
654
|
return success;
|
|
493
655
|
}
|
|
494
|
-
/**
|
|
495
|
-
* Turn device on
|
|
496
|
-
*/
|
|
497
|
-
async turnOn() {
|
|
498
|
-
logger_1.logger.info(`Turning on device: ${this.deviceName}`);
|
|
499
|
-
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
500
|
-
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
501
|
-
cid: this.cid,
|
|
502
|
-
configModule: this.configModule,
|
|
503
|
-
payload: {
|
|
504
|
-
data: {
|
|
505
|
-
enabled: true,
|
|
506
|
-
id: 0
|
|
507
|
-
},
|
|
508
|
-
method: 'setSwitch',
|
|
509
|
-
source: 'APP'
|
|
510
|
-
}
|
|
511
|
-
}, helpers_1.Helpers.reqHeaderBypass());
|
|
512
|
-
const success = this.checkResponse([response, status], 'turnOn');
|
|
513
|
-
if (!success) {
|
|
514
|
-
logger_1.logger.error(`Failed to turn on device: ${this.deviceName}`);
|
|
515
|
-
}
|
|
516
|
-
return success;
|
|
517
|
-
}
|
|
518
|
-
/**
|
|
519
|
-
* Turn device off
|
|
520
|
-
*/
|
|
521
|
-
async turnOff() {
|
|
522
|
-
logger_1.logger.info(`Turning off device: ${this.deviceName}`);
|
|
523
|
-
const [response, status] = await this.callApi('/cloud/v2/deviceManaged/bypassV2', 'post', {
|
|
524
|
-
...helpers_1.Helpers.reqBody(this.manager, 'bypassV2'),
|
|
525
|
-
cid: this.cid,
|
|
526
|
-
configModule: this.configModule,
|
|
527
|
-
payload: {
|
|
528
|
-
data: {
|
|
529
|
-
enabled: false,
|
|
530
|
-
id: 0
|
|
531
|
-
},
|
|
532
|
-
method: 'setSwitch',
|
|
533
|
-
source: 'APP'
|
|
534
|
-
}
|
|
535
|
-
}, helpers_1.Helpers.reqHeaderBypass());
|
|
536
|
-
const success = this.checkResponse([response, status], 'turnOff');
|
|
537
|
-
if (!success) {
|
|
538
|
-
logger_1.logger.error(`Failed to turn off device: ${this.deviceName}`);
|
|
539
|
-
}
|
|
540
|
-
return success;
|
|
541
|
-
}
|
|
542
656
|
/**
|
|
543
657
|
* Set target humidity
|
|
544
658
|
*/
|
|
@@ -756,6 +870,24 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
756
870
|
this.warmLevels = [1, 2, 3];
|
|
757
871
|
logger_1.logger.debug(`Initialized VeSyncWarmHumidifier device: ${this.deviceName}`);
|
|
758
872
|
}
|
|
873
|
+
/**
|
|
874
|
+
* Get device details
|
|
875
|
+
*/
|
|
876
|
+
async getDetails() {
|
|
877
|
+
const success = await super.getDetails();
|
|
878
|
+
if (success && this.details) {
|
|
879
|
+
// Add warm humidifier specific fields
|
|
880
|
+
this.details = {
|
|
881
|
+
...this.details,
|
|
882
|
+
warm_enabled: this.details.warm_level > 0,
|
|
883
|
+
drying_mode_enabled: this.details.autoDryingSwitch === 1,
|
|
884
|
+
drying_mode_state: this.details.dryingMode || '',
|
|
885
|
+
drying_mode_level: this.details.dryingLevel || 0,
|
|
886
|
+
drying_mode_seconds_remaining: this.details.dryingRemainTime || 0
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
return success;
|
|
890
|
+
}
|
|
759
891
|
/**
|
|
760
892
|
* Change fan speed - Implemented to satisfy interface but redirects to setMistLevel
|
|
761
893
|
*/
|
|
@@ -786,7 +918,10 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
786
918
|
}
|
|
787
919
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
788
920
|
const success = this.checkResponse([response, status], 'setMode');
|
|
789
|
-
if (
|
|
921
|
+
if (success) {
|
|
922
|
+
this.details.mode = mode;
|
|
923
|
+
}
|
|
924
|
+
else {
|
|
790
925
|
logger_1.logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
791
926
|
}
|
|
792
927
|
return success;
|
|
@@ -819,7 +954,11 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
819
954
|
}
|
|
820
955
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
821
956
|
const success = this.checkResponse([response, status], 'setWarmLevel');
|
|
822
|
-
if (
|
|
957
|
+
if (success) {
|
|
958
|
+
this.details.warm_level = level;
|
|
959
|
+
this.details.warm_enabled = level > 0;
|
|
960
|
+
}
|
|
961
|
+
else {
|
|
823
962
|
logger_1.logger.error(`Failed to set warm level to ${level} for device: ${this.deviceName}`);
|
|
824
963
|
}
|
|
825
964
|
return success;
|
|
@@ -847,11 +986,45 @@ class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
847
986
|
}
|
|
848
987
|
}, helpers_1.Helpers.reqHeaderBypass());
|
|
849
988
|
const success = this.checkResponse([response, status], 'setDryingModeEnabled');
|
|
850
|
-
if (
|
|
989
|
+
if (success) {
|
|
990
|
+
this.details.drying_mode_enabled = enabled;
|
|
991
|
+
this.details.autoDryingSwitch = enabled ? 1 : 0;
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
851
994
|
logger_1.logger.error(`Failed to set drying mode to ${enabled} for device: ${this.deviceName}`);
|
|
852
995
|
}
|
|
853
996
|
return success;
|
|
854
997
|
}
|
|
998
|
+
/**
|
|
999
|
+
* Get warm mist enabled status
|
|
1000
|
+
*/
|
|
1001
|
+
get warmMistEnabled() {
|
|
1002
|
+
return this.details.warm_enabled || false;
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Get drying mode enabled status
|
|
1006
|
+
*/
|
|
1007
|
+
get dryingModeEnabled() {
|
|
1008
|
+
return this.details.drying_mode_enabled || false;
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Get drying mode state
|
|
1012
|
+
*/
|
|
1013
|
+
get dryingModeState() {
|
|
1014
|
+
return this.details.drying_mode_state || '';
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Get drying mode level
|
|
1018
|
+
*/
|
|
1019
|
+
get dryingModeLevel() {
|
|
1020
|
+
return this.details.drying_mode_level || 0;
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Get drying mode seconds remaining
|
|
1024
|
+
*/
|
|
1025
|
+
get dryingModeSecondsRemaining() {
|
|
1026
|
+
return this.details.drying_mode_seconds_remaining || 0;
|
|
1027
|
+
}
|
|
855
1028
|
}
|
|
856
1029
|
exports.VeSyncWarmHumidifier = VeSyncWarmHumidifier;
|
|
857
1030
|
// Export fan modules dictionary
|
package/dist/lib/vesyncOutlet.js
CHANGED
|
@@ -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';
|
package/package.json
CHANGED
package/src/lib/vesync.ts
CHANGED
package/src/lib/vesyncFanImpl.ts
CHANGED
|
@@ -26,6 +26,51 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
26
26
|
*/
|
|
27
27
|
async getDetails(): Promise<Boolean> {
|
|
28
28
|
logger.debug(`Getting details for device: ${this.deviceName}`);
|
|
29
|
+
|
|
30
|
+
// Special handling for LV series
|
|
31
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
32
|
+
const [response, status] = await this.callApi(
|
|
33
|
+
'/131airPurifier/v1/device/devicedetail',
|
|
34
|
+
'post',
|
|
35
|
+
{
|
|
36
|
+
acceptLanguage: 'en',
|
|
37
|
+
accountID: this.manager.accountId!,
|
|
38
|
+
appVersion: '2.8.6',
|
|
39
|
+
method: 'devicedetail',
|
|
40
|
+
mobileId: '1234567890123456',
|
|
41
|
+
phoneBrand: 'SM N9005',
|
|
42
|
+
phoneOS: 'Android',
|
|
43
|
+
timeZone: this.manager.timeZone!,
|
|
44
|
+
token: this.manager.token!,
|
|
45
|
+
uuid: this.uuid
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
'accept-language': 'en',
|
|
49
|
+
'accountId': this.manager.accountId!,
|
|
50
|
+
'appVersion': '2.8.6',
|
|
51
|
+
'content-type': 'application/json',
|
|
52
|
+
'tk': this.manager.token!,
|
|
53
|
+
'tz': this.manager.timeZone!
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const success = this.checkResponse([response, status], 'getDetails');
|
|
58
|
+
if (success && response) {
|
|
59
|
+
this.deviceStatus = response.result?.result?.deviceStatus === 'on' ? 'on' : 'off';
|
|
60
|
+
this.details = {
|
|
61
|
+
mode: response.result?.result?.mode || '',
|
|
62
|
+
speed: response.result?.result?.level || 0,
|
|
63
|
+
filterLife: response.result?.result?.filterLife || 0,
|
|
64
|
+
screenStatus: response.result?.result?.display || false,
|
|
65
|
+
childLock: response.result?.result?.childLock || false,
|
|
66
|
+
airQuality: response.result?.result?.airQuality || 0
|
|
67
|
+
};
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Original implementation for other devices
|
|
29
74
|
const [response, status] = await this.callApi(
|
|
30
75
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
31
76
|
'post',
|
|
@@ -46,10 +91,7 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
46
91
|
if (success) {
|
|
47
92
|
const result = response?.result?.result;
|
|
48
93
|
if (result) {
|
|
49
|
-
// Update device status
|
|
50
94
|
this.deviceStatus = result.enabled ? 'on' : 'off';
|
|
51
|
-
|
|
52
|
-
// Store device settings
|
|
53
95
|
this.details = {
|
|
54
96
|
mode: result.mode || '',
|
|
55
97
|
speed: result.level || 0,
|
|
@@ -59,7 +101,6 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
59
101
|
airQuality: result.air_quality || 0
|
|
60
102
|
};
|
|
61
103
|
|
|
62
|
-
// Store configuration if available
|
|
63
104
|
if (result.configuration) {
|
|
64
105
|
this.config = result.configuration;
|
|
65
106
|
}
|
|
@@ -74,6 +115,38 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
74
115
|
*/
|
|
75
116
|
async turnOn(): Promise<boolean> {
|
|
76
117
|
logger.info(`Turning on device: ${this.deviceName}`);
|
|
118
|
+
|
|
119
|
+
// Special handling for LV series
|
|
120
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
121
|
+
const [response, status] = await this.callApi(
|
|
122
|
+
'/131airPurifier/v1/device/deviceStatus',
|
|
123
|
+
'put',
|
|
124
|
+
{
|
|
125
|
+
acceptLanguage: 'en',
|
|
126
|
+
accountID: this.manager.accountId!,
|
|
127
|
+
status: 'on',
|
|
128
|
+
timeZone: this.manager.timeZone!,
|
|
129
|
+
token: this.manager.token!,
|
|
130
|
+
uuid: this.uuid
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
'accept-language': 'en',
|
|
134
|
+
'accountId': this.manager.accountId!,
|
|
135
|
+
'appVersion': '2.8.6',
|
|
136
|
+
'content-type': 'application/json',
|
|
137
|
+
'tk': this.manager.token!,
|
|
138
|
+
'tz': this.manager.timeZone!
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const success = this.checkResponse([response, status], 'turnOn');
|
|
143
|
+
if (!success) {
|
|
144
|
+
logger.error(`Failed to turn on device: ${this.deviceName}`);
|
|
145
|
+
}
|
|
146
|
+
return success;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Original implementation for other devices
|
|
77
150
|
const [response, status] = await this.callApi(
|
|
78
151
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
79
152
|
'post',
|
|
@@ -105,6 +178,38 @@ export class VeSyncAirBypass extends VeSyncFan {
|
|
|
105
178
|
*/
|
|
106
179
|
async turnOff(): Promise<boolean> {
|
|
107
180
|
logger.info(`Turning off device: ${this.deviceName}`);
|
|
181
|
+
|
|
182
|
+
// Special handling for LV series
|
|
183
|
+
if (this.deviceType.startsWith('LV-')) {
|
|
184
|
+
const [response, status] = await this.callApi(
|
|
185
|
+
'/131airPurifier/v1/device/deviceStatus',
|
|
186
|
+
'put',
|
|
187
|
+
{
|
|
188
|
+
acceptLanguage: 'en',
|
|
189
|
+
accountID: this.manager.accountId!,
|
|
190
|
+
status: 'off',
|
|
191
|
+
timeZone: this.manager.timeZone!,
|
|
192
|
+
token: this.manager.token!,
|
|
193
|
+
uuid: this.uuid
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
'accept-language': 'en',
|
|
197
|
+
'accountId': this.manager.accountId!,
|
|
198
|
+
'appVersion': '2.8.6',
|
|
199
|
+
'content-type': 'application/json',
|
|
200
|
+
'tk': this.manager.token!,
|
|
201
|
+
'tz': this.manager.timeZone!
|
|
202
|
+
}
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const success = this.checkResponse([response, status], 'turnOff');
|
|
206
|
+
if (!success) {
|
|
207
|
+
logger.error(`Failed to turn off device: ${this.deviceName}`);
|
|
208
|
+
}
|
|
209
|
+
return success;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Original implementation for other devices
|
|
108
213
|
const [response, status] = await this.callApi(
|
|
109
214
|
'/cloud/v2/deviceManaged/bypassV2',
|
|
110
215
|
'post',
|
|
@@ -519,12 +624,100 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
519
624
|
|
|
520
625
|
const success = this.checkResponse([response, status], 'getDetails');
|
|
521
626
|
if (success && response?.result?.result) {
|
|
522
|
-
|
|
627
|
+
const result = response.result.result;
|
|
628
|
+
|
|
629
|
+
// Handle model-specific status fields
|
|
630
|
+
if (this.deviceType.startsWith('Classic') || this.deviceType === 'Dual200S') {
|
|
631
|
+
this.deviceStatus = result.enabled ? 'on' : 'off';
|
|
632
|
+
} else {
|
|
633
|
+
this.deviceStatus = result.powerSwitch === 1 ? 'on' : 'off';
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
this.details = {
|
|
637
|
+
mode: result.mode || '',
|
|
638
|
+
humidity: result.humidity || 0,
|
|
639
|
+
mist_level: result.mistLevel || 0,
|
|
640
|
+
mist_virtual_level: result.virtualLevel || 0,
|
|
641
|
+
warm_level: result.warmLevel || 0,
|
|
642
|
+
water_lacks: result.waterLacks || false,
|
|
643
|
+
humidity_high: result.humidityHigh || false,
|
|
644
|
+
water_tank_lifted: result.waterTankLifted || false,
|
|
645
|
+
display: result.display || false,
|
|
646
|
+
automatic_stop: result.automaticStop || false,
|
|
647
|
+
configuration: result.configuration || {},
|
|
648
|
+
connection_status: result.connectionStatus || null
|
|
649
|
+
};
|
|
523
650
|
logger.debug(`Successfully got details for device: ${this.deviceName}`);
|
|
524
651
|
}
|
|
525
652
|
return success;
|
|
526
653
|
}
|
|
527
654
|
|
|
655
|
+
/**
|
|
656
|
+
* Turn device on
|
|
657
|
+
*/
|
|
658
|
+
async turnOn(): Promise<boolean> {
|
|
659
|
+
return this.toggleSwitch(true);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* Turn device off
|
|
664
|
+
*/
|
|
665
|
+
async turnOff(): Promise<boolean> {
|
|
666
|
+
return this.toggleSwitch(false);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Get model-specific toggle payload
|
|
671
|
+
*/
|
|
672
|
+
protected getTogglePayload(enabled: boolean): Record<string, any> {
|
|
673
|
+
// Model-specific toggle payload based on PyVeSync implementation
|
|
674
|
+
if (this.deviceType.startsWith('Classic') || this.deviceType === 'Dual200S') {
|
|
675
|
+
return {
|
|
676
|
+
enabled: enabled,
|
|
677
|
+
id: 0
|
|
678
|
+
};
|
|
679
|
+
} else if (this.deviceType.startsWith('Superior')) {
|
|
680
|
+
return {
|
|
681
|
+
powerSwitch: enabled ? 1 : 0,
|
|
682
|
+
switchIdx: 0
|
|
683
|
+
};
|
|
684
|
+
} else {
|
|
685
|
+
return {
|
|
686
|
+
powerSwitch: enabled ? 1 : 0
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Toggle device power
|
|
693
|
+
*/
|
|
694
|
+
async toggleSwitch(enabled: boolean): Promise<boolean> {
|
|
695
|
+
logger.info(`Setting device power to ${enabled ? 'on' : 'off'}: ${this.deviceName}`);
|
|
696
|
+
const [response, status] = await this.callApi(
|
|
697
|
+
'/cloud/v2/deviceManaged/bypassV2',
|
|
698
|
+
'post',
|
|
699
|
+
{
|
|
700
|
+
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
701
|
+
cid: this.cid,
|
|
702
|
+
configModule: this.configModule,
|
|
703
|
+
payload: {
|
|
704
|
+
data: this.getTogglePayload(enabled),
|
|
705
|
+
method: 'setSwitch',
|
|
706
|
+
source: 'APP'
|
|
707
|
+
}
|
|
708
|
+
},
|
|
709
|
+
Helpers.reqHeaderBypass()
|
|
710
|
+
);
|
|
711
|
+
|
|
712
|
+
const success = this.checkResponse([response, status], 'toggleSwitch');
|
|
713
|
+
if (success) {
|
|
714
|
+
this.deviceStatus = enabled ? 'on' : 'off';
|
|
715
|
+
} else {
|
|
716
|
+
logger.error(`Failed to set device power to ${enabled ? 'on' : 'off'} for device: ${this.deviceName}`);
|
|
717
|
+
}
|
|
718
|
+
return success;
|
|
719
|
+
}
|
|
720
|
+
|
|
528
721
|
/**
|
|
529
722
|
* Set mist level
|
|
530
723
|
*/
|
|
@@ -607,68 +800,6 @@ export class VeSyncHumidifier extends VeSyncFan {
|
|
|
607
800
|
return success;
|
|
608
801
|
}
|
|
609
802
|
|
|
610
|
-
/**
|
|
611
|
-
* Turn device on
|
|
612
|
-
*/
|
|
613
|
-
async turnOn(): Promise<boolean> {
|
|
614
|
-
logger.info(`Turning on device: ${this.deviceName}`);
|
|
615
|
-
const [response, status] = await this.callApi(
|
|
616
|
-
'/cloud/v2/deviceManaged/bypassV2',
|
|
617
|
-
'post',
|
|
618
|
-
{
|
|
619
|
-
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
620
|
-
cid: this.cid,
|
|
621
|
-
configModule: this.configModule,
|
|
622
|
-
payload: {
|
|
623
|
-
data: {
|
|
624
|
-
enabled: true,
|
|
625
|
-
id: 0
|
|
626
|
-
},
|
|
627
|
-
method: 'setSwitch',
|
|
628
|
-
source: 'APP'
|
|
629
|
-
}
|
|
630
|
-
},
|
|
631
|
-
Helpers.reqHeaderBypass()
|
|
632
|
-
);
|
|
633
|
-
|
|
634
|
-
const success = this.checkResponse([response, status], 'turnOn');
|
|
635
|
-
if (!success) {
|
|
636
|
-
logger.error(`Failed to turn on device: ${this.deviceName}`);
|
|
637
|
-
}
|
|
638
|
-
return success;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
/**
|
|
642
|
-
* Turn device off
|
|
643
|
-
*/
|
|
644
|
-
async turnOff(): Promise<boolean> {
|
|
645
|
-
logger.info(`Turning off device: ${this.deviceName}`);
|
|
646
|
-
const [response, status] = await this.callApi(
|
|
647
|
-
'/cloud/v2/deviceManaged/bypassV2',
|
|
648
|
-
'post',
|
|
649
|
-
{
|
|
650
|
-
...Helpers.reqBody(this.manager, 'bypassV2'),
|
|
651
|
-
cid: this.cid,
|
|
652
|
-
configModule: this.configModule,
|
|
653
|
-
payload: {
|
|
654
|
-
data: {
|
|
655
|
-
enabled: false,
|
|
656
|
-
id: 0
|
|
657
|
-
},
|
|
658
|
-
method: 'setSwitch',
|
|
659
|
-
source: 'APP'
|
|
660
|
-
}
|
|
661
|
-
},
|
|
662
|
-
Helpers.reqHeaderBypass()
|
|
663
|
-
);
|
|
664
|
-
|
|
665
|
-
const success = this.checkResponse([response, status], 'turnOff');
|
|
666
|
-
if (!success) {
|
|
667
|
-
logger.error(`Failed to turn off device: ${this.deviceName}`);
|
|
668
|
-
}
|
|
669
|
-
return success;
|
|
670
|
-
}
|
|
671
|
-
|
|
672
803
|
/**
|
|
673
804
|
* Set target humidity
|
|
674
805
|
*/
|
|
@@ -938,6 +1069,25 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
938
1069
|
logger.debug(`Initialized VeSyncWarmHumidifier device: ${this.deviceName}`);
|
|
939
1070
|
}
|
|
940
1071
|
|
|
1072
|
+
/**
|
|
1073
|
+
* Get device details
|
|
1074
|
+
*/
|
|
1075
|
+
async getDetails(): Promise<Boolean> {
|
|
1076
|
+
const success = await super.getDetails();
|
|
1077
|
+
if (success && this.details) {
|
|
1078
|
+
// Add warm humidifier specific fields
|
|
1079
|
+
this.details = {
|
|
1080
|
+
...this.details,
|
|
1081
|
+
warm_enabled: this.details.warm_level > 0,
|
|
1082
|
+
drying_mode_enabled: this.details.autoDryingSwitch === 1,
|
|
1083
|
+
drying_mode_state: this.details.dryingMode || '',
|
|
1084
|
+
drying_mode_level: this.details.dryingLevel || 0,
|
|
1085
|
+
drying_mode_seconds_remaining: this.details.dryingRemainTime || 0
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
return success;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
941
1091
|
/**
|
|
942
1092
|
* Change fan speed - Implemented to satisfy interface but redirects to setMistLevel
|
|
943
1093
|
*/
|
|
@@ -976,7 +1126,9 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
976
1126
|
);
|
|
977
1127
|
|
|
978
1128
|
const success = this.checkResponse([response, status], 'setMode');
|
|
979
|
-
if (
|
|
1129
|
+
if (success) {
|
|
1130
|
+
this.details.mode = mode;
|
|
1131
|
+
} else {
|
|
980
1132
|
logger.error(`Failed to set mode to ${mode} for device: ${this.deviceName}`);
|
|
981
1133
|
}
|
|
982
1134
|
return success;
|
|
@@ -1018,7 +1170,10 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1018
1170
|
);
|
|
1019
1171
|
|
|
1020
1172
|
const success = this.checkResponse([response, status], 'setWarmLevel');
|
|
1021
|
-
if (
|
|
1173
|
+
if (success) {
|
|
1174
|
+
this.details.warm_level = level;
|
|
1175
|
+
this.details.warm_enabled = level > 0;
|
|
1176
|
+
} else {
|
|
1022
1177
|
logger.error(`Failed to set warm level to ${level} for device: ${this.deviceName}`);
|
|
1023
1178
|
}
|
|
1024
1179
|
return success;
|
|
@@ -1054,11 +1209,49 @@ export class VeSyncWarmHumidifier extends VeSyncHumidifier {
|
|
|
1054
1209
|
);
|
|
1055
1210
|
|
|
1056
1211
|
const success = this.checkResponse([response, status], 'setDryingModeEnabled');
|
|
1057
|
-
if (
|
|
1212
|
+
if (success) {
|
|
1213
|
+
this.details.drying_mode_enabled = enabled;
|
|
1214
|
+
this.details.autoDryingSwitch = enabled ? 1 : 0;
|
|
1215
|
+
} else {
|
|
1058
1216
|
logger.error(`Failed to set drying mode to ${enabled} for device: ${this.deviceName}`);
|
|
1059
1217
|
}
|
|
1060
1218
|
return success;
|
|
1061
1219
|
}
|
|
1220
|
+
|
|
1221
|
+
/**
|
|
1222
|
+
* Get warm mist enabled status
|
|
1223
|
+
*/
|
|
1224
|
+
get warmMistEnabled(): boolean {
|
|
1225
|
+
return this.details.warm_enabled || false;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
/**
|
|
1229
|
+
* Get drying mode enabled status
|
|
1230
|
+
*/
|
|
1231
|
+
get dryingModeEnabled(): boolean {
|
|
1232
|
+
return this.details.drying_mode_enabled || false;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* Get drying mode state
|
|
1237
|
+
*/
|
|
1238
|
+
get dryingModeState(): string {
|
|
1239
|
+
return this.details.drying_mode_state || '';
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
/**
|
|
1243
|
+
* Get drying mode level
|
|
1244
|
+
*/
|
|
1245
|
+
get dryingModeLevel(): number {
|
|
1246
|
+
return this.details.drying_mode_level || 0;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
/**
|
|
1250
|
+
* Get drying mode seconds remaining
|
|
1251
|
+
*/
|
|
1252
|
+
get dryingModeSecondsRemaining(): number {
|
|
1253
|
+
return this.details.drying_mode_seconds_remaining || 0;
|
|
1254
|
+
}
|
|
1062
1255
|
}
|
|
1063
1256
|
|
|
1064
1257
|
// Export fan modules dictionary
|
package/src/lib/vesyncOutlet.ts
CHANGED
|
@@ -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
|
};
|