homebridge-melcloud-control 4.3.9-beta.0 → 4.3.9-beta.10
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 +363 -412
- package/package.json +1 -1
- package/src/constants.js +5 -1
- package/src/deviceata.js +2 -1
- package/src/melcloudata.js +21 -10
|
@@ -9,439 +9,390 @@
|
|
|
9
9
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/js/all.min.js"></script>
|
|
10
10
|
</head>
|
|
11
11
|
|
|
12
|
-
<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<img src="homebridge-melcloud-control.png" alt="Image" height="120" />
|
|
17
|
-
</div>
|
|
18
|
-
|
|
19
|
-
<div id="melCloudAccount" class="card card-body mt-2">
|
|
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: 14px;"></label>
|
|
24
|
-
<label id="info1" class="d-block" style="font-size: 12px;"></label>
|
|
25
|
-
<label id="info2" class="d-block" style="font-size: 12px;"></label>
|
|
26
|
-
</div>
|
|
27
|
-
|
|
28
|
-
<div class="mb-2">
|
|
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-2">
|
|
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-2 position-relative">
|
|
39
|
-
<label for="passwd" class="form-label">Password</label>
|
|
40
|
-
<div class="input-group">
|
|
41
|
-
<input id="passwd" type="password" class="form-control" autocomplete="off" required>
|
|
42
|
-
<button type="button" id="togglePasswd" class="btn btn-outline-secondary">
|
|
43
|
-
<i class="fas fa-eye"></i>
|
|
44
|
-
</button>
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<div class="mb-2">
|
|
49
|
-
<label for="language" class="form-label">Language</label>
|
|
50
|
-
<select id="language" name="language" class="form-control">
|
|
51
|
-
<option value="0">English</option>
|
|
52
|
-
<option value="1">Български</option>
|
|
53
|
-
<option value="2">Čeština</option>
|
|
54
|
-
<option value="3">Dansk</option>
|
|
55
|
-
<option value="4">Deutsch</option>
|
|
56
|
-
<option value="5">Eesti</option>
|
|
57
|
-
<option value="6">Español</option>
|
|
58
|
-
<option value="7">Français</option>
|
|
59
|
-
<option value="8">Հայերեն</option>
|
|
60
|
-
<option value="9">Latviešu</option>
|
|
61
|
-
<option value="10">Lietuvių</option>
|
|
62
|
-
<option value="11">Magyar</option>
|
|
63
|
-
<option value="12">Nederlands</option>
|
|
64
|
-
<option value="13">Norwegian</option>
|
|
65
|
-
<option value="14">Polski</option>
|
|
66
|
-
<option value="15">Português</option>
|
|
67
|
-
<option value="16">Русский</option>
|
|
68
|
-
<option value="17">Suomi</option>
|
|
69
|
-
<option value="18">Svenska</option>
|
|
70
|
-
<option value="19">Українська</option>
|
|
71
|
-
<option value="20">Türkçe</option>
|
|
72
|
-
<option value="21">Ελληνικά</option>
|
|
73
|
-
<option value="22">Hrvatski</option>
|
|
74
|
-
<option value="23">Română</option>
|
|
75
|
-
<option value="24">Slovenščina</option>
|
|
76
|
-
</select>
|
|
77
|
-
</div>
|
|
78
|
-
|
|
79
|
-
<div class="mb-2">
|
|
80
|
-
<label for="accountType" class="form-label">Account Type</label>
|
|
81
|
-
<select id="accountType" name="accountType" class="form-control">
|
|
82
|
-
<option value="disabled">None/Disabled</option>
|
|
83
|
-
<option value="melcloud">MELCloud</option>
|
|
84
|
-
<option value="melcloudhome">MELCloud Home</option>
|
|
85
|
-
</select>
|
|
86
|
-
</div>
|
|
12
|
+
<div class="container mt-3">
|
|
13
|
+
<div class="text-center">
|
|
14
|
+
<img src="homebridge-melcloud-control.png" alt="Image" height="120" />
|
|
15
|
+
</div>
|
|
87
16
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
17
|
+
<div id="melCloudAccount" class="card card-body mt-2">
|
|
18
|
+
<form id="configForm">
|
|
19
|
+
<div class="text-center">
|
|
20
|
+
<label id="accountName" class="fw-bold" style="font-size: 23px;">Account</label><br>
|
|
21
|
+
<label id="info" class="d-block" style="font-size: 14px;"></label>
|
|
22
|
+
<label id="info1" class="d-block" style="font-size: 12px;"></label>
|
|
23
|
+
<label id="info2" class="d-block" style="font-size: 12px;"></label>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="mb-2">
|
|
27
|
+
<label for="name" class="form-label">Name</label>
|
|
28
|
+
<input id="name" type="text" class="form-control" required>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="mb-2">
|
|
32
|
+
<label for="user" class="form-label">User Name</label>
|
|
33
|
+
<input id="user" type="text" class="form-control" required>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="mb-2 position-relative">
|
|
37
|
+
<label for="passwd" class="form-label">Password</label>
|
|
38
|
+
<div class="input-group">
|
|
39
|
+
<input id="passwd" type="password" class="form-control" autocomplete="off" required>
|
|
40
|
+
<button type="button" id="togglePasswd" class="btn btn-outline-secondary">
|
|
41
|
+
<i class="fas fa-eye"></i>
|
|
42
|
+
</button>
|
|
91
43
|
</div>
|
|
92
|
-
</
|
|
93
|
-
|
|
94
|
-
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="mb-2">
|
|
47
|
+
<label for="language" class="form-label">Language</label>
|
|
48
|
+
<select id="language" name="language" class="form-control">
|
|
49
|
+
<option value="0">English</option>
|
|
50
|
+
<option value="1">Български</option>
|
|
51
|
+
<option value="2">Čeština</option>
|
|
52
|
+
<option value="3">Dansk</option>
|
|
53
|
+
<option value="4">Deutsch</option>
|
|
54
|
+
<option value="5">Eesti</option>
|
|
55
|
+
<option value="6">Español</option>
|
|
56
|
+
<option value="7">Français</option>
|
|
57
|
+
<option value="8">Հայերեն</option>
|
|
58
|
+
<option value="9">Latviešu</option>
|
|
59
|
+
<option value="10">Lietuvių</option>
|
|
60
|
+
<option value="11">Magyar</option>
|
|
61
|
+
<option value="12">Nederlands</option>
|
|
62
|
+
<option value="13">Norwegian</option>
|
|
63
|
+
<option value="14">Polski</option>
|
|
64
|
+
<option value="15">Português</option>
|
|
65
|
+
<option value="16">Русский</option>
|
|
66
|
+
<option value="17">Suomi</option>
|
|
67
|
+
<option value="18">Svenska</option>
|
|
68
|
+
<option value="19">Українська</option>
|
|
69
|
+
<option value="20">Türkçe</option>
|
|
70
|
+
<option value="21">Ελληνικά</option>
|
|
71
|
+
<option value="22">Hrvatski</option>
|
|
72
|
+
<option value="23">Română</option>
|
|
73
|
+
<option value="24">Slovenščina</option>
|
|
74
|
+
</select>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div class="mb-2">
|
|
78
|
+
<label for="accountType" class="form-label">Account Type</label>
|
|
79
|
+
<select id="accountType" name="accountType" class="form-control">
|
|
80
|
+
<option value="disabled">None/Disabled</option>
|
|
81
|
+
<option value="melcloud">MELCloud</option>
|
|
82
|
+
<option value="melcloudhome">MELCloud Home</option>
|
|
83
|
+
</select>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div class="text-center">
|
|
87
|
+
<button id="logIn" type="button" class="btn btn-secondary">Connect to MELCloud</button>
|
|
88
|
+
<button id="configButton" type="button" class="btn btn-secondary"><i class="fas fa-gear"></i></button>
|
|
89
|
+
</div>
|
|
90
|
+
</form>
|
|
91
|
+
<div id="accountButton" class="d-flex flex-wrap justify-content-center gap-1 mt-3"></div>
|
|
95
92
|
</div>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<script>
|
|
96
|
+
(async () => {
|
|
97
|
+
const pluginConfig = await homebridge.getPluginConfig();
|
|
98
|
+
|
|
99
|
+
if (!pluginConfig.length) {
|
|
100
|
+
pluginConfig.push({});
|
|
101
|
+
await homebridge.updatePluginConfig(pluginConfig);
|
|
102
|
+
homebridge.showSchemaForm();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const accounts = pluginConfig[0].accounts || [];
|
|
107
|
+
const accountsCount = accounts.length;
|
|
108
|
+
|
|
109
|
+
const container = document.getElementById("accountButton");
|
|
110
|
+
container.style.display = 'flex';
|
|
111
|
+
container.style.flexWrap = 'wrap';
|
|
112
|
+
container.style.justifyContent = 'center';
|
|
113
|
+
container.style.gap = '0.25rem';
|
|
114
|
+
container.style.alignItems = 'center';
|
|
115
|
+
|
|
116
|
+
const formElements = {
|
|
117
|
+
accountName: document.getElementById('accountName'),
|
|
118
|
+
info: document.getElementById('info'),
|
|
119
|
+
info1: document.getElementById('info1'),
|
|
120
|
+
info2: document.getElementById('info2'),
|
|
121
|
+
name: document.getElementById('name'),
|
|
122
|
+
user: document.getElementById('user'),
|
|
123
|
+
passwd: document.getElementById('passwd'),
|
|
124
|
+
language: document.getElementById('language'),
|
|
125
|
+
accountType: document.getElementById('accountType'),
|
|
126
|
+
logIn: document.getElementById('logIn')
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Tworzenie przycisków
|
|
130
|
+
accounts.forEach((account, i) => {
|
|
131
|
+
this.account = account;
|
|
132
|
+
|
|
133
|
+
const button = document.createElement("button");
|
|
134
|
+
button.type = "button";
|
|
135
|
+
button.id = `button${i}`;
|
|
136
|
+
button.className = "btn btn-primary";
|
|
137
|
+
button.style.textTransform = 'none';
|
|
138
|
+
button.innerText = account.name || `Account ${i + 1}`;
|
|
139
|
+
container.appendChild(button);
|
|
140
|
+
|
|
141
|
+
button.addEventListener('click', async () => {
|
|
133
142
|
this.account = account;
|
|
134
143
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
button.className = "btn btn-primary";
|
|
139
|
-
button.style.textTransform = 'none';
|
|
140
|
-
button.innerText = account.name || `Account ${i + 1}`;
|
|
141
|
-
container.appendChild(button);
|
|
142
|
-
|
|
143
|
-
button.addEventListener('click', async () => {
|
|
144
|
-
this.account = account;
|
|
145
|
-
|
|
146
|
-
// Zmieniamy klasę wszystkich przycisków
|
|
147
|
-
accounts.forEach((_, j) => {
|
|
148
|
-
document.getElementById(`button${j}`).className = (j === i ? 'btn btn-primary' : 'btn btn-secondary');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// Ustawiamy formularz
|
|
152
|
-
formElements.accountName.innerText = account.name || '';
|
|
153
|
-
formElements.info.innerText = ``;
|
|
154
|
-
formElements.info1.innerText = '';
|
|
155
|
-
formElements.info2.innerText = '';
|
|
156
|
-
formElements.name.value = account.name || '';
|
|
157
|
-
formElements.user.value = account.user || '';
|
|
158
|
-
formElements.passwd.value = account.passwd || '';
|
|
159
|
-
formElements.language.value = account.language || '0';
|
|
160
|
-
formElements.accountType.value = account.type || 'disabled';
|
|
161
|
-
formElements.logIn.disabled = !(account.name && account.user && account.passwd && account.language && account.type);
|
|
144
|
+
// Zmieniamy klasę wszystkich przycisków
|
|
145
|
+
accounts.forEach((_, j) => {
|
|
146
|
+
document.getElementById(`button${j}`).className = (j === i ? 'btn btn-primary' : 'btn btn-secondary');
|
|
162
147
|
});
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
// Klikamy pierwszy przycisk po zakończeniu pętli
|
|
166
|
-
if (accountsCount > 0) document.getElementById('button0').click();
|
|
167
|
-
|
|
168
|
-
// Jeden listener input dla całego formularza
|
|
169
|
-
document.getElementById('configForm').addEventListener('input', async () => {
|
|
170
|
-
const account = this.account;
|
|
171
|
-
if (!account) return;
|
|
172
|
-
|
|
173
|
-
account.name = formElements.name.value;
|
|
174
|
-
account.user = formElements.user.value;
|
|
175
|
-
account.passwd = formElements.passwd.value;
|
|
176
|
-
account.language = formElements.language.value;
|
|
177
|
-
account.type = formElements.accountType.value;
|
|
178
148
|
|
|
149
|
+
// Ustawiamy formularz
|
|
150
|
+
formElements.accountName.innerText = account.name || '';
|
|
151
|
+
formElements.info.innerText = ``;
|
|
152
|
+
formElements.info1.innerText = '';
|
|
153
|
+
formElements.info2.innerText = '';
|
|
154
|
+
formElements.name.value = account.name || '';
|
|
155
|
+
formElements.user.value = account.user || '';
|
|
156
|
+
formElements.passwd.value = account.passwd || '';
|
|
157
|
+
formElements.language.value = account.language || '0';
|
|
158
|
+
formElements.accountType.value = account.type || 'disabled';
|
|
179
159
|
formElements.logIn.disabled = !(account.name && account.user && account.passwd && account.language && account.type);
|
|
180
|
-
|
|
181
|
-
await homebridge.updatePluginConfig(pluginConfig);
|
|
182
|
-
await homebridge.savePluginConfig(pluginConfig);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
document.getElementById('melCloudAccount').style.display = 'block';
|
|
186
|
-
|
|
187
|
-
// Config Button Toggle
|
|
188
|
-
const configButton = document.getElementById('configButton');
|
|
189
|
-
let configButtonState = false;
|
|
190
|
-
configButton.addEventListener('click', () => {
|
|
191
|
-
configButtonState = !configButtonState;
|
|
192
|
-
homebridge[configButtonState ? 'showSchemaForm' : 'hideSchemaForm']();
|
|
193
|
-
configButton.className = configButtonState ? 'btn btn-primary' : 'btn btn-secondary';
|
|
194
160
|
});
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Klikamy pierwszy przycisk po zakończeniu pętli
|
|
164
|
+
if (accountsCount > 0) document.getElementById('button0').click();
|
|
165
|
+
|
|
166
|
+
// Jeden listener input dla całego formularza
|
|
167
|
+
document.getElementById('configForm').addEventListener('input', async () => {
|
|
168
|
+
const account = this.account;
|
|
169
|
+
if (!account) return;
|
|
170
|
+
|
|
171
|
+
account.name = formElements.name.value;
|
|
172
|
+
account.user = formElements.user.value;
|
|
173
|
+
account.passwd = formElements.passwd.value;
|
|
174
|
+
account.language = formElements.language.value;
|
|
175
|
+
account.type = formElements.accountType.value;
|
|
176
|
+
|
|
177
|
+
formElements.logIn.disabled = !(account.name && account.user && account.passwd && account.language && account.type);
|
|
178
|
+
|
|
179
|
+
await homebridge.updatePluginConfig(pluginConfig);
|
|
180
|
+
await homebridge.savePluginConfig(pluginConfig);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
document.getElementById('melCloudAccount').style.display = 'block';
|
|
184
|
+
|
|
185
|
+
// Config Button Toggle
|
|
186
|
+
const configButton = document.getElementById('configButton');
|
|
187
|
+
let configButtonState = false;
|
|
188
|
+
configButton.addEventListener('click', () => {
|
|
189
|
+
configButtonState = !configButtonState;
|
|
190
|
+
homebridge[configButtonState ? 'showSchemaForm' : 'hideSchemaForm']();
|
|
191
|
+
configButton.className = configButtonState ? 'btn btn-primary' : 'btn btn-secondary';
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Password toggle
|
|
195
|
+
document.getElementById('togglePasswd').addEventListener('click', () => {
|
|
196
|
+
const passwdInput = document.getElementById('passwd');
|
|
197
|
+
const icon = document.querySelector('#togglePasswd i');
|
|
198
|
+
if (passwdInput.type === 'password') {
|
|
199
|
+
passwdInput.type = 'text';
|
|
200
|
+
icon.classList.replace('fa-eye', 'fa-eye-slash');
|
|
201
|
+
} else {
|
|
202
|
+
passwdInput.type = 'password';
|
|
203
|
+
icon.classList.replace('fa-eye-slash', 'fa-eye');
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Device Handling & Login Logic
|
|
208
|
+
function removeStaleDevices(configDevices, melcloudDevices) {
|
|
209
|
+
const melcloudIds = melcloudDevices.map(d => d.DeviceID);
|
|
210
|
+
const removedDevices = [];
|
|
211
|
+
|
|
212
|
+
for (let i = configDevices.length - 1; i >= 0; i--) {
|
|
213
|
+
const device = configDevices[i];
|
|
214
|
+
if (!melcloudIds.includes(device.id)) {
|
|
215
|
+
removedDevices.push(device);
|
|
216
|
+
configDevices.splice(i, 1);
|
|
206
217
|
}
|
|
207
|
-
}
|
|
218
|
+
}
|
|
219
|
+
return removedDevices;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function updateInfo(id, text, color) {
|
|
223
|
+
const el = document.getElementById(id);
|
|
224
|
+
if (el) {
|
|
225
|
+
el.innerText = text;
|
|
226
|
+
el.style.color = color;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
208
229
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
const melcloudIds = melcloudDevices.map(d => d.DeviceID);
|
|
212
|
-
const removedDevices = [];
|
|
230
|
+
document.getElementById('logIn').addEventListener('click', async () => {
|
|
231
|
+
homebridge.showSpinner();
|
|
213
232
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
configDevices.splice(i, 1);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return removedDevices;
|
|
222
|
-
}
|
|
233
|
+
document.getElementById(`logIn`).className = "btn btn-primary";
|
|
234
|
+
updateInfo('info', '', 'white');
|
|
235
|
+
updateInfo('info1', '', 'white');
|
|
236
|
+
updateInfo('info2', '', 'white');
|
|
223
237
|
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
238
|
+
try {
|
|
239
|
+
const account = this.account;
|
|
240
|
+
const response = await homebridge.request('/connect', account);
|
|
241
|
+
if (!response.State) {
|
|
242
|
+
homebridge.hideSpinner();
|
|
243
|
+
updateInfo('info', response.Info);
|
|
244
|
+
return;
|
|
229
245
|
}
|
|
230
|
-
}
|
|
231
246
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const response = await homebridge.request('/connect', account);
|
|
243
|
-
if (!response.State) {
|
|
244
|
-
homebridge.hideSpinner();
|
|
245
|
-
updateInfo('info', response.Info);
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
247
|
+
// Initialize devices arrays
|
|
248
|
+
const newInMelCloud = { ata: [], ataPresets: [], ataSchedules: [], atw: [], atwPresets: [], atwSchedules: [], erv: [], ervPresets: [], ervSchedules: [], scenes: [] };
|
|
249
|
+
const devicesInMelCloudByType = { ata: [], atw: [], erv: [] };
|
|
250
|
+
const scenesInMelCloud = response.Scenes ?? []
|
|
251
|
+
|
|
252
|
+
response.Devices.forEach(device => {
|
|
253
|
+
if (device.Type === 0) devicesInMelCloudByType.ata.push(device);
|
|
254
|
+
if (device.Type === 1) devicesInMelCloudByType.atw.push(device);
|
|
255
|
+
if (device.Type === 3) devicesInMelCloudByType.erv.push(device);
|
|
256
|
+
});
|
|
248
257
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const presetsInConfig = deviceInConfig.presets || [];
|
|
300
|
-
const presetIds = new Set(presetsInConfig.map(p => String(p.id)));
|
|
301
|
-
|
|
302
|
-
let addedNewPreset = false;
|
|
303
|
-
presetsInMelCloud.forEach((preset, index) => {
|
|
304
|
-
const presetId = String(preset.ID);
|
|
305
|
-
if (!presetIds.has(presetId)) {
|
|
306
|
-
const presetObj = {
|
|
307
|
-
id: presetId,
|
|
308
|
-
displayType: 0,
|
|
309
|
-
name: preset.NumberDescription || `Preset ${index}`,
|
|
310
|
-
namePrefix: false
|
|
311
|
-
};
|
|
312
|
-
presetsInConfig.push(presetObj);
|
|
313
|
-
newPresets.push(presetObj);
|
|
314
|
-
presetIds.add(presetId);
|
|
315
|
-
addedNewPreset = true;
|
|
316
|
-
}
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
// === Remove placeholder presets/schedules (id === '0') if new ones were added ===
|
|
320
|
-
if (addedNewPreset) {
|
|
321
|
-
const beforeCount = presetsInConfig.length;
|
|
322
|
-
deviceInConfig.presets = presetsInConfig.filter(p => String(p.id) !== '0');
|
|
323
|
-
const removedCount = beforeCount - deviceInConfig.presets.length;
|
|
324
|
-
|
|
325
|
-
if (removedCount > 0 && removedCount < beforeCount) {
|
|
326
|
-
updateInfo('info2', `Removed ${removedCount} placeholder preset from device ${device.DeviceID}`, 'yellow');
|
|
327
|
-
}
|
|
258
|
+
account.ataDevices = (account.ataDevices ?? []).filter(d => String(d.id) !== '0');
|
|
259
|
+
account.atwDevices = (account.atwDevices ?? []).filter(d => String(d.id) !== '0');
|
|
260
|
+
account.ervDevices = (account.ervDevices ?? []).filter(d => String(d.id) !== '0');
|
|
261
|
+
|
|
262
|
+
const removedAta = removeStaleDevices(account.ataDevices, devicesInMelCloudByType.ata);
|
|
263
|
+
const removedAtw = removeStaleDevices(account.atwDevices, devicesInMelCloudByType.atw);
|
|
264
|
+
const removedErv = removeStaleDevices(account.ervDevices, devicesInMelCloudByType.erv);
|
|
265
|
+
|
|
266
|
+
const handleDevices = (devicesInMelCloud, devicesInConfig, deviceTypeString, newDevices, newPresets, newSchedules, newScenes) => {
|
|
267
|
+
try {
|
|
268
|
+
const configDevicesMap = new Map(devicesInConfig.map(dev => [String(dev.id), dev]));
|
|
269
|
+
|
|
270
|
+
devicesInMelCloud.forEach(device => {
|
|
271
|
+
const deviceId = String(device.DeviceID);
|
|
272
|
+
let deviceInConfig = configDevicesMap.get(deviceId);
|
|
273
|
+
|
|
274
|
+
// === Create device if missing ===
|
|
275
|
+
if (!deviceInConfig) {
|
|
276
|
+
deviceInConfig = {
|
|
277
|
+
id: deviceId,
|
|
278
|
+
type: device.Type,
|
|
279
|
+
deviceTypeString,
|
|
280
|
+
displayType: 0,
|
|
281
|
+
name: device.DeviceName
|
|
282
|
+
};
|
|
283
|
+
devicesInConfig.push(deviceInConfig);
|
|
284
|
+
newDevices.push(deviceInConfig);
|
|
285
|
+
configDevicesMap.set(deviceId, deviceInConfig);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
//only for melcloud
|
|
289
|
+
if (account.type === 'melcloud') {
|
|
290
|
+
|
|
291
|
+
// === Process presets ===
|
|
292
|
+
const presetsInMelCloud = device.Presets || [];
|
|
293
|
+
const presetsInConfig = (deviceInConfig.presets ?? []).filter(p => String(p.id) !== '0');
|
|
294
|
+
const presetIds = new Set(presetsInConfig.map(p => String(p.id)));
|
|
295
|
+
|
|
296
|
+
presetsInMelCloud.forEach((preset, index) => {
|
|
297
|
+
const presetId = String(preset.ID);
|
|
298
|
+
if (!presetIds.has(presetId)) {
|
|
299
|
+
const presetObj = {
|
|
300
|
+
id: presetId,
|
|
301
|
+
displayType: 0,
|
|
302
|
+
name: preset.NumberDescription || `Preset ${index}`,
|
|
303
|
+
namePrefix: false
|
|
304
|
+
};
|
|
305
|
+
presetsInConfig.push(presetObj);
|
|
306
|
+
newPresets.push(presetObj);
|
|
307
|
+
presetIds.add(presetId);
|
|
328
308
|
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
addedNewSchedule = true;
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
// === Remove placeholder schedules (id === '0') if new ones were added ===
|
|
357
|
-
if (addedNewSchedule) {
|
|
358
|
-
const beforeCount = schedulesInConfig.length;
|
|
359
|
-
deviceInConfig.schedules = schedulesInConfig.filter(s => String(s.id) !== '0');
|
|
360
|
-
const removedCount = beforeCount - deviceInConfig.schedules.length;
|
|
361
|
-
|
|
362
|
-
if (removedCount > 0 && removedCount < beforeCount) {
|
|
363
|
-
updateInfo('info2', `Removed ${removedCount} placeholder schedule from device ${device.DeviceID}`, 'yellow');
|
|
364
|
-
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
//only for melcloudhome
|
|
313
|
+
if (account.type === 'melcloudhome') {
|
|
314
|
+
|
|
315
|
+
// === Process schedules ===
|
|
316
|
+
const schedulesInMelCloud = device.Schedule || [];
|
|
317
|
+
const schedulesInConfig = (deviceInConfig.schedules ?? []).filter(s => String(s.id) !== '0');
|
|
318
|
+
const scheduleIds = new Set(schedulesInConfig.map(s => String(s.id)));
|
|
319
|
+
|
|
320
|
+
schedulesInMelCloud.forEach((schedule, index) => {
|
|
321
|
+
const scheduleId = String(schedule.Id);
|
|
322
|
+
if (!scheduleIds.has(scheduleId)) {
|
|
323
|
+
const scheduleObj = {
|
|
324
|
+
id: scheduleId,
|
|
325
|
+
displayType: 0,
|
|
326
|
+
name: `Schedule ${index}`,
|
|
327
|
+
namePrefix: false
|
|
328
|
+
};
|
|
329
|
+
schedulesInConfig.push(scheduleObj);
|
|
330
|
+
newSchedules.push(scheduleObj);
|
|
331
|
+
scheduleIds.add(scheduleId);
|
|
365
332
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
addedNewScenes = true;
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
// === Remove placeholder scenes (id === '0') if new ones were added ===
|
|
389
|
-
if (addedNewScenes) {
|
|
390
|
-
const beforeCount = scenesInConfig.length;
|
|
391
|
-
deviceInConfig.scenes = scenesInConfig.filter(s => String(s.id) !== '0');
|
|
392
|
-
const removedCount = beforeCount - deviceInConfig.scenes.length;
|
|
393
|
-
|
|
394
|
-
if (removedCount > 0 && removedCount < beforeCount) {
|
|
395
|
-
updateInfo('info2', `Removed ${removedCount} placeholder scene from device ${device.DeviceID}`, 'yellow');
|
|
396
|
-
}
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// === Process scenes ===
|
|
336
|
+
const scenesInConfig = (deviceInConfig.scenes ?? []).filter(s => String(s.id) !== '0');
|
|
337
|
+
const sceneIds = new Set(scenesInConfig.map(s => String(s.id)));
|
|
338
|
+
|
|
339
|
+
scenesInMelCloud.forEach((scene, index) => {
|
|
340
|
+
const sceneId = String(scene.Id);
|
|
341
|
+
if (!sceneIds.has(sceneId)) {
|
|
342
|
+
const sceneObj = {
|
|
343
|
+
id: sceneId,
|
|
344
|
+
displayType: 0,
|
|
345
|
+
name: scene.Name || `Scene ${index}`,
|
|
346
|
+
namePrefix: false
|
|
347
|
+
};
|
|
348
|
+
scenesInConfig.push(sceneObj);
|
|
349
|
+
newScenes.push(sceneObj);
|
|
350
|
+
sceneIds.add(sceneId);
|
|
397
351
|
}
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
|
|
409
|
-
account.ataDevices = handleDevices(devicesInMelCloudByType.ata, account.ataDevices, "Air Conditioner", newInMelCloud.ata, newInMelCloud.ataPresets, newInMelCloud.ataSchedules, newInMelCloud.scenes);
|
|
410
|
-
account.atwDevices = handleDevices(devicesInMelCloudByType.atw, account.atwDevices, "Heat Pump", newInMelCloud.atw, newInMelCloud.atwPresets, newInMelCloud.atwSchedules, newInMelCloud.scenes);
|
|
411
|
-
account.ervDevices = handleDevices(devicesInMelCloudByType.erv, account.ervDevices, "Energy Recovery Ventilation", newInMelCloud.erv, newInMelCloud.ervPresets, newInMelCloud.ervSchedules, newInMelCloud.scenes);
|
|
412
|
-
|
|
413
|
-
const newDevicesCount = newInMelCloud.ata.length + newInMelCloud.atw.length + newInMelCloud.erv.length;
|
|
414
|
-
const newPresetsCount = newInMelCloud.ataPresets.length + newInMelCloud.atwPresets.length + newInMelCloud.ervPresets.length;
|
|
415
|
-
const newSchedulesCount = newInMelCloud.ataSchedules.length + newInMelCloud.atwSchedules.length + newInMelCloud.ervSchedules.length;
|
|
416
|
-
const newScenesCount = newInMelCloud.scenes.length;
|
|
417
|
-
const removedDevicesCount = removedAta.length + removedAtw.length + removedErv.length;
|
|
418
|
-
|
|
419
|
-
if (!newDevicesCount && !newPresetsCount && !newSchedulesCount && !newScenesCount && !removedDevicesCount) {
|
|
420
|
-
updateInfo('info', 'No changes detected.', 'white');
|
|
421
|
-
} else {
|
|
422
|
-
if (newDevicesCount)
|
|
423
|
-
updateInfo('info', `Found new devices: ${newInMelCloud.ata.length ? `ATA: ${newInMelCloud.ata.length},` : ''} ${newInMelCloud.atw.length ? `ATW: ${newInMelCloud.atw.length},` : ''} ${newInMelCloud.erv.length ? `ERV: ${newInMelCloud.erv.length},` : ''}.`, 'green');
|
|
424
|
-
if (newPresetsCount)
|
|
425
|
-
updateInfo('info1', `Found new presets: ${newInMelCloud.ataPresets.length ? `ATA: ${newInMelCloud.ataPresets.length},` : ''} ${newInMelCloud.atwPresets.length ? `ATW: ${newInMelCloud.atwPresets.length},` : ''} ${newInMelCloud.ervPresets.length ? `ERV: ${newInMelCloud.ervPresets.length}` : ''}.`, 'green');
|
|
426
|
-
if (newScenesCount || newSchedulesCount)
|
|
427
|
-
updateInfo('info1', `Found new ${newSchedulesCount ? `schedules:` : ''} ${newInMelCloud.ataSchedules.length ? `ATA: ${newInMelCloud.ataSchedules.length},` : ''} ${newInMelCloud.atwSchedules.length ? `ATW: ${newInMelCloud.atwSchedules.length},` : ''} ${newInMelCloud.ervSchedules.length ? `ERV: ${newInMelCloud.ervSchedules.length},` : ''} ${newScenesCount ? `scenes: ${newScenesCount}` : ''}.`, 'green');
|
|
428
|
-
if (removedDevicesCount)
|
|
429
|
-
updateInfo('info2', `Removed devices: ${removedAta.length ? `ATA: ${removedAta.length},` : ''} ${removedAtw.length ? `ATW: ${removedAtw.length},` : ''} ${removedErv.length ? `ERV: ${removedErv.length}` : ''}.`, 'orange');
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
// Return filtered devicesInConfig to make sure upstream code uses it
|
|
357
|
+
return devicesInConfig;
|
|
358
|
+
} catch (error) {
|
|
359
|
+
updateInfo('info', `Error while processing device: ${JSON.stringify(error)}`, 'red');
|
|
430
360
|
}
|
|
361
|
+
};
|
|
431
362
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
363
|
+
account.ataDevices = handleDevices(devicesInMelCloudByType.ata, account.ataDevices, "Air Conditioner", newInMelCloud.ata, newInMelCloud.ataPresets, newInMelCloud.ataSchedules, newInMelCloud.scenes);
|
|
364
|
+
account.atwDevices = handleDevices(devicesInMelCloudByType.atw, account.atwDevices, "Heat Pump", newInMelCloud.atw, newInMelCloud.atwPresets, newInMelCloud.atwSchedules, newInMelCloud.scenes);
|
|
365
|
+
account.ervDevices = handleDevices(devicesInMelCloudByType.erv, account.ervDevices, "Energy Recovery Ventilation", newInMelCloud.erv, newInMelCloud.ervPresets, newInMelCloud.ervSchedules, newInMelCloud.scenes);
|
|
366
|
+
|
|
367
|
+
const newDevicesCount = newInMelCloud.ata.length + newInMelCloud.atw.length + newInMelCloud.erv.length;
|
|
368
|
+
const newPresetsCount = newInMelCloud.ataPresets.length + newInMelCloud.atwPresets.length + newInMelCloud.ervPresets.length;
|
|
369
|
+
const newSchedulesCount = newInMelCloud.ataSchedules.length + newInMelCloud.atwSchedules.length + newInMelCloud.ervSchedules.length;
|
|
370
|
+
const newScenesCount = newInMelCloud.scenes.length;
|
|
371
|
+
const removedDevicesCount = removedAta.length + removedAtw.length + removedErv.length;
|
|
372
|
+
|
|
373
|
+
if (!newDevicesCount && !newPresetsCount && !newSchedulesCount && !newScenesCount && !removedDevicesCount) {
|
|
374
|
+
updateInfo('info', 'No changes detected.', 'white');
|
|
375
|
+
} else {
|
|
376
|
+
if (newDevicesCount)
|
|
377
|
+
updateInfo('info', `Found new devices: ${newInMelCloud.ata.length ? `ATA: ${newInMelCloud.ata.length},` : ''} ${newInMelCloud.atw.length ? `ATW: ${newInMelCloud.atw.length},` : ''} ${newInMelCloud.erv.length ? `ERV: ${newInMelCloud.erv.length},` : ''}.`, 'green');
|
|
378
|
+
if (newPresetsCount)
|
|
379
|
+
updateInfo('info1', `Found new presets: ${newInMelCloud.ataPresets.length ? `ATA: ${newInMelCloud.ataPresets.length},` : ''} ${newInMelCloud.atwPresets.length ? `ATW: ${newInMelCloud.atwPresets.length},` : ''} ${newInMelCloud.ervPresets.length ? `ERV: ${newInMelCloud.ervPresets.length}` : ''}.`, 'green');
|
|
380
|
+
if (newScenesCount || newSchedulesCount)
|
|
381
|
+
updateInfo('info1', `Found new ${newSchedulesCount ? `schedules:` : ''} ${newInMelCloud.ataSchedules.length ? `ATA: ${newInMelCloud.ataSchedules.length},` : ''} ${newInMelCloud.atwSchedules.length ? `ATW: ${newInMelCloud.atwSchedules.length},` : ''} ${newInMelCloud.ervSchedules.length ? `ERV: ${newInMelCloud.ervSchedules.length},` : ''} ${newScenesCount ? `scenes: ${newScenesCount}` : ''}.`, 'green');
|
|
382
|
+
if (removedDevicesCount)
|
|
383
|
+
updateInfo('info2', `Removed devices: ${removedAta.length ? `ATA: ${removedAta.length},` : ''} ${removedAtw.length ? `ATW: ${removedAtw.length},` : ''} ${removedErv.length ? `ERV: ${removedErv.length}` : ''}.`, 'orange');
|
|
440
384
|
}
|
|
441
|
-
});
|
|
442
385
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
386
|
+
await homebridge.updatePluginConfig(pluginConfig);
|
|
387
|
+
await homebridge.savePluginConfig(pluginConfig);
|
|
388
|
+
} catch (error) {
|
|
389
|
+
updateInfo('info', `Prepare config error ${JSON.stringify(error)}`, 'red');
|
|
390
|
+
document.getElementById('logIn').className = "btn btn-secondary";
|
|
391
|
+
} finally {
|
|
392
|
+
document.getElementById('logIn').className = "btn btn-secondary";
|
|
393
|
+
homebridge.hideSpinner();
|
|
394
|
+
}
|
|
395
|
+
});
|
|
446
396
|
|
|
447
|
-
|
|
397
|
+
})();
|
|
398
|
+
</script>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "MELCloud Control",
|
|
3
3
|
"name": "homebridge-melcloud-control",
|
|
4
|
-
"version": "4.3.9-beta.
|
|
4
|
+
"version": "4.3.9-beta.10",
|
|
5
5
|
"description": "Homebridge plugin to control Mitsubishi Air Conditioner, Heat Pump and Energy Recovery Ventilation.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
package/src/constants.js
CHANGED
|
@@ -58,15 +58,19 @@ export const TemperatureDisplayUnits = ["°C", "°F"];
|
|
|
58
58
|
|
|
59
59
|
export const AirConditioner = {
|
|
60
60
|
SystemMapEnumToString: { 0: "Air Conditioner Off", 1: "Air Conditioner On", 2: "Air Conditioner Offline" },
|
|
61
|
-
OperationModeMapStringToEnum: { "0": 0, "Heat": 1, "Dry": 2, "Cool": 3, "4":
|
|
61
|
+
OperationModeMapStringToEnum: { "0": 0, "Heat": 1, "Dry": 2, "Cool": 3, "4": 4, "5": 5, "6": 6, "Fan": 7, "Automatic": 8, "Isee Heat": 9, "Isee Dry": 10, "Isee Cool": 11 },
|
|
62
62
|
OperationModeMapEnumToString: { 0: "0", 1: "Heat", 2: "Dry", 3: "Cool", 4: "4", 5: "5", 6: "6", 7: "Fan", 8: "Automatic", 9: "Isee Heat", 10: "Isee Dry", 11: "Isee Cool" },
|
|
63
|
+
OperationModeMapEnumToEnumWs: { 0: 0, 1: 1, 2: 2, 3: 3, 4: 7, 5: 8, 6: 9, 7: 10, 8: 11 },
|
|
63
64
|
FanSpeedMapStringToEnum: { "Auto": 0, "One": 1, "Two": 2, "Three": 3, "Four": 4, "Five": 5 },
|
|
64
65
|
FanSpeedMapEnumToString: { 0: "Auto", 1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five" },
|
|
66
|
+
AktualFanSpeedMapStringToEnum: { "Auto": 0, "One": 1, "Two": 2, "Three": 3, "Four": 4, "Five": 5 },
|
|
65
67
|
AktualFanSpeedMapEnumToString: { 0: "Quiet", 1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five" },
|
|
66
68
|
VaneVerticalDirectionMapStringToEnum: { "Auto": 0, "One": 1, "Two": 2, "Three": 3, "Four": 4, "Five": 5, "Six": 6, "Swing": 7 },
|
|
67
69
|
VaneVerticalDirectionMapEnumToString: { 0: "Auto", 1: "One", 2: "Two", 3: "Three", 4: "Four", 5: "Five", 6: "Six", 7: "Swing" },
|
|
70
|
+
VaneVerticalDirectionMapEnumToEnumWs: { 6: 7 },
|
|
68
71
|
VaneHorizontalDirectionMapStringToEnum: { "Auto": 0, "Left": 1, "LeftCentre": 2, "Centre": 3, "RightCentre": 4, "Right": 5, "Six": 6, "Seven": 7, "Split": 8, "Nine": 9, "Ten": 10, "Eleven": 11, "Swing": 12 },
|
|
69
72
|
VaneHorizontalDirectionMapEnumToString: { 0: "Auto", 1: "Left", 2: "LeftCentre", 3: "Centre", 4: "RightCentre", 5: "Right", 6: "Six", 7: "Seven", 8: "Split", 9: "Nine", 10: "Ten", 11: "Eleven", 12: "Swing" },
|
|
73
|
+
VaneHorizontalDirectionMapEnumToEnumWs: { 7: 12 },
|
|
70
74
|
AirDirectionMapEnumToString: { 0: "Auto", 1: "Swing" },
|
|
71
75
|
CurrentOperationModeMapEnumToStringHeatherCooler: { 0: "Inactive", 1: "Idle", 2: "Heating", 3: "Cooling" },
|
|
72
76
|
CurrentOperationModeMapEnumToStringThermostat: { 0: "Inactive", 1: "Heating", 2: "Cooling" },
|
package/src/deviceata.js
CHANGED
|
@@ -439,7 +439,8 @@ class DeviceAta extends EventEmitter {
|
|
|
439
439
|
if (supportsSwingFunction) {
|
|
440
440
|
melCloudService.getCharacteristic(Characteristic.SwingMode)
|
|
441
441
|
.onGet(async () => {
|
|
442
|
-
//Vane Horizontal: Auto, 1, 2, 3, 4, 5, 6, 7 =
|
|
442
|
+
//Vane Horizontal: Auto, 1, 2, 3, 4, 5, 6, 7 = Split, 12 = Swing //Vertical: Auto, 1, 2, 3, 4, 5, 7 = Swing
|
|
443
|
+
//Home Vane Horizontal: Auto, 1, 2, 3, 4, 5, 6, 7 = Swing, 8 = Split //Vertical: Auto, 1, 2, 3, 4, 5, 6 = Swing
|
|
443
444
|
const value = this.accessory.currentSwingMode;
|
|
444
445
|
return value;
|
|
445
446
|
})
|
package/src/melcloudata.js
CHANGED
|
@@ -35,6 +35,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
35
35
|
deviceData.Scenes = devicesData.Scenes ?? [];
|
|
36
36
|
|
|
37
37
|
//update state
|
|
38
|
+
if (!this.logDebug) this.emit('debug', `Request update device settings: ${JSON.stringify(deviceData.Device, null, 2)}`);
|
|
38
39
|
await this.updateState(deviceData);
|
|
39
40
|
}).on('webSocket', async (parsedMessage) => {
|
|
40
41
|
try {
|
|
@@ -62,9 +63,12 @@ class MelCloudAta extends EventEmitter {
|
|
|
62
63
|
|
|
63
64
|
//update device settings
|
|
64
65
|
if (key in deviceData.Device) {
|
|
65
|
-
|
|
66
|
+
let parsedValue = this.functions.convertValue(value);
|
|
67
|
+
deviceData.Device[key] = parsedValue;
|
|
66
68
|
}
|
|
67
69
|
}
|
|
70
|
+
|
|
71
|
+
if (!this.logDebug) this.emit('debug', `WS update device settings: ${JSON.stringify(deviceData.Device, null, 2)}`);
|
|
68
72
|
updateState = true;
|
|
69
73
|
break;
|
|
70
74
|
case 'unitHolidayModeTriggered':
|
|
@@ -88,21 +92,28 @@ class MelCloudAta extends EventEmitter {
|
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
//update state
|
|
91
|
-
if (updateState) await this.updateState(deviceData);
|
|
95
|
+
if (updateState) await this.updateState(deviceData, 'ws');
|
|
92
96
|
} catch (error) {
|
|
93
97
|
if (this.logError) this.emit('error', `Web socket process message error: ${error}`);
|
|
94
98
|
}
|
|
95
99
|
});
|
|
96
100
|
}
|
|
97
101
|
|
|
98
|
-
async updateState(deviceData) {
|
|
102
|
+
async updateState(deviceData, type) {
|
|
99
103
|
try {
|
|
100
104
|
if (this.accountType === 'melcloudhome') {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
|
|
106
|
+
if (type === 'ws') {
|
|
107
|
+
deviceData.Device.OperationMode = AirConditioner.OperationModeMapEnumToEnumWs[deviceData.Device.OperationMode] ?? deviceData.Device.OperationMode;
|
|
108
|
+
deviceData.Device.VaneHorizontalDirection = AirConditioner.VaneHorizontalDirectionMapEnumToEnumWs[deviceData.Device.VaneHorizontalDirection] ?? deviceData.Device.VaneHorizontalDirection;
|
|
109
|
+
deviceData.Device.VaneVerticalDirection = AirConditioner.VaneVerticalDirectionMapEnumToEnumWs[deviceData.Device.VaneVerticalDirection] ?? deviceData.Device.VaneVerticalDirection;
|
|
110
|
+
} else {
|
|
111
|
+
deviceData.Device.OperationMode = AirConditioner.OperationModeMapStringToEnum[deviceData.Device.OperationMode] ?? deviceData.Device.OperationMode;
|
|
112
|
+
deviceData.Device.ActualFanSpeed = AirConditioner.AktualFanSpeedMapStringToEnum[deviceData.Device.ActualFanSpeed] ?? deviceData.Device.ActualFanSpeed;
|
|
113
|
+
deviceData.Device.SetFanSpeed = AirConditioner.FanSpeedMapStringToEnum[deviceData.Device.SetFanSpeed] ?? deviceData.Device.SetFanSpeed;
|
|
114
|
+
deviceData.Device.VaneHorizontalDirection = AirConditioner.VaneHorizontalDirectionMapStringToEnum[deviceData.Device.VaneHorizontalDirection] ?? deviceData.Device.VaneHorizontalDirection;
|
|
115
|
+
deviceData.Device.VaneVerticalDirection = AirConditioner.VaneVerticalDirectionMapStringToEnum[deviceData.Device.VaneVerticalDirection] ?? deviceData.Device.VaneVerticalDirection;
|
|
116
|
+
}
|
|
106
117
|
|
|
107
118
|
//read default temps
|
|
108
119
|
const temps = await this.functions.readData(this.defaultTempsFile, true);
|
|
@@ -224,7 +235,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
224
235
|
}
|
|
225
236
|
|
|
226
237
|
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}`);
|
|
227
|
-
|
|
238
|
+
|
|
228
239
|
await axios(path, {
|
|
229
240
|
method: 'POST',
|
|
230
241
|
baseURL: ApiUrls.BaseURL,
|
|
@@ -313,7 +324,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
313
324
|
//sens payload
|
|
314
325
|
headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
315
326
|
headers.Origin = ApiUrlsHome.Origin;
|
|
316
|
-
if (this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}`);
|
|
327
|
+
if (!this.logDebug) this.emit('debug', `Send Data: ${JSON.stringify(payload, null, 2)}`);
|
|
317
328
|
|
|
318
329
|
await axios(path, {
|
|
319
330
|
method: method,
|