4
4
import math
5
5
import struct
6
6
import time
7
- from abc import ABC
7
+ from abc import ABC , abstractmethod
8
8
from collections .abc import Callable , Coroutine
9
9
from typing import Any , TypeVar , final
10
10
78
78
EVICT_TIME = 60
79
79
80
80
81
+ _SendCommandT = Callable [[RoborockCommand | str , list | dict | int | None ], Any ]
82
+
83
+
81
84
class AttributeCache :
82
- def __init__ (self , attribute : RoborockAttribute , api : RoborockClient ):
85
+ def __init__ (self , attribute : RoborockAttribute , loop : asyncio . AbstractEventLoop , send_command : _SendCommandT ):
83
86
self .attribute = attribute
84
- self .api = api
87
+ self ._send_command = send_command
85
88
self .attribute = attribute
86
- self .task = RepeatableTask (self . api . event_loop , self ._async_value , EVICT_TIME )
89
+ self .task = RepeatableTask (loop , self ._async_value , EVICT_TIME )
87
90
self ._value : Any = None
88
91
self ._mutex = asyncio .Lock ()
89
92
self .unsupported : bool = False
@@ -96,7 +99,7 @@ async def _async_value(self):
96
99
if self .unsupported :
97
100
return None
98
101
try :
99
- self ._value = await self .api . _send_command (self .attribute .get_command )
102
+ self ._value = await self ._send_command (self .attribute .get_command , None )
100
103
except UnknownMethodError as err :
101
104
# Limit the amount of times we call unsupported methods
102
105
self .unsupported = True
@@ -115,21 +118,21 @@ def stop(self):
115
118
async def update_value (self , params ) -> None :
116
119
if self .attribute .set_command is None :
117
120
raise RoborockException (f"{ self .attribute .attribute } have no set command" )
118
- response = await self .api . _send_command (self .attribute .set_command , params )
121
+ response = await self ._send_command (self .attribute .set_command , params )
119
122
await self ._async_value ()
120
123
return response
121
124
122
125
async def add_value (self , params ):
123
126
if self .attribute .add_command is None :
124
127
raise RoborockException (f"{ self .attribute .attribute } have no add command" )
125
- response = await self .api . _send_command (self .attribute .add_command , params )
128
+ response = await self ._send_command (self .attribute .add_command , params )
126
129
await self ._async_value ()
127
130
return response
128
131
129
132
async def close_value (self , params = None ) -> None :
130
133
if self .attribute .close_command is None :
131
134
raise RoborockException (f"{ self .attribute .attribute } have no close command" )
132
- response = await self .api . _send_command (self .attribute .close_command , params )
135
+ response = await self ._send_command (self .attribute .close_command , params )
133
136
await self ._async_value ()
134
137
return response
135
138
@@ -153,7 +156,8 @@ def __init__(self, device_info: DeviceData, endpoint: str):
153
156
super ().__init__ (device_info )
154
157
self ._status_type : type [Status ] = ModelStatus .get (device_info .model , S7MaxVStatus )
155
158
self .cache : dict [CacheableAttribute , AttributeCache ] = {
156
- cacheable_attribute : AttributeCache (attr , self ) for cacheable_attribute , attr in get_cache_map ().items ()
159
+ cacheable_attribute : AttributeCache (attr , self .event_loop , self ._send_command )
160
+ for cacheable_attribute , attr in get_cache_map ().items ()
157
161
}
158
162
if device_info .device .duid not in self ._listeners :
159
163
self ._listeners [device_info .device .duid ] = ListenerModel ({}, self .cache )
@@ -364,6 +368,14 @@ def _get_payload(
364
368
)
365
369
return request_id , timestamp , payload
366
370
371
+ @abstractmethod
372
+ async def _send_command (
373
+ self ,
374
+ method : RoborockCommand | str ,
375
+ params : list | dict | int | None = None ,
376
+ ) -> Any :
377
+ """Send a command to the Roborock device."""
378
+
367
379
def on_message_received (self , messages : list [RoborockMessage ]) -> None :
368
380
try :
369
381
self ._last_device_msg_in = time .monotonic ()
0 commit comments