77import os
88import pathlib
99import time
10- from typing import List , Optional , Type , Union
10+ from enum import Enum
11+ from typing import Any , List , Optional , Type
1112
1213import click
1314import pytz
2122 command ,
2223)
2324from miio .device import Device , DeviceInfo
24- from miio .devicestatus import action
25+ from miio .devicestatus import DeviceStatus , action
2526from miio .exceptions import DeviceInfoUnavailableException , UnsupportedFeatureException
2627from miio .interfaces import FanspeedPresets , VacuumInterface
2728
29+ from .updatehelper import UpdateHelper
2830from .vacuum_enums import (
2931 CarpetCleaningMode ,
3032 Consumable ,
@@ -143,6 +145,33 @@ def __init__(
143145 self .manual_seqnum = - 1
144146 self ._maps : Optional [MapList ] = None
145147 self ._map_enum_cache = None
148+ self ._status_helper = UpdateHelper (self .vacuum_status )
149+ self ._status_helper .add_update_method ("consumables" , self .consumable_status )
150+ self ._status_helper .add_update_method ("dnd_status" , self .dnd_status )
151+ self ._status_helper .add_update_method ("clean_history" , self .clean_history )
152+ self ._status_helper .add_update_method ("last_clean" , self .last_clean_details )
153+ self ._status_helper .add_update_method ("mop_dryer" , self .mop_dryer_settings )
154+
155+ def send (
156+ self ,
157+ command : str ,
158+ parameters : Optional [Any ] = None ,
159+ retry_count : Optional [int ] = None ,
160+ * ,
161+ extra_parameters = None ,
162+ ) -> Any :
163+ """Send command to the device.
164+
165+ This is overridden to raise an exception on unknown methods.
166+ """
167+ res = super ().send (
168+ command , parameters , retry_count , extra_parameters = extra_parameters
169+ )
170+ if res == "unknown_method" :
171+ raise UnsupportedFeatureException (
172+ f"Command { command } is not supported by the device"
173+ )
174+ return res
146175
147176 @command ()
148177 def start (self ):
@@ -335,13 +364,9 @@ def manual_control(
335364 self .send ("app_rc_move" , [params ])
336365
337366 @command ()
338- def status (self ) -> VacuumStatus :
367+ def status (self ) -> DeviceStatus :
339368 """Return status of the vacuum."""
340- status = self .vacuum_status ()
341- status .embed ("consumables" , self .consumable_status ())
342- status .embed ("cleaning_history" , self .clean_history ())
343- status .embed ("dnd" , self .dnd_status ())
344- return status
369+ return self ._status_helper .status ()
345370
346371 @command ()
347372 def vacuum_status (self ) -> VacuumStatus :
@@ -382,7 +407,7 @@ def get_maps(self) -> MapList:
382407 self ._maps = MapList (self .send ("get_multi_maps_list" )[0 ])
383408 return self ._maps
384409
385- def _map_enum (self ) -> Optional [enum . Enum ]:
410+ def _map_enum (self ) -> Optional [Type [ Enum ] ]:
386411 """Enum of the available map names."""
387412 if self ._map_enum_cache is not None :
388413 return self ._map_enum_cache
@@ -508,9 +533,7 @@ def last_clean_details(self) -> Optional[CleaningDetails]:
508533 @command (
509534 click .argument ("id_" , type = int , metavar = "ID" ),
510535 )
511- def clean_details (
512- self , id_ : int
513- ) -> Union [List [CleaningDetails ], Optional [CleaningDetails ]]:
536+ def clean_details (self , id_ : int ) -> Optional [CleaningDetails ]:
514537 """Return details about specific cleaning."""
515538 details = self .send ("get_clean_record" , [id_ ])
516539
@@ -583,7 +606,7 @@ def update_timer(self, timer_id: str, mode: TimerState):
583606 return self .send ("upd_timer" , [timer_id , mode .value ])
584607
585608 @command ()
586- def dnd_status (self ):
609+ def dnd_status (self ) -> DNDStatus :
587610 """Returns do-not-disturb status."""
588611 # {'result': [{'enabled': 1, 'start_minute': 0, 'end_minute': 0,
589612 # 'start_hour': 22, 'end_hour': 8}], 'id': 1}
@@ -760,7 +783,7 @@ def configure_wifi(self, ssid, password, uid=0, timezone=None):
760783 return super ().configure_wifi (ssid , password , uid , extra_params )
761784
762785 @command ()
763- def carpet_mode (self ):
786+ def carpet_mode (self ) -> CarpetModeStatus :
764787 """Get carpet mode settings."""
765788 return CarpetModeStatus (self .send ("get_carpet_mode" )[0 ])
766789
@@ -975,28 +998,19 @@ def set_child_lock(self, lock: bool) -> bool:
975998 """Set child lock setting."""
976999 return self .send ("set_child_lock_status" , {"lock_status" : int (lock )})[0 ] == "ok"
9771000
978- def _verify_mop_dryer_supported (self ) -> None :
979- """Checks if model supports mop dryer add-on."""
980- # dryer add-on is only supported by following models
981- if self .model not in [ROCKROBO_S7 , ROCKROBO_S7_MAXV ]:
982- raise UnsupportedFeatureException ("Dryer not supported by %s" , self .model )
983-
9841001 @command ()
9851002 def mop_dryer_settings (self ) -> MopDryerSettings :
9861003 """Get mop dryer settings."""
987- self ._verify_mop_dryer_supported ()
9881004 return MopDryerSettings (self .send ("app_get_dryer_setting" ))
9891005
9901006 @command (click .argument ("enabled" , type = bool ))
9911007 def set_mop_dryer_enabled (self , enabled : bool ) -> bool :
9921008 """Set mop dryer add-on enabled."""
993- self ._verify_mop_dryer_supported ()
9941009 return self .send ("app_set_dryer_setting" , {"status" : int (enabled )})[0 ] == "ok"
9951010
9961011 @command (click .argument ("dry_time" , type = int ))
9971012 def set_mop_dryer_dry_time (self , dry_time_seconds : int ) -> bool :
9981013 """Set mop dryer add-on dry time."""
999- self ._verify_mop_dryer_supported ()
10001014 return (
10011015 self .send ("app_set_dryer_setting" , {"on" : {"dry_time" : dry_time_seconds }})[
10021016 0
@@ -1008,14 +1022,12 @@ def set_mop_dryer_dry_time(self, dry_time_seconds: int) -> bool:
10081022 @action (name = "Start mop drying" , icon = "mdi:tumble-dryer" )
10091023 def start_mop_drying (self ) -> bool :
10101024 """Start mop drying."""
1011- self ._verify_mop_dryer_supported ()
10121025 return self .send ("app_set_dryer_status" , {"status" : 1 })[0 ] == "ok"
10131026
10141027 @command ()
10151028 @action (name = "Stop mop drying" , icon = "mdi:tumble-dryer" )
10161029 def stop_mop_drying (self ) -> bool :
10171030 """Stop mop drying."""
1018- self ._verify_mop_dryer_supported ()
10191031 return self .send ("app_set_dryer_status" , {"status" : 0 })[0 ] == "ok"
10201032
10211033 @command ()
0 commit comments