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,89 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const { MerossHttpClient, TransportMode } = require('meross-iot');
|
|
5
|
+
|
|
6
|
+
async function processOptionsAndCreateHttpClient(opts) {
|
|
7
|
+
const email = opts.email || process.env.MEROSS_EMAIL || null;
|
|
8
|
+
const password = opts.password || process.env.MEROSS_PASSWORD || null;
|
|
9
|
+
const mfaCode = opts.mfaCode || process.env.MEROSS_MFA_CODE || null;
|
|
10
|
+
|
|
11
|
+
let tokenData = null;
|
|
12
|
+
const tokenDataPath = opts.tokenData || process.env.MEROSS_TOKEN_DATA || null;
|
|
13
|
+
if (tokenDataPath && fs.existsSync(tokenDataPath)) {
|
|
14
|
+
try {
|
|
15
|
+
tokenData = JSON.parse(fs.readFileSync(tokenDataPath, 'utf8'));
|
|
16
|
+
} catch (error) {
|
|
17
|
+
throw new Error(`Error reading token data file: ${error.message}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const timeout = opts.timeout ? parseInt(opts.timeout, 10) : 10000;
|
|
22
|
+
const enableStats = opts.enableStats || false;
|
|
23
|
+
const verbose = opts.verbose || false;
|
|
24
|
+
|
|
25
|
+
let httpClient;
|
|
26
|
+
|
|
27
|
+
if (tokenData) {
|
|
28
|
+
httpClient = MerossHttpClient.fromCredentials(tokenData, {
|
|
29
|
+
logger: verbose ? console.log : null,
|
|
30
|
+
timeout,
|
|
31
|
+
autoRetryOnBadDomain: true,
|
|
32
|
+
enableStats,
|
|
33
|
+
maxStatsSamples: 1000
|
|
34
|
+
});
|
|
35
|
+
} else if (email && password) {
|
|
36
|
+
httpClient = await MerossHttpClient.fromUserPassword({
|
|
37
|
+
email,
|
|
38
|
+
password,
|
|
39
|
+
mfaCode,
|
|
40
|
+
logger: verbose ? console.log : null,
|
|
41
|
+
timeout,
|
|
42
|
+
autoRetryOnBadDomain: true,
|
|
43
|
+
enableStats,
|
|
44
|
+
maxStatsSamples: 1000
|
|
45
|
+
});
|
|
46
|
+
} else {
|
|
47
|
+
throw new Error('Email and password are required (or provide token data).\nUse --email and --password options or set MEROSS_EMAIL and MEROSS_PASSWORD environment variables.');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const transportModeStr = opts.transportMode || 'mqtt_only';
|
|
51
|
+
let transportMode = TransportMode.MQTT_ONLY;
|
|
52
|
+
if (transportModeStr === 'lan_http_first') {
|
|
53
|
+
transportMode = TransportMode.LAN_HTTP_FIRST;
|
|
54
|
+
} else if (transportModeStr === 'lan_http_first_only_get') {
|
|
55
|
+
transportMode = TransportMode.LAN_HTTP_FIRST_ONLY_GET;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
httpClient,
|
|
60
|
+
options: {
|
|
61
|
+
httpClient,
|
|
62
|
+
transportMode,
|
|
63
|
+
timeout,
|
|
64
|
+
enableStats,
|
|
65
|
+
logger: verbose ? console.log : null
|
|
66
|
+
},
|
|
67
|
+
config: {
|
|
68
|
+
transportMode,
|
|
69
|
+
timeout,
|
|
70
|
+
enableStats,
|
|
71
|
+
verbose
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function getTransportModeName(mode) {
|
|
77
|
+
const modeMap = {
|
|
78
|
+
[TransportMode.MQTT_ONLY]: 'MQTT Only',
|
|
79
|
+
[TransportMode.LAN_HTTP_FIRST]: 'LAN HTTP First',
|
|
80
|
+
[TransportMode.LAN_HTTP_FIRST_ONLY_GET]: 'LAN HTTP First (GET only)'
|
|
81
|
+
};
|
|
82
|
+
return modeMap[mode] || `Unknown (${mode})`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
module.exports = {
|
|
86
|
+
processOptionsAndCreateHttpClient,
|
|
87
|
+
getTransportModeName
|
|
88
|
+
};
|
|
89
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const MerossManager = require('meross-iot');
|
|
4
|
+
const { MerossHttpClient, TransportMode } = require('meross-iot');
|
|
5
|
+
const ora = require('ora');
|
|
6
|
+
|
|
7
|
+
async function createMerossInstance(optionsOrEmail, password, mfaCode, transportMode, timeout, enableStats, verbose) {
|
|
8
|
+
let httpClient;
|
|
9
|
+
let finalTransportMode;
|
|
10
|
+
let finalTimeout;
|
|
11
|
+
let finalEnableStats;
|
|
12
|
+
let finalVerbose;
|
|
13
|
+
|
|
14
|
+
// Handle both old signature (individual params) and new signature (options object)
|
|
15
|
+
if (typeof optionsOrEmail === 'object' && optionsOrEmail !== null && optionsOrEmail.httpClient) {
|
|
16
|
+
// New signature: options object
|
|
17
|
+
const options = optionsOrEmail;
|
|
18
|
+
httpClient = options.httpClient;
|
|
19
|
+
finalTransportMode = options.transportMode || TransportMode.MQTT_ONLY;
|
|
20
|
+
finalTimeout = options.timeout || 10000;
|
|
21
|
+
finalEnableStats = options.enableStats || false;
|
|
22
|
+
finalVerbose = options.verbose || false;
|
|
23
|
+
} else {
|
|
24
|
+
// Old signature: individual parameters
|
|
25
|
+
const email = optionsOrEmail;
|
|
26
|
+
finalTransportMode = transportMode || TransportMode.MQTT_ONLY;
|
|
27
|
+
finalTimeout = timeout || 10000;
|
|
28
|
+
finalEnableStats = enableStats || false;
|
|
29
|
+
finalVerbose = verbose || false;
|
|
30
|
+
|
|
31
|
+
// Create HTTP client
|
|
32
|
+
httpClient = await MerossHttpClient.fromUserPassword({
|
|
33
|
+
email,
|
|
34
|
+
password,
|
|
35
|
+
mfaCode,
|
|
36
|
+
logger: finalVerbose ? console.log : null,
|
|
37
|
+
timeout: finalTimeout,
|
|
38
|
+
autoRetryOnBadDomain: true,
|
|
39
|
+
enableStats: finalEnableStats,
|
|
40
|
+
maxStatsSamples: 1000
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const instance = new MerossManager({
|
|
45
|
+
httpClient,
|
|
46
|
+
transportMode: finalTransportMode,
|
|
47
|
+
timeout: finalTimeout,
|
|
48
|
+
enableStats: finalEnableStats,
|
|
49
|
+
logger: finalVerbose ? console.log : null
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
instance.on('deviceInitialized', (deviceId) => {
|
|
53
|
+
if (finalVerbose) {
|
|
54
|
+
console.log(`Device initialized: ${deviceId}`);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
instance.on('connected', (deviceId) => {
|
|
59
|
+
if (finalVerbose) {
|
|
60
|
+
console.log(`Device connected: ${deviceId}`);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
instance.on('error', (error, deviceId) => {
|
|
65
|
+
if (finalVerbose) {
|
|
66
|
+
console.error(`Error${deviceId ? ` (${deviceId})` : ''}: ${error.message}`);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return instance;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function connectMeross(manager) {
|
|
74
|
+
const spinner = ora('Connecting to Meross cloud...').start();
|
|
75
|
+
try {
|
|
76
|
+
const deviceCount = await manager.connect();
|
|
77
|
+
spinner.succeed(`Connected to ${deviceCount} device(s)`);
|
|
78
|
+
|
|
79
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
80
|
+
return true;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
spinner.fail(`Connection error: ${error.message}`);
|
|
83
|
+
if (error.stack && process.env.MEROSS_VERBOSE) {
|
|
84
|
+
console.error(error.stack);
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function disconnectMeross(manager) {
|
|
91
|
+
try {
|
|
92
|
+
if (manager && manager.authenticated) {
|
|
93
|
+
await manager.logout();
|
|
94
|
+
manager.disconnectAll(true);
|
|
95
|
+
}
|
|
96
|
+
} catch (error) {
|
|
97
|
+
// Ignore logout errors
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
module.exports = {
|
|
102
|
+
createMerossInstance,
|
|
103
|
+
connectMeross,
|
|
104
|
+
disconnectMeross
|
|
105
|
+
};
|
|
106
|
+
|