meross-cli 0.2.0 → 0.3.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 +9 -0
- package/README.md +13 -6
- package/cli/commands/info.js +29 -26
- package/cli/control-registry.js +2 -2
- package/cli/tests/test-control.js +3 -4
- package/cli/tests/test-diffuser.js +2 -2
- package/cli/tests/test-dnd.js +1 -2
- package/cli/tests/test-encryption.js +5 -5
- package/cli/tests/test-helper.js +24 -34
- package/cli/tests/test-hub-sensors.js +1 -1
- package/cli/tests/test-runner.js +7 -10
- package/cli/tests/test-runtime.js +3 -4
- package/cli/tests/test-template.js +2 -2
- package/cli/tests/test-toggle.js +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2026-01-16
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
- **BREAKING**: Updated to use simplified device API from `meross-iot` v0.4.0
|
|
12
|
+
- Updated to use `initializeDevices()` instead of `getDevices()`
|
|
13
|
+
- Updated to use direct device properties instead of `cachedHttpInfo`
|
|
14
|
+
- Updated to use camelCase property names consistently
|
|
15
|
+
- Updated all tests and commands to use new API patterns
|
|
16
|
+
|
|
8
17
|
## [0.2.0] - 2026-01-15
|
|
9
18
|
|
|
10
19
|
### Changed
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Command-line interface for controlling and managing Meross smart home devices.
|
|
|
23
23
|
npm install -g meross-cli@alpha
|
|
24
24
|
|
|
25
25
|
# Or install specific version
|
|
26
|
-
npm install -g meross-cli@0.
|
|
26
|
+
npm install -g meross-cli@0.3.0
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Or use via npx:
|
|
@@ -77,6 +77,18 @@ The CLI supports all devices that are supported by the underlying `meross-iot` l
|
|
|
77
77
|
|
|
78
78
|
## Changelog
|
|
79
79
|
|
|
80
|
+
### [0.3.0] - 2026-01-16
|
|
81
|
+
|
|
82
|
+
#### Changed
|
|
83
|
+
- **BREAKING**: Updated to use simplified device API from `meross-iot` v0.4.0
|
|
84
|
+
- Updated to use `initializeDevices()` instead of `getDevices()`
|
|
85
|
+
- Updated to use direct device properties instead of `cachedHttpInfo`
|
|
86
|
+
- Updated to use camelCase property names consistently
|
|
87
|
+
- Updated all tests and commands to use new API patterns
|
|
88
|
+
|
|
89
|
+
<details>
|
|
90
|
+
<summary>Older</summary>
|
|
91
|
+
|
|
80
92
|
### [0.2.0] - 2026-01-15
|
|
81
93
|
|
|
82
94
|
#### Changed
|
|
@@ -107,11 +119,6 @@ The CLI supports all devices that are supported by the underlying `meross-iot` l
|
|
|
107
119
|
- This is an initial, pre-stable release. Please expect bugs.
|
|
108
120
|
- Some edge cases may not be fully handled yet.
|
|
109
121
|
|
|
110
|
-
<details>
|
|
111
|
-
<summary>Older</summary>
|
|
112
|
-
|
|
113
|
-
<!-- Older changelog entries will appear here -->
|
|
114
|
-
|
|
115
122
|
</details>
|
|
116
123
|
|
|
117
124
|
## Disclaimer
|
package/cli/commands/info.js
CHANGED
|
@@ -84,35 +84,41 @@ function _displayChannels(device) {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
|
-
*
|
|
87
|
+
* Extracts HTTP device info properties for display.
|
|
88
|
+
*
|
|
89
|
+
* Collects HTTP metadata properties (domain, reservedDomain, subType, region, etc.)
|
|
90
|
+
* that are now directly accessible on the device instance for formatting in the CLI output.
|
|
91
|
+
*
|
|
92
|
+
* @param {Object} device - MerossDevice instance
|
|
93
|
+
* @returns {Array<Array<string>>} Array of [label, value] pairs for display
|
|
88
94
|
*/
|
|
89
|
-
function _buildHttpInfoData(
|
|
95
|
+
function _buildHttpInfoData(device) {
|
|
90
96
|
const httpInfoData = [];
|
|
91
97
|
|
|
92
|
-
if (
|
|
93
|
-
httpInfoData.push(['MQTT Domain',
|
|
98
|
+
if (device.domain) {
|
|
99
|
+
httpInfoData.push(['MQTT Domain', device.domain]);
|
|
94
100
|
}
|
|
95
|
-
if (
|
|
96
|
-
httpInfoData.push(['Reserved Domain',
|
|
101
|
+
if (device.reservedDomain) {
|
|
102
|
+
httpInfoData.push(['Reserved Domain', device.reservedDomain]);
|
|
97
103
|
}
|
|
98
|
-
if (
|
|
99
|
-
httpInfoData.push(['Sub Type',
|
|
104
|
+
if (device.subType) {
|
|
105
|
+
httpInfoData.push(['Sub Type', device.subType]);
|
|
100
106
|
}
|
|
101
|
-
if (
|
|
102
|
-
httpInfoData.push(['Region',
|
|
107
|
+
if (device.region) {
|
|
108
|
+
httpInfoData.push(['Region', device.region]);
|
|
103
109
|
}
|
|
104
|
-
if (
|
|
105
|
-
httpInfoData.push(['Skill Number',
|
|
110
|
+
if (device.skillNumber) {
|
|
111
|
+
httpInfoData.push(['Skill Number', device.skillNumber]);
|
|
106
112
|
}
|
|
107
|
-
if (
|
|
108
|
-
httpInfoData.push(['Icon ID',
|
|
113
|
+
if (device.devIconId) {
|
|
114
|
+
httpInfoData.push(['Icon ID', device.devIconId]);
|
|
109
115
|
}
|
|
110
|
-
if (
|
|
111
|
-
httpInfoData.push(['Bind Time',
|
|
116
|
+
if (device.bindTime) {
|
|
117
|
+
httpInfoData.push(['Bind Time', device.bindTime.toLocaleString()]);
|
|
112
118
|
}
|
|
113
|
-
if (
|
|
114
|
-
const onlineStatusText =
|
|
115
|
-
|
|
119
|
+
if (device.onlineStatus !== undefined) {
|
|
120
|
+
const onlineStatusText = device.onlineStatus === OnlineStatus.ONLINE ? chalk.green('Online') :
|
|
121
|
+
device.onlineStatus === OnlineStatus.OFFLINE ? chalk.red('Offline') :
|
|
116
122
|
chalk.yellow('Unknown');
|
|
117
123
|
httpInfoData.push(['Online Status', onlineStatusText]);
|
|
118
124
|
}
|
|
@@ -121,15 +127,12 @@ function _buildHttpInfoData(httpInfo) {
|
|
|
121
127
|
}
|
|
122
128
|
|
|
123
129
|
/**
|
|
124
|
-
* Displays HTTP device info if available.
|
|
130
|
+
* Displays HTTP device info section if properties are available.
|
|
131
|
+
*
|
|
132
|
+
* @param {Object} device - MerossDevice instance
|
|
125
133
|
*/
|
|
126
134
|
function _displayHttpInfo(device) {
|
|
127
|
-
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const httpInfo = device.cachedHttpInfo;
|
|
132
|
-
const httpInfoData = _buildHttpInfoData(httpInfo);
|
|
135
|
+
const httpInfoData = _buildHttpInfoData(device);
|
|
133
136
|
|
|
134
137
|
if (httpInfoData.length === 0) {
|
|
135
138
|
return;
|
package/cli/control-registry.js
CHANGED
|
@@ -762,10 +762,10 @@ function getMethodsByCategory() {
|
|
|
762
762
|
* @returns {boolean} True if device supports the namespace
|
|
763
763
|
*/
|
|
764
764
|
function deviceSupportsNamespace(device, namespace) {
|
|
765
|
-
if (!device.
|
|
765
|
+
if (!device.abilities || typeof device.abilities !== 'object') {
|
|
766
766
|
return false;
|
|
767
767
|
}
|
|
768
|
-
return !!device.
|
|
768
|
+
return !!device.abilities[namespace];
|
|
769
769
|
}
|
|
770
770
|
|
|
771
771
|
/**
|
|
@@ -28,15 +28,14 @@ async function runTests(context) {
|
|
|
28
28
|
// Also get any online device for testing control features
|
|
29
29
|
const allDevices = manager.devices.list();
|
|
30
30
|
const onlineDevices = allDevices.filter(device => {
|
|
31
|
-
|
|
32
|
-
return status === OnlineStatus.ONLINE;
|
|
31
|
+
return device.onlineStatus === OnlineStatus.ONLINE;
|
|
33
32
|
});
|
|
34
33
|
|
|
35
34
|
// Combine and deduplicate
|
|
36
35
|
testDevices = [...multipleDevices];
|
|
37
36
|
for (const device of onlineDevices.slice(0, 2)) {
|
|
38
|
-
const uuid = device.
|
|
39
|
-
if (!testDevices.find(d =>
|
|
37
|
+
const uuid = device.uuid;
|
|
38
|
+
if (!testDevices.find(d => d.uuid === uuid)) {
|
|
40
39
|
testDevices.push(device);
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -27,10 +27,10 @@ async function runTests(context) {
|
|
|
27
27
|
if (devices && devices.length > 0) {
|
|
28
28
|
// Use provided devices, filter by capabilities
|
|
29
29
|
lightDevices = devices.filter(d =>
|
|
30
|
-
d.
|
|
30
|
+
d.abilities && d.abilities['Appliance.Control.Diffuser.Light']
|
|
31
31
|
);
|
|
32
32
|
sprayDevices = devices.filter(d =>
|
|
33
|
-
d.
|
|
33
|
+
d.abilities && d.abilities['Appliance.Control.Diffuser.Spray']
|
|
34
34
|
);
|
|
35
35
|
} else {
|
|
36
36
|
// Find diffuser light devices
|
package/cli/tests/test-dnd.js
CHANGED
|
@@ -26,8 +26,7 @@ async function runTests(context) {
|
|
|
26
26
|
// Find devices that support DND mode (most devices support this)
|
|
27
27
|
const allDevices = manager.devices.list();
|
|
28
28
|
testDevices = allDevices.filter(d => {
|
|
29
|
-
|
|
30
|
-
return status === OnlineStatus.ONLINE &&
|
|
29
|
+
return d.onlineStatus === OnlineStatus.ONLINE &&
|
|
31
30
|
typeof d.getDNDMode === 'function' &&
|
|
32
31
|
typeof d.setDNDMode === 'function';
|
|
33
32
|
});
|
|
@@ -31,7 +31,7 @@ async function runTests(context) {
|
|
|
31
31
|
// Combine and deduplicate
|
|
32
32
|
const allDevices = [...encryptionDevices];
|
|
33
33
|
for (const device of suiteDevices) {
|
|
34
|
-
if (!allDevices.find(d => d.
|
|
34
|
+
if (!allDevices.find(d => d.uuid === device.uuid)) {
|
|
35
35
|
allDevices.push(device);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -115,8 +115,8 @@ async function runTests(context) {
|
|
|
115
115
|
const isKeySet = testDevice.isEncryptionKeySet();
|
|
116
116
|
|
|
117
117
|
// If key is not set and we have the required info, set it
|
|
118
|
-
if (!isKeySet && testDevice.
|
|
119
|
-
testDevice.setEncryptionKey(testDevice.
|
|
118
|
+
if (!isKeySet && testDevice.uuid && manager.key && testDevice.macAddress) {
|
|
119
|
+
testDevice.setEncryptionKey(testDevice.uuid, manager.key, testDevice.macAddress);
|
|
120
120
|
|
|
121
121
|
const keySetAfter = testDevice.isEncryptionKeySet();
|
|
122
122
|
|
|
@@ -180,8 +180,8 @@ async function runTests(context) {
|
|
|
180
180
|
} else {
|
|
181
181
|
// Ensure encryption key is set
|
|
182
182
|
if (!testDevice.isEncryptionKeySet()) {
|
|
183
|
-
if (testDevice.
|
|
184
|
-
testDevice.setEncryptionKey(testDevice.
|
|
183
|
+
if (testDevice.uuid && manager.key && testDevice.macAddress) {
|
|
184
|
+
testDevice.setEncryptionKey(testDevice.uuid, manager.key, testDevice.macAddress);
|
|
185
185
|
} else {
|
|
186
186
|
results.push({
|
|
187
187
|
name: 'should encrypt and decrypt messages if encryption key is set',
|
package/cli/tests/test-helper.js
CHANGED
|
@@ -10,10 +10,15 @@ const { OnlineStatus } = require('meross-iot');
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Waits for devices to be discovered
|
|
13
|
+
* Waits for devices to be discovered.
|
|
14
|
+
*
|
|
15
|
+
* Returns an array of MerossDevice instances once they are initialized. Uses
|
|
16
|
+
* device UUID (or subdevice ID) for deduplication to avoid returning the same
|
|
17
|
+
* device multiple times.
|
|
18
|
+
*
|
|
14
19
|
* @param {Object} manager - ManagerMeross instance
|
|
15
20
|
* @param {number} timeout - Timeout in milliseconds (default: 5000)
|
|
16
|
-
* @returns {Promise<Array
|
|
21
|
+
* @returns {Promise<Array<MerossDevice>>} Array of device instances
|
|
17
22
|
*/
|
|
18
23
|
function waitForDevices(manager, timeout = 5000) {
|
|
19
24
|
return new Promise((resolve) => {
|
|
@@ -24,33 +29,28 @@ function waitForDevices(manager, timeout = 5000) {
|
|
|
24
29
|
const deviceIds = new Set();
|
|
25
30
|
|
|
26
31
|
for (const device of existingDevices) {
|
|
27
|
-
// Use unique identifier for subdevices (
|
|
32
|
+
// Use unique identifier for subdevices (parentUUID:subdeviceId) or UUID for base devices
|
|
28
33
|
const deviceId = device.subdeviceId
|
|
29
|
-
? `${device.
|
|
30
|
-
:
|
|
34
|
+
? `${device.uuid}:${device.subdeviceId}`
|
|
35
|
+
: device.uuid;
|
|
31
36
|
|
|
32
37
|
if (!deviceIds.has(deviceId)) {
|
|
33
38
|
deviceIds.add(deviceId);
|
|
34
|
-
devices.push(
|
|
35
|
-
deviceId: deviceId,
|
|
36
|
-
deviceDef: device.dev || { uuid: device.uuid },
|
|
37
|
-
device
|
|
38
|
-
});
|
|
39
|
+
devices.push(device);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
resolve(devices);
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
// Wait for devices to be initialized
|
|
46
46
|
const devices = [];
|
|
47
47
|
const deviceIds = new Set();
|
|
48
48
|
let timeoutId = null;
|
|
49
49
|
|
|
50
|
-
const onDeviceInitialized = (deviceId,
|
|
50
|
+
const onDeviceInitialized = (deviceId, device) => {
|
|
51
51
|
if (!deviceIds.has(deviceId)) {
|
|
52
52
|
deviceIds.add(deviceId);
|
|
53
|
-
devices.push(
|
|
53
|
+
devices.push(device);
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
|
|
@@ -61,7 +61,8 @@ function waitForDevices(manager, timeout = 5000) {
|
|
|
61
61
|
resolve(devices);
|
|
62
62
|
}, timeout);
|
|
63
63
|
|
|
64
|
-
//
|
|
64
|
+
// Periodic check handles cases where deviceInitialized event was missed
|
|
65
|
+
// (e.g., devices initialized before event handler was attached)
|
|
65
66
|
const checkInterval = setInterval(() => {
|
|
66
67
|
const currentDevices = manager.devices.list();
|
|
67
68
|
if (currentDevices && currentDevices.length > 0) {
|
|
@@ -71,19 +72,14 @@ function waitForDevices(manager, timeout = 5000) {
|
|
|
71
72
|
}
|
|
72
73
|
manager.removeListener('deviceInitialized', onDeviceInitialized);
|
|
73
74
|
|
|
74
|
-
// Add any new devices
|
|
75
75
|
for (const device of currentDevices) {
|
|
76
76
|
const deviceId = device.subdeviceId
|
|
77
|
-
? `${device.
|
|
78
|
-
:
|
|
77
|
+
? `${device.uuid}:${device.subdeviceId}`
|
|
78
|
+
: device.uuid;
|
|
79
79
|
|
|
80
80
|
if (!deviceIds.has(deviceId)) {
|
|
81
81
|
deviceIds.add(deviceId);
|
|
82
|
-
devices.push(
|
|
83
|
-
deviceId: deviceId,
|
|
84
|
-
deviceDef: device.dev || { uuid: device.uuid },
|
|
85
|
-
device
|
|
86
|
-
});
|
|
82
|
+
devices.push(device);
|
|
87
83
|
}
|
|
88
84
|
}
|
|
89
85
|
resolve(devices);
|
|
@@ -98,13 +94,7 @@ function waitForDevices(manager, timeout = 5000) {
|
|
|
98
94
|
* @returns {number|null} OnlineStatus value or null if not available
|
|
99
95
|
*/
|
|
100
96
|
function getDeviceOnlineStatus(device) {
|
|
101
|
-
|
|
102
|
-
return device.onlineStatus;
|
|
103
|
-
}
|
|
104
|
-
if (device.dev && device.dev.onlineStatus !== undefined) {
|
|
105
|
-
return device.dev.onlineStatus;
|
|
106
|
-
}
|
|
107
|
-
return null;
|
|
97
|
+
return device.onlineStatus !== undefined ? device.onlineStatus : null;
|
|
108
98
|
}
|
|
109
99
|
|
|
110
100
|
/**
|
|
@@ -114,7 +104,7 @@ function getDeviceOnlineStatus(device) {
|
|
|
114
104
|
* @returns {boolean} True if device has the ability
|
|
115
105
|
*/
|
|
116
106
|
function deviceHasAbility(device, namespace) {
|
|
117
|
-
return !!(device.
|
|
107
|
+
return !!(device.abilities && device.abilities[namespace]);
|
|
118
108
|
}
|
|
119
109
|
|
|
120
110
|
/**
|
|
@@ -146,7 +136,7 @@ async function findDevicesByAbility(manager, namespace, onlineStatus = null, dev
|
|
|
146
136
|
const devices = await waitForDevices(manager, 2000);
|
|
147
137
|
const filteredDevices = [];
|
|
148
138
|
|
|
149
|
-
for (const
|
|
139
|
+
for (const device of devices) {
|
|
150
140
|
// Check if device has the ability
|
|
151
141
|
if (deviceHasAbility(device, namespace)) {
|
|
152
142
|
// Filter by online status if specified
|
|
@@ -176,7 +166,7 @@ async function findDevicesByType(manager, deviceType, onlineStatus = null, devic
|
|
|
176
166
|
// If device filter is provided, use it instead of discovering devices
|
|
177
167
|
if (deviceFilter && Array.isArray(deviceFilter) && deviceFilter.length > 0) {
|
|
178
168
|
return deviceFilter.filter(device => {
|
|
179
|
-
const baseDeviceType = device.
|
|
169
|
+
const baseDeviceType = device.deviceType;
|
|
180
170
|
const subdeviceType = device.type || device._type;
|
|
181
171
|
const matchesType = baseDeviceType === deviceType || subdeviceType === deviceType;
|
|
182
172
|
|
|
@@ -197,9 +187,9 @@ async function findDevicesByType(manager, deviceType, onlineStatus = null, devic
|
|
|
197
187
|
const devices = await waitForDevices(manager, 2000);
|
|
198
188
|
const filteredDevices = [];
|
|
199
189
|
|
|
200
|
-
for (const
|
|
190
|
+
for (const device of devices) {
|
|
201
191
|
// Check both base device type and subdevice type
|
|
202
|
-
const baseDeviceType = device.
|
|
192
|
+
const baseDeviceType = device.deviceType;
|
|
203
193
|
const subdeviceType = device.type || device._type;
|
|
204
194
|
const matchesType = baseDeviceType === deviceType || subdeviceType === deviceType;
|
|
205
195
|
|
|
@@ -36,7 +36,7 @@ async function runTests(context) {
|
|
|
36
36
|
// Also try finding by hub sensor abilities
|
|
37
37
|
const sensorHubs = await findDevicesByAbility(manager, 'Appliance.Hub.Sensor.All', OnlineStatus.ONLINE);
|
|
38
38
|
for (const device of sensorHubs) {
|
|
39
|
-
if (!hubDevices.find(d =>
|
|
39
|
+
if (!hubDevices.find(d => d.uuid === device.uuid)) {
|
|
40
40
|
hubDevices.push(device);
|
|
41
41
|
}
|
|
42
42
|
}
|
package/cli/tests/test-runner.js
CHANGED
|
@@ -325,7 +325,7 @@ async function findDevicesForTestType(testType, manager) {
|
|
|
325
325
|
if (!allDevices || allDevices.length === 0) {
|
|
326
326
|
const { waitForDevices } = require('./test-helper');
|
|
327
327
|
const deviceList = await waitForDevices(manager, 1000);
|
|
328
|
-
return deviceList.
|
|
328
|
+
return deviceList.filter(d => d);
|
|
329
329
|
}
|
|
330
330
|
|
|
331
331
|
const matchingDevices = [];
|
|
@@ -340,13 +340,12 @@ async function findDevicesForTestType(testType, manager) {
|
|
|
340
340
|
}
|
|
341
341
|
|
|
342
342
|
for (const device of allDevices) {
|
|
343
|
-
const uuid = device.
|
|
343
|
+
const uuid = device.uuid;
|
|
344
344
|
if (seenUuids.has(uuid)) {
|
|
345
345
|
continue;
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
-
if (device.onlineStatus !== OnlineStatus.ONLINE
|
|
349
|
-
device.dev?.onlineStatus !== OnlineStatus.ONLINE) {
|
|
348
|
+
if (device.onlineStatus !== OnlineStatus.ONLINE) {
|
|
350
349
|
continue;
|
|
351
350
|
}
|
|
352
351
|
|
|
@@ -371,7 +370,7 @@ async function findDevicesForTestType(testType, manager) {
|
|
|
371
370
|
}
|
|
372
371
|
|
|
373
372
|
const hasAbility = abilities.some(ability =>
|
|
374
|
-
device.
|
|
373
|
+
device.abilities && device.abilities[ability]
|
|
375
374
|
);
|
|
376
375
|
|
|
377
376
|
if (hasAbility) {
|
|
@@ -383,17 +382,15 @@ async function findDevicesForTestType(testType, manager) {
|
|
|
383
382
|
// For garage, also try by device type if no matches found
|
|
384
383
|
if (testType.toLowerCase() === 'garage' && matchingDevices.length === 0) {
|
|
385
384
|
for (const device of allDevices) {
|
|
386
|
-
const uuid = device.
|
|
385
|
+
const uuid = device.uuid;
|
|
387
386
|
if (seenUuids.has(uuid)) {
|
|
388
387
|
continue;
|
|
389
388
|
}
|
|
390
389
|
|
|
391
|
-
const baseDeviceType = device.dev?.deviceType;
|
|
392
390
|
const subdeviceType = device.type || device._type;
|
|
393
|
-
const matchesType =
|
|
391
|
+
const matchesType = device.deviceType === 'msg100' || subdeviceType === 'msg100';
|
|
394
392
|
|
|
395
|
-
if (matchesType &&
|
|
396
|
-
device.dev?.onlineStatus === OnlineStatus.ONLINE)) {
|
|
393
|
+
if (matchesType && device.onlineStatus === OnlineStatus.ONLINE) {
|
|
397
394
|
seenUuids.add(uuid);
|
|
398
395
|
matchingDevices.push(device);
|
|
399
396
|
}
|
|
@@ -25,11 +25,10 @@ async function runTests(context) {
|
|
|
25
25
|
// Runtime is typically available on most devices, so we'll test with any online device
|
|
26
26
|
const allDevices = manager.devices.list();
|
|
27
27
|
testDevices = allDevices.filter(device => {
|
|
28
|
-
|
|
29
|
-
if (status !== OnlineStatus.ONLINE) return false;
|
|
28
|
+
if (device.onlineStatus !== OnlineStatus.ONLINE) return false;
|
|
30
29
|
// Check if device has runtime ability or if it's a common device type
|
|
31
|
-
return device.
|
|
32
|
-
device.
|
|
30
|
+
return device.abilities && (
|
|
31
|
+
device.abilities['Appliance.System.Runtime'] ||
|
|
33
32
|
// Most devices support runtime, so we'll test with any online device
|
|
34
33
|
true
|
|
35
34
|
);
|
|
@@ -52,8 +52,8 @@ async function runTests(context) {
|
|
|
52
52
|
// Combine and deduplicate
|
|
53
53
|
testDevices = [...toggleXDevices];
|
|
54
54
|
for (const device of toggleDevices) {
|
|
55
|
-
const uuid = device.
|
|
56
|
-
if (!testDevices.find(d =>
|
|
55
|
+
const uuid = device.uuid;
|
|
56
|
+
if (!testDevices.find(d => d.uuid === uuid)) {
|
|
57
57
|
testDevices.push(device);
|
|
58
58
|
}
|
|
59
59
|
}
|
package/cli/tests/test-toggle.js
CHANGED
|
@@ -29,8 +29,8 @@ async function findAllToggleDevices(manager) {
|
|
|
29
29
|
// Combine and deduplicate
|
|
30
30
|
const allToggleDevices = [...toggleXDevices];
|
|
31
31
|
for (const device of toggleDevices) {
|
|
32
|
-
const uuid = device.
|
|
33
|
-
if (!allToggleDevices.find(d =>
|
|
32
|
+
const uuid = device.uuid;
|
|
33
|
+
if (!allToggleDevices.find(d => d.uuid === uuid)) {
|
|
34
34
|
allToggleDevices.push(device);
|
|
35
35
|
}
|
|
36
36
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meross-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Command-line interface for controlling Meross smart home devices",
|
|
5
5
|
"author": "Abe Haverkamp",
|
|
6
6
|
"homepage": "https://github.com/Doekse/merossiot#readme",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"chalk": "^4.1.2",
|
|
25
25
|
"commander": "^12.1.0",
|
|
26
26
|
"inquirer": "^8.2.6",
|
|
27
|
-
"meross-iot": "^0.
|
|
27
|
+
"meross-iot": "^0.4.0",
|
|
28
28
|
"ora": "^5.4.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|