homebridge-melcloud-control 3.9.0-beta.5 → 3.9.0-beta.7

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.
@@ -20,9 +20,9 @@
20
20
  <form id="configForm">
21
21
  <div class="text-center">
22
22
  <label id="accountName" class="fw-bold" style="font-size: 23px;">Account</label><br>
23
- <label id="info" class="d-block" style="font-size: 17px;"></label>
24
- <label id="info1" class="d-block" style="font-size: 15px;"></label>
25
- <label id="info2" class="d-block" style="font-size: 15px;"></label>
23
+ <label id="info" class="d-block" style="font-size: 16px;"></label>
24
+ <label id="info1" class="d-block" style="font-size: 14px;"></label>
25
+ <label id="info2" class="d-block" style="font-size: 14px;"></label>
26
26
  </div>
27
27
 
28
28
  <div class="mb-3">
@@ -83,9 +83,7 @@
83
83
 
84
84
  <script>
85
85
  (async () => {
86
- //get the plugin config array
87
86
  const pluginConfig = await homebridge.getPluginConfig();
88
-
89
87
  if (!pluginConfig.length) {
90
88
  pluginConfig.push({});
91
89
  await homebridge.updatePluginConfig(pluginConfig);
@@ -94,11 +92,9 @@
94
92
  }
95
93
  this.configButtonState = false;
96
94
 
97
- //get accounts count
98
95
  const accountsCount = pluginConfig[0].accounts.length;
99
96
  this.deviceIndex = 0;
100
97
  for (let i = 0; i < accountsCount; i++) {
101
- //create buttons
102
98
  const button = document.createElement("button");
103
99
  button.setAttribute("type", "button");
104
100
  button.setAttribute("id", `button${i}`);
@@ -107,10 +103,11 @@
107
103
  button.innerText = pluginConfig[0].accounts[i].name;
108
104
  document.getElementById("accountButton").appendChild(button);
109
105
 
110
- //get actuall value on account select
111
106
  document.getElementById(`button${i}`).addEventListener('click', async () => {
112
107
  for (let j = 0; j < accountsCount; j++) {
113
- const setRemoveAtribute = j === i ? document.getElementById(`button${j}`).setAttribute("class", "btn btn-secondary") : document.getElementById(`button${j}`).setAttribute("class", "btn btn-primary");
108
+ j === i
109
+ ? document.getElementById(`button${j}`).setAttribute("class", "btn btn-secondary")
110
+ : document.getElementById(`button${j}`).setAttribute("class", "btn btn-primary");
114
111
  }
115
112
 
116
113
  document.getElementById('accountName').innerHTML = pluginConfig[0].accounts[i].name || '';
@@ -120,20 +117,19 @@
120
117
  document.getElementById('language').value = pluginConfig[0].accounts[i].language || '';
121
118
 
122
119
  const accountConfigured = pluginConfig[0].accounts[i].name && pluginConfig[0].accounts[i].user && pluginConfig[0].accounts[i].passwd && pluginConfig[0].accounts[i].language;
123
- const button = document.getElementById('logIn');
124
- const setButtonState = accountConfigured ? button.disabled = false : button.disabled = true;
120
+ document.getElementById('logIn').disabled = !accountConfigured;
125
121
 
126
122
  await homebridge.updatePluginConfig(pluginConfig);
127
123
  this.deviceIndex = i;
128
124
  });
129
- const click = i === accountsCount - 1 ? document.getElementById(`button0`).click() : false;
130
- const update = i === accountsCount - 1 ? await homebridge.updatePluginConfig(pluginConfig) : false;
131
- };
125
+ if (i === accountsCount - 1) {
126
+ document.getElementById(`button0`).click();
127
+ await homebridge.updatePluginConfig(pluginConfig);
128
+ }
129
+ }
132
130
 
133
- //load melCloudAccount form
134
131
  document.getElementById('melCloudAccount').style.display = 'block';
135
132
 
136
- //watch for changes to the form
137
133
  document.getElementById('configForm').addEventListener('input', async () => {
138
134
  pluginConfig[0].accounts[this.deviceIndex].name = document.querySelector('#name').value;
139
135
  pluginConfig[0].accounts[this.deviceIndex].user = document.querySelector('#user').value;
@@ -141,58 +137,55 @@
141
137
  pluginConfig[0].accounts[this.deviceIndex].language = document.querySelector('#language').value;
142
138
 
143
139
  const accountConfigured = pluginConfig[0].accounts[this.deviceIndex].name && pluginConfig[0].accounts[this.deviceIndex].user && pluginConfig[0].accounts[this.deviceIndex].passwd && pluginConfig[0].accounts[this.deviceIndex].language;
144
- const button = document.getElementById('logIn');
145
- const setButtonState = accountConfigured ? button.disabled = false : button.disabled = true;
140
+ document.getElementById('logIn').disabled = !accountConfigured;
146
141
 
147
142
  await homebridge.updatePluginConfig(pluginConfig);
148
143
  await homebridge.savePluginConfig(pluginConfig);
149
144
  });
150
145
 
151
- //watch for changes to the config button
152
146
  document.getElementById('configButton').addEventListener('click', async () => {
153
- const showHideSettings = this.configButtonState ? homebridge.hideSchemaForm() : homebridge.showSchemaForm();
154
- const setRemoveAtribute = this.configButtonState ? document.getElementById(`configButton`).setAttribute("class", "btn btn-secondary") : document.getElementById(`configButton`).setAttribute("class", "btn btn-primary");
147
+ this.configButtonState ? homebridge.hideSchemaForm() : homebridge.showSchemaForm();
148
+ this.configButtonState
149
+ ? document.getElementById(`configButton`).setAttribute("class", "btn btn-secondary")
150
+ : document.getElementById(`configButton`).setAttribute("class", "btn btn-primary");
155
151
  this.configButtonState = !this.configButtonState;
156
152
  });
157
153
 
158
- // Helper to remove stale devices by comparing with MELCloud
159
154
  function removeStaleDevices(configDevices, melcloudDevices) {
160
155
  const melcloudIds = melcloudDevices.map(d => d.DeviceID);
156
+ const removedDevices = [];
161
157
  for (let i = configDevices.length - 1; i >= 0; i--) {
162
158
  const device = configDevices[i];
163
159
  if (device.id !== 0 && !melcloudIds.includes(device.id)) {
160
+ removedDevices.push(device);
164
161
  configDevices.splice(i, 1);
165
162
  }
166
163
  }
164
+ return removedDevices;
165
+ }
166
+
167
+ function updateInfo(id, text, color) {
168
+ const el = document.getElementById(id);
169
+ if (el) {
170
+ el.innerHTML = text;
171
+ el.style.color = color;
172
+ }
167
173
  }
168
174
 
169
- //watch for click on the login button
170
175
  document.getElementById('logIn').addEventListener('click', async () => {
171
176
  homebridge.showSpinner();
172
-
173
177
  document.getElementById(`logIn`).setAttribute("class", "btn btn-primary");
174
- document.getElementById('info').innerHTML = 'Connecting...';
175
- document.getElementById('info').style.color = 'yellow';
178
+ updateInfo('info', 'Connecting...', 'yellow');
176
179
 
177
180
  try {
178
181
  const account = pluginConfig[0].accounts[this.deviceIndex];
179
182
  const { name: accountName, user, passwd, language } = account;
180
-
181
183
  const payload = { accountName, user, passwd, language };
182
184
  const devicesInMelCloud = await homebridge.request('/connect', payload);
183
185
 
184
- const newDevices = {
185
- ata: [],
186
- ataPresets: [],
187
- atw: [],
188
- atwPresets: [],
189
- erv: [],
190
- ervPresets: [],
191
- };
192
-
186
+ const newDevices = { ata: [], ataPresets: [], atw: [], atwPresets: [], erv: [], ervPresets: [] };
193
187
  const devicesByTypeInMelCloud = { ata: [], atw: [], erv: [] };
194
188
 
195
- // Categorize devices by type
196
189
  for (const deviceInMelcloud of devicesInMelCloud) {
197
190
  switch (deviceInMelcloud.Type) {
198
191
  case 0: devicesByTypeInMelCloud.ata.push(deviceInMelcloud); break;
@@ -201,27 +194,16 @@
201
194
  }
202
195
  }
203
196
 
204
- // Ensure config arrays exist
205
197
  const ataDevicesInConfig = account.ataDevices ?? (account.ataDevices = []);
206
198
  const atwDevicesInConfig = account.atwDevices ?? (account.atwDevices = []);
207
199
  const ervDevicesInConfig = account.ervDevices ?? (account.ervDevices = []);
208
200
 
209
- // Remove stale devices
210
- removeStaleDevices(ataDevicesInConfig, devicesByTypeInMelCloud.ata);
211
- removeStaleDevices(atwDevicesInConfig, devicesByTypeInMelCloud.atw);
212
- removeStaleDevices(ervDevicesInConfig, devicesByTypeInMelCloud.erv);
213
-
214
- // Helper for updating UI
215
- const updateInfo = (id, text, color) => {
216
- const el = document.getElementById(id);
217
- if (el) {
218
- el.innerHTML = text;
219
- el.style.color = color;
220
- }
221
- };
201
+ const removedAta = removeStaleDevices(ataDevicesInConfig, devicesByTypeInMelCloud.ata);
202
+ const removedAtw = removeStaleDevices(atwDevicesInConfig, devicesByTypeInMelCloud.atw);
203
+ const removedErv = removeStaleDevices(ervDevicesInConfig, devicesByTypeInMelCloud.erv);
222
204
 
223
- // Handle ATA devices
224
- devicesByTypeInMelCloud.ata.forEach((device) => {
205
+ // === Handle ATA devices ===
206
+ devicesByTypeInMelCloud.ata.forEach(device => {
225
207
  const { DeviceID: deviceId, Type: deviceType, DeviceName: deviceName, Presets: devicePresets = [] } = device;
226
208
  const deviceAta = {
227
209
  id: deviceId,
@@ -237,29 +219,26 @@
237
219
  presets: [],
238
220
  buttonsSensors: []
239
221
  };
240
-
241
- if (!ataDevicesInConfig.some(device => device.id === deviceId)) {
222
+ if (!ataDevicesInConfig.some(d => d.id === deviceId)) {
242
223
  ataDevicesInConfig.push(deviceAta);
243
224
  newDevices.ata.push(deviceAta);
244
225
  }
245
-
246
- devicePresets.forEach((preset) => {
226
+ devicePresets.forEach(preset => {
247
227
  const { ID: presetId, NumberDescription: presetName } = preset;
248
228
  preset.id = presetId;
249
229
  preset.name = presetName;
250
230
  preset.displayType = 0;
251
231
  preset.namePrefix = false;
252
-
253
- const ataDevice = ataDevicesInConfig.find((device) => device.id === deviceId);
254
- if (ataDevice && !ataDevice.presets.some((p) => p.id === presetId)) {
232
+ const ataDevice = ataDevicesInConfig.find(d => d.id === deviceId);
233
+ if (ataDevice && !ataDevice.presets.some(p => p.id === presetId)) {
255
234
  ataDevice.presets.push(preset);
256
235
  newDevices.ataPresets.push(preset);
257
236
  }
258
237
  });
259
238
  });
260
239
 
261
- // Handle ATW devices
262
- devicesByTypeInMelCloud.atw.forEach((device) => {
240
+ // === Handle ATW devices ===
241
+ devicesByTypeInMelCloud.atw.forEach(device => {
263
242
  const { DeviceID: deviceId, Type: deviceType, DeviceName: deviceName, Presets: devicePresets = [] } = device;
264
243
  const deviceAtw = {
265
244
  id: deviceId,
@@ -269,107 +248,89 @@
269
248
  displayMode: 1,
270
249
  hideZone: 0,
271
250
  temperatureSensor: false,
272
- temperatureSensorFlow: false,
273
- temperatureSensorReturn: false,
274
- temperatureSensorFlowZone1: false,
275
- temperatureSensorReturnZone1: false,
276
- temperatureSensorFlowWaterTank: false,
277
- temperatureSensorReturnWaterTank: false,
278
- temperatureSensorFlowZone2: false,
279
- temperatureSensorReturnZone2: false,
280
- temperatureSensorOutdoor: false,
281
251
  presets: [],
282
252
  buttonsSensors: []
283
253
  };
284
-
285
- if (!atwDevicesInConfig.some(device => device.id === deviceId)) {
254
+ if (!atwDevicesInConfig.some(d => d.id === deviceId)) {
286
255
  atwDevicesInConfig.push(deviceAtw);
287
256
  newDevices.atw.push(deviceAtw);
288
257
  }
289
-
290
- devicePresets.forEach((preset) => {
258
+ devicePresets.forEach(preset => {
291
259
  const { ID: presetId, NumberDescription: presetName } = preset;
292
260
  preset.id = presetId;
293
261
  preset.name = presetName;
294
262
  preset.displayType = 0;
295
263
  preset.namePrefix = false;
296
-
297
- const atwDevice = atwDevicesInConfig.find((device) => device.id === deviceId);
298
- if (atwDevice && !atwDevice.presets.some((p) => p.id === presetId)) {
264
+ const atwDevice = atwDevicesInConfig.find(d => d.id === deviceId);
265
+ if (atwDevice && !atwDevice.presets.some(p => p.id === presetId)) {
299
266
  atwDevice.presets.push(preset);
300
267
  newDevices.atwPresets.push(preset);
301
268
  }
302
269
  });
303
270
  });
304
271
 
305
- // Handle ERV devices
306
- devicesByTypeInMelCloud.erv.forEach((device) => {
272
+ // === Handle ERV devices ===
273
+ devicesByTypeInMelCloud.erv.forEach(device => {
307
274
  const { DeviceID: deviceId, Type: deviceType, DeviceName: deviceName, Presets: devicePresets = [] } = device;
308
275
  const deviceErv = {
309
276
  id: deviceId,
310
277
  type: deviceType,
311
- typeString: "Energy Recovery Ventilation",
278
+ typeString: "ERV",
312
279
  name: deviceName,
313
280
  displayMode: 1,
314
281
  temperatureSensor: false,
315
- temperatureSensorOutdoor: false,
316
- temperatureSensorSupply: false,
317
282
  presets: [],
318
283
  buttonsSensors: []
319
284
  };
320
-
321
- if (!ervDevicesInConfig.some(device => device.id === deviceId)) {
285
+ if (!ervDevicesInConfig.some(d => d.id === deviceId)) {
322
286
  ervDevicesInConfig.push(deviceErv);
323
287
  newDevices.erv.push(deviceErv);
324
288
  }
325
-
326
- devicePresets.forEach((preset) => {
289
+ devicePresets.forEach(preset => {
327
290
  const { ID: presetId, NumberDescription: presetName } = preset;
328
291
  preset.id = presetId;
329
292
  preset.name = presetName;
330
293
  preset.displayType = 0;
331
294
  preset.namePrefix = false;
332
-
333
- const ervDevice = ervDevicesInConfig.find((device) => device.id === deviceId);
334
- if (ervDevice && !ervDevice.presets.some((p) => p.id === presetId)) {
295
+ const ervDevice = ervDevicesInConfig.find(d => d.id === deviceId);
296
+ if (ervDevice && !ervDevice.presets.some(p => p.id === presetId)) {
335
297
  ervDevice.presets.push(preset);
336
298
  newDevices.ervPresets.push(preset);
337
299
  }
338
300
  });
339
301
  });
340
302
 
341
- // Display info
303
+ // --- Display Info Section ---
342
304
  const textAta = `ATA: ${newDevices.ata.length}`;
343
305
  const textAtw = `ATW: ${newDevices.atw.length}`;
344
306
  const textErv = `ERV: ${newDevices.erv.length}`;
345
307
  const textAtaPresets = `ATA Presets: ${newDevices.ataPresets.length}`;
346
308
  const textAtwPresets = `ATW Presets: ${newDevices.atwPresets.length}`;
347
309
  const textErvPresets = `ERV Presets: ${newDevices.ervPresets.length}`;
310
+ const textRemovedAta = `ATA: ${removedAta.length}`;
311
+ const textRemovedAtw = `ATW: ${removedAtw.length}`;
312
+ const textRemovedErv = `ERV: ${removedErv.length}`;
348
313
 
349
314
  const newDevicesCount = newDevices.ata.length + newDevices.atw.length + newDevices.erv.length;
350
315
  const newPresetsCount = newDevices.ataPresets.length + newDevices.atwPresets.length + newDevices.ervPresets.length;
316
+ const removedCount = removedAta.length + removedAtw.length + removedErv.length;
351
317
 
352
- if (newDevicesCount === 0 && newPresetsCount === 0) {
353
- updateInfo('info', 'No new devices found.', 'white');
318
+ if (newDevicesCount === 0 && newPresetsCount === 0 && removedCount === 0) {
319
+ updateInfo('info', 'No changes detected.', 'white');
354
320
  } else {
355
321
  if (newDevicesCount > 0) {
356
- updateInfo('info', `Found, ${textAta}, ${textAtw}, ${textErv}.`, 'green');
357
- updateInfo('info2', 'Now You can configure it.', 'green');
322
+ updateInfo('info', `Found new devices: ${textAta}, ${textAtw}, ${textErv}.`, 'green');
358
323
  }
359
324
  if (newPresetsCount > 0) {
360
- updateInfo('info1', `${textAtaPresets}, ${textAtwPresets}, ${textErvPresets}.`, 'green');
361
- if (newDevicesCount === 0) {
362
- updateInfo('info', `Found, ${textAtaPresets}, ${textAtwPresets}, ${textErvPresets}.`, 'green');
363
- updateInfo('info1', 'Now You can configure it.', 'green');
364
- }
325
+ updateInfo('info1', `Found new presets: ${textAtaPresets}, ${textAtwPresets}, ${textErvPresets}.`, 'green');
326
+ }
327
+ if (removedCount > 0) {
328
+ updateInfo('info2', `Removed devices: ${textRemovedAta}, ${textRemovedAtw}, ${textRemovedErv}.`, 'orange');
365
329
  }
366
330
  }
367
331
 
368
- // Save updated config
369
332
  await homebridge.updatePluginConfig(pluginConfig);
370
333
  await homebridge.savePluginConfig(pluginConfig);
371
-
372
- // Update button
373
334
  document.getElementById('logIn').setAttribute('class', 'btn btn-secondary');
374
335
  homebridge.hideSpinner();
375
336
 
@@ -380,7 +341,6 @@
380
341
  } finally {
381
342
  homebridge.hideSpinner();
382
343
  }
383
-
384
344
  });
385
345
  })();
386
346
  </script>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "displayName": "MELCloud Control",
3
3
  "name": "homebridge-melcloud-control",
4
- "version": "3.9.0-beta.5",
4
+ "version": "3.9.0-beta.7",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",