Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add device override config. #119

Merged
merged 12 commits into from
Dec 12, 2022
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ assignees: ''

---

- [ ] I've read the [Readme - Troubleshooting](https://github.com/0x5e/homebridge-tuya-platform#troubleshooting) section.
- [ ] I've read the [Readme - FAQ](https://github.com/0x5e/homebridge-tuya-platform#faq) and [Readme - Troubleshooting](https://github.com/0x5e/homebridge-tuya-platform#troubleshooting) section.

**Describe the bug**
A clear and concise description of what the bug is.
Expand Down
131 changes: 131 additions & 0 deletions ADVANCED_OPTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Advanced Options

**During the beta version, the options are unstable, may get changed during updates.**

- `options.deviceOverrides` - **optional**: An array of device overriding config objects.
- `options.deviceOverrides[].id` - **required**: Device ID, Product ID, Scene ID, or `global`.
<!--
- `options.deviceOverrides[].accessoryCategory` - **optional**: Accessory Category ID. Overriding this property can change accessory's icon. See: [Homebridge Plugin Documentation > Categories](https://developers.homebridge.io/#/categories)
-->
- `options.deviceOverrides[].category` - **optional**: Device category code. See [SUPPORTED_DEVICES.md](./SUPPORTED_DEVICES.md). Also you can use `hidden` to hide device, product, or scene. **⚠️Overriding this property may leads to unexpected behaviors and exceptions. Please remove accessory cache after change this.**

- `options.deviceOverrides[].schema` - **optional**: An array of schema overriding config objects. When your device have non-standard schemas, this is used for transform them.
- `options.deviceOverrides[].schema[].oldCode` - **required**: Original Schema code.
- `options.deviceOverrides[].schema[].code` - **required**: New Schema code.
- `options.deviceOverrides[].schema[].type` - **optional**: New schema type. One of the `Boolean`, `Integer`, `Enum`, `String`, `Json`, `Raw`.
- `options.deviceOverrides[].schema[].property` - **optional**: New schema property object. For `Integer` type, the object should contains `min`, `max`, `scale`, `step`; For `Enum` type, the object should contains `range`. For detail information, please see `TuyaDeviceSchemaProperty` in [TuyaDevice.ts](./src/device/TuyaDevice.ts).
- `options.deviceOverrides[].schema[].onGet` - **optional**: An one-line JavaScript code convert old value to new value. The function is called with one argument: `value`.
- `options.deviceOverrides[].schema[].onSet` - **optional**: An one-line JavaScript code convert new value to old value. The function is called with one argument: `value`.

## Examples

### Hide device

```js
{
"options": {
// ...
"deviceOverrides": [{
"id": "{device_id}",
"category": "hidden"
}]
}
}
```

### Changing schema code

```js
{
"options": {
// ...
"deviceOverrides": [{
"id": "{device_id}",
"schema": [{
"oldCode": "{oldCode}",
"code": "{newCode}",
}]
}]
}
}
```

### Convert from enum schema to boolean schema

If you want to convert a enum schema as a switch, you can do it like this:

```js
{
"options": {
// ...
"deviceOverrides": [{
"id": "{device_id}",
"schema": [{
"oldCode": "{oldCode}",
"code": "{newCode}",
"type": "Boolean",
"onGet": "(value === 'open') ? true : false;",
"onSet": "(value === true) ? 'open' : 'close';",
}]
}]
}
}
```

### Adjust integer schema ranges

Some odd thermostat stores double of the real value to keep the decimal part (0.5°C).

For example: `40` means `20.0°C`, `41` means `20.5°C`. (storeValue = realValue x 2)

But actually, schema already support storing decimal value by setting the `scale` to `1`. The `min`, `max`, `step`, `value` should always be divided by `10^scale`. When `scale = 1`, means they should be divided by `10`.

After transform the value using `onGet` and `onSet`, the `property` should be changed to fit the new ranges.

```js
{
"options": {
// ...
"deviceOverrides": [{
"id": "{device_id}",
"schema": [{
"oldCode": "{oldCode}",
"code": "{newCode}",
"onGet": "(value * 5);",
"onSet": "(value / 5);",
"property": {
"min": 200,
"max": 500,
"scale": 1,
"step": 5,
}
}]
}]
}
}
```

Or if you are not familiar with `scale`, just simply ignore the decimal part is also okay.

```js
{
"options": {
// ...
"deviceOverrides": [{
"id": "{device_id}",
"schema": [{
"oldCode": "{oldCode}",
"code": "{newCode}",
"onGet": "Math.round(value / 2);",
"onSet": "(value * 2);",
"property": {
"min": 20,
"max": 50,
"scale": 0,
"step": 1,
}
}]
}]
}
}
```
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

### Added
- Add scene support. (#118)
- Add `sceneWhitelist` option for whitelisting scenes. (#118)
- Add Wireless Switch support (`wxkg`).
- Add Solar Light support (`tyndj`).
- Add Dehumidifier support (`cs`).
- Add Scene Switch support (`wxkg`).
- Add device overriding config support. "non-standard" devices have possibility to be supported now.


### Changed
- Support Ceiling Fan icon customize and Floor Fan `lock`, `swing` feature. (#131)
Expand Down
60 changes: 48 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Fork version of official Tuya Homebridge plugin. Brings a lot of bug fix and new
- Less API errors.
- Less development costs for new accessory categroies.
- Scene supported.
- Support overriding device config.
- More supported devices.
- [Light] Spotlight (`sxd`)
- [Light] Motion Sensor Light (`gyd`)
Expand Down Expand Up @@ -83,46 +84,81 @@ Before configuration, please goto [Tuya IoT Platform](https://iot.tuya.com)
- Device Status Notification
- IoT Core
- Industry Project Client Service (for "Custom" project)
- **⚠️Extend the API trial period every 6 months here (first-time subscription only give 1 month): [Tuya IoT Platform -> Cloud -> Cloud Services -> IoT Core](https://iot.tuya.com/cloud/products/detail?abilityId=1442730014117204014&id=p1668587814138nv4h3n&abilityAuth=0&tab=1)**
- **⚠️Extend the API trial period every 6 months here (first-time subscription only give 1 month): [Tuya IoT Platform > Cloud > Cloud Services > IoT Core](https://iot.tuya.com/cloud/products/detail?abilityId=1442730014117204014&id=p1668587814138nv4h3n&abilityAuth=0&tab=1)**

#### For "Custom" Project

- `platform` - **required** : Must be 'TuyaPlatform'
- `options.projectType` - **required** : Must be '1'
- `options.endpoint` - **required** : Endpoint URL from [API Reference -> Endpoints](https://developer.tuya.com/en/docs/iot/api-request?id=Ka4a8uuo1j4t4#title-1-Endpoints) table.
- `options.accessId` - **required** : Access ID from [Tuya IoT Platform -> Cloud Develop](https://iot.tuya.com/cloud)
- `options.accessKey` - **required** : Access Secret from [Tuya IoT Platform -> Cloud Develop](https://iot.tuya.com/cloud)
- `options.endpoint` - **required** : Endpoint URL from [API Reference > Endpoints](https://developer.tuya.com/en/docs/iot/api-request?id=Ka4a8uuo1j4t4#title-1-Endpoints) table.
- `options.accessId` - **required** : Access ID from [Tuya IoT Platform > Cloud Develop](https://iot.tuya.com/cloud)
- `options.accessKey` - **required** : Access Secret from [Tuya IoT Platform > Cloud Develop](https://iot.tuya.com/cloud)

#### For "Smart Home" Project

- `platform` - **required** : Must be 'TuyaPlatform'
- `options.projectType` - **required** : Must be '2'
- `options.accessId` - **required** : Access ID from [Tuya IoT Platform -> Cloud Develop](https://iot.tuya.com/cloud)
- `options.accessKey` - **required** : Access Secret from [Tuya IoT Platform -> Cloud Develop](https://iot.tuya.com/cloud)
- `options.accessId` - **required** : Access ID from [Tuya IoT Platform > Cloud Develop](https://iot.tuya.com/cloud)
- `options.accessKey` - **required** : Access Secret from [Tuya IoT Platform > Cloud Develop](https://iot.tuya.com/cloud)
- `options.countryCode` - **required** : Country Code
- `options.username` - **required** : Username
- `options.password` - **required** : Password
- `options.appSchema` - **required** : App schema. 'tuyaSmart' for Tuya Smart App, 'smartlife' for Smart Life App.
- `options.homeWhitelist` - **optional**: An array of integer home ID values to whitelist. If present, only includes devices matching this Home ID value.
- `options.sceneWhitelist` - **optional**: An array of integer scene ID values to whitelist. If present, only includes scene matching this Scene ID value.


#### Advanced options
See [ADVANCED_OPTIONS.md](./ADVANCED_OPTIONS.md)


## Limitations
- **⚠️Don't forget to extend the API trial period every 6 months. Maybe you can set up a reminder in calendar.**
- The app account can't be used in multiple Homebridge/HomeAssistant instance at the same time! Please consider using different app accounts instead.
- The plugin requires the internet access to Tuya Cloud, and the lan protocol is not supported. See [#90](https://github.com/0x5e/homebridge-tuya-platform/issues/90)

## FAQ

#### What is "standard device" and "non-standard device", how to know what my device is?

If your device is working properly, you don't need to know this.

"standard device" means the device's DP Code is matching the code in documentation at: [Tuya IoT Development Platform Documentation > Cloud Development > Standard Instruction Set](https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq).

For example, a Lightbulb must have `switch_led` for power on/off, and optional code
`bright_value`/`bright_value_v2` for brightness, `temp_value`/`temp_value_v2` for color temperature, `work_mode` for change working mode. These code can be found from above documentation.

If your Lightbulb can adjust brightness in Tuya App, but can't do with the plugin, then mostly it's an "non-standard device".


#### Can "non-standard device" be supportd by this plugin?

Yes. The device should be in the support list, then you need do these steps before it's working.
1. Change device's control mode on Tuya Platform.
- Go to "[Tuya Platform Cloud Development](https://iot.tuya.com/cloud/) > Your Project > Devices > All Devices > View Devices by Product".
- Find your device-related product, click the "pencil" icon (Change Control Instruction Mode).
- <img width="500" alt="image" src="https://user-images.githubusercontent.com/5144674/202967707-8b934e05-36d6-4b42-bb7b-87e5b24474c4.png">
- The "Table of Instructions" shows the cloud mapping, you can know which DP Codes of your device is missing, you need to manually map them later.
- <img width="500" alt="image" src="https://user-images.githubusercontent.com/5144674/202967528-4838f9a1-0547-4102-afbb-180dc9b198b1.png">
- Select "DP Instruction" and save.
2. Config the schema with [ADVANCED_OPTIONS.md](./ADVANCED_OPTIONS.md).


#### Local support
See [#90](https://github.com/0x5e/homebridge-tuya-platform/issues/90).

Although the plugin didn't implemented tuya local protocol now, it still remains possibility in the future.


## Troubleshooting

If your device is in the support list, but not working properly, meanwhile, the same feature works well in Tuya App, please complete the following steps before submit the issue.
If your device is not supported, please complete the following steps to collecting the data.

#### 1. Get Device Information

After successful launching Homebridge, the device info list will be saved inside Homebridge's persist path.
You can get the file path from homebridge log:
```
[2022/11/3 18:37:43] [TuyaPlatform] Device list saved at ~/.homebridge/persist/TuyaDeviceList.{uid}.json
[2022/11/3 18:37:43] [TuyaPlatform] Device list saved at /path/to/TuyaDeviceList.{uid}.json
```

**⚠️Please remove the sensitive data such as `ip`, `lon`, `lat`, `local_key`, `uid` before submit the file.**
Expand Down Expand Up @@ -161,14 +197,14 @@ message = {
}
```

If you can't get any mqtt logs when controlling the device, mostly means that your device is a "non-standard device". You need to change device control mode into "DP Instruction" mode. See [#111](https://github.com/0x5e/homebridge-tuya-platform/issues/111).
If you can't get any mqtt logs when controlling the device, mostly means that your device is a "non-standard device".

If you can get mqtt logs, please submit the issue with device info json and logs.
With the device info json and mqtt logs, please submit the issue to help us supporting new device category.


## Contributing

Please see https://github.com/homebridge/homebridge-plugin-template
Please see https://github.com/homebridge/homebridge-plugin-template for setup development environment.

PRs and issues are welcome.

Expand Down
97 changes: 89 additions & 8 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,97 @@
"functionBody": "return model.options.projectType === '2';"
}
},
"sceneWhitelist": {
"title": "Whitelisted Scene IDs",
"description": "An optional list of Scene IDs to match. If blank, all scenes are matched.",
"deviceOverrides": {
"title": "Device Overriding Configs",
"type": "array",
"items": {
"title": "Scene ID",
"type": "integer"
},
"condition": {
"functionBody": "return model.options.projectType === '2';"
"type": "object",
"properties": {
"id": {
"title": "ID",
"description": "Device ID or Product ID or `global`",
"type": "string",
"required": true
},
"category": {
"title": "Category",
"description": "Category Code or `hidden`",
"type": "string"
},
"schema": {
"title": "Schema Overriding Configs",
"type": "array",
"items": {
"type": "object",
"properties": {
"oldCode": {
"title": "Original Schema Code",
"type": "string",
"required": true
},
"code": {
"title": "New Schema Code",
"type": "string",
"required": true
},
"type": {
"title": "New Schema Type",
"type": "string",
"default": "Boolean",
"oneOf": [{
"title": "Boolean",
"enum": ["Boolean"]
}, {
"title": "Integer",
"enum": ["Integer"]
}, {
"title": "Enum",
"enum": ["Enum"]
}, {
"title": "String",
"enum": ["String"]
}, {
"title": "Json",
"enum": ["Json"]
}, {
"title": "Raw",
"enum": ["Raw"]
}]
},
"property": {
"title": "New Schema Property",
"type": "object",
"properties": {
"min": {
"title": "min",
"type": "integer"
},
"max": {
"title": "max",
"type": "integer"
},
"scale": {
"title": "scale",
"type": "integer"
},
"step": {
"title": "step",
"type": "integer"
},
"range": {
"title": "range",
"type": "array",
"items": {
"title": "value",
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
Expand Down
Loading