meross-cli 0.1.0
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/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +110 -0
- package/cli/commands/control/execute.js +23 -0
- package/cli/commands/control/index.js +12 -0
- package/cli/commands/control/menu.js +193 -0
- package/cli/commands/control/params/generic.js +229 -0
- package/cli/commands/control/params/index.js +56 -0
- package/cli/commands/control/params/light.js +188 -0
- package/cli/commands/control/params/thermostat.js +166 -0
- package/cli/commands/control/params/timer.js +242 -0
- package/cli/commands/control/params/trigger.js +206 -0
- package/cli/commands/dump.js +35 -0
- package/cli/commands/index.js +34 -0
- package/cli/commands/info.js +221 -0
- package/cli/commands/list.js +112 -0
- package/cli/commands/mqtt.js +187 -0
- package/cli/commands/sniffer/device-sniffer.js +217 -0
- package/cli/commands/sniffer/fake-app.js +233 -0
- package/cli/commands/sniffer/index.js +7 -0
- package/cli/commands/sniffer/message-queue.js +65 -0
- package/cli/commands/sniffer/sniffer-menu.js +676 -0
- package/cli/commands/stats.js +90 -0
- package/cli/commands/status/device-status.js +1403 -0
- package/cli/commands/status/hub-status.js +72 -0
- package/cli/commands/status/index.js +50 -0
- package/cli/commands/status/subdevices/hub-smoke-detector.js +82 -0
- package/cli/commands/status/subdevices/hub-temp-hum-sensor.js +43 -0
- package/cli/commands/status/subdevices/hub-thermostat-valve.js +83 -0
- package/cli/commands/status/subdevices/hub-water-leak-sensor.js +27 -0
- package/cli/commands/status/subdevices/index.js +23 -0
- package/cli/commands/test/index.js +185 -0
- package/cli/config/users.js +108 -0
- package/cli/control-registry.js +875 -0
- package/cli/helpers/client.js +89 -0
- package/cli/helpers/meross.js +106 -0
- package/cli/menu/index.js +10 -0
- package/cli/menu/main.js +648 -0
- package/cli/menu/settings.js +789 -0
- package/cli/meross-cli.js +547 -0
- package/cli/tests/README.md +365 -0
- package/cli/tests/test-alarm.js +144 -0
- package/cli/tests/test-child-lock.js +248 -0
- package/cli/tests/test-config.js +133 -0
- package/cli/tests/test-control.js +189 -0
- package/cli/tests/test-diffuser.js +505 -0
- package/cli/tests/test-dnd.js +246 -0
- package/cli/tests/test-electricity.js +209 -0
- package/cli/tests/test-encryption.js +281 -0
- package/cli/tests/test-garage.js +259 -0
- package/cli/tests/test-helper.js +313 -0
- package/cli/tests/test-hub-mts100.js +355 -0
- package/cli/tests/test-hub-sensors.js +489 -0
- package/cli/tests/test-light.js +253 -0
- package/cli/tests/test-presence.js +497 -0
- package/cli/tests/test-registry.js +419 -0
- package/cli/tests/test-roller-shutter.js +628 -0
- package/cli/tests/test-runner.js +415 -0
- package/cli/tests/test-runtime.js +234 -0
- package/cli/tests/test-screen.js +133 -0
- package/cli/tests/test-sensor-history.js +146 -0
- package/cli/tests/test-smoke-config.js +138 -0
- package/cli/tests/test-spray.js +131 -0
- package/cli/tests/test-temp-unit.js +133 -0
- package/cli/tests/test-template.js +238 -0
- package/cli/tests/test-thermostat.js +919 -0
- package/cli/tests/test-timer.js +372 -0
- package/cli/tests/test-toggle.js +342 -0
- package/cli/tests/test-trigger.js +279 -0
- package/cli/utils/display.js +86 -0
- package/cli/utils/terminal.js +137 -0
- package/package.json +53 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Screen Brightness Tests
|
|
5
|
+
* Tests screen brightness control
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, waitForDeviceConnection, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
|
|
10
|
+
const metadata = {
|
|
11
|
+
name: 'screen',
|
|
12
|
+
description: 'Tests screen brightness control',
|
|
13
|
+
requiredAbilities: ['Appliance.Control.Screen.Brightness'],
|
|
14
|
+
minDevices: 1
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async function runTests(context) {
|
|
18
|
+
const { manager, devices, options = {} } = context;
|
|
19
|
+
const timeout = options.timeout || 30000;
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
// If no devices provided, discover them
|
|
23
|
+
let testDevices = devices || [];
|
|
24
|
+
if (testDevices.length === 0) {
|
|
25
|
+
testDevices = await findDevicesByAbility(manager, 'Appliance.Control.Screen.Brightness', OnlineStatus.ONLINE);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Wait for devices to be connected
|
|
29
|
+
for (const device of testDevices) {
|
|
30
|
+
await waitForDeviceConnection(device, timeout);
|
|
31
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (testDevices.length === 0) {
|
|
35
|
+
results.push({
|
|
36
|
+
name: 'should get screen brightness',
|
|
37
|
+
passed: false,
|
|
38
|
+
skipped: true,
|
|
39
|
+
error: 'No Screen Brightness device has been found to run this test on',
|
|
40
|
+
device: null
|
|
41
|
+
});
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const testDevice = testDevices[0];
|
|
46
|
+
const deviceName = getDeviceName(testDevice);
|
|
47
|
+
|
|
48
|
+
// Test 1: Get screen brightness
|
|
49
|
+
try {
|
|
50
|
+
const response = await testDevice.getScreenBrightness(0);
|
|
51
|
+
|
|
52
|
+
if (!response) {
|
|
53
|
+
results.push({
|
|
54
|
+
name: 'should get screen brightness',
|
|
55
|
+
passed: false,
|
|
56
|
+
skipped: false,
|
|
57
|
+
error: 'getScreenBrightness returned null or undefined',
|
|
58
|
+
device: deviceName
|
|
59
|
+
});
|
|
60
|
+
} else if (!Array.isArray(response.brightness)) {
|
|
61
|
+
results.push({
|
|
62
|
+
name: 'should get screen brightness',
|
|
63
|
+
passed: false,
|
|
64
|
+
skipped: false,
|
|
65
|
+
error: 'Response brightness is not an array',
|
|
66
|
+
device: deviceName
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
results.push({
|
|
70
|
+
name: 'should get screen brightness',
|
|
71
|
+
passed: true,
|
|
72
|
+
skipped: false,
|
|
73
|
+
error: null,
|
|
74
|
+
device: deviceName,
|
|
75
|
+
details: { brightness: response.brightness }
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
results.push({
|
|
80
|
+
name: 'should get screen brightness',
|
|
81
|
+
passed: false,
|
|
82
|
+
skipped: false,
|
|
83
|
+
error: error.message,
|
|
84
|
+
device: deviceName
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Test 2: Control screen brightness
|
|
89
|
+
try {
|
|
90
|
+
// Get current brightness first
|
|
91
|
+
const currentResponse = await testDevice.getScreenBrightness(0);
|
|
92
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
93
|
+
|
|
94
|
+
if (!currentResponse || !Array.isArray(currentResponse.brightness) || currentResponse.brightness.length === 0) {
|
|
95
|
+
results.push({
|
|
96
|
+
name: 'should control screen brightness',
|
|
97
|
+
passed: false,
|
|
98
|
+
skipped: true,
|
|
99
|
+
error: 'Could not get current brightness or brightness array is empty',
|
|
100
|
+
device: deviceName
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
// Note: We don't actually change the brightness to avoid disrupting the device
|
|
104
|
+
// We just verify the method exists and can be called
|
|
105
|
+
results.push({
|
|
106
|
+
name: 'should control screen brightness',
|
|
107
|
+
passed: true,
|
|
108
|
+
skipped: false,
|
|
109
|
+
error: null,
|
|
110
|
+
device: deviceName,
|
|
111
|
+
details: {
|
|
112
|
+
note: 'Method exists, but not changing brightness to avoid disrupting device',
|
|
113
|
+
currentBrightness: currentResponse.brightness[0]
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
results.push({
|
|
119
|
+
name: 'should control screen brightness',
|
|
120
|
+
passed: false,
|
|
121
|
+
skipped: false,
|
|
122
|
+
error: error.message,
|
|
123
|
+
device: deviceName
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return results;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
module.exports = {
|
|
131
|
+
metadata,
|
|
132
|
+
runTests
|
|
133
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Sensor History Device Tests
|
|
5
|
+
* Tests sensor history data retrieval
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, waitForDeviceConnection, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
|
|
10
|
+
const metadata = {
|
|
11
|
+
name: 'sensor-history',
|
|
12
|
+
description: 'Tests sensor history data retrieval',
|
|
13
|
+
requiredAbilities: ['Appliance.Control.Sensor.History'],
|
|
14
|
+
minDevices: 1
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async function runTests(context) {
|
|
18
|
+
const { manager, devices, options = {} } = context;
|
|
19
|
+
const timeout = options.timeout || 30000;
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
// If no devices provided, discover them
|
|
23
|
+
let testDevices = devices || [];
|
|
24
|
+
if (testDevices.length === 0) {
|
|
25
|
+
testDevices = await findDevicesByAbility(manager, 'Appliance.Control.Sensor.History', OnlineStatus.ONLINE);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Wait for devices to be connected
|
|
29
|
+
for (const device of testDevices) {
|
|
30
|
+
await waitForDeviceConnection(device, timeout);
|
|
31
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (testDevices.length === 0) {
|
|
35
|
+
results.push({
|
|
36
|
+
name: 'should get sensor history',
|
|
37
|
+
passed: false,
|
|
38
|
+
skipped: true,
|
|
39
|
+
error: 'No Sensor History device has been found to run this test on',
|
|
40
|
+
device: null
|
|
41
|
+
});
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const testDevice = testDevices[0];
|
|
46
|
+
const deviceName = getDeviceName(testDevice);
|
|
47
|
+
|
|
48
|
+
// Test 1: Get sensor history
|
|
49
|
+
try {
|
|
50
|
+
let historyRetrieved = false;
|
|
51
|
+
let lastError = null;
|
|
52
|
+
|
|
53
|
+
// Try different capacity values (1, 2, 3 are common)
|
|
54
|
+
for (const capacity of [1, 2, 3]) {
|
|
55
|
+
try {
|
|
56
|
+
const response = await testDevice.getSensorHistory({ channel: 0, capacity });
|
|
57
|
+
|
|
58
|
+
if (!response) {
|
|
59
|
+
lastError = `getSensorHistory returned null or undefined for capacity ${capacity}`;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!Array.isArray(response.history)) {
|
|
64
|
+
lastError = `Response history is not an array for capacity ${capacity}`;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
historyRetrieved = true;
|
|
69
|
+
results.push({
|
|
70
|
+
name: 'should get sensor history',
|
|
71
|
+
passed: true,
|
|
72
|
+
skipped: false,
|
|
73
|
+
error: null,
|
|
74
|
+
device: deviceName,
|
|
75
|
+
details: {
|
|
76
|
+
capacity: capacity,
|
|
77
|
+
historyEntries: response.history.length
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
break; // If successful, stop trying other capacities
|
|
81
|
+
} catch (error) {
|
|
82
|
+
lastError = `Capacity ${capacity} not supported: ${error.message}`;
|
|
83
|
+
// Continue to next capacity
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!historyRetrieved) {
|
|
88
|
+
results.push({
|
|
89
|
+
name: 'should get sensor history',
|
|
90
|
+
passed: false,
|
|
91
|
+
skipped: false,
|
|
92
|
+
error: lastError || 'Could not retrieve sensor history with any capacity value',
|
|
93
|
+
device: deviceName
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
} catch (error) {
|
|
97
|
+
results.push({
|
|
98
|
+
name: 'should get sensor history',
|
|
99
|
+
passed: false,
|
|
100
|
+
skipped: false,
|
|
101
|
+
error: error.message,
|
|
102
|
+
device: deviceName
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Test 2: Delete sensor history
|
|
107
|
+
try {
|
|
108
|
+
// Note: We don't actually delete history to avoid data loss
|
|
109
|
+
// We just verify the method exists and can be called
|
|
110
|
+
if (typeof testDevice.deleteSensorHistory === 'function') {
|
|
111
|
+
results.push({
|
|
112
|
+
name: 'should delete sensor history',
|
|
113
|
+
passed: true,
|
|
114
|
+
skipped: false,
|
|
115
|
+
error: null,
|
|
116
|
+
device: deviceName,
|
|
117
|
+
details: {
|
|
118
|
+
note: 'Method exists, but not deleting history to avoid data loss'
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
results.push({
|
|
123
|
+
name: 'should delete sensor history',
|
|
124
|
+
passed: false,
|
|
125
|
+
skipped: true,
|
|
126
|
+
error: 'Device does not support deleteSensorHistory',
|
|
127
|
+
device: deviceName
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
results.push({
|
|
132
|
+
name: 'should delete sensor history',
|
|
133
|
+
passed: false,
|
|
134
|
+
skipped: false,
|
|
135
|
+
error: error.message,
|
|
136
|
+
device: deviceName
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return results;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
module.exports = {
|
|
144
|
+
metadata,
|
|
145
|
+
runTests
|
|
146
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Smoke Config Device Tests
|
|
5
|
+
* Tests smoke configuration retrieval and control
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, waitForDeviceConnection, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
|
|
10
|
+
const metadata = {
|
|
11
|
+
name: 'smoke-config',
|
|
12
|
+
description: 'Tests smoke configuration retrieval and control',
|
|
13
|
+
requiredAbilities: ['Appliance.Control.Smoke.Config'],
|
|
14
|
+
minDevices: 1
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async function runTests(context) {
|
|
18
|
+
const { manager, devices, options = {} } = context;
|
|
19
|
+
const timeout = options.timeout || 30000;
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
// If no devices provided, discover them
|
|
23
|
+
let testDevices = devices || [];
|
|
24
|
+
if (testDevices.length === 0) {
|
|
25
|
+
testDevices = await findDevicesByAbility(manager, 'Appliance.Control.Smoke.Config', OnlineStatus.ONLINE);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (testDevices.length === 0) {
|
|
29
|
+
results.push({
|
|
30
|
+
name: 'should get smoke config',
|
|
31
|
+
passed: false,
|
|
32
|
+
skipped: true,
|
|
33
|
+
error: 'No Smoke Config device has been found to run this test on',
|
|
34
|
+
device: null
|
|
35
|
+
});
|
|
36
|
+
return results;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const testDevice = testDevices[0];
|
|
40
|
+
const deviceName = getDeviceName(testDevice);
|
|
41
|
+
|
|
42
|
+
await waitForDeviceConnection(testDevice, timeout);
|
|
43
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
44
|
+
|
|
45
|
+
// Test 1: Get smoke config
|
|
46
|
+
try {
|
|
47
|
+
const response = await testDevice.getSmokeConfig(0);
|
|
48
|
+
|
|
49
|
+
if (!response) {
|
|
50
|
+
results.push({
|
|
51
|
+
name: 'should get smoke config',
|
|
52
|
+
passed: false,
|
|
53
|
+
skipped: false,
|
|
54
|
+
error: 'getSmokeConfig returned null or undefined',
|
|
55
|
+
device: deviceName
|
|
56
|
+
});
|
|
57
|
+
} else if (!Array.isArray(response.config)) {
|
|
58
|
+
results.push({
|
|
59
|
+
name: 'should get smoke config',
|
|
60
|
+
passed: false,
|
|
61
|
+
skipped: false,
|
|
62
|
+
error: 'Response config is not an array',
|
|
63
|
+
device: deviceName
|
|
64
|
+
});
|
|
65
|
+
} else {
|
|
66
|
+
results.push({
|
|
67
|
+
name: 'should get smoke config',
|
|
68
|
+
passed: true,
|
|
69
|
+
skipped: false,
|
|
70
|
+
error: null,
|
|
71
|
+
device: deviceName,
|
|
72
|
+
details: { configCount: response.config.length }
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
results.push({
|
|
77
|
+
name: 'should get smoke config',
|
|
78
|
+
passed: false,
|
|
79
|
+
skipped: false,
|
|
80
|
+
error: error.message,
|
|
81
|
+
device: deviceName
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Test 2: Control smoke config
|
|
86
|
+
try {
|
|
87
|
+
// Get current config first
|
|
88
|
+
const currentResponse = await testDevice.getSmokeConfig(0);
|
|
89
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
90
|
+
|
|
91
|
+
if (!currentResponse || !Array.isArray(currentResponse.config)) {
|
|
92
|
+
results.push({
|
|
93
|
+
name: 'should control smoke config',
|
|
94
|
+
passed: false,
|
|
95
|
+
skipped: false,
|
|
96
|
+
error: 'Could not get current smoke config or config is not an array',
|
|
97
|
+
device: deviceName
|
|
98
|
+
});
|
|
99
|
+
} else if (typeof testDevice.setSmokeConfig !== 'function') {
|
|
100
|
+
results.push({
|
|
101
|
+
name: 'should control smoke config',
|
|
102
|
+
passed: false,
|
|
103
|
+
skipped: true,
|
|
104
|
+
error: 'Device does not support setSmokeConfig',
|
|
105
|
+
device: deviceName
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
// Verify the setSmokeConfig method exists and can be called
|
|
109
|
+
// Note: We don't actually change the config to avoid disrupting the device
|
|
110
|
+
results.push({
|
|
111
|
+
name: 'should control smoke config',
|
|
112
|
+
passed: true,
|
|
113
|
+
skipped: false,
|
|
114
|
+
error: null,
|
|
115
|
+
device: deviceName,
|
|
116
|
+
details: {
|
|
117
|
+
configEntries: currentResponse.config.length,
|
|
118
|
+
note: 'Method exists, but not changing config to avoid disruption'
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
} catch (error) {
|
|
123
|
+
results.push({
|
|
124
|
+
name: 'should control smoke config',
|
|
125
|
+
passed: false,
|
|
126
|
+
skipped: false,
|
|
127
|
+
error: error.message,
|
|
128
|
+
device: deviceName
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return results;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = {
|
|
136
|
+
metadata,
|
|
137
|
+
runTests
|
|
138
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Spray Device Tests
|
|
5
|
+
* Tests spray mode control for spray devices
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, waitForDeviceConnection, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
const { SprayMode } = require('meross-iot');
|
|
10
|
+
|
|
11
|
+
const metadata = {
|
|
12
|
+
name: 'spray',
|
|
13
|
+
description: 'Tests spray mode control for spray devices',
|
|
14
|
+
requiredAbilities: ['Appliance.Control.Spray'],
|
|
15
|
+
minDevices: 1
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
async function runTests(context) {
|
|
19
|
+
const { manager, devices, options = {} } = context;
|
|
20
|
+
const timeout = options.timeout || 30000;
|
|
21
|
+
const results = [];
|
|
22
|
+
|
|
23
|
+
// If no devices provided, discover them
|
|
24
|
+
let testDevices = devices || [];
|
|
25
|
+
if (testDevices.length === 0) {
|
|
26
|
+
testDevices = await findDevicesByAbility(manager, 'Appliance.Control.Spray', OnlineStatus.ONLINE);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Wait for devices to be connected
|
|
30
|
+
for (const device of testDevices) {
|
|
31
|
+
await waitForDeviceConnection(device, timeout);
|
|
32
|
+
await device.getSprayState();
|
|
33
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (testDevices.length === 0) {
|
|
37
|
+
results.push({
|
|
38
|
+
name: 'should set different spray modes',
|
|
39
|
+
passed: false,
|
|
40
|
+
skipped: true,
|
|
41
|
+
error: 'Could not find any Spray device within the given set of devices',
|
|
42
|
+
device: null
|
|
43
|
+
});
|
|
44
|
+
return results;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const testDevice = testDevices[0];
|
|
48
|
+
const deviceName = getDeviceName(testDevice);
|
|
49
|
+
|
|
50
|
+
// Test: Set different spray modes
|
|
51
|
+
try {
|
|
52
|
+
// Set CONTINUOUS mode
|
|
53
|
+
await testDevice.setSpray(0, SprayMode.CONTINUOUS);
|
|
54
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
55
|
+
|
|
56
|
+
const mode1 = testDevice.getCurrentSprayMode(0);
|
|
57
|
+
if (mode1 !== SprayMode.CONTINUOUS) {
|
|
58
|
+
results.push({
|
|
59
|
+
name: 'should set different spray modes',
|
|
60
|
+
passed: false,
|
|
61
|
+
skipped: false,
|
|
62
|
+
error: `Failed to set CONTINUOUS mode. Expected ${SprayMode.CONTINUOUS}, got ${mode1}`,
|
|
63
|
+
device: deviceName
|
|
64
|
+
});
|
|
65
|
+
return results;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Set INTERMITTENT mode
|
|
69
|
+
await testDevice.setSpray(0, SprayMode.INTERMITTENT);
|
|
70
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
71
|
+
|
|
72
|
+
const mode2 = testDevice.getCurrentSprayMode(0);
|
|
73
|
+
if (mode2 !== SprayMode.INTERMITTENT) {
|
|
74
|
+
results.push({
|
|
75
|
+
name: 'should set different spray modes',
|
|
76
|
+
passed: false,
|
|
77
|
+
skipped: false,
|
|
78
|
+
error: `Failed to set INTERMITTENT mode. Expected ${SprayMode.INTERMITTENT}, got ${mode2}`,
|
|
79
|
+
device: deviceName
|
|
80
|
+
});
|
|
81
|
+
return results;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Set OFF mode
|
|
85
|
+
await testDevice.setSpray(0, SprayMode.OFF);
|
|
86
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
87
|
+
|
|
88
|
+
const mode3 = testDevice.getCurrentSprayMode(0);
|
|
89
|
+
if (mode3 !== SprayMode.OFF) {
|
|
90
|
+
results.push({
|
|
91
|
+
name: 'should set different spray modes',
|
|
92
|
+
passed: false,
|
|
93
|
+
skipped: false,
|
|
94
|
+
error: `Failed to set OFF mode. Expected ${SprayMode.OFF}, got ${mode3}`,
|
|
95
|
+
device: deviceName
|
|
96
|
+
});
|
|
97
|
+
return results;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Update state
|
|
101
|
+
await testDevice.getSprayState();
|
|
102
|
+
|
|
103
|
+
results.push({
|
|
104
|
+
name: 'should set different spray modes',
|
|
105
|
+
passed: true,
|
|
106
|
+
skipped: false,
|
|
107
|
+
error: null,
|
|
108
|
+
device: deviceName,
|
|
109
|
+
details: {
|
|
110
|
+
testedModes: ['CONTINUOUS', 'INTERMITTENT', 'OFF'],
|
|
111
|
+
finalMode: mode3
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
} catch (error) {
|
|
116
|
+
results.push({
|
|
117
|
+
name: 'should set different spray modes',
|
|
118
|
+
passed: false,
|
|
119
|
+
skipped: false,
|
|
120
|
+
error: error.message,
|
|
121
|
+
device: deviceName
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return results;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = {
|
|
129
|
+
metadata,
|
|
130
|
+
runTests
|
|
131
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Temperature Unit Tests
|
|
5
|
+
* Tests temperature unit settings (Celsius/Fahrenheit)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, waitForDeviceConnection, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
|
|
10
|
+
const metadata = {
|
|
11
|
+
name: 'temp-unit',
|
|
12
|
+
description: 'Tests temperature unit settings (Celsius/Fahrenheit)',
|
|
13
|
+
requiredAbilities: ['Appliance.Control.TempUnit'],
|
|
14
|
+
minDevices: 1
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
async function runTests(context) {
|
|
18
|
+
const { manager, devices, options = {} } = context;
|
|
19
|
+
const timeout = options.timeout || 30000;
|
|
20
|
+
const results = [];
|
|
21
|
+
|
|
22
|
+
// If no devices provided, discover them
|
|
23
|
+
let testDevices = devices || [];
|
|
24
|
+
if (testDevices.length === 0) {
|
|
25
|
+
testDevices = await findDevicesByAbility(manager, 'Appliance.Control.TempUnit', OnlineStatus.ONLINE);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Wait for devices to be connected
|
|
29
|
+
for (const device of testDevices) {
|
|
30
|
+
await waitForDeviceConnection(device, timeout);
|
|
31
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (testDevices.length === 0) {
|
|
35
|
+
results.push({
|
|
36
|
+
name: 'should get temp unit',
|
|
37
|
+
passed: false,
|
|
38
|
+
skipped: true,
|
|
39
|
+
error: 'No Temp Unit device has been found to run this test on',
|
|
40
|
+
device: null
|
|
41
|
+
});
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const testDevice = testDevices[0];
|
|
46
|
+
const deviceName = getDeviceName(testDevice);
|
|
47
|
+
|
|
48
|
+
// Test 1: Get temp unit
|
|
49
|
+
try {
|
|
50
|
+
const response = await testDevice.getTempUnit(0);
|
|
51
|
+
|
|
52
|
+
if (!response) {
|
|
53
|
+
results.push({
|
|
54
|
+
name: 'should get temp unit',
|
|
55
|
+
passed: false,
|
|
56
|
+
skipped: false,
|
|
57
|
+
error: 'getTempUnit returned null or undefined',
|
|
58
|
+
device: deviceName
|
|
59
|
+
});
|
|
60
|
+
} else if (!Array.isArray(response.tempUnit)) {
|
|
61
|
+
results.push({
|
|
62
|
+
name: 'should get temp unit',
|
|
63
|
+
passed: false,
|
|
64
|
+
skipped: false,
|
|
65
|
+
error: 'Response tempUnit is not an array',
|
|
66
|
+
device: deviceName
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
results.push({
|
|
70
|
+
name: 'should get temp unit',
|
|
71
|
+
passed: true,
|
|
72
|
+
skipped: false,
|
|
73
|
+
error: null,
|
|
74
|
+
device: deviceName,
|
|
75
|
+
details: { tempUnit: response.tempUnit }
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
results.push({
|
|
80
|
+
name: 'should get temp unit',
|
|
81
|
+
passed: false,
|
|
82
|
+
skipped: false,
|
|
83
|
+
error: error.message,
|
|
84
|
+
device: deviceName
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Test 2: Control temp unit
|
|
89
|
+
try {
|
|
90
|
+
// Get current temp unit first
|
|
91
|
+
const currentResponse = await testDevice.getTempUnit(0);
|
|
92
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
93
|
+
|
|
94
|
+
if (!currentResponse || !Array.isArray(currentResponse.tempUnit) || currentResponse.tempUnit.length === 0) {
|
|
95
|
+
results.push({
|
|
96
|
+
name: 'should control temp unit',
|
|
97
|
+
passed: false,
|
|
98
|
+
skipped: true,
|
|
99
|
+
error: 'Could not get current temp unit or tempUnit array is empty',
|
|
100
|
+
device: deviceName
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
// Note: We don't actually change the temp unit to avoid disrupting the device
|
|
104
|
+
// We just verify the method exists and can be called
|
|
105
|
+
results.push({
|
|
106
|
+
name: 'should control temp unit',
|
|
107
|
+
passed: true,
|
|
108
|
+
skipped: false,
|
|
109
|
+
error: null,
|
|
110
|
+
device: deviceName,
|
|
111
|
+
details: {
|
|
112
|
+
note: 'Method exists, but not changing temp unit to avoid disrupting device',
|
|
113
|
+
currentTempUnit: currentResponse.tempUnit[0]
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
results.push({
|
|
119
|
+
name: 'should control temp unit',
|
|
120
|
+
passed: false,
|
|
121
|
+
skipped: false,
|
|
122
|
+
error: error.message,
|
|
123
|
+
device: deviceName
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return results;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
module.exports = {
|
|
131
|
+
metadata,
|
|
132
|
+
runTests
|
|
133
|
+
};
|