homebridge-melcloud-control 4.4.1-beta.1 → 4.4.1-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/README.md +29 -29
- package/config.schema.json +64 -64
- package/index.js +32 -32
- package/package.json +2 -2
- package/src/constants.js +62 -50
- package/src/deviceata.js +2 -6
- package/src/deviceatw.js +2 -6
- package/src/deviceerv.js +25 -30
- package/src/functions.js +120 -94
- package/src/melcloud.js +4 -4
- package/src/melcloudata.js +15 -11
- package/src/melcloudatw.js +14 -10
- package/src/melclouderv.js +20 -8
- package/src/melcloudhome.js +39 -22
package/src/functions.js
CHANGED
|
@@ -56,161 +56,187 @@ class Functions extends EventEmitter {
|
|
|
56
56
|
|
|
57
57
|
async ensureChromiumInstalled() {
|
|
58
58
|
try {
|
|
59
|
-
|
|
60
|
-
const { stdout: osOut } = await execPromise("uname -s");
|
|
59
|
+
const { stdout: osOut } = await execPromise('uname -s');
|
|
61
60
|
const osName = osOut.trim();
|
|
62
|
-
|
|
61
|
+
|
|
62
|
+
const { stdout: archOut } = await execPromise('uname -m');
|
|
63
63
|
const arch = archOut.trim();
|
|
64
64
|
|
|
65
|
-
const isARM =
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
const isARM =
|
|
66
|
+
arch.startsWith('arm') ||
|
|
67
|
+
arch.startsWith('aarch64') ||
|
|
68
|
+
arch.startsWith('aarch');
|
|
69
|
+
|
|
70
|
+
const isMac = osName === 'Darwin';
|
|
71
|
+
const isLinux = osName === 'Linux';
|
|
72
|
+
const isQnap = fs.existsSync('/etc/config/uLinux.conf') || fs.existsSync('/etc/config/qpkg.conf');
|
|
68
73
|
|
|
69
74
|
// Detect Docker
|
|
70
75
|
let isDocker = false;
|
|
71
76
|
try {
|
|
72
|
-
await access(
|
|
77
|
+
await access('/.dockerenv');
|
|
73
78
|
isDocker = true;
|
|
74
79
|
} catch { }
|
|
80
|
+
|
|
75
81
|
try {
|
|
76
|
-
const { stdout } = await execPromise(
|
|
77
|
-
if (stdout.includes(
|
|
82
|
+
const { stdout } = await execPromise('cat /proc/1/cgroup || true');
|
|
83
|
+
if (stdout.includes('docker') || stdout.includes('containerd')) {
|
|
84
|
+
isDocker = true;
|
|
85
|
+
}
|
|
78
86
|
} catch { }
|
|
79
87
|
|
|
80
|
-
|
|
88
|
+
/* ===================== macOS ===================== */
|
|
81
89
|
if (isMac) {
|
|
82
90
|
const macCandidates = [
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
92
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium'
|
|
85
93
|
];
|
|
86
|
-
|
|
94
|
+
|
|
95
|
+
for (const path of macCandidates) {
|
|
87
96
|
try {
|
|
88
|
-
await access(
|
|
89
|
-
return
|
|
97
|
+
await access(path, fs.constants.X_OK);
|
|
98
|
+
return path;
|
|
90
99
|
} catch { }
|
|
91
100
|
}
|
|
92
|
-
|
|
101
|
+
|
|
102
|
+
// macOS → Puppeteer fallback is OK
|
|
103
|
+
try {
|
|
104
|
+
return puppeteer.executablePath();
|
|
105
|
+
} catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
93
108
|
}
|
|
94
109
|
|
|
95
|
-
|
|
96
|
-
if (
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
"/snap/bin/chromium"
|
|
110
|
+
/* ===================== QNAP ===================== */
|
|
111
|
+
if (isQnap) {
|
|
112
|
+
const entwareChromiumCandidates = [
|
|
113
|
+
'/opt/bin/chromium',
|
|
114
|
+
'/opt/bin/chromium-browser'
|
|
101
115
|
];
|
|
102
116
|
|
|
103
|
-
//
|
|
104
|
-
for (const
|
|
117
|
+
// Check existing Entware Chromium
|
|
118
|
+
for (const path of entwareChromiumCandidates) {
|
|
105
119
|
try {
|
|
106
|
-
await access(
|
|
107
|
-
return
|
|
120
|
+
await access(path, fs.constants.X_OK);
|
|
121
|
+
return path;
|
|
108
122
|
} catch { }
|
|
109
123
|
}
|
|
110
124
|
|
|
111
|
-
//
|
|
112
|
-
|
|
125
|
+
// Try installing via Entware
|
|
126
|
+
try {
|
|
127
|
+
await access('/opt/bin/opkg', fs.constants.X_OK);
|
|
128
|
+
|
|
129
|
+
await execPromise('/opt/bin/opkg update');
|
|
130
|
+
await execPromise(
|
|
131
|
+
'/opt/bin/opkg install chromium nspr nss libx11 libxcomposite libxdamage libxrandr atk libcups libdrm libgbm alsa-lib'
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// Ensure Entware libs are visible
|
|
135
|
+
process.env.LD_LIBRARY_PATH =
|
|
136
|
+
`/opt/lib:${process.env.LD_LIBRARY_PATH || ''}`;
|
|
137
|
+
|
|
138
|
+
} catch {
|
|
139
|
+
// opkg missing or install failed
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Retry after install
|
|
144
|
+
for (const path of entwareChromiumCandidates) {
|
|
113
145
|
try {
|
|
114
|
-
await
|
|
146
|
+
await access(path, fs.constants.X_OK);
|
|
147
|
+
return path;
|
|
115
148
|
} catch { }
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* ===================== ARM Linux ===================== */
|
|
155
|
+
if (isLinux && isARM) {
|
|
156
|
+
const armCandidates = [
|
|
157
|
+
'/usr/bin/chromium-browser',
|
|
158
|
+
'/usr/bin/chromium',
|
|
159
|
+
'/snap/bin/chromium'
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
for (const path of armCandidates) {
|
|
116
163
|
try {
|
|
117
|
-
await
|
|
164
|
+
await access(path, fs.constants.X_OK);
|
|
165
|
+
return path;
|
|
118
166
|
} catch { }
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Try auto-install (only if not Docker)
|
|
170
|
+
if (!isDocker) {
|
|
119
171
|
try {
|
|
120
|
-
await execPromise(
|
|
172
|
+
await execPromise('sudo apt-get update -y');
|
|
173
|
+
await execPromise(
|
|
174
|
+
'sudo apt-get install -y chromium chromium-browser chromium-codecs-ffmpeg || true'
|
|
175
|
+
);
|
|
121
176
|
} catch { }
|
|
122
177
|
}
|
|
123
178
|
|
|
124
|
-
// Retry after
|
|
125
|
-
for (const
|
|
179
|
+
// Retry after install
|
|
180
|
+
for (const path of armCandidates) {
|
|
126
181
|
try {
|
|
127
|
-
await access(
|
|
128
|
-
return
|
|
182
|
+
await access(path, fs.constants.X_OK);
|
|
183
|
+
return path;
|
|
129
184
|
} catch { }
|
|
130
185
|
}
|
|
131
186
|
|
|
187
|
+
// ARM → NO Puppeteer fallback
|
|
132
188
|
return null;
|
|
133
189
|
}
|
|
134
190
|
|
|
135
|
-
|
|
136
|
-
let entwareExists = false;
|
|
137
|
-
try {
|
|
138
|
-
await access("/opt/bin/opkg", fs.constants.X_OK);
|
|
139
|
-
entwareExists = true;
|
|
140
|
-
} catch { }
|
|
141
|
-
|
|
142
|
-
if (entwareExists) {
|
|
143
|
-
try {
|
|
144
|
-
await execPromise("/opt/bin/opkg update");
|
|
145
|
-
await execPromise("/opt/bin/opkg install nspr nss libx11 libxcomposite libxdamage libxrandr atk libcups libdrm libgbm alsa-lib");
|
|
146
|
-
process.env.LD_LIBRARY_PATH = `/opt/lib:${process.env.LD_LIBRARY_PATH || ""}`;
|
|
147
|
-
} catch { }
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Synology DSM 7
|
|
151
|
-
const synoCandidates = [
|
|
152
|
-
"/var/packages/Chromium/target/usr/bin/chromium",
|
|
153
|
-
"/usr/local/chromium/bin/chromium"
|
|
154
|
-
];
|
|
155
|
-
for (const p of synoCandidates) {
|
|
156
|
-
try {
|
|
157
|
-
await access(p, fs.constants.X_OK);
|
|
158
|
-
return p;
|
|
159
|
-
} catch { }
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Linux x64
|
|
191
|
+
/* ===================== Linux x64 ===================== */
|
|
163
192
|
if (isLinux) {
|
|
164
193
|
const linuxCandidates = [
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
194
|
+
'/usr/bin/chromium',
|
|
195
|
+
'/usr/bin/chromium-browser',
|
|
196
|
+
'/usr/bin/google-chrome',
|
|
197
|
+
'/snap/bin/chromium',
|
|
198
|
+
'/usr/local/bin/chromium'
|
|
170
199
|
];
|
|
171
200
|
|
|
172
201
|
try {
|
|
173
|
-
const { stdout } = await execPromise(
|
|
174
|
-
|
|
175
|
-
|
|
202
|
+
const { stdout } = await execPromise(
|
|
203
|
+
'which chromium || which chromium-browser || which google-chrome || true'
|
|
204
|
+
);
|
|
205
|
+
if (stdout.trim()) return stdout.trim();
|
|
176
206
|
} catch { }
|
|
177
207
|
|
|
178
|
-
for (const
|
|
208
|
+
for (const path of linuxCandidates) {
|
|
179
209
|
try {
|
|
180
|
-
await access(
|
|
181
|
-
return
|
|
210
|
+
await access(path, fs.constants.X_OK);
|
|
211
|
+
return path;
|
|
182
212
|
} catch { }
|
|
183
213
|
}
|
|
184
214
|
|
|
185
|
-
// Docker
|
|
215
|
+
// Docker x64 → try install
|
|
186
216
|
if (isDocker) {
|
|
187
217
|
try {
|
|
188
|
-
await execPromise(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
await access(
|
|
192
|
-
return
|
|
218
|
+
await execPromise(
|
|
219
|
+
'apt-get update -y && apt-get install -y chromium || true'
|
|
220
|
+
);
|
|
221
|
+
await access('/usr/bin/chromium', fs.constants.X_OK);
|
|
222
|
+
return '/usr/bin/chromium';
|
|
193
223
|
} catch { }
|
|
194
224
|
}
|
|
195
225
|
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
];
|
|
202
|
-
for (const cmd of depCommands) {
|
|
203
|
-
try {
|
|
204
|
-
await execPromise(`sudo ${cmd}`);
|
|
205
|
-
} catch { }
|
|
226
|
+
// Linux x64 → Puppeteer fallback OK
|
|
227
|
+
try {
|
|
228
|
+
return puppeteer.executablePath();
|
|
229
|
+
} catch {
|
|
230
|
+
return null;
|
|
206
231
|
}
|
|
207
|
-
|
|
208
|
-
return null;
|
|
209
232
|
}
|
|
210
233
|
|
|
234
|
+
|
|
211
235
|
return null;
|
|
212
|
-
} catch (
|
|
213
|
-
if (this.logError)
|
|
236
|
+
} catch (error) {
|
|
237
|
+
if (this.logError) {
|
|
238
|
+
this.emit('error', `Chromium detection error: ${error.message}`);
|
|
239
|
+
}
|
|
214
240
|
return null;
|
|
215
241
|
}
|
|
216
242
|
}
|
package/src/melcloud.js
CHANGED
|
@@ -56,7 +56,7 @@ class MelCloud extends EventEmitter {
|
|
|
56
56
|
try {
|
|
57
57
|
const devicesList = { State: false, Info: null, Devices: [], Scenes: [] }
|
|
58
58
|
if (this.logDebug) this.emit('debug', `Scanning for devices...`);
|
|
59
|
-
const listDevicesData = await this.client(ApiUrls.ListDevices, { method: 'GET', });
|
|
59
|
+
const listDevicesData = await this.client(ApiUrls.Get.ListDevices, { method: 'GET', });
|
|
60
60
|
|
|
61
61
|
if (!listDevicesData || !listDevicesData.data) {
|
|
62
62
|
devicesList.Info = 'Invalid or empty response from MELCloud API'
|
|
@@ -132,9 +132,9 @@ class MelCloud extends EventEmitter {
|
|
|
132
132
|
CaptchaResponse: '',
|
|
133
133
|
Persist: true
|
|
134
134
|
};
|
|
135
|
-
const accountData = await axios(ApiUrls.ClientLogin, {
|
|
135
|
+
const accountData = await axios(ApiUrls.Post.ClientLogin, {
|
|
136
136
|
method: 'POST',
|
|
137
|
-
baseURL: ApiUrls.
|
|
137
|
+
baseURL: ApiUrls.Base,
|
|
138
138
|
timeout: 15000,
|
|
139
139
|
data: payload
|
|
140
140
|
});
|
|
@@ -164,7 +164,7 @@ class MelCloud extends EventEmitter {
|
|
|
164
164
|
};
|
|
165
165
|
|
|
166
166
|
this.client = axios.create({
|
|
167
|
-
baseURL: ApiUrls.
|
|
167
|
+
baseURL: ApiUrls.Base,
|
|
168
168
|
timeout: 30000,
|
|
169
169
|
headers: headers
|
|
170
170
|
});
|
package/src/melcloudata.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
import Functions from './functions.js';
|
|
3
|
-
import { ApiUrls,
|
|
3
|
+
import { ApiUrls, AirConditioner } from './constants.js';
|
|
4
4
|
|
|
5
5
|
class MelCloudAta extends EventEmitter {
|
|
6
6
|
constructor(account, device, defaultTempsFile, accountFile, melcloud) {
|
|
@@ -204,7 +204,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
204
204
|
case 'account':
|
|
205
205
|
flagData.Account.LoginData.UseFahrenheit = flagData.UseFahrenheit;
|
|
206
206
|
payload = { data: flagData.LoginData };
|
|
207
|
-
path = ApiUrls.UpdateApplicationOptions;
|
|
207
|
+
path = ApiUrls.Post.UpdateApplicationOptions;
|
|
208
208
|
await this.functions.saveData(this.accountFile, flagData);
|
|
209
209
|
break;
|
|
210
210
|
default:
|
|
@@ -230,14 +230,19 @@ class MelCloudAta extends EventEmitter {
|
|
|
230
230
|
HideDryModeControl: deviceData.HideDryModeControl,
|
|
231
231
|
HasPendingCommand: true
|
|
232
232
|
};
|
|
233
|
-
path = ApiUrls.
|
|
233
|
+
path = ApiUrls.Post.Ata;
|
|
234
|
+
update = true;
|
|
234
235
|
break;
|
|
235
236
|
}
|
|
236
237
|
|
|
237
238
|
if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
|
|
238
239
|
await this.client(path, { method: 'POST', data: payload });
|
|
239
240
|
|
|
240
|
-
|
|
241
|
+
if (update) {
|
|
242
|
+
setTimeout(() => {
|
|
243
|
+
this.emit('deviceState', deviceData);
|
|
244
|
+
}, 500);
|
|
245
|
+
}
|
|
241
246
|
return true;
|
|
242
247
|
case "melcloudhome":
|
|
243
248
|
switch (flag) {
|
|
@@ -249,7 +254,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
249
254
|
units: { ATA: [deviceData.DeviceID] }
|
|
250
255
|
};
|
|
251
256
|
method = 'POST';
|
|
252
|
-
path =
|
|
257
|
+
path = ApiUrls.Home.Post.ProtectionFrost;
|
|
253
258
|
update = true;
|
|
254
259
|
break;
|
|
255
260
|
case 'overheatprotection':
|
|
@@ -260,7 +265,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
260
265
|
units: { ATA: [deviceData.DeviceID] }
|
|
261
266
|
};
|
|
262
267
|
method = 'POST';
|
|
263
|
-
path =
|
|
268
|
+
path = ApiUrls.Home.Post.ProtectionOverheat;
|
|
264
269
|
update = true;
|
|
265
270
|
break;
|
|
266
271
|
case 'holidaymode':
|
|
@@ -271,17 +276,17 @@ class MelCloudAta extends EventEmitter {
|
|
|
271
276
|
units: { ATA: [deviceData.DeviceID] }
|
|
272
277
|
};
|
|
273
278
|
method = 'POST';
|
|
274
|
-
path =
|
|
279
|
+
path = ApiUrls.Home.Post.HolidayMode;
|
|
275
280
|
break;
|
|
276
281
|
case 'schedule':
|
|
277
282
|
payload = { enabled: deviceData.ScheduleEnabled };
|
|
278
283
|
method = 'PUT';
|
|
279
|
-
path =
|
|
284
|
+
path = ApiUrls.Home.Put.ScheduleEnableDisable.Home.replace('deviceid', deviceData.DeviceID);
|
|
280
285
|
update = true;
|
|
281
286
|
break;
|
|
282
287
|
case 'scene':
|
|
283
288
|
method = 'PUT';
|
|
284
|
-
path =
|
|
289
|
+
path = `${ApiUrls.Home.Put.SceneEnableDisable.replace('sceneid', flagData.Id)}${flagData.Enabled ? 'enable' : 'disable'}`;
|
|
285
290
|
break;
|
|
286
291
|
default:
|
|
287
292
|
if (displayType === 1 && deviceData.Device.OperationMode === 8) {
|
|
@@ -307,7 +312,7 @@ class MelCloudAta extends EventEmitter {
|
|
|
307
312
|
inStandbyMode: null
|
|
308
313
|
};
|
|
309
314
|
method = 'PUT';
|
|
310
|
-
path =
|
|
315
|
+
path = ApiUrls.Home.Put.Ata.replace('deviceid', deviceData.DeviceID);
|
|
311
316
|
break;
|
|
312
317
|
}
|
|
313
318
|
|
|
@@ -320,7 +325,6 @@ class MelCloudAta extends EventEmitter {
|
|
|
320
325
|
this.emit('deviceState', deviceData);
|
|
321
326
|
}, 500);
|
|
322
327
|
}
|
|
323
|
-
|
|
324
328
|
return true;
|
|
325
329
|
default:
|
|
326
330
|
return;
|
package/src/melcloudatw.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
import Functions from './functions.js';
|
|
3
|
-
import { ApiUrls,
|
|
3
|
+
import { ApiUrls, HeatPump } from './constants.js';
|
|
4
4
|
|
|
5
5
|
class MelCloudAtw extends EventEmitter {
|
|
6
6
|
constructor(account, device, defaultTempsFile, accountFile, melcloud) {
|
|
@@ -204,7 +204,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
204
204
|
case 'account':
|
|
205
205
|
flagData.Account.LoginData.UseFahrenheit = flagData.UseFahrenheit;
|
|
206
206
|
payload = { data: flagData.LoginData };
|
|
207
|
-
path = ApiUrls.UpdateApplicationOptions;
|
|
207
|
+
path = ApiUrls.Post.UpdateApplicationOptions;
|
|
208
208
|
await this.functions.saveData(this.accountFile, flagData);
|
|
209
209
|
break;
|
|
210
210
|
default:
|
|
@@ -231,14 +231,19 @@ class MelCloudAtw extends EventEmitter {
|
|
|
231
231
|
ProhibitHotWater: deviceData.Device.ProhibitHotWater,
|
|
232
232
|
HasPendingCommand: true
|
|
233
233
|
}
|
|
234
|
-
path = ApiUrls.
|
|
234
|
+
path = ApiUrls.Post.Atw;
|
|
235
|
+
update = true;
|
|
235
236
|
break;
|
|
236
237
|
}
|
|
237
238
|
|
|
238
239
|
if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
|
|
239
240
|
await this.client(path, { method: 'POST', data: payload });
|
|
240
241
|
|
|
241
|
-
|
|
242
|
+
if (update) {
|
|
243
|
+
setTimeout(() => {
|
|
244
|
+
this.emit('deviceState', deviceData);
|
|
245
|
+
}, 500);
|
|
246
|
+
}
|
|
242
247
|
return true;
|
|
243
248
|
case "melcloudhome":
|
|
244
249
|
switch (flag) {
|
|
@@ -250,7 +255,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
250
255
|
units: { ATA: [deviceData.DeviceID] }
|
|
251
256
|
};
|
|
252
257
|
method = 'POST';
|
|
253
|
-
path =
|
|
258
|
+
path = ApiUrls.Home.Post.ProtectionFrost;
|
|
254
259
|
update = true;
|
|
255
260
|
break;
|
|
256
261
|
case 'holidaymode':
|
|
@@ -261,17 +266,17 @@ class MelCloudAtw extends EventEmitter {
|
|
|
261
266
|
units: { ATW: [deviceData.DeviceID] }
|
|
262
267
|
};
|
|
263
268
|
method = 'POST';
|
|
264
|
-
path =
|
|
269
|
+
path = ApiUrls.Home.Post.HolidayMode;
|
|
265
270
|
break;
|
|
266
271
|
case 'schedule':
|
|
267
272
|
payload = { enabled: deviceData.ScheduleEnabled };
|
|
268
273
|
method = 'PUT';
|
|
269
|
-
path =
|
|
274
|
+
path = ApiUrls.Home.Put.ScheduleEnableDisable.Home.replace('deviceid', deviceData.DeviceID);
|
|
270
275
|
update = true;
|
|
271
276
|
break;
|
|
272
277
|
case 'scene':
|
|
273
278
|
method = 'PUT';
|
|
274
|
-
path =
|
|
279
|
+
path = `${ApiUrls.Home.Put.SceneEnableDisable.replace('sceneid', flagData.Id)}${flagData.Enabled ? 'enable' : 'disable'}`;
|
|
275
280
|
break;
|
|
276
281
|
default:
|
|
277
282
|
payload = {
|
|
@@ -290,7 +295,7 @@ class MelCloudAtw extends EventEmitter {
|
|
|
290
295
|
ecoHotWater: deviceData.Device.EcoHotWater,
|
|
291
296
|
};
|
|
292
297
|
method = 'PUT';
|
|
293
|
-
path =
|
|
298
|
+
path = ApiUrls.Home.Put.Atw.replace('deviceid', deviceData.DeviceID);
|
|
294
299
|
break
|
|
295
300
|
}
|
|
296
301
|
|
|
@@ -302,7 +307,6 @@ class MelCloudAtw extends EventEmitter {
|
|
|
302
307
|
this.emit('deviceState', deviceData);
|
|
303
308
|
}, 500);
|
|
304
309
|
}
|
|
305
|
-
|
|
306
310
|
return true;
|
|
307
311
|
default:
|
|
308
312
|
return;
|
package/src/melclouderv.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import EventEmitter from 'events';
|
|
2
2
|
import Functions from './functions.js';
|
|
3
|
-
import { ApiUrls,
|
|
3
|
+
import { ApiUrls, Ventilation } from './constants.js';
|
|
4
4
|
|
|
5
5
|
class MelCloudErv extends EventEmitter {
|
|
6
6
|
constructor(account, device, defaultTempsFile, accountFile, melcloud) {
|
|
@@ -182,13 +182,14 @@ class MelCloudErv extends EventEmitter {
|
|
|
182
182
|
let method = null
|
|
183
183
|
let payload = {};
|
|
184
184
|
let path = '';
|
|
185
|
+
let update = false;
|
|
185
186
|
switch (accountType) {
|
|
186
187
|
case "melcloud":
|
|
187
188
|
switch (flag) {
|
|
188
189
|
case 'account':
|
|
189
190
|
flagData.Account.LoginData.UseFahrenheit = flagData.UseFahrenheit;
|
|
190
191
|
payload = { data: flagData.LoginData };
|
|
191
|
-
path = ApiUrls.UpdateApplicationOptions;
|
|
192
|
+
path = ApiUrls.Post.UpdateApplicationOptions;
|
|
192
193
|
await this.functions.saveData(this.accountFile, flagData);
|
|
193
194
|
break;
|
|
194
195
|
default:
|
|
@@ -230,14 +231,19 @@ class MelCloudErv extends EventEmitter {
|
|
|
230
231
|
NightPurgeMode: deviceData.Device.NightPurgeMode,
|
|
231
232
|
HasPendingCommand: true
|
|
232
233
|
}
|
|
233
|
-
path = ApiUrls.
|
|
234
|
+
path = ApiUrls.Post.Erv;
|
|
235
|
+
update = true;
|
|
234
236
|
break;
|
|
235
237
|
}
|
|
236
238
|
|
|
237
239
|
if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
|
|
238
240
|
await this.client(path, { method: 'POST', data: payload });
|
|
239
241
|
|
|
240
|
-
|
|
242
|
+
if (update) {
|
|
243
|
+
setTimeout(() => {
|
|
244
|
+
this.emit('deviceState', deviceData);
|
|
245
|
+
}, 500);
|
|
246
|
+
} this.emit('deviceState', deviceData);
|
|
241
247
|
return true;
|
|
242
248
|
case "melcloudhome":
|
|
243
249
|
switch (flag) {
|
|
@@ -249,16 +255,17 @@ class MelCloudErv extends EventEmitter {
|
|
|
249
255
|
units: { ERV: [deviceData.DeviceID] }
|
|
250
256
|
};
|
|
251
257
|
method = 'POST';
|
|
252
|
-
path =
|
|
258
|
+
path = ApiUrls.Home.Post.HolidayMode;
|
|
253
259
|
break;
|
|
254
260
|
case 'schedule':
|
|
255
261
|
payload = { enabled: deviceData.ScheduleEnabled };
|
|
256
262
|
method = 'PUT';
|
|
257
|
-
path =
|
|
263
|
+
path = ApiUrls.Home.Put.ScheduleEnableDisable.Home.replace('deviceid', deviceData.DeviceID);
|
|
264
|
+
update = true;
|
|
258
265
|
break;
|
|
259
266
|
case 'scene':
|
|
260
267
|
method = 'PUT';
|
|
261
|
-
path =
|
|
268
|
+
path = `${ApiUrls.Home.Put.SceneEnableDisable.replace('sceneid', flagData.Id)}${flagData.Enabled ? 'enable' : 'disable'}`;
|
|
262
269
|
break;
|
|
263
270
|
default:
|
|
264
271
|
if (displayType === 1 && deviceData.Device.VentilationMode === 2) {
|
|
@@ -281,13 +288,18 @@ class MelCloudErv extends EventEmitter {
|
|
|
281
288
|
ventilationMode: Ventilation.VentilationModeMapEnumToString[deviceData.Device.VentilationMode],
|
|
282
289
|
};
|
|
283
290
|
method = 'PUT';
|
|
284
|
-
path =
|
|
291
|
+
path = ApiUrls.Home.Put.Erv.replace('deviceid', deviceData.DeviceID);
|
|
285
292
|
break
|
|
286
293
|
}
|
|
287
294
|
|
|
288
295
|
if (this.logDebug) this.emit('debug', `Send data: ${JSON.stringify(payload, null, 2)}`);
|
|
289
296
|
await this.client(path, { method: method, data: payload });
|
|
290
297
|
|
|
298
|
+
if (update) {
|
|
299
|
+
setTimeout(() => {
|
|
300
|
+
this.emit('deviceState', deviceData);
|
|
301
|
+
}, 500);
|
|
302
|
+
}
|
|
291
303
|
return true;
|
|
292
304
|
default:
|
|
293
305
|
return;
|