homebridge-melcloud-control 4.1.2-beta.61 → 4.1.2-beta.63
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 +2 -1
- package/README.md +16 -3
- package/package.json +1 -1
- package/src/functions.js +31 -12
- package/src/melcloud.js +3 -1
- package/src/melcloudata.js +9 -5
- package/src/melcloudatw.js +7 -6
- package/src/melclouderv.js +8 -7
package/CHANGELOG.md
CHANGED
|
@@ -22,10 +22,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
22
22
|
|
|
23
23
|
- Do not use Homebridge UI > v5.5.0 because of break config.json
|
|
24
24
|
|
|
25
|
-
## [4.1.2] - (
|
|
25
|
+
## [4.1.2] - (11.11.2025)
|
|
26
26
|
|
|
27
27
|
## Changes
|
|
28
28
|
|
|
29
|
+
- fix [#218](https://github.com/grzegorz914/homebridge-melcloud-control/issues/218)
|
|
29
30
|
- added presets/schedules support for MELCLoud Home ATA devices
|
|
30
31
|
- config schema updated
|
|
31
32
|
- readme updated
|
package/README.md
CHANGED
|
@@ -65,6 +65,7 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
|
|
|
65
65
|
* Vane V mode `AUTO/1/2/3/4/5/SWING`.
|
|
66
66
|
* Fan speed mode `AUTO/1/2/3/4/5`.
|
|
67
67
|
* Presets `SET/UNSET`.
|
|
68
|
+
* Schedules `ON/OFF`.
|
|
68
69
|
* Sensors:
|
|
69
70
|
* For automation and notifications.
|
|
70
71
|
* Power `ON/OFF`.
|
|
@@ -232,10 +233,14 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
|
|
|
232
233
|
| `ataDevices[].scheduleSensor` | This enable extra `Shedule` sensor to use with automations in HomeKit app. |
|
|
233
234
|
| `ataDevices[].errorSensor` | This enable `Error` sensor to use with automations in HomeKit app. |
|
|
234
235
|
| `ataDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
|
|
235
|
-
| `ataDevices[].presets[]` | Array of ATA device Presets created automatically after login to MELCloud from plugin config UI. |
|
|
236
|
+
| `ataDevices[].presets[]` | Array of ATA device `Presets` created automatically after login to MELCloud from plugin config UI. |
|
|
236
237
|
| `ataDevices[].presets[].id` | Read only data, do not change it. |
|
|
237
238
|
| `ataDevices[].presets[].name` | Here You can schange the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
|
|
238
239
|
| `ataDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
|
|
240
|
+
| `ataDevices[].schedules[]` | Array of ATA device `Schedules` created automatically after login to MELCloud Home from plugin config UI. |
|
|
241
|
+
| `ataDevices[].schedules[].id` | Read only data, do not change it. |
|
|
242
|
+
| `ataDevices[].schedules[].name` | Here You can schange the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
|
|
243
|
+
| `ataDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
|
|
239
244
|
| `ataDevices[].buttonsSensors[]` | Array of buttons sensors. |
|
|
240
245
|
| `ataDevices[].buttonsSensors[].name` | Here set `Button Name` which You want expose to the `Homebridge/HomeKit`. |
|
|
241
246
|
| `ataDevices[].buttonsSensors[].mode` | Here select button mode, VH - Vane Horizontal, VV - Vane Horizontal. |
|
|
@@ -259,10 +264,14 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
|
|
|
259
264
|
| `atwDevices[].temperatureReturnZone2Sensor` | This enable extra `Return Zone 2` temperature sensor to use with automations in HomeKit app. |
|
|
260
265
|
| `atwDevices[].errorSensor` | This enable `Error` sensors to use with automations in HomeKit app. |
|
|
261
266
|
| `atwDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
|
|
262
|
-
| `atwDevices[].presets[]` | Array of
|
|
267
|
+
| `atwDevices[].presets[]` | Array of ATW device `Presets` created automatically after login to MELCloud from plugin config UI. |
|
|
263
268
|
| `atwDevices[].presets[].id` | Read only data, do not change it. |
|
|
264
269
|
| `atwDevices[].presets[].name` | Here You can schange the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
|
|
265
270
|
| `atwDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
|
|
271
|
+
| `atwDevices[].schedules[]` | Array of ATW device `Schedules` created automatically after login to MELCloud Home from plugin config UI. |
|
|
272
|
+
| `atwDevices[].schedules[].id` | Read only data, do not change it. |
|
|
273
|
+
| `atwDevices[].schedules[].name` | Here You can schange the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
|
|
274
|
+
| `atwDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
|
|
266
275
|
| `atwDevices[].buttonsSensors[]` | Array of buttons sensors. |
|
|
267
276
|
| `atwDevices[].buttonsSensors[].name` | Here set `Button Name` which You want expose to the `Homebridge/HomeKit`. |
|
|
268
277
|
| `atwDevices[].buttonsSensors[].mode` | Here select button mode. |
|
|
@@ -279,10 +288,14 @@ Homebridge plugin for Air Conditioner, Heat Pump and Energy Recovery Ventilation
|
|
|
279
288
|
| `ervDevices[].temperatureSupplySensor` | This enable extra `Supply` temperature sensor to use with automations in HomeKit app. |
|
|
280
289
|
| `ervDevices[].errorSensor` | This enable `Error` sensors to use with automations in HomeKit app. |
|
|
281
290
|
| `ervDevices[].refreshInterval` | Here set the background devices state refresh time in (sec), default `5s`. |
|
|
282
|
-
| `ervDevices[].presets[]` | Array of
|
|
291
|
+
| `ervDevices[].presets[]` | Array of ERV device `Presets` created automatically after login to MELCloud from plugin config UI. |
|
|
283
292
|
| `ervDevices[].presets[].id` | Read only data, do not change it. |
|
|
284
293
|
| `ervDevices[].presets[].name` | Here You can schange the `Preset Name` which is exposed to the `Homebridge/HomeKit`. |
|
|
285
294
|
| `ervDevices[].presets[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
|
|
295
|
+
| `ervDevices[].schedules[]` | Array of ERV device `Schedules` created automatically after login to MELCloud Home from plugin config UI. |
|
|
296
|
+
| `ervDevices[].schedules[].id` | Read only data, do not change it. |
|
|
297
|
+
| `ervDevices[].schedules[].name` | Here You can schange the `Schedule Name` which is exposed to the `Homebridge/HomeKit`. |
|
|
298
|
+
| `ervDevices[].schedules[].displayType` | Here select display type in HomeKit, `0 - None/Disabled`, `1 - Outlet`, `2 - Switch`, `3 - Motion Sensor`, `4 - Occupancy Sensor`, `5 - Contact Sensor`. |
|
|
286
299
|
| `ervDevices[].buttonsSensors[]` | Array of buttons sensors. |
|
|
287
300
|
| `ervDevices[].buttonsSensors[].name` | Here set `Button Name` which You want expose to the `Homebridge/HomeKit`. |
|
|
288
301
|
| `ervDevices[].buttonsSensors[].mode` | Here select button mode. |
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "MELCloud Control",
|
|
3
3
|
"name": "homebridge-melcloud-control",
|
|
4
|
-
"version": "4.1.2-beta.
|
|
4
|
+
"version": "4.1.2-beta.63",
|
|
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
|
@@ -70,25 +70,41 @@ class Functions extends EventEmitter {
|
|
|
70
70
|
|
|
71
71
|
// --- Detect Docker ---
|
|
72
72
|
let isDocker = false;
|
|
73
|
-
try {
|
|
73
|
+
try {
|
|
74
|
+
await access('/.dockerenv', fs.constants.F_OK); isDocker = true;
|
|
75
|
+
} catch { }
|
|
76
|
+
|
|
74
77
|
try {
|
|
75
78
|
const { stdout } = await execPromise('cat /proc/1/cgroup || true');
|
|
76
79
|
if (stdout.includes('docker') || stdout.includes('containerd')) isDocker = true;
|
|
77
80
|
} catch { }
|
|
81
|
+
|
|
78
82
|
if (isDocker && this.logDebug) this.emit('debug', 'Running inside Docker container.');
|
|
79
83
|
|
|
80
84
|
// === macOS ===
|
|
81
85
|
if (osName === 'Darwin') {
|
|
82
86
|
chromiumPath = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
|
83
|
-
try {
|
|
87
|
+
try {
|
|
88
|
+
await access(chromiumPath, fs.constants.X_OK);
|
|
89
|
+
return chromiumPath;
|
|
90
|
+
} catch {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
// === ARM ===
|
|
87
96
|
if (arch.startsWith('arm')) {
|
|
88
|
-
try {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
try {
|
|
98
|
+
chromiumPath = '/usr/bin/chromium-browser';
|
|
99
|
+
await access(chromiumPath, fs.constants.X_OK);
|
|
100
|
+
return chromiumPath;
|
|
101
|
+
} catch {
|
|
102
|
+
try {
|
|
103
|
+
await execPromise('sudo apt-get update -y && sudo apt-get install -y chromium-browser chromium-codecs-ffmpeg');
|
|
104
|
+
return chromiumPath;
|
|
105
|
+
} catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
92
108
|
}
|
|
93
109
|
}
|
|
94
110
|
|
|
@@ -102,13 +118,16 @@ class Functions extends EventEmitter {
|
|
|
102
118
|
|
|
103
119
|
// --- Detect Entware (QNAP) ---
|
|
104
120
|
let entwareExists = false;
|
|
105
|
-
try {
|
|
121
|
+
try {
|
|
122
|
+
await access('/opt/bin/opkg', fs.constants.X_OK);
|
|
123
|
+
entwareExists = true;
|
|
124
|
+
} catch { }
|
|
106
125
|
|
|
107
126
|
if (entwareExists) {
|
|
108
127
|
try {
|
|
109
128
|
await execPromise('/opt/bin/opkg update');
|
|
110
129
|
await execPromise('/opt/bin/opkg install nspr nss libx11 libxcomposite libxdamage libxrandr libatk libatk-bridge libcups libdrm libgbm libasound');
|
|
111
|
-
process.env.LD_LIBRARY_PATH =
|
|
130
|
+
process.env.LD_LIBRARY_PATH = `/opt/lib:${process.env.LD_LIBRARY_PATH || ''}`;
|
|
112
131
|
} catch { }
|
|
113
132
|
}
|
|
114
133
|
|
|
@@ -119,16 +138,16 @@ class Functions extends EventEmitter {
|
|
|
119
138
|
'yum install -y nspr nss libX11 libXcomposite libXdamage libXrandr atk cups libdrm libgbm alsa-lib'
|
|
120
139
|
];
|
|
121
140
|
for (const cmd of depInstall) {
|
|
122
|
-
try {
|
|
141
|
+
try {
|
|
142
|
+
await execPromise(`sudo ${cmd}`);
|
|
143
|
+
} catch { }
|
|
123
144
|
}
|
|
124
145
|
|
|
125
146
|
// Set LD_LIBRARY_PATH so Puppeteer's Chromium can find libs
|
|
126
|
-
process.env.LD_LIBRARY_PATH =
|
|
127
|
-
|
|
147
|
+
process.env.LD_LIBRARY_PATH = `/usr/lib:/usr/lib64:${process.env.LD_LIBRARY_PATH || ''}`;
|
|
128
148
|
return systemChromium;
|
|
129
149
|
}
|
|
130
150
|
|
|
131
|
-
|
|
132
151
|
if (this.logDebug) this.emit('debug', `Unsupported OS: ${osName}.`);
|
|
133
152
|
return null;
|
|
134
153
|
} catch (error) {
|
package/src/melcloud.js
CHANGED
|
@@ -345,9 +345,11 @@ class MelCloud extends EventEmitter {
|
|
|
345
345
|
const puppeteerPath = puppeteer.executablePath();
|
|
346
346
|
if (puppeteerPath && fs.existsSync(puppeteerPath)) {
|
|
347
347
|
chromiumPath = puppeteerPath;
|
|
348
|
-
if (this.logDebug) this.emit('debug', `Using
|
|
348
|
+
if (this.logDebug) this.emit('debug', `Using puppeteer Chromium at ${chromiumPath}`);
|
|
349
349
|
}
|
|
350
350
|
} catch { }
|
|
351
|
+
} else {
|
|
352
|
+
if (this.logDebug) this.emit('debug', `Using system Chromium at ${chromiumPath}`);
|
|
351
353
|
}
|
|
352
354
|
|
|
353
355
|
if (!chromiumPath) {
|
package/src/melcloudata.js
CHANGED
|
@@ -23,7 +23,6 @@ class MelCloudAta extends EventEmitter {
|
|
|
23
23
|
|
|
24
24
|
//set default values
|
|
25
25
|
this.deviceData = {};
|
|
26
|
-
this.headers = {};
|
|
27
26
|
|
|
28
27
|
//lock flags
|
|
29
28
|
this.locks = {
|
|
@@ -60,7 +59,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
60
59
|
return null;
|
|
61
60
|
}
|
|
62
61
|
const deviceData = devicesData.find(device => device.DeviceID === this.deviceId);
|
|
63
|
-
|
|
62
|
+
|
|
64
63
|
if (this.accountType === 'melcloudhome') {
|
|
65
64
|
deviceData.SerialNumber = deviceData.DeviceID || '4.0.0';
|
|
66
65
|
deviceData.Device.FirmwareAppVersion = deviceData.ConnectedInterfaceIdentifier || '4.0.0';
|
|
@@ -75,7 +74,12 @@ class MelCloudAta extends EventEmitter {
|
|
|
75
74
|
deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
|
|
76
75
|
deviceData.Device.DefaultCoolingSetTemperature = temps?.defaultCoolingSetTemperature ?? 24;
|
|
77
76
|
}
|
|
78
|
-
|
|
77
|
+
|
|
78
|
+
const safeConfig = {
|
|
79
|
+
...deviceData,
|
|
80
|
+
headers: 'removed',
|
|
81
|
+
};
|
|
82
|
+
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
79
83
|
|
|
80
84
|
//device
|
|
81
85
|
const serialNumber = deviceData.SerialNumber;
|
|
@@ -144,7 +148,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
144
148
|
method: 'POST',
|
|
145
149
|
baseURL: ApiUrls.BaseURL,
|
|
146
150
|
timeout: 10000,
|
|
147
|
-
headers:
|
|
151
|
+
headers: deviceData.headers,
|
|
148
152
|
withCredentials: true
|
|
149
153
|
});
|
|
150
154
|
|
|
@@ -183,7 +187,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
183
187
|
method: 'PUT',
|
|
184
188
|
baseURL: ApiUrlsHome.BaseURL,
|
|
185
189
|
timeout: 10000,
|
|
186
|
-
headers:
|
|
190
|
+
headers: deviceData.headers,
|
|
187
191
|
withCredentials: true
|
|
188
192
|
});
|
|
189
193
|
|
package/src/melcloudatw.js
CHANGED
|
@@ -23,7 +23,6 @@ class MelCloudAtw extends EventEmitter {
|
|
|
23
23
|
|
|
24
24
|
//set default values
|
|
25
25
|
this.devicesData = {};
|
|
26
|
-
this.headers = {};
|
|
27
26
|
|
|
28
27
|
//lock flags
|
|
29
28
|
this.locks = {
|
|
@@ -55,19 +54,21 @@ class MelCloudAtw extends EventEmitter {
|
|
|
55
54
|
try {
|
|
56
55
|
//read device info from file
|
|
57
56
|
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
58
|
-
|
|
59
57
|
if (!Array.isArray(devicesData)) {
|
|
60
58
|
if (this.logWarn) this.emit('warn', `Device data not found`);
|
|
61
59
|
return null;
|
|
62
60
|
}
|
|
63
61
|
const deviceData = devicesData.find(device => device.DeviceID === this.deviceId);
|
|
64
|
-
this.headers = deviceData.Headers;
|
|
65
62
|
|
|
66
63
|
if (this.accountType === 'melcloudhome') {
|
|
67
64
|
deviceData.SerialNumber = deviceData.DeviceID || '4.0.0';
|
|
68
65
|
deviceData.Device.FirmwareAppVersion = deviceData.ConnectedInterfaceIdentifier || '4.0.0';
|
|
69
66
|
}
|
|
70
|
-
|
|
67
|
+
const safeConfig = {
|
|
68
|
+
...deviceData,
|
|
69
|
+
headers: 'removed',
|
|
70
|
+
};
|
|
71
|
+
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
71
72
|
|
|
72
73
|
//device
|
|
73
74
|
const serialNumber = deviceData.SerialNumber;
|
|
@@ -152,7 +153,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
152
153
|
method: 'POST',
|
|
153
154
|
baseURL: ApiUrls.BaseURL,
|
|
154
155
|
timeout: 10000,
|
|
155
|
-
headers:
|
|
156
|
+
headers: deviceData.headers,
|
|
156
157
|
withCredentials: true
|
|
157
158
|
});
|
|
158
159
|
|
|
@@ -190,7 +191,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
190
191
|
method: 'PUT',
|
|
191
192
|
baseURL: ApiUrlsHome.BaseURL,
|
|
192
193
|
timeout: 10000,
|
|
193
|
-
headers:
|
|
194
|
+
headers: deviceData.headers,
|
|
194
195
|
withCredentials: true
|
|
195
196
|
});
|
|
196
197
|
|
package/src/melclouderv.js
CHANGED
|
@@ -23,7 +23,6 @@ class MelCloudErv extends EventEmitter {
|
|
|
23
23
|
|
|
24
24
|
//set default values
|
|
25
25
|
this.devicesData = {};
|
|
26
|
-
this.headers = {};
|
|
27
26
|
|
|
28
27
|
//lock flags
|
|
29
28
|
this.locks = {
|
|
@@ -55,14 +54,12 @@ class MelCloudErv extends EventEmitter {
|
|
|
55
54
|
try {
|
|
56
55
|
//read device info from file
|
|
57
56
|
const devicesData = await this.functions.readData(this.devicesFile, true);
|
|
58
|
-
|
|
59
57
|
if (!Array.isArray(devicesData)) {
|
|
60
58
|
if (this.logWarn) this.emit('warn', `Device data not found`);
|
|
61
59
|
return null;
|
|
62
60
|
}
|
|
63
61
|
const deviceData = devicesData.find(device => device.DeviceID === this.deviceId);
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
|
|
66
63
|
if (this.accountType === 'melcloudhome') {
|
|
67
64
|
deviceData.SerialNumber = deviceData.DeviceID || '4.0.0';
|
|
68
65
|
deviceData.Device.FirmwareAppVersion = deviceData.ConnectedInterfaceIdentifier || '4.0.0';
|
|
@@ -72,7 +69,11 @@ class MelCloudErv extends EventEmitter {
|
|
|
72
69
|
deviceData.Device.DefaultHeatingSetTemperature = temps?.defaultHeatingSetTemperature ?? 20;
|
|
73
70
|
deviceData.Device.DefaultCoolingSetTemperature = temps?.defaultCoolingSetTemperature ?? 24;
|
|
74
71
|
}
|
|
75
|
-
|
|
72
|
+
const safeConfig = {
|
|
73
|
+
...deviceData,
|
|
74
|
+
headers: 'removed',
|
|
75
|
+
};
|
|
76
|
+
if (this.logDebug) this.emit('debug', `Device Data: ${JSON.stringify(safeConfig, null, 2)}`);
|
|
76
77
|
|
|
77
78
|
//presets
|
|
78
79
|
const serialNumber = deviceData.SerialNumber;
|
|
@@ -141,7 +142,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
141
142
|
method: 'POST',
|
|
142
143
|
baseURL: ApiUrls.BaseURL,
|
|
143
144
|
timeout: 10000,
|
|
144
|
-
headers:
|
|
145
|
+
headers: deviceData.headers,
|
|
145
146
|
withCredentials: true
|
|
146
147
|
});
|
|
147
148
|
|
|
@@ -194,7 +195,7 @@ class MelCloudErv extends EventEmitter {
|
|
|
194
195
|
method: 'PUT',
|
|
195
196
|
baseURL: ApiUrlsHome.BaseURL,
|
|
196
197
|
timeout: 10000,
|
|
197
|
-
headers:
|
|
198
|
+
headers: deviceData.headers,
|
|
198
199
|
withCredentials: true
|
|
199
200
|
});
|
|
200
201
|
|