homebridge-melcloud-control 4.4.1-beta.11 → 4.4.1-beta.13
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 +1 -1
- package/src/functions.js +50 -93
- package/src/melcloudhome.js +10 -35
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "MELCloud Control",
|
|
3
3
|
"name": "homebridge-melcloud-control",
|
|
4
|
-
"version": "4.4.1-beta.
|
|
4
|
+
"version": "4.4.1-beta.13",
|
|
5
5
|
"description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
package/src/functions.js
CHANGED
|
@@ -60,13 +60,14 @@ class Functions extends EventEmitter {
|
|
|
60
60
|
const osName = osOut.trim();
|
|
61
61
|
|
|
62
62
|
const { stdout: archOut } = await execPromise('uname -m');
|
|
63
|
-
|
|
63
|
+
let arch = archOut.trim() || 'unknown';
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
// Normalizacja architektury
|
|
66
|
+
if (arch.startsWith('arm') || arch.startsWith('aarch')) arch = 'arm';
|
|
67
|
+
else if (arch.includes('64')) arch = 'x64';
|
|
68
|
+
else arch = 'x86';
|
|
69
69
|
|
|
70
|
+
const isARM = arch === 'arm';
|
|
70
71
|
const isMac = osName === 'Darwin';
|
|
71
72
|
const isLinux = osName === 'Linux';
|
|
72
73
|
const isQnap = fs.existsSync('/etc/config/uLinux.conf') || fs.existsSync('/etc/config/qpkg.conf');
|
|
@@ -77,167 +78,124 @@ class Functions extends EventEmitter {
|
|
|
77
78
|
await access('/.dockerenv');
|
|
78
79
|
isDocker = true;
|
|
79
80
|
} catch { }
|
|
80
|
-
|
|
81
81
|
try {
|
|
82
82
|
const { stdout } = await execPromise('cat /proc/1/cgroup || true');
|
|
83
|
-
if (stdout.includes('docker') || stdout.includes('containerd'))
|
|
84
|
-
isDocker = true;
|
|
85
|
-
}
|
|
83
|
+
if (stdout.includes('docker') || stdout.includes('containerd')) isDocker = true;
|
|
86
84
|
} catch { }
|
|
87
85
|
|
|
86
|
+
const result = { path: null, arch };
|
|
87
|
+
|
|
88
88
|
/* ===================== macOS ===================== */
|
|
89
89
|
if (isMac) {
|
|
90
90
|
const macCandidates = [
|
|
91
91
|
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
92
92
|
'/Applications/Chromium.app/Contents/MacOS/Chromium'
|
|
93
93
|
];
|
|
94
|
-
|
|
95
94
|
for (const path of macCandidates) {
|
|
96
95
|
try {
|
|
97
96
|
await access(path, fs.constants.X_OK);
|
|
98
|
-
|
|
97
|
+
result.path = path;
|
|
98
|
+
return result;
|
|
99
99
|
} catch { }
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
// macOS → Puppeteer fallback is OK
|
|
103
|
-
try {
|
|
104
|
-
return puppeteer.executablePath();
|
|
105
|
-
} catch {
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
101
|
}
|
|
109
102
|
|
|
110
103
|
/* ===================== QNAP ===================== */
|
|
111
104
|
if (isQnap) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
'/opt/bin/chromium-browser'
|
|
115
|
-
];
|
|
116
|
-
|
|
117
|
-
// Check existing Entware Chromium
|
|
118
|
-
for (const path of entwareChromiumCandidates) {
|
|
105
|
+
const qnapCandidates = ['/opt/bin/chromium', '/opt/bin/chromium-browser'];
|
|
106
|
+
for (const path of qnapCandidates) {
|
|
119
107
|
try {
|
|
120
108
|
await access(path, fs.constants.X_OK);
|
|
121
|
-
|
|
109
|
+
result.path = path;
|
|
110
|
+
return result;
|
|
122
111
|
} catch { }
|
|
123
112
|
}
|
|
124
113
|
|
|
125
|
-
// Try installing via Entware
|
|
126
114
|
try {
|
|
127
115
|
await access('/opt/bin/opkg', fs.constants.X_OK);
|
|
128
|
-
|
|
129
116
|
await execPromise('/opt/bin/opkg update');
|
|
130
|
-
await execPromise(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
// Ensure Entware libs are visible
|
|
135
|
-
process.env.LD_LIBRARY_PATH =
|
|
136
|
-
`/opt/lib:${process.env.LD_LIBRARY_PATH || ''}`;
|
|
137
|
-
|
|
138
|
-
} catch {
|
|
139
|
-
// opkg missing or install failed
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
117
|
+
await execPromise('opkg install chromium nspr nss libx11 libxcomposite libxdamage libxrandr atk libcups libdrm libgbm alsa-lib');
|
|
118
|
+
process.env.LD_LIBRARY_PATH = `/opt/lib:${process.env.LD_LIBRARY_PATH || ''}`;
|
|
119
|
+
} catch { }
|
|
142
120
|
|
|
143
|
-
|
|
144
|
-
for (const path of entwareChromiumCandidates) {
|
|
121
|
+
for (const path of qnapCandidates) {
|
|
145
122
|
try {
|
|
146
123
|
await access(path, fs.constants.X_OK);
|
|
147
|
-
|
|
124
|
+
result.path = path;
|
|
125
|
+
return result;
|
|
148
126
|
} catch { }
|
|
149
127
|
}
|
|
150
|
-
|
|
151
|
-
return null;
|
|
152
128
|
}
|
|
153
129
|
|
|
154
|
-
/* ===================== ARM
|
|
130
|
+
/* ===================== Linux ARM ===================== */
|
|
155
131
|
if (isLinux && isARM) {
|
|
156
|
-
const armCandidates = [
|
|
157
|
-
'/usr/bin/chromium-browser',
|
|
158
|
-
'/usr/bin/chromium',
|
|
159
|
-
'/snap/bin/chromium'
|
|
160
|
-
];
|
|
132
|
+
const armCandidates = ['/usr/bin/chromium-browser', '/usr/bin/chromium', '/snap/bin/chromium'];
|
|
161
133
|
|
|
134
|
+
// 1. Sprawdź istniejące
|
|
162
135
|
for (const path of armCandidates) {
|
|
163
136
|
try {
|
|
164
137
|
await access(path, fs.constants.X_OK);
|
|
165
|
-
|
|
138
|
+
result.path = path;
|
|
139
|
+
return result;
|
|
166
140
|
} catch { }
|
|
167
141
|
}
|
|
168
142
|
|
|
169
|
-
//
|
|
143
|
+
// 2. Zainstaluj jeśli nie Docker
|
|
170
144
|
if (!isDocker) {
|
|
171
145
|
try {
|
|
172
146
|
await execPromise('sudo apt-get update -y');
|
|
173
|
-
await execPromise(
|
|
174
|
-
|
|
175
|
-
);
|
|
147
|
+
await execPromise('sudo apt-get install -y chromium chromium-browser chromium-codecs-ffmpeg || true');
|
|
148
|
+
await execPromise('sudo apt-get install -y libnspr4 libnss3 libx11-6 libxcomposite1 libxdamage1 libxrandr2 libatk1.0-0 libcups2 libdrm2 libgbm1 libasound2 || true');
|
|
176
149
|
} catch { }
|
|
177
150
|
}
|
|
178
151
|
|
|
179
|
-
// Retry
|
|
152
|
+
// 3. Retry po instalacji
|
|
180
153
|
for (const path of armCandidates) {
|
|
181
154
|
try {
|
|
182
155
|
await access(path, fs.constants.X_OK);
|
|
183
|
-
|
|
156
|
+
result.path = path;
|
|
157
|
+
return result;
|
|
184
158
|
} catch { }
|
|
185
159
|
}
|
|
186
160
|
|
|
187
|
-
//
|
|
188
|
-
return
|
|
161
|
+
// 4. Jeśli dalej brak → path = null
|
|
162
|
+
return result;
|
|
189
163
|
}
|
|
190
164
|
|
|
165
|
+
|
|
191
166
|
/* ===================== Linux x64 ===================== */
|
|
192
167
|
if (isLinux) {
|
|
193
|
-
const linuxCandidates = [
|
|
194
|
-
'/usr/bin/chromium',
|
|
195
|
-
'/usr/bin/chromium-browser',
|
|
196
|
-
'/usr/bin/google-chrome',
|
|
197
|
-
'/snap/bin/chromium',
|
|
198
|
-
'/usr/local/bin/chromium'
|
|
199
|
-
];
|
|
200
|
-
|
|
168
|
+
const linuxCandidates = ['/usr/bin/chromium', '/usr/bin/chromium-browser', '/usr/bin/google-chrome', '/snap/bin/chromium', '/usr/local/bin/chromium'];
|
|
201
169
|
try {
|
|
202
|
-
const { stdout } = await execPromise(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
170
|
+
const { stdout } = await execPromise('which chromium || which chromium-browser || which google-chrome || true');
|
|
171
|
+
if (stdout.trim()) {
|
|
172
|
+
result.path = stdout.trim();
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
206
175
|
} catch { }
|
|
207
176
|
|
|
208
177
|
for (const path of linuxCandidates) {
|
|
209
178
|
try {
|
|
210
179
|
await access(path, fs.constants.X_OK);
|
|
211
|
-
|
|
180
|
+
result.path = path;
|
|
181
|
+
return result;
|
|
212
182
|
} catch { }
|
|
213
183
|
}
|
|
214
184
|
|
|
215
|
-
// Docker x64 → try install
|
|
216
185
|
if (isDocker) {
|
|
217
186
|
try {
|
|
218
|
-
await execPromise(
|
|
219
|
-
'apt-get update -y && apt-get install -y chromium || true'
|
|
220
|
-
);
|
|
187
|
+
await execPromise('apt-get update -y && apt-get install -y chromium || true');
|
|
221
188
|
await access('/usr/bin/chromium', fs.constants.X_OK);
|
|
222
|
-
|
|
189
|
+
result.path = '/usr/bin/chromium';
|
|
190
|
+
return result;
|
|
223
191
|
} catch { }
|
|
224
192
|
}
|
|
225
|
-
|
|
226
|
-
// Linux x64 → Puppeteer fallback OK
|
|
227
|
-
try {
|
|
228
|
-
return puppeteer.executablePath();
|
|
229
|
-
} catch {
|
|
230
|
-
return null;
|
|
231
|
-
}
|
|
232
193
|
}
|
|
233
194
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
this.emit('error', `Chromium detection error: ${error.message}`);
|
|
239
|
-
}
|
|
240
|
-
return null;
|
|
195
|
+
return result;
|
|
196
|
+
} catch (err) {
|
|
197
|
+
if (this.logError) this.emit('error', `Chromium detection error: ${err.message}`);
|
|
198
|
+
return { path: null, arch: 'unknown' };
|
|
241
199
|
}
|
|
242
200
|
}
|
|
243
201
|
|
|
@@ -306,7 +264,6 @@ class Functions extends EventEmitter {
|
|
|
306
264
|
|
|
307
265
|
return { min, max };
|
|
308
266
|
}
|
|
309
|
-
|
|
310
267
|
}
|
|
311
268
|
|
|
312
269
|
export default Functions
|
package/src/melcloudhome.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
1
|
import axios from 'axios';
|
|
3
2
|
import WebSocket from 'ws';
|
|
4
3
|
import { exec } from 'child_process';
|
|
@@ -225,44 +224,20 @@ class MelCloudHome extends EventEmitter {
|
|
|
225
224
|
const accountInfo = { State: false, Info: '', Account: {}, UseFahrenheit: false };
|
|
226
225
|
|
|
227
226
|
// Get Chromium path from resolver
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
// Detect architecture again (cheap & explicit)
|
|
231
|
-
const { stdout: archOut } = await execPromise('uname -m');
|
|
232
|
-
const arch = archOut.trim();
|
|
233
|
-
const isARM =
|
|
234
|
-
arch.startsWith('arm') ||
|
|
235
|
-
arch.startsWith('aarch64') ||
|
|
236
|
-
arch.startsWith('aarch');
|
|
237
|
-
|
|
238
|
-
// Detect QNAP
|
|
239
|
-
const isQnap =
|
|
240
|
-
fs.existsSync('/etc/config/uLinux.conf') ||
|
|
241
|
-
fs.existsSync('/etc/config/qpkg.conf');
|
|
242
|
-
|
|
243
|
-
// Conditional Puppeteer fallback
|
|
244
|
-
if (!chromiumPath) {
|
|
245
|
-
if (!isARM && !isQnap) {
|
|
246
|
-
try {
|
|
247
|
-
const puppeteerPath = puppeteer.executablePath();
|
|
248
|
-
if (!puppeteerPath) {
|
|
249
|
-
accountInfo.Info = 'Puppeteer returned empty Chromium path';
|
|
250
|
-
return accountInfo;
|
|
251
|
-
}
|
|
227
|
+
const chromiumInfo = await this.functions.ensureChromiumInstalled();
|
|
228
|
+
let chromiumPath = chromiumInfo.path;
|
|
252
229
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
accountInfo.Info = 'Chromium not available for this platform. Install system Chromium.';
|
|
230
|
+
// Try Puppeteer Chromium if path null
|
|
231
|
+
if (!chromiumPath) {
|
|
232
|
+
try {
|
|
233
|
+
chromiumPath = puppeteer.executablePath();
|
|
234
|
+
if (this.logDebug) this.emit('debug', `Using Puppeteer Chromium (${chromiumInfo.arch}) at ${chromiumPath}`);
|
|
235
|
+
} catch (error) {
|
|
236
|
+
accountInfo.Info = `No Chromium available for architecture ${chromiumInfo.arch}`;
|
|
261
237
|
return accountInfo;
|
|
262
238
|
}
|
|
263
239
|
}
|
|
264
240
|
|
|
265
|
-
|
|
266
241
|
// Verify Chromium executable
|
|
267
242
|
try {
|
|
268
243
|
const { stdout } = await execPromise(`"${chromiumPath}" --version`);
|
|
@@ -305,7 +280,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
305
280
|
const hash = params.get('hash');
|
|
306
281
|
if (this.logDebug) this.emit('debug', `Web socket hash detected: ${hash}`);
|
|
307
282
|
|
|
308
|
-
//
|
|
283
|
+
// Web socket connection
|
|
309
284
|
if (!this.connecting && !this.socketConnected) {
|
|
310
285
|
this.connecting = true;
|
|
311
286
|
|