Closed mschlenstedt closed 1 year ago
Very cool @mschlenstedt !
@uzlonewolf - I know we don't want to burden the library with a large json mapping payload (it is TINYtuya after all), but this seems reasonable for the server tool. Thoughts? 😄
I agree for the Lib to not include mapping - this should be done on the application side. But as the server is an application, I would really like mapping here :-)
I'm actually about half done with a DP mapping thing myself. Instead of manually assigning names, it uses the cloud.getdps() to pull all of them after grouping by product_id and saves them to mappings.json. I'll see if I can get it cleaned up later today and get a PR in.
Grabbing the mapping "live" is cool - I wasn't successfull with it to be honest. But it's more "tiny" than delivering a 5 MB json database...
Important for me is that the /status call delivers the scheme for other software which uses the API. I would like to use it from my MQTT server script.
I wasn't successful with it to be honest
What problem did you run into?
I played a little bit around with https://eu.iot.tuya.com/cloud/explorer But I haven't found any Cloud call which gives me back name/code and DP ID. Best results I found was with https://openapi.tuyaeu.com/v1.2/iot-03/devices/{device_id}/specification
and/or https://openapi.tuyaeu.com/v1.0/iot-03/devices/{device_id}/functions
. But both just give me the names and codes, but not the corresponding DPS.
{
"result": {
"category": "rs",
"functions": [
{
"code": "Power",
"desc": "{}",
"name": "开关",
"type": "Boolean",
"values": "{}"
},
{
"code": "temp_set",
"desc": "{\"unit\":\"℃\",\"min\":8,\"max\":40,\"scale\":0,\"step\":1}",
"name": "设置温度",
"type": "Integer",
"values": "{\"unit\":\"℃\",\"min\":8,\"max\":40,\"scale\":0,\"step\":1}"
},
{
"code": "mode",
"desc": "{\"range\":[\"auto\",\"cold\",\"hot\"]}",
"name": "模式",
"type": "Enum",
"values": "{\"range\":[\"auto\",\"cold\",\"hot\"]}"
}
],
"status": [
{
"code": "Power",
"name": "开关",
"type": "Boolean",
"values": "{}"
},
{
"code": "temp_set",
"name": "设置温度",
"type": "Integer",
"values": "{\"unit\":\"℃\",\"min\":8,\"max\":40,\"scale\":0,\"step\":1}"
},
{
"code": "temp_current",
"name": "当前温度",
"type": "Integer",
"values": "{\"unit\":\"℃\",\"min\":-10,\"max\":100,\"scale\":0,\"step\":1}"
},
{
"code": "mode",
"name": "模式",
"type": "Enum",
"values": "{\"range\":[\"auto\",\"cold\",\"hot\"]}"
},
{
"code": "fault",
"name": "故障告警",
"type": "Bitmap",
"values": "{\"label\":[\"P1\",\"P2\",\"P3\",\"P4\",\"P6\",\"P7\",\"P8\",\"P9\",\"PL\",\"PC\",\"E3\",\"E4\",\"E8\",\"CS\",\"E6\"],\"maxlen\":15}"
}
]
},
"success": true,
"t": 1684949165736,
"tid": "105ee88bfa5811edbfbfa24bf1d21c99"
}
Does tinytuya's cloud.getdps(dev_id)
(which calls /v1.1/devices/<device>/specifications
) not list them for you? It lists them for my devices:
{
"result": {
"category": "kg",
"functions": [
{
"code": "switch_1",
"dp_id": 1,
"type": "Boolean",
"values": "{}"
},
{
"code": "countdown_1",
"dp_id": 7,
"type": "Integer",
"values": "{\"unit\":\"s\",\"min\":0,\"max\":86400,\"scale\":0,\"step\":1}"
},
{
"code": "sense_0",
"dp_id": 101,
"type": "Enum",
"values": "{\"range\":[\"sense\"]}"
},
{
"code": "sense_1",
"dp_id": 102,
"type": "Enum",
"values": "{\"range\":[\"sense\"]}"
},
...
{
"code": "sense_13",
"dp_id": 114,
"type": "Enum",
"values": "{\"range\":[\"sense\"]}"
}
],
"status": [
{
"code": "switch_1",
"dp_id": 1,
"type": "Boolean",
"values": "{}"
},
{
"code": "countdown_1",
"dp_id": 7,
"type": "Integer",
"values": "{\"unit\":\"s\",\"min\":0,\"max\":86400,\"scale\":0,\"step\":1}"
},
{
"code": "sense_0",
"dp_id": 101,
"type": "Enum",
"values": "{\"range\":[\"sense\"]}"
},
{
"code": "sense_1",
"dp_id": 102,
"type": "Enum",
"values": "{\"range\":[\"sense\"]}"
},
{
"code": "sense_2",
"dp_id": 103,
"type": "Enum",
"values": "{\"range\":[\"sense\"]}"
},
...
{
"code": "sense_13",
"dp_id": 114,
"type": "Enum",
"values": "{\"range\":[\"sense\"]}"
}
]
},
"success": true,
"t": 1684951183675,
"tid": "c3273fc2fa5c11ed8adfb6b4e10a8863"
}
My mappings downloader in #356 turns that into:
{
"xjnax8te3tdkoq9z": {
"1": {
"name": "switch_1",
"type": "Boolean",
"values": {}
},
"7": {
"name": "countdown_1",
"type": "Integer",
"values": {
"unit": "s",
"min": 0,
"max": 86400,
"scale": 0,
"step": 1
}
},
"101": {
"name": "sense_0",
"type": "Enum",
"values": {
"range": [
"sense"
]
}
},
"102": {
"name": "sense_1",
"type": "Enum",
"values": {
"range": [
"sense"
]
}
},
...
"114": {
"name": "sense_13",
"type": "Enum",
"values": {
"range": [
"sense"
]
}
}
}
}
Yes, I can confirm that I get same result as you with cloud.getdps(dev_id)`. This is great - never tried this!
Maybe you should use "code" instead of "name" in your mappings.json - as this is the standard. When your PR is included, I can change my functions to use the format of your mappings.json.
{
"result": {
"category": "rs",
"functions": [
{
"code": "Power",
"dp_id": 1,
"type": "Boolean",
"values": "{}"
},
{
"code": "temp_set",
"dp_id": 2,
"type": "Integer",
"values": "{\"unit\":\"\u2103\",\"min\":8,\"max\":40,\"scale\":0,\"step\":1}"
},
{
"code": "mode",
"dp_id": 4,
"type": "Enum",
"values": "{\"range\":[\"auto\",\"cold\",\"hot\"]}"
}
],
"lang_config": {},
"status": [
{
"code": "Power",
"dp_id": 1,
"type": "Boolean",
"values": "{}"
},
{
"code": "temp_set",
"dp_id": 2,
"type": "Integer",
"values": "{\"unit\":\"\u2103\",\"min\":8,\"max\":40,\"scale\":0,\"step\":1}"
},
{
"code": "temp_current",
"dp_id": 3,
"type": "Integer",
"values": "{\"unit\":\"\u2103\",\"min\":-10,\"max\":100,\"scale\":0,\"step\":1}"
},
{
"code": "mode",
"dp_id": 4,
"type": "Enum",
"values": "{\"range\":[\"auto\",\"cold\",\"hot\"]}"
},
{
"code": "fault",
"dp_id": 9,
"type": "Bitmap",
"values": "{\"label\":[\"P1\",\"P2\",\"P3\",\"P4\",\"P6\",\"P7\",\"P8\",\"P9\",\"PL\",\"PC\",\"E3\",\"E4\",\"E8\",\"CS\",\"E6\"],\"maxlen\":15}"
}
]
},
"success": true,
"t": 1684958124149,
"tid": "ec01691cfa6c11edbfbfa24bf1d21c99"
}
I now changed over to the DPS mapping from Tuya Cloud now. The server now uses the mappings found in devices.json (if any). It's shown in the WebUI and also used in the set API call, e. g.
/set/pool%20heat%20pump/temp_set/26
is possible now.
This is great @mschlenstedt !! Love this...
Thanks @mschlenstedt !! This is a great enhancement to the server!
Thanks for removing the obsolete stuff ;-)
Hi all,
I added a first "Proof of Concept" for doing a DPS <-> Name/Code mapping to have a more comfortable way to set and read the DPS.
At a first step I included mappings from IOBroker and FHEM project (they already use the DPS<->Code/Name mapping). The mapping is read once at startup after reading the devices.json and after saving a new deivces.json. Only those mappings are kept in memory (in a dict) which are currently used. This keeps things small and almost fast.
/status/{DEVICE_ID}
now additionally give back the mapping scheme if one exists for the Product_Key inmappings/mappings.json
:At a first step I included the mapping in the WebUI:
What's still missing:
/set/....
command