tsvesync 1.0.13 → 1.0.14
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/package.json +1 -1
- package/dist/lib/helpers.js.map +0 -1
- package/dist/lib/vesync.js.map +0 -1
- package/dist/lib/vesyncBaseDevice.js.map +0 -1
- package/dist/lib/vesyncBulb.js.map +0 -1
- package/dist/lib/vesyncFan.js.map +0 -1
- package/dist/lib/vesyncKitchen.d.ts +0 -0
- package/dist/lib/vesyncKitchen.js +0 -2
- package/dist/lib/vesyncKitchen.js.map +0 -1
- package/dist/lib/vesyncOutlet.js.map +0 -1
- package/dist/lib/vesyncSwitch.js.map +0 -1
- package/dist/src/lib/helpers.d.ts +0 -88
- package/dist/src/lib/helpers.js +0 -244
- package/dist/src/lib/vesync.d.ts +0 -89
- package/dist/src/lib/vesync.js +0 -430
- package/dist/src/lib/vesyncBaseDevice.d.ts +0 -43
- package/dist/src/lib/vesyncBaseDevice.js +0 -87
- package/dist/src/lib/vesyncBulb.d.ts +0 -79
- package/dist/src/lib/vesyncBulb.js +0 -198
- package/dist/src/lib/vesyncBulbImpl.d.ts +0 -38
- package/dist/src/lib/vesyncBulbImpl.js +0 -161
- package/dist/src/lib/vesyncFan.d.ts +0 -80
- package/dist/src/lib/vesyncFan.js +0 -406
- package/dist/src/lib/vesyncFanImpl.d.ts +0 -137
- package/dist/src/lib/vesyncFanImpl.js +0 -643
- package/dist/src/lib/vesyncOutlet.d.ts +0 -53
- package/dist/src/lib/vesyncOutlet.js +0 -98
- package/dist/src/lib/vesyncOutletImpl.d.ts +0 -70
- package/dist/src/lib/vesyncOutletImpl.js +0 -206
- package/dist/src/lib/vesyncSwitch.d.ts +0 -169
- package/dist/src/lib/vesyncSwitch.js +0 -414
- package/dist/src/lib/vesyncSwitchImpl.d.ts +0 -82
- package/dist/src/lib/vesyncSwitchImpl.js +0 -290
- package/dist/test/testFeatures.d.ts +0 -4
- package/dist/test/testFeatures.js +0 -394
- package/dist/test/testService.d.ts +0 -62
- package/dist/test/testService.js +0 -540
- package/dist/test/testSpecial.d.ts +0 -5
- package/dist/test/testSpecial.js +0 -227
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* VeSync Switch Implementations
|
|
4
|
-
*/
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.switchModules = exports.VeSyncDimmerSwitch = exports.VeSyncWallSwitch = void 0;
|
|
7
|
-
const vesyncSwitch_1 = require("./vesyncSwitch");
|
|
8
|
-
const helpers_1 = require("./helpers");
|
|
9
|
-
/**
|
|
10
|
-
* Basic Wall Switch Implementation (ESWL01, ESWL03)
|
|
11
|
-
*/
|
|
12
|
-
class VeSyncWallSwitch extends vesyncSwitch_1.VeSyncSwitch {
|
|
13
|
-
constructor(details, manager) {
|
|
14
|
-
super(details, manager);
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Get wall switch details
|
|
18
|
-
*/
|
|
19
|
-
async getDetails() {
|
|
20
|
-
const body = {
|
|
21
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicedetail'),
|
|
22
|
-
uuid: this.cid,
|
|
23
|
-
method: 'devicedetail'
|
|
24
|
-
};
|
|
25
|
-
const [response] = await helpers_1.Helpers.callApi('/inwallswitch/v1/device/devicedetail', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
26
|
-
if (response?.code === 0 && response?.result) {
|
|
27
|
-
const result = response.result;
|
|
28
|
-
this.deviceStatus = result.deviceStatus || this.deviceStatus;
|
|
29
|
-
this.details.active_time = result.activeTime || 0;
|
|
30
|
-
this.connectionStatus = result.connectionStatus || this.connectionStatus;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Get switch device configuration info
|
|
35
|
-
*/
|
|
36
|
-
async getConfig() {
|
|
37
|
-
const body = {
|
|
38
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicedetail'),
|
|
39
|
-
method: 'configurations',
|
|
40
|
-
uuid: this.cid
|
|
41
|
-
};
|
|
42
|
-
const [response] = await helpers_1.Helpers.callApi('/inwallswitch/v1/device/configurations', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
43
|
-
if (response?.code === 0) {
|
|
44
|
-
this.config = helpers_1.Helpers.buildConfigDict(response);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Turn off wall switch
|
|
49
|
-
*/
|
|
50
|
-
async turnOff() {
|
|
51
|
-
const body = {
|
|
52
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
53
|
-
status: 'off',
|
|
54
|
-
uuid: this.cid
|
|
55
|
-
};
|
|
56
|
-
const [response] = await helpers_1.Helpers.callApi('/inwallswitch/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
57
|
-
if (response?.code === 0) {
|
|
58
|
-
this.deviceStatus = 'off';
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Turn on wall switch
|
|
65
|
-
*/
|
|
66
|
-
async turnOn() {
|
|
67
|
-
const body = {
|
|
68
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
69
|
-
status: 'on',
|
|
70
|
-
uuid: this.cid
|
|
71
|
-
};
|
|
72
|
-
const [response] = await helpers_1.Helpers.callApi('/inwallswitch/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
73
|
-
if (response?.code === 0) {
|
|
74
|
-
this.deviceStatus = 'on';
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
exports.VeSyncWallSwitch = VeSyncWallSwitch;
|
|
81
|
-
/**
|
|
82
|
-
* Dimmer Switch Implementation (ESWD16)
|
|
83
|
-
*/
|
|
84
|
-
class VeSyncDimmerSwitch extends vesyncSwitch_1.VeSyncSwitch {
|
|
85
|
-
constructor(details, manager) {
|
|
86
|
-
super(details, manager);
|
|
87
|
-
this._brightness = 0;
|
|
88
|
-
this._rgbValue = { red: 0, blue: 0, green: 0 };
|
|
89
|
-
this._rgbStatus = 'unknown';
|
|
90
|
-
this._indicatorLight = 'unknown';
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Get dimmer switch details
|
|
94
|
-
*/
|
|
95
|
-
async getDetails() {
|
|
96
|
-
const body = {
|
|
97
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicedetail'),
|
|
98
|
-
uuid: this.cid,
|
|
99
|
-
method: 'devicedetail'
|
|
100
|
-
};
|
|
101
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/devicedetail', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
102
|
-
if (response?.code === 0 && response?.result) {
|
|
103
|
-
const result = response.result;
|
|
104
|
-
this.deviceStatus = result.deviceStatus || this.deviceStatus;
|
|
105
|
-
this.details.active_time = result.activeTime || 0;
|
|
106
|
-
this.connectionStatus = result.connectionStatus || this.connectionStatus;
|
|
107
|
-
this._brightness = result.brightness || this._brightness;
|
|
108
|
-
this._rgbStatus = result.rgbStatus || this._rgbStatus;
|
|
109
|
-
this._indicatorLight = result.indicatorlightStatus || this._indicatorLight;
|
|
110
|
-
if (result.rgbValue) {
|
|
111
|
-
this._rgbValue = {
|
|
112
|
-
red: result.rgbValue.red || 0,
|
|
113
|
-
green: result.rgbValue.green || 0,
|
|
114
|
-
blue: result.rgbValue.blue || 0
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Get dimmer switch configuration info
|
|
121
|
-
*/
|
|
122
|
-
async getConfig() {
|
|
123
|
-
const body = {
|
|
124
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicedetail'),
|
|
125
|
-
method: 'configurations',
|
|
126
|
-
uuid: this.cid
|
|
127
|
-
};
|
|
128
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/configurations', 'post', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
129
|
-
if (response?.code === 0) {
|
|
130
|
-
this.config = helpers_1.Helpers.buildConfigDict(response);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Turn off dimmer switch
|
|
135
|
-
*/
|
|
136
|
-
async turnOff() {
|
|
137
|
-
const body = {
|
|
138
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
139
|
-
status: 'off',
|
|
140
|
-
uuid: this.cid
|
|
141
|
-
};
|
|
142
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
143
|
-
if (response?.code === 0) {
|
|
144
|
-
this.deviceStatus = 'off';
|
|
145
|
-
return true;
|
|
146
|
-
}
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Turn on dimmer switch
|
|
151
|
-
*/
|
|
152
|
-
async turnOn() {
|
|
153
|
-
const body = {
|
|
154
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
155
|
-
status: 'on',
|
|
156
|
-
uuid: this.cid
|
|
157
|
-
};
|
|
158
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/devicestatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
159
|
-
if (response?.code === 0) {
|
|
160
|
-
this.deviceStatus = 'on';
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Set brightness level
|
|
167
|
-
*/
|
|
168
|
-
async setBrightness(brightness) {
|
|
169
|
-
if (!this.isDimmable()) {
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
const body = {
|
|
173
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
174
|
-
brightness: brightness.toString(),
|
|
175
|
-
uuid: this.cid
|
|
176
|
-
};
|
|
177
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/updatebrightness', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
178
|
-
if (response?.code === 0) {
|
|
179
|
-
this._brightness = brightness;
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Set RGB indicator color
|
|
186
|
-
*/
|
|
187
|
-
async rgbColorSet(red, green, blue) {
|
|
188
|
-
const body = {
|
|
189
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
190
|
-
rgbValue: {
|
|
191
|
-
red: Math.round(red),
|
|
192
|
-
green: Math.round(green),
|
|
193
|
-
blue: Math.round(blue)
|
|
194
|
-
},
|
|
195
|
-
status: 'on',
|
|
196
|
-
uuid: this.cid
|
|
197
|
-
};
|
|
198
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/devicergbstatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
199
|
-
if (response?.code === 0) {
|
|
200
|
-
this._rgbValue = { red, green, blue };
|
|
201
|
-
this._rgbStatus = 'on';
|
|
202
|
-
return true;
|
|
203
|
-
}
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Turn on RGB indicator
|
|
208
|
-
*/
|
|
209
|
-
async rgbColorOn() {
|
|
210
|
-
const body = {
|
|
211
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
212
|
-
status: 'on',
|
|
213
|
-
uuid: this.cid
|
|
214
|
-
};
|
|
215
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/devicergbstatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
216
|
-
if (response?.code === 0) {
|
|
217
|
-
this._rgbStatus = 'on';
|
|
218
|
-
return true;
|
|
219
|
-
}
|
|
220
|
-
return false;
|
|
221
|
-
}
|
|
222
|
-
/**
|
|
223
|
-
* Turn off RGB indicator
|
|
224
|
-
*/
|
|
225
|
-
async rgbColorOff() {
|
|
226
|
-
const body = {
|
|
227
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
228
|
-
status: 'off',
|
|
229
|
-
uuid: this.cid
|
|
230
|
-
};
|
|
231
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/devicergbstatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
232
|
-
if (response?.code === 0) {
|
|
233
|
-
this._rgbStatus = 'off';
|
|
234
|
-
return true;
|
|
235
|
-
}
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Turn on indicator light
|
|
240
|
-
*/
|
|
241
|
-
async indicatorLightOn() {
|
|
242
|
-
const body = {
|
|
243
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
244
|
-
status: 'on',
|
|
245
|
-
uuid: this.cid
|
|
246
|
-
};
|
|
247
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/indicatorlightstatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
248
|
-
if (response?.code === 0) {
|
|
249
|
-
this._indicatorLight = 'on';
|
|
250
|
-
return true;
|
|
251
|
-
}
|
|
252
|
-
return false;
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Turn off indicator light
|
|
256
|
-
*/
|
|
257
|
-
async indicatorLightOff() {
|
|
258
|
-
const body = {
|
|
259
|
-
...helpers_1.Helpers.reqBody(this.manager, 'devicestatus'),
|
|
260
|
-
status: 'off',
|
|
261
|
-
uuid: this.cid
|
|
262
|
-
};
|
|
263
|
-
const [response] = await helpers_1.Helpers.callApi('/dimmer/v1/device/indicatorlightstatus', 'put', body, helpers_1.Helpers.reqHeaders(this.manager));
|
|
264
|
-
if (response?.code === 0) {
|
|
265
|
-
this._indicatorLight = 'off';
|
|
266
|
-
return true;
|
|
267
|
-
}
|
|
268
|
-
return false;
|
|
269
|
-
}
|
|
270
|
-
// Getters
|
|
271
|
-
get brightness() {
|
|
272
|
-
return this._brightness;
|
|
273
|
-
}
|
|
274
|
-
get indicatorLightStatus() {
|
|
275
|
-
return this._indicatorLight;
|
|
276
|
-
}
|
|
277
|
-
get rgbLightStatus() {
|
|
278
|
-
return this._rgbStatus;
|
|
279
|
-
}
|
|
280
|
-
get rgbLightValue() {
|
|
281
|
-
return { ...this._rgbValue };
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
exports.VeSyncDimmerSwitch = VeSyncDimmerSwitch;
|
|
285
|
-
// Export the switch modules dictionary
|
|
286
|
-
exports.switchModules = {
|
|
287
|
-
'ESWL01': VeSyncWallSwitch,
|
|
288
|
-
'ESWL03': VeSyncWallSwitch,
|
|
289
|
-
'ESWD16': VeSyncDimmerSwitch
|
|
290
|
-
};
|
|
@@ -1,394 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Test all device features using TSVeSync device classes
|
|
4
|
-
*/
|
|
5
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
-
}
|
|
11
|
-
Object.defineProperty(o, k2, desc);
|
|
12
|
-
}) : (function(o, m, k, k2) {
|
|
13
|
-
if (k2 === undefined) k2 = k;
|
|
14
|
-
o[k2] = m[k];
|
|
15
|
-
}));
|
|
16
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
-
}) : function(o, v) {
|
|
19
|
-
o["default"] = v;
|
|
20
|
-
});
|
|
21
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
-
var ownKeys = function(o) {
|
|
23
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
-
var ar = [];
|
|
25
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
-
return ar;
|
|
27
|
-
};
|
|
28
|
-
return ownKeys(o);
|
|
29
|
-
};
|
|
30
|
-
return function (mod) {
|
|
31
|
-
if (mod && mod.__esModule) return mod;
|
|
32
|
-
var result = {};
|
|
33
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
-
__setModuleDefault(result, mod);
|
|
35
|
-
return result;
|
|
36
|
-
};
|
|
37
|
-
})();
|
|
38
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
const vesync_1 = require("../src/lib/vesync");
|
|
40
|
-
const fs = __importStar(require("fs"));
|
|
41
|
-
const path = __importStar(require("path"));
|
|
42
|
-
const yaml = __importStar(require("js-yaml"));
|
|
43
|
-
const helpers_1 = require("../src/lib/helpers");
|
|
44
|
-
// Configure logging
|
|
45
|
-
const DEBUG = true;
|
|
46
|
-
class DeviceFeatureTest {
|
|
47
|
-
constructor() {
|
|
48
|
-
this.deviceSpecs = new Map();
|
|
49
|
-
this.testSummary = new Map();
|
|
50
|
-
// Method name mapping from Python snake_case to TypeScript camelCase
|
|
51
|
-
this.methodNameMap = {
|
|
52
|
-
'change_fan_speed': 'changeFanSpeed',
|
|
53
|
-
'set_brightness': 'setBrightness',
|
|
54
|
-
'set_color_temp': 'setColorTemp',
|
|
55
|
-
'set_hsv': 'setHsv',
|
|
56
|
-
'set_timer': 'setTimer',
|
|
57
|
-
'set_mist_level': 'setMistLevel',
|
|
58
|
-
'set_warm_level': 'setWarmLevel',
|
|
59
|
-
'set_drying_mode_enabled': 'setDryingModeEnabled',
|
|
60
|
-
'change_mode': 'setMode',
|
|
61
|
-
'get_monthly_energy': 'getMonthlyEnergy',
|
|
62
|
-
'get_weekly_energy': 'getWeeklyEnergy',
|
|
63
|
-
'get_yearly_energy': 'getYearlyEnergy',
|
|
64
|
-
'rgb_color_set': 'rgbColorSet',
|
|
65
|
-
'rgb_color_on': 'rgbColorOn',
|
|
66
|
-
'rgb_color_off': 'rgbColorOff',
|
|
67
|
-
'set_temperature': 'setTemperature',
|
|
68
|
-
'set_cooking_time': 'setCookingTime',
|
|
69
|
-
'set_cooking_mode': 'setCookingMode',
|
|
70
|
-
'turn_on': 'turnOn',
|
|
71
|
-
'turn_off': 'turnOff',
|
|
72
|
-
'turn_on_nightlight': 'turnOnNightlight',
|
|
73
|
-
'turn_off_nightlight': 'turnOffNightlight',
|
|
74
|
-
'toggle': 'toggle',
|
|
75
|
-
'clear_timer': 'clearTimer',
|
|
76
|
-
'manual_mode': 'setMode',
|
|
77
|
-
'sleep_mode': 'setMode',
|
|
78
|
-
'turn_off_display': 'setDisplay',
|
|
79
|
-
'turn_on_display': 'setDisplay',
|
|
80
|
-
'update': 'update',
|
|
81
|
-
'auto_mode': 'setMode',
|
|
82
|
-
'set_auto_mode': 'setMode',
|
|
83
|
-
'set_manual_mode': 'setMode',
|
|
84
|
-
'automatic_stop_on': 'automaticStopOn',
|
|
85
|
-
'automatic_stop_off': 'automaticStopOff',
|
|
86
|
-
'set_humidity': 'setHumidity',
|
|
87
|
-
'indicator_light_on': 'indicatorLightOn',
|
|
88
|
-
'indicator_light_off': 'indicatorLightOff',
|
|
89
|
-
'enable_white_mode': 'enableWhiteMode',
|
|
90
|
-
'set_rgb': 'setRgb',
|
|
91
|
-
'set_mode': 'setMode',
|
|
92
|
-
'set_display': 'setDisplay',
|
|
93
|
-
'set_child_lock': 'setChildLock',
|
|
94
|
-
'set_night_light': 'setNightLight'
|
|
95
|
-
};
|
|
96
|
-
// Property name mapping from Python snake_case to TypeScript camelCase
|
|
97
|
-
this.propertyNameMap = {
|
|
98
|
-
'current_temperature': 'currentTemperature',
|
|
99
|
-
'cooking_status': 'cookingStatus',
|
|
100
|
-
'remaining_time': 'remainingTime',
|
|
101
|
-
'current_humidity': 'currentHumidity',
|
|
102
|
-
'water_lacks': 'waterLacks',
|
|
103
|
-
'voltage': 'voltage',
|
|
104
|
-
'power': 'power',
|
|
105
|
-
'filter_life': 'filterLife',
|
|
106
|
-
'screen_status': 'screenStatus',
|
|
107
|
-
'child_lock': 'childLock',
|
|
108
|
-
'air_quality': 'airQuality',
|
|
109
|
-
'mist_level': 'mistLevel',
|
|
110
|
-
'warm_level': 'warmLevel'
|
|
111
|
-
};
|
|
112
|
-
(0, helpers_1.setApiBaseUrl)('http://localhost:8000');
|
|
113
|
-
this.manager = new vesync_1.VeSync('test@example.com', 'test123', 'America/New_York', DEBUG);
|
|
114
|
-
// Load all YAML specs
|
|
115
|
-
const apiDir = path.join(__dirname, '..', 'api');
|
|
116
|
-
for (const deviceType of ['vesyncfan', 'vesyncbulb', 'vesyncoutlet', 'vesyncswitch']) {
|
|
117
|
-
const deviceDir = path.join(apiDir, deviceType);
|
|
118
|
-
if (fs.existsSync(deviceDir)) {
|
|
119
|
-
for (const file of fs.readdirSync(deviceDir)) {
|
|
120
|
-
if (file.endsWith('.yaml')) {
|
|
121
|
-
const model = path.basename(file, '.yaml');
|
|
122
|
-
const spec = yaml.load(fs.readFileSync(path.join(deviceDir, file), 'utf8'));
|
|
123
|
-
this.deviceSpecs.set(model, spec);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
getDeviceSpec(deviceType) {
|
|
130
|
-
return this.deviceSpecs.get(deviceType) || {};
|
|
131
|
-
}
|
|
132
|
-
logError(deviceName, methodName, error) {
|
|
133
|
-
const errorMsg = error?.message || error;
|
|
134
|
-
if (!this.testSummary.has(deviceName)) {
|
|
135
|
-
this.testSummary.set(deviceName, {
|
|
136
|
-
testedFeatures: new Set(),
|
|
137
|
-
failedFeatures: new Set(),
|
|
138
|
-
errors: new Map()
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
const summary = this.testSummary.get(deviceName);
|
|
142
|
-
if (!summary.errors.has(methodName)) {
|
|
143
|
-
summary.errors.set(methodName, []);
|
|
144
|
-
}
|
|
145
|
-
summary.errors.get(methodName).push(errorMsg);
|
|
146
|
-
console.error(`[${deviceName}] ${methodName}: ${errorMsg}`);
|
|
147
|
-
}
|
|
148
|
-
async testMethod(device, methodName, spec) {
|
|
149
|
-
const deviceName = `${device.deviceName} (${device.deviceType})`;
|
|
150
|
-
const summary = this.testSummary.get(deviceName);
|
|
151
|
-
summary.testedFeatures.add(methodName);
|
|
152
|
-
try {
|
|
153
|
-
// Convert method name from snake_case to camelCase
|
|
154
|
-
const camelCaseMethod = this.methodNameMap[methodName];
|
|
155
|
-
if (!camelCaseMethod) {
|
|
156
|
-
throw new Error(`No camelCase mapping found for method: ${methodName}`);
|
|
157
|
-
}
|
|
158
|
-
const method = device[camelCaseMethod];
|
|
159
|
-
if (!method) {
|
|
160
|
-
throw new Error(`Method ${camelCaseMethod} not found`);
|
|
161
|
-
}
|
|
162
|
-
// Handle special cases for method parameters
|
|
163
|
-
switch (methodName) {
|
|
164
|
-
case 'manual_mode':
|
|
165
|
-
case 'set_manual_mode':
|
|
166
|
-
await method.call(device, 'manual');
|
|
167
|
-
break;
|
|
168
|
-
case 'auto_mode':
|
|
169
|
-
case 'set_auto_mode':
|
|
170
|
-
await method.call(device, 'auto');
|
|
171
|
-
break;
|
|
172
|
-
case 'sleep_mode':
|
|
173
|
-
await method.call(device, 'sleep');
|
|
174
|
-
break;
|
|
175
|
-
case 'turn_on_display':
|
|
176
|
-
await method.call(device, true);
|
|
177
|
-
break;
|
|
178
|
-
case 'turn_off_display':
|
|
179
|
-
await method.call(device, false);
|
|
180
|
-
break;
|
|
181
|
-
case 'change_fan_speed':
|
|
182
|
-
const speeds = device.deviceType.match(/Core|LAP|LTF|LV/) ? [1, 2, 3, 4, 5] : [1, 2, 3];
|
|
183
|
-
for (const speed of speeds) {
|
|
184
|
-
await method.call(device, speed);
|
|
185
|
-
}
|
|
186
|
-
break;
|
|
187
|
-
case 'set_warm_level':
|
|
188
|
-
await method.call(device, 2);
|
|
189
|
-
break;
|
|
190
|
-
case 'set_mist_level':
|
|
191
|
-
await method.call(device, 2);
|
|
192
|
-
break;
|
|
193
|
-
case 'set_brightness':
|
|
194
|
-
for (const brightness of [25, 50, 75, 100]) {
|
|
195
|
-
await method.call(device, brightness);
|
|
196
|
-
}
|
|
197
|
-
break;
|
|
198
|
-
case 'set_color_temp':
|
|
199
|
-
for (const temp of [2700, 4000, 5500]) {
|
|
200
|
-
await method.call(device, temp);
|
|
201
|
-
}
|
|
202
|
-
break;
|
|
203
|
-
case 'set_hsv':
|
|
204
|
-
const colors = [
|
|
205
|
-
[0, 100, 100], // Red
|
|
206
|
-
[120, 100, 100], // Green
|
|
207
|
-
[240, 100, 100] // Blue
|
|
208
|
-
];
|
|
209
|
-
for (const [h, s, v] of colors) {
|
|
210
|
-
await method.call(device, h, s, v);
|
|
211
|
-
}
|
|
212
|
-
break;
|
|
213
|
-
case 'set_timer':
|
|
214
|
-
await method.call(device, 2); // 2 hours
|
|
215
|
-
break;
|
|
216
|
-
case 'set_mode':
|
|
217
|
-
for (const mode of ['auto', 'manual', 'sleep']) {
|
|
218
|
-
await method.call(device, mode);
|
|
219
|
-
}
|
|
220
|
-
break;
|
|
221
|
-
case 'set_display':
|
|
222
|
-
case 'set_child_lock':
|
|
223
|
-
case 'set_night_light':
|
|
224
|
-
for (const state of [true, false]) {
|
|
225
|
-
await method.call(device, state);
|
|
226
|
-
}
|
|
227
|
-
break;
|
|
228
|
-
case 'set_humidity':
|
|
229
|
-
for (const humidity of [30, 50, 80]) {
|
|
230
|
-
await method.call(device, humidity);
|
|
231
|
-
}
|
|
232
|
-
break;
|
|
233
|
-
default:
|
|
234
|
-
// For simple methods with no parameters
|
|
235
|
-
await method.call(device);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
summary.failedFeatures.add(methodName);
|
|
240
|
-
this.logError(deviceName, methodName, error);
|
|
241
|
-
throw error;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
async testDeviceFeatures(device) {
|
|
245
|
-
const deviceType = device.deviceType;
|
|
246
|
-
const spec = this.getDeviceSpec(deviceType);
|
|
247
|
-
if (!spec) {
|
|
248
|
-
console.error(`No YAML spec found for device type: ${deviceType}`);
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
const deviceName = `${device.deviceName} (${deviceType})`;
|
|
252
|
-
this.testSummary.set(deviceName, {
|
|
253
|
-
testedFeatures: new Set(),
|
|
254
|
-
failedFeatures: new Set(),
|
|
255
|
-
errors: new Map()
|
|
256
|
-
});
|
|
257
|
-
// Test each method from the YAML spec
|
|
258
|
-
for (const methodName of Object.keys(spec)) {
|
|
259
|
-
await this.testMethod(device, methodName, spec[methodName]);
|
|
260
|
-
}
|
|
261
|
-
// Test device-specific properties
|
|
262
|
-
if (deviceType.match(/Core|LAP|LTF|LV/)) {
|
|
263
|
-
// Test air purifier properties
|
|
264
|
-
const properties = ['mode', 'speed', 'filterLife', 'screenStatus', 'childLock', 'airQuality'];
|
|
265
|
-
for (const prop of properties) {
|
|
266
|
-
const summary = this.testSummary.get(deviceName);
|
|
267
|
-
summary.testedFeatures.add(prop);
|
|
268
|
-
try {
|
|
269
|
-
device[prop];
|
|
270
|
-
}
|
|
271
|
-
catch (error) {
|
|
272
|
-
summary.failedFeatures.add(prop);
|
|
273
|
-
this.logError(deviceName, prop, error);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
if (deviceType.match(/Classic|Dual/)) {
|
|
278
|
-
// Test humidifier properties
|
|
279
|
-
const properties = ['mode', 'speed', 'humidity', 'mistLevel'];
|
|
280
|
-
for (const prop of properties) {
|
|
281
|
-
const summary = this.testSummary.get(deviceName);
|
|
282
|
-
summary.testedFeatures.add(prop);
|
|
283
|
-
try {
|
|
284
|
-
device[prop];
|
|
285
|
-
}
|
|
286
|
-
catch (error) {
|
|
287
|
-
summary.failedFeatures.add(prop);
|
|
288
|
-
this.logError(deviceName, prop, error);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
if (deviceType.match(/LUH|LEH/)) {
|
|
293
|
-
// Test warm humidifier properties
|
|
294
|
-
const properties = ['mode', 'speed', 'humidity', 'mistLevel', 'warmLevel'];
|
|
295
|
-
for (const prop of properties) {
|
|
296
|
-
const summary = this.testSummary.get(deviceName);
|
|
297
|
-
summary.testedFeatures.add(prop);
|
|
298
|
-
try {
|
|
299
|
-
device[prop];
|
|
300
|
-
}
|
|
301
|
-
catch (error) {
|
|
302
|
-
summary.failedFeatures.add(prop);
|
|
303
|
-
this.logError(deviceName, prop, error);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
// Test outlet properties
|
|
308
|
-
if (deviceType.match(/ESW|ESO/)) {
|
|
309
|
-
const properties = ['voltage', 'power'];
|
|
310
|
-
for (const prop of properties) {
|
|
311
|
-
const camelCaseProp = this.propertyNameMap[prop] || prop;
|
|
312
|
-
if (camelCaseProp in device) {
|
|
313
|
-
const summary = this.testSummary.get(deviceName);
|
|
314
|
-
summary.testedFeatures.add(prop);
|
|
315
|
-
try {
|
|
316
|
-
device[camelCaseProp];
|
|
317
|
-
}
|
|
318
|
-
catch (error) {
|
|
319
|
-
summary.failedFeatures.add(prop);
|
|
320
|
-
this.logError(deviceName, prop, error);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
displaySummary() {
|
|
327
|
-
console.log('\n=== Test Summary ===\n');
|
|
328
|
-
// First print all errors
|
|
329
|
-
console.log('=== All Errors Found ===');
|
|
330
|
-
let hasErrors = false;
|
|
331
|
-
for (const [deviceName, summary] of this.testSummary) {
|
|
332
|
-
if (summary.errors.size > 0) {
|
|
333
|
-
hasErrors = true;
|
|
334
|
-
console.log(`\nDevice: ${deviceName}`);
|
|
335
|
-
for (const [method, errors] of summary.errors) {
|
|
336
|
-
console.log(`\nMethod: ${method}`);
|
|
337
|
-
for (const error of errors) {
|
|
338
|
-
console.log(`Error: ${error}`);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
if (!hasErrors) {
|
|
344
|
-
console.log('No errors found!');
|
|
345
|
-
}
|
|
346
|
-
// Then print feature summary
|
|
347
|
-
console.log('\n=== Feature Summary ===');
|
|
348
|
-
for (const [deviceName, summary] of this.testSummary) {
|
|
349
|
-
console.log(`\nDevice: ${deviceName}`);
|
|
350
|
-
console.log('Tested features:');
|
|
351
|
-
for (const feature of Array.from(summary.testedFeatures).sort()) {
|
|
352
|
-
const status = summary.failedFeatures.has(feature) ? '✗' : '✓';
|
|
353
|
-
console.log(` ${status} ${feature}`);
|
|
354
|
-
}
|
|
355
|
-
if (summary.failedFeatures.size > 0) {
|
|
356
|
-
console.log('Failed features:');
|
|
357
|
-
for (const feature of Array.from(summary.failedFeatures).sort()) {
|
|
358
|
-
console.log(` ✗ ${feature}`);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
async run() {
|
|
364
|
-
console.log('Using credentials:', {
|
|
365
|
-
username: this.manager.username,
|
|
366
|
-
password: '*'.repeat(this.manager.password.length)
|
|
367
|
-
});
|
|
368
|
-
console.log('\nTesting login...');
|
|
369
|
-
if (!await this.manager.login()) {
|
|
370
|
-
console.error('Login failed');
|
|
371
|
-
return;
|
|
372
|
-
}
|
|
373
|
-
console.log('\nTesting device discovery...');
|
|
374
|
-
await this.manager.getDevices();
|
|
375
|
-
if (this.manager.devices && this.manager.devices.length > 0) {
|
|
376
|
-
for (const device of this.manager.devices) {
|
|
377
|
-
await this.testDeviceFeatures(device);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
console.log('No devices found. Tests will be skipped.');
|
|
382
|
-
}
|
|
383
|
-
this.displaySummary();
|
|
384
|
-
console.log('\n✓ All tests completed');
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
// Run tests if this file is executed directly
|
|
388
|
-
if (require.main === module) {
|
|
389
|
-
const test = new DeviceFeatureTest();
|
|
390
|
-
test.run().catch(error => {
|
|
391
|
-
console.error('Test failed:', error);
|
|
392
|
-
process.exit(1);
|
|
393
|
-
});
|
|
394
|
-
}
|