homebridge-tuya-plus 3.1.2

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 (42) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  2. package/.github/ISSUE_TEMPLATE/new-device.md +24 -0
  3. package/.github/workflows/codeql-analysis.yml +67 -0
  4. package/.github/workflows/lint.yml +23 -0
  5. package/Changelog.md +63 -0
  6. package/LICENSE +21 -0
  7. package/Readme.MD +106 -0
  8. package/assets/Tuya-Plugin-Branding.png +0 -0
  9. package/bin/cli-decode.js +197 -0
  10. package/bin/cli-find.js +207 -0
  11. package/bin/cli.js +13 -0
  12. package/config-example.MD +43 -0
  13. package/config.schema.json +538 -0
  14. package/eslint.config.mjs +15 -0
  15. package/index.js +242 -0
  16. package/lib/AirConditionerAccessory.js +445 -0
  17. package/lib/AirPurifierAccessory.js +532 -0
  18. package/lib/BaseAccessory.js +290 -0
  19. package/lib/ConvectorAccessory.js +313 -0
  20. package/lib/CustomMultiOutletAccessory.js +111 -0
  21. package/lib/DehumidifierAccessory.js +301 -0
  22. package/lib/DoorbellAccessory.js +208 -0
  23. package/lib/EnergyCharacteristics.js +86 -0
  24. package/lib/GarageDoorAccessory.js +307 -0
  25. package/lib/MultiOutletAccessory.js +106 -0
  26. package/lib/OilDiffuserAccessory.js +480 -0
  27. package/lib/OutletAccessory.js +83 -0
  28. package/lib/RGBTWLightAccessory.js +234 -0
  29. package/lib/RGBTWOutletAccessory.js +296 -0
  30. package/lib/SimpleBlindsAccessory.js +299 -0
  31. package/lib/SimpleDimmer2Accessory.js +54 -0
  32. package/lib/SimpleDimmerAccessory.js +54 -0
  33. package/lib/SimpleFanAccessory.js +137 -0
  34. package/lib/SimpleFanLightAccessory.js +201 -0
  35. package/lib/SimpleHeaterAccessory.js +154 -0
  36. package/lib/SimpleLightAccessory.js +39 -0
  37. package/lib/SwitchAccessory.js +106 -0
  38. package/lib/TWLightAccessory.js +91 -0
  39. package/lib/TuyaAccessory.js +746 -0
  40. package/lib/TuyaDiscovery.js +165 -0
  41. package/lib/ValveAccessory.js +150 -0
  42. package/package.json +49 -0
@@ -0,0 +1,480 @@
1
+ const BaseAccessory = require('./BaseAccessory');
2
+ const async = require('async');
3
+
4
+ class OilDiffuserAccessory extends BaseAccessory {
5
+ static getCategory(Categories) {
6
+ return Categories.DEHUMIDIFIER;
7
+ }
8
+
9
+ constructor(...props) {
10
+ super(...props);
11
+ }
12
+
13
+ _isBelleLife() {
14
+ if (this.device.context.manufacturer.trim().toLowerCase() === 'bellelife') {
15
+ return true;
16
+ } else {
17
+ return false;
18
+ }
19
+ }
20
+
21
+ _isGeeni() {
22
+ if (this.device.context.manufacturer.trim().toLowerCase() === 'geeni') {
23
+ return true;
24
+ } else {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ _isAsakuki() {
30
+ if (this.device.context.manufacturer.trim().toLowerCase() === 'asakuki') {
31
+ return true;
32
+ } else {
33
+ return false;
34
+ }
35
+ }
36
+
37
+ _registerPlatformAccessory() {
38
+ this._verifyCachedPlatformAccessory();
39
+ this._justRegistered = true;
40
+
41
+ super._registerPlatformAccessory();
42
+ }
43
+
44
+ _verifyCachedPlatformAccessory() {
45
+ if (this._justRegistered) return;
46
+
47
+ const {Service} = this.hap;
48
+
49
+ const humidifierName = this.device.context.name;
50
+ let humidifierService = this.accessory.getServiceByUUIDAndSubType(Service.HumidifierDehumidifier, 'humidifier');
51
+ if (humidifierService) this._checkServiceName(humidifierService, humidifierName);
52
+ else humidifierService = this.accessory.addService(Service.HumidifierDehumidifier, humidifierName, 'humidifier');
53
+
54
+ const lightName = this.device.context.name + ' Light';
55
+ let lightService = this.accessory.getServiceByUUIDAndSubType(Service.Lightbulb, 'lightbulb');
56
+ if (lightService) this._checkServiceName(lightService, lightName);
57
+ else lightService = this.accessory.addService(Service.Lightbulb, lightName, 'lightbulb');
58
+
59
+ this.accessory.services
60
+ .forEach(service => {
61
+ if ((service.UUID === Service.HumidifierDehumidifier.UUID && service !== humidifierService) || (service.UUID === Service.Lightbulb.UUID && service !== lightService))
62
+ this.accessory.removeService(service);
63
+ });
64
+ }
65
+
66
+ _registerCharacteristics(dps) {
67
+ this._verifyCachedPlatformAccessory();
68
+
69
+ const {Service, AdaptiveLightingController, Characteristic, EnergyCharacteristics} = this.hap;
70
+
71
+ const humidifierService = this.accessory.getServiceByUUIDAndSubType(Service.HumidifierDehumidifier, 'humidifier');
72
+ const lightService = this.accessory.getServiceByUUIDAndSubType(Service.Lightbulb, 'lightbulb');
73
+
74
+ this.dpLight = this._getCustomDP(this.device.context.dpLight) || '5';
75
+ this.dpMode = this._getCustomDP(this.device.context.dpMode) || '6';
76
+ this.dpColor = this._getCustomDP(this.device.context.dpColor) || '8';
77
+ this.dpActive = this._getCustomDP(this.device.context.dpActive) || '1';
78
+ this.dpRotationSpeed = this._getCustomDP(this.device.context.dpRotationSpeed) || '2';
79
+ this.dpWaterLevel = this._getCustomDP(this.device.context.dpWaterLevel) || '9';
80
+ this.maxSpeed = this._getCustomDP(this.device.context.maxSpeed) || 2;
81
+
82
+ if(this._isBelleLife()){
83
+ this.cmdInterval = 'interval';
84
+ this.cmdLow = 'small';
85
+ this.cmdHigh = 'large';
86
+ }
87
+ else if(this._isGeeni()){
88
+ this.cmdInterval = '2';
89
+ this.cmdContinuous = '1';
90
+ }
91
+ else if(this._isAsakuki()){
92
+ this.cmdLow = 'small';
93
+ this.cmdHigh = 'big';
94
+ }
95
+ else {
96
+ this.cmdInterval = this.device.context.cmdInterval || '2';
97
+ this.cmdContinuous = this.device.context.cmdContinuous || '1';
98
+ }
99
+
100
+ this._detectColorFunction(dps[this.dpColor]);
101
+
102
+ this.cmdWhite = 'white';
103
+ if (this.device.context.cmdWhite) {
104
+ if (/^w[a-z]+$/i.test(this.device.context.cmdWhite)) this.cmdWhite = ('' + this.device.context.cmdWhite).trim();
105
+ else throw new Error(`The cmdWhite doesn't appear to be valid: ${this.device.context.cmdWhite}`);
106
+ }
107
+
108
+ this.cmdColor = 'colour';
109
+ if (this.device.context.cmdColor) {
110
+ if (/^c[a-z]+$/i.test(this.device.context.cmdColor)) this.cmdColor = ('' + this.device.context.cmdColor).trim();
111
+ else throw new Error(`The cmdColor doesn't appear to be valid: ${this.device.context.cmdColor}`);
112
+ } else if (this.device.context.cmdColour) {
113
+ if (/^c[a-z]+$/i.test(this.device.context.cmdColour)) this.cmdColor = ('' + this.device.context.cmdColour).trim();
114
+ else throw new Error(`The cmdColour doesn't appear to be valid: ${this.device.context.cmdColour}`);
115
+ }
116
+
117
+ // Led Light
118
+
119
+ const characteristicLightOn = lightService.getCharacteristic(Characteristic.On)
120
+ .updateValue(dps[this.dpLight])
121
+ .on('get', this.getState.bind(this, this.dpLight))
122
+ .on('set', this.setState.bind(this, this.dpLight));
123
+
124
+ const characteristicBrightness = lightService.getCharacteristic(Characteristic.Brightness)
125
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? this.convertBrightnessFromTuyaToHomeKit(dps[this.dpColor]).b : this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).b)
126
+ .on('get', this.getBrightness.bind(this))
127
+ .on('set', this.setBrightness.bind(this));
128
+
129
+ const characteristicColorTemperature = lightService.getCharacteristic(Characteristic.ColorTemperature)
130
+ .setProps({
131
+ minValue: 0,
132
+ maxValue: 600
133
+ })
134
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? this.convertColorTemperatureFromTuyaToHomeKit(dps[this.dpColorTemperature]) : 0)
135
+ .on('get', this.getColorTemperature.bind(this))
136
+ .on('set', this.setColorTemperature.bind(this));
137
+
138
+ const characteristicHue = lightService.getCharacteristic(Characteristic.Hue)
139
+ .updateValue(this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).h)
140
+ .on('get', this.getHue.bind(this))
141
+ .on('set', this.setHue.bind(this));
142
+
143
+ const characteristicSaturation = lightService.getCharacteristic(Characteristic.Saturation)
144
+ .updateValue(this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).s)
145
+ .on('get', this.getSaturation.bind(this))
146
+ .on('set', this.setSaturation.bind(this));
147
+
148
+
149
+ this.characteristicHue = characteristicHue;
150
+ this.characteristicSaturation = characteristicSaturation;
151
+ this.characteristicColorTemperature = characteristicColorTemperature;
152
+ this.characteristicBrightness = characteristicBrightness;
153
+
154
+ if (this.adaptiveLightingSupport()) {
155
+ this.adaptiveLightingController = new AdaptiveLightingController(lightService);
156
+ this.accessory.configureController(this.adaptiveLightingController);
157
+ this.accessory.adaptiveLightingController = this.adaptiveLightingController;
158
+ }
159
+
160
+ // Humidifier
161
+
162
+ const characteristicActive = humidifierService.getCharacteristic(Characteristic.Active)
163
+ .updateValue(this._getActive(dps[this.dpActive]))
164
+ .on('get', this.getActive.bind(this))
165
+ .on('set', this.setActive.bind(this));
166
+
167
+ humidifierService.getCharacteristic(Characteristic.CurrentHumidifierDehumidifierState)
168
+ .updateValue(this._getCurrentHumidifierDehumidifierState(dps))
169
+ .on('get', this.getCurrentHumidifierDehumidifierState.bind(this));
170
+
171
+ humidifierService.getCharacteristic(Characteristic.TargetHumidifierDehumidifierState)
172
+ .setProps({
173
+ minValue: 1,
174
+ maxValue: 1,
175
+ validValues: [1]
176
+ })
177
+ .updateValue(this._getTargetHumidifierDehumidifierState())
178
+ .on('get', this.getTargetHumidifierDehumidifierState.bind(this))
179
+ .on('set', this.setTargetHumidifierDehumidifierState.bind(this));
180
+
181
+ const characteristicWaterLevel = humidifierService.getCharacteristic(Characteristic.WaterLevel)
182
+ .updateValue(this._getWaterLevel(dps[this.dpWaterLevel]))
183
+ .on('get', this.getWaterLevel.bind(this))
184
+
185
+ humidifierService.getCharacteristic(Characteristic.CurrentRelativeHumidity)
186
+ .updateValue(this.dpActive ? 1 : 0)
187
+ .on('get', this.getRotationSpeed.bind(this));
188
+
189
+ const characteristicRotationSpeed = humidifierService.getCharacteristic(Characteristic.RotationSpeed)
190
+ .setProps({
191
+ minValue: 0,
192
+ maxValue: this.maxSpeed,
193
+ minStep: 1
194
+ })
195
+ .updateValue(this._getRotationSpeed(dps))
196
+ .on('get', this.getRotationSpeed.bind(this))
197
+ .on('set', this.setRotationSpeed.bind(this));
198
+
199
+ this.characteristicActive = characteristicActive;
200
+ this.characteristicRotationSpeed = characteristicRotationSpeed;
201
+
202
+
203
+
204
+ this.device.on('change', (changes, state) => {
205
+ if (changes.hasOwnProperty(this.dpLight) && characteristicLightOn.value !== changes[this.dpLight]) characteristicLightOn.updateValue(changes[this.dpLight]);
206
+
207
+ if (changes.hasOwnProperty(this.dpActive)) {
208
+ const newActive = this._getActive(changes[this.dpActive]);
209
+ if (characteristicActive.value !== newActive) characteristicActive.updateValue(newActive);
210
+ }
211
+
212
+ if (changes.hasOwnProperty(this.dpRotationSpeed)) {
213
+ const newValue = this._getRotationSpeed(changes[this.dpRotationSpeed]);
214
+ if (characteristicRotationSpeed.value !== newValue) characteristicRotationSpeed.updateValue(newValue);
215
+ }
216
+
217
+ if (changes.hasOwnProperty(this.dpWaterLevel) && characteristicWaterLevel) {
218
+ const waterLevel = changes[this.dpWaterLevel]
219
+ if (characteristicWaterLevel.value !== waterLevel) characteristicWaterLevel.updateValue(waterLevel);
220
+ }
221
+
222
+ if (changes.hasOwnProperty(this.dpColor)) {
223
+ const oldColor = this.convertColorFromTuyaToHomeKit(this.convertColorFromHomeKitToTuya({
224
+ h: characteristicHue.value,
225
+ s: characteristicSaturation.value,
226
+ b: characteristicBrightness.value
227
+ }));
228
+ const newColor = this.convertColorFromTuyaToHomeKit(changes[this.dpColor]);
229
+
230
+ if (oldColor.h !== newColor.h) characteristicHue.updateValue(newColor.h);
231
+
232
+ if (oldColor.s !== newColor.s) characteristicSaturation.updateValue(newColor.s);
233
+
234
+ if (oldColor.b !== newColor.b) characteristicBrightness.updateValue(newColor.b);
235
+ }
236
+
237
+ });
238
+ }
239
+
240
+ getBrightness(callback) {
241
+ if (this.device.state[this.dpMode] === this.cmdWhite) return callback(null, this.convertBrightnessFromTuyaToHomeKit(this.device.state[this.dpColor]).b);
242
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).b);
243
+ }
244
+
245
+ setBrightness(value, callback) {
246
+ if(value === 0) {
247
+ return this.setState(this.dpLight, false, callback);
248
+ }
249
+ else {
250
+ if (this.device.state[this.dpMode] === this.cmdWhite) return this.setState((this.dpColor).b, this.convertBrightnessFromHomeKitToTuya({b: value}), callback);
251
+ this.device.state[this.dpMode] = this.cmdColor;
252
+ this.setMultiState({[this.dpMode]: this.cmdColor, [this.dpColor]: this.convertColorFromHomeKitToTuya({b: value})}, callback);
253
+ }
254
+ }
255
+
256
+ getColorTemperature(callback) {
257
+ if (this.device.state[this.dpMode] !== this.cmdWhite) return callback(null, 0);
258
+ callback(null, this.convertColorTemperatureFromTuyaToHomeKit(this.device.state[this.dpColorTemperature]));
259
+ }
260
+
261
+ setColorTemperature(value, callback) {
262
+ if (value === 0) return callback(null, true);
263
+
264
+ const newColor = this.convertHomeKitColorTemperatureToHomeKitColor(value);
265
+ const oldColor = this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]);
266
+
267
+ this.characteristicHue.updateValue(newColor.h);
268
+ this.characteristicSaturation.updateValue(newColor.s);
269
+ this.device.state[this.dpMode] = this.cmdColor;
270
+
271
+ this.setMultiState({[this.dpMode]: this.cmdColor, [this.dpColor]: this.convertColorFromHomeKitToTuya(newColor)}, callback);
272
+ }
273
+
274
+ getHue(callback) {
275
+ if (this.device.state[this.dpMode] === this.cmdWhite) return callback(null, 0);
276
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).h);
277
+ }
278
+
279
+ setHue(value, callback) {
280
+ this._setHueSaturation({h: value}, callback);
281
+ }
282
+
283
+ getSaturation(callback) {
284
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).s);
285
+ }
286
+
287
+ setSaturation(value, callback) {
288
+ this._setHueSaturation({s: value}, callback);
289
+ }
290
+
291
+ _setHueSaturation(prop, callback) {
292
+ if (!this._pendingHueSaturation) {
293
+ this._pendingHueSaturation = {props: {}, callbacks: []};
294
+ }
295
+
296
+ if (prop) {
297
+ if (this._pendingHueSaturation.timer) clearTimeout(this._pendingHueSaturation.timer);
298
+
299
+ this._pendingHueSaturation.props = {...this._pendingHueSaturation.props, ...prop};
300
+ this._pendingHueSaturation.callbacks.push(callback);
301
+
302
+ this._pendingHueSaturation.timer = setTimeout(() => {
303
+ this._setHueSaturation();
304
+ }, 500);
305
+ return;
306
+ }
307
+
308
+ const callbacks = this._pendingHueSaturation.callbacks;
309
+ const callEachBack = err => {
310
+ async.eachSeries(callbacks, (callback, next) => {
311
+ try {
312
+ callback(err);
313
+ } catch (ex) {}
314
+ next();
315
+ });
316
+ };
317
+
318
+ const isSham = this._pendingHueSaturation.props.h === 0 && this._pendingHueSaturation.props.s === 0;
319
+ const newValue = this.convertColorFromHomeKitToTuya(this._pendingHueSaturation.props);
320
+ this._pendingHueSaturation = null;
321
+
322
+ this.setMultiState({[this.dpMode]: this.cmdColor, [this.dpColor]: newValue}, callEachBack);
323
+ }
324
+
325
+ getActive(callback) {
326
+ this.getState(this.dpActive, (err, dp) => {
327
+ if (err) return callback(err);
328
+ callback(null, this._getActive(dp));
329
+ });
330
+ }
331
+
332
+ _getActive(dp) {
333
+ const {Characteristic} = this.hap;
334
+ return dp ? Characteristic.Active.ACTIVE : Characteristic.Active.INACTIVE;
335
+ }
336
+
337
+ setActive(value, callback) {
338
+ if (this.characteristicActive.value !== value){
339
+ const {Characteristic} = this.hap;
340
+ switch (value) {
341
+ case Characteristic.Active.ACTIVE:
342
+ return this.setState(this.dpActive, true, callback);
343
+
344
+ case Characteristic.Active.INACTIVE:
345
+ return this.setState(this.dpActive, false, callback);
346
+ }
347
+ callback();
348
+ }
349
+ }
350
+
351
+ getCurrentHumidifierDehumidifierState(callback) {
352
+ this.getState([this.dpActive], (err, dps) => {
353
+ if (err) return callback(err);
354
+ callback(null, this._getCurrentHumidifierDehumidifierState(dps));
355
+ });
356
+ }
357
+
358
+ _getCurrentHumidifierDehumidifierState(dps) {
359
+ const {Characteristic} = this.hap;
360
+ return dps[this.dpActive] ? Characteristic.CurrentHumidifierDehumidifierState.HUMIDIFYING : Characteristic.CurrentHumidifierDehumidifierState.INACTIVE;
361
+ }
362
+
363
+ getTargetHumidifierDehumidifierState(callback) {
364
+ this.getState([this.dpActive], (err, dps) => {
365
+ if (err) return callback(err);
366
+ callback(null, this._getTargetHumidifierDehumidifierState(dps));
367
+ });
368
+ //callback(null, this._getTargetHumidifierDehumidifierState());
369
+ }
370
+
371
+ _getTargetHumidifierDehumidifierState() {
372
+ const {Characteristic} = this.hap;
373
+ return Characteristic.TargetHumidifierDehumidifierState.HUMIDIFIER;
374
+ }
375
+
376
+ setTargetHumidifierDehumidifierState(value, callback) {
377
+ this.setState(this.dpActive, true, callback);
378
+ }
379
+
380
+ getWaterLevel(callback) {
381
+ this.getState(this.dpWaterLevel, (err, dp) => {
382
+ if (err) return callback(err);
383
+ callback(null, this._getWaterLevel(dp));
384
+ });
385
+ }
386
+
387
+ // Will hardcode water levels until its needed -Ed, mine only shows empty or not.
388
+ _getWaterLevel(value) {
389
+ if(parseFloat(value) == 0) {return 69;}
390
+ else {return 0;}
391
+ }
392
+
393
+ getRotationSpeed(callback) {
394
+ this.getState([this.dpActive, this.dpRotationSpeed], (err, dps) => {
395
+ if (err) return callback(err);
396
+ callback(null, this._getRotationSpeed(dps));
397
+ });
398
+ }
399
+
400
+ _getRotationSpeed(dps) {
401
+ if (!dps[this.dpActive]) return 0;
402
+ if (this._hkRotationSpeed) {
403
+ const currentRotationSpeed = this.convertRotationSpeedFromHomeKitToTuya(this._hkRotationSpeed);
404
+
405
+ return currentRotationSpeed === dps[this.dpRotationSpeed] ? this._hkRotationSpeed : this.convertRotationSpeedFromTuyaToHomeKit(dps[this.dpRotationSpeed]);
406
+ }
407
+
408
+ return this._hkRotationSpeed = this.convertRotationSpeedFromTuyaToHomeKit(dps[this.dpRotationSpeed]);
409
+ }
410
+
411
+ setRotationSpeed(value, callback) {
412
+ const {Characteristic} = this.hap;
413
+
414
+ if (value === 0) {
415
+ this.setState(this.dpActive, false, callback);
416
+ } else {
417
+ this._hkRotationSpeed = value;
418
+ const newSpeed = this.convertRotationSpeedFromHomeKitToTuya(value);
419
+ const currentSpeed = this.convertRotationSpeedFromHomeKitToTuya(this.characteristicRotationSpeed.value);
420
+ if (this.enableFlipSpeedSlider) this._hkRotationSpeed = this.convertRotationSpeedFromTuyaToHomeKit(newSpeed);
421
+
422
+ if (newSpeed !== currentSpeed) {
423
+ this.characteristicRotationSpeed.updateValue(this._hkRotationSpeed);
424
+ this.setMultiState({[this.dpActive]: true, [this.dpRotationSpeed]: newSpeed}, callback);
425
+ } else {
426
+ callback();
427
+ if (this.enableFlipSpeedSlider)
428
+ process.nextTick(() => {
429
+ this.characteristicRotationSpeed.updateValue(this._hkRotationSpeed);
430
+ });
431
+ }
432
+ }
433
+ }
434
+
435
+ convertRotationSpeedFromTuyaToHomeKit(value) {
436
+ if (this._isBelleLife()) {
437
+ return {[this.cmdInterval]: 1, [this.cmdLow]: 2, [this.cmdHigh]: 3}[value];
438
+ }
439
+ else if (this._isGeeni()){
440
+ return {[this.cmdInterval]: 1, [this.cmdContinuous]: 2}[value];
441
+ }
442
+ else if (this._isAsakuki()){
443
+ return {[this.cmdLow]: 1, [this.cmdHigh]: 2}[value];
444
+ }
445
+ else{
446
+ return {[this.cmdInterval]: 1, [this.cmdContinuous]: 2}[value];
447
+ }
448
+ }
449
+
450
+ convertRotationSpeedFromHomeKitToTuya(value) {
451
+ if (this._isBelleLife()) {
452
+ if (value < 2)
453
+ return this.cmdLow;
454
+ else if (value < 3)
455
+ return this.cmdMiddle
456
+ else
457
+ return this.cmdHigh;
458
+ }
459
+ else if (this._isGeeni()) {
460
+ if (value < 2)
461
+ return this.cmdInterval;
462
+ else
463
+ return this.cmdContinuous;
464
+ }
465
+ else if (this._isAsakuki()) {
466
+ if (value < 2)
467
+ return this.cmdLow;
468
+ else
469
+ return this.cmdHigh;
470
+ }
471
+ else {
472
+ if (value < 2)
473
+ return this.cmdLow;
474
+ else
475
+ return this.cmdHigh;
476
+ }
477
+ }
478
+ }
479
+
480
+ module.exports = OilDiffuserAccessory;
@@ -0,0 +1,83 @@
1
+ const BaseAccessory = require('./BaseAccessory');
2
+
3
+ class OutletAccessory extends BaseAccessory {
4
+ static getCategory(Categories) {
5
+ return Categories.OUTLET;
6
+ }
7
+
8
+ constructor(...props) {
9
+ super(...props);
10
+ }
11
+
12
+ _registerPlatformAccessory() {
13
+ const {Service} = this.hap;
14
+
15
+ this.accessory.addService(Service.Outlet, this.device.context.name);
16
+
17
+ super._registerPlatformAccessory();
18
+ }
19
+
20
+ _registerCharacteristics(dps) {
21
+ const {Service, Characteristic, EnergyCharacteristics} = this.hap;
22
+ const service = this.accessory.getService(Service.Outlet);
23
+ this._checkServiceName(service, this.device.context.name);
24
+
25
+ this.dpPower = this._getCustomDP(this.device.context.dpPower) || '1';
26
+
27
+ const energyKeys = {
28
+ volts: this._getCustomDP(this.device.context.voltsId),
29
+ voltsDivisor: parseInt(this.device.context.voltsDivisor) || 10,
30
+ amps: this._getCustomDP(this.device.context.ampsId),
31
+ ampsDivisor: parseInt(this.device.context.ampsDivisor) || 1000,
32
+ watts: this._getCustomDP(this.device.context.wattsId),
33
+ wattsDivisor: parseInt(this.device.context.wattsDivisor) || 10
34
+ };
35
+
36
+ let characteristicVolts;
37
+ if (energyKeys.volts) {
38
+ characteristicVolts = service.getCharacteristic(EnergyCharacteristics.Volts)
39
+ .updateValue(this._getDividedState(dps[energyKeys.volts], energyKeys.voltsDivisor))
40
+ .on('get', this.getDividedState.bind(this, energyKeys.volts, energyKeys.voltsDivisor));
41
+ } else this._removeCharacteristic(service, EnergyCharacteristics.Volts);
42
+
43
+ let characteristicAmps;
44
+ if (energyKeys.amps) {
45
+ characteristicAmps = service.getCharacteristic(EnergyCharacteristics.Amperes)
46
+ .updateValue(this._getDividedState(dps[energyKeys.amps], energyKeys.ampsDivisor))
47
+ .on('get', this.getDividedState.bind(this, energyKeys.amps, energyKeys.ampsDivisor));
48
+ } else this._removeCharacteristic(service, EnergyCharacteristics.Amperes);
49
+
50
+ let characteristicWatts;
51
+ if (energyKeys.watts) {
52
+ characteristicWatts = service.getCharacteristic(EnergyCharacteristics.Watts)
53
+ .updateValue(this._getDividedState(dps[energyKeys.watts], energyKeys.wattsDivisor))
54
+ .on('get', this.getDividedState.bind(this, energyKeys.watts, energyKeys.wattsDivisor));
55
+ } else this._removeCharacteristic(service, EnergyCharacteristics.Watts);
56
+
57
+ const characteristicOn = service.getCharacteristic(Characteristic.On)
58
+ .updateValue(dps[this.dpPower])
59
+ .on('get', this.getState.bind(this, this.dpPower))
60
+ .on('set', this.setState.bind(this, this.dpPower));
61
+
62
+ this.device.on('change', changes => {
63
+ if (changes.hasOwnProperty(this.dpPower) && characteristicOn.value !== changes[this.dpPower]) characteristicOn.updateValue(changes[this.dpPower]);
64
+
65
+ if (changes.hasOwnProperty(energyKeys.volts) && characteristicVolts) {
66
+ const newVolts = this._getDividedState(changes[energyKeys.volts], energyKeys.voltsDivisor);
67
+ if (characteristicVolts.value !== newVolts) characteristicVolts.updateValue(newVolts);
68
+ }
69
+
70
+ if (changes.hasOwnProperty(energyKeys.amps) && characteristicAmps) {
71
+ const newAmps = this._getDividedState(changes[energyKeys.amps], energyKeys.ampsDivisor);
72
+ if (characteristicAmps.value !== newAmps) characteristicAmps.updateValue(newAmps);
73
+ }
74
+
75
+ if (changes.hasOwnProperty(energyKeys.watts) && characteristicWatts) {
76
+ const newWatts = this._getDividedState(changes[energyKeys.watts], energyKeys.wattsDivisor);
77
+ if (characteristicWatts.value !== newWatts) characteristicWatts.updateValue(newWatts);
78
+ }
79
+ });
80
+ }
81
+ }
82
+
83
+ module.exports = OutletAccessory;