homebridge-melcloud-control 4.0.0-beta.443 → 4.0.0-beta.445
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/package.json +2 -2
- package/src/functions.js +47 -66
- package/src/melcloud.js +6 -4
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "MELCloud Control",
|
|
3
3
|
"name": "homebridge-melcloud-control",
|
|
4
|
-
"version": "4.0.0-beta.
|
|
4
|
+
"version": "4.0.0-beta.445",
|
|
5
5
|
"description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"async-mqtt": "^2.6.3",
|
|
40
40
|
"axios": "^1.13.0",
|
|
41
41
|
"express": "^5.1.0",
|
|
42
|
-
"puppeteer
|
|
42
|
+
"puppeteer": "^24.26.1",
|
|
43
43
|
"axios-cookiejar-support": "^6.0.4",
|
|
44
44
|
"tough-cookie": "^6.0.0",
|
|
45
45
|
"jsdom": "^27.0.1"
|
package/src/functions.js
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
+
import util from 'util';
|
|
2
3
|
import { promises as fsPromises } from 'fs';
|
|
3
4
|
import { exec } from 'child_process';
|
|
4
|
-
import puppeteer from 'puppeteer
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import puppeteer from 'puppeteer';
|
|
6
|
+
import EventEmitter from 'events';
|
|
7
|
+
const access = util.promisify(fs.access);
|
|
8
|
+
const execPromise = util.promisify(exec);
|
|
9
|
+
|
|
10
|
+
class Functions extends EventEmitter {
|
|
11
|
+
constructor(logWarn, logError, logDebug) {
|
|
12
|
+
super();
|
|
13
|
+
this.logWarn = logWarn;
|
|
14
|
+
this.logError = logError;
|
|
15
|
+
this.logDebug = logDebug;
|
|
8
16
|
}
|
|
9
17
|
|
|
10
18
|
async saveData(path, data, stringify = true) {
|
|
@@ -52,118 +60,91 @@ class Functions {
|
|
|
52
60
|
|
|
53
61
|
try {
|
|
54
62
|
// --- Detect architecture ---
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
exec('uname -m', (e, out) => e ? rej(e) : res({ stdout: out }))
|
|
59
|
-
);
|
|
60
|
-
arch = stdout.trim();
|
|
61
|
-
console.log(`Detected architecture: ${arch}`);
|
|
62
|
-
} catch (err) {
|
|
63
|
-
console.log(`Failed to detect architecture: ${err.message}`);
|
|
64
|
-
}
|
|
63
|
+
const { stdout: archOut } = await execPromise('uname -m');
|
|
64
|
+
const arch = archOut.trim();
|
|
65
|
+
if (this.logDebug) this.emit('debug', `Detected architecture: ${arch}`);
|
|
65
66
|
|
|
66
67
|
// --- Detect OS ---
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
exec('uname -s', (e, out) => e ? rej(e) : res({ stdout: out }))
|
|
71
|
-
);
|
|
72
|
-
osName = stdout.trim();
|
|
73
|
-
console.log(`Detected OS: ${osName}`);
|
|
74
|
-
} catch (err) {
|
|
75
|
-
console.log(`Failed to detect OS: ${err.message}`);
|
|
76
|
-
}
|
|
68
|
+
const { stdout: osOut } = await execPromise('uname -s');
|
|
69
|
+
const osName = osOut.trim();
|
|
70
|
+
if (this.logDebug) this.emit('debug', `Detected OS: ${osName}`);
|
|
77
71
|
|
|
78
72
|
// --- macOS fallback ---
|
|
79
73
|
if (osName === 'Darwin') {
|
|
80
|
-
console.log('Running on macOS — using system Chromium/Chrome');
|
|
81
74
|
chromiumPath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
|
82
|
-
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
await access(chromiumPath, fs.constants.X_OK);
|
|
78
|
+
if (this.logDebug) this.emit('debug', `Using system Chrome at ${chromiumPath}`);
|
|
79
|
+
} catch {
|
|
80
|
+
if (this.logError) this.emit('error', 'System Chrome not found. Falling back to Puppeteer bundled Chromium.');
|
|
81
|
+
chromiumPath = puppeteer.executablePath();
|
|
82
|
+
}
|
|
83
83
|
return chromiumPath;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// --- Linux distro detection ---
|
|
87
87
|
let linuxDistro = 'unknown';
|
|
88
88
|
try {
|
|
89
|
-
const { stdout } = await
|
|
90
|
-
|
|
91
|
-
);
|
|
92
|
-
linuxDistro = stdout.split('\n')[0] || 'unknown';
|
|
89
|
+
const { stdout: distroOut } = await execPromise('cat /etc/os-release');
|
|
90
|
+
linuxDistro = distroOut.split('\n')[0] || 'unknown';
|
|
93
91
|
} catch {
|
|
94
|
-
|
|
92
|
+
if (this.logError) this.emit('error', '/etc/os-release not found, skipping OS detection.');
|
|
95
93
|
}
|
|
96
|
-
|
|
94
|
+
if (this.logDebug) this.emit('debug', `Linux distro: ${linuxDistro}`);
|
|
97
95
|
|
|
98
96
|
// --- Check if Chromium exists ---
|
|
99
97
|
let chromiumCheck = '';
|
|
100
98
|
try {
|
|
101
|
-
const { stdout } = await
|
|
102
|
-
|
|
103
|
-
);
|
|
104
|
-
chromiumCheck = stdout.trim();
|
|
99
|
+
const { stdout: checkOut } = await execPromise('which chromium || which chromium-browser || true');
|
|
100
|
+
chromiumCheck = checkOut.trim();
|
|
105
101
|
} catch { }
|
|
106
102
|
if (chromiumCheck) {
|
|
107
103
|
chromiumPath = chromiumCheck;
|
|
108
|
-
|
|
104
|
+
if (this.logDebug) this.emit('debug', `Found system Chromium: ${chromiumPath}`);
|
|
109
105
|
return chromiumPath;
|
|
110
106
|
}
|
|
111
107
|
|
|
112
|
-
|
|
108
|
+
if (this.logWarn) this.emit('warn', 'Chromium not found. Attempting installation...');
|
|
113
109
|
|
|
114
110
|
// --- apt-get ---
|
|
115
111
|
try {
|
|
116
|
-
await
|
|
117
|
-
|
|
118
|
-
);
|
|
119
|
-
chromiumPath = '/usr/bin/chromium-browser';
|
|
120
|
-
console.log('Chromium installed successfully via apt-get.');
|
|
112
|
+
await execPromise('sudo apt-get update -y && sudo apt-get install -y chromium-browser chromium-codecs-ffmpeg');
|
|
113
|
+
if (this.logDebug) this.emit('debug', 'Chromium installed successfully via apt-get.');
|
|
121
114
|
return chromiumPath;
|
|
122
115
|
} catch {
|
|
123
|
-
|
|
116
|
+
if (this.logError) this.emit('error', 'apt-get install failed. Trying apk or yum...');
|
|
124
117
|
}
|
|
125
118
|
|
|
126
119
|
// --- apk (Alpine) ---
|
|
127
120
|
try {
|
|
128
|
-
await
|
|
129
|
-
|
|
130
|
-
);
|
|
131
|
-
chromiumPath = '/usr/bin/chromium-browser';
|
|
132
|
-
console.log('Chromium installed successfully via apk.');
|
|
121
|
+
await execPromise('sudo apk add --no-cache chromium ffmpeg');
|
|
122
|
+
if (this.logDebug) this.emit('debug', 'Chromium installed successfully via apk.');
|
|
133
123
|
return chromiumPath;
|
|
134
124
|
} catch {
|
|
135
|
-
|
|
125
|
+
if (this.logError) this.emit('error', 'apk install failed. Trying yum...');
|
|
136
126
|
}
|
|
137
127
|
|
|
138
128
|
// --- yum (RHEL/CentOS) ---
|
|
139
129
|
try {
|
|
140
|
-
await
|
|
141
|
-
|
|
142
|
-
);
|
|
143
|
-
chromiumPath = '/usr/bin/chromium-browser';
|
|
144
|
-
console.log('Chromium installed successfully via yum.');
|
|
130
|
+
await execPromise('sudo yum install -y chromium chromium-codecs-ffmpeg');
|
|
131
|
+
if (this.logDebug) this.emit('debug', 'Chromium installed successfully via yum.');
|
|
145
132
|
return chromiumPath;
|
|
146
133
|
} catch {
|
|
147
|
-
|
|
134
|
+
if (this.logError) this.emit('error', 'yum install failed. Falling back to Puppeteer bundled Chromium.');
|
|
148
135
|
}
|
|
149
136
|
|
|
150
|
-
// --- Fallback Puppeteer
|
|
137
|
+
// --- Fallback Puppeteer ---
|
|
151
138
|
chromiumPath = puppeteer.executablePath();
|
|
152
|
-
if (
|
|
153
|
-
console.log('Puppeteer bundled Chromium not found');
|
|
154
|
-
throw new Error('Puppeteer bundled Chromium not found');
|
|
155
|
-
}
|
|
156
|
-
console.log(`Using bundled Puppeteer Chromium at ${chromiumPath}`);
|
|
139
|
+
if (this.logDebug) this.emit('debug', `Using bundled Puppeteer Chromium at ${chromiumPath || 'not found'}`);
|
|
157
140
|
return chromiumPath;
|
|
158
141
|
|
|
159
|
-
} catch (
|
|
160
|
-
|
|
161
|
-
throw err;
|
|
142
|
+
} catch (error) {
|
|
143
|
+
throw new Error(`Chromium detection/install error: ${error.message}`);
|
|
162
144
|
}
|
|
163
145
|
}
|
|
164
146
|
|
|
165
147
|
|
|
166
|
-
|
|
167
148
|
async isRunningInDocker() {
|
|
168
149
|
try {
|
|
169
150
|
if (fs.existsSync('/.dockerenv')) return true;
|
package/src/melcloud.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import EventEmitter from 'events';
|
|
3
|
-
import puppeteer from 'puppeteer
|
|
3
|
+
import puppeteer from 'puppeteer';
|
|
4
4
|
import MelCloudHomeToken from './melcloudhometoken.js';
|
|
5
5
|
import ImpulseGenerator from './impulsegenerator.js';
|
|
6
6
|
import Functions from './functions.js';
|
|
@@ -21,8 +21,11 @@ class MelCloud extends EventEmitter {
|
|
|
21
21
|
this.devicesFile = devicesFile;
|
|
22
22
|
this.devicesId = [];
|
|
23
23
|
this.contextKey = '';
|
|
24
|
-
this.functions = new Functions(
|
|
25
|
-
|
|
24
|
+
this.functions = new Functions({
|
|
25
|
+
logWarn: this.logWarn,
|
|
26
|
+
logError: this.logError,
|
|
27
|
+
logDebug: this.logDebug,
|
|
28
|
+
})
|
|
26
29
|
|
|
27
30
|
if (pluginStart) {
|
|
28
31
|
//lock flags
|
|
@@ -342,7 +345,6 @@ class MelCloud extends EventEmitter {
|
|
|
342
345
|
});
|
|
343
346
|
|
|
344
347
|
const page = await browser.newPage();
|
|
345
|
-
|
|
346
348
|
page.on('error', err => { if (this.logError) this.emit('error', `Page crashed: ${err.message}`); });
|
|
347
349
|
page.on('pageerror', err => { if (this.logError) this.emit('error', `Browser error: ${err.message}`); });
|
|
348
350
|
page.on('close', () => { if (this.logDebug) this.emit('debug', 'Page was closed unexpectedly'); });
|