@switchbot/homebridge-switchbot 1.4.0 → 1.4.1-beta.3

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/config.schema.json +83 -11
  3. package/dist/devices/bots.d.ts +13 -3
  4. package/dist/devices/bots.d.ts.map +1 -1
  5. package/dist/devices/bots.js +162 -105
  6. package/dist/devices/bots.js.map +1 -1
  7. package/dist/devices/colorbulb.d.ts +13 -3
  8. package/dist/devices/colorbulb.d.ts.map +1 -1
  9. package/dist/devices/colorbulb.js +161 -96
  10. package/dist/devices/colorbulb.js.map +1 -1
  11. package/dist/devices/contact.d.ts +13 -3
  12. package/dist/devices/contact.d.ts.map +1 -1
  13. package/dist/devices/contact.js +117 -63
  14. package/dist/devices/contact.js.map +1 -1
  15. package/dist/devices/curtains.d.ts +14 -5
  16. package/dist/devices/curtains.d.ts.map +1 -1
  17. package/dist/devices/curtains.js +198 -140
  18. package/dist/devices/curtains.js.map +1 -1
  19. package/dist/devices/humidifiers.d.ts +13 -3
  20. package/dist/devices/humidifiers.d.ts.map +1 -1
  21. package/dist/devices/humidifiers.js +180 -127
  22. package/dist/devices/humidifiers.js.map +1 -1
  23. package/dist/devices/meters.d.ts +13 -3
  24. package/dist/devices/meters.d.ts.map +1 -1
  25. package/dist/devices/meters.js +121 -63
  26. package/dist/devices/meters.js.map +1 -1
  27. package/dist/devices/motion.d.ts +13 -3
  28. package/dist/devices/motion.d.ts.map +1 -1
  29. package/dist/devices/motion.js +104 -45
  30. package/dist/devices/motion.js.map +1 -1
  31. package/dist/devices/plugs.d.ts +13 -3
  32. package/dist/devices/plugs.d.ts.map +1 -1
  33. package/dist/devices/plugs.js +99 -35
  34. package/dist/devices/plugs.js.map +1 -1
  35. package/dist/irdevices/airconditioners.d.ts +11 -3
  36. package/dist/irdevices/airconditioners.d.ts.map +1 -1
  37. package/dist/irdevices/airconditioners.js +80 -45
  38. package/dist/irdevices/airconditioners.js.map +1 -1
  39. package/dist/irdevices/airpurifiers.d.ts +11 -3
  40. package/dist/irdevices/airpurifiers.d.ts.map +1 -1
  41. package/dist/irdevices/airpurifiers.js +68 -31
  42. package/dist/irdevices/airpurifiers.js.map +1 -1
  43. package/dist/irdevices/cameras.d.ts +11 -3
  44. package/dist/irdevices/cameras.d.ts.map +1 -1
  45. package/dist/irdevices/cameras.js +64 -24
  46. package/dist/irdevices/cameras.js.map +1 -1
  47. package/dist/irdevices/fans.d.ts +11 -3
  48. package/dist/irdevices/fans.d.ts.map +1 -1
  49. package/dist/irdevices/fans.js +74 -35
  50. package/dist/irdevices/fans.js.map +1 -1
  51. package/dist/irdevices/lights.d.ts +11 -3
  52. package/dist/irdevices/lights.d.ts.map +1 -1
  53. package/dist/irdevices/lights.js +65 -25
  54. package/dist/irdevices/lights.js.map +1 -1
  55. package/dist/irdevices/others.d.ts +11 -3
  56. package/dist/irdevices/others.d.ts.map +1 -1
  57. package/dist/irdevices/others.js +71 -31
  58. package/dist/irdevices/others.js.map +1 -1
  59. package/dist/irdevices/tvs.d.ts +11 -3
  60. package/dist/irdevices/tvs.d.ts.map +1 -1
  61. package/dist/irdevices/tvs.js +81 -42
  62. package/dist/irdevices/tvs.js.map +1 -1
  63. package/dist/irdevices/vacuumcleaners.d.ts +11 -3
  64. package/dist/irdevices/vacuumcleaners.d.ts.map +1 -1
  65. package/dist/irdevices/vacuumcleaners.js +64 -24
  66. package/dist/irdevices/vacuumcleaners.js.map +1 -1
  67. package/dist/irdevices/waterheaters.d.ts +11 -3
  68. package/dist/irdevices/waterheaters.d.ts.map +1 -1
  69. package/dist/irdevices/waterheaters.js +64 -24
  70. package/dist/irdevices/waterheaters.js.map +1 -1
  71. package/dist/platform.d.ts +10 -10
  72. package/dist/platform.d.ts.map +1 -1
  73. package/dist/platform.js +290 -307
  74. package/dist/platform.js.map +1 -1
  75. package/dist/settings.d.ts +4 -1
  76. package/dist/settings.d.ts.map +1 -1
  77. package/dist/settings.js.map +1 -1
  78. package/nodemon.json +1 -1
  79. package/package.json +70 -66
  80. package/src/devices/bots.ts +169 -105
  81. package/src/devices/colorbulb.ts +170 -99
  82. package/src/devices/contact.ts +124 -64
  83. package/src/devices/curtains.ts +207 -145
  84. package/src/devices/humidifiers.ts +187 -129
  85. package/src/devices/meters.ts +128 -64
  86. package/src/devices/motion.ts +110 -45
  87. package/src/devices/plugs.ts +104 -36
  88. package/src/irdevices/airconditioners.ts +85 -45
  89. package/src/irdevices/airpurifiers.ts +73 -31
  90. package/src/irdevices/cameras.ts +69 -24
  91. package/src/irdevices/fans.ts +79 -36
  92. package/src/irdevices/lights.ts +70 -25
  93. package/src/irdevices/others.ts +76 -31
  94. package/src/irdevices/tvs.ts +86 -42
  95. package/src/irdevices/vacuumcleaners.ts +69 -24
  96. package/src/irdevices/waterheaters.ts +69 -24
  97. package/src/platform.ts +285 -302
  98. package/src/settings.ts +4 -1
  99. package/dist/devices/indoorcam.d.ts +0 -64
  100. package/dist/devices/indoorcam.d.ts.map +0 -1
  101. package/dist/devices/indoorcam.js +0 -249
  102. package/dist/devices/indoorcam.js.map +0 -1
  103. package/src/devices/indoorcam.ts +0 -309
@@ -3,7 +3,7 @@ import Switchbot from 'node-switchbot';
3
3
  import { interval, Subject } from 'rxjs';
4
4
  import { SwitchBotPlatform } from '../platform';
5
5
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
6
- import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
6
+ import { Service, PlatformAccessory, CharacteristicValue, HAPStatus } from 'homebridge';
7
7
  import { DeviceURL, device, devicesConfig, serviceData, ad, deviceStatusResponse, payload } from '../settings';
8
8
 
9
9
  /**
@@ -37,8 +37,8 @@ export class Humidifier {
37
37
 
38
38
  // Config
39
39
  set_minStep?: number;
40
- private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
41
- private readonly debugDebug = this.platform.config.options?.debug === 'debug' || this.platform.debugMode;
40
+ deviceLogging!: string;
41
+ deviceRefreshRate!: number;
42
42
 
43
43
  // Updates
44
44
  humidifierUpdateInProgress!: boolean;
@@ -49,11 +49,9 @@ export class Humidifier {
49
49
  private accessory: PlatformAccessory,
50
50
  public device: device & devicesConfig,
51
51
  ) {
52
- // Humidifiers Config
53
- this.platform.device(`Humidifier: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, hide_temperature: `
54
- + `${device.humidifier?.hide_temperature}, set_minStep: ${device.humidifier?.set_minStep})`);
55
-
56
52
  // default placeholders
53
+ this.refreshRate();
54
+ this.logs();
57
55
  this.CurrentRelativeHumidity = 0;
58
56
  this.TargetHumidifierDehumidifierState = this.platform.Characteristic.TargetHumidifierDehumidifierState.HUMIDIFIER;
59
57
  this.CurrentHumidifierDehumidifierState = this.platform.Characteristic.CurrentHumidifierDehumidifierState.INACTIVE;
@@ -62,6 +60,10 @@ export class Humidifier {
62
60
  this.CurrentTemperature = 0;
63
61
  this.WaterLevel = 0;
64
62
 
63
+ // Humidifiers Config
64
+ this.debugLog(`Humidifier: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, hide_temperature: `
65
+ + `${device.humidifier?.hide_temperature}, set_minStep: ${device.humidifier?.set_minStep})`);
66
+
65
67
  // this is subject we use to track when we need to POST changes to the SwitchBot API
66
68
  this.doHumidifierUpdate = new Subject();
67
69
  this.humidifierUpdateInProgress = false;
@@ -124,11 +126,11 @@ export class Humidifier {
124
126
  // create a new Temperature Sensor service
125
127
  // Temperature Sensor Service
126
128
  if (device.humidifier?.hide_temperature || device.ble) {
127
- this.platform.device(`Humidifier: ${accessory.displayName} Removing Temperature Sensor Service`);
129
+ this.debugLog(`Humidifier: ${accessory.displayName} Removing Temperature Sensor Service`);
128
130
  this.temperatureservice = this.accessory.getService(this.platform.Service.TemperatureSensor);
129
131
  accessory.removeService(this.temperatureservice!);
130
132
  } else if (!this.temperatureservice && !device.ble) {
131
- this.platform.device(`Humidifier: ${accessory.displayName} Add Temperature Sensor Service`);
133
+ this.debugLog(`Humidifier: ${accessory.displayName} Add Temperature Sensor Service`);
132
134
  (this.temperatureservice =
133
135
  this.accessory.getService(this.platform.Service.TemperatureSensor) ||
134
136
  this.accessory.addService(this.platform.Service.TemperatureSensor)), `${accessory.displayName} Temperature Sensor`;
@@ -147,16 +149,14 @@ export class Humidifier {
147
149
  return Number.isNaN(this.CurrentTemperature);
148
150
  });
149
151
  } else {
150
- if (this.platform.config.options?.debug) {
151
- this.platform.device(`Humidifier: ${accessory.displayName} Temperature Sensor Service Not Added`);
152
- }
152
+ this.debugLog(`Humidifier: ${accessory.displayName} Temperature Sensor Service Not Added`);
153
153
  }
154
154
 
155
155
  // Retrieve initial values and updateHomekit
156
156
  this.updateHomeKitCharacteristics();
157
157
 
158
158
  // Start an update interval
159
- interval(this.platform.config.options!.refreshRate! * 1000)
159
+ interval(this.deviceRefreshRate * 1000)
160
160
  .pipe(skipWhile(() => this.humidifierUpdateInProgress))
161
161
  .subscribe(() => {
162
162
  this.refreshStatus();
@@ -175,21 +175,54 @@ export class Humidifier {
175
175
  try {
176
176
  await this.pushChanges();
177
177
  } catch (e: any) {
178
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges`);
179
- if (this.deviceDebug) {
180
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges,`
178
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges`);
179
+ if (this.deviceLogging === 'debug') {
180
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges,`
181
181
  + ` Error Message: ${JSON.stringify(e.message)}`);
182
182
  }
183
- if (this.debugDebug) {
184
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges,`
183
+ if (this.platform.debugMode) {
184
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges,`
185
185
  + ` Error: ${JSON.stringify(e)}`);
186
186
  }
187
- this.apiError(e);
187
+ this.apiError();
188
188
  }
189
189
  this.humidifierUpdateInProgress = false;
190
190
  });
191
191
  }
192
192
 
193
+ refreshRate() {
194
+ if (this.device.refreshRate) {
195
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.device.refreshRate;
196
+ if (this.platform.debugMode) {
197
+ this.warnLog(`Using Device Config refreshRate: ${this.deviceRefreshRate}`);
198
+ }
199
+ } else if (this.platform.config.options!.refreshRate) {
200
+ this.deviceRefreshRate = this.accessory.context.refreshRate = this.platform.config.options!.refreshRate;
201
+ if (this.platform.debugMode) {
202
+ this.warnLog(`Using Platform Config refreshRate: ${this.deviceRefreshRate}`);
203
+ }
204
+ }
205
+ }
206
+
207
+ logs() {
208
+ if (this.device.logging) {
209
+ this.deviceLogging = this.accessory.context.logging = this.device.logging;
210
+ if (this.platform.debugMode) {
211
+ this.warnLog(`Using Device Config Logging: ${this.deviceLogging}`);
212
+ }
213
+ } else if (this.platform.config.options?.logging) {
214
+ this.deviceLogging = this.accessory.context.logging = this.platform.config.options?.logging;
215
+ if (this.platform.debugMode) {
216
+ this.warnLog(`Using Platform Config Logging: ${this.deviceLogging}`);
217
+ }
218
+ } else {
219
+ this.deviceLogging = this.accessory.context.logging = 'standard';
220
+ if (this.platform.debugMode) {
221
+ this.warnLog('Using Device Standard Logging');
222
+ }
223
+ }
224
+ }
225
+
193
226
  private minStep(): number | undefined {
194
227
  if (this.device.humidifier?.set_minStep) {
195
228
  this.set_minStep = this.device.humidifier?.set_minStep;
@@ -211,29 +244,29 @@ export class Humidifier {
211
244
  }
212
245
 
213
246
  private BLEparseStatus() {
214
- this.platform.debug(`Humidifier: ${this.accessory.displayName} BLE parseStatus`);
247
+ this.debugLog(`Humidifier: ${this.accessory.displayName} BLE parseStatus`);
215
248
  // Current Relative Humidity
216
249
  this.CurrentRelativeHumidity = this.percentage!;
217
- this.platform.debug(`Humidifier: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
250
+ this.debugLog(`Humidifier: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
218
251
  // Active
219
252
  if (this.onState) {
220
253
  this.Active = this.platform.Characteristic.Active.ACTIVE;
221
254
  } else {
222
255
  this.Active = this.platform.Characteristic.Active.INACTIVE;
223
256
  }
224
- this.platform.debug(`Humidifier: ${this.accessory.displayName} Active: ${this.Active}`);
257
+ this.debugLog(`Humidifier: ${this.accessory.displayName} Active: ${this.Active}`);
225
258
  }
226
259
 
227
260
  private openAPIparseStatus() {
228
261
  if (this.platform.config.credentials?.openToken) {
229
- this.platform.debug(`Humidifier: ${this.accessory.displayName} OpenAPI parseStatus`);
262
+ this.debugLog(`Humidifier: ${this.accessory.displayName} OpenAPI parseStatus`);
230
263
  // Current Relative Humidity
231
264
  this.CurrentRelativeHumidity = this.deviceStatus.body.humidity!;
232
- this.platform.debug(`Humidifier: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
265
+ this.debugLog(`Humidifier: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
233
266
  // Current Temperature
234
267
  if (!this.device.humidifier?.hide_temperature) {
235
268
  this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
236
- this.platform.debug(`Humidifier: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
269
+ this.debugLog(`Humidifier: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
237
270
  }
238
271
  // Target Humidifier Dehumidifier State
239
272
  switch (this.deviceStatus.body.auto) {
@@ -257,10 +290,10 @@ export class Humidifier {
257
290
  this.CurrentHumidifierDehumidifierState = this.platform.Characteristic.CurrentHumidifierDehumidifierState.HUMIDIFYING;
258
291
  }
259
292
  }
260
- this.platform.debug(`Humidifier: ${this.accessory.displayName} TargetHumidifierDehumidifierState: ${this.TargetHumidifierDehumidifierState}`);
261
- this.platform.debug(`Humidifier: ${this.accessory.displayName}`
293
+ this.debugLog(`Humidifier: ${this.accessory.displayName} TargetHumidifierDehumidifierState: ${this.TargetHumidifierDehumidifierState}`);
294
+ this.debugLog(`Humidifier: ${this.accessory.displayName}`
262
295
  + ` RelativeHumidityHumidifierThreshold: ${this.RelativeHumidityHumidifierThreshold}`);
263
- this.platform.debug(`Humidifier: ${this.accessory.displayName} CurrentHumidifierDehumidifierState: ${this.CurrentHumidifierDehumidifierState}`);
296
+ this.debugLog(`Humidifier: ${this.accessory.displayName} CurrentHumidifierDehumidifierState: ${this.CurrentHumidifierDehumidifierState}`);
264
297
  // Active
265
298
  switch (this.deviceStatus.body.power) {
266
299
  case 'on':
@@ -269,14 +302,14 @@ export class Humidifier {
269
302
  default:
270
303
  this.Active = this.platform.Characteristic.Active.INACTIVE;
271
304
  }
272
- this.platform.debug(`Humidifier: ${this.accessory.displayName} Active: ${this.Active}`);
305
+ this.debugLog(`Humidifier: ${this.accessory.displayName} Active: ${this.Active}`);
273
306
  // Water Level
274
307
  if (this.deviceStatus.body.lackWater) {
275
308
  this.WaterLevel = 0;
276
309
  } else {
277
310
  this.WaterLevel = 100;
278
311
  }
279
- this.platform.debug(`Humidifier: ${this.accessory.displayName} WaterLevel: ${this.WaterLevel}`);
312
+ this.debugLog(`Humidifier: ${this.accessory.displayName} WaterLevel: ${this.WaterLevel}`);
280
313
  }
281
314
  }
282
315
 
@@ -294,12 +327,12 @@ export class Humidifier {
294
327
  private connectBLE() {
295
328
  const switchbot = new Switchbot();
296
329
  this.device.bleMac = ((this.device.deviceId!.match(/.{1,2}/g))!.join(':')).toLowerCase();
297
- this.platform.device(`Humidifier: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
330
+ this.debugLog(`Humidifier: ${this.accessory.displayName} BLE Address: ${this.device.bleMac}`);
298
331
  return switchbot;
299
332
  }
300
333
 
301
334
  private async BLERefreshStatus() {
302
- this.platform.device(`Humidifier: ${this.accessory.displayName} BLE refreshStatus`);
335
+ this.debugLog(`Humidifier: ${this.accessory.displayName} BLE refreshStatus`);
303
336
  // eslint-disable-next-line @typescript-eslint/no-var-requires
304
337
  const switchbot = this.connectBLE();
305
338
  // Start to monitor advertisement packets
@@ -313,16 +346,16 @@ export class Humidifier {
313
346
  this.autoMode = ad.serviceData.autoMode;
314
347
  this.onState = ad.serviceData.onState;
315
348
  this.percentage = ad.serviceData.percentage;
316
- this.platform.device(`Humidifier: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
317
- this.platform.device(`Humidifier: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName},`
349
+ this.debugLog(`Humidifier: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
350
+ this.debugLog(`Humidifier: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName},`
318
351
  + `autoMode: ${ad.serviceData.autoMode}, onState: ${ad.serviceData.onState}, percentage: ${ad.serviceData.percentage}`);
319
352
 
320
353
  if (this.serviceData) {
321
354
  this.connected = true;
322
- this.platform.device(`Humidifier: ${this.accessory.displayName} connected: ${this.connected}`);
355
+ this.debugLog(`Humidifier: ${this.accessory.displayName} connected: ${this.connected}`);
323
356
  } else {
324
357
  this.connected = false;
325
- this.platform.device(`Humidifier: ${this.accessory.displayName} connected: ${this.connected}`);
358
+ this.debugLog(`Humidifier: ${this.accessory.displayName} connected: ${this.connected}`);
326
359
  }
327
360
  };
328
361
  // Wait 10 seconds
@@ -334,53 +367,53 @@ export class Humidifier {
334
367
  this.parseStatus();
335
368
  this.updateHomeKitCharacteristics();
336
369
  } else {
337
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
370
+ this.errorLog(`Humidifier: ${this.accessory.displayName} wasn't able to establish BLE Connection`);
338
371
  if (this.platform.config.credentials?.openToken) {
339
- this.platform.log.warn(`Humidifier: ${this.accessory.displayName} Using OpenAPI Connection`);
372
+ this.warnLog(`Humidifier: ${this.accessory.displayName} Using OpenAPI Connection`);
340
373
  await this.openAPIRefreshStatus();
341
374
  }
342
375
  }
343
376
  }).catch(async (e: any) => {
344
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
345
- if (this.deviceDebug) {
346
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
377
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed refreshStatus with BLE Connection`);
378
+ if (this.deviceLogging === 'debug') {
379
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
347
380
  + ` Error Message: ${JSON.stringify(e.message)}`);
348
381
  }
349
- if (this.debugDebug) {
350
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
382
+ if (this.platform.debugMode) {
383
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed refreshStatus with BLE Connection,`
351
384
  + ` Error: ${JSON.stringify(e)}`);
352
385
  }
353
386
  if (this.platform.config.credentials?.openToken) {
354
- this.platform.log.warn(`Humidifier: ${this.accessory.displayName} Using OpenAPI Connection`);
387
+ this.warnLog(`Humidifier: ${this.accessory.displayName} Using OpenAPI Connection`);
355
388
  await this.openAPIRefreshStatus();
356
389
  }
357
- this.apiError(e);
390
+ this.apiError();
358
391
  });
359
392
  }
360
393
 
361
394
  private async openAPIRefreshStatus() {
362
395
  if (this.platform.config.credentials?.openToken) {
363
- this.platform.device(`Humidifier: ${this.accessory.displayName} OpenAPI refreshStatus`);
396
+ this.debugLog(`Humidifier: ${this.accessory.displayName} OpenAPI refreshStatus`);
364
397
  try {
365
398
  this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
366
399
  if (this.deviceStatus.message === 'success') {
367
- this.platform.debug(`Humidifier: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
400
+ this.debugLog(`Humidifier: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
368
401
  this.parseStatus();
369
402
  this.updateHomeKitCharacteristics();
370
403
  } else {
371
- this.platform.debug(this.deviceStatus);
404
+ this.debugLog(this.deviceStatus);
372
405
  }
373
406
  } catch (e: any) {
374
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
375
- if (this.deviceDebug) {
376
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
407
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection`);
408
+ if (this.deviceLogging === 'debug') {
409
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
377
410
  + ` Error Message: ${JSON.stringify(e.message)}`);
378
411
  }
379
- if (this.debugDebug) {
380
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
412
+ if (this.platform.debugMode) {
413
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed refreshStatus with OpenAPI Connection,`
381
414
  + ` Error: ${JSON.stringify(e)}`);
382
415
  }
383
- this.apiError(e);
416
+ this.apiError();
384
417
  }
385
418
  }
386
419
  }
@@ -403,65 +436,65 @@ export class Humidifier {
403
436
  }
404
437
 
405
438
  private async BLEpushChanges() {
406
- this.platform.debug(`Humidifier: ${this.accessory.displayName} BLE pushChanges`);
439
+ this.debugLog(`Humidifier: ${this.accessory.displayName} BLE pushChanges`);
407
440
  const switchbot = this.connectBLE();
408
441
  switchbot.discover({ model: 'e', quick: true, id: this.device.bleMac }).then((device_list) => {
409
- this.platform.log.info(`${this.accessory.displayName} Target Position: ${this.Active}`);
442
+ this.infoLog(`${this.accessory.displayName} Target Position: ${this.Active}`);
410
443
  return device_list[0].percentage(this.RelativeHumidityHumidifierThreshold);
411
444
  }).then(() => {
412
- this.platform.device(`Humidifier: ${this.accessory.displayName} Done.`);
445
+ this.debugLog(`Humidifier: ${this.accessory.displayName} Done.`);
413
446
  }).catch(async (e: any) => {
414
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
415
- if (this.deviceDebug) {
416
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
447
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
448
+ if (this.deviceLogging === 'debug') {
449
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
417
450
  + ` Error Message: ${JSON.stringify(e.message)}`);
418
451
  }
419
- if (this.debugDebug) {
420
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
452
+ if (this.platform.debugMode) {
453
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
421
454
  + ` Error: ${JSON.stringify(e)}`);
422
455
  }
423
456
  if (this.platform.config.credentials?.openToken) {
424
- this.platform.log.warn(`Humidifier: ${this.accessory.displayName} Using OpenAPI Connection`);
457
+ this.warnLog(`Humidifier: ${this.accessory.displayName} Using OpenAPI Connection`);
425
458
  await this.OpenAPIpushChanges();
426
459
  }
427
- this.apiError(e);
460
+ this.apiError();
428
461
  });
429
462
  }
430
463
 
431
464
  private async OpenAPIpushChanges() {
432
465
  if (this.platform.config.credentials?.openToken) {
433
- this.platform.device(`Humidifier: ${this.accessory.displayName} OpenAPI pushChanges`);
466
+ this.debugLog(`Humidifier: ${this.accessory.displayName} OpenAPI pushChanges`);
434
467
  if (
435
468
  this.TargetHumidifierDehumidifierState ===
436
469
  this.platform.Characteristic.TargetHumidifierDehumidifierState.HUMIDIFIER &&
437
470
  this.Active === this.platform.Characteristic.Active.ACTIVE
438
471
  ) {
439
472
  try {
440
- this.platform.debug(`Pushing Manual: ${this.RelativeHumidityHumidifierThreshold}!`);
473
+ this.debugLog(`Pushing Manual: ${this.RelativeHumidityHumidifierThreshold}!`);
441
474
  const payload = {
442
475
  commandType: 'command',
443
476
  command: 'setMode',
444
477
  parameter: `${this.RelativeHumidityHumidifierThreshold}`,
445
478
  } as payload;
446
479
 
447
- this.platform.log.info(`Humidifier: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
480
+ this.infoLog(`Humidifier: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
448
481
  + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
449
482
 
450
483
  // Make the API request
451
484
  const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
452
- this.platform.debug(`Humidifier: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
485
+ this.debugLog(`Humidifier: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
453
486
  this.statusCode(push);
454
487
  } catch (e: any) {
455
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
456
- if (this.deviceDebug) {
457
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
488
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
489
+ if (this.deviceLogging === 'debug') {
490
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
458
491
  + ` Error Message: ${JSON.stringify(e.message)}`);
459
492
  }
460
- if (this.debugDebug) {
461
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
493
+ if (this.platform.debugMode) {
494
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection,`
462
495
  + ` Error: ${JSON.stringify(e)}`);
463
496
  }
464
- this.apiError(e);
497
+ this.apiError();
465
498
  }
466
499
  } else if (
467
500
  this.TargetHumidifierDehumidifierState ===
@@ -485,32 +518,32 @@ export class Humidifier {
485
518
  this.platform.Characteristic.TargetHumidifierDehumidifierState.HUMIDIFIER_OR_DEHUMIDIFIER &&
486
519
  this.Active === this.platform.Characteristic.Active.ACTIVE
487
520
  ) {
488
- this.platform.debug('Pushing Auto!');
521
+ this.debugLog('Pushing Auto!');
489
522
  const payload = {
490
523
  commandType: 'command',
491
524
  command: 'setMode',
492
525
  parameter: 'auto',
493
526
  } as payload;
494
527
 
495
- this.platform.log.info(`Humidifier: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
528
+ this.infoLog(`Humidifier: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
496
529
  + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
497
530
 
498
531
  // Make the API request
499
532
  const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
500
- this.platform.debug(`Humidifier: ${this.accessory.displayName} pushAutoChanges: ${JSON.stringify(push.data)}`);
533
+ this.debugLog(`Humidifier: ${this.accessory.displayName} pushAutoChanges: ${JSON.stringify(push.data)}`);
501
534
  this.statusCode(push);
502
535
  }
503
536
  } catch (e: any) {
504
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushAutoChanges with OpenAPI Connection`);
505
- if (this.deviceDebug) {
506
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushAutoChanges with OpenAPI Connection,`
537
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushAutoChanges with OpenAPI Connection`);
538
+ if (this.deviceLogging === 'debug') {
539
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushAutoChanges with OpenAPI Connection,`
507
540
  + ` Error Message: ${JSON.stringify(e.message)}`);
508
541
  }
509
- if (this.debugDebug) {
510
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushAutoChanges with OpenAPI Connection,`
542
+ if (this.platform.debugMode) {
543
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushAutoChanges with OpenAPI Connection,`
511
544
  + ` Error: ${JSON.stringify(e)}`);
512
545
  }
513
- this.apiError(e);
546
+ this.apiError();
514
547
  }
515
548
  }
516
549
 
@@ -520,32 +553,32 @@ export class Humidifier {
520
553
  async pushActiveChanges() {
521
554
  try {
522
555
  if (this.Active === this.platform.Characteristic.Active.INACTIVE) {
523
- this.platform.debug('Pushing Off!');
556
+ this.debugLog('Pushing Off!');
524
557
  const payload = {
525
558
  commandType: 'command',
526
559
  command: 'turnOff',
527
560
  parameter: 'default',
528
561
  } as payload;
529
562
 
530
- this.platform.log.info(`Humidifier: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
563
+ this.infoLog(`Humidifier: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
531
564
  + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
532
565
 
533
566
  // Make the API request
534
567
  const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
535
- this.platform.debug(`Humidifier: ${this.accessory.displayName} pushActiveChanges: ${JSON.stringify(push.data)}`);
568
+ this.debugLog(`Humidifier: ${this.accessory.displayName} pushActiveChanges: ${JSON.stringify(push.data)}`);
536
569
  this.statusCode(push);
537
570
  }
538
571
  } catch (e: any) {
539
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushActiveChanges with OpenAPI Connection`);
540
- if (this.deviceDebug) {
541
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushActiveChanges with OpenAPI Connection,`
572
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushActiveChanges with OpenAPI Connection`);
573
+ if (this.deviceLogging === 'debug') {
574
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushActiveChanges with OpenAPI Connection,`
542
575
  + ` Error Message: ${JSON.stringify(e.message)}`);
543
576
  }
544
- if (this.debugDebug) {
545
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} failed pushActiveChanges with OpenAPI Connection,`
577
+ if (this.platform.debugMode) {
578
+ this.errorLog(`Humidifier: ${this.accessory.displayName} failed pushActiveChanges with OpenAPI Connection,`
546
579
  + ` Error: ${JSON.stringify(e)}`);
547
580
  }
548
- this.apiError(e);
581
+ this.apiError();
549
582
  }
550
583
  }
551
584
 
@@ -554,100 +587,90 @@ export class Humidifier {
554
587
  */
555
588
  updateHomeKitCharacteristics() {
556
589
  if (this.CurrentRelativeHumidity === undefined) {
557
- this.platform.debug(`Humidifier: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
590
+ this.debugLog(`Humidifier: ${this.accessory.displayName} CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
558
591
  } else {
559
592
  this.service.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.CurrentRelativeHumidity);
560
- this.platform.device(`Humidifier: ${this.accessory.displayName}`
593
+ this.debugLog(`Humidifier: ${this.accessory.displayName}`
561
594
  + ` updateCharacteristic CurrentRelativeHumidity: ${this.CurrentRelativeHumidity}`);
562
595
  }
563
596
  if (!this.device.ble) {
564
597
  if (this.WaterLevel === undefined) {
565
- this.platform.debug(`Humidifier: ${this.accessory.displayName} WaterLevel: ${this.WaterLevel}`);
598
+ this.debugLog(`Humidifier: ${this.accessory.displayName} WaterLevel: ${this.WaterLevel}`);
566
599
  } else {
567
600
  this.service.updateCharacteristic(this.platform.Characteristic.WaterLevel, this.WaterLevel);
568
- this.platform.device(`Humidifier: ${this.accessory.displayName} updateCharacteristic WaterLevel: ${this.WaterLevel}`);
601
+ this.debugLog(`Humidifier: ${this.accessory.displayName} updateCharacteristic WaterLevel: ${this.WaterLevel}`);
569
602
  }
570
603
  }
571
604
  if (this.CurrentHumidifierDehumidifierState === undefined) {
572
- this.platform.debug(`Humidifier: ${this.accessory.displayName} CurrentHumidifierDehumidifierState: ${this.CurrentHumidifierDehumidifierState}`);
605
+ this.debugLog(`Humidifier: ${this.accessory.displayName} CurrentHumidifierDehumidifierState: ${this.CurrentHumidifierDehumidifierState}`);
573
606
  } else {
574
607
  this.service.updateCharacteristic(this.platform.Characteristic.CurrentHumidifierDehumidifierState, this.CurrentHumidifierDehumidifierState);
575
- this.platform.device(`Humidifier: ${this.accessory.displayName}`
608
+ this.debugLog(`Humidifier: ${this.accessory.displayName}`
576
609
  + ` updateCharacteristic CurrentHumidifierDehumidifierState: ${this.CurrentHumidifierDehumidifierState}`);
577
610
  }
578
611
  if (this.TargetHumidifierDehumidifierState === undefined) {
579
- this.platform.debug(`Humidifier: ${this.accessory.displayName} TargetHumidifierDehumidifierState: ${this.TargetHumidifierDehumidifierState}`);
612
+ this.debugLog(`Humidifier: ${this.accessory.displayName} TargetHumidifierDehumidifierState: ${this.TargetHumidifierDehumidifierState}`);
580
613
  } else {
581
614
  this.service.updateCharacteristic(this.platform.Characteristic.TargetHumidifierDehumidifierState, this.TargetHumidifierDehumidifierState);
582
- this.platform.device(`Humidifier: ${this.accessory.displayName}`
615
+ this.debugLog(`Humidifier: ${this.accessory.displayName}`
583
616
  + ` updateCharacteristic TargetHumidifierDehumidifierState: ${this.TargetHumidifierDehumidifierState}`);
584
617
  }
585
618
  if (this.Active === undefined) {
586
- this.platform.debug(`Humidifier: ${this.accessory.displayName} Active: ${this.Active}`);
619
+ this.debugLog(`Humidifier: ${this.accessory.displayName} Active: ${this.Active}`);
587
620
  } else {
588
621
  this.service.updateCharacteristic(this.platform.Characteristic.Active, this.Active);
589
- this.platform.device(`Humidifier: ${this.accessory.displayName} updateCharacteristic Active: ${this.Active}`);
622
+ this.debugLog(`Humidifier: ${this.accessory.displayName} updateCharacteristic Active: ${this.Active}`);
590
623
  }
591
624
  if (this.RelativeHumidityHumidifierThreshold === undefined) {
592
- this.platform.debug(`Humidifier: ${this.accessory.displayName}`
625
+ this.debugLog(`Humidifier: ${this.accessory.displayName}`
593
626
  + ` RelativeHumidityHumidifierThreshold: ${this.RelativeHumidityHumidifierThreshold}`);
594
627
  } else {
595
628
  this.service.updateCharacteristic(this.platform.Characteristic.RelativeHumidityHumidifierThreshold, this.RelativeHumidityHumidifierThreshold);
596
- this.platform.device(`Humidifier: ${this.accessory.displayName}`
629
+ this.debugLog(`Humidifier: ${this.accessory.displayName}`
597
630
  + ` updateCharacteristic RelativeHumidityHumidifierThreshold: ${this.RelativeHumidityHumidifierThreshold}`);
598
631
  }
599
632
  if (!this.device.humidifier?.hide_temperature && !this.device.ble) {
600
633
  if (this.CurrentTemperature === undefined) {
601
- this.platform.debug(`Humidifier: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
634
+ this.debugLog(`Humidifier: ${this.accessory.displayName} CurrentTemperature: ${this.CurrentTemperature}`);
602
635
  } else {
603
636
  this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.CurrentTemperature);
604
- this.platform.device(`Humidifier: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
637
+ this.debugLog(`Humidifier: ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.CurrentTemperature}`);
605
638
  }
606
639
  }
607
640
  }
608
641
 
609
- public apiError(e: any) {
610
- this.service.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, e);
611
- if (!this.device.ble) {
612
- this.service.updateCharacteristic(this.platform.Characteristic.WaterLevel, e);
613
- }
614
- this.service.updateCharacteristic(this.platform.Characteristic.CurrentHumidifierDehumidifierState, e);
615
- this.service.updateCharacteristic(this.platform.Characteristic.TargetHumidifierDehumidifierState, e);
616
- this.service.updateCharacteristic(this.platform.Characteristic.Active, e);
617
- this.service.updateCharacteristic(this.platform.Characteristic.RelativeHumidityHumidifierThreshold, e);
618
- if (!this.device.humidifier?.hide_temperature && !this.device.ble) {
619
- this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
620
- }
642
+ public apiError() {
643
+ throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
621
644
  }
622
645
 
623
646
  private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
624
647
  switch (push.data.statusCode) {
625
648
  case 151:
626
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} Command not supported by this device type.`);
649
+ this.errorLog(`Humidifier: ${this.accessory.displayName} Command not supported by this device type.`);
627
650
  break;
628
651
  case 152:
629
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device not found.`);
652
+ this.errorLog(`Humidifier: ${this.accessory.displayName} Device not found.`);
630
653
  break;
631
654
  case 160:
632
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} Command is not supported.`);
655
+ this.errorLog(`Humidifier: ${this.accessory.displayName} Command is not supported.`);
633
656
  break;
634
657
  case 161:
635
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device is offline.`);
658
+ this.errorLog(`Humidifier: ${this.accessory.displayName} Device is offline.`);
636
659
  this.offlineOff();
637
660
  break;
638
661
  case 171:
639
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
662
+ this.errorLog(`Humidifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
640
663
  this.offlineOff();
641
664
  break;
642
665
  case 190:
643
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
666
+ this.errorLog(`Humidifier: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
644
667
  + ` Or command: ${JSON.stringify(push.data)} format is invalid`);
645
668
  break;
646
669
  case 100:
647
- this.platform.debug(`Humidifier: ${this.accessory.displayName} Command successfully sent.`);
670
+ this.debugLog(`Humidifier: ${this.accessory.displayName} Command successfully sent.`);
648
671
  break;
649
672
  default:
650
- this.platform.debug(`Humidifier: ${this.accessory.displayName} Unknown statusCode.`);
673
+ this.debugLog(`Humidifier: ${this.accessory.displayName} Unknown statusCode.`);
651
674
  }
652
675
  }
653
676
 
@@ -662,7 +685,7 @@ export class Humidifier {
662
685
  * Handle requests to set the "Target Humidifier Dehumidifier State" characteristic
663
686
  */
664
687
  private handleTargetHumidifierDehumidifierStateSet(value: CharacteristicValue) {
665
- this.platform.debug(`Humidifier: ${this.accessory.displayName} TargetHumidifierDehumidifierState: ${value}`);
688
+ this.debugLog(`Humidifier: ${this.accessory.displayName} TargetHumidifierDehumidifierState: ${value}`);
666
689
 
667
690
  this.TargetHumidifierDehumidifierState = value;
668
691
  this.doHumidifierUpdate.next();
@@ -672,7 +695,7 @@ export class Humidifier {
672
695
  * Handle requests to set the "Active" characteristic
673
696
  */
674
697
  private handleActiveSet(value: CharacteristicValue) {
675
- this.platform.debug(`Humidifier: ${this.accessory.displayName} Active: ${value}`);
698
+ this.debugLog(`Humidifier: ${this.accessory.displayName} Active: ${value}`);
676
699
  this.Active = value;
677
700
  this.doHumidifierUpdate.next();
678
701
  }
@@ -681,7 +704,7 @@ export class Humidifier {
681
704
  * Handle requests to set the "Relative Humidity Humidifier Threshold" characteristic
682
705
  */
683
706
  private handleRelativeHumidityHumidifierThresholdSet(value: CharacteristicValue) {
684
- this.platform.debug(`Humidifier: ${this.accessory.displayName} RelativeHumidityHumidifierThreshold: ${value}`);
707
+ this.debugLog(`Humidifier: ${this.accessory.displayName} RelativeHumidityHumidifierThreshold: ${value}`);
685
708
 
686
709
  this.RelativeHumidityHumidifierThreshold = value;
687
710
  if (this.Active === this.platform.Characteristic.Active.INACTIVE) {
@@ -690,4 +713,39 @@ export class Humidifier {
690
713
  }
691
714
  this.doHumidifierUpdate.next();
692
715
  }
716
+
717
+ /**
718
+ * Logging for Device
719
+ */
720
+ infoLog(...log: any[]) {
721
+ if (this.enablingDeviceLogging()) {
722
+ this.platform.log.info(String(...log));
723
+ }
724
+ }
725
+
726
+ warnLog(...log: any[]) {
727
+ if (this.enablingDeviceLogging()) {
728
+ this.platform.log.warn(String(...log));
729
+ }
730
+ }
731
+
732
+ errorLog(...log: any[]) {
733
+ if (this.enablingDeviceLogging()) {
734
+ this.platform.log.error(String(...log));
735
+ }
736
+ }
737
+
738
+ debugLog(...log: any[]) {
739
+ if (this.enablingDeviceLogging()) {
740
+ if (this.deviceLogging === 'debug') {
741
+ this.platform.log.info('[DEBUG]', String(...log));
742
+ } else {
743
+ this.platform.log.debug(String(...log));
744
+ }
745
+ }
746
+ }
747
+
748
+ enablingDeviceLogging(): boolean {
749
+ return this.deviceLogging === 'debug' || this.deviceLogging === 'standard';
750
+ }
693
751
  }