homebridge-melcloud-control 4.3.11-beta.8 → 4.3.11-beta.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "4.3.11-beta.8",
4
+ "version": "4.3.11-beta.9",
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/deviceata.js CHANGED
@@ -142,7 +142,7 @@ class DeviceAta extends EventEmitter {
142
142
  });
143
143
  }
144
144
  } catch (error) {
145
- this.emit('warn', `RESTFul integration start error: ${error}`);
145
+ if (this.logWarn) this.emit('warn', `RESTFul integration start error: ${error}`);
146
146
  };
147
147
  }
148
148
 
@@ -186,7 +186,7 @@ class DeviceAta extends EventEmitter {
186
186
  });
187
187
  }
188
188
  } catch (error) {
189
- this.emit('warn', `MQTT integration start error: ${error}`);
189
+ if (this.logWarn) this.emit('warn', `MQTT integration start error: ${error}`);
190
190
  };
191
191
  }
192
192
 
@@ -1861,7 +1861,7 @@ class DeviceAta extends EventEmitter {
1861
1861
  if (supportsFanSpeed) this.emit('info', `Current fan speed: ${AirConditioner.AktualFanSpeedMapEnumToString[actualFanSpeed]}`);
1862
1862
  if (vaneHorizontalDirection !== null) this.emit('info', `Vane horizontal: ${AirConditioner.VaneHorizontalDirectionMapEnumToString[vaneHorizontalDirection]}`);
1863
1863
  if (vaneVerticalDirection !== null) this.emit('info', `Vane vertical: ${AirConditioner.VaneVerticalDirectionMapEnumToString[vaneVerticalDirection]}`);
1864
- if (supportsSwingFunction) this.emit('info', `Air direction: ${AirConditioner.AirDirectionMapEnumToString[obj.currentSwingMode]}`);
1864
+ if (supportsSwingFunction) this.emit('info', `Air direction: ${AirConditioner.AirDirectionMapEnumToString[currentSwingMode]}`);
1865
1865
  this.emit('info', `Temperature display unit: ${obj.temperatureUnit}`);
1866
1866
  this.emit('info', `Lock physical controls: ${obj.lockPhysicalControl ? 'Locked' : 'Unlocked'}`);
1867
1867
  if (this.accountType === 'melcloudhome') this.emit('info', `Signal strength: ${deviceData.Rssi}dBm`);
package/src/deviceatw.js CHANGED
@@ -146,7 +146,7 @@ class DeviceAtw extends EventEmitter {
146
146
  });
147
147
  }
148
148
  } catch (error) {
149
- this.emit('warn', `RESTFul integration start error: ${error}`);
149
+ if (this.logWarn) this.emit('warn', `RESTFul integration start error: ${error}`);
150
150
  };
151
151
  }
152
152
 
@@ -190,7 +190,7 @@ class DeviceAtw extends EventEmitter {
190
190
  });
191
191
  }
192
192
  } catch (error) {
193
- this.emit('warn', `MQTT integration start error: ${error}`);
193
+ if (this.logWarn) this.emit('warn', `MQTT integration start error: ${error}`);
194
194
  };
195
195
  }
196
196
  }
package/src/deviceerv.js CHANGED
@@ -138,7 +138,7 @@ class DeviceErv extends EventEmitter {
138
138
  });
139
139
  }
140
140
  } catch (error) {
141
- this.emit('warn', `RESTFul integration start error: ${error}`);
141
+ if (this.logWarn) this.emit('warn', `RESTFul integration start error: ${error}`);
142
142
  };
143
143
  }
144
144
 
@@ -182,7 +182,7 @@ class DeviceErv extends EventEmitter {
182
182
  });
183
183
  }
184
184
  } catch (error) {
185
- this.emit('warn', `MQTT integration start error: ${error}`);
185
+ if (this.logWarn) this.emit('warn', `MQTT integration start error: ${error}`);
186
186
  };
187
187
  }
188
188
  }
package/src/functions.js CHANGED
@@ -71,7 +71,8 @@ class Functions extends EventEmitter {
71
71
  // --- Detect Docker ---
72
72
  let isDocker = false;
73
73
  try {
74
- await access('/.dockerenv', fs.constants.F_OK); isDocker = true;
74
+ await access('/.dockerenv', fs.constants.F_OK);
75
+ isDocker = true;
75
76
  } catch { }
76
77
 
77
78
  try {
@@ -156,6 +157,82 @@ class Functions extends EventEmitter {
156
157
  }
157
158
  }
158
159
 
160
+ async ensureChromiumInstalled() {
161
+ let chromiumPath = '/usr/bin/chromium-browser';
162
+
163
+ try {
164
+ const { stdout: osOut } = await execPromise('uname -s');
165
+ const osName = osOut.trim();
166
+ if (this.logDebug) this.emit('debug', `Detected OS: ${osName}`);
167
+
168
+ const { stdout: archOut } = await execPromise('uname -m');
169
+ const arch = archOut.trim();
170
+ if (this.logDebug) this.emit('debug', `Detected architecture: ${arch}`);
171
+
172
+ // Docker detection
173
+ let isDocker = false;
174
+ try { await access('/.dockerenv', fs.constants.F_OK); isDocker = true; } catch { }
175
+ try {
176
+ const { stdout } = await execPromise('cat /proc/1/cgroup || true');
177
+ if (stdout.includes('docker') || stdout.includes('containerd')) isDocker = true;
178
+ } catch { }
179
+ if (isDocker && this.logDebug) this.emit('debug', 'Running inside Docker container.');
180
+
181
+ // macOS
182
+ if (osName === 'Darwin') {
183
+ chromiumPath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
184
+ try { await access(chromiumPath, fs.constants.X_OK); return chromiumPath; } catch { return null; }
185
+ }
186
+
187
+ // ARM
188
+ if (arch.startsWith('arm') || arch.startsWith('aarch')) {
189
+ try { await access(chromiumPath, fs.constants.X_OK); return chromiumPath; }
190
+ catch {
191
+ try { await execPromise('sudo apt-get update -y && sudo apt-get install -y chromium-browser chromium-codecs-ffmpeg'); return chromiumPath; }
192
+ catch { return null; }
193
+ }
194
+ }
195
+
196
+ // Linux x64
197
+ if (osName === 'Linux') {
198
+ let systemChromium = null;
199
+ try {
200
+ const { stdout: checkOut } = await execPromise('which chromium || which chromium-browser || true');
201
+ systemChromium = checkOut.trim() || null;
202
+ } catch { }
203
+
204
+ // Entware (QNAP)
205
+ let entwareExists = false;
206
+ try { await access('/opt/bin/opkg', fs.constants.X_OK); entwareExists = true; } catch { }
207
+ if (entwareExists) {
208
+ try {
209
+ await execPromise('/opt/bin/opkg update');
210
+ await execPromise('/opt/bin/opkg install nspr nss libx11 libxcomposite libxdamage libxrandr libatk libatk-bridge libcups libdrm libgbm libasound');
211
+ process.env.LD_LIBRARY_PATH = `/opt/lib:${process.env.LD_LIBRARY_PATH || ''}`;
212
+ } catch { }
213
+ }
214
+
215
+ // Install missing libs
216
+ const depCommands = [
217
+ 'apt-get update -y && apt-get install -y libnspr4 libnss3 libx11-6 libxcomposite1 libxdamage1 libxrandr2 libatk1.0-0 libcups2 libdrm2 libgbm1 libasound2',
218
+ 'apk add --no-cache nspr nss libx11 libxcomposite libxdamage libxrandr atk cups libdrm libgbm alsa-lib',
219
+ 'yum install -y nspr nss libX11 libXcomposite libXdamage libXrandr atk cups libdrm libgbm alsa-lib'
220
+ ];
221
+ for (const cmd of depCommands) { try { await execPromise(`sudo ${cmd}`); } catch { } }
222
+
223
+ process.env.LD_LIBRARY_PATH = `/usr/lib:/usr/lib64:${process.env.LD_LIBRARY_PATH || ''}`;
224
+ return systemChromium;
225
+ }
226
+
227
+ if (this.logDebug) this.emit('debug', `Unsupported OS: ${osName}`);
228
+ return null;
229
+
230
+ } catch (error) {
231
+ if (this.logError) this.emit('error', `Chromium detection/install error: ${error.message}`);
232
+ return null;
233
+ }
234
+ }
235
+
159
236
  isValidValue(v) {
160
237
  return v !== undefined && v !== null && !(typeof v === 'number' && Number.isNaN(v));
161
238
  }
@@ -274,19 +274,23 @@ class MelCloudHome extends EventEmitter {
274
274
  let browser;
275
275
  try {
276
276
  const accountInfo = { State: false, Info: '', Account: {}, UseFahrenheit: false };
277
+
278
+ // Get Chromium path
277
279
  let chromiumPath = await this.functions.ensureChromiumInstalled();
278
280
 
279
281
  // === Fallback to Puppeteer's built-in Chromium ===
280
282
  if (!chromiumPath) {
281
- try {
282
- const puppeteerPath = puppeteer.executablePath();
283
- if (puppeteerPath && fs.existsSync(puppeteerPath)) {
284
- chromiumPath = puppeteerPath;
285
- if (this.logDebug) this.emit('debug', `Using puppeteer Chromium at ${chromiumPath}`);
286
- }
287
- } catch { }
288
- } else {
289
- if (this.logDebug) this.emit('debug', `Using system Chromium at ${chromiumPath}`);
283
+ if (!arch.startsWith('arm')) {
284
+ try {
285
+ const puppeteerPath = puppeteer.executablePath();
286
+ if (puppeteerPath && fs.existsSync(puppeteerPath)) {
287
+ chromiumPath = puppeteerPath;
288
+ if (this.logDebug) this.emit('debug', `Using Puppeteer Chromium at ${chromiumPath}`);
289
+ }
290
+ } catch { }
291
+ } else {
292
+ if (this.logDebug) this.emit('debug', 'Skipping Puppeteer Chromium on ARM (incompatible)');
293
+ }
290
294
  }
291
295
 
292
296
  if (!chromiumPath) {
@@ -303,6 +307,7 @@ class MelCloudHome extends EventEmitter {
303
307
  return accountInfo;
304
308
  }
305
309
 
310
+ // Launch Chromium
306
311
  if (this.logDebug) this.emit('debug', `Launching Chromium...`);
307
312
  browser = await puppeteer.launch({
308
313
  headless: true,