homebridge-tuya-community 3.3.0

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 (44) hide show
  1. package/.eslintrc.js +29 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  3. package/.github/ISSUE_TEMPLATE/new-device.md +24 -0
  4. package/.github/workflows/codeql-analysis.yml +67 -0
  5. package/.github/workflows/eslint.yml +28 -0
  6. package/Changelog.md +87 -0
  7. package/LICENSE +21 -0
  8. package/Readme.MD +99 -0
  9. package/assets/Tuya-Plugin-Branding.png +0 -0
  10. package/bin/cli-decode.js +197 -0
  11. package/bin/cli-find.js +207 -0
  12. package/bin/cli.js +13 -0
  13. package/config-example.MD +43 -0
  14. package/config.schema.json +554 -0
  15. package/index.js +288 -0
  16. package/lib/AirConditionerAccessory.js +445 -0
  17. package/lib/AirPurifierAccessory.js +531 -0
  18. package/lib/BaseAccessory.js +292 -0
  19. package/lib/ConvectorAccessory.js +313 -0
  20. package/lib/CustomMultiLightAccessory.js +70 -0
  21. package/lib/CustomMultiOutletAccessory.js +111 -0
  22. package/lib/DehumidifierAccessory.js +301 -0
  23. package/lib/EnergyCharacteristics.js +86 -0
  24. package/lib/GarageDoorAccessory.js +307 -0
  25. package/lib/MultiLightAccessory.js +64 -0
  26. package/lib/MultiOutletAccessory.js +106 -0
  27. package/lib/OilDiffuserAccessory.js +480 -0
  28. package/lib/OutletAccessory.js +83 -0
  29. package/lib/RGBTWLightAccessory.js +234 -0
  30. package/lib/RGBTWOutletAccessory.js +296 -0
  31. package/lib/SimpleBlindsAccessory.js +298 -0
  32. package/lib/SimpleDimmer2Accessory.js +54 -0
  33. package/lib/SimpleDimmerAccessory.js +54 -0
  34. package/lib/SimpleFanAccessory.js +132 -0
  35. package/lib/SimpleFanLightAccessory.js +205 -0
  36. package/lib/SimpleHeaterAccessory.js +154 -0
  37. package/lib/SimpleLightAccessory.js +39 -0
  38. package/lib/SingleLightAccessory.js +45 -0
  39. package/lib/SwitchAccessory.js +106 -0
  40. package/lib/TWLightAccessory.js +91 -0
  41. package/lib/TuyaAccessory.js +744 -0
  42. package/lib/TuyaDiscovery.js +278 -0
  43. package/lib/ValveAccessory.js +150 -0
  44. package/package.json +49 -0
@@ -0,0 +1,234 @@
1
+ const BaseAccessory = require('./BaseAccessory');
2
+ const async = require('async');
3
+
4
+ class RGBTWLightAccessory extends BaseAccessory {
5
+ static getCategory(Categories) {
6
+ return Categories.LIGHTBULB;
7
+ }
8
+
9
+ constructor(...props) {
10
+ super(...props);
11
+ }
12
+
13
+ _registerPlatformAccessory() {
14
+ const {Service} = this.hap;
15
+
16
+ this.accessory.addService(Service.Lightbulb, this.device.context.name);
17
+
18
+ super._registerPlatformAccessory();
19
+ }
20
+
21
+ _registerCharacteristics(dps) {
22
+ const {Service, Characteristic, AdaptiveLightingController} = this.hap;
23
+ const service = this.accessory.getService(Service.Lightbulb);
24
+ this._checkServiceName(service, this.device.context.name);
25
+
26
+ this.dpPower = this._getCustomDP(this.device.context.dpPower) || '1';
27
+ this.dpMode = this._getCustomDP(this.device.context.dpMode) || '2';
28
+ this.dpBrightness = this._getCustomDP(this.device.context.dpBrightness) || '3';
29
+ this.dpColorTemperature = this._getCustomDP(this.device.context.dpColorTemperature) || '4';
30
+ this.dpColor = this._getCustomDP(this.device.context.dpColor) || '5';
31
+
32
+ this._detectColorFunction(dps[this.dpColor]);
33
+
34
+ this.cmdWhite = 'white';
35
+ if (this.device.context.cmdWhite) {
36
+ if (/^w[a-z]+$/i.test(this.device.context.cmdWhite)) this.cmdWhite = ('' + this.device.context.cmdWhite).trim();
37
+ else throw new Error(`The cmdWhite doesn't appear to be valid: ${this.device.context.cmdWhite}`);
38
+ }
39
+
40
+ this.cmdColor = 'colour';
41
+ if (this.device.context.cmdColor) {
42
+ if (/^c[a-z]+$/i.test(this.device.context.cmdColor)) this.cmdColor = ('' + this.device.context.cmdColor).trim();
43
+ else throw new Error(`The cmdColor doesn't appear to be valid: ${this.device.context.cmdColor}`);
44
+ } else if (this.device.context.cmdColour) {
45
+ if (/^c[a-z]+$/i.test(this.device.context.cmdColour)) this.cmdColor = ('' + this.device.context.cmdColour).trim();
46
+ else throw new Error(`The cmdColour doesn't appear to be valid: ${this.device.context.cmdColour}`);
47
+ }
48
+
49
+ const characteristicOn = service.getCharacteristic(Characteristic.On)
50
+ .updateValue(dps[this.dpPower])
51
+ .on('get', this.getState.bind(this, this.dpPower))
52
+ .on('set', this.setState.bind(this, this.dpPower));
53
+
54
+ const characteristicBrightness = service.getCharacteristic(Characteristic.Brightness)
55
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? this.convertBrightnessFromTuyaToHomeKit(dps[this.dpBrightness]) : this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).b)
56
+ .on('get', this.getBrightness.bind(this))
57
+ .on('set', this.setBrightness.bind(this));
58
+
59
+ const characteristicColorTemperature = service.getCharacteristic(Characteristic.ColorTemperature)
60
+ .setProps({
61
+ minValue: 0,
62
+ maxValue: 600
63
+ })
64
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? this.convertColorTemperatureFromTuyaToHomeKit(dps[this.dpColorTemperature]) : 0)
65
+ .on('get', this.getColorTemperature.bind(this))
66
+ .on('set', this.setColorTemperature.bind(this));
67
+
68
+ const characteristicHue = service.getCharacteristic(Characteristic.Hue)
69
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? 0 : this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).h)
70
+ .on('get', this.getHue.bind(this))
71
+ .on('set', this.setHue.bind(this));
72
+
73
+ const characteristicSaturation = service.getCharacteristic(Characteristic.Saturation)
74
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? 0 : this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).s)
75
+ .on('get', this.getSaturation.bind(this))
76
+ .on('set', this.setSaturation.bind(this));
77
+
78
+ this.characteristicHue = characteristicHue;
79
+ this.characteristicSaturation = characteristicSaturation;
80
+ this.characteristicColorTemperature = characteristicColorTemperature;
81
+
82
+ if (this.adaptiveLightingSupport()) {
83
+ this.adaptiveLightingController = new AdaptiveLightingController(service);
84
+ this.accessory.configureController(this.adaptiveLightingController);
85
+ this.accessory.adaptiveLightingController = this.adaptiveLightingController;
86
+ }
87
+
88
+ this.device.on('change', (changes, state) => {
89
+ if (changes.hasOwnProperty(this.dpPower) && characteristicOn.value !== changes[this.dpPower]) characteristicOn.updateValue(changes[this.dpPower]);
90
+
91
+ switch (state[this.dpMode]) {
92
+ case this.cmdWhite:
93
+ if (changes.hasOwnProperty(this.dpBrightness) && this.convertBrightnessFromHomeKitToTuya(characteristicBrightness.value) !== changes[this.dpBrightness])
94
+ characteristicBrightness.updateValue(this.convertBrightnessFromTuyaToHomeKit(changes[this.dpBrightness]));
95
+
96
+ if (changes.hasOwnProperty(this.dpColorTemperature) && this.convertColorTemperatureFromHomeKitToTuya(characteristicColorTemperature.value) !== changes[this.dpColorTemperature]) {
97
+
98
+ const newColorTemperature = this.convertColorTemperatureFromTuyaToHomeKit(changes[this.dpColorTemperature]);
99
+ const newColor = this.convertHomeKitColorTemperatureToHomeKitColor(newColorTemperature);
100
+
101
+ characteristicHue.updateValue(newColor.h);
102
+ characteristicSaturation.updateValue(newColor.s);
103
+ characteristicColorTemperature.updateValue(newColorTemperature);
104
+
105
+ } else if (changes[this.dpMode] && !changes.hasOwnProperty(this.dpColorTemperature)) {
106
+
107
+ const newColorTemperature = this.convertColorTemperatureFromTuyaToHomeKit(state[this.dpColorTemperature]);
108
+ const newColor = this.convertHomeKitColorTemperatureToHomeKitColor(newColorTemperature);
109
+
110
+ characteristicHue.updateValue(newColor.h);
111
+ characteristicSaturation.updateValue(newColor.s);
112
+ characteristicColorTemperature.updateValue(newColorTemperature);
113
+ }
114
+
115
+ break;
116
+
117
+ default:
118
+ if (changes.hasOwnProperty(this.dpColor)) {
119
+ const oldColor = this.convertColorFromTuyaToHomeKit(this.convertColorFromHomeKitToTuya({
120
+ h: characteristicHue.value,
121
+ s: characteristicSaturation.value,
122
+ b: characteristicBrightness.value
123
+ }));
124
+ const newColor = this.convertColorFromTuyaToHomeKit(changes[this.dpColor]);
125
+
126
+ if (oldColor.b !== newColor.b) characteristicBrightness.updateValue(newColor.b);
127
+ if (oldColor.h !== newColor.h) characteristicHue.updateValue(newColor.h);
128
+
129
+ if (oldColor.s !== newColor.s) characteristicSaturation.updateValue(newColor.h);
130
+
131
+ if (characteristicColorTemperature.value !== 0) characteristicColorTemperature.updateValue(0);
132
+
133
+ } else if (changes[this.dpMode]) {
134
+ if (characteristicColorTemperature.value !== 0) characteristicColorTemperature.updateValue(0);
135
+ }
136
+ }
137
+ });
138
+ }
139
+
140
+ getBrightness(callback) {
141
+ if (this.device.state[this.dpMode] === this.cmdWhite) return callback(null, this.convertBrightnessFromTuyaToHomeKit(this.device.state[this.dpBrightness]));
142
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).b);
143
+ }
144
+
145
+ setBrightness(value, callback) {
146
+ if (this.device.state[this.dpMode] === this.cmdWhite) return this.setState(this.dpBrightness, this.convertBrightnessFromHomeKitToTuya(value), callback);
147
+ this.setState(this.dpColor, this.convertColorFromHomeKitToTuya({b: value}), callback);
148
+ }
149
+
150
+ getColorTemperature(callback) {
151
+ if (this.device.state[this.dpMode] !== this.cmdWhite) return callback(null, 0);
152
+ callback(null, this.convertColorTemperatureFromTuyaToHomeKit(this.device.state[this.dpColorTemperature]));
153
+ }
154
+
155
+ setColorTemperature(value, callback) {
156
+ this.log.debug(`setColorTemperature: ${value}`);
157
+ if (value === 0) return callback(null, true);
158
+
159
+ const newColor = this.convertHomeKitColorTemperatureToHomeKitColor(value);
160
+ this.characteristicHue.updateValue(newColor.h);
161
+ this.characteristicSaturation.updateValue(newColor.s);
162
+
163
+ this.setMultiState({[this.dpMode]: this.cmdWhite, [this.dpColorTemperature]: this.convertColorTemperatureFromHomeKitToTuya(value)}, callback);
164
+ }
165
+
166
+ getHue(callback) {
167
+ if (this.device.state[this.dpMode] === this.cmdWhite) return callback(null, 0);
168
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).h);
169
+ }
170
+
171
+ setHue(value, callback) {
172
+ this._setHueSaturation({h: value}, callback);
173
+ }
174
+
175
+ getSaturation(callback) {
176
+ if (this.device.state[this.dpMode] === this.cmdWhite) return callback(null, 0);
177
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).s);
178
+ }
179
+
180
+ setSaturation(value, callback) {
181
+ this._setHueSaturation({s: value}, callback);
182
+ }
183
+
184
+ _setHueSaturation(prop, callback) {
185
+ if (!this._pendingHueSaturation) {
186
+ this._pendingHueSaturation = {props: {}, callbacks: []};
187
+ }
188
+
189
+ if (prop) {
190
+ if (this._pendingHueSaturation.timer) clearTimeout(this._pendingHueSaturation.timer);
191
+
192
+ this._pendingHueSaturation.props = {...this._pendingHueSaturation.props, ...prop};
193
+ this._pendingHueSaturation.callbacks.push(callback);
194
+
195
+ this._pendingHueSaturation.timer = setTimeout(() => {
196
+ this._setHueSaturation();
197
+ }, 500);
198
+ return;
199
+ }
200
+
201
+ //this.characteristicColorTemperature.updateValue(0);
202
+
203
+ const callbacks = this._pendingHueSaturation.callbacks;
204
+ const callEachBack = err => {
205
+ async.eachSeries(callbacks, (callback, next) => {
206
+ try {
207
+ callback(err);
208
+ } catch (ex) {}
209
+ next();
210
+ }, () => {
211
+ this.characteristicColorTemperature.updateValue(0);
212
+ });
213
+ };
214
+
215
+ const isSham = this._pendingHueSaturation.props.h === 0 && this._pendingHueSaturation.props.s === 0;
216
+ const newValue = this.convertColorFromHomeKitToTuya(this._pendingHueSaturation.props);
217
+ this._pendingHueSaturation = null;
218
+
219
+
220
+ if (this.device.state[this.dpMode] === this.cmdWhite && isSham) return callEachBack();
221
+
222
+ this.setMultiState({[this.dpMode]: this.cmdColor, [this.dpColor]: newValue}, callEachBack);
223
+ }
224
+
225
+ getControllers() {
226
+ if (!this.adaptiveLightingController) {
227
+ return [];
228
+ } else {
229
+ return [this.adaptiveLightingController];
230
+ }
231
+ }
232
+ }
233
+
234
+ module.exports = RGBTWLightAccessory;
@@ -0,0 +1,296 @@
1
+ const BaseAccessory = require('./BaseAccessory');
2
+ const async = require('async');
3
+
4
+ class RGBTWOutletAccessory extends BaseAccessory {
5
+ static getCategory(Categories) {
6
+ return Categories.OUTLET;
7
+ }
8
+
9
+ constructor(...props) {
10
+ super(...props);
11
+ }
12
+
13
+ _registerPlatformAccessory() {
14
+ this._verifyCachedPlatformAccessory();
15
+ this._justRegistered = true;
16
+
17
+ super._registerPlatformAccessory();
18
+ }
19
+
20
+ _verifyCachedPlatformAccessory() {
21
+ if (this._justRegistered) return;
22
+
23
+ const { Service } = this.hap;
24
+
25
+ const outletName = 'Outlet - ' + this.device.context.name;
26
+ let outletService = this.accessory.getServiceById(Service.Outlet, 'outlet');
27
+ if (outletService) this._checkServiceName(outletService, outletName);
28
+ else outletService = this.accessory.addService(Service.Outlet, outletName, 'outlet');
29
+
30
+ const lightName = 'RGBTWLight - ' + this.device.context.name;
31
+ let lightService = this.accessory.getServiceById(Service.Lightbulb, 'lightbulb');
32
+ if (lightService) this._checkServiceName(lightService, lightName);
33
+ else lightService = this.accessory.addService(Service.Lightbulb, lightName, 'lightbulb');
34
+
35
+ this.accessory.services
36
+ .forEach(service => {
37
+ if ((service.UUID === Service.Outlet.UUID && service !== outletService) || (service.UUID === Service.Lightbulb.UUID && service !== lightService))
38
+ this.accessory.removeService(service);
39
+ });
40
+ }
41
+
42
+ _registerCharacteristics(dps) {
43
+ this._verifyCachedPlatformAccessory();
44
+
45
+ const { Service, Characteristic, EnergyCharacteristics } = this.hap;
46
+
47
+ const outletService = this.accessory.getServiceById(Service.Outlet, 'outlet');
48
+ const lightService = this.accessory.getServiceById(Service.Lightbulb, 'lightbulb');
49
+
50
+ this.dpLight = this._getCustomDP(this.device.context.dpLight) || '1';
51
+ this.dpMode = this._getCustomDP(this.device.context.dpMode) || '2';
52
+ this.dpBrightness = this._getCustomDP(this.device.context.dpBrightness) || '3';
53
+ this.dpColorTemperature = this._getCustomDP(this.device.context.dpColorTemperature) || '4';
54
+ this.dpColor = this._getCustomDP(this.device.context.dpColor) || '5';
55
+
56
+ this.dpPower = this._getCustomDP(this.device.context.dpPower) || '101';
57
+
58
+ this._detectColorFunction(dps[this.dpColor]);
59
+
60
+ this.cmdWhite = 'white';
61
+ if (this.device.context.cmdWhite) {
62
+ if (/^w[a-z]+$/i.test(this.device.context.cmdWhite)) this.cmdWhite = ('' + this.device.context.cmdWhite).trim();
63
+ else throw new Error(`The cmdWhite doesn't appear to be valid: ${this.device.context.cmdWhite}`);
64
+ }
65
+
66
+ this.cmdColor = 'colour';
67
+ if (this.device.context.cmdColor) {
68
+ if (/^c[a-z]+$/i.test(this.device.context.cmdColor)) this.cmdColor = ('' + this.device.context.cmdColor).trim();
69
+ else throw new Error(`The cmdColor doesn't appear to be valid: ${this.device.context.cmdColor}`);
70
+ } else if (this.device.context.cmdColour) {
71
+ if (/^c[a-z]+$/i.test(this.device.context.cmdColour)) this.cmdColor = ('' + this.device.context.cmdColour).trim();
72
+ else throw new Error(`The cmdColour doesn't appear to be valid: ${this.device.context.cmdColour}`);
73
+ }
74
+
75
+ const energyKeys = {
76
+ volts: this._getCustomDP(this.device.context.voltsId),
77
+ voltsDivisor: parseInt(this.device.context.voltsDivisor) || 10,
78
+ amps: this._getCustomDP(this.device.context.ampsId),
79
+ ampsDivisor: parseInt(this.device.context.ampsDivisor) || 1000,
80
+ watts: this._getCustomDP(this.device.context.wattsId),
81
+ wattsDivisor: parseInt(this.device.context.wattsDivisor) || 10
82
+ };
83
+
84
+ const characteristicLightOn = lightService.getCharacteristic(Characteristic.On)
85
+ .updateValue(dps[this.dpLight])
86
+ .on('get', this.getState.bind(this, this.dpLight))
87
+ .on('set', this.setState.bind(this, this.dpLight));
88
+
89
+ const characteristicBrightness = lightService.getCharacteristic(Characteristic.Brightness)
90
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? this.convertBrightnessFromTuyaToHomeKit(dps[this.dpBrightness]) : this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).b)
91
+ .on('get', this.getBrightness.bind(this))
92
+ .on('set', this.setBrightness.bind(this));
93
+
94
+ const characteristicColorTemperature = lightService.getCharacteristic(Characteristic.ColorTemperature)
95
+ .setProps({
96
+ minValue: 0,
97
+ maxValue: 600
98
+ })
99
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? this.convertColorTemperatureFromTuyaToHomeKit(dps[this.dpColorTemperature]) : 0)
100
+ .on('get', this.getColorTemperature.bind(this))
101
+ .on('set', this.setColorTemperature.bind(this));
102
+
103
+ const characteristicHue = lightService.getCharacteristic(Characteristic.Hue)
104
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? 0 : this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).h)
105
+ .on('get', this.getHue.bind(this))
106
+ .on('set', this.setHue.bind(this));
107
+
108
+ const characteristicSaturation = lightService.getCharacteristic(Characteristic.Saturation)
109
+ .updateValue(dps[this.dpMode] === this.cmdWhite ? 0 : this.convertColorFromTuyaToHomeKit(dps[this.dpColor]).s)
110
+ .on('get', this.getSaturation.bind(this))
111
+ .on('set', this.setSaturation.bind(this));
112
+
113
+ this.characteristicHue = characteristicHue;
114
+ this.characteristicSaturation = characteristicSaturation;
115
+ this.characteristicColorTemperature = characteristicColorTemperature;
116
+
117
+ let characteristicVolts;
118
+ if (energyKeys.volts) {
119
+ characteristicVolts = outletService.getCharacteristic(EnergyCharacteristics.Volts)
120
+ .updateValue(this._getDividedState(dps[energyKeys.volts], energyKeys.voltsDivisor))
121
+ .on('get', this.getDividedState.bind(this, energyKeys.volts, energyKeys.voltsDivisor));
122
+ } else this._removeCharacteristic(outletService, EnergyCharacteristics.Volts);
123
+
124
+ let characteristicAmps;
125
+ if (energyKeys.amps) {
126
+ characteristicAmps = outletService.getCharacteristic(EnergyCharacteristics.Amperes)
127
+ .updateValue(this._getDividedState(dps[energyKeys.amps], energyKeys.ampsDivisor))
128
+ .on('get', this.getDividedState.bind(this, energyKeys.amps, energyKeys.ampsDivisor));
129
+ } else this._removeCharacteristic(outletService, EnergyCharacteristics.Amperes);
130
+
131
+ let characteristicWatts;
132
+ if (energyKeys.watts) {
133
+ characteristicWatts = outletService.getCharacteristic(EnergyCharacteristics.Watts)
134
+ .updateValue(this._getDividedState(dps[energyKeys.watts], energyKeys.wattsDivisor))
135
+ .on('get', this.getDividedState.bind(this, energyKeys.watts, energyKeys.wattsDivisor));
136
+ } else this._removeCharacteristic(outletService, EnergyCharacteristics.Watts);
137
+
138
+ const characteristicOutletOn = outletService.getCharacteristic(Characteristic.On)
139
+ .updateValue(dps[this.dpPower])
140
+ .on('get', this.getState.bind(this, this.dpPower))
141
+ .on('set', this.setState.bind(this, this.dpPower));
142
+
143
+ this.device.on('change', (changes, state) => {
144
+ if (changes.hasOwnProperty(this.dpLight) && characteristicLightOn.value !== changes[this.dpLight]) characteristicLightOn.updateValue(changes[this.dpLight]);
145
+
146
+ switch (state[this.dpMode]) {
147
+ case this.cmdWhite:
148
+ if (changes.hasOwnProperty(this.dpBrightness) && this.convertBrightnessFromHomeKitToTuya(characteristicBrightness.value) !== changes[this.dpBrightness])
149
+ characteristicBrightness.updateValue(this.convertBrightnessFromTuyaToHomeKit(changes[this.dpBrightness]));
150
+
151
+ if (changes.hasOwnProperty(this.dpColorTemperature) && this.convertColorTemperatureFromHomeKitToTuya(characteristicColorTemperature.value) !== changes[this.dpColorTemperature]) {
152
+
153
+ const newColorTemperature = this.convertColorTemperatureFromTuyaToHomeKit(changes[this.dpColorTemperature]);
154
+ const newColor = this.convertHomeKitColorTemperatureToHomeKitColor(newColorTemperature);
155
+
156
+ characteristicHue.updateValue(newColor.h);
157
+ characteristicSaturation.updateValue(newColor.s);
158
+ characteristicColorTemperature.updateValue(newColorTemperature);
159
+
160
+ } else if (changes[this.dpMode] && !changes.hasOwnProperty(this.dpColorTemperature)) {
161
+
162
+ const newColorTemperature = this.convertColorTemperatureFromTuyaToHomeKit(state[this.dpColorTemperature]);
163
+ const newColor = this.convertHomeKitColorTemperatureToHomeKitColor(newColorTemperature);
164
+
165
+ characteristicHue.updateValue(newColor.h);
166
+ characteristicSaturation.updateValue(newColor.s);
167
+ characteristicColorTemperature.updateValue(newColorTemperature);
168
+ }
169
+
170
+ break;
171
+
172
+ default:
173
+ if (changes.hasOwnProperty(this.dpColor)) {
174
+ const oldColor = this.convertColorFromTuyaToHomeKit(this.convertColorFromHomeKitToTuya({
175
+ h: characteristicHue.value,
176
+ s: characteristicSaturation.value,
177
+ b: characteristicBrightness.value
178
+ }));
179
+ const newColor = this.convertColorFromTuyaToHomeKit(changes[this.dpColor]);
180
+
181
+ if (oldColor.b !== newColor.b) characteristicBrightness.updateValue(newColor.b);
182
+ if (oldColor.h !== newColor.h) characteristicHue.updateValue(newColor.h);
183
+
184
+ if (oldColor.s !== newColor.s) characteristicSaturation.updateValue(newColor.h);
185
+
186
+ if (characteristicColorTemperature.value !== 0) characteristicColorTemperature.updateValue(0);
187
+
188
+ } else if (changes[this.dpMode]) {
189
+ if (characteristicColorTemperature.value !== 0) characteristicColorTemperature.updateValue(0);
190
+ }
191
+ }
192
+
193
+ if (changes.hasOwnProperty(this.dpPower) && characteristicOutletOn.value !== changes[this.dpPower]) characteristicOutletOn.updateValue(changes[this.dpPower]);
194
+
195
+ if (changes.hasOwnProperty(energyKeys.volts) && characteristicVolts) {
196
+ const newVolts = this._getDividedState(changes[energyKeys.volts], energyKeys.voltsDivisor);
197
+ if (characteristicVolts.value !== newVolts) characteristicVolts.updateValue(newVolts);
198
+ }
199
+
200
+ if (changes.hasOwnProperty(energyKeys.amps) && characteristicAmps) {
201
+ const newAmps = this._getDividedState(changes[energyKeys.amps], energyKeys.ampsDivisor);
202
+ if (characteristicAmps.value !== newAmps) characteristicAmps.updateValue(newAmps);
203
+ }
204
+
205
+ if (changes.hasOwnProperty(energyKeys.watts) && characteristicWatts) {
206
+ const newWatts = this._getDividedState(changes[energyKeys.watts], energyKeys.wattsDivisor);
207
+ if (characteristicWatts.value !== newWatts) characteristicWatts.updateValue(newWatts);
208
+ }
209
+ });
210
+ }
211
+
212
+ getBrightness(callback) {
213
+ if (this.device.state[this.dpMode] === this.cmdWhite) return callback(null, this.convertBrightnessFromTuyaToHomeKit(this.device.state[this.dpBrightness]));
214
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).b);
215
+ }
216
+
217
+ setBrightness(value, callback) {
218
+ if (this.device.state[this.dpMode] === this.cmdWhite) return this.setState(this.dpBrightness, this.convertBrightnessFromHomeKitToTuya(value), callback);
219
+ this.setState(this.dpColor, this.convertColorFromHomeKitToTuya({ b: value }), callback);
220
+ }
221
+
222
+ getColorTemperature(callback) {
223
+ if (this.device.state[this.dpMode] !== this.cmdWhite) return callback(null, 0);
224
+ callback(null, this.convertColorTemperatureFromTuyaToHomeKit(this.device.state[this.dpColorTemperature]));
225
+ }
226
+
227
+ setColorTemperature(value, callback) {
228
+ if (value === 0) return callback(null, true);
229
+
230
+ const newColor = this.convertHomeKitColorTemperatureToHomeKitColor(value);
231
+ this.characteristicHue.updateValue(newColor.h);
232
+ this.characteristicSaturation.updateValue(newColor.s);
233
+
234
+ this.setMultiState({ [this.dpMode]: this.cmdWhite, [this.dpColorTemperature]: this.convertColorTemperatureFromHomeKitToTuya(value) }, callback);
235
+ }
236
+
237
+ getHue(callback) {
238
+ if (this.device.state[this.dpMode] === this.cmdWhite) return callback(null, 0);
239
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).h);
240
+ }
241
+
242
+ setHue(value, callback) {
243
+ this._setHueSaturation({ h: value }, callback);
244
+ }
245
+
246
+ getSaturation(callback) {
247
+ if (this.device.state[this.dpMode] === this.cmdWhite) return callback(null, 0);
248
+ callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).s);
249
+ }
250
+
251
+ setSaturation(value, callback) {
252
+ this._setHueSaturation({ s: value }, callback);
253
+ }
254
+
255
+ _setHueSaturation(prop, callback) {
256
+ if (!this._pendingHueSaturation) {
257
+ this._pendingHueSaturation = { props: {}, callbacks: [] };
258
+ }
259
+
260
+ if (prop) {
261
+ if (this._pendingHueSaturation.timer) clearTimeout(this._pendingHueSaturation.timer);
262
+
263
+ this._pendingHueSaturation.props = { ...this._pendingHueSaturation.props, ...prop };
264
+ this._pendingHueSaturation.callbacks.push(callback);
265
+
266
+ this._pendingHueSaturation.timer = setTimeout(() => {
267
+ this._setHueSaturation();
268
+ }, 500);
269
+ return;
270
+ }
271
+
272
+ //this.characteristicColorTemperature.updateValue(0);
273
+
274
+ const callbacks = this._pendingHueSaturation.callbacks;
275
+ const callEachBack = err => {
276
+ async.eachSeries(callbacks, (callback, next) => {
277
+ try {
278
+ callback(err);
279
+ } catch (ex) { }
280
+ next();
281
+ }, () => {
282
+ this.characteristicColorTemperature.updateValue(0);
283
+ });
284
+ };
285
+
286
+ const isSham = this._pendingHueSaturation.props.h === 0 && this._pendingHueSaturation.props.s === 0;
287
+ const newValue = this.convertColorFromHomeKitToTuya(this._pendingHueSaturation.props);
288
+ this._pendingHueSaturation = null;
289
+
290
+ if (this.device.state[this.dpMode] === this.cmdWhite && isSham) return callEachBack();
291
+
292
+ this.setMultiState({ [this.dpMode]: this.cmdColor, [this.dpColor]: newValue }, callEachBack);
293
+ }
294
+ }
295
+
296
+ module.exports = RGBTWOutletAccessory;