tsvesync 1.0.13 → 1.0.15

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.
Files changed (41) hide show
  1. package/dist/lib/vesyncOutlet.js +21 -2
  2. package/package.json +1 -1
  3. package/src/lib/vesyncOutlet.ts +21 -3
  4. package/dist/lib/helpers.js.map +0 -1
  5. package/dist/lib/vesync.js.map +0 -1
  6. package/dist/lib/vesyncBaseDevice.js.map +0 -1
  7. package/dist/lib/vesyncBulb.js.map +0 -1
  8. package/dist/lib/vesyncFan.js.map +0 -1
  9. package/dist/lib/vesyncKitchen.d.ts +0 -0
  10. package/dist/lib/vesyncKitchen.js +0 -2
  11. package/dist/lib/vesyncKitchen.js.map +0 -1
  12. package/dist/lib/vesyncOutlet.js.map +0 -1
  13. package/dist/lib/vesyncSwitch.js.map +0 -1
  14. package/dist/src/lib/helpers.d.ts +0 -88
  15. package/dist/src/lib/helpers.js +0 -244
  16. package/dist/src/lib/vesync.d.ts +0 -89
  17. package/dist/src/lib/vesync.js +0 -430
  18. package/dist/src/lib/vesyncBaseDevice.d.ts +0 -43
  19. package/dist/src/lib/vesyncBaseDevice.js +0 -87
  20. package/dist/src/lib/vesyncBulb.d.ts +0 -79
  21. package/dist/src/lib/vesyncBulb.js +0 -198
  22. package/dist/src/lib/vesyncBulbImpl.d.ts +0 -38
  23. package/dist/src/lib/vesyncBulbImpl.js +0 -161
  24. package/dist/src/lib/vesyncFan.d.ts +0 -80
  25. package/dist/src/lib/vesyncFan.js +0 -406
  26. package/dist/src/lib/vesyncFanImpl.d.ts +0 -137
  27. package/dist/src/lib/vesyncFanImpl.js +0 -643
  28. package/dist/src/lib/vesyncOutlet.d.ts +0 -53
  29. package/dist/src/lib/vesyncOutlet.js +0 -98
  30. package/dist/src/lib/vesyncOutletImpl.d.ts +0 -70
  31. package/dist/src/lib/vesyncOutletImpl.js +0 -206
  32. package/dist/src/lib/vesyncSwitch.d.ts +0 -169
  33. package/dist/src/lib/vesyncSwitch.js +0 -414
  34. package/dist/src/lib/vesyncSwitchImpl.d.ts +0 -82
  35. package/dist/src/lib/vesyncSwitchImpl.js +0 -290
  36. package/dist/test/testFeatures.d.ts +0 -4
  37. package/dist/test/testFeatures.js +0 -394
  38. package/dist/test/testService.d.ts +0 -62
  39. package/dist/test/testService.js +0 -540
  40. package/dist/test/testSpecial.d.ts +0 -5
  41. 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,4 +0,0 @@
1
- /**
2
- * Test all device features using TSVeSync device classes
3
- */
4
- export {};
@@ -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
- }