Skip to content

Commit 3ed8e86

Browse files
authored
Add support for DEEBOT T90 PRO OMNI (#1561)
Register the twunby hardware profile with capabilities verified against a real device. The model uses getWorkState for state/station refresh and supports sweep mode, while similar T50-derived clean info and multimap/carpet boost capabilities are not supported.
1 parent cf37ac6 commit 3ed8e86

1 file changed

Lines changed: 267 additions & 0 deletions

File tree

deebot_client/hardware/twunby.py

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
"""DEEBOT T90 PRO OMNI Capabilities."""
2+
3+
from __future__ import annotations
4+
5+
from deebot_client.capabilities import (
6+
Capabilities,
7+
CapabilityClean,
8+
CapabilityCleanAction,
9+
CapabilityCustomCommand,
10+
CapabilityEvent,
11+
CapabilityExecute,
12+
CapabilityExecuteTypes,
13+
CapabilityLifeSpan,
14+
CapabilityMap,
15+
CapabilityNumber,
16+
CapabilitySet,
17+
CapabilitySetEnable,
18+
CapabilitySettings,
19+
CapabilitySetTypes,
20+
CapabilityStation,
21+
CapabilityStats,
22+
CapabilityWater,
23+
DeviceType,
24+
)
25+
from deebot_client.commands import StationAction
26+
from deebot_client.commands.json import station_action
27+
from deebot_client.commands.json.auto_empty import GetAutoEmpty, SetAutoEmpty
28+
from deebot_client.commands.json.battery import GetBattery
29+
from deebot_client.commands.json.charge import Charge
30+
from deebot_client.commands.json.charge_state import GetChargeState
31+
from deebot_client.commands.json.child_lock import GetChildLock, SetChildLock
32+
from deebot_client.commands.json.clean import (
33+
Clean,
34+
CleanArea,
35+
)
36+
from deebot_client.commands.json.clean_count import GetCleanCount, SetCleanCount
37+
from deebot_client.commands.json.clean_logs import GetCleanLogs
38+
from deebot_client.commands.json.continuous_cleaning import (
39+
GetContinuousCleaning,
40+
SetContinuousCleaning,
41+
)
42+
from deebot_client.commands.json.custom import CustomCommand
43+
from deebot_client.commands.json.error import GetError
44+
from deebot_client.commands.json.fan_speed import GetFanSpeed, SetFanSpeed
45+
from deebot_client.commands.json.life_span import GetLifeSpan, ResetLifeSpan
46+
from deebot_client.commands.json.map import (
47+
GetCachedMapInfo,
48+
GetMajorMap,
49+
GetMapInfoV2,
50+
GetMapSetV2,
51+
GetMapTrace,
52+
GetMinorMap,
53+
SetMajorMap,
54+
)
55+
from deebot_client.commands.json.mop_auto_wash_frequency import (
56+
GetMopAutoWashFrequency,
57+
SetMopAutoWashFrequency,
58+
)
59+
from deebot_client.commands.json.network import GetNetInfo
60+
from deebot_client.commands.json.ota import GetOta, SetOta
61+
from deebot_client.commands.json.play_sound import PlaySound
62+
from deebot_client.commands.json.pos import GetPos
63+
from deebot_client.commands.json.relocation import SetRelocationState
64+
from deebot_client.commands.json.stats import GetStats, GetTotalStats
65+
from deebot_client.commands.json.sweep_mode import GetSweepMode, SetSweepMode
66+
from deebot_client.commands.json.true_detect import GetTrueDetect, SetTrueDetect
67+
from deebot_client.commands.json.voice_assistant_state import (
68+
GetVoiceAssistantState,
69+
SetVoiceAssistantState,
70+
)
71+
from deebot_client.commands.json.volume import GetVolume, SetVolume
72+
from deebot_client.commands.json.water_info import GetWaterInfo, SetWaterInfo
73+
from deebot_client.commands.json.work_mode import GetWorkMode, SetWorkMode
74+
from deebot_client.commands.json.work_state import GetWorkState
75+
from deebot_client.const import DataType
76+
from deebot_client.events import (
77+
AvailabilityEvent,
78+
BatteryEvent,
79+
CachedMapInfoEvent,
80+
ChildLockEvent,
81+
CleanCountEvent,
82+
CleanLogEvent,
83+
ContinuousCleaningEvent,
84+
CustomCommandEvent,
85+
ErrorEvent,
86+
FanSpeedEvent,
87+
FanSpeedLevel,
88+
LifeSpan,
89+
LifeSpanEvent,
90+
MajorMapEvent,
91+
MapChangedEvent,
92+
MapTraceEvent,
93+
NetworkInfoEvent,
94+
OtaEvent,
95+
PositionsEvent,
96+
ReportStatsEvent,
97+
RoomsEvent,
98+
StateEvent,
99+
StationEvent,
100+
StatsEvent,
101+
SweepModeEvent,
102+
TotalStatsEvent,
103+
TrueDetectEvent,
104+
VoiceAssistantStateEvent,
105+
VolumeEvent,
106+
WorkMode,
107+
WorkModeEvent,
108+
auto_empty,
109+
water_info,
110+
)
111+
from deebot_client.events.auto_empty import AutoEmptyEvent
112+
from deebot_client.events.mop_auto_wash_frequency import MopAutoWashFrequencyEvent
113+
from deebot_client.models import StaticDeviceInfo
114+
115+
116+
def get_device_info() -> StaticDeviceInfo:
117+
"""Get device info for this model."""
118+
return StaticDeviceInfo(
119+
DataType.JSON,
120+
Capabilities(
121+
device_type=DeviceType.VACUUM,
122+
availability=CapabilityEvent(
123+
AvailabilityEvent, [GetBattery(is_available_check=True)]
124+
),
125+
battery=CapabilityEvent(BatteryEvent, [GetBattery()]),
126+
charge=CapabilityExecute(Charge),
127+
clean=CapabilityClean(
128+
action=CapabilityCleanAction(command=Clean, area=CleanArea),
129+
continuous=CapabilitySetEnable(
130+
ContinuousCleaningEvent,
131+
[GetContinuousCleaning()],
132+
SetContinuousCleaning,
133+
),
134+
count=CapabilitySet(CleanCountEvent, [GetCleanCount()], SetCleanCount),
135+
log=CapabilityEvent(CleanLogEvent, [GetCleanLogs()]),
136+
work_mode=CapabilitySetTypes(
137+
event=WorkModeEvent,
138+
get=[GetWorkMode()],
139+
set=SetWorkMode,
140+
types=(
141+
WorkMode.MOP,
142+
WorkMode.MOP_AFTER_VACUUM,
143+
WorkMode.VACUUM,
144+
WorkMode.VACUUM_AND_MOP,
145+
),
146+
),
147+
),
148+
custom=CapabilityCustomCommand(
149+
event=CustomCommandEvent, get=[], set=CustomCommand
150+
),
151+
error=CapabilityEvent(ErrorEvent, [GetError()]),
152+
fan_speed=CapabilitySetTypes(
153+
event=FanSpeedEvent,
154+
get=[GetFanSpeed()],
155+
set=SetFanSpeed,
156+
types=(
157+
FanSpeedLevel.QUIET,
158+
FanSpeedLevel.NORMAL,
159+
FanSpeedLevel.MAX,
160+
FanSpeedLevel.MAX_PLUS,
161+
),
162+
),
163+
life_span=CapabilityLifeSpan(
164+
types=(
165+
LifeSpan.SIDE_BRUSH,
166+
LifeSpan.BRUSH,
167+
LifeSpan.FILTER,
168+
LifeSpan.UNIT_CARE,
169+
LifeSpan.ROUND_MOP,
170+
LifeSpan.DUST_BAG,
171+
LifeSpan.CLEANING_SOLUTION,
172+
),
173+
event=LifeSpanEvent,
174+
get=[
175+
GetLifeSpan(
176+
[
177+
LifeSpan.SIDE_BRUSH,
178+
LifeSpan.BRUSH,
179+
LifeSpan.FILTER,
180+
LifeSpan.UNIT_CARE,
181+
LifeSpan.ROUND_MOP,
182+
LifeSpan.DUST_BAG,
183+
LifeSpan.CLEANING_SOLUTION,
184+
]
185+
)
186+
],
187+
reset=ResetLifeSpan,
188+
),
189+
map=CapabilityMap(
190+
cached_info=CapabilityEvent(CachedMapInfoEvent, [GetCachedMapInfo()]),
191+
changed=CapabilityEvent(MapChangedEvent, []),
192+
info=CapabilityExecute(GetMapInfoV2),
193+
major=CapabilitySet(MajorMapEvent, [GetMajorMap()], SetMajorMap),
194+
minor=CapabilityExecute(GetMinorMap),
195+
position=CapabilityEvent(PositionsEvent, [GetPos()]),
196+
relocation=CapabilityExecute(SetRelocationState),
197+
rooms=CapabilityEvent(RoomsEvent, [GetCachedMapInfo()]),
198+
set=CapabilityExecute(GetMapSetV2),
199+
trace=CapabilityEvent(MapTraceEvent, [GetMapTrace()]),
200+
),
201+
network=CapabilityEvent(NetworkInfoEvent, [GetNetInfo()]),
202+
play_sound=CapabilityExecute(PlaySound),
203+
settings=CapabilitySettings(
204+
child_lock=CapabilitySetEnable(
205+
ChildLockEvent, [GetChildLock()], SetChildLock
206+
),
207+
mop_auto_wash_frequency=CapabilityNumber(
208+
event=MopAutoWashFrequencyEvent,
209+
get=[GetMopAutoWashFrequency()],
210+
set=SetMopAutoWashFrequency,
211+
min=0,
212+
max=60,
213+
),
214+
ota=CapabilitySetEnable(OtaEvent, [GetOta()], SetOta),
215+
sweep_mode=CapabilitySetEnable(
216+
SweepModeEvent, [GetSweepMode()], SetSweepMode
217+
),
218+
true_detect=CapabilitySetEnable(
219+
TrueDetectEvent, [GetTrueDetect()], SetTrueDetect
220+
),
221+
voice_assistant=CapabilitySetEnable(
222+
VoiceAssistantStateEvent,
223+
[GetVoiceAssistantState()],
224+
SetVoiceAssistantState,
225+
),
226+
volume=CapabilitySet(VolumeEvent, [GetVolume()], SetVolume),
227+
),
228+
state=CapabilityEvent(StateEvent, [GetChargeState(), GetWorkState()]),
229+
station=CapabilityStation(
230+
action=CapabilityExecuteTypes(
231+
station_action.StationAction,
232+
types=(
233+
StationAction.EMPTY_DUSTBIN,
234+
StationAction.DRY_MOP,
235+
StationAction.WASH_MOP,
236+
),
237+
),
238+
auto_empty=CapabilitySetTypes(
239+
event=AutoEmptyEvent,
240+
get=[GetAutoEmpty()],
241+
set=SetAutoEmpty,
242+
types=(
243+
auto_empty.Frequency.AUTO,
244+
auto_empty.Frequency.SMART,
245+
),
246+
),
247+
state=CapabilityEvent(StationEvent, [GetWorkState()]),
248+
),
249+
stats=CapabilityStats(
250+
clean=CapabilityEvent(StatsEvent, [GetStats()]),
251+
report=CapabilityEvent(ReportStatsEvent, []),
252+
total=CapabilityEvent(TotalStatsEvent, [GetTotalStats()]),
253+
),
254+
water=CapabilityWater(
255+
amount=CapabilityNumber(
256+
event=water_info.WaterCustomAmountEvent,
257+
get=[GetWaterInfo()],
258+
set=lambda custom_amount: SetWaterInfo(custom_amount=custom_amount),
259+
min=0,
260+
max=50,
261+
),
262+
mop_attached=CapabilityEvent(
263+
water_info.MopAttachedEvent, [GetWaterInfo()]
264+
),
265+
),
266+
),
267+
)

0 commit comments

Comments
 (0)