homebridge-melcloud-control 3.9.0-beta.11 → 3.9.0-beta.13

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.
@@ -43,6 +43,14 @@
43
43
  const tabs = document.getElementById("accountTabs");
44
44
  const content = document.getElementById("accountTabsContent");
45
45
 
46
+ function updateConfigButtonState(account, configButton) {
47
+ const hasMultipleDevices =
48
+ (account.ataDevices?.length || 0) > 1 ||
49
+ (account.atwDevices?.length || 0) > 1 ||
50
+ (account.ervDevices?.length || 0) > 1;
51
+ configButton.disabled = !hasMultipleDevices;
52
+ }
53
+
46
54
  function createAccountForm(account, i) {
47
55
  // Tab header
48
56
  const li = document.createElement("li");
@@ -101,12 +109,19 @@
101
109
  <option value="19" ${account.language == 19 ? 'selected' : ''}>Türkçe</option>
102
110
  </select>
103
111
  </div>
104
- <button type="button" class="btn btn-secondary" id="logIn-${i}">Connect</button>
105
- <button type="button" class="btn btn-danger ms-2" id="remove-${i}">❌ Remove Account</button>
106
- <button type="button" class="btn btn-primary" id="configButton">⚙️ Config</button>
112
+ <div class="mb-3">
113
+ <button type="button" class="btn btn-secondary" id="logIn-${i}">Connect</button>
114
+ <button type="button" class="btn btn-danger ms-2" id="remove-${i}">❌ Remove Account</button>
115
+ <button type="button" class="btn btn-primary ms-2" id="config-${i}" disabled>⚙️ Config</button>
116
+ </div>
107
117
  </form>`;
108
118
  content.appendChild(pane);
109
119
 
120
+ const configButton = document.getElementById(`config-${i}`);
121
+
122
+ // Enable config button if devices > 1
123
+ updateConfigButtonState(account, configButton);
124
+
110
125
  // Handle input updates
111
126
  pane.querySelector("form").addEventListener("input", async () => {
112
127
  account.name = document.getElementById(`name-${i}`).value;
@@ -124,45 +139,11 @@
124
139
  accounts.splice(i, 1);
125
140
  document.getElementById(`tab-li-${i}`).remove();
126
141
  document.getElementById(`pane-${i}`).remove();
127
-
128
- // Rebuild IDs
129
- const panes = document.querySelectorAll(".tab-pane");
130
- panes.forEach((p, index) => {
131
- p.id = `pane-${index}`;
132
- p.querySelector("form").id = `configForm-${index}`;
133
- p.querySelector(`[id^="name-"]`).id = `name-${index}`;
134
- p.querySelector(`[id^="user-"]`).id = `user-${index}`;
135
- p.querySelector(`[id^="passwd-"]`).id = `passwd-${index}`;
136
- p.querySelector(`[id^="language-"]`).id = `language-${index}`;
137
- p.querySelector(`[id^="logIn-"]`).id = `logIn-${index}`;
138
- p.querySelector(`[id^="remove-"]`).id = `remove-${index}`;
139
- });
140
- const tabButtons = document.querySelectorAll(".nav-link");
141
- tabButtons.forEach((btn, idx) => {
142
- btn.id = `tab-${idx}`;
143
- btn.dataset.bsTarget = `#pane-${idx}`;
144
- });
145
-
146
142
  await homebridge.updatePluginConfig(pluginConfig);
147
143
  await homebridge.savePluginConfig(pluginConfig);
148
-
149
144
  if (accounts.length > 0) new bootstrap.Tab(document.getElementById("tab-0")).show();
150
145
  });
151
146
 
152
- document.getElementById('configButton').addEventListener('click', async () => {
153
- if (this.configButtonState) {
154
- homebridge.hideSchemaForm();
155
- document.getElementById('configButton').className = "btn btn-secondary";
156
- } else {
157
- homebridge.showSchemaForm();
158
- document.getElementById('configButton').className = "btn btn-primary";
159
- }
160
- this.configButtonState = !this.configButtonState;
161
- });
162
-
163
- // Initialize state
164
- this.configButtonState = false;
165
-
166
147
  // Login button
167
148
  document.getElementById(`logIn-${i}`).addEventListener("click", async () => {
168
149
  homebridge.showSpinner();
@@ -175,7 +156,6 @@
175
156
  language: account.language
176
157
  });
177
158
 
178
- const newDevices = { ata: [], ataPresets: [], atw: [], atwPresets: [], erv: [], ervPresets: [] };
179
159
  const devicesByType = { ata: [], atw: [], erv: [] };
180
160
  for (const d of devicesInMelCloud) {
181
161
  if (d.Type === 0) devicesByType.ata.push(d);
@@ -183,72 +163,39 @@
183
163
  if (d.Type === 3) devicesByType.erv.push(d);
184
164
  }
185
165
 
186
- // Remove stale function
166
+ // Initialize device arrays if missing
167
+ account.ataDevices = account.ataDevices ?? [{}];
168
+ account.atwDevices = account.atwDevices ?? [{}];
169
+ account.ervDevices = account.ervDevices ?? [{}];
170
+
171
+ // Remove stale devices
187
172
  function removeStaleDevices(configDevices, melcloudDevices) {
188
173
  const melcloudIds = melcloudDevices.map(d => d.DeviceID);
189
- const removed = [];
190
174
  for (let j = configDevices.length - 1; j >= 0; j--) {
191
175
  const dev = configDevices[j];
192
- if (dev.id !== 0 && !melcloudIds.includes(dev.id)) {
193
- removed.push(dev);
194
- configDevices.splice(j, 1);
195
- }
176
+ if (dev.id !== 0 && !melcloudIds.includes(dev.id)) configDevices.splice(j, 1);
196
177
  }
197
- return removed;
198
178
  }
199
179
 
200
- const ataDevices = account.ataDevices ?? (account.ataDevices = []);
201
- const atwDevices = account.atwDevices ?? (account.atwDevices = []);
202
- const ervDevices = account.ervDevices ?? (account.ervDevices = []);
180
+ removeStaleDevices(account.ataDevices, devicesByType.ata);
181
+ removeStaleDevices(account.atwDevices, devicesByType.atw);
182
+ removeStaleDevices(account.ervDevices, devicesByType.erv);
203
183
 
204
- const removedAta = removeStaleDevices(ataDevices, devicesByType.ata);
205
- const removedAtw = removeStaleDevices(atwDevices, devicesByType.atw);
206
- const removedErv = removeStaleDevices(ervDevices, devicesByType.erv);
207
-
208
- // Add new devices & presets
209
- function handleDevices(configArray, devicesArray, typeName, newDevicesArr, newPresetsArr) {
184
+ // Add new devices
185
+ function addDevices(configArray, devicesArray) {
210
186
  devicesArray.forEach(d => {
211
- const existing = configArray.find(x => x.id === d.DeviceID);
212
- if (!existing) {
213
- const devObj = {
214
- id: d.DeviceID,
215
- type: d.Type,
216
- typeString: typeName,
217
- name: d.DeviceName,
218
- displayMode: 1,
219
- presets: [],
220
- buttonsSensors: []
221
- };
222
- configArray.push(devObj);
223
- newDevicesArr.push(devObj);
187
+ if (!configArray.find(x => x.id === d.DeviceID)) {
188
+ configArray.push({ id: d.DeviceID, type: d.Type, name: d.DeviceName });
224
189
  }
225
- (d.Presets || []).forEach(p => {
226
- const preset = { ...p, id: p.ID, name: p.NumberDescription, displayType: 0, namePrefix: false };
227
- if (!existing?.presets.some(pr => pr.id === p.ID)) {
228
- existing?.presets.push(preset);
229
- newPresetsArr.push(preset);
230
- }
231
- });
232
190
  });
233
191
  }
234
192
 
235
- handleDevices(ataDevices, devicesByType.ata, "Air Conditioner", newDevices.ata, newDevices.ataPresets);
236
- handleDevices(atwDevices, devicesByType.atw, "Heat Pump", newDevices.atw, newDevices.atwPresets);
237
- handleDevices(ervDevices, devicesByType.erv, "ERV", newDevices.erv, newDevices.ervPresets);
238
-
239
- // Info display
240
- function updateInfo(id, text, color) {
241
- const el = document.getElementById(id);
242
- if (el) { el.innerHTML = text; el.style.color = color; }
243
- }
244
-
245
- const textInfo = `Found devices: ATA(${newDevices.ata.length}), ATW(${newDevices.atw.length}), ERV(${newDevices.erv.length})`;
246
- const textPresets = `Found presets: ATA(${newDevices.ataPresets.length}), ATW(${newDevices.atwPresets.length}), ERV(${newDevices.ervPresets.length})`;
247
- const textRemoved = `Removed devices: ATA(${removedAta.length}), ATW(${removedAtw.length}), ERV(${removedErv.length})`;
193
+ addDevices(account.ataDevices, devicesByType.ata);
194
+ addDevices(account.atwDevices, devicesByType.atw);
195
+ addDevices(account.ervDevices, devicesByType.erv);
248
196
 
249
- updateInfo('info', textInfo, newDevices.ata.length + newDevices.atw.length + newDevices.erv.length > 0 ? 'green' : 'white');
250
- updateInfo('info1', textPresets, newDevices.ataPresets.length + newDevices.atwPresets.length + newDevices.ervPresets.length > 0 ? 'green' : 'white');
251
- updateInfo('info2', textRemoved, removedAta.length + removedAtw.length + removedErv.length > 0 ? 'orange' : 'white');
197
+ // Update Config button state
198
+ updateConfigButtonState(account, configButton);
252
199
 
253
200
  await homebridge.updatePluginConfig(pluginConfig);
254
201
  await homebridge.savePluginConfig(pluginConfig);
@@ -258,6 +205,15 @@
258
205
  homebridge.hideSpinner();
259
206
  }
260
207
  });
208
+
209
+ // Config button click
210
+ configButton.addEventListener('click', () => {
211
+ if (configButton.classList.contains('btn-primary')) {
212
+ homebridge.showSchemaForm();
213
+ } else {
214
+ homebridge.hideSchemaForm();
215
+ }
216
+ });
261
217
  }
262
218
 
263
219
  // Render accounts
@@ -270,7 +226,7 @@
270
226
  tabs.appendChild(addLi);
271
227
 
272
228
  document.getElementById("addTab").addEventListener("click", async () => {
273
- const newAccount = { name: "", user: "", passwd: "", language: 0 };
229
+ const newAccount = { name: "", user: "", passwd: "", language: 0, ataDevices: [{}], atwDevices: [{}], ervDevices: [{}] };
274
230
  accounts.push(newAccount);
275
231
  const i = accounts.length - 1;
276
232
  createAccountForm(newAccount, i);
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.11",
4
+ "version": "3.9.0-beta.13",
5
5
  "description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
6
6
  "license": "MIT",
7
7
  "author": "grzegorz914",