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