homebridge-tuya-community 3.3.0 → 3.3.1

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.
@@ -0,0 +1,54 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ id-token: write # Required for provenance
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Setup Node.js
17
+ uses: actions/setup-node@v4
18
+ with:
19
+ node-version: '20'
20
+ registry-url: 'https://registry.npmjs.org'
21
+
22
+ - name: Cache npm dependencies
23
+ uses: actions/cache@v4
24
+ with:
25
+ path: ~/.npm
26
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
27
+ restore-keys: |
28
+ ${{ runner.os }}-node-
29
+
30
+ - name: Get version from tag
31
+ id: get_version
32
+ run: |
33
+ # Remove 'v' prefix if present (e.g., v3.3.1 -> 3.3.1)
34
+ VERSION=${GITHUB_REF_NAME#v}
35
+ echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
36
+ echo "Publishing version: $VERSION"
37
+
38
+ - name: Install dependencies
39
+ run: npm ci
40
+
41
+ - name: Update package.json and package-lock.json version
42
+ run: npm version ${{ steps.get_version.outputs.VERSION }} --no-git-tag-version --allow-same-version
43
+
44
+ - name: Publish to npm
45
+ run: |
46
+ if [[ "${{ github.event.release.prerelease }}" == "true" ]]; then
47
+ echo "Publishing with 'next' tag (pre-release)"
48
+ npm publish --access public --tag next
49
+ else
50
+ echo "Publishing with 'latest' tag (stable)"
51
+ npm publish --access public
52
+ fi
53
+ env:
54
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/Readme.MD CHANGED
@@ -5,14 +5,14 @@
5
5
 
6
6
  <span align="center">
7
7
 
8
- # Homebridge-Tuya
8
+ # Homebridge-Tuya-Community
9
9
 
10
10
 
11
11
  </span>
12
12
 
13
13
 
14
14
 
15
- Control your supported Tuya accessories locally in HomeKit
15
+ Control your supported Tuya accessories locally in HomeKit!
16
16
 
17
17
  * [Supported Device Types](#supported-device-types)
18
18
  * [Installation Instructions](#installation-instructions)
@@ -46,7 +46,7 @@ Control your supported Tuya accessories locally in HomeKit
46
46
  * Outlets<sup>[14](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types#outlets)</sup>
47
47
  * Switches<sup>[15](https://github.com/iRayanKhan/homebridge-tuya/wiki/Supported-Device-Types)</sup>
48
48
 
49
- Note: Motion, and other sensor types don't behave well with responce requests, so they will not be added.
49
+ Note: Motion sensors and others don't behave well with response requests, so they will not be supported.
50
50
 
51
51
 
52
52
  ## Installation Instructions
package/bin/cli-decode.js CHANGED
@@ -43,7 +43,7 @@ const decodeLine = (key, input, log = true) => {
43
43
  const len = buffer.length;
44
44
  if (buffer.readUInt32BE(0) !== 0x000055aa || buffer.readUInt32BE(len - 4) !== 0x0000aa55) {
45
45
  console.log("*** Input doesn't match the expected signature:", buffer.readUInt32BE(0).toString(16).padStart(8, '0'), buffer.readUInt32BE(len - 4).toString(16).padStart(8, '0'));
46
- return rl.prompt();
46
+ return;
47
47
  }
48
48
 
49
49
  // Try 3.3
package/bin/cli-find.js CHANGED
@@ -12,7 +12,7 @@ const fs = require('fs-extra');
12
12
  // Disable debug messages from the proxy
13
13
  try {
14
14
  require('debug').disable();
15
- } catch(ex) {}
15
+ } catch (ex) { /* Intentionally empty */ }
16
16
 
17
17
  const ROOT = path.resolve(__dirname);
18
18
 
@@ -52,7 +52,7 @@ const localIPPorts = localIPs.map(ip => `${ip}:${program.port}`);
52
52
 
53
53
  const escapeUnicode = str => str.replace(/[\u00A0-\uffff]/gu, c => '\\u' + ('000' + c.charCodeAt().toString(16)).slice(-4));
54
54
 
55
- proxy.onError(function(ctx, err) {
55
+ proxy.onError(function (ctx, err) {
56
56
  switch (err.code) {
57
57
  case 'ERR_STREAM_DESTROYED':
58
58
  case 'ECONNRESET':
@@ -71,7 +71,7 @@ proxy.onError(function(ctx, err) {
71
71
  }
72
72
  });
73
73
 
74
- proxy.onRequest(function(ctx, callback) {
74
+ proxy.onRequest(function (ctx, callback) {
75
75
  if (ctx.clientToProxyRequest.method === 'GET' && ctx.clientToProxyRequest.url === '/cert' && localIPPorts.includes(ctx.clientToProxyRequest.headers.host)) {
76
76
  ctx.use(Proxy.gunzip);
77
77
  console.log('Intercepted certificate request');
@@ -94,19 +94,19 @@ proxy.onRequest(function(ctx, callback) {
94
94
  } else if (ctx.clientToProxyRequest.method === 'POST' && /tuya/.test(ctx.clientToProxyRequest.headers.host)) {
95
95
  ctx.use(Proxy.gunzip);
96
96
 
97
- ctx.onRequestData(function(ctx, chunk, callback) {
97
+ ctx.onRequestData(function (ctx, chunk, callback) {
98
98
  return callback(null, chunk);
99
99
  });
100
- ctx.onRequestEnd(function(ctx, callback) {
100
+ ctx.onRequestEnd(function (ctx, callback) {
101
101
  callback();
102
102
  });
103
103
 
104
104
  let chunks = [];
105
- ctx.onResponseData(function(ctx, chunk, callback) {
105
+ ctx.onResponseData(function (ctx, chunk, callback) {
106
106
  chunks.push(chunk);
107
107
  return callback(null, chunk);
108
108
  });
109
- ctx.onResponseEnd(function(ctx, callback) {
109
+ ctx.onResponseEnd(function (ctx, callback) {
110
110
  emitter.emit('tuya-config', Buffer.concat(chunks).toString());
111
111
  callback();
112
112
  });
@@ -188,17 +188,17 @@ emitter.on('tuya-config', body => {
188
188
  }, 5000);
189
189
  });
190
190
 
191
- proxy.listen({port: program.port, sslCaDir: ROOT}, err => {
191
+ proxy.listen({ port: program.port, sslCaDir: ROOT }, err => {
192
192
  if (err) {
193
193
  console.error('Error starting proxy: ' + err);
194
194
  return setTimeout(() => {
195
195
  process.exit(0);
196
196
  }, 5000);
197
197
  }
198
- let {address, port} = proxy.httpServer.address();
198
+ let { address, port } = proxy.httpServer.address();
199
199
  if (address === '::' || address === '0.0.0.0') address = localIPs[0];
200
200
 
201
- QRCode.toString(`http://${address}:${port}/cert`, {type: 'terminal'}, function(err, url) {
201
+ QRCode.toString(`http://${address}:${port}/cert`, { type: 'terminal' }, function (err, url) {
202
202
  console.log(url);
203
203
  console.log('\nFollow the instructions on https://github.com/AMoo-Miki/homebridge-tuya-lan/wiki/Setup-Instructions');
204
204
  console.log(`Proxy IP: ${address}`);
package/index.js CHANGED
@@ -54,12 +54,12 @@ const CLASS_DEF = {
54
54
  oildiffuser: OilDiffuserAccessory
55
55
  };
56
56
 
57
- let Characteristic, PlatformAccessory, Service, Categories, AdaptiveLightingController, UUID, Perms;
57
+ let Characteristic, PlatformAccessory, Service, Categories, _AdaptiveLightingController, UUID, Perms;
58
58
 
59
59
  module.exports = function (homebridge) {
60
60
  ({
61
61
  platformAccessory: PlatformAccessory,
62
- hap: { Characteristic, Service, AdaptiveLightingController, Accessory: { Categories }, uuid: UUID, Perms }
62
+ hap: { Characteristic, Service, AdaptiveLightingController: _AdaptiveLightingController, Accessory: { Categories }, uuid: UUID, Perms }
63
63
  } = homebridge);
64
64
 
65
65
  homebridge.registerPlatform(PLUGIN_NAME, PLATFORM_NAME, TuyaLan, true);
@@ -117,7 +117,7 @@ class TuyaLan {
117
117
  device.type = ('' + device.type).trim();
118
118
 
119
119
  device.ip = ('' + (device.ip || '')).trim();
120
- } catch (ex) { }
120
+ } catch (ex) { /* Intentionally empty */ }
121
121
 
122
122
  if (!device.type) return this.log.error('%s (%s) doesn\'t have a type defined.', device.name || 'Unnamed device', device.id);
123
123
  if (!CLASS_DEF[device.type.toLowerCase()]) return this.log.error('%s (%s) doesn\'t have a valid type defined.', device.name || 'Unnamed device', device.id);
@@ -89,43 +89,43 @@ class AirPurifierAccessory extends BaseAccessory {
89
89
  }
90
90
  constructor(...props) {
91
91
  super(...props);
92
- const {Characteristic} = this.hap;
92
+ const { Characteristic } = this.hap;
93
93
 
94
- if (this.device.context.noRotationSpeed) {
94
+ if (this.device.context.noRotationSpeed) {
95
95
 
96
- let fanSpeedSteps = (
97
- this.device.context.fanSpeedSteps &&
98
- isFinite(this.device.context.fanSpeedSteps) &&
99
- this.device.context.fanSpeedSteps > 0 &&
96
+ let fanSpeedSteps = (
97
+ this.device.context.fanSpeedSteps &&
98
+ isFinite(this.device.context.fanSpeedSteps) &&
99
+ this.device.context.fanSpeedSteps > 0 &&
100
100
  this.device.context.fanSpeedSteps < 100) ? this.device.context.fanSpeedSteps : 100;
101
101
  let _fanSpeedLabels = {};
102
102
  // Special handling for particular devices //
103
103
  switch (this.device.context.manufacturer) {
104
- case 'Breville':
105
- _fanSpeedLabels = {0: 'off', 1: 'low', 2: 'mid', 3: 'high', 4: 'turbo'};
106
- this._rotationSteps = [...Array(5).keys()];
107
- fanSpeedSteps = 5;
108
- break;
104
+ case 'Breville':
105
+ _fanSpeedLabels = { 0: 'off', 1: 'low', 2: 'mid', 3: 'high', 4: 'turbo' };
106
+ this._rotationSteps = [...Array(5).keys()];
107
+ fanSpeedSteps = 5;
108
+ break;
109
109
  case 'Proscenic':
110
- _fanSpeedLabels = {0: 'sleep', 1: 'mid', 2: 'high', 3: 'auto'};
110
+ _fanSpeedLabels = { 0: 'sleep', 1: 'mid', 2: 'high', 3: 'auto' };
111
111
  fanSpeedSteps = 3;
112
112
  this._rotationSteps = [...Array(4).keys()];
113
113
  break;
114
114
  case 'siguro':
115
- _fanSpeedLabels = {0: 'sleep', 1: 'auto'};
115
+ _fanSpeedLabels = { 0: 'sleep', 1: 'auto' };
116
116
  fanSpeedSteps = 2;
117
117
  this._rotationSteps = [...Array(2).keys()];
118
- break;
119
- default: // Just use numeric values
120
- this._rotationSteps = [...Array(fanSpeedSteps).keys()];
118
+ break;
119
+ default: // Just use numeric values
120
+ this._rotationSteps = [...Array(fanSpeedSteps).keys()];
121
121
  for (let i = 0; i <= fanSpeedSteps; i++) {
122
- _fanSpeedLabels[i] = i;
122
+ _fanSpeedLabels[i] = i;
123
123
  }
124
124
  }
125
- this._rotationStops = {0: _fanSpeedLabels[0]};
125
+ this._rotationStops = { 0: _fanSpeedLabels[0] };
126
126
  for (let i = 0; i < 100; i++) {
127
127
  const _rotationStep = Math.floor(fanSpeedSteps * i / 100);
128
- this._rotationStops[i+1] = _fanSpeedLabels[_rotationStep];
128
+ this._rotationStops[i + 1] = _fanSpeedLabels[_rotationStep];
129
129
  }
130
130
  }
131
131
  this.airQualityLevels = [
@@ -145,7 +145,7 @@ class AirPurifierAccessory extends BaseAccessory {
145
145
  * Register the services that this accessory supports.
146
146
  */
147
147
  _registerPlatformAccessory() {
148
- const {Service} = this.hap;
148
+ const { Service } = this.hap;
149
149
  /* Add the main air purifier */
150
150
  this.accessory.addService(Service.AirPurifier, this.device.context.name);
151
151
  /* If configured to include air quality data, include that service too */
@@ -161,7 +161,7 @@ class AirPurifierAccessory extends BaseAccessory {
161
161
  * if the configuration is updated after the device is first added.
162
162
  */
163
163
  _addAirQualityService() {
164
- const {Service} = this.hap;
164
+ const { Service } = this.hap;
165
165
  const nameAirQuality = this.device.context.nameAirQuality || 'Air Quality';
166
166
  this.log.info('Adding air quality sensor: %s', nameAirQuality);
167
167
  this.accessory.addService(Service.AirQualitySensor, nameAirQuality);
@@ -171,7 +171,7 @@ class AirPurifierAccessory extends BaseAccessory {
171
171
  * @param {*} dps
172
172
  */
173
173
  _registerCharacteristics(dps) {
174
- const {Service, Characteristic} = this.hap;
174
+ const { Service, Characteristic } = this.hap;
175
175
  /* Air purifier service characteristics */
176
176
  const airPurifierService = this.accessory.getService(Service.AirPurifier);
177
177
  this._checkServiceName(airPurifierService, this.device.context.name);
@@ -185,10 +185,10 @@ class AirPurifierAccessory extends BaseAccessory {
185
185
  .on('get', this.getCurrentAirPurifierState.bind(this));
186
186
 
187
187
 
188
- const characteristicTargetAirPurifierState = airPurifierService.getCharacteristic(Characteristic.TargetAirPurifierState)
189
- .updateValue(this._getTargetAirPurifierState(this._getMode(dps)))
190
- .on('get', this.getTargetAirPurifierState.bind(this))
191
- .on('set', this.setTargetAirPurifierState.bind(this));
188
+ const characteristicTargetAirPurifierState = airPurifierService.getCharacteristic(Characteristic.TargetAirPurifierState)
189
+ .updateValue(this._getTargetAirPurifierState(this._getMode(dps)))
190
+ .on('get', this.getTargetAirPurifierState.bind(this))
191
+ .on('set', this.setTargetAirPurifierState.bind(this));
192
192
 
193
193
  let characteristicLockPhysicalControls;
194
194
  if (!this.device.context.noChildLock) {
@@ -197,7 +197,7 @@ class AirPurifierAccessory extends BaseAccessory {
197
197
  .on('get', this.getLockPhysicalControls.bind(this))
198
198
  .on('set', this.setLockPhysicalControls.bind(this));
199
199
  } else {
200
- this._removeCharacteristic(service, Characteristic.LockPhysicalControls);
200
+ this._removeCharacteristic(airPurifierService, Characteristic.LockPhysicalControls);
201
201
  }
202
202
  const characteristicRotationSpeed = airPurifierService.getCharacteristic(Characteristic.RotationSpeed)
203
203
  .updateValue(this._getRotationSpeed(dps))
@@ -230,46 +230,46 @@ class AirPurifierAccessory extends BaseAccessory {
230
230
  /* Listen for changes */
231
231
  this.device.on('change', (changes, state) => {
232
232
  this.log.debug('Changes: %o, State: %o', changes, state);
233
- if (changes.hasOwnProperty(DP_SWITCH)) {
234
- /* On/Off state change */
235
- const newActive = this._getActive(changes[DP_SWITCH]);
233
+ if (changes.hasOwnProperty(DP_SWITCH)) {
234
+ /* On/Off state change */
235
+ const newActive = this._getActive(changes[DP_SWITCH]);
236
236
 
237
- // switch power on before other updates to avoid "Turning on..." state
238
- if (changes[DP_SWITCH]) {
239
- this.log.debug('Switching state first');
240
- characteristicActive.updateValue(newActive);
237
+ // switch power on before other updates to avoid "Turning on..." state
238
+ if (changes[DP_SWITCH]) {
239
+ this.log.debug('Switching state first');
240
+ characteristicActive.updateValue(newActive);
241
241
 
242
- characteristicCurrentAirPurifierState.updateValue(
243
- this._getCurrentAirPurifierState(changes[DP_SWITCH]));
244
- }
242
+ characteristicCurrentAirPurifierState.updateValue(
243
+ this._getCurrentAirPurifierState(changes[DP_SWITCH]));
244
+ }
245
245
 
246
- if (!changes.hasOwnProperty(DP_FAN_SPEED)) {
247
- characteristicRotationSpeed.updateValue(this._getRotationSpeed(state));
248
- }
249
- if (!changes.hasOwnProperty(DP_MODE)) {
250
- characteristicTargetAirPurifierState.updateValue(
251
- this._getTargetAirPurifierState(this._getMode(state)));
252
- }
246
+ if (!changes.hasOwnProperty(DP_FAN_SPEED)) {
247
+ characteristicRotationSpeed.updateValue(this._getRotationSpeed(state));
248
+ }
249
+ if (!changes.hasOwnProperty(DP_MODE)) {
250
+ characteristicTargetAirPurifierState.updateValue(
251
+ this._getTargetAirPurifierState(this._getMode(state)));
252
+ }
253
253
 
254
- // switch power off after other updates to avoid "Turning off..." state
255
- if (!changes[DP_SWITCH]) {
256
- this.log.debug('Switching state last');
257
- characteristicCurrentAirPurifierState.updateValue(
258
- this._getCurrentAirPurifierState(changes[DP_SWITCH]));
254
+ // switch power off after other updates to avoid "Turning off..." state
255
+ if (!changes[DP_SWITCH]) {
256
+ this.log.debug('Switching state last');
257
+ characteristicCurrentAirPurifierState.updateValue(
258
+ this._getCurrentAirPurifierState(changes[DP_SWITCH]));
259
259
 
260
- characteristicActive.updateValue(newActive);
261
- }
262
- }
260
+ characteristicActive.updateValue(newActive);
261
+ }
262
+ }
263
263
 
264
- if (changes.hasOwnProperty(DP_FAN_SPEED)) {
265
- /* Fan speed change */
266
- const newRotationSpeed = this._getRotationSpeed(state);
267
- // Proscenic "auto" fan speed is not mapped and should not trigger a rotation speed update
268
- if (newRotationSpeed) {
269
- if (characteristicRotationSpeed.value !== newRotationSpeed) {
270
- characteristicRotationSpeed.updateValue(newRotationSpeed);
271
- }
272
- }
264
+ if (changes.hasOwnProperty(DP_FAN_SPEED)) {
265
+ /* Fan speed change */
266
+ const newRotationSpeed = this._getRotationSpeed(state);
267
+ // Proscenic "auto" fan speed is not mapped and should not trigger a rotation speed update
268
+ if (newRotationSpeed) {
269
+ if (characteristicRotationSpeed.value !== newRotationSpeed) {
270
+ characteristicRotationSpeed.updateValue(newRotationSpeed);
271
+ }
272
+ }
273
273
 
274
274
  if (!changes.hasOwnProperty(DP_MODE)) {
275
275
  characteristicTargetAirPurifierState.updateValue(
@@ -301,32 +301,32 @@ class AirPurifierAccessory extends BaseAccessory {
301
301
  characteristicAirQuality.updateValue(this._getAirQuality(state));
302
302
  }
303
303
  }
304
- });
305
- }
304
+ });
305
+ }
306
306
 
307
- /* Proscenic air purifier does not support DP_MODE but has fan speed 'auto' */
308
- _getMode(state) {
309
- if (state[DP_MODE]) {
310
- return state[DP_MODE];
311
- } else {
312
- return state[DP_FAN_SPEED] == 'auto' ? 'auto' : 'manual';
313
- }
314
- }
307
+ /* Proscenic air purifier does not support DP_MODE but has fan speed 'auto' */
308
+ _getMode(state) {
309
+ if (state[DP_MODE]) {
310
+ return state[DP_MODE];
311
+ } else {
312
+ return state[DP_FAN_SPEED] == 'auto' ? 'auto' : 'manual';
313
+ }
314
+ }
315
315
 
316
- getActive(callback) {
317
- this.getState(DP_SWITCH, (err, dp) => {
318
- if (err) {
316
+ getActive(callback) {
317
+ this.getState(DP_SWITCH, (err, dp) => {
318
+ if (err) {
319
319
  return callback(err);
320
320
  }
321
321
  callback(null, this._getActive(dp));
322
322
  });
323
323
  }
324
324
  _getActive(dp) {
325
- const {Characteristic} = this.hap;
325
+ const { Characteristic } = this.hap;
326
326
  return dp ? Characteristic.Active.ACTIVE : Characteristic.Active.INACTIVE;
327
327
  }
328
328
  setActive(value, callback) {
329
- const {Characteristic} = this.hap;
329
+ const { Characteristic } = this.hap;
330
330
  switch (value) {
331
331
  case Characteristic.Active.ACTIVE:
332
332
  return this.setState(DP_SWITCH, true, callback);
@@ -344,33 +344,33 @@ class AirPurifierAccessory extends BaseAccessory {
344
344
  });
345
345
  }
346
346
  _getAirQuality(dps) {
347
- const {Characteristic} = this.hap;
347
+ const { Characteristic } = this.hap;
348
348
  /* TODO: Other DP values can be used for Air Quality */
349
349
  switch (this.device.context.manufacturer) {
350
350
  case 'Breville':
351
351
  if (dps[DP_AIR_QUALITY]) {
352
- switch (dps[DP_AIR_QUALITY]) {
353
- case 'poor':
354
- return Characteristic.AirQuality.POOR;
355
- case 'good':
356
- return Characteristic.AirQuality.GOOD;
357
- case 'great':
358
- return Characteristic.AirQuality.EXCELLENT;
359
- default:
360
- this.log.warn('Unhandled _getAirQuality value: %s', dps[DP_AIR_QUALITY]);
361
- return Characteristic.AirQuality.UNKNOWN;
362
- }
352
+ switch (dps[DP_AIR_QUALITY]) {
353
+ case 'poor':
354
+ return Characteristic.AirQuality.POOR;
355
+ case 'good':
356
+ return Characteristic.AirQuality.GOOD;
357
+ case 'great':
358
+ return Characteristic.AirQuality.EXCELLENT;
359
+ default:
360
+ this.log.warn('Unhandled _getAirQuality value: %s', dps[DP_AIR_QUALITY]);
361
+ return Characteristic.AirQuality.UNKNOWN;
362
+ }
363
363
  }
364
364
  break;
365
365
  default:
366
- if (dps[DP_PM25]) {
367
- /* Loop through the air quality levels until a match is found */
368
- for (var item of this.airQualityLevels) {
369
- if (dps[DP_PM25] >= item[0]) {
370
- return item[1];
371
- }
372
- }
373
- }
366
+ if (dps[DP_PM25]) {
367
+ /* Loop through the air quality levels until a match is found */
368
+ for (var item of this.airQualityLevels) {
369
+ if (dps[DP_PM25] >= item[0]) {
370
+ return item[1];
371
+ }
372
+ }
373
+ }
374
374
  }
375
375
  /* Default return value if nothing has already returned */
376
376
  return 0;
@@ -382,7 +382,7 @@ class AirPurifierAccessory extends BaseAccessory {
382
382
  });
383
383
  }
384
384
  _getCurrentAirPurifierState(dp) {
385
- const {Characteristic} = this.hap;
385
+ const { Characteristic } = this.hap;
386
386
  /* There isn't really a direct mapping to this from the purifier,
387
387
  * so just using as inactive or purifying.
388
388
  */
@@ -397,11 +397,11 @@ class AirPurifierAccessory extends BaseAccessory {
397
397
  });
398
398
  }
399
399
  _getLockPhysicalControls(dp) {
400
- const {Characteristic} = this.hap;
400
+ const { Characteristic } = this.hap;
401
401
  return dp ? Characteristic.LockPhysicalControls.CONTROL_LOCK_ENABLED : Characteristic.LockPhysicalControls.CONTROL_LOCK_DISABLED;
402
402
  }
403
403
  setLockPhysicalControls(value, callback) {
404
- const {Characteristic} = this.hap;
404
+ const { Characteristic } = this.hap;
405
405
  switch (value) {
406
406
  case Characteristic.LockPhysicalControls.CONTROL_LOCK_ENABLED:
407
407
  return this.setState(DP_LOCK_PHYSICAL_CONTROLS, true, callback);
@@ -409,16 +409,16 @@ class AirPurifierAccessory extends BaseAccessory {
409
409
  return this.setState(DP_LOCK_PHYSICAL_CONTROLS, false, callback);
410
410
  }
411
411
  callback();
412
- }
412
+ }
413
413
 
414
- getPM25(callback) {
415
- this.getState(DP_PM25, (err, dp) => {
416
- if (err) {
417
- return callback(err);
418
- }
419
- callback(null, dp);
420
- });
421
- }
414
+ getPM25(callback) {
415
+ this.getState(DP_PM25, (err, dp) => {
416
+ if (err) {
417
+ return callback(err);
418
+ }
419
+ callback(null, dp);
420
+ });
421
+ }
422
422
 
423
423
  getRotationSpeed(callback) {
424
424
  this.getState([DP_SWITCH, DP_FAN_SPEED], (err, dps) => {
@@ -438,7 +438,7 @@ class AirPurifierAccessory extends BaseAccessory {
438
438
  return this._hkRotationSpeed = this.convertRotationSpeedFromTuyaToHomeKit(dps[DP_FAN_SPEED]);
439
439
  }
440
440
  setRotationSpeed(value, callback) {
441
- const {Characteristic} = this.hap;
441
+ const { Characteristic } = this.hap;
442
442
  if (value === 0) {
443
443
  this.setActive(Characteristic.Active.INACTIVE, callback);
444
444
  } else {
@@ -449,26 +449,27 @@ class AirPurifierAccessory extends BaseAccessory {
449
449
  //return this.setMultiState(newState, callback);
450
450
  return this.setState(DP_FAN_SPEED, this.convertRotationSpeedFromHomeKitToTuya(value), callback);
451
451
  }
452
- }
452
+ }
453
453
 
454
- getTargetAirPurifierState(callback) {
455
- this.getState([DP_MODE, DP_FAN_SPEED], (err, dps) => {
456
- if (err) {
457
- return callback(err);
458
- }
454
+ getTargetAirPurifierState(callback) {
455
+ this.getState([DP_MODE, DP_FAN_SPEED], (err, dps) => {
456
+ if (err) {
457
+ return callback(err);
458
+ }
459
459
 
460
- callback(null, this._getTargetAirPurifierState(this._getMode(dps)));
461
- });
462
- }
460
+ callback(null, this._getTargetAirPurifierState(this._getMode(dps)));
461
+ });
462
+ }
463
463
 
464
464
  _getTargetAirPurifierState(dp) {
465
- const {Characteristic} = this.hap;
465
+ const { Characteristic } = this.hap;
466
466
  switch (dp) {
467
467
  case 'manual':
468
468
  case 'Manual':
469
469
  return Characteristic.TargetAirPurifierState.MANUAL;
470
470
  case 'Sleep':
471
- //TODO: Handle differently than passing through?
471
+ //TODO: Handle differently than passing through?
472
+ // falls through
472
473
  case 'auto':
473
474
  case 'Auto':
474
475
  return Characteristic.TargetAirPurifierState.AUTO;
@@ -478,31 +479,31 @@ class AirPurifierAccessory extends BaseAccessory {
478
479
  }
479
480
  }
480
481
  setTargetAirPurifierState(value, callback) {
481
- const {Characteristic} = this.hap;
482
+ const { Characteristic } = this.hap;
482
483
  switch (value) {
483
- case Characteristic.TargetAirPurifierState.MANUAL:
484
+ case Characteristic.TargetAirPurifierState.MANUAL:
484
485
  if (this.device.context.manufacturer == 'Breville') {
485
- return this.setState(DP_MODE, 'manual', callback);
486
+ return this.setState(DP_MODE, 'manual', callback);
486
487
  } else if (this.device.context.manufacturer == 'Proscenic') {
487
488
  // When going from auto to manual, set to the lowest speed
488
- return this.setState(DP_FAN_SPEED, 'sleep', callback);
489
+ return this.setState(DP_FAN_SPEED, 'sleep', callback);
489
490
 
490
491
  } else if (this.device.context.manufacturer == 'siguro') {
491
492
  // When going from auto to manual, set to the lowest speed
492
- return this.setState(DP_FAN_SPEED, 'sleep', callback);
493
+ return this.setState(DP_FAN_SPEED, 'sleep', callback);
493
494
  } else {
494
495
  return this.setState(DP_MODE, 'Manual', callback);
495
496
  }
496
497
 
497
- case Characteristic.TargetAirPurifierState.AUTO:
498
+ case Characteristic.TargetAirPurifierState.AUTO:
498
499
  if (this.device.context.manufacturer == 'Breville') {
499
- return this.setState(DP_MODE, 'auto', callback);
500
+ return this.setState(DP_MODE, 'auto', callback);
500
501
  } else if (this.device.context.manufacturer == 'Proscenic') {
501
502
  return this.setState(DP_FAN_SPEED, 'auto', callback);
502
503
  } else if (this.device.context.manufacturer == 'siguro') {
503
- return this.setState(DP_FAN_SPEED, 'auto', callback);
504
+ return this.setState(DP_FAN_SPEED, 'auto', callback);
504
505
  } else {
505
- return this.setState(DP_MODE, 'Auto', callback);
506
+ return this.setState(DP_MODE, 'Auto', callback);
506
507
  }
507
508
  default:
508
509
  //TODO: Can we do anything about Sleep?
@@ -511,21 +512,21 @@ class AirPurifierAccessory extends BaseAccessory {
511
512
  callback();
512
513
  }
513
514
  getKeyByValue(object, value) {
514
- return Object.keys(object).find(key => object[key] === value);
515
+ return Object.keys(object).find(key => object[key] === value);
515
516
  }
516
517
  convertRotationSpeedFromHomeKitToTuya(value) {
517
518
  this.log.debug('convertRotationSpeedFromHomeKitToTuya: %s: %s', value, this._rotationStops[parseInt(value)]);
518
519
  return this._rotationStops[parseInt(value)];
519
520
  }
520
521
 
521
- convertRotationSpeedFromTuyaToHomeKit(value) {
522
- this.log.debug('convertRotationSpeedFromTuyaToHomeKit: %s: %s', value, this.getKeyByValue(this._rotationStops, value));
523
- let speed = this.device.context.fanSpeedSteps ? '' + this.getKeyByValue(this._rotationStops, value) : this.getKeyByValue(this._rotationStops, value);
524
- if (speed === undefined) {
525
- return 0;
526
- }
527
- return speed;
528
- }
522
+ convertRotationSpeedFromTuyaToHomeKit(value) {
523
+ this.log.debug('convertRotationSpeedFromTuyaToHomeKit: %s: %s', value, this.getKeyByValue(this._rotationStops, value));
524
+ let speed = this.device.context.fanSpeedSteps ? '' + this.getKeyByValue(this._rotationStops, value) : this.getKeyByValue(this._rotationStops, value);
525
+ if (speed === undefined) {
526
+ return 0;
527
+ }
528
+ return speed;
529
+ }
529
530
 
530
- }
531
+ }
531
532
  module.exports = AirPurifierAccessory;