Любой домостроитель знает: лучшее облако — локальное “облако”. А потому будем отучать увлажнитель воздуха Tuvio TAP01DE от чужих серверов.
Intro
Какое-то время назад я прикупил себе увлажнитель/очиститель воздуха Tuvio TAP01DE — вот такой:
Это ни в коем случае не рекомендация, просто факт. Даже не знаю, почему взял именно его — возможно, захотелось побыть рискованным парнем :)
Для моей небольшой студии его мощности вполне хватает, спать не мешает, но бесят две вещи:
- очень часто приходится заправлять бак (буквально раз в полтора дня);
- управляется через облако.
И если с первым я ничего поделать не могу (кроме как собрать свой, офк), то от облака его вполне можно отучить. Ведь Tuvio — это обычный white-label на платформе Tuya. А значит, Tuya Local или Local Tuya должен зарешать.
Зачем? Ну… как обычно:
- любое вендорское облако — злющее зло;
- зачем мне иметь по приложению на каждое устройство, если есть Home Assistant;
- само приложение Tuvio — это какой-то стыд с лужей мочи в центре (не открывайте).
Dive into
Чтобы локально подключиться к Tuya-устройству, сначала нужно раздобыть его device id и local key. Есть разные способы их заполучить, но самый простой — через портал разработчика Tuya. Поэтому, прежде чем открывать Home Assistant:
- ставим мобильное приложение SmartLife и регистрируемся (я выбрал регион RU);
- добавляем наш очиститель, зажав иконку регулировки скорости вентилятора;
- регистрируемся в Tuya Developer Platform;
- создаём новое облако в ДЦ “Central Europe Data Center” (к нему привязан RU регион);
- идём в
Cloud→Project Management→Open Projectи запоминаем креды:
- не уходя со страницы проекта, идём в
Devices→Link App Accountи жмёмAdd App Account→Tuya App Account Authorization:
- сканируем QR-код в приложении
SmartLife, авторизуемся, и в портал подтягиваются наши устройства. Запоминаем егоdevice id:
Дальше есть два пути:
- надеяться на
Tuya Local/Local Tuya, отдав их мастеру свой аккаунт разработчика; - воспользоваться tinytuya.
Мне ближе второй вариант — тем более, он пригодится и для отладки:
# Ставим tinytuya
% pip install tinytuya
# Запускаем визард и вводим ранее прикопанные Access ID, Access Secret и Device ID
% tinytuya wizard
TinyTuya Setup Wizard [1.17.4]
Enter API Key from tuya.com: c44ufc3q9um7k7wae44d
Enter API Secret from tuya.com: a3c4d402056e490ca96db802382cb2d2
Enter any Device ID currently registered in Tuya App (used to pull full list) or 'scan' to scan for one: bf9f4125ac798e6a383jaj
Region List
cn China Data Center (alias: AY)
us US - Western America Data Center (alias: AZ)
us-e US - Eastern America Data Center (alias: UE)
eu Central Europe Data Center
eu-w Western Europe Data Center (alias: WE)
in India Data Center
sg Singapore Data Center
Enter Your Region (Options: cn, us, us-e, eu, eu-w, in, or sg): eu
>> Configuration Data Saved to tinytuya.json
{
"apiKey": "c44ufc3q9um7k7wae44d",
"apiSecret": "a3c4d402056e490ca96db802382cb2d2",
"apiRegion": "eu",
"apiDeviceID": "bf9f4125ac798e6a383jaj"
}
Download DP Name mappings? (Y/n): Y
Device Listing
[
{
"name": "Tuvio TAP01DE",
"id": "bf9XXXXXXXX",
"key": "XXXXXXXX",
"mac": "80:64:7c:0c:77:aa",
"uuid": "XXXXXXXX",
"sn": "XXXXXXXX",
"category": "jsq",
"product_name": "Tuvio TAP01DE",
"product_id": "cdtata05klpwbyu9",
"biz_type": 18,
"model": "TAP01DE",
"sub": false,
"icon": "https://images.tuyaeu.com/smart/icon/bay1695300390722FkGj/2c7da8627d8684e73531929f4cdd0ed3.png",
"mapping": {}
}
]
>> Saving list to devices.json
1 registered devices saved
>> Saving raw TuyaPlatform response to tuya-raw.json
Poll local devices? (Y/n): Y
Scanning local network for Tuya devices...
1 local devices discovered
Polling local devices...
[Tuvio TAP01DE ] 10.11.0.146 - [On] - DPS: {'1': True, '5': True, '13': 50, '14': 42, '16': False, '19': 'cancel', '20': 0, '22': 0, '33': 1693, '101': '1', '102': True, '103': True, '104': False, '105': False, '106': 60, '108': False, '109': False}
>> Saving device snapshot data to snapshot.json
>> Saving IP addresses to devices.json
1 device IP addresses found
Done.
Нас больше всего интересует две вещи:
- локальный ключ увлажнителя (не забудем прикопать);
- отсутствие официального маппинга DP-кодов (data points).
Разумеется, без маппинга железкой никак не поуправлять, ибо хз как с ней говорить. А потому придётся или искать в интернетах, или собирать самому. Собрать самому несложно — открываем питоний, подключаемся к устройству и запрашиваем текущее состояние:
In [1]: import tinytuya
In [2]: d = tinytuya.Device('<device_id>', '<device_ip>', '<local_key>', version=3.4)
In [3]: d.status()
Out[3]:
{'dps': {'1': True,
'5': True,
'13': 50,
'14': 44,
'16': False,
'19': 'cancel',
'20': 0,
'22': 0,
'33': 1693,
'101': '1',
'102': True,
'103': True,
'104': False,
'105': False,
'106': 60,
'108': False,
'109': False}}
Дальше идём в SmartLife, крутим доступные крутилки, и составляем список кодов (что такое 22 — я так и не понял, вероятно, какая-то диагностика):
1: bool - power switch
5: bool - light
13: from 40 to 70 - target humidity
14: from 0 to 100 - current humidity
16: bool - sleep
19: cancel/1H/2H/3H/4H/5H/6H/7H/8H/9H - countdown (cancel mean off)
20: 1/2/3/4/5/6/7/8/9 - left time in countdown mode
33: integer - filter life (h)
101: A/1/2/3/4 - fan level (A mean auto)
102: bool - vertical switch (swing??)
103: bool - uv
104: bool - wet
105: bool - drying
106: from 1 to 100 - night light bright
108: bool - humidity switch
109: bool - beeper switch
Итак, как-будто всё готово. Можно добавлять устройство в Home Assistant!
Tuya Local
Но сперва решить, что лучше Tuya Local или Local Tuya? Если честно — я не знаю :)
Я выбрал Tuya Local, потому что:
- у него есть отдельный хелпер для увлажнителей;
- устройства описываются ямличками, с которыми ChatGPT почти справляется :)
В интернетах пишут разное, у кого первый стабильнее работает, у кого второй. Для меня пока единственный минус — нельзя держать описания устройств out-of-tree, поэтому репу пришлось форкнуть. А дальше всё просто:
- скармливаем ChatGPT (было лениво иконки выбирать) всю нужную инфу:
- маппинг DP-кодов;
- информацию об устройстве;
- примеры описаний других увлажнителей;
- слегка правим шероховатости (особенно
humidifier), поглядывая в humidifier.py; - и вуаля — вот описание нашего увлажнителя:
name: Tuvio TAP01DE Air Washer
products:
- id: cdtata05klpwbyu9
manufacturer: Tuvio
model: TAP01DE
entities:
- entity: humidifier
class: humidifier
icon: mdi:air-humidifier
dps:
- id: 1
name: switch
type: boolean
- id: 13
name: humidity
type: integer
range:
min: 40
max: 70
unit: "%"
mapping:
- constraint: mode
conditions:
- dps_val: true
invalid: false
- dps_val: false
invalid: true
- id: 14
name: current_humidity
type: integer
unit: "%"
- id: 104
type: boolean
name: action
mapping:
- dps_val: true
value: "work"
- dps_val: false
value: "idle"
- id: 108
type: boolean
name: mode
mapping:
- dps_val: false
value: "auto"
- dps_val: true
value: "normal"
- entity: switch
name: Sleep
icon: mdi:sleep
dps:
- id: 16
name: switch
type: boolean
- entity: select
name: Timer
icon: mdi:timer-outline
dps:
- id: 19
name: option
type: string
mapping:
- dps_val: "cancel"
value: "Off"
- dps_val: "1H"
value: "1 Hour"
- dps_val: "2H"
value: "2 Hours"
- dps_val: "3H"
value: "3 Hours"
- dps_val: "4H"
value: "4 Hours"
- dps_val: "5H"
value: "5 Hours"
- dps_val: "6H"
value: "6 Hours"
- dps_val: "7H"
value: "7 Hours"
- dps_val: "8H"
value: "8 Hours"
- dps_val: "9H"
value: "9 Hours"
- entity: sensor
name: Time remaining
icon: mdi:timer-sand
class: duration
dps:
- id: 20
name: sensor
type: integer
unit: "h"
- entity: sensor
name: Filter life
icon: mdi:air-filter
class: duration
category: diagnostic
dps:
- id: 33
type: integer
name: sensor
unit: "h"
- entity: select
name: Fan speed
icon: mdi:fan
dps:
- id: 101
name: option
type: string
mapping:
- dps_val: "A"
value: "Auto"
- dps_val: "1"
value: "Low"
- dps_val: "2"
value: "Medium"
- dps_val: "3"
value: "High"
- dps_val: "4"
value: "Turbo"
- entity: switch
name: Vertical swing
icon: mdi:pan-vertical
dps:
- id: 102
name: switch
type: boolean
- entity: switch
name: UV
icon: mdi:radiation
dps:
- id: 103
name: switch
type: boolean
- entity: switch
name: Wet
icon: mdi:water-outline
dps:
- id: 104
type: boolean
name: switch
- entity: switch
name: Drying
icon: mdi:hair-dryer
dps:
- id: 105
name: switch
type: boolean
- entity: light
name: Night Light
category: config
dps:
- id: 5
type: boolean
name: switch
- id: 106
type: integer
name: brightness
range:
min: 1
max: 100
unit: "%"
- entity: switch
name: Beeper
icon: mdi:volume-high
category: config
dps:
- id: 109
name: switch
type: boolean
Финишная прямая, я обещаю.
Home Assistant
Когда все запчасти собраны, остаётся только чуть мышкой поелозить:
- ставим HACS;
- добавляем новую репу
buglloc/tuya-local:
- ставим
Tuya Localи перезагружаем Home Assistant; - добавляем устройство
Tuya Local:
- выбираем ручное подключение (тут по вкусу, но раз уж всё у нас на руках…):

- заполняем данные для подключения:

- если всё хорошо,
Tuya Localнайдёт подходящее описание:
Клик-клик. Щёлк-щёлк. Па-ба-ам:

Ну не красота ли? :)
Upd
Ахаха, дописав пост, решил отправить PR в Tuya Local и внезапно нашёл похожий:
feat: add Tuvio Air Washer device support.
Вак всегда, я сильно быстрее умных мыслей ;)
Заключение
Как ни странно, но это моё чуть ли не первое устройство на Tuya. Не скажу, что я в восторге, но чего не отнять — так это его популярности. А популярность конвертируется в тулинг, благодаря чему на добавление увлажнителя ушло всего пару часов вместе с чтением манов.
А пока у меня всё. Всем кота! (づ˶•༝•˶)づ♡