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,248 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Child Lock (Physical Lock) Tests
|
|
5
|
+
* Tests physical lock/child lock safety features
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
|
|
10
|
+
const metadata = {
|
|
11
|
+
name: 'child-lock',
|
|
12
|
+
description: 'Tests physical lock/child lock safety features',
|
|
13
|
+
requiredAbilities: ['Appliance.Control.PhysicalLock'],
|
|
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.PhysicalLock', OnlineStatus.ONLINE);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (testDevices.length === 0) {
|
|
29
|
+
results.push({
|
|
30
|
+
name: 'should find devices with child lock capability',
|
|
31
|
+
passed: false,
|
|
32
|
+
skipped: true,
|
|
33
|
+
error: 'No devices with child lock capability found',
|
|
34
|
+
device: null
|
|
35
|
+
});
|
|
36
|
+
return results;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
results.push({
|
|
40
|
+
name: 'should find devices with child lock capability',
|
|
41
|
+
passed: true,
|
|
42
|
+
skipped: false,
|
|
43
|
+
error: null,
|
|
44
|
+
device: null
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const testDevice = testDevices[0];
|
|
48
|
+
const deviceName = getDeviceName(testDevice);
|
|
49
|
+
|
|
50
|
+
// Test 1: Get child lock status
|
|
51
|
+
try {
|
|
52
|
+
const lockStatus = await testDevice.getChildLock({ channel: 0 });
|
|
53
|
+
|
|
54
|
+
if (!lockStatus) {
|
|
55
|
+
results.push({
|
|
56
|
+
name: 'should get child lock status',
|
|
57
|
+
passed: false,
|
|
58
|
+
skipped: false,
|
|
59
|
+
error: 'getChildLock returned null or undefined',
|
|
60
|
+
device: deviceName
|
|
61
|
+
});
|
|
62
|
+
} else if (!lockStatus.lock) {
|
|
63
|
+
results.push({
|
|
64
|
+
name: 'should get child lock status',
|
|
65
|
+
passed: false,
|
|
66
|
+
skipped: false,
|
|
67
|
+
error: 'Response does not contain lock property',
|
|
68
|
+
device: deviceName
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
results.push({
|
|
72
|
+
name: 'should get child lock status',
|
|
73
|
+
passed: true,
|
|
74
|
+
skipped: false,
|
|
75
|
+
error: null,
|
|
76
|
+
device: deviceName,
|
|
77
|
+
details: { lockStatus: lockStatus.lock }
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
} catch (error) {
|
|
81
|
+
results.push({
|
|
82
|
+
name: 'should get child lock status',
|
|
83
|
+
passed: false,
|
|
84
|
+
skipped: false,
|
|
85
|
+
error: error.message,
|
|
86
|
+
device: deviceName
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Test 2: Control child lock status
|
|
91
|
+
try {
|
|
92
|
+
// Get initial lock status
|
|
93
|
+
const initialStatus = await testDevice.getChildLock({ channel: 0 });
|
|
94
|
+
|
|
95
|
+
if (!initialStatus || !initialStatus.lock || !Array.isArray(initialStatus.lock) || initialStatus.lock.length === 0) {
|
|
96
|
+
results.push({
|
|
97
|
+
name: 'should control child lock status',
|
|
98
|
+
passed: false,
|
|
99
|
+
skipped: true,
|
|
100
|
+
error: 'Could not get initial lock status or lock array is empty',
|
|
101
|
+
device: deviceName
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
const initialLockState = initialStatus.lock[0].onoff;
|
|
105
|
+
|
|
106
|
+
// Toggle lock state
|
|
107
|
+
const newLockState = initialLockState === 1 ? 0 : 1;
|
|
108
|
+
const lockData = {
|
|
109
|
+
channel: 0,
|
|
110
|
+
onoff: newLockState
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
await testDevice.setChildLock(lockData);
|
|
114
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
115
|
+
|
|
116
|
+
// Verify the change
|
|
117
|
+
const updatedStatus = await testDevice.getChildLock({ channel: 0 });
|
|
118
|
+
|
|
119
|
+
if (!updatedStatus || !updatedStatus.lock || !updatedStatus.lock[0]) {
|
|
120
|
+
results.push({
|
|
121
|
+
name: 'should control child lock status',
|
|
122
|
+
passed: false,
|
|
123
|
+
skipped: false,
|
|
124
|
+
error: 'Could not verify updated lock status',
|
|
125
|
+
device: deviceName
|
|
126
|
+
});
|
|
127
|
+
} else if (updatedStatus.lock[0].onoff !== newLockState) {
|
|
128
|
+
results.push({
|
|
129
|
+
name: 'should control child lock status',
|
|
130
|
+
passed: false,
|
|
131
|
+
skipped: false,
|
|
132
|
+
error: `Lock state did not change. Expected ${newLockState}, got ${updatedStatus.lock[0].onoff}`,
|
|
133
|
+
device: deviceName
|
|
134
|
+
});
|
|
135
|
+
} else {
|
|
136
|
+
// Restore original state
|
|
137
|
+
const restoreLockData = {
|
|
138
|
+
channel: 0,
|
|
139
|
+
onoff: initialLockState
|
|
140
|
+
};
|
|
141
|
+
await testDevice.setChildLock(restoreLockData);
|
|
142
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
143
|
+
|
|
144
|
+
const restoredStatus = await testDevice.getChildLock({ channel: 0 });
|
|
145
|
+
|
|
146
|
+
if (!restoredStatus || !restoredStatus.lock || !restoredStatus.lock[0] ||
|
|
147
|
+
restoredStatus.lock[0].onoff !== initialLockState) {
|
|
148
|
+
results.push({
|
|
149
|
+
name: 'should control child lock status',
|
|
150
|
+
passed: false,
|
|
151
|
+
skipped: false,
|
|
152
|
+
error: `Failed to restore lock state. Expected ${initialLockState}, got ${restoredStatus?.lock?.[0]?.onoff}`,
|
|
153
|
+
device: deviceName
|
|
154
|
+
});
|
|
155
|
+
} else {
|
|
156
|
+
results.push({
|
|
157
|
+
name: 'should control child lock status',
|
|
158
|
+
passed: true,
|
|
159
|
+
skipped: false,
|
|
160
|
+
error: null,
|
|
161
|
+
device: deviceName
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
} catch (error) {
|
|
167
|
+
results.push({
|
|
168
|
+
name: 'should control child lock status',
|
|
169
|
+
passed: false,
|
|
170
|
+
skipped: false,
|
|
171
|
+
error: error.message,
|
|
172
|
+
device: deviceName
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Test 3: Handle multiple channel lock control
|
|
177
|
+
try {
|
|
178
|
+
// Get initial status for all channels
|
|
179
|
+
const initialStatus = await testDevice.getChildLock({ channel: 0 });
|
|
180
|
+
|
|
181
|
+
if (!initialStatus || !initialStatus.lock) {
|
|
182
|
+
results.push({
|
|
183
|
+
name: 'should handle multiple channel lock control',
|
|
184
|
+
passed: false,
|
|
185
|
+
skipped: true,
|
|
186
|
+
error: 'Could not get initial lock status',
|
|
187
|
+
device: deviceName
|
|
188
|
+
});
|
|
189
|
+
} else {
|
|
190
|
+
// Control multiple channels using array
|
|
191
|
+
const lockDataArray = [
|
|
192
|
+
{
|
|
193
|
+
channel: 0,
|
|
194
|
+
onoff: initialStatus.lock[0]?.onoff || 0
|
|
195
|
+
}
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
// If device has multiple channels, add them
|
|
199
|
+
if (initialStatus.lock.length > 1) {
|
|
200
|
+
for (let i = 1; i < initialStatus.lock.length; i++) {
|
|
201
|
+
lockDataArray.push({
|
|
202
|
+
channel: initialStatus.lock[i].channel || i,
|
|
203
|
+
onoff: initialStatus.lock[i].onoff || 0
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
await testDevice.setChildLock({ lockData: lockDataArray });
|
|
209
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
210
|
+
|
|
211
|
+
// Verify all channels were set
|
|
212
|
+
const updatedStatus = await testDevice.getChildLock({ channel: 0 });
|
|
213
|
+
|
|
214
|
+
if (!updatedStatus) {
|
|
215
|
+
results.push({
|
|
216
|
+
name: 'should handle multiple channel lock control',
|
|
217
|
+
passed: false,
|
|
218
|
+
skipped: false,
|
|
219
|
+
error: 'Could not verify updated lock status',
|
|
220
|
+
device: deviceName
|
|
221
|
+
});
|
|
222
|
+
} else {
|
|
223
|
+
results.push({
|
|
224
|
+
name: 'should handle multiple channel lock control',
|
|
225
|
+
passed: true,
|
|
226
|
+
skipped: false,
|
|
227
|
+
error: null,
|
|
228
|
+
device: deviceName
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
} catch (error) {
|
|
233
|
+
results.push({
|
|
234
|
+
name: 'should handle multiple channel lock control',
|
|
235
|
+
passed: false,
|
|
236
|
+
skipped: false,
|
|
237
|
+
error: error.message,
|
|
238
|
+
device: deviceName
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return results;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
module.exports = {
|
|
246
|
+
metadata,
|
|
247
|
+
runTests
|
|
248
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Config Device Tests
|
|
5
|
+
* Tests device configuration and settings
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, waitForDeviceConnection, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
|
|
10
|
+
const metadata = {
|
|
11
|
+
name: 'config',
|
|
12
|
+
description: 'Tests device configuration and settings',
|
|
13
|
+
requiredAbilities: ['Appliance.Config.OverTemp'],
|
|
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.Config.OverTemp', 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 config over temp',
|
|
37
|
+
passed: false,
|
|
38
|
+
skipped: true,
|
|
39
|
+
error: 'No Config Over Temp 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 config over temp
|
|
49
|
+
try {
|
|
50
|
+
const response = await testDevice.getConfigOverTemp();
|
|
51
|
+
|
|
52
|
+
if (!response) {
|
|
53
|
+
results.push({
|
|
54
|
+
name: 'should get config over temp',
|
|
55
|
+
passed: false,
|
|
56
|
+
skipped: false,
|
|
57
|
+
error: 'getConfigOverTemp returned null or undefined',
|
|
58
|
+
device: deviceName
|
|
59
|
+
});
|
|
60
|
+
} else if (!response.overTemp) {
|
|
61
|
+
results.push({
|
|
62
|
+
name: 'should get config over temp',
|
|
63
|
+
passed: false,
|
|
64
|
+
skipped: false,
|
|
65
|
+
error: 'Response does not contain overTemp property',
|
|
66
|
+
device: deviceName
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
results.push({
|
|
70
|
+
name: 'should get config over temp',
|
|
71
|
+
passed: true,
|
|
72
|
+
skipped: false,
|
|
73
|
+
error: null,
|
|
74
|
+
device: deviceName,
|
|
75
|
+
details: { overTemp: response.overTemp }
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
results.push({
|
|
80
|
+
name: 'should get config over temp',
|
|
81
|
+
passed: false,
|
|
82
|
+
skipped: false,
|
|
83
|
+
error: error.message,
|
|
84
|
+
device: deviceName
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Test 2: Control config over temp
|
|
89
|
+
try {
|
|
90
|
+
// Get current config first
|
|
91
|
+
const currentResponse = await testDevice.getConfigOverTemp();
|
|
92
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
93
|
+
|
|
94
|
+
if (!currentResponse || !currentResponse.overTemp) {
|
|
95
|
+
results.push({
|
|
96
|
+
name: 'should control config over temp',
|
|
97
|
+
passed: false,
|
|
98
|
+
skipped: true,
|
|
99
|
+
error: 'Could not get current config over temp',
|
|
100
|
+
device: deviceName
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
// Note: We don't actually change the config to avoid disrupting the device
|
|
104
|
+
// We just verify the method exists and can be called
|
|
105
|
+
results.push({
|
|
106
|
+
name: 'should control config over temp',
|
|
107
|
+
passed: true,
|
|
108
|
+
skipped: false,
|
|
109
|
+
error: null,
|
|
110
|
+
device: deviceName,
|
|
111
|
+
details: {
|
|
112
|
+
note: 'Method exists, but not changing config to avoid disrupting device',
|
|
113
|
+
currentConfig: currentResponse.overTemp
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
} catch (error) {
|
|
118
|
+
results.push({
|
|
119
|
+
name: 'should control config over temp',
|
|
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,189 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Control Device Tests
|
|
5
|
+
* Tests multiple control features and device capabilities
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, waitForDeviceConnection, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
|
|
10
|
+
const metadata = {
|
|
11
|
+
name: 'control',
|
|
12
|
+
description: 'Tests multiple control features and device capabilities',
|
|
13
|
+
requiredAbilities: ['Appliance.Control.Multiple', 'Appliance.Control.Upgrade', 'Appliance.Control.OverTemp'],
|
|
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
|
+
// Find devices with control multiple support (most devices support this)
|
|
26
|
+
const multipleDevices = await findDevicesByAbility(manager, 'Appliance.Control.Multiple', OnlineStatus.ONLINE);
|
|
27
|
+
|
|
28
|
+
// Also get any online device for testing control features
|
|
29
|
+
const allDevices = manager.getAllDevices();
|
|
30
|
+
const onlineDevices = allDevices.filter(device => {
|
|
31
|
+
const status = device.onlineStatus !== undefined ? device.onlineStatus : (device.dev?.onlineStatus);
|
|
32
|
+
return status === OnlineStatus.ONLINE;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Combine and deduplicate
|
|
36
|
+
testDevices = [...multipleDevices];
|
|
37
|
+
for (const device of onlineDevices.slice(0, 2)) {
|
|
38
|
+
const uuid = device.dev?.uuid || device.uuid;
|
|
39
|
+
if (!testDevices.find(d => (d.dev?.uuid || d.uuid) === uuid)) {
|
|
40
|
+
testDevices.push(device);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Wait for devices to be connected
|
|
46
|
+
for (const device of testDevices) {
|
|
47
|
+
await waitForDeviceConnection(device, timeout);
|
|
48
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (testDevices.length === 0) {
|
|
52
|
+
results.push({
|
|
53
|
+
name: 'should find devices with control capabilities',
|
|
54
|
+
passed: false,
|
|
55
|
+
skipped: true,
|
|
56
|
+
error: 'No device has been found to run this test on',
|
|
57
|
+
device: null
|
|
58
|
+
});
|
|
59
|
+
return results;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const device = testDevices[0];
|
|
63
|
+
const deviceName = getDeviceName(device);
|
|
64
|
+
|
|
65
|
+
// Test 1: Control Multiple
|
|
66
|
+
try {
|
|
67
|
+
if (typeof device.setMultiple !== 'function') {
|
|
68
|
+
results.push({
|
|
69
|
+
name: 'should execute multiple commands',
|
|
70
|
+
passed: false,
|
|
71
|
+
skipped: true,
|
|
72
|
+
error: 'Device does not support setMultiple',
|
|
73
|
+
device: deviceName
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
const commands = [
|
|
77
|
+
{
|
|
78
|
+
namespace: 'Appliance.System.All',
|
|
79
|
+
method: 'GET',
|
|
80
|
+
payload: {}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
namespace: 'Appliance.System.Ability',
|
|
84
|
+
method: 'GET',
|
|
85
|
+
payload: {}
|
|
86
|
+
}
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
const response = await device.setMultiple(commands);
|
|
90
|
+
|
|
91
|
+
if (!response) {
|
|
92
|
+
results.push({
|
|
93
|
+
name: 'should execute multiple commands',
|
|
94
|
+
passed: false,
|
|
95
|
+
skipped: false,
|
|
96
|
+
error: 'setMultiple returned null or undefined',
|
|
97
|
+
device: deviceName
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
results.push({
|
|
101
|
+
name: 'should execute multiple commands',
|
|
102
|
+
passed: true,
|
|
103
|
+
skipped: false,
|
|
104
|
+
error: null,
|
|
105
|
+
device: deviceName
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
results.push({
|
|
111
|
+
name: 'should execute multiple commands',
|
|
112
|
+
passed: false,
|
|
113
|
+
skipped: false,
|
|
114
|
+
error: error.message,
|
|
115
|
+
device: deviceName
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Test 2: Control Over Temp
|
|
120
|
+
try {
|
|
121
|
+
if (typeof device.acknowledgeControlOverTemp !== 'function') {
|
|
122
|
+
results.push({
|
|
123
|
+
name: 'should acknowledge over temp event',
|
|
124
|
+
passed: false,
|
|
125
|
+
skipped: true,
|
|
126
|
+
error: 'Device does not support acknowledgeControlOverTemp',
|
|
127
|
+
device: deviceName
|
|
128
|
+
});
|
|
129
|
+
} else {
|
|
130
|
+
// Note: OverTemp is typically SET by the device, and we acknowledge it
|
|
131
|
+
// We don't actually trigger an over temp event, just verify the method exists
|
|
132
|
+
results.push({
|
|
133
|
+
name: 'should acknowledge over temp event',
|
|
134
|
+
passed: true,
|
|
135
|
+
skipped: false,
|
|
136
|
+
error: null,
|
|
137
|
+
device: deviceName,
|
|
138
|
+
details: { note: 'Method exists, but not triggering actual over temp event' }
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
} catch (error) {
|
|
142
|
+
results.push({
|
|
143
|
+
name: 'should acknowledge over temp event',
|
|
144
|
+
passed: false,
|
|
145
|
+
skipped: false,
|
|
146
|
+
error: error.message,
|
|
147
|
+
device: deviceName
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Test 3: Control Upgrade
|
|
152
|
+
try {
|
|
153
|
+
if (typeof device.setUpgrade !== 'function') {
|
|
154
|
+
results.push({
|
|
155
|
+
name: 'should have upgrade method available',
|
|
156
|
+
passed: false,
|
|
157
|
+
skipped: true,
|
|
158
|
+
error: 'Device does not support setUpgrade',
|
|
159
|
+
device: deviceName
|
|
160
|
+
});
|
|
161
|
+
} else {
|
|
162
|
+
// Note: We don't actually trigger an upgrade to avoid disrupting the device
|
|
163
|
+
// We just verify the method exists
|
|
164
|
+
results.push({
|
|
165
|
+
name: 'should have upgrade method available',
|
|
166
|
+
passed: true,
|
|
167
|
+
skipped: false,
|
|
168
|
+
error: null,
|
|
169
|
+
device: deviceName,
|
|
170
|
+
details: { note: 'Method exists, but not triggering actual upgrade' }
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
} catch (error) {
|
|
174
|
+
results.push({
|
|
175
|
+
name: 'should have upgrade method available',
|
|
176
|
+
passed: false,
|
|
177
|
+
skipped: false,
|
|
178
|
+
error: error.message,
|
|
179
|
+
device: deviceName
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return results;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
module.exports = {
|
|
187
|
+
metadata,
|
|
188
|
+
runTests
|
|
189
|
+
};
|