16 Commits

Author SHA1 Message Date
Alex M
de14f71616 3.1.5 2024-02-19 21:03:42 +03:00
Alex M
adb59a0d9d Update README.md
Friendly topics
2024-02-19 19:48:39 +03:00
Alex M
f865e259a1 Added friendly topics for the devices behind gateway
You can now use:
tuya/gw1/lv/dps/2/command
instead of tuya/zgw1/2342cd828dfsxckkk/dps/2/command
2024-02-19 19:42:02 +03:00
Alex M
4ea2f0a58f Added friendly topics for the devices behind gateway
You can now use:
tuya/gw1/lv/dps/2/command
instead of tuya/zgw1/2342cd828dfsxckkk/dps/2/command
2024-02-19 19:40:13 +03:00
lehanspb
f3d0d0602e decription for systemd startup script 2023-02-15 16:47:43 +03:00
lehanspb
bb97e731a9 v3.1.4 2023-02-15 13:46:48 +03:00
lehanspb
9a9a314d14 decription for systemd startup script 2023-02-15 13:39:38 +03:00
lehanspb
9080a41d9a DPS Topics for devices behind Tuya Gateway 2023-02-15 13:30:18 +03:00
lehanspb
f6bd28c41a Description for MQTT DPS topics for subdevices (cid) behind Tuya Gateway 2023-02-15 12:37:46 +03:00
lehanspb
1d1ab0d62a Description for MQTT DPS topics for subdevices (cid) behind Tuya Gateway 2023-02-15 12:36:25 +03:00
lehanspb
a170287e9e OpenHAB 3.x exmples 2023-02-15 12:21:22 +03:00
lehanspb
47734e03d0 Description for MQTT DPS topics for subdevices (cid) behind Tuya Gateway 2023-02-15 12:16:10 +03:00
lehanspb
eb800133a0 Some comments 2023-02-15 10:37:22 +03:00
lehanspb
6aded16979 Added cid support and dp-refresh function 2023-02-15 10:34:17 +03:00
lehanspb
7cc3d1d5a6 Change packege.json and requirements 2023-02-15 10:22:14 +03:00
Alex M
59d1131db5 Update README.md 2023-02-13 17:04:58 +03:00
6 changed files with 397 additions and 154 deletions

View File

@@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [3.1.5]
### Added
- Added support of friendly names for the subDevices behind gateway (processDpsKeyWcidNameCommand)
### Changed
- Functions publishTopics and publishDpsTopics now can publish subDevice's friendly name to MQTT
## [3.1.0]
Forked from https://github.com/TheAgentK/tuya-mqtt
### Added
- Added support for Zigdee subdevices for Tuya Wireless Gateway
- Added new dp-refresh funtion according to tuyapi documentation
- Command and state topics for DPS keys for subdevices
### Changed
- Updated some libraries to latest version
## [3.0.0] ## [3.0.0]
The 3.0.0 release is a major refactor of the project with significant changes from previous version. Only major additions and changes are listed below. The 3.0.0 release is a major refactor of the project with significant changes from previous version. Only major additions and changes are listed below.
### Added ### Added

112
README.md
View File

@@ -1,9 +1,12 @@
# tuya-mqtt # tuya-mqtt
# !!!! Important Note !!!! # Note
This project is currently in maintainance mode. No further enhancements to this project are planned and will not be planned for the future unless someone out there is interested in becoming the new maintainer. Please do not open issues to request new features, new device support, etc, as they will likely be closed with no comment. I will try to support existing functionality, but even this will likely be on a very limited basis. If you are interested in maintaining this project, please post [here](https://github.com/rospogrigio/localtuya/issues/194).
I have decided to step away from this project as I've made the personal decision to rid myself of any Tuya Wifi based devices (I'm down to only 4 at this point, and they are all easy to replace or at least flash with Tasmota). This decision was made due to the fact that Tuya continues to make it more and more difficult to control their devices locally. While I don't blame them for this, these devices were only interesting to me because of this local control and thus I can no longer meet my personal goals with Tuya devices (at least the Wifi ones) so I will no longer be purchasing/using them going forward. I'm not a developer and I'm new to nodejs.
I just need to get data from Zigbee devices behind Tuya Wireless Gateway and the ability to control them using MQTT commands.
I forked this repository [TheAgentK](https://github.com/TheAgentK/tuya-mqtt) and made some changes.
# About # About
This project is a bridge that allows locally controlling IOT devices manufactured by Tuya Inc., and sold under many different brands, via simple MQTT topics. It effectively translate the Tuya protocol to easy to use topics. This project is a bridge that allows locally controlling IOT devices manufactured by Tuya Inc., and sold under many different brands, via simple MQTT topics. It effectively translate the Tuya protocol to easy to use topics.
@@ -14,9 +17,6 @@ To acquire keys for your device please see the instructions at the TuyAPI projec
**Acquiring device keys is outside the scope of this project!** Issues opened regarding acquiring keys will likely be closed without comment. Please verify that your device can be queried and controlled via tuya-cli before opening any issue. If your device can't be controlled by tuya-cli then it cannot be used with this project. **Acquiring device keys is outside the scope of this project!** Issues opened regarding acquiring keys will likely be closed without comment. Please verify that your device can be queried and controlled via tuya-cli before opening any issue. If your device can't be controlled by tuya-cli then it cannot be used with this project.
**!!!!!!!!!! Important information regarding the 3.0 release !!!!!!!!!!**\
The 3.0.0 release (Oct 17th, 2020) is a major refactor of the tuya-mqtt project and, as such, is a breaking release for all users of previous versions. Almost everything about the project is different, including configuration method, topic names, etc. Upgrading users should carefully read the instructions below and assume they are starting over from scratch.
## Installation ## Installation
Download this project to your system into any directory (example below uses /opt/tuya-mqtt) and install tuyapi from the same folder that the tuya-mqtt.js is in Download this project to your system into any directory (example below uses /opt/tuya-mqtt) and install tuyapi from the same folder that the tuya-mqtt.js is in
``` ```
@@ -24,7 +24,7 @@ Download this project to your system into any directory (example below uses /opt
cd /opt cd /opt
// clone this project // clone this project
git clone https://github.com/TheAgentK/tuya-mqtt git clone https://github.com/lehanspb/tuya-mqtt
// change directory to the project directory // change directory to the project directory
cd tuya-mqtt cd tuya-mqtt
@@ -51,13 +51,27 @@ If you use the "tuya-cli wizard" method to acquire your device keys you can leve
[ [
{ {
name: 'Tuya Device 1', name: 'Tuya Device 1',
version: '3.3',
ip: '192.168.20.251',
id: '86435357d8b123456789', id: '86435357d8b123456789',
key: '8b2a69c9876543210' key: '8b2a69c9876543210'
}, },
{ {
name: 'Tuya Device 2', name: 'Tuya Device 2',
version: '3.3',
ip: '192.168.20.252',
id: 'eb532eea7d12345678abc', id: 'eb532eea7d12345678abc',
key: '899810012345678' key: '899810012345678',
subDevices:
[ { name: 'subdevice1',
id: 'zt431eda8d12345678awc',
cid: '1a24fkfffe6b4e24'
},
{ name: 'subdevice1',
id: 'rb737qea7v15342678aq3',
cid: '1a24fkfffe0t2c29'
}
]
} }
] ]
``` ```
@@ -74,8 +88,41 @@ node tuya-mqtt.js
To enable debugging output (required when opening an issue): To enable debugging output (required when opening an issue):
``` ```
DEBUG=tuya-mqtt:* tuya-mqtt.js DEBUG=tuya-mqtt:* tuya-mqtt.js
or
DEBUG=* tuya-mqtt.js
for full debugging
``` ```
### Systemd script for Debian-like OS
Just create file /etc/systemd/system/tuya-mqtt.service
```
[Unit]
Description=tuya-mqtt
After=network.target
[Service]
ExecStart=/usr/bin/node /opt/tuya-mqtt/tuya-mqtt.js
Restart=always
User=openhab
Group=openhab
Environment=PATH=/usr/bin/
Environment=NODE_ENV=production
WorkingDirectory=/opt/tuya-mqtt/
[Install]
WantedBy=multi-user.target
```
Enable and run:
```
systemctl enable tuya-mqtt.service
systemctl start tuya-mqtt
```
### Updating devices.conf with new and/or changed devices: ### Updating devices.conf with new and/or changed devices:
After adding or changing devices to your Tuya account the devices.conf file can be automatically updated with all new devices and name/key changes by using the merge-devices.js script. Create a file named new-devices.conf with the new "tuya-cli wizard" output then run ```node merge-devices.js```. A dated backup of the original devices.conf file will be created automatically before changes are made. Devices are only added and updated, never removed. The resulting devices.conf file will be neatly formatted and sorted alphabetically by device name. After adding or changing devices to your Tuya account the devices.conf file can be automatically updated with all new devices and name/key changes by using the merge-devices.js script. Create a file named new-devices.conf with the new "tuya-cli wizard" output then run ```node merge-devices.js```. A dated backup of the original devices.conf file will be created automatically before changes are made. Devices are only added and updated, never removed. The resulting devices.conf file will be neatly formatted and sorted alphabetically by device name.
@@ -136,26 +183,49 @@ tuya/dimmer_device/DPS/2/command <-- accepts 1-255 for controlling brightness l
**!!! Important Note !!!** **!!! Important Note !!!**
When sending commands directly to DPS values there are no limitation on what values are sent as tuya-mqtt has no way to know what are valid vs invalid for any given DPS key. Sending values that are out-of-range or of different types than the DPS key expects can cause unpredictable behavior of your device, from causing timeouts, to reboots, to hanging the device. While I've never seen a device fail to recover after a restart, please keep this in mind when sending commands to your device. When sending commands directly to DPS values there are no limitation on what values are sent as tuya-mqtt has no way to know what are valid vs invalid for any given DPS key. Sending values that are out-of-range or of different types than the DPS key expects can cause unpredictable behavior of your device, from causing timeouts, to reboots, to hanging the device. While I've never seen a device fail to recover after a restart, please keep this in mind when sending commands to your device.
## DPS Topics for devices behind Tuya Gateway
In addition to the DPS Key topics, it's possible to use the DPS for devices behind Tuya Gateway.
'cid' - is the subdevice id.
'cidname' - is the name of subdevice (from devices.conf)
This example demostrates DPS values and commands for Tuya Smart Thermostat Radiator Valve behind Tuya Gateway:
```
Thermostat mode:
tuya/zgw1/thermostat/dsp/4/state --> {"4":"auto"}
Possible values: auto/temp_auto/holiday/manual/comfort/eco/BOOST
tuya/zgw1/thermostat/dps/4/command <-- auto
Temperature Setpoint:
tuya/zgw1/thermostat/dps/2/state --> {"2": 220}
Where 220 - 22.0 Celsius
tuya/zgw1/thermostat/dps/command <-- 225
Current Temperature:
tuya/zgw1/thermostat/dps/3/state --> {"3": 225}
Where 225 - 22.5 Celsius
Valve percent:
tuya/zgw1/thermostat/dps/109/state --> {"109": 30}
Where 30 - 30%
```
You can also use JSON commands with 'cid'
```
tuya/zgw1/dps/command <-- {"dps": 2, "set": 225, "cid": "2c34f13fde594a34"}
```
## Issues ## Issues
Not all Tuya protocols are supported. For example, some devices use protocol 3.2 which currently remains unsupported by the TuyAPI project due to lack of enough information to reverse engineer the protocol. If you are unable to control your devices with tuya-mqtt please verify that you can query and control them with tuya-cli first. If tuya-cli works, then this script should also work, if it doesn't then this script will not work either. Not all Tuya protocols are supported. For example, some devices use protocol 3.2 which currently remains unsupported by the TuyAPI project due to lack of enough information to reverse engineer the protocol. If you are unable to control your devices with tuya-mqtt please verify that you can query and control them with tuya-cli first. If tuya-cli works, then this script should also work, if it doesn't then this script will not work either.
## Integration with other Home Automation tools ## Integration with openHAB
openHAB examples are [here](docs/openHAB.md). openHAB 3.x examples are [here](docs/openHAB.md).
## Contributors ## Contributors
- [TheAgentK](https://github.com/TheAgentK) - [TheAgentK](https://github.com/TheAgentK)
- [tsightler](https://github.com/tsightler) - [lehanspb](https://github.com/lehanspb)
- [Tycale](https://github.com/Tycale)
- [crashdummymch](https://github.com/crashdummymch)
- [GadgetAngel](https://github.com/GadgetAngel)
- [dkrahmer](https://github.com/dkrahmer)
## Related Projects: ## Related Projects:
- https://github.com/codetheweb/tuyapi - https://github.com/codetheweb/tuyapi
- https://github.com/unparagoned/njsTuya
- https://github.com/clach04/python-tuya
- https://github.com/Marcus-L/m4rcus.TuyaCore
- Specs: https://docs.tuya.com/en/cloudapi/cloud_access.html
[![forthebadge](https://forthebadge.com/images/badges/made-with-javascript.svg)](https://forthebadge.com)
[![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://forthebadge.com)

View File

@@ -18,6 +18,7 @@ class TuyaDevice {
key: this.config.key key: this.config.key
} }
if (this.config.name) { this.options.name = this.config.name.toLowerCase().replace(/\s|\+|#|\//g,'_') } if (this.config.name) { this.options.name = this.config.name.toLowerCase().replace(/\s|\+|#|\//g,'_') }
if (this.config.ip) { if (this.config.ip) {
this.options.ip = this.config.ip this.options.ip = this.config.ip
if (this.config.version) { if (this.config.version) {
@@ -27,6 +28,9 @@ class TuyaDevice {
} }
} }
debug(' ############ Config ', JSON.stringify(this.config))
debug(' ############ Options ', JSON.stringify(this.options))
// Set default device data for Home Assistant device registry // Set default device data for Home Assistant device registry
// Values may be overridden by individual devices // Values may be overridden by individual devices
this.deviceData = { this.deviceData = {
@@ -37,6 +41,7 @@ class TuyaDevice {
// Initialize properties to hold cached device state data // Initialize properties to hold cached device state data
this.dps = {} this.dps = {}
this.cid = {}
this.color = {'h': 0, 's': 0, 'b': 0} this.color = {'h': 0, 's': 0, 'b': 0}
// Device friendly topics // Device friendly topics
@@ -56,10 +61,31 @@ class TuyaDevice {
// Create the new Tuya Device // Create the new Tuya Device
this.device = new TuyAPI(JSON.parse(JSON.stringify(this.options))) this.device = new TuyAPI(JSON.parse(JSON.stringify(this.options)))
this.device.on('dp-refresh', (data) => {
if (typeof data === 'object') {
if (data.cid) {
debug('Received dp-refresh data from device '+this.options.id+' cid: '+data.cid+' ->', JSON.stringify(data.dps))
} else {
debug('Received dp-refresh data from device '+this.options.id+' ->', JSON.stringify(data.dps))
debug('Received dp-refresh data from device '+this.options.id+' ->', JSON.stringify(data))
}
this.updateState(data)
} else {
if (data !== 'json obj data unvalid') {
debug('Received string data from device '+this.options.id+' ->', data.replace(/[^a-zA-Z0-9 ]/g, ''))
}
}
})
// Listen for device data and call update DPS function if valid // Listen for device data and call update DPS function if valid
this.device.on('data', (data) => { this.device.on('data', (data) => {
if (typeof data === 'object') { if (typeof data === 'object') {
if (data.cid) {
debug('Received JSON data from device '+this.options.id+' cid: '+data.cid+' ->', JSON.stringify(data.dps))
} else {
debug('Received JSON data from device '+this.options.id+' ->', JSON.stringify(data.dps)) debug('Received JSON data from device '+this.options.id+' ->', JSON.stringify(data.dps))
debug('Received JSON data from device '+this.options.id+' ->', JSON.stringify(data))
}
this.updateState(data) this.updateState(data)
} else { } else {
if (data !== 'json obj data unvalid') { if (data !== 'json obj data unvalid') {
@@ -148,16 +174,27 @@ class TuyaDevice {
} }
} }
} }
if (this.connected) { let cid = data.cid
this.cid = cid
// Had to comment this out 2024.02.19
// New Tuya multimode gateway (zigbee & ble) don't send connected state from BLE-devices
// if (this.connected) {
// this.publishTopics()
// }
this.publishTopics() this.publishTopics()
} } else {
debug('Could not updateState ' + JSON.stringify(data))
} }
} }
// Publish device specific state topics // Publish device specific state topics
publishTopics() { publishTopics() {
// Don't publish if device is not connected // Don't publish if device is not connected
if (!this.connected) return
// Had to comment it out 2024.02.19
// New Tuya multimode gateway (zigbee & ble) don't send connected state from BLE-devices
// if (!this.connected) return
// Loop through and publish all device specific topics // Loop through and publish all device specific topics
for (let topic in this.deviceTopics) { for (let topic in this.deviceTopics) {
@@ -167,10 +204,17 @@ class TuyaDevice {
if (this.dps[key] && this.dps[key].updated) { if (this.dps[key] && this.dps[key].updated) {
const state = this.getTopicState(deviceTopic, this.dps[key].val) const state = this.getTopicState(deviceTopic, this.dps[key].val)
if (state) { if (state) {
if (this.cid) {
// this.publishMqtt(this.baseTopic + cid + '/' + topic, state, true)
// Change cid to cidname
let cidname = this.config.subDevices.find(el => el.cid === this.cid);
this.publishMqtt(this.baseTopic + cidname.name + '/' + topic, state, true)
} else {
this.publishMqtt(this.baseTopic + topic, state, true) this.publishMqtt(this.baseTopic + topic, state, true)
} }
} }
} }
}
// Publish Generic Dps Topics // Publish Generic Dps Topics
this.publishDpsTopics() this.publishDpsTopics()
@@ -181,7 +225,18 @@ class TuyaDevice {
try { try {
if (!Object.keys(this.dps).length) { return } if (!Object.keys(this.dps).length) { return }
const dpsTopic = this.baseTopic + 'dps' let dpsTopic
if (this.cid) {
// dpsTopic = this.baseTopic + this.cid + '/dps'
// Change cid to cidname
let cidname = this.config.subDevices.find(el => el.cid === this.cid);
dpsTopic = this.baseTopic + cidname.name + '/dps'
} else {
dpsTopic = this.baseTopic + 'dps'
}
// const dpsTopic = this.baseTopic + 'dps'
// Publish DPS JSON data if not empty // Publish DPS JSON data if not empty
let data = {} let data = {}
for (let key in this.dps) { for (let key in this.dps) {
@@ -196,6 +251,7 @@ class TuyaDevice {
this.publishMqtt(dpsStateTopic, data, false) this.publishMqtt(dpsStateTopic, data, false)
// Publish dps/<#>/state value for each device DPS // Publish dps/<#>/state value for each device DPS
// or cid/dps/<#>/state if cid exists
for (let key in this.dps) { for (let key in this.dps) {
// Only publish values if different from previous value // Only publish values if different from previous value
if (this.dps[key].updated) { if (this.dps[key].updated) {
@@ -289,7 +345,7 @@ class TuyaDevice {
const deviceTopic = this.deviceTopics.hasOwnProperty(stateTopic) ? this.deviceTopics[stateTopic] : '' const deviceTopic = this.deviceTopics.hasOwnProperty(stateTopic) ? this.deviceTopics[stateTopic] : ''
if (deviceTopic) { if (deviceTopic) {
debugCommand('Device '+this.options.id+' received command topic: '+commandTopic+', message: '+command) // debugCommand('Device '+this.options.id+' received command topic: '+commandTopic+', message: '+command)
let commandResult = this.sendTuyaCommand(command, deviceTopic) let commandResult = this.sendTuyaCommand(command, deviceTopic)
if (!commandResult) { if (!commandResult) {
debugCommand('Command topic '+this.baseTopic+commandTopic+' received invalid value: '+command) debugCommand('Command topic '+this.baseTopic+commandTopic+' received invalid value: '+command)
@@ -326,6 +382,24 @@ class TuyaDevice {
} }
} }
processDpsKeyWcidNameCommand(message, subDevDpsKey, cidName) {
if (utils.isJsonString(message)) {
debugCommand('Individual DPS command topics do not accept JSON values')
} else {
const dpsMessage = this.parseDpsMessage(message)
let subdev = this.config.subDevices.find(el => el.name === cidName);
const sdcid = subdev.cid
debugCommand('Received command for '+sdcid+' DPS'+subDevDpsKey+': ', message)
const command = {
dps: subDevDpsKey,
set: dpsMessage,
cid: sdcid
}
this.set(command)
}
}
// Parse string message into boolean and number types // Parse string message into boolean and number types
parseDpsMessage(message) { parseDpsMessage(message) {
if (typeof message === 'boolean' ) { if (typeof message === 'boolean' ) {

View File

@@ -1,142 +1,217 @@
:exclamation: There is a greate Step-By-Step guide from user HolgiHab at openhab community ([Step-By-Step Guide]( ## Example items for OpenHAB 3.x Bindings
https://community.openhab.org/t/step-by-step-guide-for-adding-tuya-bulbs-smart-life-to-oh2-using-tuya-mqtt-js-by-agentk/59371)). This guide is not only for light bulbs, but also applies to sockets. :exclamation:
## Example items for OpenHAB 1.x Bindings (still works with OH > 2.4 but only if legacy 1.x MQTT bindings are enabled) ### Tuya Smart Thermostat Radiator Valve behind Tuya Gateway
### simple switch on/off
### Things channels (configured via web):
#### Thermostat mode:
Channel identifier:
```
mode
``` ```
Switch tuya_kitchen_coffeemachine_mqtt "Steckdose Kaffeemaschine" <socket> (<GROUPS>) ["Switchable"] { State:
mqtt="<[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/state:state:default:.*], ```
>[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/on:command:ON:true], tuya/zgw1/1a24fkfffe6b4e24/dsp/4/state
>[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/off:command:OFF:false]" ```
Example output: {"4":"auto"}
Possible values: auto/temp_auto/holiday/manual/comfort/eco/BOOST
Command:
```
tuya/zgw1/dps/command
```
Outgoing Value Format:
```
{"dps": 4, "set": "%s", "cid": "1a24fkfffe6b4e24"}
```
#### Temperature Setpoint
Channel identifier:
```
setpoint
```
State:
```
tuya/zgw1/1a24fkfffe6b4e24/dsp/2/state
```
Example output: {"2": 220}
Command:
```
tuya/zgw1/dps/command
```
Incoming Value Transformations:
```
JS:tuya-in.js
```
Outgoing Value Transformation:
```
JS:tuya-out.js
```
Outgoing Value Format:
```
{"dps": 2, "set": "%s", "cid": "1a24fkfffe6b4e24"}
```
#### Current Temperature
Channel identifier:
```
temperature
```
State:
```
tuya/zgw1/1a24fkfffe6b4e24/dsp/3/state
```
Incoming Value Transformations:
```
JS:tuya-in.js
```
#### Valve percent
Channel identifier:
```
valve_percent
```
State:
```
tuya/zgw1/1a24fkfffe6b4e24/dsp/109/state
```
Command:
```
tuya/zgw1/dps/command
```
Outgoing Value Format:
```
{"dps": 109, "set": %s, "cid": "1a24fkfffe6b4e24"}
```
### Transformations
tuya-in.js:
```
(function(i) {
return (i / 10)
})(input)
```
tuya-out.js:
```
(function(i) {
return (i * 10)
})(input)
```
### items/thermostat.items
```
String Radiator_Mode "Mode" <radiator> { channel="mqtt:topic:home:zgw1dev1:mode" }
Number Radiator_Setpoint "Temperature setpoint [%.1f °C]" <radiator> { channel="mqtt:topic:home:zgw1dev1:setpoint" }
Number Radiator_Temperature "Current temperature [%.1f °C]" <temperature> { channel="mqtt:topic:home:zgw1dev1:temperature" }
Number Radiator_Valve_Percent "Valve percent [%d %%]" { channel="mqtt:topic:home:zgw1dev1:valve_percent" }
```
### sitemaps/home.sitemap
```
Frame label="Heating" {
Setpoint item=Radiator_Setpoint minValue=15 maxValue=30 step=0.5
Selection item=Radiator_Mode mappings=[auto='Auto', temp_auto='Auto temp', manual='Manual', comfort='Comfort']
Text item=Radiator_Setpoint
Text item=Radiator_Temperature
Text item=Radiator_Valve_Percent
} }
Switch tuya_livingroom_ledstrip_tv "LED Regal" <lightbulb> (<GROUPS>) ["Lighting"] {
mqtt="<[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/state:state:default:.*],
>[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/on:command:ON:true],
>[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command/off:command:OFF:false]"
}
``` ```
### change color of lightbulb
### Simple on/off switch with power measurement capability
### Things channels (configured via web):
#### Power switch
Channel identifier:
```
power
``` ```
# .items State:
Group gTuyaLivingColor "Tuya color group" <lightbulb> ```
Color tuya_livingroom_colorpicker "Stehlampe farbe" (LivingDining) tuya/tuya_device_1/state
```
String tuya_livingroom_ledstrip_tv_color "Set color [%s]" (gTuyaLivingColor, LivingDining) { Example output: {"4":"auto"}
mqtt=">[broker:tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/color:command:*:default]" Possible values: auto/temp_auto/holiday/manual/comfort/eco/BOOST
}
# .rules
import org.openhab.core.library.types.HSBType;
rule "Set HSB value of item RGBLed to RGB color value"
when
Item tuya_livingroom_colorpicker received command
then
var appName = "Colorpicker.livingroom"
var color = receivedCommand.toString;
// get all colors and send it via mqtt if light ist enabled
gTuyaLivingColor.members.forEach[ i |
var name = i.name;
var stateName = name.toString.split("_color").get(0);
var stateItem = gTuyaLights.allMembers.filter [ conf | conf.name.contains(stateName.toString) ].head;
if(stateItem.state == ON){
logInfo(appName, name + " change to color: " + color);
i.sendCommand(color);
Thread::sleep(400);
}
]
end
Command:
```
tuya/tuya_device_1/command
``` ```
## Example items for OpenHAB 2.4 Bindings Custom On/Open Value:
### simple switch on/off ```
ON
With OpenHAB 2.X MQTT bindings you can add devices using a generic MQTT Thing via PaperUI or
configuration files. For PaperUI simply at the generic MQTT Thing and set the state and
command topics as follows:
``` ```
tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/state Custom Off/Closed Value:
```
tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command OFF
``` ```
If you prefer using configuration files vs PaperUI, it should look something like this: #### Power consumption watts
See also OpenHAB 2.X MQTT binding [documentation](https://www.openhab.org/v2.4/addons/bindings/mqtt.generic/) Channel identifier:
```
w
``` ```
Bridge mqtt:broker:myUnsecureBroker [ host="localhost", secure=false ] State:
{ ```
tuya/tuya_device_1/dps/19/state
Thing mqtt:topic:myCustomMQTT {
Channels:
Type switch : tuya_kitchen_coffeemachine_mqtt_channel "Kitchen Coffee Machine MQTT Channel" [
stateTopic="tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/state",
commandTopic="tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/command",
// optional custom mqtt-payloads for ON and OFF
on="{ \"dps\": 1, \"set\": true }",
off="0"
]
}
}
# *.item Example
Switch tuya_kitchen_coffeemachine_mqtt "Kitchen Coffee Machine Switch" <socket> (gKitchen, gTuya) ["Switchable"] {
channel="mqtt:topic:myUnsecureBroker:myCustomMQTT:tuya_kitchen_coffeemachine_mqtt_channel"
}
``` ```
For one RGB bulb you would need a separate channel with the command topic set to Incoming Value Transformations:
`tuya/<tuyAPI-id>/<tuyAPI-key>/<tuyAPI-ip>/color` and link that to your color item. JS:tuya-energy.js
#### Power consumption volts
Channel identifier:
```
v
``` ```
Bridge mqtt:broker:myUnsecureBroker [ host="localhost", secure=false ] State:
{ ```
Thing mqtt:topic:myCustomMQTT { tuya/tuya_device_1/dps/20/state
Channels:
Type colorHSB : livingroom_floorlamp_1_color "Livingroom floorlamp color MQTT Channel" [
stateTopic="tuya/05200399bcddc2e02ec9/b58cf92e8bc5c899/192.168.178.49/state",
commandTopic="tuya/05200399bcddc2e02ec9/b58cf92e8bc5c899/192.168.178.49/color"
]
}
}
# *.item Example
Color tuya_livingroom_colorpicker "Floorlamp colorpicker" (gLivingroom){
channel="mqtt:topic:myUnsecureBroker:myCustomMQTT:livingroom_floorlamp_1_color"
}
``` ```
#### Basic UI sitemap Incoming Value Transformations:
JS:tuya-energy.js
### transform/tuya-energy.js
```
(function(i) {
return Math.ceil(i / 10)
})(input)
``` ```
Switch item=tuya_kitchen_coffeemachine_mqtt ### items/socket.items
# turn the color bulb off or on Switch Socket_Power "Socket" { channel="mqtt:topic:socket:power" }
Switch item=tuya_livingroom_colorpicker label="RGB lamp [%s]" Number Socket_W "Power (W)" { channel="mqtt:topic:socket:w" }
Number Socket_Vt "Power (V) [%s]" { channel="mqtt:topic:socket:v" }
# pick the color level to send to the color bulb via MQTT color Channel ### sitemaps/home.sitempa
Slider item=tuya_livingroom_colorpicker label="RGB lamp level [%s]" minValue=0 maxValue=100 step=1
# color picked and sent via MQTT Color channel Switch item=Socket_Power
Colorpicker item=tuya_livingroom_colorpicker label="RGB lamp color [%s]" icon="colorpicker" sendFrequency=30000 Text item=Socket_W
Text item=Socket_Vt
```

View File

@@ -1,8 +1,8 @@
{ {
"name": "tuya-mqtt", "name": "tuya-mqtt",
"version": "3.0.4", "version": "3.1.4",
"description": "Control Tuya devices locally via MQTT", "description": "Control Tuya devices locally via MQTT",
"homepage": "https://github.com/TheAgentK/tuya-mqtt#readme", "homepage": "https://github.com/lehanspb/tuya-mqtt#readme",
"main": "tuya-mqtt.js", "main": "tuya-mqtt.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
@@ -19,11 +19,11 @@
"json5": "^2.1.3", "json5": "^2.1.3",
"mqtt": "^4.2.6", "mqtt": "^4.2.6",
"supports-color": "^8.1.0", "supports-color": "^8.1.0",
"tuyapi": "^6.1.4", "tuyapi": "^7.5.1",
"mathjs": "8.1.1" "mathjs": "8.1.1"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/TheAgentK/tuya-mqtt.git" "url": "git://github.com/lehanspb/tuya-mqtt.git"
} }
} }

View File

@@ -165,6 +165,11 @@ const main = async() => {
const dpsKey = splitTopic[topicLength-2] const dpsKey = splitTopic[topicLength-2]
device.processDpsKeyCommand(message, dpsKey) device.processDpsKeyCommand(message, dpsKey)
break; break;
case 6:
const subDevDpsKey = splitTopic[topicLength-2]
const cidName = splitTopic[topicLength-4]
device.processDpsKeyWcidNameCommand(message, subDevDpsKey, cidName)
break;
} }
} }
} catch (e) { } catch (e) {