homebridge-tuya-plus 3.1.2 → 3.2.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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- package/Readme.MD +14 -15
- package/bin/cli-find.js +1 -1
- package/config-example.MD +8 -4
- package/config.schema.json +12 -4
- package/index.js +2 -1
- package/lib/AirConditionerAccessory.js +4 -4
- package/lib/BaseAccessory.js +4 -6
- package/lib/RGBTWLightAccessory.js +28 -13
- package/lib/SimpleHeaterAccessory.js +22 -10
- package/lib/TWLightAccessory.js +6 -3
- package/package.json +1 -1
- package/wiki/Common-Problems.md +20 -0
- package/wiki/Device-Mapping.md +3 -0
- package/wiki/Get-Local-Keys-for-Your-Devices.md +77 -0
- package/wiki/Setup.md +6 -0
- package/wiki/Supported-Device-Types.md +539 -0
- package/wiki/Supported-Devices.md +51 -0
- package/wiki/User-documented-device-config.md +513 -0
- package/wiki/_Home.md +4 -0
package/Readme.MD
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
# homebridge-tuya-plus
|
|
9
9
|
|
|
10
10
|
[](https://www.npmjs.com/package/homebridge-tuya-plus)
|
|
11
|
-
[](https://www.npmjs.com/package/homebridge-tuya-plus)
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
</span>
|
|
@@ -29,22 +28,22 @@ A community-maintained Homebridge plugin for controlling Tuya devices locally ov
|
|
|
29
28
|
## Supported Device Types
|
|
30
29
|
> Click the number next to your device to find the possible DataPoint "DP" values, then add as needed to your config.
|
|
31
30
|
|
|
32
|
-
* Air Conditioner<sup>[1](https://github.com/
|
|
31
|
+
* Air Conditioner<sup>[1](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md#air-conditioners)</sup>
|
|
33
32
|
* Air Purifiers<sup>[2]()</sup>
|
|
34
|
-
* Convectors<sup>[3](https://github.com/
|
|
35
|
-
* Dehumidifers<sup>[4](https://github.com/
|
|
36
|
-
* Dimmers<sup>[5](https://github.com/
|
|
37
|
-
* Fan<sup>[6](https://github.com/
|
|
38
|
-
* Fan v2<sup>[7](https://github.com/
|
|
39
|
-
* Garages<sup>[8](https://github.com/
|
|
40
|
-
* Heaters<sup>[9](https://github.com/
|
|
33
|
+
* Convectors<sup>[3](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md#heat-convectors)</sup>
|
|
34
|
+
* Dehumidifers<sup>[4](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md)</sup>
|
|
35
|
+
* Dimmers<sup>[5](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md#simple-dimmers)</sup>
|
|
36
|
+
* Fan<sup>[6](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md)</sup>
|
|
37
|
+
* Fan v2<sup>[7](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md)</sup>
|
|
38
|
+
* Garages<sup>[8](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md#garage-doors)</sup>
|
|
39
|
+
* Heaters<sup>[9](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md)</sup>
|
|
41
40
|
* Lights
|
|
42
|
-
* On/Off<sup>[10](https://github.com/
|
|
43
|
-
* Brightness<sup>[11](https://github.com/
|
|
44
|
-
* Color<sup>[12](https://github.com/
|
|
45
|
-
* Oil Diffusers<sup>[13](https://github.com/
|
|
46
|
-
* Outlets<sup>[14](https://github.com/
|
|
47
|
-
* Switches<sup>[15](https://github.com/
|
|
41
|
+
* On/Off<sup>[10](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md)</sup>
|
|
42
|
+
* Brightness<sup>[11](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md#tunable-white-light-bulbs)</sup>
|
|
43
|
+
* Color<sup>[12](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md#white-and-color-light-bulbs)</sup> (Hue, Saturation, Adaptive Lighting)
|
|
44
|
+
* Oil Diffusers<sup>[13](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md)</sup>
|
|
45
|
+
* Outlets<sup>[14](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md#outlets)</sup>
|
|
46
|
+
* Switches<sup>[15](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md)</sup>
|
|
48
47
|
|
|
49
48
|
Note: Motion, and other sensor types don't behave well with responce requests, so they will not be added.
|
|
50
49
|
|
package/bin/cli-find.js
CHANGED
|
@@ -200,7 +200,7 @@ proxy.listen({port: program.port, sslCaDir: ROOT}, err => {
|
|
|
200
200
|
|
|
201
201
|
QRCode.toString(`http://${address}:${port}/cert`, {type: 'terminal'}, function(err, url) {
|
|
202
202
|
console.log(url);
|
|
203
|
-
console.log('\nFollow the instructions on https://github.com/
|
|
203
|
+
console.log('\nFollow the instructions on https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Get-Local-Keys-for-Your-Devices.md');
|
|
204
204
|
console.log(`Proxy IP: ${address}`);
|
|
205
205
|
console.log(`Proxy Port: ${port}\n\n`);
|
|
206
206
|
})
|
package/config-example.MD
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
## Configurations
|
|
9
|
-
The configuration parameters to enable your devices would need to be added to `platforms` section of the Homebridge configuration file. Examples of device configs can be found on the [Supported Device Types](https://github.com/
|
|
9
|
+
The configuration parameters to enable your devices would need to be added to `platforms` section of the Homebridge configuration file. Examples of device configs can be found on the [Supported Device Types](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md) page. Check out the [Common Problems](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Common-Problems.md) page for solutions or raise an issue if you face problems.
|
|
10
10
|
```json5
|
|
11
11
|
{
|
|
12
12
|
...
|
|
@@ -15,6 +15,7 @@ The configuration parameters to enable your devices would need to be added to `p
|
|
|
15
15
|
/* The block you need to enable this plugin */
|
|
16
16
|
{
|
|
17
17
|
"platform": "TuyaLan",
|
|
18
|
+
"discoverTimeout": 60000,
|
|
18
19
|
"devices": [
|
|
19
20
|
/* The block you need for each device */
|
|
20
21
|
{
|
|
@@ -33,11 +34,14 @@ The configuration parameters to enable your devices would need to be added to `p
|
|
|
33
34
|
...
|
|
34
35
|
}
|
|
35
36
|
```
|
|
36
|
-
####
|
|
37
|
+
#### Device parameters
|
|
37
38
|
* `name` (required) is anything you'd like to use to identify this device. You can always change the name from within the Home app.
|
|
38
|
-
* `type` (required) is a case-insensitive identifier that lets the plugin know how to handle your device. Find your device `type` on the [Supported Device Type List](https://github.com/
|
|
39
|
+
* `type` (required) is a case-insensitive identifier that lets the plugin know how to handle your device. Find your device `type` on the [Supported Device Type List](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Supported-Device-Types.md) page.
|
|
39
40
|
* `manufacturer` and `model` are anything you like; the purpose of them is to help you identify the device.
|
|
40
41
|
* `id` (required) and `key` (required) are parameters for your device. If you don't have them, follow the steps found on the [Setup Instructions](https://github.com/iRayanKgan/homebridge-tuya/wiki/Setup-Instructions) page.
|
|
41
|
-
* `ip` needs to be added **_only_** if you face discovery issues. See [Common Problems](https://github.com/
|
|
42
|
+
* `ip` needs to be added **_only_** if you face discovery issues. See [Common Problems](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Common-Problems.md) for more details.
|
|
42
43
|
|
|
43
44
|
> To find out which `id` belongs to which device, open the Tuya Smart app and check the `Device Information` by tapping the configuration icon of your devices; it is almost always a tiny icon on the top-right.
|
|
45
|
+
|
|
46
|
+
#### Other parameters
|
|
47
|
+
* `discoverTimeout` (optional) is the time period (millisecond) the plugin should spend for device auto-discovery. If unspecified, the default value is 60000.
|
package/config.schema.json
CHANGED
|
@@ -2,11 +2,19 @@
|
|
|
2
2
|
"pluginAlias": "TuyaLan",
|
|
3
3
|
"pluginType": "platform",
|
|
4
4
|
"singular": true,
|
|
5
|
-
"headerDisplay": "<p align='center'><img height='60px' src='https://user-images.githubusercontent.com/3979615/78354049-dc7ff780-75f6-11ea-8026-2f8bf81d8331.png'></p>\n\nBefore using the Tuya plugin you need to discover your devices by following [these instructions](https://github.com/
|
|
5
|
+
"headerDisplay": "<p align='center'><img height='60px' src='https://user-images.githubusercontent.com/3979615/78354049-dc7ff780-75f6-11ea-8026-2f8bf81d8331.png'></p>\n\nBefore using the Tuya plugin you need to discover your devices by following [these instructions](https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Get-Local-Keys-for-Your-Devices.md).\n\n",
|
|
6
6
|
"footerDisplay": "",
|
|
7
7
|
"schema": {
|
|
8
8
|
"type": "object",
|
|
9
9
|
"properties": {
|
|
10
|
+
"discoverTimeout": {
|
|
11
|
+
"title": "Device IP auto-discovery timeout",
|
|
12
|
+
"type": "integer",
|
|
13
|
+
"minimum": 0,
|
|
14
|
+
"placeholder": "Timeout (millisecond) for device IP address discovery",
|
|
15
|
+
"default": 60000,
|
|
16
|
+
"required": false
|
|
17
|
+
},
|
|
10
18
|
"devices": {
|
|
11
19
|
"type": "array",
|
|
12
20
|
"orderable": false,
|
|
@@ -133,7 +141,7 @@
|
|
|
133
141
|
"id": {
|
|
134
142
|
"type": "string",
|
|
135
143
|
"title": "Tuya ID",
|
|
136
|
-
"description": "If you don't have the Tuya ID or Key, follow the steps found on the <a href='https://github.com/
|
|
144
|
+
"description": "If you don't have the Tuya ID or Key, follow the steps found on the <a href='https://github.com/adrianjagielak/homebridge-tuya-plus/blob/main/wiki/Get-Local-Keys-for-Your-Devices.md' target='_blank'>Setup Instructions</a> page.",
|
|
137
145
|
"required": true,
|
|
138
146
|
"condition": {
|
|
139
147
|
"functionBody": "return model.devices && model.devices[arrayIndices].type !== 'null';"
|
|
@@ -475,9 +483,9 @@
|
|
|
475
483
|
"functionBody": "return model.devices && model.devices[arrayIndices] && ['SimpleHeater'].includes(model.devices[arrayIndices].type);"
|
|
476
484
|
}
|
|
477
485
|
},
|
|
478
|
-
"
|
|
486
|
+
"temperatureOffset": {
|
|
479
487
|
"type": "integer",
|
|
480
|
-
"placeholder": "
|
|
488
|
+
"placeholder": "0",
|
|
481
489
|
"condition": {
|
|
482
490
|
"functionBody": "return model.devices && model.devices[arrayIndices] && ['SimpleHeater'].includes(model.devices[arrayIndices].type);"
|
|
483
491
|
}
|
package/index.js
CHANGED
|
@@ -26,6 +26,7 @@ const DoorbellAccessory = require('./lib/DoorbellAccessory');
|
|
|
26
26
|
|
|
27
27
|
const PLUGIN_NAME = 'homebridge-tuya';
|
|
28
28
|
const PLATFORM_NAME = 'TuyaLan';
|
|
29
|
+
const DEFAULT_DISCOVER_TIMEOUT = 60000;
|
|
29
30
|
|
|
30
31
|
const CLASS_DEF = {
|
|
31
32
|
outlet: OutletAccessory,
|
|
@@ -154,7 +155,7 @@ class TuyaLan {
|
|
|
154
155
|
this.log.warn('Failed to discover %s (%s) in time but will keep looking.', devices[deviceId].name, deviceId);
|
|
155
156
|
}
|
|
156
157
|
});
|
|
157
|
-
},
|
|
158
|
+
}, this.config.discoverTimeout ?? DEFAULT_DISCOVER_TIMEOUT);
|
|
158
159
|
}
|
|
159
160
|
|
|
160
161
|
registerPlatformAccessories(platformAccessories) {
|
|
@@ -55,7 +55,7 @@ class AirConditionerAccessory extends BaseAccessory {
|
|
|
55
55
|
const {Service, Characteristic} = this.hap;
|
|
56
56
|
const service = this.accessory.getService(Service.HeaterCooler);
|
|
57
57
|
this._checkServiceName(service, this.device.context.name);
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
this.dpActive = this._getCustomDP(this.device.context.dpActive) || '1';
|
|
60
60
|
this.dpThreshold = this._getCustomDP(this.device.context.dpThreshold) || '2';
|
|
61
61
|
this.dpCurrentTemperature = this._getCustomDP(this.device.context.dpCurrentTemperature) || '3';
|
|
@@ -64,7 +64,7 @@ class AirConditionerAccessory extends BaseAccessory {
|
|
|
64
64
|
this.dpChildLock = this._getCustomDP(this.device.context.dpChildLock) || '6';
|
|
65
65
|
this.dpTempUnits = this._getCustomDP(this.device.context.dpTempUnits) || '19';
|
|
66
66
|
this.dpSwingMode = this._getCustomDP(this.device.context.dpSwingMode) || '104';
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
const characteristicActive = service.getCharacteristic(Characteristic.Active)
|
|
69
69
|
.updateValue(this._getActive(this.dpActive))
|
|
70
70
|
.on('get', this.getActive.bind(this))
|
|
@@ -89,8 +89,8 @@ class AirConditionerAccessory extends BaseAccessory {
|
|
|
89
89
|
.on('set', this.setTargetHeaterCoolerState.bind(this));
|
|
90
90
|
|
|
91
91
|
const characteristicCurrentTemperature = service.getCharacteristic(Characteristic.CurrentTemperature)
|
|
92
|
-
.updateValue(dps[this.
|
|
93
|
-
.on('get', this.getState.bind(this, this.
|
|
92
|
+
.updateValue(dps[this.dpCurrentTemperature])
|
|
93
|
+
.on('get', this.getState.bind(this, this.dpCurrentTemperature));
|
|
94
94
|
|
|
95
95
|
let characteristicSwingMode;
|
|
96
96
|
if (!this.device.context.noSwing) {
|
package/lib/BaseAccessory.js
CHANGED
|
@@ -154,18 +154,16 @@ class BaseAccessory {
|
|
|
154
154
|
const min = this.device.context.minWhiteColor || 140;
|
|
155
155
|
const max = this.device.context.maxWhiteColor || 400;
|
|
156
156
|
const scale = this.device.context.scaleWhiteColor || 255;
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
return Math.min(scale, Math.max(0, convertedValue));
|
|
157
|
+
const result = Math.round(Math.max(Math.min(scale-(scale-1)/(max-min)*(value-min),scale),1));
|
|
158
|
+
return result;
|
|
160
159
|
}
|
|
161
160
|
|
|
162
161
|
convertColorTemperatureFromTuyaToHomeKit(value) {
|
|
163
162
|
const min = this.device.context.minWhiteColor || 140;
|
|
164
163
|
const max = this.device.context.maxWhiteColor || 400;
|
|
165
164
|
const scale = this.device.context.scaleWhiteColor || 255;
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
return Math.min(600, Math.max(71, convertedValue));
|
|
165
|
+
const result = Math.round(Math.max(Math.min((scale-value)/((scale-1)/(max-min))+min,max),min));
|
|
166
|
+
return Math.min(600, Math.max(71, result));
|
|
169
167
|
}
|
|
170
168
|
|
|
171
169
|
convertColorFromHomeKitToTuya(value, dpValue) {
|
|
@@ -58,10 +58,10 @@ class RGBTWLightAccessory extends BaseAccessory {
|
|
|
58
58
|
|
|
59
59
|
const characteristicColorTemperature = service.getCharacteristic(Characteristic.ColorTemperature)
|
|
60
60
|
.setProps({
|
|
61
|
-
minValue:
|
|
62
|
-
maxValue:
|
|
61
|
+
minValue: this.device.context.minWhiteColor,
|
|
62
|
+
maxValue: this.device.context.maxWhiteColor
|
|
63
63
|
})
|
|
64
|
-
.updateValue(dps[this.dpMode] === this.cmdWhite ? this.convertColorTemperatureFromTuyaToHomeKit(dps[this.dpColorTemperature]) :
|
|
64
|
+
.updateValue(dps[this.dpMode] === this.cmdWhite ? this.convertColorTemperatureFromTuyaToHomeKit(dps[this.dpColorTemperature]) : this.device.context.minWhiteColor)
|
|
65
65
|
.on('get', this.getColorTemperature.bind(this))
|
|
66
66
|
.on('set', this.setColorTemperature.bind(this));
|
|
67
67
|
|
|
@@ -126,12 +126,12 @@ class RGBTWLightAccessory extends BaseAccessory {
|
|
|
126
126
|
if (oldColor.b !== newColor.b) characteristicBrightness.updateValue(newColor.b);
|
|
127
127
|
if (oldColor.h !== newColor.h) characteristicHue.updateValue(newColor.h);
|
|
128
128
|
|
|
129
|
-
if (oldColor.s !== newColor.s) characteristicSaturation.updateValue(newColor.
|
|
129
|
+
if (oldColor.s !== newColor.s) characteristicSaturation.updateValue(newColor.s);
|
|
130
130
|
|
|
131
|
-
if (characteristicColorTemperature.value !==
|
|
131
|
+
if (characteristicColorTemperature.value !== this.device.context.minWhiteColor) characteristicColorTemperature.updateValue(this.device.context.minWhiteColor);
|
|
132
132
|
|
|
133
133
|
} else if (changes[this.dpMode]) {
|
|
134
|
-
if (characteristicColorTemperature.value !==
|
|
134
|
+
if (characteristicColorTemperature.value !== this.device.context.minWhiteColor) characteristicColorTemperature.updateValue(this.device.context.minWhiteColor);
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
});
|
|
@@ -148,7 +148,7 @@ class RGBTWLightAccessory extends BaseAccessory {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
getColorTemperature(callback) {
|
|
151
|
-
if (this.device.state[this.dpMode] !== this.cmdWhite) return callback(null,
|
|
151
|
+
if (this.device.state[this.dpMode] !== this.cmdWhite) return callback(null, this.device.context.minWhiteColor);
|
|
152
152
|
callback(null, this.convertColorTemperatureFromTuyaToHomeKit(this.device.state[this.dpColorTemperature]));
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -160,12 +160,20 @@ class RGBTWLightAccessory extends BaseAccessory {
|
|
|
160
160
|
this.characteristicHue.updateValue(newColor.h);
|
|
161
161
|
this.characteristicSaturation.updateValue(newColor.s);
|
|
162
162
|
|
|
163
|
-
this.
|
|
163
|
+
if (this.device.state[this.dpMode] !== this.cmdWhite) {
|
|
164
|
+
this.setMultiState({[this.dpMode]: this.cmdWhite, [this.dpColorTemperature]: this.convertColorTemperatureFromHomeKitToTuya(value), [this.dpBrightness]: this.convertBrightnessFromHomeKitToTuya(this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).b)}, callback);
|
|
165
|
+
} else {
|
|
166
|
+
this.setMultiState({[this.dpMode]: this.cmdWhite, [this.dpColorTemperature]: this.convertColorTemperatureFromHomeKitToTuya(value)}, callback);
|
|
167
|
+
}
|
|
164
168
|
}
|
|
165
169
|
|
|
166
170
|
getHue(callback) {
|
|
167
|
-
if (this.device.state[this.dpMode] === this.cmdWhite)
|
|
168
|
-
|
|
171
|
+
if (this.device.state[this.dpMode] === this.cmdWhite) {
|
|
172
|
+
const prepareHue = this.convertHomeKitColorTemperatureToHomeKitColor(this.convertColorTemperatureFromTuyaToHomeKit(this.device.state[this.dpColorTemperature]));
|
|
173
|
+
callback(null, prepareHue.h);
|
|
174
|
+
} else {
|
|
175
|
+
callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).h);
|
|
176
|
+
}
|
|
169
177
|
}
|
|
170
178
|
|
|
171
179
|
setHue(value, callback) {
|
|
@@ -173,8 +181,12 @@ class RGBTWLightAccessory extends BaseAccessory {
|
|
|
173
181
|
}
|
|
174
182
|
|
|
175
183
|
getSaturation(callback) {
|
|
176
|
-
if (this.device.state[this.dpMode] === this.cmdWhite)
|
|
177
|
-
|
|
184
|
+
if (this.device.state[this.dpMode] === this.cmdWhite) {
|
|
185
|
+
const prepareSaturation = this.convertHomeKitColorTemperatureToHomeKitColor(this.convertColorTemperatureFromTuyaToHomeKit(this.device.state[this.dpColorTemperature]));
|
|
186
|
+
callback(null, prepareSaturation.s);
|
|
187
|
+
} else {
|
|
188
|
+
callback(null, this.convertColorFromTuyaToHomeKit(this.device.state[this.dpColor]).s);
|
|
189
|
+
}
|
|
178
190
|
}
|
|
179
191
|
|
|
180
192
|
setSaturation(value, callback) {
|
|
@@ -208,10 +220,13 @@ class RGBTWLightAccessory extends BaseAccessory {
|
|
|
208
220
|
} catch (ex) {}
|
|
209
221
|
next();
|
|
210
222
|
}, () => {
|
|
211
|
-
this.characteristicColorTemperature.updateValue(
|
|
223
|
+
this.characteristicColorTemperature.updateValue(this.device.context.minWhiteColor);
|
|
212
224
|
});
|
|
213
225
|
};
|
|
214
226
|
|
|
227
|
+
if (this.device.state[this.dpMode] !== this.cmdColor)
|
|
228
|
+
this._pendingHueSaturation.props.b = this.convertBrightnessFromTuyaToHomeKit(this.device.state[this.dpBrightness]);
|
|
229
|
+
|
|
215
230
|
const isSham = this._pendingHueSaturation.props.h === 0 && this._pendingHueSaturation.props.s === 0;
|
|
216
231
|
const newValue = this.convertColorFromHomeKitToTuya(this._pendingHueSaturation.props);
|
|
217
232
|
this._pendingHueSaturation = null;
|
|
@@ -7,6 +7,7 @@ class SimpleHeaterAccessory extends BaseAccessory {
|
|
|
7
7
|
|
|
8
8
|
constructor(...props) {
|
|
9
9
|
super(...props);
|
|
10
|
+
this.currentHeaterCoolerState = 0;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
_registerPlatformAccessory() {
|
|
@@ -27,14 +28,14 @@ class SimpleHeaterAccessory extends BaseAccessory {
|
|
|
27
28
|
this.dpCurrentTemperature = this._getCustomDP(this.device.context.dpCurrentTemperature) || '3';
|
|
28
29
|
this.temperatureDivisor = parseInt(this.device.context.temperatureDivisor) || 1;
|
|
29
30
|
this.thresholdTemperatureDivisor = parseInt(this.device.context.thresholdTemperatureDivisor) || 1;
|
|
30
|
-
this.
|
|
31
|
+
this.temperatureOffset = parseInt(this.device.context.temperatureOffset) || 0;
|
|
31
32
|
|
|
32
33
|
const characteristicActive = service.getCharacteristic(Characteristic.Active)
|
|
33
34
|
.updateValue(this._getActive(dps[this.dpActive]))
|
|
34
35
|
.on('get', this.getActive.bind(this))
|
|
35
36
|
.on('set', this.setActive.bind(this));
|
|
36
37
|
|
|
37
|
-
service.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
|
|
38
|
+
const characteristicCurrentHeaterCoolerState = service.getCharacteristic(Characteristic.CurrentHeaterCoolerState)
|
|
38
39
|
.updateValue(this._getCurrentHeaterCoolerState(dps))
|
|
39
40
|
.on('get', this.getCurrentHeaterCoolerState.bind(this));
|
|
40
41
|
|
|
@@ -75,11 +76,12 @@ class SimpleHeaterAccessory extends BaseAccessory {
|
|
|
75
76
|
|
|
76
77
|
if (changes.hasOwnProperty(this.dpDesiredTemperature)) {
|
|
77
78
|
if (characteristicHeatingThresholdTemperature.value !== changes[this.dpDesiredTemperature])
|
|
78
|
-
characteristicHeatingThresholdTemperature.updateValue(changes[this.dpDesiredTemperature
|
|
79
|
+
characteristicHeatingThresholdTemperature.updateValue(this._getDividedState(changes[this.dpDesiredTemperature], this.thresholdTemperatureDivisor));
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
if (changes.hasOwnProperty(this.dpCurrentTemperature) && characteristicCurrentTemperature.value !== changes[this.dpCurrentTemperature]) characteristicCurrentTemperature.updateValue(this._getDividedState(changes[this.dpCurrentTemperature], this.temperatureDivisor));
|
|
82
83
|
|
|
84
|
+
characteristicCurrentHeaterCoolerState.updateValue(this._getCurrentHeaterCoolerState(state));
|
|
83
85
|
this.log.info('SimpleHeater changed: ' + JSON.stringify(state));
|
|
84
86
|
});
|
|
85
87
|
}
|
|
@@ -113,16 +115,22 @@ class SimpleHeaterAccessory extends BaseAccessory {
|
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
getCurrentHeaterCoolerState(callback) {
|
|
116
|
-
|
|
117
|
-
if (err) return callback(err);
|
|
118
|
-
|
|
119
|
-
callback(null, this._getCurrentHeaterCoolerState(dps));
|
|
120
|
-
});
|
|
118
|
+
callback(null, this.currentHeaterCoolerState);
|
|
121
119
|
}
|
|
122
120
|
|
|
123
121
|
_getCurrentHeaterCoolerState(dps) {
|
|
124
122
|
const {Characteristic} = this.hap;
|
|
125
|
-
|
|
123
|
+
if (dps[this.dpActive]) {
|
|
124
|
+
if (dps[this.dpCurrentTemperature] < dps[this.dpDesiredTemperature]) {
|
|
125
|
+
this.currentHeaterCoolerState = Characteristic.CurrentHeaterCoolerState.HEATING;
|
|
126
|
+
}
|
|
127
|
+
if (dps[this.dpCurrentTemperature] > dps[this.dpDesiredTemperature]) {
|
|
128
|
+
this.currentHeaterCoolerState = Characteristic.CurrentHeaterCoolerState.IDLE;
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
this.currentHeaterCoolerState = Characteristic.CurrentHeaterCoolerState.INACTIVE;
|
|
132
|
+
};
|
|
133
|
+
return this.currentHeaterCoolerState;
|
|
126
134
|
}
|
|
127
135
|
|
|
128
136
|
getTargetHeaterCoolerState(callback) {
|
|
@@ -139,7 +147,7 @@ class SimpleHeaterAccessory extends BaseAccessory {
|
|
|
139
147
|
}
|
|
140
148
|
|
|
141
149
|
setTargetThresholdTemperature(value, callback) {
|
|
142
|
-
this.setState(this.dpDesiredTemperature, value * this.thresholdTemperatureDivisor, err => {
|
|
150
|
+
this.setState(this.dpDesiredTemperature, (value - this.temperatureOffset) * this.thresholdTemperatureDivisor, err => {
|
|
143
151
|
if (err) return callback(err);
|
|
144
152
|
|
|
145
153
|
if (this.characteristicHeatingThresholdTemperature) {
|
|
@@ -149,6 +157,10 @@ class SimpleHeaterAccessory extends BaseAccessory {
|
|
|
149
157
|
callback();
|
|
150
158
|
});
|
|
151
159
|
}
|
|
160
|
+
|
|
161
|
+
_getDividedState(dp, divisor) {
|
|
162
|
+
return ((parseFloat(dp) / divisor) + this.temperatureOffset) || 0;
|
|
163
|
+
}
|
|
152
164
|
}
|
|
153
165
|
|
|
154
166
|
module.exports = SimpleHeaterAccessory;
|
package/lib/TWLightAccessory.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const BaseAccessory = require('./BaseAccessory');
|
|
2
2
|
const async = require('async');
|
|
3
3
|
|
|
4
|
+
const DEFAULT_MIN_WHITE_COLOR = 0;
|
|
5
|
+
const DEFAULT_MAX_WHITE_COLOR = 600;
|
|
6
|
+
|
|
4
7
|
class TWLightAccessory extends BaseAccessory {
|
|
5
8
|
static getCategory(Categories) {
|
|
6
9
|
return Categories.LIGHTBULB;
|
|
@@ -39,8 +42,8 @@ class TWLightAccessory extends BaseAccessory {
|
|
|
39
42
|
|
|
40
43
|
const characteristicColorTemperature = service.getCharacteristic(Characteristic.ColorTemperature)
|
|
41
44
|
.setProps({
|
|
42
|
-
minValue:
|
|
43
|
-
maxValue:
|
|
45
|
+
minValue: this.device.context.minWhiteColor ?? DEFAULT_MIN_WHITE_COLOR,
|
|
46
|
+
maxValue: this.device.context.maxWhiteColor ?? DEFAULT_MAX_WHITE_COLOR
|
|
44
47
|
})
|
|
45
48
|
.updateValue(this.convertColorTemperatureFromTuyaToHomeKit(dps[this.dpColorTemperature]))
|
|
46
49
|
.on('get', this.getColorTemperature.bind(this))
|
|
@@ -88,4 +91,4 @@ class TWLightAccessory extends BaseAccessory {
|
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
module.exports = TWLightAccessory;
|
|
94
|
+
module.exports = TWLightAccessory;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-tuya-plus",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "A community-maintained Homebridge plugin for controlling Tuya devices locally over LAN. Includes new features, fixes, and updated device support.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Common Problems
|
|
2
|
+
> Find answers to previously answered questions, if this guide doesn't help you, please file a new issue.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## Error getting keys with HOOBS/Config-Ui-X
|
|
6
|
+
|
|
7
|
+
HOOBS and Config-Ui-X both utilise port 8080. If you are not using port 8080, your network may have a device hosting something on that port. To fix this issue, change the discovery port. [First appeared](https://github.com/iRayanKhan/homebridge-tuya-platform/issues/4).
|
|
8
|
+
|
|
9
|
+
## Device only partially works.
|
|
10
|
+
|
|
11
|
+
Your device may have different data points/commands than the plugin is defaulted to handle. To fix this issue, you currently have to manually edit the device type file for your specific device. Version 2.0 (Not in Beta yet), will allow you to fix this issue via the config.json file. [First appeared](https://github.com/iRayanKhan/homebridge-tuya-platform/issues/11)
|
|
12
|
+
|
|
13
|
+
## Can't get device keys.
|
|
14
|
+
|
|
15
|
+
Tuya has updated their SDK to prevent the MITM method used to extract deviceID and keys. A guide is being compiled to fix this issue. Alternatively a website is being updated to add support for the old Tuya apps, to keep this method going. [First appeared](https://github.com/iRayanKhan/homebridge-tuya-platform/issues/13)
|
|
16
|
+
|
|
17
|
+
## How to install the beta?
|
|
18
|
+
|
|
19
|
+
Currently there is no beta release that you can use via NPM. You can visit the RC branch, and git clone it from there. If you do not know how to Git Clone, a guide is being compiled. A new beta will be published soon, and this page will be constantly updated to reflect a new beta update, with instructions. [First appeared](No-ref-yet.com/)
|
|
20
|
+
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
## Device Mapping
|
|
2
|
+
|
|
3
|
+
Your device may have different command to interact with this. This (W.I.P) guide will provide a detailed example for each device of all optional parameters per device, and an example of an implementation. To get your devices details, please refer to the schema of your device.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
To get the local keys for your devices, you'll need an account on Tuya's IoT site. Don't be overwhelmed, there's a lot on that site but it's pretty easy to get what you need out of it. The free trial will give you enough access to the Tuya API to get the information you need, on up to 50 devices.
|
|
2
|
+
|
|
3
|
+
## 1 - Tuya Smart App
|
|
4
|
+
As a prerequisite, add all of your devices to the Tuya Smart app ([iOS](https://apps.apple.com/au/app/tuya-smart/id1034649547) / [Android](https://play.google.com/store/apps/details?id=com.tuya.smart&hl=en_AU&gl=US&pli=1))
|
|
5
|
+
|
|
6
|
+
## 2 - Sign up for an IoT account
|
|
7
|
+
Go to https://iot.tuya.com and click Sign Up
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
* Fill in your information
|
|
12
|
+
* Make up a company name if you need to
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
* Check Agree to Terms
|
|
17
|
+
* Click Agree
|
|
18
|
+
* You'll be emailed a code, enter it
|
|
19
|
+
|
|
20
|
+
## 3 - Sign in at iot.tuya.com
|
|
21
|
+
|
|
22
|
+
## 4 - Create a cloud project
|
|
23
|
+
* Click through the intro
|
|
24
|
+
* On the sidebar click cloud, then projects
|
|
25
|
+
* Click Free Trial under TRIAL EDITION
|
|
26
|
+
|
|
27
|
+

|
|
28
|
+
|
|
29
|
+
* Click Buy now in the new tab
|
|
30
|
+
|
|
31
|
+

|
|
32
|
+
|
|
33
|
+
* Close the Tuya Value Added Service tab/popup
|
|
34
|
+
* In the Tuya IoT Platform tab, click Subscribed to be taken back to Cloud -> Projects
|
|
35
|
+
* Click create
|
|
36
|
+
|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
* Make sure you pick smart home PAAS and the correct region, this affects whether you will be able to access your devices in the following steps. Click create
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
* Click Authorize for the recommended APIs
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
## 5 - Link devices registered in Tuya app to the IoT site
|
|
48
|
+
* From your project, click the link devices tab, then Link devices by App Account, then Add App Account
|
|
49
|
+
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
* In the Tuya Smart app, click me at the bottom, then the scan button, then scan your QR code
|
|
53
|
+
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
* Confirm the sign in
|
|
57
|
+
|
|
58
|
+
## 6 - Get the keys for your devices
|
|
59
|
+
* Go to the device list tab
|
|
60
|
+
* Copy the device ID for your device
|
|
61
|
+
|
|
62
|
+

|
|
63
|
+
|
|
64
|
+
* In the sidebar, hover over "Cloud" and click on "API Explorer"
|
|
65
|
+
|
|
66
|
+

|
|
67
|
+
|
|
68
|
+
* In the sidebar, search for "get device information" endpoint and click on the highlighted option. (It should be under "General Devices management" section. Note: there is also another endpoint called "Get _the_ device information" which will not work.)
|
|
69
|
+
|
|
70
|
+
* In the "device_id" text field, paste in the device ID you copied and click "Submit Request"
|
|
71
|
+
|
|
72
|
+
* In the "Response" section, there should be a property called `local_key` which is your local key.
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
|
|
76
|
+
## 7 - Video Tutorial
|
|
77
|
+
* [YouTube](https://youtu.be/FpY-xsY-pZ8)
|