homebridge-melcloud-control 3.7.3-beta.0 → 3.7.3-beta.2
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 +396 -376
- package/package.json +1 -1
|
@@ -1,401 +1,421 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>MELCloud Account Configuration</title>
|
|
8
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/css/bootstrap.min.css">
|
|
9
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/js/all.min.js"></script>
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
<body>
|
|
13
|
+
|
|
14
|
+
<div class="container mt-4">
|
|
15
|
+
<div class="text-center">
|
|
16
|
+
<img src="homebridge-melcloud-control.png" alt="Image" height="120" />
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div id="melCloudAccount" class="card card-body mt-3">
|
|
20
|
+
<form id="configForm">
|
|
21
|
+
<div class="text-center">
|
|
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>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="mb-3">
|
|
29
|
+
<label for="name" class="form-label">Name</label>
|
|
30
|
+
<input id="name" type="text" class="form-control" required>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div class="mb-3">
|
|
34
|
+
<label for="user" class="form-label">User Name</label>
|
|
35
|
+
<input id="user" type="text" class="form-control" required>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="mb-3">
|
|
39
|
+
<label for="passwd" class="form-label">Password</label>
|
|
40
|
+
<input id="passwd" type="password" class="form-control" autocomplete="off" required>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div class="mb-3">
|
|
44
|
+
<label for="language" class="form-label">Language</label>
|
|
45
|
+
<select id="language" name="language" class="form-control">
|
|
46
|
+
<option value="0">English</option>
|
|
47
|
+
<option value="1">Български</option>
|
|
48
|
+
<option value="2">Čeština</option>
|
|
49
|
+
<option value="3">Dansk</option>
|
|
50
|
+
<option value="4">Deutsch</option>
|
|
51
|
+
<option value="5">Eesti</option>
|
|
52
|
+
<option value="6">Español</option>
|
|
53
|
+
<option value="7">Français</option>
|
|
54
|
+
<option value="8">Հայերեն</option>
|
|
55
|
+
<option value="9">Latviešu</option>
|
|
56
|
+
<option value="10">Lietuvių</option>
|
|
57
|
+
<option value="11">Magyar</option>
|
|
58
|
+
<option value="12">Nederlands</option>
|
|
59
|
+
<option value="13">Norwegian</option>
|
|
60
|
+
<option value="14">Polski</option>
|
|
61
|
+
<option value="15">Português</option>
|
|
62
|
+
<option value="16">Русский</option>
|
|
63
|
+
<option value="17">Suomi</option>
|
|
64
|
+
<option value="18">Svenska</option>
|
|
65
|
+
<option value="19">Українська</option>
|
|
66
|
+
<option value="20">Türkçe</option>
|
|
67
|
+
<option value="21">Ελληνικά</option>
|
|
68
|
+
<option value="22">Hrvatski</option>
|
|
69
|
+
<option value="23">Română</option>
|
|
70
|
+
<option value="24">Slovenščina</option>
|
|
71
|
+
</select>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="text-center">
|
|
75
|
+
<button id="logIn" type="button" class="btn btn-secondary">Connect to MELCloud</button>
|
|
76
|
+
<button id="configButton" type="button" class="btn btn-secondary"><i class="fas fa-gear"></i></button>
|
|
77
|
+
</div>
|
|
78
|
+
</form>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div id="accountButton" class="mt-3"></div>
|
|
4
82
|
</div>
|
|
5
83
|
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
<option value="24">Slovenščina</option>
|
|
58
|
-
</select>
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<div class="text-center">
|
|
62
|
-
<button id="logIn" type="button" class="btn btn-primary">Connect to MELCloud</button>
|
|
63
|
-
<button id="configButton" type="button" class="btn btn-dark"><i class="fas fa-gear"></i></button>
|
|
64
|
-
</div>
|
|
65
|
-
</form>
|
|
66
|
-
</div>
|
|
84
|
+
<script>
|
|
85
|
+
(async () => {
|
|
86
|
+
//get the plugin config array
|
|
87
|
+
const pluginConfig = await homebridge.getPluginConfig();
|
|
88
|
+
|
|
89
|
+
if (!pluginConfig.length) {
|
|
90
|
+
pluginConfig.push({});
|
|
91
|
+
await homebridge.updatePluginConfig(pluginConfig);
|
|
92
|
+
homebridge.showSchemaForm();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.configButtonState = false;
|
|
96
|
+
|
|
97
|
+
//get accounts count
|
|
98
|
+
const accountsCount = pluginConfig[0].accounts.length;
|
|
99
|
+
this.deviceIndex = 0;
|
|
100
|
+
for (let i = 0; i < accountsCount; i++) {
|
|
101
|
+
//create buttons
|
|
102
|
+
const button = document.createElement("button");
|
|
103
|
+
button.setAttribute("type", "button");
|
|
104
|
+
button.setAttribute("id", `button${i}`);
|
|
105
|
+
button.setAttribute("class", "btn btn-primary");
|
|
106
|
+
button.style.textTransform = 'none';
|
|
107
|
+
button.innerText = pluginConfig[0].accounts[i].name;
|
|
108
|
+
document.getElementById("accountButton").appendChild(button);
|
|
109
|
+
|
|
110
|
+
//get actuall value on account select
|
|
111
|
+
document.getElementById(`button${i}`).addEventListener('click', async () => {
|
|
112
|
+
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");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
document.getElementById('accountName').innerHTML = pluginConfig[0].accounts[i].name || '';
|
|
117
|
+
document.getElementById('name').value = pluginConfig[0].accounts[i].name || '';
|
|
118
|
+
document.getElementById('user').value = pluginConfig[0].accounts[i].user || '';
|
|
119
|
+
document.getElementById('passwd').value = pluginConfig[0].accounts[i].passwd || '';
|
|
120
|
+
document.getElementById('language').value = pluginConfig[0].accounts[i].language || '';
|
|
121
|
+
|
|
122
|
+
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;
|
|
125
|
+
|
|
126
|
+
await homebridge.updatePluginConfig(pluginConfig);
|
|
127
|
+
this.deviceIndex = i;
|
|
128
|
+
});
|
|
129
|
+
const click = i === accountsCount - 1 ? document.getElementById(`button0`).click() : false;
|
|
130
|
+
const update = i === accountsCount - 1 ? await homebridge.updatePluginConfig(pluginConfig) : false;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
//load melCloudAccount form
|
|
134
|
+
document.getElementById('melCloudAccount').style.display = 'block';
|
|
67
135
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (!pluginConfig.length) {
|
|
77
|
-
pluginConfig.push({});
|
|
78
|
-
await homebridge.updatePluginConfig(pluginConfig);
|
|
79
|
-
homebridge.showSchemaForm();
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
//get accounts count
|
|
84
|
-
const accountsCount = pluginConfig[0].accounts.length;
|
|
85
|
-
this.deviceIndex = 0;
|
|
86
|
-
for (let i = 0; i < accountsCount; i++) {
|
|
87
|
-
//create buttons
|
|
88
|
-
const button = document.createElement("button");
|
|
89
|
-
button.setAttribute("type", "button");
|
|
90
|
-
button.setAttribute("id", `button${i}`);
|
|
91
|
-
button.setAttribute("class", "btn btn-primary");
|
|
92
|
-
button.style.textTransform = 'none';
|
|
93
|
-
button.innerText = pluginConfig[0].accounts[i].name;
|
|
94
|
-
document.getElementById("accountButton").appendChild(button);
|
|
95
|
-
|
|
96
|
-
//get actuall value on account select
|
|
97
|
-
document.getElementById(`button${i}`).addEventListener('click', async () => {
|
|
98
|
-
for (let j = 0; j < accountsCount; j++) {
|
|
99
|
-
const setRemoveAtribute = j === i ? document.getElementById(`button${j}`).setAttribute("class", "btn btn-secondary") : document.getElementById(`button${j}`).setAttribute("class", "btn btn-primary");
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
document.getElementById('accountName').innerHTML = pluginConfig[0].accounts[i].name || '';
|
|
103
|
-
document.getElementById('name').value = pluginConfig[0].accounts[i].name || '';
|
|
104
|
-
document.getElementById('user').value = pluginConfig[0].accounts[i].user || '';
|
|
105
|
-
document.getElementById('passwd').value = pluginConfig[0].accounts[i].passwd || '';
|
|
106
|
-
document.getElementById('language').value = pluginConfig[0].accounts[i].language || '';
|
|
107
|
-
|
|
108
|
-
const accountConfigured = pluginConfig[0].accounts[i].name && pluginConfig[0].accounts[i].user && pluginConfig[0].accounts[i].passwd && pluginConfig[0].accounts[i].language;
|
|
136
|
+
//watch for changes to the form
|
|
137
|
+
document.getElementById('configForm').addEventListener('input', async () => {
|
|
138
|
+
pluginConfig[0].accounts[this.deviceIndex].name = document.querySelector('#name').value;
|
|
139
|
+
pluginConfig[0].accounts[this.deviceIndex].user = document.querySelector('#user').value;
|
|
140
|
+
pluginConfig[0].accounts[this.deviceIndex].passwd = document.querySelector('#passwd').value;
|
|
141
|
+
pluginConfig[0].accounts[this.deviceIndex].language = document.querySelector('#language').value;
|
|
142
|
+
|
|
143
|
+
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;
|
|
109
144
|
const button = document.getElementById('logIn');
|
|
110
145
|
const setButtonState = accountConfigured ? button.disabled = false : button.disabled = true;
|
|
111
146
|
|
|
112
147
|
await homebridge.updatePluginConfig(pluginConfig);
|
|
113
|
-
|
|
148
|
+
await homebridge.savePluginConfig(pluginConfig);
|
|
114
149
|
});
|
|
115
|
-
const click = i === accountsCount - 1 ? document.getElementById(`button0`).click() : false;
|
|
116
|
-
const update = i === accountsCount - 1 ? await homebridge.updatePluginConfig(pluginConfig) : false;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
//load melCloudAccount form
|
|
120
|
-
document.getElementById('melCloudAccount').style.display = 'block';
|
|
121
|
-
|
|
122
|
-
//watch for changes to the form
|
|
123
|
-
document.getElementById('configForm').addEventListener('input', async () => {
|
|
124
|
-
pluginConfig[0].accounts[this.deviceIndex].name = document.querySelector('#name').value;
|
|
125
|
-
pluginConfig[0].accounts[this.deviceIndex].user = document.querySelector('#user').value;
|
|
126
|
-
pluginConfig[0].accounts[this.deviceIndex].passwd = document.querySelector('#passwd').value;
|
|
127
|
-
pluginConfig[0].accounts[this.deviceIndex].language = document.querySelector('#language').value;
|
|
128
|
-
|
|
129
|
-
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;
|
|
130
|
-
const button = document.getElementById('logIn');
|
|
131
|
-
const setButtonState = accountConfigured ? button.disabled = false : button.disabled = true;
|
|
132
|
-
|
|
133
|
-
await homebridge.updatePluginConfig(pluginConfig);
|
|
134
|
-
await homebridge.savePluginConfig(pluginConfig);
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
//watch for changes to the config button
|
|
138
|
-
document.getElementById('configButton').addEventListener('click', async () => {
|
|
139
|
-
const showHideSettings = this.configButtonState ? homebridge.hideSchemaForm() : homebridge.showSchemaForm();
|
|
140
|
-
this.configButtonState = !this.configButtonState;
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
//watch for click on the login button
|
|
144
|
-
document.getElementById('logIn').addEventListener('click', async () => {
|
|
145
|
-
homebridge.showSpinner();
|
|
146
|
-
document.getElementById('info').innerHTML = 'Connecting...';
|
|
147
|
-
document.getElementById('info').style.color = 'yellow';
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
const accountName = pluginConfig[0].accounts[this.deviceIndex].name;
|
|
151
|
-
const user = pluginConfig[0].accounts[this.deviceIndex].user;
|
|
152
|
-
const passwd = pluginConfig[0].accounts[this.deviceIndex].passwd;
|
|
153
|
-
const language = pluginConfig[0].accounts[this.deviceIndex].language;
|
|
154
|
-
|
|
155
|
-
const payload = {
|
|
156
|
-
accountName: accountName,
|
|
157
|
-
user: user,
|
|
158
|
-
passwd: passwd,
|
|
159
|
-
language: language
|
|
160
|
-
};
|
|
161
|
-
const devicesInMelCloud = await homebridge.request('/connect', payload);
|
|
162
|
-
|
|
163
|
-
//new found devices
|
|
164
|
-
const newDevices = {
|
|
165
|
-
ata: [],
|
|
166
|
-
ataPresets: [],
|
|
167
|
-
atw: [],
|
|
168
|
-
atwPresets: [],
|
|
169
|
-
erv: [],
|
|
170
|
-
ervPresets: [],
|
|
171
|
-
};
|
|
172
150
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
151
|
+
//watch for changes to the config button
|
|
152
|
+
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");
|
|
155
|
+
this.configButtonState = !this.configButtonState;
|
|
156
|
+
});
|
|
179
157
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const pusDeviceTypeAtw = deviceType === 1 ? devicesByTypeInMelCloud.atw.push(deviceInMelcloud) : false;
|
|
184
|
-
const pusDeviceTypeErv = deviceType === 3 ? devicesByTypeInMelCloud.erv.push(deviceInMelcloud) : false;
|
|
185
|
-
};
|
|
158
|
+
//watch for click on the login button
|
|
159
|
+
document.getElementById('logIn').addEventListener('click', async () => {
|
|
160
|
+
document.getElementById(`logIn`).setAttribute("class", "btn btn-primary");
|
|
186
161
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const ervDevicesInConfigExist = pluginConfig[0].accounts[this.deviceIndex].ervDevices ?? false;
|
|
191
|
-
|
|
192
|
-
//check key of devices in config exist
|
|
193
|
-
const ataDevicesInConfig = !ataDevicesInConfigExist ? pluginConfig[0].accounts[this.deviceIndex].ataDevices = [] : ataDevicesInConfigExist;
|
|
194
|
-
const atwDevicesInConfig = !atwDevicesInConfigExist ? pluginConfig[0].accounts[this.deviceIndex].atwDevices = [] : atwDevicesInConfigExist;
|
|
195
|
-
const ervDevicesInConfig = !ervDevicesInConfigExist ? pluginConfig[0].accounts[this.deviceIndex].ervDevices = [] : ervDevicesInConfigExist;
|
|
196
|
-
|
|
197
|
-
//device ata
|
|
198
|
-
devicesByTypeInMelCloud.ata.forEach((device, index) => {
|
|
199
|
-
const deviceId = device.DeviceID;
|
|
200
|
-
const deviceType = device.Type;
|
|
201
|
-
const deviceName = device.DeviceName;
|
|
202
|
-
const devicePresets = device.Presets ?? [];
|
|
203
|
-
|
|
204
|
-
const deviceAta = {
|
|
205
|
-
id: deviceId,
|
|
206
|
-
type: deviceType,
|
|
207
|
-
typeString: "Air Conditioner",
|
|
208
|
-
disableAccessory: false,
|
|
209
|
-
name: deviceName,
|
|
210
|
-
displayMode: 1,
|
|
211
|
-
heatDryFanMode: 1,
|
|
212
|
-
coolDryFanMode: 1,
|
|
213
|
-
autoDryFanMode: 1,
|
|
214
|
-
temperatureSensor: false,
|
|
215
|
-
temperatureSensorOutdoor: false,
|
|
216
|
-
presets: [],
|
|
217
|
-
buttonsSensors: []
|
|
218
|
-
};
|
|
162
|
+
homebridge.showSpinner();
|
|
163
|
+
document.getElementById('info').innerHTML = 'Connecting...';
|
|
164
|
+
document.getElementById('info').style.color = 'yellow';
|
|
219
165
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
166
|
+
try {
|
|
167
|
+
const accountName = pluginConfig[0].accounts[this.deviceIndex].name;
|
|
168
|
+
const user = pluginConfig[0].accounts[this.deviceIndex].user;
|
|
169
|
+
const passwd = pluginConfig[0].accounts[this.deviceIndex].passwd;
|
|
170
|
+
const language = pluginConfig[0].accounts[this.deviceIndex].language;
|
|
171
|
+
|
|
172
|
+
const payload = {
|
|
173
|
+
accountName: accountName,
|
|
174
|
+
user: user,
|
|
175
|
+
passwd: passwd,
|
|
176
|
+
language: language
|
|
224
177
|
};
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
//find the specific ataDevice to which the preset belongs
|
|
237
|
-
const ataDevice = ataDevicesInConfig.find((device) => device.id === deviceId);
|
|
238
|
-
if (ataDevice && !ataDevice.presets.some((p) => p.id === presetId)) {
|
|
239
|
-
ataDevice.presets.push(preset);
|
|
240
|
-
newDevices.ataPresets.push(preset);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
});
|
|
244
|
-
});
|
|
245
|
-
const textAta = `ATA: ${newDevices.ata.length}`;
|
|
246
|
-
const textAtaPresets = `ATA Presets: ${newDevices.ataPresets.length}`;
|
|
247
|
-
|
|
248
|
-
//device atw
|
|
249
|
-
devicesByTypeInMelCloud.atw.forEach((device, index) => {
|
|
250
|
-
const deviceId = device.DeviceID;
|
|
251
|
-
const deviceType = device.Type;
|
|
252
|
-
const deviceName = device.DeviceName;
|
|
253
|
-
const devicePresets = device.Presets ?? [];
|
|
254
|
-
|
|
255
|
-
const deviceAtw = {
|
|
256
|
-
id: deviceId,
|
|
257
|
-
type: deviceType,
|
|
258
|
-
typeString: "Heat Pump",
|
|
259
|
-
disableAccessory: false,
|
|
260
|
-
name: deviceName,
|
|
261
|
-
displayMode: 1,
|
|
262
|
-
temperatureSensor: false,
|
|
263
|
-
temperatureSensorFlow: false,
|
|
264
|
-
temperatureSensorReturn: false,
|
|
265
|
-
temperatureSensorFlowZone1: false,
|
|
266
|
-
temperatureSensorReturnZone1: false,
|
|
267
|
-
temperatureSensorFlowWaterTank: false,
|
|
268
|
-
temperatureSensorReturnWaterTank: false,
|
|
269
|
-
temperatureSensorFlowZone2: false,
|
|
270
|
-
temperatureSensorReturnZone2: false,
|
|
271
|
-
temperatureSensor: false,
|
|
272
|
-
temperatureSensorOutdoor: false,
|
|
273
|
-
presets: [],
|
|
274
|
-
buttonsSensors: []
|
|
178
|
+
const devicesInMelCloud = await homebridge.request('/connect', payload);
|
|
179
|
+
|
|
180
|
+
//new found devices
|
|
181
|
+
const newDevices = {
|
|
182
|
+
ata: [],
|
|
183
|
+
ataPresets: [],
|
|
184
|
+
atw: [],
|
|
185
|
+
atwPresets: [],
|
|
186
|
+
erv: [],
|
|
187
|
+
ervPresets: [],
|
|
275
188
|
};
|
|
276
189
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
190
|
+
//get devices from melcloud by type
|
|
191
|
+
const devicesByTypeInMelCloud = {
|
|
192
|
+
ata: [],
|
|
193
|
+
atw: [],
|
|
194
|
+
erv: []
|
|
281
195
|
};
|
|
282
196
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
const
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
preset.name = presetName;
|
|
290
|
-
preset.displayType == 0;
|
|
291
|
-
preset.namePrefix = false;
|
|
292
|
-
|
|
293
|
-
//find the specific ataDevice to which the preset belongs
|
|
294
|
-
const atwDevice = atwDevicesInConfig.find((device) => device.id === deviceId);
|
|
295
|
-
if (atwDevice && !atwDevice.presets.some((p) => p.id === presetId)) {
|
|
296
|
-
atwDevice.presets.push(preset);
|
|
297
|
-
newDevices.atwPresets.push(preset);
|
|
298
|
-
}
|
|
197
|
+
for (const deviceInMelcloud of devicesInMelCloud) {
|
|
198
|
+
const deviceType = deviceInMelcloud.Type;
|
|
199
|
+
const pusDeviceTypeAta = deviceType === 0 ? devicesByTypeInMelCloud.ata.push(deviceInMelcloud) : false;
|
|
200
|
+
const pusDeviceTypeAtw = deviceType === 1 ? devicesByTypeInMelCloud.atw.push(deviceInMelcloud) : false;
|
|
201
|
+
const pusDeviceTypeErv = deviceType === 3 ? devicesByTypeInMelCloud.erv.push(deviceInMelcloud) : false;
|
|
202
|
+
};
|
|
299
203
|
|
|
204
|
+
//devices in config
|
|
205
|
+
const ataDevicesInConfigExist = pluginConfig[0].accounts[this.deviceIndex].ataDevices ?? false;
|
|
206
|
+
const atwDevicesInConfigExist = pluginConfig[0].accounts[this.deviceIndex].atwDevices ?? false;
|
|
207
|
+
const ervDevicesInConfigExist = pluginConfig[0].accounts[this.deviceIndex].ervDevices ?? false;
|
|
208
|
+
|
|
209
|
+
//check key of devices in config exist
|
|
210
|
+
const ataDevicesInConfig = !ataDevicesInConfigExist ? pluginConfig[0].accounts[this.deviceIndex].ataDevices = [] : ataDevicesInConfigExist;
|
|
211
|
+
const atwDevicesInConfig = !atwDevicesInConfigExist ? pluginConfig[0].accounts[this.deviceIndex].atwDevices = [] : atwDevicesInConfigExist;
|
|
212
|
+
const ervDevicesInConfig = !ervDevicesInConfigExist ? pluginConfig[0].accounts[this.deviceIndex].ervDevices = [] : ervDevicesInConfigExist;
|
|
213
|
+
|
|
214
|
+
//device ata
|
|
215
|
+
devicesByTypeInMelCloud.ata.forEach((device, index) => {
|
|
216
|
+
const deviceId = device.DeviceID;
|
|
217
|
+
const deviceType = device.Type;
|
|
218
|
+
const deviceName = device.DeviceName;
|
|
219
|
+
const devicePresets = device.Presets ?? [];
|
|
220
|
+
|
|
221
|
+
const deviceAta = {
|
|
222
|
+
id: deviceId,
|
|
223
|
+
type: deviceType,
|
|
224
|
+
typeString: "Air Conditioner",
|
|
225
|
+
disableAccessory: false,
|
|
226
|
+
name: deviceName,
|
|
227
|
+
displayMode: 1,
|
|
228
|
+
heatDryFanMode: 1,
|
|
229
|
+
coolDryFanMode: 1,
|
|
230
|
+
autoDryFanMode: 1,
|
|
231
|
+
temperatureSensor: false,
|
|
232
|
+
temperatureSensorOutdoor: false,
|
|
233
|
+
presets: [],
|
|
234
|
+
buttonsSensors: []
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const deviceExistsInConfig = ataDevicesInConfig.some(device => device.id === deviceId);
|
|
238
|
+
if (!deviceExistsInConfig) {
|
|
239
|
+
ataDevicesInConfig.push(deviceAta);
|
|
240
|
+
newDevices.ata.push(deviceAta);
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
//presets of device in melcloud
|
|
244
|
+
devicePresets.forEach((preset) => {
|
|
245
|
+
const presetId = preset.ID;
|
|
246
|
+
const presetName = preset.NumberDescription;
|
|
247
|
+
|
|
248
|
+
preset.id = presetId;
|
|
249
|
+
preset.name = presetName;
|
|
250
|
+
preset.displayType == 0;
|
|
251
|
+
preset.namePrefix = false;
|
|
252
|
+
|
|
253
|
+
//find the specific ataDevice to which the preset belongs
|
|
254
|
+
const ataDevice = ataDevicesInConfig.find((device) => device.id === deviceId);
|
|
255
|
+
if (ataDevice && !ataDevice.presets.some((p) => p.id === presetId)) {
|
|
256
|
+
ataDevice.presets.push(preset);
|
|
257
|
+
newDevices.ataPresets.push(preset);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
});
|
|
300
261
|
});
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
262
|
+
const textAta = `ATA: ${newDevices.ata.length}`;
|
|
263
|
+
const textAtaPresets = `ATA Presets: ${newDevices.ataPresets.length}`;
|
|
264
|
+
|
|
265
|
+
//device atw
|
|
266
|
+
devicesByTypeInMelCloud.atw.forEach((device, index) => {
|
|
267
|
+
const deviceId = device.DeviceID;
|
|
268
|
+
const deviceType = device.Type;
|
|
269
|
+
const deviceName = device.DeviceName;
|
|
270
|
+
const devicePresets = device.Presets ?? [];
|
|
271
|
+
|
|
272
|
+
const deviceAtw = {
|
|
273
|
+
id: deviceId,
|
|
274
|
+
type: deviceType,
|
|
275
|
+
typeString: "Heat Pump",
|
|
276
|
+
disableAccessory: false,
|
|
277
|
+
name: deviceName,
|
|
278
|
+
displayMode: 1,
|
|
279
|
+
temperatureSensor: false,
|
|
280
|
+
temperatureSensorFlow: false,
|
|
281
|
+
temperatureSensorReturn: false,
|
|
282
|
+
temperatureSensorFlowZone1: false,
|
|
283
|
+
temperatureSensorReturnZone1: false,
|
|
284
|
+
temperatureSensorFlowWaterTank: false,
|
|
285
|
+
temperatureSensorReturnWaterTank: false,
|
|
286
|
+
temperatureSensorFlowZone2: false,
|
|
287
|
+
temperatureSensorReturnZone2: false,
|
|
288
|
+
temperatureSensor: false,
|
|
289
|
+
temperatureSensorOutdoor: false,
|
|
290
|
+
presets: [],
|
|
291
|
+
buttonsSensors: []
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const deviceExistsInConfig = atwDevicesInConfig.some(device => device.id === deviceId);
|
|
295
|
+
if (!deviceExistsInConfig) {
|
|
296
|
+
atwDevicesInConfig.push(deviceAtw);
|
|
297
|
+
newDevices.atw.push(deviceAtw);
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
//presets of device in melcloud
|
|
301
|
+
devicePresets.forEach((preset) => {
|
|
302
|
+
const presetId = preset.ID;
|
|
303
|
+
const presetName = preset.NumberDescription;
|
|
304
|
+
|
|
305
|
+
preset.id = presetId;
|
|
306
|
+
preset.name = presetName;
|
|
307
|
+
preset.displayType == 0;
|
|
308
|
+
preset.namePrefix = false;
|
|
309
|
+
|
|
310
|
+
//find the specific ataDevice to which the preset belongs
|
|
311
|
+
const atwDevice = atwDevicesInConfig.find((device) => device.id === deviceId);
|
|
312
|
+
if (atwDevice && !atwDevice.presets.some((p) => p.id === presetId)) {
|
|
313
|
+
atwDevice.presets.push(preset);
|
|
314
|
+
newDevices.atwPresets.push(preset);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
const textAtw = `ATW: ${newDevices.atw.length}`;
|
|
320
|
+
const textAtwPresets = `ATW Presets: ${newDevices.atwPresets.length}`;
|
|
321
|
+
|
|
322
|
+
//device erv
|
|
323
|
+
devicesByTypeInMelCloud.erv.forEach((device, index) => {
|
|
324
|
+
const deviceId = device.DeviceID;
|
|
325
|
+
const deviceType = device.Type;
|
|
326
|
+
const deviceName = device.DeviceName;
|
|
327
|
+
const devicePresets = device.Presets ?? [];
|
|
328
|
+
|
|
329
|
+
const deviceErv = {
|
|
330
|
+
id: deviceId,
|
|
331
|
+
type: deviceType,
|
|
332
|
+
typeString: "Energy Recovery Ventilation",
|
|
333
|
+
disableAccessory: false,
|
|
334
|
+
name: deviceName,
|
|
335
|
+
displayMode: 1,
|
|
336
|
+
temperatureSensor: false,
|
|
337
|
+
temperatureSensorOutdoor: false,
|
|
338
|
+
temperatureSensorSupply: false,
|
|
339
|
+
temperatureSensor: false,
|
|
340
|
+
temperatureSensorOutdoor: false,
|
|
341
|
+
presets: [],
|
|
342
|
+
buttonsSensors: []
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const deviceExistsInConfig = ervDevicesInConfig.some(device => device.id === deviceId);
|
|
346
|
+
if (!deviceExistsInConfig) {
|
|
347
|
+
ervDevicesInConfig.push(deviceErv);
|
|
348
|
+
newDevices.erv.push(deviceErv);
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
//presets of device in melcloud
|
|
352
|
+
devicePresets.forEach((preset) => {
|
|
353
|
+
const presetId = preset.ID;
|
|
354
|
+
const presetName = preset.NumberDescription;
|
|
355
|
+
|
|
356
|
+
preset.id = presetId;
|
|
357
|
+
preset.name = presetName;
|
|
358
|
+
preset.displayType == 0;
|
|
359
|
+
preset.namePrefix = false;
|
|
360
|
+
|
|
361
|
+
//find the specific ataDevice to which the preset belongs
|
|
362
|
+
const ervDevice = ervDevicesInConfig.find((device) => device.id === deviceId);
|
|
363
|
+
if (ervDevice && !ervDevice.presets.some((p) => p.id === presetId)) {
|
|
364
|
+
ervDevice.presets.push(preset);
|
|
365
|
+
newDevices.ervPresets.push(preset);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
const textErv = `ERV: ${newDevices.erv.length}`;
|
|
371
|
+
const textErvPresets = `ERV Presets: ${newDevices.ervPresets.length}`;
|
|
372
|
+
|
|
373
|
+
//display info
|
|
374
|
+
const newDevicesCount = newDevices.ata.length + newDevices.atw.length + newDevices.erv.length ?? 0;
|
|
375
|
+
const newPresetsCount = newDevices.ataPresets.length + newDevices.atwPresets.length + newDevices.ervPresets.length ?? 0;
|
|
376
|
+
if (newDevicesCount === 0 && newPresetsCount === 0) {
|
|
377
|
+
document.getElementById('info').innerHTML = 'No new devices found.';
|
|
378
|
+
document.getElementById('info').style.color = 'white';
|
|
326
379
|
};
|
|
327
380
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
381
|
+
if (newDevicesCount > 0 && newPresetsCount > 0) {
|
|
382
|
+
document.getElementById('info').innerHTML = `Found, ${textAta}, ${textAtw}, ${textErv}.`;
|
|
383
|
+
document.getElementById('info').style.color = 'green';
|
|
384
|
+
document.getElementById('info1').innerHTML = `${textAtaPresets}, ${textAtwPresets}, ${textErvPresets}.`;
|
|
385
|
+
document.getElementById('info1').style.color = 'green';
|
|
386
|
+
document.getElementById('info2').innerHTML = 'Now You can configure it.';
|
|
387
|
+
document.getElementById('info2').style.color = 'green';
|
|
332
388
|
};
|
|
333
389
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
preset.name = presetName;
|
|
341
|
-
preset.displayType == 0;
|
|
342
|
-
preset.namePrefix = false;
|
|
343
|
-
|
|
344
|
-
//find the specific ataDevice to which the preset belongs
|
|
345
|
-
const ervDevice = ervDevicesInConfig.find((device) => device.id === deviceId);
|
|
346
|
-
if (ervDevice && !ervDevice.presets.some((p) => p.id === presetId)) {
|
|
347
|
-
ervDevice.presets.push(preset);
|
|
348
|
-
newDevices.ervPresets.push(preset);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
const textErv = `ERV: ${newDevices.erv.length}`;
|
|
354
|
-
const textErvPresets = `ERV Presets: ${newDevices.ervPresets.length}`;
|
|
355
|
-
|
|
356
|
-
//display info
|
|
357
|
-
const newDevicesCount = newDevices.ata.length + newDevices.atw.length + newDevices.erv.length ?? 0;
|
|
358
|
-
const newPresetsCount = newDevices.ataPresets.length + newDevices.atwPresets.length + newDevices.ervPresets.length ?? 0;
|
|
359
|
-
if (newDevicesCount === 0 && newPresetsCount === 0) {
|
|
360
|
-
document.getElementById('info').innerHTML = 'No new devices found.';
|
|
361
|
-
document.getElementById('info').style.color = 'white';
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
if (newDevicesCount > 0 && newPresetsCount > 0) {
|
|
365
|
-
document.getElementById('info').innerHTML = `Found, ${textAta}, ${textAtw}, ${textErv}.`;
|
|
366
|
-
document.getElementById('info').style.color = 'green';
|
|
367
|
-
document.getElementById('info1').innerHTML = `${textAtaPresets}, ${textAtwPresets}, ${textErvPresets}.`;
|
|
368
|
-
document.getElementById('info1').style.color = 'green';
|
|
369
|
-
document.getElementById('info2').innerHTML = 'Now You can configure it.';
|
|
370
|
-
document.getElementById('info2').style.color = 'green';
|
|
371
|
-
};
|
|
390
|
+
if (newDevicesCount > 0 && newPresetsCount === 0) {
|
|
391
|
+
document.getElementById('info').innerHTML = `Found, ${textAta}, ${textAtw}, ${textErv}.`;
|
|
392
|
+
document.getElementById('info').style.color = 'green';
|
|
393
|
+
document.getElementById('info1').innerHTML = 'Now You can configure it.';
|
|
394
|
+
document.getElementById('info1').style.color = 'green';
|
|
395
|
+
};
|
|
372
396
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
397
|
+
if (newDevicesCount === 0 && newPresetsCount > 0) {
|
|
398
|
+
document.getElementById('info').innerHTML = `Found, ${textAtaPresets}, ${textAtwPresets}, ${textErvPresets}.`;
|
|
399
|
+
document.getElementById('info').style.color = 'green';
|
|
400
|
+
document.getElementById('info1').innerHTML = 'Now You can configure it.';
|
|
401
|
+
document.getElementById('info1').style.color = 'green';
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
//update button state
|
|
405
|
+
document.getElementById(`logIn`).setAttribute("class", "btn btn-secondary");
|
|
406
|
+
|
|
407
|
+
//update ans save plugin config
|
|
408
|
+
await homebridge.updatePluginConfig(pluginConfig);
|
|
409
|
+
await homebridge.savePluginConfig(pluginConfig);
|
|
410
|
+
homebridge.hideSpinner();
|
|
411
|
+
} catch (error) {
|
|
412
|
+
document.getElementById('info').innerHTML = 'Check Your credentials data and try again.';
|
|
413
|
+
document.getElementById('info').style.color = 'yellow';
|
|
414
|
+
document.getElementById('info1').innerHTML = `Error: ${error}`;
|
|
415
|
+
document.getElementById('info1').style.color = 'red';
|
|
416
|
+
} finally {
|
|
417
|
+
homebridge.hideSpinner();
|
|
378
418
|
};
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
document.getElementById('info').style.color = 'green';
|
|
383
|
-
document.getElementById('info1').innerHTML = 'Now You can configure it.';
|
|
384
|
-
document.getElementById('info1').style.color = 'green';
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
//update ans save plugin config
|
|
388
|
-
await homebridge.updatePluginConfig(pluginConfig);
|
|
389
|
-
await homebridge.savePluginConfig(pluginConfig);
|
|
390
|
-
homebridge.hideSpinner();
|
|
391
|
-
} catch (error) {
|
|
392
|
-
document.getElementById('info').innerHTML = 'Check Your credentials data and try again.';
|
|
393
|
-
document.getElementById('info').style.color = 'yellow';
|
|
394
|
-
document.getElementById('info1').innerHTML = `Error: ${error}`;
|
|
395
|
-
document.getElementById('info1').style.color = 'red';
|
|
396
|
-
} finally {
|
|
397
|
-
homebridge.hideSpinner();
|
|
398
|
-
};
|
|
399
|
-
});
|
|
400
|
-
})();
|
|
401
|
-
</script>
|
|
419
|
+
});
|
|
420
|
+
})();
|
|
421
|
+
</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.7.3-beta.
|
|
4
|
+
"version": "3.7.3-beta.2",
|
|
5
5
|
"description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|