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/src/functions.js CHANGED
@@ -56,161 +56,187 @@ class Functions extends EventEmitter {
56
56
 
57
57
  async ensureChromiumInstalled() {
58
58
  try {
59
- // Detect OS
60
- const { stdout: osOut } = await execPromise("uname -s");
59
+ const { stdout: osOut } = await execPromise('uname -s');
61
60
  const osName = osOut.trim();
62
- const { stdout: archOut } = await execPromise("uname -m");
61
+
62
+ const { stdout: archOut } = await execPromise('uname -m');
63
63
  const arch = archOut.trim();
64
64
 
65
- const isARM = arch.startsWith("arm") || arch.startsWith("aarch64") || arch.startsWith("aarch");
66
- const isMac = osName === "Darwin";
67
- const isLinux = osName === "Linux";
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("/.dockerenv");
77
+ await access('/.dockerenv');
73
78
  isDocker = true;
74
79
  } catch { }
80
+
75
81
  try {
76
- const { stdout } = await execPromise("cat /proc/1/cgroup || true");
77
- if (stdout.includes("docker") || stdout.includes("containerd")) isDocker = true;
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
- // macOS
88
+ /* ===================== macOS ===================== */
81
89
  if (isMac) {
82
90
  const macCandidates = [
83
- "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
84
- "/Applications/Chromium.app/Contents/MacOS/Chromium"
91
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
92
+ '/Applications/Chromium.app/Contents/MacOS/Chromium'
85
93
  ];
86
- for (const p of macCandidates) {
94
+
95
+ for (const path of macCandidates) {
87
96
  try {
88
- await access(p, fs.constants.X_OK);
89
- return p;
97
+ await access(path, fs.constants.X_OK);
98
+ return path;
90
99
  } catch { }
91
100
  }
92
- return null;
101
+
102
+ // macOS → Puppeteer fallback is OK
103
+ try {
104
+ return puppeteer.executablePath();
105
+ } catch {
106
+ return null;
107
+ }
93
108
  }
94
109
 
95
- // ARM / Raspberry Pi
96
- if (isARM && isLinux) {
97
- const armCandidates = [
98
- "/usr/bin/chromium-browser",
99
- "/usr/bin/chromium",
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
- // Try existing
104
- for (const p of armCandidates) {
117
+ // Check existing Entware Chromium
118
+ for (const path of entwareChromiumCandidates) {
105
119
  try {
106
- await access(p, fs.constants.X_OK);
107
- return p;
120
+ await access(path, fs.constants.X_OK);
121
+ return path;
108
122
  } catch { }
109
123
  }
110
124
 
111
- // If not in Docker, try apt installation
112
- if (!isDocker) {
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 execPromise("sudo apt-get update -y");
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 execPromise("sudo apt-get install -y chromium-browser chromium-codecs-ffmpeg || true");
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("sudo apt-get install -y chromium || true");
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 installation
125
- for (const p of armCandidates) {
179
+ // Retry after install
180
+ for (const path of armCandidates) {
126
181
  try {
127
- await access(p, fs.constants.X_OK);
128
- return p;
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
- // QNAP / Entware
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
- "/usr/bin/chromium",
166
- "/usr/bin/chromium-browser",
167
- "/usr/bin/google-chrome",
168
- "/snap/bin/chromium",
169
- "/usr/local/bin/chromium"
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("which chromium || which chromium-browser || which google-chrome || true");
174
- const found = stdout.trim();
175
- if (found) return found;
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 p of linuxCandidates) {
208
+ for (const path of linuxCandidates) {
179
209
  try {
180
- await access(p, fs.constants.X_OK);
181
- return p;
210
+ await access(path, fs.constants.X_OK);
211
+ return path;
182
212
  } catch { }
183
213
  }
184
214
 
185
- // Docker: try installing chromium inside container (if allowed)
215
+ // Docker x64 try install
186
216
  if (isDocker) {
187
217
  try {
188
- await execPromise("apt-get update -y && apt-get install -y chromium || true");
189
- } catch { }
190
- try {
191
- await access("/usr/bin/chromium", fs.constants.X_OK);
192
- return "/usr/bin/chromium";
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
- // Install missing libraries
197
- const depCommands = [
198
- "apt-get update -y && apt-get install -y libnspr4 libnss3 libx11-6 libxcomposite1 libxdamage1 libxrandr2 libatk1.0-0 libcups2 libdrm2 libgbm1 libasound2 || true",
199
- "yum install -y nspr nss libX11 libXcomposite libXdamage libXrandr atk cups libdrm libgbm alsa-lib || true",
200
- "apk add --no-cache nspr nss libx11 libxcomposite libxdamage libxrandr atk cups libdrm libgbm alsa-lib || true"
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 (err) {
213
- if (this.logError) this.emit("error", `Chromium detection error: ${err.message}`);
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.BaseURL,
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.BaseURL,
167
+ baseURL: ApiUrls.Base,
168
168
  timeout: 30000,
169
169
  headers: headers
170
170
  });
@@ -1,6 +1,6 @@
1
1
  import EventEmitter from 'events';
2
2
  import Functions from './functions.js';
3
- import { ApiUrls, ApiUrlsHome, AirConditioner } from './constants.js';
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.SetAta;
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
- this.emit('deviceState', deviceData);
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 = ApiUrlsHome.PostProtectionFrost;
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 = ApiUrlsHome.PostProtectionOverheat;
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 = ApiUrlsHome.PostHolidayMode;
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 = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
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 = ApiUrlsHome.PutScene[flagData.Enabled ? 'Enable' : 'Disable'].replace('sceneid', flagData.Id);
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 = ApiUrlsHome.PutAta.replace('deviceid', deviceData.DeviceID);
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;
@@ -1,6 +1,6 @@
1
1
  import EventEmitter from 'events';
2
2
  import Functions from './functions.js';
3
- import { ApiUrls, ApiUrlsHome, HeatPump } from './constants.js';
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.SetAtw;
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
- this.emit('deviceState', deviceData);
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 = ApiUrlsHome.PostProtectionFrost;
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 = ApiUrlsHome.PostHolidayMode;
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 = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
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 = ApiUrlsHome.PutScene[flagData.Enabled ? 'Enable' : 'Disable'].replace('sceneid', flagData.Id);
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 = ApiUrlsHome.PutAtw.replace('deviceid', deviceData.DeviceID);
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;
@@ -1,6 +1,6 @@
1
1
  import EventEmitter from 'events';
2
2
  import Functions from './functions.js';
3
- import { ApiUrls, ApiUrlsHome, Ventilation } from './constants.js';
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.SetErv;
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
- this.emit('deviceState', deviceData);
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 = ApiUrlsHome.PostHolidayMode;
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 = ApiUrlsHome.PutScheduleEnabled.replace('deviceid', deviceData.DeviceID);
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 = ApiUrlsHome.PutScene[flagData.Enabled ? 'Enable' : 'Disable'].replace('sceneid', flagData.Id);
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 = ApiUrlsHome.PutErv.replace('deviceid', deviceData.DeviceID);
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;