homebridge-melcloud-control 4.4.1-beta.5 → 4.4.1-beta.50
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 +10 -0
- package/README.md +55 -55
- package/config.schema.json +54 -54
- package/homebridge-ui/public/index.html +142 -130
- package/index.js +17 -5
- package/package.json +2 -2
- package/src/constants.js +62 -50
- package/src/deviceata.js +25 -18
- package/src/deviceatw.js +6 -10
- package/src/deviceerv.js +61 -60
- package/src/functions.js +105 -111
- package/src/melcloud.js +10 -8
- package/src/melcloudata.js +41 -10
- package/src/melcloudatw.js +25 -9
- package/src/melclouderv.js +24 -8
- package/src/melcloudhome.js +40 -36
|
@@ -204,21 +204,26 @@
|
|
|
204
204
|
}
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
207
|
+
// Generic remove function
|
|
208
|
+
// Generic remove function
|
|
209
|
+
function removeStaleEntities(configEntities, MelcloudEntities, getConfigId, getMelcloudId) {
|
|
210
|
+
const serverIds = new Set((MelcloudEntities ?? []).map(item => String(getMelcloudId(item))));
|
|
211
|
+
const removedEntities = [];
|
|
212
|
+
|
|
213
|
+
for (let i = configEntities.length - 1; i >= 0; i--) {
|
|
214
|
+
const entity = configEntities[i];
|
|
215
|
+
const entityId = String(getConfigId(entity));
|
|
216
|
+
|
|
217
|
+
if (!serverIds.has(entityId)) {
|
|
218
|
+
removedEntities.push(entity);
|
|
219
|
+
configEntities.splice(i, 1);
|
|
217
220
|
}
|
|
218
221
|
}
|
|
219
|
-
|
|
222
|
+
|
|
223
|
+
return removedEntities;
|
|
220
224
|
}
|
|
221
225
|
|
|
226
|
+
// Update info on page
|
|
222
227
|
function updateInfo(id, text, color) {
|
|
223
228
|
const el = document.getElementById(id);
|
|
224
229
|
if (el) {
|
|
@@ -227,10 +232,26 @@
|
|
|
227
232
|
}
|
|
228
233
|
}
|
|
229
234
|
|
|
235
|
+
// Map UnitId → Scenes for quick lookup
|
|
236
|
+
function mapUnitIdToScenes(scenesInMelCloud) {
|
|
237
|
+
const map = new Map();
|
|
238
|
+
|
|
239
|
+
scenesInMelCloud.forEach(scene => {
|
|
240
|
+
const allSceneSettings = [...(scene.AtaSceneSettings ?? []), ...(scene.AtwSceneSettings ?? []), ...(scene.ErvSceneSettings ?? [])];
|
|
241
|
+
allSceneSettings.forEach(setting => {
|
|
242
|
+
const unitId = String(setting.UnitId);
|
|
243
|
+
if (!map.has(unitId)) map.set(unitId, []);
|
|
244
|
+
map.get(unitId).push(scene);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
return map;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Login & Sync Logic
|
|
230
252
|
document.getElementById('logIn').addEventListener('click', async () => {
|
|
231
253
|
homebridge.showSpinner();
|
|
232
|
-
|
|
233
|
-
document.getElementById(`logIn`).className = "btn btn-primary";
|
|
254
|
+
document.getElementById('logIn').className = "btn btn-primary";
|
|
234
255
|
updateInfo('info', '', 'white');
|
|
235
256
|
updateInfo('info1', '', 'white');
|
|
236
257
|
updateInfo('info2', '', 'white');
|
|
@@ -238,161 +259,152 @@
|
|
|
238
259
|
try {
|
|
239
260
|
const account = this.account;
|
|
240
261
|
const response = await homebridge.request('/connect', account);
|
|
262
|
+
|
|
241
263
|
if (!response.State) {
|
|
242
264
|
homebridge.hideSpinner();
|
|
243
|
-
updateInfo('info', response.Info);
|
|
265
|
+
updateInfo('info', response.Info, 'red');
|
|
244
266
|
return;
|
|
245
267
|
}
|
|
246
268
|
|
|
247
|
-
//
|
|
248
|
-
const newInMelCloud = { ata: [], ataPresets: [], ataSchedules: [], atw: [], atwPresets: [], atwSchedules: [], erv: [], ervPresets: [], ervSchedules: [],
|
|
269
|
+
// Prepare MELCloud data
|
|
270
|
+
const newInMelCloud = { ata: [], ataPresets: [], ataSchedules: [], ataScenes: [], atw: [], atwPresets: [], atwSchedules: [], atwScenes: [], erv: [], ervPresets: [], ervSchedules: [], ervScenes: [] };
|
|
249
271
|
const devicesInMelCloudByType = { ata: [], atw: [], erv: [] };
|
|
250
|
-
const scenesInMelCloud = response.Scenes ?? []
|
|
272
|
+
const scenesInMelCloud = response.Scenes ?? [];
|
|
251
273
|
|
|
274
|
+
// Split devices by type
|
|
252
275
|
response.Devices.forEach(device => {
|
|
253
276
|
if (device.Type === 0) devicesInMelCloudByType.ata.push(device);
|
|
254
277
|
if (device.Type === 1) devicesInMelCloudByType.atw.push(device);
|
|
255
278
|
if (device.Type === 3) devicesInMelCloudByType.erv.push(device);
|
|
256
279
|
});
|
|
257
280
|
|
|
281
|
+
// Clean up local config
|
|
258
282
|
account.ataDevices = (account.ataDevices ?? []).filter(d => String(d.id) !== '0');
|
|
259
283
|
account.atwDevices = (account.atwDevices ?? []).filter(d => String(d.id) !== '0');
|
|
260
284
|
account.ervDevices = (account.ervDevices ?? []).filter(d => String(d.id) !== '0');
|
|
261
285
|
|
|
262
|
-
const
|
|
263
|
-
const
|
|
264
|
-
const
|
|
286
|
+
const removedFromConfigAta = removeStaleEntities(account.ataDevices, devicesInMelCloudByType.ata, d => d.id, d => d.DeviceID);
|
|
287
|
+
const removedFromConfigAtw = removeStaleEntities(account.atwDevices, devicesInMelCloudByType.atw, d => d.id, d => d.DeviceID);
|
|
288
|
+
const removedFromConfigErv = removeStaleEntities(account.ervDevices, devicesInMelCloudByType.erv, d => d.id, d => d.DeviceID);
|
|
289
|
+
const removedFromConfig = { presets: [], schedules: [], scenes: [] };
|
|
290
|
+
|
|
291
|
+
// Map UnitId → Scenes
|
|
292
|
+
const unitIdToScenes = mapUnitIdToScenes(scenesInMelCloud);
|
|
265
293
|
|
|
294
|
+
// Generic device handler (obsługuje urządzenia, presety, harmonogramy i sceny)
|
|
266
295
|
const handleDevices = (devicesInMelCloud, devicesInConfig, deviceTypeString, newDevices, newPresets, newSchedules, newScenes) => {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
displayType: 0,
|
|
345
|
-
name: scene.Name || `Scene ${index}`,
|
|
346
|
-
namePrefix: false
|
|
347
|
-
};
|
|
348
|
-
scenesInConfig.push(sceneObj);
|
|
349
|
-
newScenes.push(sceneObj);
|
|
350
|
-
sceneIds.add(sceneId);
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
// Return filtered devicesInConfig to make sure upstream code uses it
|
|
357
|
-
return devicesInConfig;
|
|
358
|
-
} catch (error) {
|
|
359
|
-
updateInfo('info', `Error while processing device: ${JSON.stringify(error)}`, 'red');
|
|
360
|
-
}
|
|
296
|
+
const configDevicesMap = new Map(devicesInConfig.map(dev => [String(dev.id), dev]));
|
|
297
|
+
|
|
298
|
+
devicesInMelCloud.forEach(device => {
|
|
299
|
+
const deviceId = String(device.DeviceID);
|
|
300
|
+
let deviceInConfig = configDevicesMap.get(deviceId);
|
|
301
|
+
|
|
302
|
+
if (!deviceInConfig) {
|
|
303
|
+
deviceInConfig = { id: deviceId, type: device.Type, deviceTypeString, displayType: 0, name: device.DeviceName };
|
|
304
|
+
devicesInConfig.push(deviceInConfig);
|
|
305
|
+
newDevices.push(deviceInConfig);
|
|
306
|
+
configDevicesMap.set(deviceId, deviceInConfig);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// PRESETS (melcloud)
|
|
310
|
+
if (account.type === 'melcloud') {
|
|
311
|
+
deviceInConfig.presets = (deviceInConfig.presets ?? []).filter(p => String(p.id) !== '0');
|
|
312
|
+
const presetsInMelCloud = device.Presets ?? [];
|
|
313
|
+
removedFromConfig.presets.push(...removeStaleEntities(deviceInConfig.presets, presetsInMelCloud, p => p.id, p => p.ID));
|
|
314
|
+
const presetIds = new Set(deviceInConfig.presets.map(p => String(p.id)));
|
|
315
|
+
presetsInMelCloud.forEach((preset, index) => {
|
|
316
|
+
const presetId = String(preset.ID);
|
|
317
|
+
if (!presetIds.has(presetId)) {
|
|
318
|
+
const presetObj = {
|
|
319
|
+
id: presetId,
|
|
320
|
+
displayType: 0,
|
|
321
|
+
name: preset.NumberDescription || `Preset ${index}`,
|
|
322
|
+
namePrefix: false
|
|
323
|
+
};
|
|
324
|
+
deviceInConfig.presets.push(presetObj);
|
|
325
|
+
newPresets.push(presetObj);
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// SCHEDULES & SCENES (melcloudhome)
|
|
331
|
+
if (account.type === 'melcloudhome') {
|
|
332
|
+
// SCHEDULES
|
|
333
|
+
deviceInConfig.schedules = (deviceInConfig.schedules ?? []).filter(s => String(s.id) !== '0');
|
|
334
|
+
const schedulesInMelCloud = device.Schedule ?? [];
|
|
335
|
+
removedFromConfig.schedules.push(...removeStaleEntities(deviceInConfig.schedules, schedulesInMelCloud, s => s.id, s => s.Id));
|
|
336
|
+
const scheduleIds = new Set(deviceInConfig.schedules.map(s => String(s.id)));
|
|
337
|
+
schedulesInMelCloud.forEach((schedule, index) => {
|
|
338
|
+
const scheduleId = String(schedule.Id);
|
|
339
|
+
if (!scheduleIds.has(scheduleId)) {
|
|
340
|
+
const scheduleObj = {
|
|
341
|
+
id: scheduleId,
|
|
342
|
+
displayType: 0,
|
|
343
|
+
name: `Schedule ${index}`,
|
|
344
|
+
namePrefix: false
|
|
345
|
+
};
|
|
346
|
+
deviceInConfig.schedules.push(scheduleObj);
|
|
347
|
+
newSchedules.push(scheduleObj);
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// SCENES
|
|
352
|
+
deviceInConfig.scenes = (deviceInConfig.scenes ?? []).filter(s => String(s.id) !== '0');
|
|
353
|
+
const scenesForDevice = unitIdToScenes.get(deviceId) ?? [];
|
|
354
|
+
removedFromConfig.scenes.push(...removeStaleEntities(deviceInConfig.scenes, scenesForDevice, s => s.id, s => s.Id));
|
|
355
|
+
const sceneIds = new Set(deviceInConfig.scenes.map(s => String(s.id)));
|
|
356
|
+
scenesForDevice.forEach((scene, index) => {
|
|
357
|
+
const sceneId = String(scene.Id);
|
|
358
|
+
if (!sceneIds.has(sceneId)) {
|
|
359
|
+
const sceneObj = {
|
|
360
|
+
id: sceneId,
|
|
361
|
+
displayType: 0,
|
|
362
|
+
name: scene.Name || `Scene ${index}`,
|
|
363
|
+
namePrefix: false
|
|
364
|
+
};
|
|
365
|
+
deviceInConfig.scenes.push(sceneObj);
|
|
366
|
+
newScenes.push(sceneObj);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
return devicesInConfig;
|
|
361
373
|
};
|
|
362
374
|
|
|
363
|
-
|
|
364
|
-
account.
|
|
365
|
-
account.
|
|
375
|
+
// Execute device handlers
|
|
376
|
+
account.ataDevices = handleDevices(devicesInMelCloudByType.ata, account.ataDevices, "Air Conditioner", newInMelCloud.ata, newInMelCloud.ataPresets, newInMelCloud.ataSchedules, newInMelCloud.ataScenes);
|
|
377
|
+
account.atwDevices = handleDevices(devicesInMelCloudByType.atw, account.atwDevices, "Heat Pump", newInMelCloud.atw, newInMelCloud.atwPresets, newInMelCloud.atwSchedules, newInMelCloud.atwScenes);
|
|
378
|
+
account.ervDevices = handleDevices(devicesInMelCloudByType.erv, account.ervDevices, "Energy Recovery Ventilation", newInMelCloud.erv, newInMelCloud.ervPresets, newInMelCloud.ervSchedules, newInMelCloud.ervScenes);
|
|
366
379
|
|
|
380
|
+
// Summary counts
|
|
367
381
|
const newDevicesCount = newInMelCloud.ata.length + newInMelCloud.atw.length + newInMelCloud.erv.length;
|
|
368
382
|
const newPresetsCount = newInMelCloud.ataPresets.length + newInMelCloud.atwPresets.length + newInMelCloud.ervPresets.length;
|
|
369
383
|
const newSchedulesCount = newInMelCloud.ataSchedules.length + newInMelCloud.atwSchedules.length + newInMelCloud.ervSchedules.length;
|
|
370
|
-
const newScenesCount = newInMelCloud.
|
|
371
|
-
const removedDevicesCount =
|
|
384
|
+
const newScenesCount = newInMelCloud.ataScenes.length + newInMelCloud.atwScenes.length + newInMelCloud.ervScenes.length;
|
|
385
|
+
const removedDevicesCount = removedFromConfigAta.length + removedFromConfigAtw.length + removedFromConfigErv.length;
|
|
386
|
+
const removedPresetsCount = removedFromConfig.presets.length;
|
|
387
|
+
const removedSchedulesCount = removedFromConfig.schedules.length;
|
|
388
|
+
const removedScenesCount = removedFromConfig.scenes.length;
|
|
372
389
|
|
|
373
|
-
if (!newDevicesCount && !newPresetsCount && !newSchedulesCount && !newScenesCount && !removedDevicesCount) {
|
|
390
|
+
if (!newDevicesCount && !newPresetsCount && !newSchedulesCount && !newScenesCount && !removedDevicesCount && !removedPresetsCount && !removedSchedulesCount && !removedScenesCount) {
|
|
374
391
|
updateInfo('info', 'No changes detected.', 'white');
|
|
375
392
|
} else {
|
|
376
|
-
if (newDevicesCount)
|
|
377
|
-
updateInfo('info', `Found new devices: ${newInMelCloud.ata.length ? `ATA: ${newInMelCloud.ata.length}
|
|
378
|
-
if (
|
|
379
|
-
updateInfo('info1', `
|
|
380
|
-
if (newScenesCount || newSchedulesCount)
|
|
381
|
-
updateInfo('info1', `Found new ${newSchedulesCount ? `schedules:` : ''} ${newInMelCloud.ataSchedules.length ? `ATA: ${newInMelCloud.ataSchedules.length},` : ''} ${newInMelCloud.atwSchedules.length ? `ATW: ${newInMelCloud.atwSchedules.length},` : ''} ${newInMelCloud.ervSchedules.length ? `ERV: ${newInMelCloud.ervSchedules.length},` : ''} ${newScenesCount ? `scenes: ${newScenesCount}` : ''}.`, 'green');
|
|
382
|
-
if (removedDevicesCount)
|
|
383
|
-
updateInfo('info2', `Removed devices: ${removedAta.length ? `ATA: ${removedAta.length},` : ''} ${removedAtw.length ? `ATW: ${removedAtw.length},` : ''} ${removedErv.length ? `ERV: ${removedErv.length}` : ''}.`, 'orange');
|
|
393
|
+
if (newDevicesCount || newPresetsCount || newSchedulesCount || newScenesCount)
|
|
394
|
+
updateInfo('info', `Found new ${newDevicesCount ? `devices:` : ''} ${newInMelCloud.ata.length ? `ATA: ${newInMelCloud.ata.length}` : ''} ${newInMelCloud.atw.length ? `, ATW: ${newInMelCloud.atw.length}` : ''} ${newInMelCloud.erv.length ? `, ERV: ${newInMelCloud.erv.length},` : ''} ${newPresetsCount ? `, presets:` : ''} ${newInMelCloud.ataPresets.length ? `ATA: ${newInMelCloud.ataPresets.length}` : ''} ${newInMelCloud.atwPresets.length ? `, ATW: ${newInMelCloud.atwPresets.length}` : ''} ${newInMelCloud.ervPresets.length ? `, ERV: ${newInMelCloud.ervPresets.length}` : ''} ${newSchedulesCount ? `, schedules:` : ''} ${newInMelCloud.ataSchedules.length ? `ATA: ${newInMelCloud.ataSchedules.length}` : ''} ${newInMelCloud.atwSchedules.length ? `, ATW: ${newInMelCloud.atwSchedules.length}` : ''} ${newInMelCloud.ervSchedules.length ? `, ERV: ${newInMelCloud.ervSchedules.length}` : ''} ${newScenesCount ? `, scenes:` : ''} ${newInMelCloud.ataScenes.length ? `ATA: ${newInMelCloud.ataScenes.length}` : ''} ${newInMelCloud.atwScenes.length ? `, ATW: ${newInMelCloud.atwScenes.length}` : ''} ${newInMelCloud.ervScenes.length ? `, ERV: ${newInMelCloud.ervScenes.length}` : ''}.`, 'green');
|
|
395
|
+
if (removedDevicesCount || removedPresetsCount || removedSchedulesCount || removedScenesCount)
|
|
396
|
+
updateInfo('info1', `Removed ${removedDevicesCount ? `devices: ${removedPresetsCount}` : ''} ${removedFromConfigAta.length ? `ATA: ${removedFromConfigAta.length}` : ''} ${removedFromConfigAtw.length ? `, ATW: ${removedFromConfigAtw.length}` : ''} ${removedFromConfigErv.length ? `, ERV: ${removedFromConfigErv.length}` : ''} ${removedPresetsCount ? `, presets: ${removedPresetsCount}` : ''} ${removedSchedulesCount ? `, schedules: ${removedSchedulesCount}` : ''} ${removedScenesCount ? `, scenes: ${removedScenesCount}` : ''}.`, 'orange');
|
|
384
397
|
}
|
|
385
398
|
|
|
386
399
|
await homebridge.updatePluginConfig(pluginConfig);
|
|
387
400
|
await homebridge.savePluginConfig(pluginConfig);
|
|
401
|
+
|
|
388
402
|
} catch (error) {
|
|
389
403
|
updateInfo('info', `Prepare config error ${JSON.stringify(error)}`, 'red');
|
|
390
|
-
document.getElementById('logIn').className = "btn btn-secondary";
|
|
391
404
|
} finally {
|
|
392
405
|
document.getElementById('logIn').className = "btn btn-secondary";
|
|
393
406
|
homebridge.hideSpinner();
|
|
394
407
|
}
|
|
395
408
|
});
|
|
396
|
-
|
|
397
409
|
})();
|
|
398
410
|
</script>
|
package/index.js
CHANGED
|
@@ -137,12 +137,24 @@ class MelCloudPlatform {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
//chack device from config exist on melcloud
|
|
140
|
-
const
|
|
141
|
-
if (!
|
|
140
|
+
const deviceInMelCloud = melcloudDevicesList.Devices.find(d => d.DeviceID === device.id);
|
|
141
|
+
if (!deviceInMelCloud) {
|
|
142
142
|
if (logLevel.warn) log.warn(`${name}, ${deviceTypeString}, ${deviceName}, not exist on server, please login to MELCLoud from plugin UI to fix this issue.`);
|
|
143
143
|
continue;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
//presets
|
|
147
|
+
const presetIds = (deviceInMelCloud.Presets ?? []).map(p => String(p.ID));
|
|
148
|
+
const presets = account.type === 'melcloud' ? (device.presets || []).filter(p => (p.displayType ?? 0) > 0 && p.id !== '0' && presetIds.includes(p.id)) : [];
|
|
149
|
+
|
|
150
|
+
//schedules
|
|
151
|
+
const schedulesIds = (deviceInMelCloud.Schedule ?? []).map(s => String(s.Id));
|
|
152
|
+
const schedules = account.type === 'melcloudhome' ? (device.schedules || []).filter(s => (s.displayType ?? 0) > 0 && s.id !== '0' && schedulesIds.includes(s.id)) : [];
|
|
153
|
+
|
|
154
|
+
//scenes
|
|
155
|
+
const scenesIds = (melcloudDevicesList.Scenes ?? []).map(s => String(s.Id));
|
|
156
|
+
const scenes = account.type === 'melcloudhome' ? (device.scenes || []).filter(s => (s.displayType ?? 0) > 0 && s.id !== '0' && scenesIds.includes(s.id)) : [];
|
|
157
|
+
|
|
146
158
|
// set rest ful port
|
|
147
159
|
account.restFul.port = (device.id).slice(-4).replace(/^0/, '9');
|
|
148
160
|
|
|
@@ -168,15 +180,15 @@ class MelCloudPlatform {
|
|
|
168
180
|
let configuredDevice;
|
|
169
181
|
switch (deviceType) {
|
|
170
182
|
case 0: //ATA
|
|
171
|
-
configuredDevice = new DeviceAta(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
|
|
183
|
+
configuredDevice = new DeviceAta(api, account, device, presets, schedules, scenes, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
|
|
172
184
|
break;
|
|
173
185
|
case 1: //ATW
|
|
174
|
-
configuredDevice = new DeviceAtw(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
|
|
186
|
+
configuredDevice = new DeviceAtw(api, account, device, presets, schedules, scenes, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
|
|
175
187
|
break;
|
|
176
188
|
case 2:
|
|
177
189
|
break;
|
|
178
190
|
case 3: //ERV
|
|
179
|
-
configuredDevice = new DeviceErv(api, account, device, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
|
|
191
|
+
configuredDevice = new DeviceErv(api, account, device, presets, schedules, scenes, defaultTempsFile, accountInfo, accountFile, melcloud, melcloudDevicesList);
|
|
180
192
|
break;
|
|
181
193
|
default:
|
|
182
194
|
if (logLevel.warn) log.warn(`${name}, ${deviceTypeString}, ${deviceName}, unknown device: ${deviceType}.`);
|
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.50",
|
|
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
|
"mqtt": "^5.14.1",
|
|
40
40
|
"axios": "^1.13.2",
|
|
41
41
|
"express": "^5.2.1",
|
|
42
|
-
"puppeteer": "^24.
|
|
42
|
+
"puppeteer": "^24.33.1",
|
|
43
43
|
"ws": "^8.18.3"
|
|
44
44
|
},
|
|
45
45
|
"keywords": [
|
package/src/constants.js
CHANGED
|
@@ -2,60 +2,67 @@ export const PlatformName = "melcloudcontrol";
|
|
|
2
2
|
export const PluginName = "homebridge-melcloud-control";
|
|
3
3
|
|
|
4
4
|
export const ApiUrls = {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
SetAtw: "/Device/SetAtw",
|
|
14
|
-
SetErv: "/Device/SetErv",
|
|
15
|
-
GetRefreshUnit: "/Device/RequestRefresh?id=deviceid",
|
|
16
|
-
UpdateApplicationOptions: "/User/UpdateApplicationOptions",
|
|
17
|
-
HolidayModeUpdate: "/HolidayMode/Update",
|
|
18
|
-
EnergyCostReport: "/EnergyCost/Report",
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const ApiUrlsHome = {
|
|
22
|
-
BaseURL: "https://melcloudhome.com",
|
|
23
|
-
GetConfiguration: "https://melcloudhome.com/api/configuration",
|
|
24
|
-
GetUserContext: "/api/user/context",
|
|
25
|
-
GetUserScenes: "/api/user/scenes",
|
|
26
|
-
PostSchedule: "/api/cloudschedule/deviceid", // POST {"days":[2],"time":"17:59:00","enabled":true,"id":"53c5e804-0663-47d0-85c2-2d8ccd2573de","power":false,"operationMode":null,"setPoint":null,"vaneVerticalDirection":null,"vaneHorizontalDirection":null,"setFanSpeed":null}
|
|
27
|
-
PostProtectionFrost: "/api/protection/frost", // POST {"enabled":true,"min":13,"max":16,"units":{"ATA":["ef333525-2699-4290-af5a-2922566676da"]}}
|
|
28
|
-
PostProtectionOverheat: "/api/protection/overheat", // POST {"enabled":true,"min":32,"max":35,"units":{"ATA":["ef333525-2699-4290-af5a-2922566676da"]}}
|
|
29
|
-
PostHolidayMode: " /api/holidaymode", // POST {"enabled":true,"startDate":"2025-11-11T17:42:24.913","endDate":"2026-06-01T09:18:00","units":{"ATA":["ef333525-2699-4290-af5a-2922566676da"]}}
|
|
30
|
-
PutAta: "/api/ataunit/deviceid",
|
|
31
|
-
PutAtw: "/api/atwunit/deviceid",
|
|
32
|
-
PutErv: "/api/ervunit/deviceid",
|
|
33
|
-
PutScheduleEnabled: "/api/cloudschedule/deviceid/enabled", // PUT {"enabled":true}
|
|
34
|
-
PutScene: {
|
|
35
|
-
Enable: "/api/scene/sceneid/enable",
|
|
36
|
-
Disable: "/api/scene/sceneid/disable",
|
|
5
|
+
Base: "https://app.melcloud.com/Mitsubishi.Wifi.Client",
|
|
6
|
+
Get: {
|
|
7
|
+
UserDetails: "/User/GetUserDetails",
|
|
8
|
+
ListDevices: "/User/ListDevices",
|
|
9
|
+
ListDeviceUnits: "/Device/ListDeviceUnits",
|
|
10
|
+
RefreshUnit: "/Device/RequestRefresh?id=deviceid",
|
|
11
|
+
DeviceState: "/Device/Get?id=DID&buildingID=BID",
|
|
12
|
+
TileState: "/Tile/Get2?id=DID&buildingID=BID",
|
|
37
13
|
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
14
|
+
Post: {
|
|
15
|
+
ClientLogin: "/Login/ClientLogin",
|
|
16
|
+
Ata: "/Device/SetAta",
|
|
17
|
+
Atw: "/Device/SetAtw",
|
|
18
|
+
Erv: "/Device/SetErv",
|
|
19
|
+
UpdateApplicationOptions: "/User/UpdateApplicationOptions",
|
|
20
|
+
HolidayMode: "/HolidayMode/Update",
|
|
21
|
+
EnergyCostReport: "/EnergyCost/Report",
|
|
46
22
|
},
|
|
47
|
-
|
|
48
|
-
|
|
23
|
+
Home: {
|
|
24
|
+
Base: "https://melcloudhome.com",
|
|
25
|
+
WebSocket: "wss://ws.melcloudhome.com/?hash=",
|
|
26
|
+
Get: {
|
|
27
|
+
Configuration: "/api/configuration",
|
|
28
|
+
ListDevices: "/api/user/context",
|
|
29
|
+
Scenes: "/api/user/scenes",
|
|
30
|
+
},
|
|
31
|
+
Post: {
|
|
32
|
+
ProtectionFrost: "/api/protection/frost", //{"enabled":true,"min":13,"max":16,"units":{"ATA":["deviceid"]}}
|
|
33
|
+
ProtectionOverheat: "/api/protection/overheat", //{"enabled":true,"min":32,"max":35,"units":{"ATA":["deviceid"]}}
|
|
34
|
+
HolidayMode: "/api/holidaymode", //{"enabled":true,"startDate":"2025-11-11T17:42:24.913","endDate":"2026-06-01T09:18:00","units":{"ATA":["deviceid"]}}
|
|
35
|
+
Schedule: "/api/cloudschedule/deviceid", //{"days":[2],"time":"17:59:00","enabled":true,"id":"scheduleid","power":false,"operationMode":null,"setPoint":null,"vaneVerticalDirection":null,"vaneHorizontalDirection":null,"setFanSpeed":null}
|
|
36
|
+
Scene: "/api/scene", //{"id": "sceneid", "userId": "userid","name": "Poza domem","enabled": false,"icon": "AwayIcon","ataSceneSettings": [{"unitId": "deviceid","ataSettings": { "power": false, "operationMode": "heat","setFanSpeed": "auto","vaneHorizontalDirection": "auto", "vaneVerticalDirection": "auto", "setTemperature": 21,"temperatureIncrementOverride": null,"inStandbyMode": null},"previousSettings": null}],"atwSceneSettings": []}
|
|
37
|
+
},
|
|
38
|
+
Put: {
|
|
39
|
+
Ata: "/api/ataunit/deviceid", //{ power: true,setTemperature: 22, setFanSpeed: "auto", operationMode: "heat", vaneHorizontalDirection: "auto",vaneVerticalDirection: "auto", temperatureIncrementOverride: null, inStandbyMode: null}
|
|
40
|
+
Atw: "/api/atwunit/deviceid",
|
|
41
|
+
Erv: "/api/ervunit/deviceid",
|
|
42
|
+
ScheduleEnableDisable: "/api/cloudschedule/deviceid/enabled", // {"enabled": true}
|
|
43
|
+
SceneEnableDisable: "/api/scene/sceneid/enabledisable",
|
|
44
|
+
},
|
|
45
|
+
Delete: {
|
|
46
|
+
Schedule: "/api/cloudschedule/deviceid/scheduleid",
|
|
47
|
+
Scene: "/api/scene/sceneid"
|
|
48
|
+
},
|
|
49
|
+
Referers: {
|
|
50
|
+
GetPutScenes: "https://melcloudhome.com/scenes",
|
|
51
|
+
PostHolidayMode: "https://melcloudhome.com/ata/deviceid/holidaymode",
|
|
52
|
+
PostProtectionFrost: "https://melcloudhome.com/ata/deviceid/frostprotection",
|
|
53
|
+
PostProtectionOverheat: "https://melcloudhome.com/ata/deviceid/overheatprotection",
|
|
54
|
+
PutDeviceSettings: "https://melcloudhome.com/dashboard",
|
|
55
|
+
PutScheduleEnabled: "https://melcloudhome.com/ata/deviceid/schedule",
|
|
56
|
+
}
|
|
57
|
+
}
|
|
49
58
|
};
|
|
50
59
|
|
|
51
|
-
export const DeviceType =
|
|
52
|
-
"Air Conditioner",
|
|
53
|
-
"Heat Pump",
|
|
54
|
-
"Unknown",
|
|
55
|
-
"Energy Recovery Ventilation"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
export const TemperatureDisplayUnits = ["°C", "°F"];
|
|
60
|
+
export const DeviceType = {
|
|
61
|
+
0: "Air Conditioner",
|
|
62
|
+
1: "Heat Pump",
|
|
63
|
+
2: "Unknown",
|
|
64
|
+
3: "Energy Recovery Ventilation"
|
|
65
|
+
};
|
|
59
66
|
|
|
60
67
|
export const AirConditioner = {
|
|
61
68
|
SystemMapEnumToString: { 0: "Air Conditioner Off", 1: "Air Conditioner On", 2: "Air Conditioner Offline" },
|
|
@@ -183,6 +190,11 @@ export const Ventilation = {
|
|
|
183
190
|
}
|
|
184
191
|
};
|
|
185
192
|
|
|
193
|
+
export const TemperatureDisplayUnits = {
|
|
194
|
+
0: "°C",
|
|
195
|
+
1: "°F"
|
|
196
|
+
};
|
|
197
|
+
|
|
186
198
|
export const AccessLevel = {
|
|
187
199
|
Quest: 3,
|
|
188
200
|
Owner: 4
|