homebridge-melcloud-control 4.4.1-beta.8 → 4.5.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 +11 -0
- package/README.md +26 -26
- package/homebridge-ui/public/index.html +147 -134
- package/index.js +20 -5
- package/package.json +2 -2
- package/src/constants.js +10 -10
- package/src/deviceata.js +24 -13
- package/src/deviceatw.js +5 -5
- package/src/deviceerv.js +60 -55
- package/src/functions.js +105 -111
- package/src/melcloud.js +6 -4
- package/src/melcloudata.js +33 -2
- package/src/melcloudatw.js +18 -2
- package/src/melclouderv.js +18 -2
- package/src/melcloudhome.js +31 -25
package/src/melcloudatw.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
import Functions from './functions.js';
|
|
3
|
-
import { ApiUrls,
|
|
3
|
+
import { ApiUrls, HeatPump } from './constants.js';
|
|
4
4
|
|
|
5
5
|
class MelCloudAtw extends EventEmitter {
|
|
6
6
|
constructor(account, device, defaultTempsFile, accountFile, melcloud) {
|
|
@@ -71,7 +71,19 @@ class MelCloudAtw extends EventEmitter {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
updateState = true;
|
|
75
|
+
break;
|
|
76
|
+
case 'atwUnitFrostProtectionTriggered':
|
|
77
|
+
deviceData.FrostProtection.Active = messageData.active;
|
|
78
|
+
|
|
79
|
+
//update device settings
|
|
80
|
+
for (const [key, value] of Object.entries(settings)) {
|
|
81
|
+
if (!this.functions.isValidValue(value)) continue;
|
|
82
|
+
|
|
83
|
+
if (key in deviceData.Device) {
|
|
84
|
+
deviceData.Device[key] = value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
75
87
|
updateState = true;
|
|
76
88
|
break;
|
|
77
89
|
case 'unitHolidayModeTriggered':
|
|
@@ -84,6 +96,10 @@ class MelCloudAtw extends EventEmitter {
|
|
|
84
96
|
deviceData.Rssi = messageData.rssi;
|
|
85
97
|
updateState = true;
|
|
86
98
|
break;
|
|
99
|
+
case 'unitCommunicationRestored':
|
|
100
|
+
timestamp = messageData.timestamp;
|
|
101
|
+
deviceData.Device.IsConnected = true;
|
|
102
|
+
break;
|
|
87
103
|
default:
|
|
88
104
|
if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${parsedMessage}`);
|
|
89
105
|
return;
|
package/src/melclouderv.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
import Functions from './functions.js';
|
|
3
|
-
import { ApiUrls,
|
|
3
|
+
import { ApiUrls, Ventilation } from './constants.js';
|
|
4
4
|
|
|
5
5
|
class MelCloudErv extends EventEmitter {
|
|
6
6
|
constructor(account, device, defaultTempsFile, accountFile, melcloud) {
|
|
@@ -71,7 +71,19 @@ class MelCloudErv extends EventEmitter {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
updateState = true;
|
|
75
|
+
break;
|
|
76
|
+
case 'ervUnitFrostProtectionTriggered':
|
|
77
|
+
deviceData.FrostProtection.Active = messageData.active;
|
|
78
|
+
|
|
79
|
+
//update device settings
|
|
80
|
+
for (const [key, value] of Object.entries(settings)) {
|
|
81
|
+
if (!this.functions.isValidValue(value)) continue;
|
|
82
|
+
|
|
83
|
+
if (key in deviceData.Device) {
|
|
84
|
+
deviceData.Device[key] = value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
75
87
|
updateState = true;
|
|
76
88
|
break;
|
|
77
89
|
case 'unitHolidayModeTriggered':
|
|
@@ -84,6 +96,10 @@ class MelCloudErv extends EventEmitter {
|
|
|
84
96
|
deviceData.Rssi = messageData.rssi;
|
|
85
97
|
updateState = true;
|
|
86
98
|
break;
|
|
99
|
+
case 'unitCommunicationRestored':
|
|
100
|
+
timestamp = messageData.timestamp;
|
|
101
|
+
deviceData.Device.IsConnected = true;
|
|
102
|
+
break;
|
|
87
103
|
default:
|
|
88
104
|
if (this.logDebug) this.emit('debug', `Unit ${unitId}, received unknown message type: ${parsedMessage}`);
|
|
89
105
|
return;
|
package/src/melcloudhome.js
CHANGED
|
@@ -77,7 +77,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
77
77
|
async checkScenesList() {
|
|
78
78
|
try {
|
|
79
79
|
if (this.logDebug) this.emit('debug', `Scanning for scenes`);
|
|
80
|
-
const listScenesData = await this.client(ApiUrls.Home.Get.
|
|
80
|
+
const listScenesData = await this.client(ApiUrls.Home.Get.Scenes, { method: 'GET', });
|
|
81
81
|
|
|
82
82
|
const scenesList = listScenesData.data;
|
|
83
83
|
if (this.logDebug) this.emit('debug', `Scenes: ${JSON.stringify(scenesList, null, 2)}`);
|
|
@@ -107,9 +107,9 @@ class MelCloudHome extends EventEmitter {
|
|
|
107
107
|
|
|
108
108
|
async checkDevicesList() {
|
|
109
109
|
try {
|
|
110
|
-
const devicesList = { State: false, Info: null, Devices: [], Scenes: [] }
|
|
110
|
+
const devicesList = { State: false, Info: null, Buildings: {}, Devices: [], Scenes: [] }
|
|
111
111
|
if (this.logDebug) this.emit('debug', `Scanning for devices`);
|
|
112
|
-
const listDevicesData = await this.client(ApiUrls.Home.Get.
|
|
112
|
+
const listDevicesData = await this.client(ApiUrls.Home.Get.ListDevices, { method: 'GET' });
|
|
113
113
|
|
|
114
114
|
const userContext = listDevicesData.data;
|
|
115
115
|
const buildings = userContext.buildings ?? [];
|
|
@@ -122,9 +122,6 @@ class MelCloudHome extends EventEmitter {
|
|
|
122
122
|
return devicesList;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
await this.functions.saveData(this.buildingsFile, userContext);
|
|
126
|
-
if (this.logDebug) this.emit('debug', `Buildings list saved`);
|
|
127
|
-
|
|
128
125
|
const devices = buildingsList.flatMap(building => {
|
|
129
126
|
// Funkcja kapitalizująca klucze obiektu
|
|
130
127
|
const capitalizeKeys = obj => Object.fromEntries(Object.entries(obj).map(([key, value]) => [key.charAt(0).toUpperCase() + key.slice(1), value]));
|
|
@@ -205,8 +202,13 @@ class MelCloudHome extends EventEmitter {
|
|
|
205
202
|
|
|
206
203
|
devicesList.State = true;
|
|
207
204
|
devicesList.Info = `Found ${devicesCount} devices ${scenes.length > 0 ? `and ${scenes.length} scenes` : ''}`;
|
|
205
|
+
devicesList.Buildings = userContext;
|
|
208
206
|
devicesList.Devices = devices;
|
|
209
207
|
devicesList.Scenes = scenes;
|
|
208
|
+
|
|
209
|
+
await this.functions.saveData(this.buildingsFile, devicesList);
|
|
210
|
+
if (this.logDebug) this.emit('debug', `Buildings list saved`);
|
|
211
|
+
|
|
210
212
|
this.emit('devicesList', devicesList);
|
|
211
213
|
|
|
212
214
|
return devicesList;
|
|
@@ -223,32 +225,36 @@ class MelCloudHome extends EventEmitter {
|
|
|
223
225
|
try {
|
|
224
226
|
const accountInfo = { State: false, Info: '', Account: {}, UseFahrenheit: false };
|
|
225
227
|
|
|
226
|
-
// Get Chromium path
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
228
|
+
// Get Chromium path from resolver
|
|
229
|
+
const chromiumInfo = await this.functions.ensureChromiumInstalled();
|
|
230
|
+
let chromiumPath = chromiumInfo.path;
|
|
231
|
+
const arch = chromiumInfo.arch;
|
|
232
|
+
const system = chromiumInfo.system;
|
|
233
|
+
|
|
234
|
+
// If path is found, use it
|
|
235
|
+
if (chromiumPath) {
|
|
236
|
+
if (!this.logDebug) this.emit('debug', `Using Chromium for ${system} (${arch}) at ${chromiumPath}`);
|
|
237
|
+
} else {
|
|
238
|
+
if (arch === 'arm') {
|
|
239
|
+
accountInfo.Info = `No Chromium found for ${system} (${arch}). Please install it manually and try again.`;
|
|
240
|
+
return accountInfo;
|
|
241
|
+
} else {
|
|
242
|
+
try {
|
|
243
|
+
chromiumPath = puppeteer.executablePath();
|
|
244
|
+
if (!this.logDebug) this.emit('debug', `Using Puppeteer Chromium for ${system} (${arch}) at ${chromiumPath}`);
|
|
245
|
+
} catch (error) {
|
|
246
|
+
accountInfo.Info = `No Puppeteer Chromium for ${system} (${arch}), error: ${error.message}`;
|
|
238
247
|
return accountInfo;
|
|
239
248
|
}
|
|
240
|
-
} catch (error) {
|
|
241
|
-
accountInfo.Info = `Failed to get Puppeteer Chromium path: ${error.message}`;
|
|
242
|
-
return accountInfo;
|
|
243
249
|
}
|
|
244
250
|
}
|
|
245
251
|
|
|
246
252
|
// Verify Chromium executable
|
|
247
253
|
try {
|
|
248
254
|
const { stdout } = await execPromise(`"${chromiumPath}" --version`);
|
|
249
|
-
if (this.logDebug) this.emit('debug', `Chromium detected: ${stdout.trim()}`);
|
|
255
|
+
if (!this.logDebug) this.emit('debug', `Chromium for ${system} (${arch}) detected: ${stdout.trim()}`);
|
|
250
256
|
} catch (error) {
|
|
251
|
-
accountInfo.Info = `Chromium found at ${chromiumPath}, but
|
|
257
|
+
accountInfo.Info = `Chromium for ${system} (${arch}) found at ${chromiumPath}, but execute error: ${error.message}. Please install it manually and try again.`;
|
|
252
258
|
return accountInfo;
|
|
253
259
|
}
|
|
254
260
|
|
|
@@ -285,7 +291,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
285
291
|
const hash = params.get('hash');
|
|
286
292
|
if (this.logDebug) this.emit('debug', `Web socket hash detected: ${hash}`);
|
|
287
293
|
|
|
288
|
-
//
|
|
294
|
+
// Web socket connection
|
|
289
295
|
if (!this.connecting && !this.socketConnected) {
|
|
290
296
|
this.connecting = true;
|
|
291
297
|
|
|
@@ -417,7 +423,7 @@ class MelCloudHome extends EventEmitter {
|
|
|
417
423
|
baseURL: ApiUrls.Home.Base,
|
|
418
424
|
timeout: 30000,
|
|
419
425
|
headers: headers
|
|
420
|
-
})
|
|
426
|
+
});
|
|
421
427
|
this.emit('client', this.client);
|
|
422
428
|
|
|
423
429
|
accountInfo.State = true;
|