pymammotion 0.2.4__tar.gz → 0.2.6__tar.gz

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.

Files changed (117) hide show
  1. {pymammotion-0.2.4 → pymammotion-0.2.6}/PKG-INFO +1 -1
  2. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/cloud_gateway.py +8 -3
  3. pymammotion-0.2.6/pymammotion/data/model/account.py +8 -0
  4. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/mammotion_command.py +2 -1
  5. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/devices/mammotion.py +100 -37
  6. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mqtt/mammotion_mqtt.py +4 -4
  7. {pymammotion-0.2.4 → pymammotion-0.2.6}/pyproject.toml +3 -3
  8. pymammotion-0.2.4/pymammotion/data/model/account.py +0 -8
  9. {pymammotion-0.2.4 → pymammotion-0.2.6}/LICENSE +0 -0
  10. {pymammotion-0.2.4 → pymammotion-0.2.6}/README.md +0 -0
  11. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/__init__.py +0 -0
  12. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/__init__.py +0 -0
  13. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/cloud_service.py +0 -0
  14. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/dataclass/aep_response.py +0 -0
  15. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/dataclass/connect_response.py +0 -0
  16. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/dataclass/dev_by_account_response.py +0 -0
  17. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/dataclass/login_by_oauth_response.py +0 -0
  18. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/dataclass/regions_response.py +0 -0
  19. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/dataclass/session_by_authcode_response.py +0 -0
  20. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/aliyun/tmp_constant.py +0 -0
  21. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/bluetooth/__init__.py +0 -0
  22. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/bluetooth/ble.py +0 -0
  23. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/bluetooth/ble_message.py +0 -0
  24. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/bluetooth/const.py +0 -0
  25. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/bluetooth/data/__init__.py +0 -0
  26. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/bluetooth/data/convert.py +0 -0
  27. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/bluetooth/data/framectrldata.py +0 -0
  28. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/bluetooth/data/notifydata.py +0 -0
  29. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/const.py +0 -0
  30. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/__init__.py +0 -0
  31. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/__init__.py +0 -0
  32. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/device.py +0 -0
  33. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/device_config.py +0 -0
  34. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/enums.py +0 -0
  35. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/excute_boarder_params.py +0 -0
  36. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/execute_boarder.py +0 -0
  37. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/generate_route_information.py +0 -0
  38. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/hash_list.py +0 -0
  39. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/location.py +0 -0
  40. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/mowing_modes.py +0 -0
  41. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/plan.py +0 -0
  42. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/rapid_state.py +0 -0
  43. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/region_data.py +0 -0
  44. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/model/report_info.py +0 -0
  45. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/mqtt/__init__.py +0 -0
  46. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/mqtt/event.py +0 -0
  47. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/mqtt/properties.py +0 -0
  48. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/mqtt/status.py +0 -0
  49. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/data/state_manager.py +0 -0
  50. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/event/__init__.py +0 -0
  51. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/event/event.py +0 -0
  52. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/http/_init_.py +0 -0
  53. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/http/http.py +0 -0
  54. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/__init__.py +0 -0
  55. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/__init__.py +0 -0
  56. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/abstract_message.py +0 -0
  57. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/messages/__init__.py +0 -0
  58. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/messages/driver.py +0 -0
  59. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/messages/media.py +0 -0
  60. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/messages/navigation.py +0 -0
  61. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/messages/network.py +0 -0
  62. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/messages/ota.py +0 -0
  63. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/messages/system.py +0 -0
  64. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/commands/messages/video.py +0 -0
  65. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/control/__init__.py +0 -0
  66. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/control/joystick.py +0 -0
  67. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mammotion/devices/__init__.py +0 -0
  68. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/mqtt/__init__.py +0 -0
  69. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/__init__.py +0 -0
  70. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/basestation.proto +0 -0
  71. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/basestation.py +0 -0
  72. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/basestation_pb2.py +0 -0
  73. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/basestation_pb2.pyi +0 -0
  74. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/common.proto +0 -0
  75. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/common.py +0 -0
  76. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/common_pb2.py +0 -0
  77. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/common_pb2.pyi +0 -0
  78. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/dev_net.proto +0 -0
  79. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/dev_net.py +0 -0
  80. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/dev_net_pb2.py +0 -0
  81. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/dev_net_pb2.pyi +0 -0
  82. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/luba_msg.proto +0 -0
  83. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/luba_msg.py +0 -0
  84. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/luba_msg_pb2.py +0 -0
  85. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/luba_msg_pb2.pyi +0 -0
  86. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/luba_mul.proto +0 -0
  87. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/luba_mul.py +0 -0
  88. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/luba_mul_pb2.py +0 -0
  89. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/luba_mul_pb2.pyi +0 -0
  90. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_driver.proto +0 -0
  91. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_driver.py +0 -0
  92. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_driver_pb2.py +0 -0
  93. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_driver_pb2.pyi +0 -0
  94. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_nav.proto +0 -0
  95. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_nav.py +0 -0
  96. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_nav_pb2.py +0 -0
  97. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_nav_pb2.pyi +0 -0
  98. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_ota.proto +0 -0
  99. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_ota.py +0 -0
  100. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_ota_pb2.py +0 -0
  101. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_ota_pb2.pyi +0 -0
  102. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_pept.proto +0 -0
  103. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_pept.py +0 -0
  104. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_pept_pb2.py +0 -0
  105. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_pept_pb2.pyi +0 -0
  106. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_sys.proto +0 -0
  107. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_sys.py +0 -0
  108. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_sys_pb2.py +0 -0
  109. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/proto/mctrl_sys_pb2.pyi +0 -0
  110. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/py.typed +0 -0
  111. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/utility/constant/__init__.py +0 -0
  112. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/utility/constant/device_constant.py +0 -0
  113. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/utility/datatype_converter.py +0 -0
  114. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/utility/device_type.py +0 -0
  115. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/utility/map.py +0 -0
  116. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/utility/periodic.py +0 -0
  117. {pymammotion-0.2.4 → pymammotion-0.2.6}/pymammotion/utility/rocker_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymammotion
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary:
5
5
  License: GNU-3.0
6
6
  Author: Michael Arthur
@@ -9,7 +9,7 @@ import random
9
9
  import string
10
10
  import time
11
11
  import uuid
12
- from logging import getLogger
12
+ from logging import getLogger, exception
13
13
 
14
14
  from aiohttp import ClientSession
15
15
  from alibabacloud_iot_api_gateway.client import Client
@@ -45,6 +45,10 @@ MOVE_HEADERS = (
45
45
  )
46
46
 
47
47
 
48
+ class SetupException(Exception):
49
+ pass
50
+
51
+
48
52
  class CloudIOTGateway:
49
53
  """Class for interacting with Aliyun Cloud IoT Gateway."""
50
54
 
@@ -522,9 +526,10 @@ class CloudIOTGateway:
522
526
  logger.error(
523
527
  "Error in sending cloud command: %s - %s",
524
528
  str(response_body_dict.get("code")),
525
- str(response_body_dict["msg"]),
529
+ str(response_body_dict.get("msg")),
526
530
  )
527
- return ""
531
+ if response_body_dict.get("code") == 29003:
532
+ raise SetupException(response_body_dict.get("code"))
528
533
 
529
534
  return message_id
530
535
 
@@ -0,0 +1,8 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class Credentials:
6
+ email: str = None
7
+ password: str = None
8
+ account_id: str = None
@@ -1,3 +1,4 @@
1
+ from pymammotion.mammotion.commands.messages.driver import MessageDriver
1
2
  from pymammotion.mammotion.commands.messages.navigation import MessageNavigation
2
3
  from pymammotion.mammotion.commands.messages.network import MessageNetwork
3
4
  from pymammotion.mammotion.commands.messages.ota import MessageOta
@@ -6,7 +7,7 @@ from pymammotion.mammotion.commands.messages.video import MessageVideo
6
7
  from pymammotion.proto import dev_net_pb2, luba_msg_pb2
7
8
 
8
9
 
9
- class MammotionCommand(MessageSystem, MessageNavigation, MessageNetwork, MessageOta, MessageVideo):
10
+ class MammotionCommand(MessageSystem, MessageNavigation, MessageNetwork, MessageOta, MessageVideo, MessageDriver):
10
11
  """MQTT commands for Luba."""
11
12
 
12
13
  def __init__(self, device_name: str) -> None:
@@ -9,6 +9,7 @@ import json
9
9
  import logging
10
10
  from abc import abstractmethod
11
11
  from enum import Enum
12
+ from functools import cache
12
13
  from typing import Any, Callable, Optional, cast
13
14
  from uuid import UUID
14
15
 
@@ -39,6 +40,7 @@ from pymammotion.mammotion.commands.mammotion_command import MammotionCommand
39
40
  from pymammotion.mqtt import MammotionMQTT
40
41
  from pymammotion.proto.luba_msg import LubaMsg
41
42
  from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck
43
+ from pymammotion.utility.rocker_util import RockerControlUtil
42
44
 
43
45
 
44
46
  class CharacteristicMissingError(Exception):
@@ -115,8 +117,10 @@ async def _handle_retry(fut: asyncio.Future[None], func, command: bytes) -> None
115
117
 
116
118
  async def _handle_retry_cloud(fut: asyncio.Future[None], func, iotId: str, command: bytes) -> None:
117
119
  """Handle a retry."""
120
+
118
121
  if not fut.done():
119
- func(iotId, command)
122
+ loop = asyncio.get_running_loop()
123
+ await loop.run_in_executor(None, func, iotId, command)
120
124
 
121
125
 
122
126
  class ConnectionPreference(Enum):
@@ -176,8 +180,9 @@ class MammotionDevices:
176
180
 
177
181
  def add_device(self, mammotion_device: MammotionMixedDeviceManager) -> None:
178
182
  exists: MammotionMixedDeviceManager | None = self.devices.get(mammotion_device.name)
179
- if not exists:
183
+ if exists is None:
180
184
  self.devices[mammotion_device.name] = mammotion_device
185
+ return
181
186
  if mammotion_device.has_cloud():
182
187
  exists.replace_cloud(mammotion_device.cloud())
183
188
  if mammotion_device.has_ble():
@@ -186,16 +191,31 @@ class MammotionDevices:
186
191
  def get_device(self, mammotion_device_name: str) -> MammotionMixedDeviceManager:
187
192
  return self.devices.get(mammotion_device_name)
188
193
 
189
- class Mammotion:
194
+ async def create_devices(ble_device: BLEDevice,
195
+ cloud_credentials: Credentials | None = None,
196
+ preference: ConnectionPreference = ConnectionPreference.BLUETOOTH):
197
+ cloud_client = await Mammotion.login(cloud_credentials.account_id or cloud_credentials.email, cloud_credentials.password)
198
+ mammotion = Mammotion(ble_device, preference)
199
+
200
+ if cloud_credentials:
201
+ await mammotion.initiate_cloud_connection(cloud_client)
202
+
203
+ return mammotion
204
+
205
+
206
+ @cache
207
+ class Mammotion(object):
190
208
  """Represents a Mammotion device."""
191
209
 
192
210
  devices = MammotionDevices()
211
+ _mammotion_mqtt: MammotionMQTT | None = None
212
+
213
+
193
214
 
194
215
  def __init__(
195
216
  self,
196
- ble_device: BLEDevice,
197
- cloud_credentials: Credentials | None = None,
198
- preference: ConnectionPreference = ConnectionPreference.BLUETOOTH,
217
+ ble_device: BLEDevice,
218
+ preference: ConnectionPreference = ConnectionPreference.BLUETOOTH
199
219
  ) -> None:
200
220
  """Initialize MammotionDevice."""
201
221
  if ble_device:
@@ -204,26 +224,32 @@ class Mammotion:
204
224
  if preference:
205
225
  self._preference = preference
206
226
 
207
- if cloud_credentials:
208
- self.initiate_cloud_connection(cloud_credentials.account_id or cloud_credentials.email, cloud_credentials.password)
227
+ async def initiate_cloud_connection(self, cloud_client: CloudIOTGateway) -> None:
228
+ if self._mammotion_mqtt is not None:
229
+ if self._mammotion_mqtt.is_connected:
230
+ return
209
231
 
210
- async def initiate_cloud_connection(self, account: str, password: str):
211
- cloud_client = await self.login(account, password)
212
232
 
213
- _mammotion_mqtt = MammotionMQTT(region_id=cloud_client._region.data.regionId,
233
+ self._mammotion_mqtt = MammotionMQTT(region_id=cloud_client._region.data.regionId,
214
234
  product_key=cloud_client._aep_response.data.productKey,
215
235
  device_name=cloud_client._aep_response.data.deviceName,
216
236
  device_secret=cloud_client._aep_response.data.deviceSecret,
217
237
  iot_token=cloud_client._session_by_authcode_response.data.iotToken,
218
238
  client_id=cloud_client._client_id)
219
239
 
220
- _mammotion_mqtt._cloud_client = cloud_client
221
- _mammotion_mqtt.connect_async()
240
+ self._mammotion_mqtt._cloud_client = cloud_client
241
+ loop = asyncio.get_running_loop()
242
+ await loop.run_in_executor(None, self._mammotion_mqtt.connect_async)
222
243
 
223
244
  for device in cloud_client.listing_dev_by_account_response.data.data:
224
245
  if device.deviceName.startswith(("Luba-", "Yuka-")):
225
- self.devices.add_device(MammotionMixedDeviceManager(name=device.deviceName, cloud_device=device, mqtt=_mammotion_mqtt))
246
+ self.devices.add_device(MammotionMixedDeviceManager(name=device.deviceName, cloud_device=device, mqtt=self._mammotion_mqtt))
226
247
 
248
+ def set_disconnect_strategy(self, disconnect: bool):
249
+ for device_name, device in self.devices.devices:
250
+ if device.ble() is not None:
251
+ ble_device: MammotionBaseBLEDevice = device.ble()
252
+ ble_device.set_disconnect_strategy(disconnect)
227
253
 
228
254
  @staticmethod
229
255
  async def login(account: str, password: str) -> CloudIOTGateway:
@@ -234,15 +260,17 @@ class Mammotion:
234
260
  country_code = mammotion_http.login_info.userInformation.domainAbbreviation
235
261
  _LOGGER.debug("CountryCode: " + country_code)
236
262
  _LOGGER.debug("AuthCode: " + mammotion_http.login_info.authorization_code)
237
- cloud_client.get_region(country_code, mammotion_http.login_info.authorization_code)
263
+ loop = asyncio.get_running_loop()
264
+ await loop.run_in_executor(None, cloud_client.get_region, country_code, mammotion_http.login_info.authorization_code)
238
265
  await cloud_client.connect()
239
266
  await cloud_client.login_by_oauth(country_code, mammotion_http.login_info.authorization_code)
240
- cloud_client.aep_handle()
241
- cloud_client.session_by_auth_code()
267
+ await loop.run_in_executor(None, cloud_client.aep_handle)
268
+ await loop.run_in_executor(None, cloud_client.session_by_auth_code)
242
269
 
243
- cloud_client.list_binding_by_account()
270
+ await loop.run_in_executor(None, cloud_client.list_binding_by_account)
244
271
  return cloud_client
245
272
 
273
+
246
274
  def get_device_by_name(self, name: str) -> MammotionMixedDeviceManager:
247
275
  return self.devices.get_device(name)
248
276
 
@@ -256,7 +284,7 @@ class Mammotion:
256
284
  return await device.cloud().command(key)
257
285
  # TODO work with both with EITHER
258
286
 
259
- async def send_command_with_args(self,name: str, key: str, kwargs):
287
+ async def send_command_with_args(self,name: str, key: str, **kwargs: any):
260
288
  """Send a command with args to the device."""
261
289
  device = self.get_device_by_name(name)
262
290
  if device:
@@ -287,7 +315,7 @@ class Mammotion:
287
315
  def mower(self, name: str):
288
316
  device = self.get_device_by_name(name)
289
317
  if device:
290
- return device.mower_state
318
+ return device.mower_state()
291
319
 
292
320
  def has_field(message: betterproto.Message) -> bool:
293
321
  """Check if the message has any fields serialized on wire."""
@@ -482,6 +510,28 @@ class MammotionBaseDevice:
482
510
  # jobs list
483
511
  # hash_list_result = await self._send_command_with_args("get_all_boundary_hash_list", sub_cmd=3)
484
512
 
513
+ async def move_forward(self):
514
+ linear_speed = 1.0
515
+ angular_speed = 0.0
516
+ transfrom3 = RockerControlUtil.getInstance().transfrom3(90, 1000)
517
+ transform4 = RockerControlUtil.getInstance().transfrom3(0, 0)
518
+
519
+ if transfrom3 is not None and len(transfrom3) > 0:
520
+ linear_speed = transfrom3[0] * 10
521
+ angular_speed = int(transform4[1] * 4.5)
522
+ await self._send_command_with_args("send_movement", linear_speed=linear_speed, angular_speed=angular_speed)
523
+
524
+ async def move_stop(self):
525
+ linear_speed = 0.0
526
+ angular_speed = 0.0
527
+ transfrom3 = RockerControlUtil.getInstance().transfrom3(0, 0)
528
+ transform4 = RockerControlUtil.getInstance().transfrom3(0, 0)
529
+
530
+ if transfrom3 is not None and len(transfrom3) > 0:
531
+ linear_speed = transfrom3[0] * 10
532
+ angular_speed = int(transform4[1] * 4.5)
533
+ await self._send_command_with_args("send_movement", linear_speed=linear_speed, angular_speed=angular_speed)
534
+
485
535
  async def command(self, key: str, **kwargs):
486
536
  """Send a command to the device."""
487
537
  return await self._send_command_with_args(key, **kwargs)
@@ -493,6 +543,7 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
493
543
  def __init__(self, mowing_state: MowingDevice, device: BLEDevice, interface: int = 0, **kwargs: Any) -> None:
494
544
  """Initialize MammotionBaseBLEDevice."""
495
545
  super().__init__(mowing_state)
546
+ self._disconnect_strategy = True
496
547
  self._ble_sync_task = None
497
548
  self._prev_notification = None
498
549
  self._interface = f"hci{interface}"
@@ -599,7 +650,10 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
599
650
  @property
600
651
  def rssi(self) -> int:
601
652
  """Return RSSI of device."""
602
- return 0
653
+ try:
654
+ return self._mower.device.sys.toapp_report_data.connect.ble_rssi
655
+ finally:
656
+ return 0
603
657
 
604
658
  async def _ensure_connected(self):
605
659
  """Ensure connection to device is established."""
@@ -629,12 +683,11 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
629
683
  return
630
684
  _LOGGER.debug("%s: Connecting; RSSI: %s", self.name, self.rssi)
631
685
  client: BleakClientWithServiceCache = await establish_connection(
632
- BleakClient,
686
+ BleakClientWithServiceCache,
633
687
  self._device,
634
688
  self.name,
635
689
  self._disconnected,
636
690
  max_attempts=10,
637
- use_services_cache=True,
638
691
  ble_device_callback=lambda: self._device,
639
692
  )
640
693
  _LOGGER.debug("%s: Connected; RSSI: %s", self.name, self.rssi)
@@ -816,6 +869,8 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
816
869
 
817
870
  async def _execute_timed_disconnect(self) -> None:
818
871
  """Execute timed disconnection."""
872
+ if not self._disconnect_strategy:
873
+ return
819
874
  _LOGGER.debug(
820
875
  "%s: Executing timed disconnect after timeout of %s",
821
876
  self.name,
@@ -865,6 +920,9 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
865
920
  if self._client is not None:
866
921
  return await self._client.disconnect()
867
922
 
923
+ def set_disconnect_strategy(self, disconnect):
924
+ self._disconnect_strategy = disconnect
925
+
868
926
 
869
927
  class MammotionBaseCloudDevice(MammotionBaseDevice):
870
928
  """Base class for Mammotion Cloud devices."""
@@ -905,22 +963,26 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
905
963
  if self.on_ready_callback:
906
964
  self.on_ready_callback()
907
965
 
966
+ asyncio.run(self._ble_sync())
967
+ asyncio.run(self.run_periodic_sync_task())
968
+
908
969
  def on_connected(self):
909
970
  """Callback for when MQTT connects."""
910
- self._ble_sync()
911
- self.run_periodic_sync_task()
971
+
912
972
 
913
973
  def on_disconnected(self):
914
974
  """Callback for when MQTT disconnects."""
915
975
 
916
- def _ble_sync(self):
976
+ async def _ble_sync(self):
917
977
  command_bytes = self._commands.send_todev_ble_sync(3)
918
- self._mqtt_client.get_cloud_client().send_cloud_command(self.iot_id, command_bytes)
978
+ loop = asyncio.get_running_loop()
979
+ await loop.run_in_executor(None, self._mqtt_client.get_cloud_client().send_cloud_command, self.iot_id, command_bytes)
980
+
919
981
 
920
982
  async def run_periodic_sync_task(self) -> None:
921
983
  """Send ble sync to robot."""
922
984
  try:
923
- self._ble_sync()
985
+ await self._ble_sync()
924
986
  finally:
925
987
  self.schedule_ble_sync()
926
988
 
@@ -943,14 +1005,14 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
943
1005
  async def _send_command(self, key: str, retry: int | None = None) -> bytes | None:
944
1006
  """Send command to device via MQTT and read response."""
945
1007
  if self._operation_lock.locked():
946
- _LOGGER.debug("%s: Operation already in progress, waiting for it to complete;", self.nick_name)
1008
+ _LOGGER.debug("%s: Operation already in progress, waiting for it to complete;", self.device.nickName)
947
1009
 
948
1010
  async with self._operation_lock:
949
1011
  try:
950
1012
  command_bytes = getattr(self._commands, key)()
951
1013
  return await self._send_command_locked(key, command_bytes)
952
1014
  except Exception as ex:
953
- _LOGGER.exception("%s: error in sending command - %s", self.nick_name, ex)
1015
+ _LOGGER.exception("%s: error in sending command - %s", self.device.nickName, ex)
954
1016
  raise
955
1017
 
956
1018
  async def _send_command_locked(self, key: str, command: bytes) -> bytes:
@@ -962,7 +1024,7 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
962
1024
  await asyncio.sleep(DBUS_ERROR_BACKOFF_TIME)
963
1025
  _LOGGER.debug(
964
1026
  "%s: error in _send_command_locked: %s",
965
- self.nick_name,
1027
+ self.device.nickName,
966
1028
  ex,
967
1029
  )
968
1030
  raise
@@ -972,11 +1034,12 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
972
1034
  assert self._mqtt_client is not None
973
1035
  self._notify_future = self.loop.create_future()
974
1036
  self._key = key
975
- _LOGGER.debug("%s: Sending command: %s", self.nick_name, key)
976
- self._mqtt_client.get_cloud_client().send_cloud_command(self.iot_id, command)
1037
+ _LOGGER.debug("%s: Sending command: %s", self.device.nickName, key)
1038
+ loop = asyncio.get_running_loop()
1039
+ await loop.run_in_executor(None, self._mqtt_client.get_cloud_client().send_cloud_command, self.iot_id, command)
977
1040
 
978
1041
  retry_handle = self.loop.call_at(
979
- self.loop.time() + 20,
1042
+ self.loop.time() + 10,
980
1043
  lambda: asyncio.ensure_future(
981
1044
  _handle_retry_cloud(
982
1045
  self._notify_future, self._mqtt_client.get_cloud_client().send_cloud_command, self.iot_id, command
@@ -997,20 +1060,20 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
997
1060
  retry_handle.cancel()
998
1061
  self._notify_future = None
999
1062
 
1000
- _LOGGER.debug("%s: Message received", self.nick_name)
1063
+ _LOGGER.debug("%s: Message received", self.device.nickName)
1001
1064
 
1002
1065
  return notify_msg
1003
1066
 
1004
1067
  async def _send_command_with_args(self, key: str, **kwargs: any) -> bytes | None:
1005
1068
  """Send command with arguments to device via MQTT and read response."""
1006
1069
  if self._operation_lock.locked():
1007
- _LOGGER.debug("%s: Operation already in progress, waiting for it to complete;", self.nick_name)
1070
+ _LOGGER.debug("%s: Operation already in progress, waiting for it to complete;", self.device.nickName)
1008
1071
  async with self._operation_lock:
1009
1072
  try:
1010
1073
  command_bytes = getattr(self._commands, key)(**kwargs)
1011
1074
  return await self._send_command_locked(key, command_bytes)
1012
1075
  except Exception as ex:
1013
- _LOGGER.exception("%s: error in sending command - %s", self.nick_name, ex)
1076
+ _LOGGER.exception("%s: error in sending command - %s", self.device.nickName, ex)
1014
1077
  raise
1015
1078
 
1016
1079
  def _extract_message_id(self, payload: dict) -> str:
@@ -1,5 +1,5 @@
1
1
  """MammotionMQTT."""
2
-
2
+ import asyncio
3
3
  import hashlib
4
4
  import hmac
5
5
  import json
@@ -81,7 +81,7 @@ class MammotionMQTT:
81
81
  logger.info("Connecting...")
82
82
  self._linkkit_client.thing_setup()
83
83
  self._linkkit_client.connect_async()
84
- self._linkkit_client.start_worker_loop()
84
+
85
85
 
86
86
  def disconnect(self):
87
87
  """Disconnect from MQTT Server."""
@@ -91,6 +91,7 @@ class MammotionMQTT:
91
91
  def _thing_on_thing_enable(self, user_data):
92
92
  """Is called when Thing is enabled."""
93
93
  logger.debug("on_thing_enable")
94
+ self.is_connected = True
94
95
  # logger.debug('subscribe_topic, topic:%s' % echo_topic)
95
96
  # self._linkkit_client.subscribe_topic(echo_topic, 0)
96
97
  self._linkkit_client.subscribe_topic(
@@ -147,12 +148,11 @@ class MammotionMQTT:
147
148
 
148
149
  # self._linkkit_client.subscribe_topic(f"/sys/{self._product_key}/{self._device_name}/#")
149
150
 
150
- def _on_disconnect(self, _client, _userdata, rc: int):
151
+ def _on_disconnect(self, _client, _userdata):
151
152
  """Is called on disconnect."""
152
153
  logger.info("Disconnected")
153
154
  self.is_connected = False
154
155
  self.is_ready = False
155
- logger.debug(rc)
156
156
  if self.on_disconnected:
157
157
  self.on_disconnected()
158
158
 
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "pymammotion"
3
- version = "0.2.4"
3
+ version = "0.2.6"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "pymammotion"
7
- version = "0.2.4"
7
+ version = "0.2.6"
8
8
  license = "GNU-3.0"
9
9
  description = ""
10
10
  readme = "README.md"
@@ -52,7 +52,7 @@ mypy = "^1.10.0"
52
52
  pre-commit = "^3.7.1"
53
53
 
54
54
  [tool.bumpver]
55
- current_version = "0.2.4"
55
+ current_version = "0.2.6"
56
56
  version_pattern = "MAJOR.MINOR.PATCH"
57
57
  commit_message = "Bump version {old_version} -> {new_version}"
58
58
  commit = true
@@ -1,8 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
-
4
- @dataclass
5
- class Credentials:
6
- email: str
7
- password: str
8
- account_id: str
File without changes
File without changes