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,313 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { OnlineStatus } = require('meross-iot');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Test Helper Utilities
|
|
7
|
+
*
|
|
8
|
+
* Pure utility functions for device discovery and connection management.
|
|
9
|
+
* All functions accept explicit parameters - no globals or environment variables.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Waits for devices to be discovered
|
|
14
|
+
* @param {Object} manager - MerossManager instance
|
|
15
|
+
* @param {number} timeout - Timeout in milliseconds (default: 5000)
|
|
16
|
+
* @returns {Promise<Array>} Array of device objects with structure: { deviceId, deviceDef, device }
|
|
17
|
+
*/
|
|
18
|
+
function waitForDevices(manager, timeout = 5000) {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
// If devices already exist, return them immediately
|
|
21
|
+
const existingDevices = manager.getAllDevices();
|
|
22
|
+
if (existingDevices && existingDevices.length > 0) {
|
|
23
|
+
const devices = [];
|
|
24
|
+
const deviceIds = new Set();
|
|
25
|
+
|
|
26
|
+
for (const device of existingDevices) {
|
|
27
|
+
// Use unique identifier for subdevices (internalId) or UUID for base devices
|
|
28
|
+
const deviceId = device.subdeviceId
|
|
29
|
+
? `${device.dev?.uuid || device.uuid}:${device.subdeviceId}`
|
|
30
|
+
: (device.dev?.uuid || device.uuid);
|
|
31
|
+
|
|
32
|
+
if (!deviceIds.has(deviceId)) {
|
|
33
|
+
deviceIds.add(deviceId);
|
|
34
|
+
devices.push({
|
|
35
|
+
deviceId: deviceId,
|
|
36
|
+
deviceDef: device.dev || { uuid: device.uuid },
|
|
37
|
+
device
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
resolve(devices);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Wait for devices to be initialized
|
|
46
|
+
const devices = [];
|
|
47
|
+
const deviceIds = new Set();
|
|
48
|
+
let timeoutId = null;
|
|
49
|
+
|
|
50
|
+
const onDeviceInitialized = (deviceId, deviceDef, device) => {
|
|
51
|
+
if (!deviceIds.has(deviceId)) {
|
|
52
|
+
deviceIds.add(deviceId);
|
|
53
|
+
devices.push({ deviceId, deviceDef, device });
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
manager.on('deviceInitialized', onDeviceInitialized);
|
|
58
|
+
|
|
59
|
+
timeoutId = setTimeout(() => {
|
|
60
|
+
manager.removeListener('deviceInitialized', onDeviceInitialized);
|
|
61
|
+
resolve(devices);
|
|
62
|
+
}, timeout);
|
|
63
|
+
|
|
64
|
+
// Also check periodically if devices were added (in case event was missed)
|
|
65
|
+
const checkInterval = setInterval(() => {
|
|
66
|
+
const currentDevices = manager.getAllDevices();
|
|
67
|
+
if (currentDevices && currentDevices.length > 0) {
|
|
68
|
+
clearInterval(checkInterval);
|
|
69
|
+
if (timeoutId) {
|
|
70
|
+
clearTimeout(timeoutId);
|
|
71
|
+
}
|
|
72
|
+
manager.removeListener('deviceInitialized', onDeviceInitialized);
|
|
73
|
+
|
|
74
|
+
// Add any new devices
|
|
75
|
+
for (const device of currentDevices) {
|
|
76
|
+
const deviceId = device.subdeviceId
|
|
77
|
+
? `${device.dev?.uuid || device.uuid}:${device.subdeviceId}`
|
|
78
|
+
: (device.dev?.uuid || device.uuid);
|
|
79
|
+
|
|
80
|
+
if (!deviceIds.has(deviceId)) {
|
|
81
|
+
deviceIds.add(deviceId);
|
|
82
|
+
devices.push({
|
|
83
|
+
deviceId: deviceId,
|
|
84
|
+
deviceDef: device.dev || { uuid: device.uuid },
|
|
85
|
+
device
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
resolve(devices);
|
|
90
|
+
}
|
|
91
|
+
}, 200);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Gets device online status
|
|
97
|
+
* @param {Object} device - Device instance
|
|
98
|
+
* @returns {number|null} OnlineStatus value or null if not available
|
|
99
|
+
*/
|
|
100
|
+
function getDeviceOnlineStatus(device) {
|
|
101
|
+
if (device.onlineStatus !== undefined) {
|
|
102
|
+
return device.onlineStatus;
|
|
103
|
+
}
|
|
104
|
+
if (device.dev && device.dev.onlineStatus !== undefined) {
|
|
105
|
+
return device.dev.onlineStatus;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Checks if device has a specific ability
|
|
112
|
+
* @param {Object} device - Device instance
|
|
113
|
+
* @param {string} namespace - Ability namespace
|
|
114
|
+
* @returns {boolean} True if device has the ability
|
|
115
|
+
*/
|
|
116
|
+
function deviceHasAbility(device, namespace) {
|
|
117
|
+
return !!(device._abilities && device._abilities[namespace]);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Finds devices by ability namespace
|
|
122
|
+
* @param {Object} manager - MerossManager instance
|
|
123
|
+
* @param {string} namespace - Ability namespace (e.g., 'Appliance.Control.ToggleX')
|
|
124
|
+
* @param {number|null} onlineStatus - OnlineStatus filter (optional, null = any status)
|
|
125
|
+
* @param {Array<Object>} deviceFilter - Optional pre-filtered device list (for CLI device selection)
|
|
126
|
+
* @returns {Promise<Array>} Array of devices with the specified ability
|
|
127
|
+
*/
|
|
128
|
+
async function findDevicesByAbility(manager, namespace, onlineStatus = null, deviceFilter = null) {
|
|
129
|
+
// If device filter is provided, use it instead of discovering devices
|
|
130
|
+
if (deviceFilter && Array.isArray(deviceFilter) && deviceFilter.length > 0) {
|
|
131
|
+
return deviceFilter.filter(device => {
|
|
132
|
+
// Check ability
|
|
133
|
+
if (!deviceHasAbility(device, namespace)) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
// Filter by online status if specified
|
|
137
|
+
if (onlineStatus !== null) {
|
|
138
|
+
const deviceOnlineStatus = getDeviceOnlineStatus(device);
|
|
139
|
+
return deviceOnlineStatus === onlineStatus;
|
|
140
|
+
}
|
|
141
|
+
return true;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Normal behavior - discover devices
|
|
146
|
+
const devices = await waitForDevices(manager, 2000);
|
|
147
|
+
const filteredDevices = [];
|
|
148
|
+
|
|
149
|
+
for (const { device } of devices) {
|
|
150
|
+
// Check if device has the ability
|
|
151
|
+
if (deviceHasAbility(device, namespace)) {
|
|
152
|
+
// Filter by online status if specified
|
|
153
|
+
if (onlineStatus !== null) {
|
|
154
|
+
const deviceOnlineStatus = getDeviceOnlineStatus(device);
|
|
155
|
+
if (deviceOnlineStatus === onlineStatus) {
|
|
156
|
+
filteredDevices.push(device);
|
|
157
|
+
}
|
|
158
|
+
} else {
|
|
159
|
+
filteredDevices.push(device);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return filteredDevices;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Finds devices by device type
|
|
169
|
+
* @param {Object} manager - MerossManager instance
|
|
170
|
+
* @param {string} deviceType - Device type (e.g., 'mss310', 'msg100')
|
|
171
|
+
* @param {number|null} onlineStatus - OnlineStatus filter (optional, null = any status)
|
|
172
|
+
* @param {Array<Object>} deviceFilter - Optional pre-filtered device list (for CLI device selection)
|
|
173
|
+
* @returns {Promise<Array>} Array of devices with the specified type
|
|
174
|
+
*/
|
|
175
|
+
async function findDevicesByType(manager, deviceType, onlineStatus = null, deviceFilter = null) {
|
|
176
|
+
// If device filter is provided, use it instead of discovering devices
|
|
177
|
+
if (deviceFilter && Array.isArray(deviceFilter) && deviceFilter.length > 0) {
|
|
178
|
+
return deviceFilter.filter(device => {
|
|
179
|
+
const baseDeviceType = device.dev?.deviceType;
|
|
180
|
+
const subdeviceType = device.type || device._type;
|
|
181
|
+
const matchesType = baseDeviceType === deviceType || subdeviceType === deviceType;
|
|
182
|
+
|
|
183
|
+
if (!matchesType) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Filter by online status if specified
|
|
188
|
+
if (onlineStatus !== null) {
|
|
189
|
+
const deviceOnlineStatus = getDeviceOnlineStatus(device);
|
|
190
|
+
return deviceOnlineStatus === onlineStatus;
|
|
191
|
+
}
|
|
192
|
+
return true;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Normal behavior - discover devices
|
|
197
|
+
const devices = await waitForDevices(manager, 2000);
|
|
198
|
+
const filteredDevices = [];
|
|
199
|
+
|
|
200
|
+
for (const { device } of devices) {
|
|
201
|
+
// Check both base device type and subdevice type
|
|
202
|
+
const baseDeviceType = device.dev?.deviceType;
|
|
203
|
+
const subdeviceType = device.type || device._type;
|
|
204
|
+
const matchesType = baseDeviceType === deviceType || subdeviceType === deviceType;
|
|
205
|
+
|
|
206
|
+
if (matchesType) {
|
|
207
|
+
// Filter by online status if specified
|
|
208
|
+
if (onlineStatus !== null) {
|
|
209
|
+
const deviceOnlineStatus = getDeviceOnlineStatus(device);
|
|
210
|
+
if (deviceOnlineStatus === onlineStatus) {
|
|
211
|
+
filteredDevices.push(device);
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
filteredDevices.push(device);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return filteredDevices;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Waits for a device to be connected
|
|
224
|
+
* @param {Object} device - Device instance
|
|
225
|
+
* @param {number} timeout - Timeout in milliseconds (default: 10000)
|
|
226
|
+
* @returns {Promise<boolean>} True if connected, false if timeout
|
|
227
|
+
*/
|
|
228
|
+
function waitForDeviceConnection(device, timeout = 10000) {
|
|
229
|
+
return new Promise((resolve) => {
|
|
230
|
+
if (device.deviceConnected) {
|
|
231
|
+
resolve(true);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const onConnected = () => {
|
|
236
|
+
device.removeListener('connected', onConnected);
|
|
237
|
+
device.removeListener('error', onError);
|
|
238
|
+
clearTimeout(timeoutId);
|
|
239
|
+
resolve(true);
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const onError = (error) => {
|
|
243
|
+
device.removeListener('connected', onConnected);
|
|
244
|
+
device.removeListener('error', onError);
|
|
245
|
+
clearTimeout(timeoutId);
|
|
246
|
+
resolve(false);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const timeoutId = setTimeout(() => {
|
|
250
|
+
device.removeListener('connected', onConnected);
|
|
251
|
+
device.removeListener('error', onError);
|
|
252
|
+
resolve(false);
|
|
253
|
+
}, timeout);
|
|
254
|
+
|
|
255
|
+
device.on('connected', onConnected);
|
|
256
|
+
device.on('error', onError);
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Waits for a push notification on a device
|
|
262
|
+
* @param {Object} device - Device instance
|
|
263
|
+
* @param {string} namespace - Namespace to wait for
|
|
264
|
+
* @param {number} timeout - Timeout in milliseconds (default: 10000)
|
|
265
|
+
* @returns {Promise<Object>} Push notification payload
|
|
266
|
+
*/
|
|
267
|
+
function waitForPushNotification(device, namespace, timeout = 10000) {
|
|
268
|
+
return new Promise((resolve, reject) => {
|
|
269
|
+
const timeoutId = setTimeout(() => {
|
|
270
|
+
device.removeListener('data', onData);
|
|
271
|
+
reject(new Error(`Timeout waiting for push notification: ${namespace}`));
|
|
272
|
+
}, timeout);
|
|
273
|
+
|
|
274
|
+
const onData = (ns, payload) => {
|
|
275
|
+
if (ns === namespace) {
|
|
276
|
+
clearTimeout(timeoutId);
|
|
277
|
+
device.removeListener('data', onData);
|
|
278
|
+
resolve(payload);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
device.on('data', onData);
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Gets device display name
|
|
288
|
+
* @param {Object} device - Device instance
|
|
289
|
+
* @returns {string} Device display name
|
|
290
|
+
*/
|
|
291
|
+
function getDeviceName(device) {
|
|
292
|
+
if (!device) return 'Unknown device';
|
|
293
|
+
return device.name || device.uuid || 'Unknown device';
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
module.exports = {
|
|
297
|
+
// Device discovery
|
|
298
|
+
waitForDevices,
|
|
299
|
+
findDevicesByAbility,
|
|
300
|
+
findDevicesByType,
|
|
301
|
+
|
|
302
|
+
// Device connection
|
|
303
|
+
waitForDeviceConnection,
|
|
304
|
+
waitForPushNotification,
|
|
305
|
+
|
|
306
|
+
// Device utilities
|
|
307
|
+
getDeviceName,
|
|
308
|
+
getDeviceOnlineStatus,
|
|
309
|
+
deviceHasAbility,
|
|
310
|
+
|
|
311
|
+
// Enums
|
|
312
|
+
OnlineStatus
|
|
313
|
+
};
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hub MTS100 Thermostat Valves Tests
|
|
5
|
+
* Tests MTS100 thermostat valve control and configuration
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { findDevicesByAbility, waitForDeviceConnection, getDeviceName, OnlineStatus } = require('./test-helper');
|
|
9
|
+
|
|
10
|
+
const metadata = {
|
|
11
|
+
name: 'hub-mts100',
|
|
12
|
+
description: 'Tests MTS100 thermostat valve control and configuration',
|
|
13
|
+
requiredAbilities: ['Appliance.Hub.Mts100.All'],
|
|
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 testHub = null;
|
|
24
|
+
if (devices && devices.length > 0) {
|
|
25
|
+
testHub = devices[0];
|
|
26
|
+
} else {
|
|
27
|
+
// Find hub devices with MTS100 support
|
|
28
|
+
const mts100Hubs = await findDevicesByAbility(manager, 'Appliance.Hub.Mts100.All', OnlineStatus.ONLINE);
|
|
29
|
+
|
|
30
|
+
if (mts100Hubs.length > 0) {
|
|
31
|
+
testHub = mts100Hubs[0];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!testHub) {
|
|
36
|
+
results.push({
|
|
37
|
+
name: 'should get MTS100 all data',
|
|
38
|
+
passed: false,
|
|
39
|
+
skipped: true,
|
|
40
|
+
error: 'No Hub device with MTS100 support has been found to run this test on',
|
|
41
|
+
device: null
|
|
42
|
+
});
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const deviceName = getDeviceName(testHub);
|
|
47
|
+
|
|
48
|
+
await waitForDeviceConnection(testHub, timeout);
|
|
49
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
50
|
+
|
|
51
|
+
// Test 1: Get MTS100 all data
|
|
52
|
+
try {
|
|
53
|
+
if (typeof testHub.getMts100All !== 'function') {
|
|
54
|
+
results.push({
|
|
55
|
+
name: 'should get MTS100 all data',
|
|
56
|
+
passed: false,
|
|
57
|
+
skipped: true,
|
|
58
|
+
error: 'Hub does not support getMts100All',
|
|
59
|
+
device: deviceName
|
|
60
|
+
});
|
|
61
|
+
} else {
|
|
62
|
+
// Get MTS100 subdevices
|
|
63
|
+
const subdevices = testHub.getSubdevices();
|
|
64
|
+
const mts100Ids = subdevices
|
|
65
|
+
.filter(sub => sub.type === 'mts100v3' || sub.type === 'mts100')
|
|
66
|
+
.map(sub => sub.subdeviceId);
|
|
67
|
+
|
|
68
|
+
if (mts100Ids.length === 0) {
|
|
69
|
+
results.push({
|
|
70
|
+
name: 'should get MTS100 all data',
|
|
71
|
+
passed: false,
|
|
72
|
+
skipped: true,
|
|
73
|
+
error: 'Hub has no MTS100 subdevices',
|
|
74
|
+
device: deviceName
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
const response = await testHub.getMts100All(mts100Ids);
|
|
78
|
+
|
|
79
|
+
if (!response) {
|
|
80
|
+
results.push({
|
|
81
|
+
name: 'should get MTS100 all data',
|
|
82
|
+
passed: false,
|
|
83
|
+
skipped: false,
|
|
84
|
+
error: 'getMts100All returned null or undefined',
|
|
85
|
+
device: deviceName
|
|
86
|
+
});
|
|
87
|
+
} else if (!Array.isArray(response.all)) {
|
|
88
|
+
results.push({
|
|
89
|
+
name: 'should get MTS100 all data',
|
|
90
|
+
passed: false,
|
|
91
|
+
skipped: false,
|
|
92
|
+
error: 'Response all is not an array',
|
|
93
|
+
device: deviceName
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
results.push({
|
|
97
|
+
name: 'should get MTS100 all data',
|
|
98
|
+
passed: true,
|
|
99
|
+
skipped: false,
|
|
100
|
+
error: null,
|
|
101
|
+
device: deviceName,
|
|
102
|
+
details: { deviceCount: response.all.length }
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
results.push({
|
|
109
|
+
name: 'should get MTS100 all data',
|
|
110
|
+
passed: false,
|
|
111
|
+
skipped: false,
|
|
112
|
+
error: error.message,
|
|
113
|
+
device: deviceName
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Test 2: Control MTS100 mode
|
|
118
|
+
try {
|
|
119
|
+
if (typeof testHub.controlHubMts100Mode !== 'function') {
|
|
120
|
+
results.push({
|
|
121
|
+
name: 'should control MTS100 mode',
|
|
122
|
+
passed: false,
|
|
123
|
+
skipped: true,
|
|
124
|
+
error: 'Hub does not support controlHubMts100Mode',
|
|
125
|
+
device: deviceName
|
|
126
|
+
});
|
|
127
|
+
} else {
|
|
128
|
+
const subdevices = testHub.getSubdevices();
|
|
129
|
+
const mts100Ids = subdevices
|
|
130
|
+
.filter(sub => sub.type === 'mts100v3' || sub.type === 'mts100')
|
|
131
|
+
.map(sub => sub.subdeviceId);
|
|
132
|
+
|
|
133
|
+
if (mts100Ids.length === 0) {
|
|
134
|
+
results.push({
|
|
135
|
+
name: 'should control MTS100 mode',
|
|
136
|
+
passed: false,
|
|
137
|
+
skipped: true,
|
|
138
|
+
error: 'Hub has no MTS100 subdevices',
|
|
139
|
+
device: deviceName
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
// Get current state first
|
|
143
|
+
await testHub.getMts100All([mts100Ids[0]]);
|
|
144
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
145
|
+
|
|
146
|
+
// Note: We don't actually change the mode to avoid disrupting the device
|
|
147
|
+
// We just verify the method exists and can be called
|
|
148
|
+
results.push({
|
|
149
|
+
name: 'should control MTS100 mode',
|
|
150
|
+
passed: true,
|
|
151
|
+
skipped: false,
|
|
152
|
+
error: null,
|
|
153
|
+
device: deviceName,
|
|
154
|
+
details: { note: 'Method exists, but not changing mode to avoid disruption' }
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
} catch (error) {
|
|
159
|
+
results.push({
|
|
160
|
+
name: 'should control MTS100 mode',
|
|
161
|
+
passed: false,
|
|
162
|
+
skipped: false,
|
|
163
|
+
error: error.message,
|
|
164
|
+
device: deviceName
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Test 3: Control MTS100 temperature
|
|
169
|
+
try {
|
|
170
|
+
if (typeof testHub.controlHubMts100Temperature !== 'function') {
|
|
171
|
+
results.push({
|
|
172
|
+
name: 'should control MTS100 temperature',
|
|
173
|
+
passed: false,
|
|
174
|
+
skipped: true,
|
|
175
|
+
error: 'Hub does not support controlHubMts100Temperature',
|
|
176
|
+
device: deviceName
|
|
177
|
+
});
|
|
178
|
+
} else {
|
|
179
|
+
const subdevices = testHub.getSubdevices();
|
|
180
|
+
const mts100Ids = subdevices
|
|
181
|
+
.filter(sub => sub.type === 'mts100v3' || sub.type === 'mts100')
|
|
182
|
+
.map(sub => sub.subdeviceId);
|
|
183
|
+
|
|
184
|
+
if (mts100Ids.length === 0) {
|
|
185
|
+
results.push({
|
|
186
|
+
name: 'should control MTS100 temperature',
|
|
187
|
+
passed: false,
|
|
188
|
+
skipped: true,
|
|
189
|
+
error: 'Hub has no MTS100 subdevices',
|
|
190
|
+
device: deviceName
|
|
191
|
+
});
|
|
192
|
+
} else {
|
|
193
|
+
// Get current state first
|
|
194
|
+
await testHub.getMts100All([mts100Ids[0]]);
|
|
195
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
196
|
+
|
|
197
|
+
// Note: We don't actually change the temperature to avoid disrupting the device
|
|
198
|
+
// We just verify the method exists
|
|
199
|
+
results.push({
|
|
200
|
+
name: 'should control MTS100 temperature',
|
|
201
|
+
passed: true,
|
|
202
|
+
skipped: false,
|
|
203
|
+
error: null,
|
|
204
|
+
device: deviceName,
|
|
205
|
+
details: { note: 'Method exists, but not changing temperature to avoid disruption' }
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} catch (error) {
|
|
210
|
+
results.push({
|
|
211
|
+
name: 'should control MTS100 temperature',
|
|
212
|
+
passed: false,
|
|
213
|
+
skipped: false,
|
|
214
|
+
error: error.message,
|
|
215
|
+
device: deviceName
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Test 4: Get MTS100 adjustment settings
|
|
220
|
+
try {
|
|
221
|
+
if (typeof testHub.getMts100Adjust !== 'function') {
|
|
222
|
+
results.push({
|
|
223
|
+
name: 'should get MTS100 adjustment settings',
|
|
224
|
+
passed: false,
|
|
225
|
+
skipped: true,
|
|
226
|
+
error: 'Hub does not support getMts100Adjust',
|
|
227
|
+
device: deviceName
|
|
228
|
+
});
|
|
229
|
+
} else {
|
|
230
|
+
const subdevices = testHub.getSubdevices();
|
|
231
|
+
const mts100Ids = subdevices
|
|
232
|
+
.filter(sub => sub.type === 'mts100v3' || sub.type === 'mts100')
|
|
233
|
+
.map(sub => sub.subdeviceId);
|
|
234
|
+
|
|
235
|
+
if (mts100Ids.length === 0) {
|
|
236
|
+
results.push({
|
|
237
|
+
name: 'should get MTS100 adjustment settings',
|
|
238
|
+
passed: false,
|
|
239
|
+
skipped: true,
|
|
240
|
+
error: 'Hub has no MTS100 subdevices',
|
|
241
|
+
device: deviceName
|
|
242
|
+
});
|
|
243
|
+
} else {
|
|
244
|
+
const response = await testHub.getMts100Adjust(mts100Ids);
|
|
245
|
+
|
|
246
|
+
if (!response) {
|
|
247
|
+
results.push({
|
|
248
|
+
name: 'should get MTS100 adjustment settings',
|
|
249
|
+
passed: false,
|
|
250
|
+
skipped: false,
|
|
251
|
+
error: 'getMts100Adjust returned null or undefined',
|
|
252
|
+
device: deviceName
|
|
253
|
+
});
|
|
254
|
+
} else if (!Array.isArray(response.adjust)) {
|
|
255
|
+
results.push({
|
|
256
|
+
name: 'should get MTS100 adjustment settings',
|
|
257
|
+
passed: false,
|
|
258
|
+
skipped: false,
|
|
259
|
+
error: 'Response adjust is not an array',
|
|
260
|
+
device: deviceName
|
|
261
|
+
});
|
|
262
|
+
} else {
|
|
263
|
+
results.push({
|
|
264
|
+
name: 'should get MTS100 adjustment settings',
|
|
265
|
+
passed: true,
|
|
266
|
+
skipped: false,
|
|
267
|
+
error: null,
|
|
268
|
+
device: deviceName,
|
|
269
|
+
details: { adjustCount: response.adjust.length }
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} catch (error) {
|
|
275
|
+
results.push({
|
|
276
|
+
name: 'should get MTS100 adjustment settings',
|
|
277
|
+
passed: false,
|
|
278
|
+
skipped: false,
|
|
279
|
+
error: error.message,
|
|
280
|
+
device: deviceName
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Test 5: Get MTS100 config
|
|
285
|
+
try {
|
|
286
|
+
if (typeof testHub.getMts100Config !== 'function') {
|
|
287
|
+
results.push({
|
|
288
|
+
name: 'should get MTS100 config',
|
|
289
|
+
passed: false,
|
|
290
|
+
skipped: true,
|
|
291
|
+
error: 'Hub does not support getMts100Config',
|
|
292
|
+
device: deviceName
|
|
293
|
+
});
|
|
294
|
+
} else {
|
|
295
|
+
const subdevices = testHub.getSubdevices();
|
|
296
|
+
const mts100Ids = subdevices
|
|
297
|
+
.filter(sub => sub.type === 'mts100v3' || sub.type === 'mts100')
|
|
298
|
+
.map(sub => sub.subdeviceId);
|
|
299
|
+
|
|
300
|
+
if (mts100Ids.length === 0) {
|
|
301
|
+
results.push({
|
|
302
|
+
name: 'should get MTS100 config',
|
|
303
|
+
passed: false,
|
|
304
|
+
skipped: true,
|
|
305
|
+
error: 'Hub has no MTS100 subdevices',
|
|
306
|
+
device: deviceName
|
|
307
|
+
});
|
|
308
|
+
} else {
|
|
309
|
+
const response = await testHub.getMts100Config(mts100Ids);
|
|
310
|
+
|
|
311
|
+
if (!response) {
|
|
312
|
+
results.push({
|
|
313
|
+
name: 'should get MTS100 config',
|
|
314
|
+
passed: false,
|
|
315
|
+
skipped: false,
|
|
316
|
+
error: 'getMts100Config returned null or undefined',
|
|
317
|
+
device: deviceName
|
|
318
|
+
});
|
|
319
|
+
} else if (!Array.isArray(response.config)) {
|
|
320
|
+
results.push({
|
|
321
|
+
name: 'should get MTS100 config',
|
|
322
|
+
passed: false,
|
|
323
|
+
skipped: false,
|
|
324
|
+
error: 'Response config is not an array',
|
|
325
|
+
device: deviceName
|
|
326
|
+
});
|
|
327
|
+
} else {
|
|
328
|
+
results.push({
|
|
329
|
+
name: 'should get MTS100 config',
|
|
330
|
+
passed: true,
|
|
331
|
+
skipped: false,
|
|
332
|
+
error: null,
|
|
333
|
+
device: deviceName,
|
|
334
|
+
details: { configCount: response.config.length }
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
} catch (error) {
|
|
340
|
+
results.push({
|
|
341
|
+
name: 'should get MTS100 config',
|
|
342
|
+
passed: false,
|
|
343
|
+
skipped: false,
|
|
344
|
+
error: error.message,
|
|
345
|
+
device: deviceName
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return results;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
module.exports = {
|
|
353
|
+
metadata,
|
|
354
|
+
runTests
|
|
355
|
+
};
|