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.
- package/homebridge-ui/public/index.html +47 -91
- package/package.json +1 -1
|
@@ -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
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
180
|
+
removeStaleDevices(account.ataDevices, devicesByType.ata);
|
|
181
|
+
removeStaleDevices(account.atwDevices, devicesByType.atw);
|
|
182
|
+
removeStaleDevices(account.ervDevices, devicesByType.erv);
|
|
203
183
|
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
212
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
250
|
-
|
|
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.
|
|
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",
|