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.
@@ -204,21 +204,26 @@
204
204
  }
205
205
  });
206
206
 
207
- // Device Handling & Login Logic
208
- function removeStaleDevices(configDevices, melcloudDevices) {
209
- const melcloudIds = melcloudDevices.map(d => d.DeviceID);
210
- const removedDevices = [];
211
-
212
- for (let i = configDevices.length - 1; i >= 0; i--) {
213
- const device = configDevices[i];
214
- if (!melcloudIds.includes(device.id)) {
215
- removedDevices.push(device);
216
- configDevices.splice(i, 1);
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
- return removedDevices;
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
- // Initialize devices arrays
248
- const newInMelCloud = { ata: [], ataPresets: [], ataSchedules: [], atw: [], atwPresets: [], atwSchedules: [], erv: [], ervPresets: [], ervSchedules: [], scenes: [] };
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 removedAta = removeStaleDevices(account.ataDevices, devicesInMelCloudByType.ata);
263
- const removedAtw = removeStaleDevices(account.atwDevices, devicesInMelCloudByType.atw);
264
- const removedErv = removeStaleDevices(account.ervDevices, devicesInMelCloudByType.erv);
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
- try {
268
- const configDevicesMap = new Map(devicesInConfig.map(dev => [String(dev.id), dev]));
269
-
270
- devicesInMelCloud.forEach(device => {
271
- const deviceId = String(device.DeviceID);
272
- let deviceInConfig = configDevicesMap.get(deviceId);
273
-
274
- // === Create device if missing ===
275
- if (!deviceInConfig) {
276
- deviceInConfig = {
277
- id: deviceId,
278
- type: device.Type,
279
- deviceTypeString,
280
- displayType: 0,
281
- name: device.DeviceName
282
- };
283
- devicesInConfig.push(deviceInConfig);
284
- newDevices.push(deviceInConfig);
285
- configDevicesMap.set(deviceId, deviceInConfig);
286
- }
287
-
288
- //only for melcloud
289
- if (account.type === 'melcloud') {
290
-
291
- // === Process presets ===
292
- const presetsInMelCloud = device.Presets || [];
293
- const presetsInConfig = (deviceInConfig.presets ?? []).filter(p => String(p.id) !== '0');
294
- const presetIds = new Set(presetsInConfig.map(p => String(p.id)));
295
-
296
- presetsInMelCloud.forEach((preset, index) => {
297
- const presetId = String(preset.ID);
298
- if (!presetIds.has(presetId)) {
299
- const presetObj = {
300
- id: presetId,
301
- displayType: 0,
302
- name: preset.NumberDescription || `Preset ${index}`,
303
- namePrefix: false
304
- };
305
- presetsInConfig.push(presetObj);
306
- newPresets.push(presetObj);
307
- presetIds.add(presetId);
308
- }
309
- });
310
- }
311
-
312
- //only for melcloudhome
313
- if (account.type === 'melcloudhome') {
314
-
315
- // === Process schedules ===
316
- const schedulesInMelCloud = device.Schedule || [];
317
- const schedulesInConfig = (deviceInConfig.schedules ?? []).filter(s => String(s.id) !== '0');
318
- const scheduleIds = new Set(schedulesInConfig.map(s => String(s.id)));
319
-
320
- schedulesInMelCloud.forEach((schedule, index) => {
321
- const scheduleId = String(schedule.Id);
322
- if (!scheduleIds.has(scheduleId)) {
323
- const scheduleObj = {
324
- id: scheduleId,
325
- displayType: 0,
326
- name: `Schedule ${index}`,
327
- namePrefix: false
328
- };
329
- schedulesInConfig.push(scheduleObj);
330
- newSchedules.push(scheduleObj);
331
- scheduleIds.add(scheduleId);
332
- }
333
- });
334
-
335
- // === Process scenes ===
336
- const scenesInConfig = (deviceInConfig.scenes ?? []).filter(s => String(s.id) !== '0');
337
- const sceneIds = new Set(scenesInConfig.map(s => String(s.id)));
338
-
339
- scenesInMelCloud.forEach((scene, index) => {
340
- const sceneId = String(scene.Id);
341
- if (!sceneIds.has(sceneId)) {
342
- const sceneObj = {
343
- id: sceneId,
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
- account.ataDevices = handleDevices(devicesInMelCloudByType.ata, account.ataDevices, "Air Conditioner", newInMelCloud.ata, newInMelCloud.ataPresets, newInMelCloud.ataSchedules, newInMelCloud.scenes);
364
- account.atwDevices = handleDevices(devicesInMelCloudByType.atw, account.atwDevices, "Heat Pump", newInMelCloud.atw, newInMelCloud.atwPresets, newInMelCloud.atwSchedules, newInMelCloud.scenes);
365
- account.ervDevices = handleDevices(devicesInMelCloudByType.erv, account.ervDevices, "Energy Recovery Ventilation", newInMelCloud.erv, newInMelCloud.ervPresets, newInMelCloud.ervSchedules, newInMelCloud.scenes);
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.scenes.length;
371
- const removedDevicesCount = removedAta.length + removedAtw.length + removedErv.length;
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},` : ''} ${newInMelCloud.atw.length ? `ATW: ${newInMelCloud.atw.length},` : ''} ${newInMelCloud.erv.length ? `ERV: ${newInMelCloud.erv.length},` : ''}.`, 'green');
378
- if (newPresetsCount)
379
- updateInfo('info1', `Found new presets: ${newInMelCloud.ataPresets.length ? `ATA: ${newInMelCloud.ataPresets.length},` : ''} ${newInMelCloud.atwPresets.length ? `ATW: ${newInMelCloud.atwPresets.length},` : ''} ${newInMelCloud.ervPresets.length ? `ERV: ${newInMelCloud.ervPresets.length}` : ''}.`, 'green');
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 deviceExistInMelCloud = melcloudDevicesList.Devices.some(dev => dev.DeviceID === device.id);
141
- if (!deviceExistInMelCloud) {
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.5",
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.32.1",
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
- BaseURL: "https://app.melcloud.com/Mitsubishi.Wifi.Client",
6
- ClientLogin: "/Login/ClientLogin",
7
- GetUserDetails: "/User/GetUserDetails",
8
- ListDevices: "/User/ListDevices",
9
- ListDeviceUnits: "/Device/ListDeviceUnits",
10
- DeviceState: "/Device/Get?id=DID&buildingID=BID",
11
- TileState: "/Tile/Get2?id=DID&buildingID=BID",
12
- SetAta: "/Device/SetAta",
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
- DeleteSchedule: "/api/cloudschedule/deviceid/scheduleid",
39
- Referers: {
40
- GetPutScenes: "https://melcloudhome.com/scenes",
41
- PostHolidayMode: "https://melcloudhome.com/ata/deviceid/holidaymode",
42
- PostProtectionFrost: "https://melcloudhome.com/ata/deviceid/frostprotection",
43
- PostProtectionOverheat: "https://melcloudhome.com/ata/deviceid/overheatprotection",
44
- PutDeviceSettings: "https://melcloudhome.com/dashboard",
45
- PutScheduleEnabled: "https://melcloudhome.com/ata/deviceid/schedule",
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
- Origin: "https://melcloudhome.com",
48
- WebSocketURL: "wss://ws.melcloudhome.com/?hash="
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