pymammotion 0.2.62__py3-none-any.whl → 0.5.51__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pymammotion might be problematic. Click here for more details.
- pymammotion/__init__.py +9 -6
- pymammotion/aliyun/client.py +235 -0
- pymammotion/aliyun/cloud_gateway.py +320 -69
- pymammotion/aliyun/model/aep_response.py +1 -2
- pymammotion/aliyun/model/dev_by_account_response.py +170 -23
- pymammotion/aliyun/model/login_by_oauth_response.py +2 -3
- pymammotion/aliyun/model/regions_response.py +3 -3
- pymammotion/aliyun/model/session_by_authcode_response.py +2 -2
- pymammotion/aliyun/model/thing_response.py +12 -0
- pymammotion/aliyun/regions.py +62 -0
- pymammotion/aliyun/tea/core.py +297 -0
- pymammotion/bluetooth/ble.py +11 -15
- pymammotion/bluetooth/ble_message.py +389 -106
- pymammotion/bluetooth/model/atomic_integer.py +54 -0
- pymammotion/const.py +3 -0
- pymammotion/data/model/__init__.py +1 -2
- pymammotion/data/model/device.py +92 -240
- pymammotion/data/model/device_config.py +10 -24
- pymammotion/data/model/device_info.py +35 -0
- pymammotion/data/model/device_limits.py +49 -0
- pymammotion/data/model/enums.py +12 -2
- pymammotion/data/model/errors.py +12 -0
- pymammotion/data/model/events.py +14 -0
- pymammotion/data/model/generate_geojson.py +521 -0
- pymammotion/data/model/generate_route_information.py +3 -4
- pymammotion/data/model/hash_list.py +384 -48
- pymammotion/data/model/location.py +4 -4
- pymammotion/data/model/mowing_modes.py +24 -1
- pymammotion/data/model/raw_data.py +215 -0
- pymammotion/data/model/region_data.py +10 -11
- pymammotion/data/model/report_info.py +62 -6
- pymammotion/data/model/work.py +27 -0
- pymammotion/data/mower_state_manager.py +316 -0
- pymammotion/data/mqtt/event.py +73 -28
- pymammotion/data/mqtt/mammotion_properties.py +257 -0
- pymammotion/data/mqtt/properties.py +93 -78
- pymammotion/data/mqtt/status.py +18 -17
- pymammotion/event/event.py +32 -8
- pymammotion/homeassistant/__init__.py +3 -0
- pymammotion/homeassistant/mower_api.py +484 -0
- pymammotion/homeassistant/rtk_api.py +54 -0
- pymammotion/http/__init__.py +0 -0
- pymammotion/http/encryption.py +220 -0
- pymammotion/http/http.py +652 -44
- pymammotion/http/model/__init__.py +0 -0
- pymammotion/{aliyun/model/stream_subscription_response.py → http/model/camera_stream.py} +14 -2
- pymammotion/http/model/http.py +160 -9
- pymammotion/http/model/response_factory.py +61 -0
- pymammotion/http/model/rtk.py +16 -0
- pymammotion/mammotion/commands/abstract_message.py +7 -5
- pymammotion/mammotion/commands/mammotion_command.py +32 -3
- pymammotion/mammotion/commands/messages/basestation.py +43 -0
- pymammotion/mammotion/commands/messages/driver.py +61 -29
- pymammotion/mammotion/commands/messages/media.py +68 -15
- pymammotion/mammotion/commands/messages/navigation.py +61 -25
- pymammotion/mammotion/commands/messages/network.py +93 -100
- pymammotion/mammotion/commands/messages/ota.py +18 -18
- pymammotion/mammotion/commands/messages/system.py +97 -72
- pymammotion/mammotion/commands/messages/video.py +17 -12
- pymammotion/mammotion/devices/__init__.py +27 -3
- pymammotion/mammotion/devices/base.py +50 -127
- pymammotion/mammotion/devices/mammotion.py +447 -212
- pymammotion/mammotion/devices/mammotion_bluetooth.py +105 -60
- pymammotion/mammotion/devices/mammotion_cloud.py +157 -105
- pymammotion/mammotion/devices/mammotion_mower_ble.py +49 -0
- pymammotion/mammotion/devices/mammotion_mower_cloud.py +39 -0
- pymammotion/mammotion/devices/managers/managers.py +81 -0
- pymammotion/mammotion/devices/mower_device.py +124 -0
- pymammotion/mammotion/devices/mower_manager.py +107 -0
- pymammotion/mammotion/devices/rtk_ble.py +89 -0
- pymammotion/mammotion/devices/rtk_cloud.py +113 -0
- pymammotion/mammotion/devices/rtk_device.py +50 -0
- pymammotion/mammotion/devices/rtk_manager.py +122 -0
- pymammotion/mqtt/__init__.py +2 -1
- pymammotion/mqtt/aliyun_mqtt.py +232 -0
- pymammotion/mqtt/linkkit/__init__.py +5 -0
- pymammotion/mqtt/linkkit/h2client.py +585 -0
- pymammotion/mqtt/linkkit/linkkit.py +3023 -0
- pymammotion/mqtt/mammotion_mqtt.py +176 -169
- pymammotion/mqtt/mqtt_models.py +66 -0
- pymammotion/proto/__init__.py +4839 -4
- pymammotion/proto/basestation.proto +8 -0
- pymammotion/proto/basestation_pb2.py +11 -9
- pymammotion/proto/basestation_pb2.pyi +16 -2
- pymammotion/proto/dev_net.proto +79 -55
- pymammotion/proto/dev_net_pb2.py +60 -56
- pymammotion/proto/dev_net_pb2.pyi +49 -6
- pymammotion/proto/luba_msg.proto +2 -1
- pymammotion/proto/luba_msg_pb2.py +6 -6
- pymammotion/proto/luba_msg_pb2.pyi +1 -0
- pymammotion/proto/luba_mul.proto +62 -1
- pymammotion/proto/luba_mul_pb2.py +38 -22
- pymammotion/proto/luba_mul_pb2.pyi +94 -7
- pymammotion/proto/mctrl_driver.proto +44 -4
- pymammotion/proto/mctrl_driver_pb2.py +26 -14
- pymammotion/proto/mctrl_driver_pb2.pyi +66 -11
- pymammotion/proto/mctrl_nav.proto +97 -51
- pymammotion/proto/mctrl_nav_pb2.py +75 -67
- pymammotion/proto/mctrl_nav_pb2.pyi +142 -56
- pymammotion/proto/mctrl_ota.proto +40 -2
- pymammotion/proto/mctrl_ota_pb2.py +23 -13
- pymammotion/proto/mctrl_ota_pb2.pyi +67 -4
- pymammotion/proto/mctrl_pept.proto +8 -3
- pymammotion/proto/mctrl_pept_pb2.py +8 -6
- pymammotion/proto/mctrl_pept_pb2.pyi +14 -6
- pymammotion/proto/mctrl_sys.proto +325 -86
- pymammotion/proto/mctrl_sys_pb2.py +162 -98
- pymammotion/proto/mctrl_sys_pb2.pyi +451 -25
- pymammotion/proto/message_pool.py +3 -0
- pymammotion/proto/py.typed +0 -0
- pymammotion/utility/constant/device_constant.py +65 -21
- pymammotion/utility/datatype_converter.py +13 -12
- pymammotion/utility/device_config.py +755 -0
- pymammotion/utility/device_type.py +218 -21
- pymammotion/utility/map.py +238 -51
- pymammotion/utility/mur_mur_hash.py +159 -0
- {pymammotion-0.2.62.dist-info → pymammotion-0.5.51.dist-info}/METADATA +27 -31
- pymammotion-0.5.51.dist-info/RECORD +152 -0
- {pymammotion-0.2.62.dist-info → pymammotion-0.5.51.dist-info}/WHEEL +1 -1
- pymammotion/aliyun/cloud_service.py +0 -65
- pymammotion/data/model/plan.py +0 -58
- pymammotion/data/state_manager.py +0 -130
- pymammotion/proto/basestation.py +0 -59
- pymammotion/proto/common.py +0 -12
- pymammotion/proto/dev_net.py +0 -381
- pymammotion/proto/luba_msg.py +0 -81
- pymammotion/proto/luba_mul.py +0 -76
- pymammotion/proto/mctrl_driver.py +0 -100
- pymammotion/proto/mctrl_nav.py +0 -660
- pymammotion/proto/mctrl_ota.py +0 -48
- pymammotion/proto/mctrl_pept.py +0 -41
- pymammotion/proto/mctrl_sys.py +0 -574
- pymammotion-0.2.62.dist-info/RECORD +0 -125
- /pymammotion/{http/_init_.py → bluetooth/model/__init__.py} +0 -0
- {pymammotion-0.2.62.dist-info → pymammotion-0.5.51.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
from collections.abc import Awaitable, Callable
|
|
2
3
|
import logging
|
|
3
|
-
|
|
4
|
+
import time
|
|
5
|
+
from typing import Any
|
|
4
6
|
from uuid import UUID
|
|
5
7
|
|
|
6
|
-
import
|
|
8
|
+
import betterproto2
|
|
7
9
|
from bleak import BleakGATTCharacteristic, BleakGATTServiceCollection, BLEDevice
|
|
8
10
|
from bleak.exc import BleakDBusError
|
|
9
11
|
from bleak_retry_connector import (
|
|
@@ -13,12 +15,12 @@ from bleak_retry_connector import (
|
|
|
13
15
|
establish_connection,
|
|
14
16
|
)
|
|
15
17
|
|
|
18
|
+
from pymammotion.aliyun.model.dev_by_account_response import Device
|
|
16
19
|
from pymammotion.bluetooth import BleMessage
|
|
17
|
-
from pymammotion.data.
|
|
20
|
+
from pymammotion.data.mower_state_manager import MowerStateManager
|
|
18
21
|
from pymammotion.mammotion.commands.mammotion_command import MammotionCommand
|
|
19
22
|
from pymammotion.mammotion.devices.base import MammotionBaseDevice
|
|
20
|
-
from pymammotion.proto import
|
|
21
|
-
from pymammotion.proto.luba_msg import LubaMsg
|
|
23
|
+
from pymammotion.proto import LubaMsg
|
|
22
24
|
|
|
23
25
|
DBUS_ERROR_BACKOFF_TIME = 0.25
|
|
24
26
|
|
|
@@ -69,33 +71,61 @@ async def _handle_retry(fut: asyncio.Future[None], func, command: bytes) -> None
|
|
|
69
71
|
class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
70
72
|
"""Base class for Mammotion BLE devices."""
|
|
71
73
|
|
|
72
|
-
def __init__(
|
|
74
|
+
def __init__(
|
|
75
|
+
self,
|
|
76
|
+
state_manager: MowerStateManager,
|
|
77
|
+
cloud_device: Device,
|
|
78
|
+
device: BLEDevice,
|
|
79
|
+
interface: int = 0,
|
|
80
|
+
**kwargs: Any,
|
|
81
|
+
) -> None:
|
|
73
82
|
"""Initialize MammotionBaseBLEDevice."""
|
|
74
|
-
super().__init__(
|
|
83
|
+
super().__init__(state_manager, cloud_device)
|
|
84
|
+
self.command_sent_time = 0
|
|
75
85
|
self._disconnect_strategy = True
|
|
76
86
|
self._ble_sync_task = None
|
|
77
87
|
self._prev_notification = None
|
|
78
88
|
self._interface = f"hci{interface}"
|
|
79
|
-
self.
|
|
89
|
+
self.ble_device = device
|
|
80
90
|
self._client: BleakClientWithServiceCache | None = None
|
|
81
91
|
self._read_char: BleakGATTCharacteristic | int | str | UUID = 0
|
|
82
92
|
self._write_char: BleakGATTCharacteristic | int | str | UUID = 0
|
|
83
93
|
self._disconnect_timer: asyncio.TimerHandle | None = None
|
|
84
94
|
self._message: BleMessage | None = None
|
|
85
|
-
self._commands: MammotionCommand = MammotionCommand(device.name)
|
|
95
|
+
self._commands: MammotionCommand = MammotionCommand(device.name, 1)
|
|
96
|
+
self.command_queue = asyncio.Queue()
|
|
86
97
|
self._expected_disconnect = False
|
|
87
98
|
self._connect_lock = asyncio.Lock()
|
|
88
99
|
self._operation_lock = asyncio.Lock()
|
|
89
100
|
self._key: str | None = None
|
|
101
|
+
self._cloud_device = cloud_device
|
|
90
102
|
self.set_queue_callback(self.queue_command)
|
|
103
|
+
loop = asyncio.get_event_loop()
|
|
104
|
+
loop.create_task(self.process_queue())
|
|
105
|
+
|
|
106
|
+
def __del__(self) -> None:
|
|
107
|
+
"""Cleanup."""
|
|
108
|
+
if self._disconnect_timer:
|
|
109
|
+
self._disconnect_timer.cancel()
|
|
110
|
+
if self._ble_sync_task:
|
|
111
|
+
self._ble_sync_task.cancel()
|
|
112
|
+
|
|
113
|
+
self._state_manager.ble_queue_command_callback.remove_subscribers(self.queue_command)
|
|
114
|
+
|
|
115
|
+
def set_notification_callback(self, func: Callable[[tuple[str, Any | None]], Awaitable[None]]) -> None:
|
|
116
|
+
self._state_manager.ble_on_notification_callback.add_subscribers(func)
|
|
117
|
+
|
|
118
|
+
def set_queue_callback(self, func: Callable[[str, dict[str, Any]], Awaitable[None]]) -> None:
|
|
119
|
+
self._state_manager.ble_queue_command_callback.add_subscribers(func)
|
|
91
120
|
|
|
92
121
|
def update_device(self, device: BLEDevice) -> None:
|
|
93
122
|
"""Update the BLE device."""
|
|
94
|
-
self.
|
|
123
|
+
self.ble_device = device
|
|
95
124
|
|
|
96
125
|
async def _ble_sync(self) -> None:
|
|
97
|
-
|
|
98
|
-
|
|
126
|
+
if self._client is not None and self._client.is_connected:
|
|
127
|
+
command_bytes = self._commands.send_todev_ble_sync(2)
|
|
128
|
+
await self._message.post_custom_data_bytes(command_bytes)
|
|
99
129
|
|
|
100
130
|
async def run_periodic_sync_task(self) -> None:
|
|
101
131
|
"""Send ble sync to robot."""
|
|
@@ -113,11 +143,37 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
|
113
143
|
|
|
114
144
|
async def stop(self) -> None:
|
|
115
145
|
"""Stop all tasks and disconnect."""
|
|
116
|
-
self._ble_sync_task
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
146
|
+
if self._ble_sync_task:
|
|
147
|
+
self._ble_sync_task.cancel()
|
|
148
|
+
if self._client is not None and self._client.is_connected:
|
|
149
|
+
await self._client.disconnect()
|
|
150
|
+
|
|
151
|
+
async def queue_command(self, key: str, **kwargs: Any) -> None:
|
|
152
|
+
# Create a future to hold the result
|
|
153
|
+
_LOGGER.debug("Queueing command: %s", key)
|
|
154
|
+
future = asyncio.Future()
|
|
155
|
+
# Put the command in the queue as a tuple (key, command, future)
|
|
156
|
+
command_bytes = getattr(self._commands, key)(**kwargs)
|
|
157
|
+
await self.command_queue.put((key, command_bytes, future))
|
|
158
|
+
# Wait for the future to be resolved
|
|
159
|
+
await future
|
|
160
|
+
# return await self._send_command_with_args(key, **kwargs)
|
|
161
|
+
|
|
162
|
+
async def process_queue(self) -> None:
|
|
163
|
+
while True:
|
|
164
|
+
# Get the next item from the queue
|
|
165
|
+
key, command, future = await self.command_queue.get()
|
|
166
|
+
try:
|
|
167
|
+
# Process the command using _execute_command_locked
|
|
168
|
+
result = await self._send_command_locked(key, command)
|
|
169
|
+
# Set the result on the future
|
|
170
|
+
future.set_result(result)
|
|
171
|
+
except Exception as ex:
|
|
172
|
+
# Set the exception on the future if something goes wrong
|
|
173
|
+
future.set_exception(ex)
|
|
174
|
+
finally:
|
|
175
|
+
# Mark the task as done
|
|
176
|
+
self.command_queue.task_done()
|
|
121
177
|
|
|
122
178
|
async def _send_command_with_args(self, key: str, **kwargs) -> bytes | None:
|
|
123
179
|
"""Send command to device and read response."""
|
|
@@ -184,15 +240,17 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
|
184
240
|
@property
|
|
185
241
|
def name(self) -> str:
|
|
186
242
|
"""Return device name."""
|
|
187
|
-
return f"{self.
|
|
243
|
+
return f"{self.ble_device.name} ({self.ble_device.address})"
|
|
188
244
|
|
|
189
245
|
@property
|
|
190
246
|
def rssi(self) -> int:
|
|
191
247
|
"""Return RSSI of device."""
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
248
|
+
return self.mower.report_data.connect.ble_rssi
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def client(self) -> BleakClientWithServiceCache | None:
|
|
252
|
+
"""Return client."""
|
|
253
|
+
return self._client
|
|
196
254
|
|
|
197
255
|
async def _ensure_connected(self) -> None:
|
|
198
256
|
"""Ensure connection to device is established."""
|
|
@@ -223,11 +281,11 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
|
223
281
|
_LOGGER.debug("%s: Connecting; RSSI: %s", self.name, self.rssi)
|
|
224
282
|
client: BleakClientWithServiceCache = await establish_connection(
|
|
225
283
|
BleakClientWithServiceCache,
|
|
226
|
-
self.
|
|
284
|
+
self.ble_device,
|
|
227
285
|
self.name,
|
|
228
286
|
self._disconnected,
|
|
229
287
|
max_attempts=10,
|
|
230
|
-
ble_device_callback=lambda: self.
|
|
288
|
+
ble_device_callback=lambda: self.ble_device,
|
|
231
289
|
)
|
|
232
290
|
_LOGGER.debug("%s: Connected; RSSI: %s", self.name, self.rssi)
|
|
233
291
|
self._client = client
|
|
@@ -255,11 +313,10 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
|
255
313
|
)
|
|
256
314
|
self._reset_disconnect_timer()
|
|
257
315
|
await self._start_notify()
|
|
258
|
-
|
|
259
|
-
await self._message.post_custom_data_bytes(command_bytes)
|
|
316
|
+
await self._ble_sync()
|
|
260
317
|
self.schedule_ble_sync()
|
|
261
318
|
|
|
262
|
-
async def _send_command_locked(self, key: str, command: bytes) ->
|
|
319
|
+
async def _send_command_locked(self, key: str, command: bytes) -> None:
|
|
263
320
|
"""Send command to device and read response."""
|
|
264
321
|
await self._ensure_connected()
|
|
265
322
|
try:
|
|
@@ -284,73 +341,60 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
|
284
341
|
|
|
285
342
|
async def _notification_handler(self, _sender: BleakGATTCharacteristic, data: bytearray) -> None:
|
|
286
343
|
"""Handle notification responses."""
|
|
344
|
+
|
|
287
345
|
if self._message is None:
|
|
288
346
|
return
|
|
289
347
|
result = self._message.parseNotification(data)
|
|
290
348
|
if result == 0:
|
|
291
349
|
data = await self._message.parseBlufiNotifyData(True)
|
|
292
|
-
self.
|
|
293
|
-
|
|
350
|
+
self._message.clear_notification()
|
|
351
|
+
try:
|
|
352
|
+
self._update_raw_data(data)
|
|
353
|
+
except (KeyError, ValueError, IndexError, UnicodeDecodeError):
|
|
354
|
+
_LOGGER.exception("Error parsing message %s", data)
|
|
355
|
+
data = b""
|
|
356
|
+
|
|
294
357
|
_LOGGER.debug("%s: Received notification: %s", self.name, data)
|
|
295
358
|
else:
|
|
296
359
|
return
|
|
360
|
+
|
|
297
361
|
new_msg = LubaMsg().parse(data)
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
362
|
+
res = betterproto2.which_one_of(new_msg, "LubaSubMsg")
|
|
363
|
+
if res[0] == "net":
|
|
364
|
+
if new_msg.net.todev_ble_sync != 0 or new_msg.net.toapp_wifi_iot_status is not None:
|
|
365
|
+
if new_msg.net.toapp_wifi_iot_status is not None and self._commands.get_device_product_key() == "":
|
|
301
366
|
self._commands.set_device_product_key(new_msg.net.toapp_wifi_iot_status.productkey)
|
|
302
367
|
|
|
303
|
-
|
|
368
|
+
await self._state_manager.notification(new_msg)
|
|
304
369
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
self._notify_future.set_result(data)
|
|
370
|
+
if self._execute_timed_disconnect is None:
|
|
371
|
+
await self._execute_forced_disconnect()
|
|
308
372
|
|
|
309
373
|
self._reset_disconnect_timer()
|
|
310
|
-
await self._state_manager.notification(new_msg)
|
|
311
374
|
|
|
312
375
|
async def _start_notify(self) -> None:
|
|
313
376
|
"""Start notification."""
|
|
314
377
|
_LOGGER.debug("%s: Subscribe to notifications; RSSI: %s", self.name, self.rssi)
|
|
315
378
|
await self._client.start_notify(self._read_char, self._notification_handler)
|
|
316
379
|
|
|
317
|
-
async def _execute_command_locked(self, key: str, command: bytes) ->
|
|
380
|
+
async def _execute_command_locked(self, key: str, command: bytes) -> None:
|
|
318
381
|
"""Execute command and read response."""
|
|
319
382
|
assert self._client is not None
|
|
320
|
-
self._notify_future = self.loop.create_future()
|
|
321
|
-
self._key = key
|
|
322
383
|
_LOGGER.debug("%s: Sending command: %s", self.name, key)
|
|
323
384
|
await self._message.post_custom_data_bytes(command)
|
|
324
|
-
|
|
325
|
-
timeout = 2
|
|
326
|
-
timeout_handle = self.loop.call_at(self.loop.time() + timeout, _handle_timeout, self._notify_future)
|
|
327
|
-
timeout_expired = False
|
|
328
|
-
try:
|
|
329
|
-
notify_msg = await self._notify_future
|
|
330
|
-
except asyncio.TimeoutError:
|
|
331
|
-
timeout_expired = True
|
|
332
|
-
notify_msg = b""
|
|
333
|
-
finally:
|
|
334
|
-
if not timeout_expired:
|
|
335
|
-
timeout_handle.cancel()
|
|
336
|
-
self._notify_future = None
|
|
337
|
-
|
|
338
|
-
_LOGGER.debug("%s: Notification received: %s", self.name, notify_msg.hex())
|
|
339
|
-
return notify_msg
|
|
385
|
+
self.command_sent_time = time.time()
|
|
340
386
|
|
|
341
387
|
def get_address(self) -> str:
|
|
342
388
|
"""Return address of device."""
|
|
343
|
-
return self.
|
|
389
|
+
return self.ble_device.address
|
|
344
390
|
|
|
345
391
|
def _resolve_characteristics(self, services: BleakGATTServiceCollection) -> None:
|
|
346
392
|
"""Resolve characteristics."""
|
|
347
393
|
self._read_char = services.get_characteristic(READ_CHAR_UUID)
|
|
348
394
|
if not self._read_char:
|
|
349
|
-
self._read_char = READ_CHAR_UUID
|
|
350
395
|
_LOGGER.error(CharacteristicMissingError(READ_CHAR_UUID))
|
|
351
396
|
self._write_char = services.get_characteristic(WRITE_CHAR_UUID)
|
|
352
397
|
if not self._write_char:
|
|
353
|
-
self._write_char = WRITE_CHAR_UUID
|
|
354
398
|
_LOGGER.error(CharacteristicMissingError(WRITE_CHAR_UUID))
|
|
355
399
|
|
|
356
400
|
def _reset_disconnect_timer(self) -> None:
|
|
@@ -370,6 +414,7 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
|
370
414
|
self.rssi,
|
|
371
415
|
)
|
|
372
416
|
self._cancel_disconnect_timer()
|
|
417
|
+
self._client = None
|
|
373
418
|
|
|
374
419
|
def _disconnect_from_timer(self) -> None:
|
|
375
420
|
"""Disconnect from device."""
|
|
@@ -448,5 +493,5 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
|
448
493
|
_LOGGER.debug("%s: Disconnect completed successfully", self.name)
|
|
449
494
|
self._client = None
|
|
450
495
|
|
|
451
|
-
def set_disconnect_strategy(self, disconnect: bool) -> None:
|
|
496
|
+
def set_disconnect_strategy(self, *, disconnect: bool) -> None:
|
|
452
497
|
self._disconnect_strategy = disconnect
|