6
6
7
7
import logging
8
8
from collections .abc import Callable
9
- from typing import Any , TypeVar
9
+ from typing import TypeVar
10
10
11
11
from roborock .containers import HomeDataDevice , NetworkInfo , RoborockBase , UserData
12
12
from roborock .exceptions import RoborockException
13
13
from roborock .mqtt .session import MqttParams , MqttSession
14
14
from roborock .protocols .v1_protocol import (
15
- CommandType ,
16
- ParamsType ,
17
15
SecurityData ,
18
- create_mqtt_payload_encoder ,
19
16
create_security_data ,
20
- decode_rpc_response ,
21
- encode_local_payload ,
22
17
)
23
18
from roborock .roborock_message import RoborockMessage
24
19
from roborock .roborock_typing import RoborockCommand
25
20
26
21
from .local_channel import LocalChannel , LocalSession , create_local_session
27
22
from .mqtt_channel import MqttChannel
23
+ from .v1_rpc_channel import V1RpcChannel , create_combined_rpc_channel , create_mqtt_rpc_channel
28
24
29
25
_LOGGER = logging .getLogger (__name__ )
30
26
@@ -58,9 +54,10 @@ def __init__(
58
54
"""
59
55
self ._device_uid = device_uid
60
56
self ._mqtt_channel = mqtt_channel
61
- self ._mqtt_payload_encoder = create_mqtt_payload_encoder ( security_data )
57
+ self ._mqtt_rpc_channel = create_mqtt_rpc_channel ( mqtt_channel , security_data )
62
58
self ._local_session = local_session
63
59
self ._local_channel : LocalChannel | None = None
60
+ self ._combined_rpc_channel : V1RpcChannel | None = None
64
61
self ._mqtt_unsub : Callable [[], None ] | None = None
65
62
self ._local_unsub : Callable [[], None ] | None = None
66
63
self ._callback : Callable [[RoborockMessage ], None ] | None = None
@@ -76,6 +73,16 @@ def is_mqtt_connected(self) -> bool:
76
73
"""Return whether MQTT connection is available."""
77
74
return self ._mqtt_unsub is not None
78
75
76
+ @property
77
+ def rpc_channel (self ) -> V1RpcChannel :
78
+ """Return the combined RPC channel prefers local with a fallback to MQTT."""
79
+ return self ._combined_rpc_channel or self ._mqtt_rpc_channel
80
+
81
+ @property
82
+ def mqtt_rpc_channel (self ) -> V1RpcChannel :
83
+ """Return the MQTT RPC channel."""
84
+ return self ._mqtt_rpc_channel
85
+
79
86
async def subscribe (self , callback : Callable [[RoborockMessage ], None ]) -> Callable [[], None ]:
80
87
"""Subscribe to all messages from the device.
81
88
@@ -119,7 +126,9 @@ async def _get_networking_info(self) -> NetworkInfo:
119
126
This is a cloud only command used to get the local device's IP address.
120
127
"""
121
128
try :
122
- return await self ._send_mqtt_decoded_command (RoborockCommand .GET_NETWORK_INFO , response_type = NetworkInfo )
129
+ return await self ._mqtt_rpc_channel .send_command (
130
+ RoborockCommand .GET_NETWORK_INFO , response_type = NetworkInfo
131
+ )
123
132
except RoborockException as e :
124
133
raise RoborockException (f"Network info failed for device { self ._device_uid } " ) from e
125
134
@@ -136,59 +145,9 @@ async def _local_connect(self) -> Callable[[], None]:
136
145
except RoborockException as e :
137
146
self ._local_channel = None
138
147
raise RoborockException (f"Error connecting to local device { self ._device_uid } : { e } " ) from e
139
-
148
+ self . _combined_rpc_channel = create_combined_rpc_channel ( self . _local_channel , self . _mqtt_rpc_channel )
140
149
return await self ._local_channel .subscribe (self ._on_local_message )
141
150
142
- async def send_decoded_command (
143
- self ,
144
- method : CommandType ,
145
- * ,
146
- response_type : type [_T ],
147
- params : ParamsType = None ,
148
- ) -> _T :
149
- """Send a command using the best available transport.
150
-
151
- Will prefer local connection if available, falling back to MQTT.
152
- """
153
- connection = "local" if self .is_local_connected else "mqtt"
154
- _LOGGER .debug ("Sending command (%s): %s, params=%s" , connection , method , params )
155
- if self ._local_channel :
156
- return await self ._send_local_decoded_command (method , response_type = response_type , params = params )
157
- return await self ._send_mqtt_decoded_command (method , response_type = response_type , params = params )
158
-
159
- async def _send_mqtt_raw_command (self , method : CommandType , params : ParamsType | None = None ) -> dict [str , Any ]:
160
- """Send a raw command and return a raw unparsed response."""
161
- message = self ._mqtt_payload_encoder (method , params )
162
- _LOGGER .debug ("Sending MQTT message for device %s: %s" , self ._device_uid , message )
163
- response = await self ._mqtt_channel .send_command (message )
164
- return decode_rpc_response (response )
165
-
166
- async def _send_mqtt_decoded_command (
167
- self , method : CommandType , * , response_type : type [_T ], params : ParamsType | None = None
168
- ) -> _T :
169
- """Send a command over MQTT and decode the response."""
170
- decoded_response = await self ._send_mqtt_raw_command (method , params )
171
- return response_type .from_dict (decoded_response )
172
-
173
- async def _send_local_raw_command (self , method : CommandType , params : ParamsType | None = None ) -> dict [str , Any ]:
174
- """Send a raw command over local connection."""
175
- if not self ._local_channel :
176
- raise RoborockException ("Local channel is not connected" )
177
-
178
- message = encode_local_payload (method , params )
179
- _LOGGER .debug ("Sending local message for device %s: %s" , self ._device_uid , message )
180
- response = await self ._local_channel .send_command (message )
181
- return decode_rpc_response (response )
182
-
183
- async def _send_local_decoded_command (
184
- self , method : CommandType , * , response_type : type [_T ], params : ParamsType | None = None
185
- ) -> _T :
186
- """Send a command over local connection and decode the response."""
187
- if not self ._local_channel :
188
- raise RoborockException ("Local channel is not connected" )
189
- decoded_response = await self ._send_local_raw_command (method , params )
190
- return response_type .from_dict (decoded_response )
191
-
192
151
def _on_mqtt_message (self , message : RoborockMessage ) -> None :
193
152
"""Handle incoming MQTT messages."""
194
153
_LOGGER .debug ("V1Channel received MQTT message from device %s: %s" , self ._device_uid , message )
0 commit comments