pymammotion 0.4.0b7__py3-none-any.whl → 0.4.1__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.
Files changed (44) hide show
  1. pymammotion/bluetooth/ble_message.py +6 -7
  2. pymammotion/data/model/device.py +2 -7
  3. pymammotion/data/model/hash_list.py +84 -10
  4. pymammotion/data/model/raw_data.py +1 -8
  5. pymammotion/data/state_manager.py +30 -10
  6. pymammotion/mammotion/commands/abstract_message.py +2 -2
  7. pymammotion/mammotion/commands/messages/driver.py +27 -20
  8. pymammotion/mammotion/commands/messages/media.py +13 -14
  9. pymammotion/mammotion/commands/messages/navigation.py +16 -13
  10. pymammotion/mammotion/commands/messages/network.py +13 -10
  11. pymammotion/mammotion/commands/messages/ota.py +9 -14
  12. pymammotion/mammotion/commands/messages/system.py +36 -25
  13. pymammotion/mammotion/commands/messages/video.py +8 -10
  14. pymammotion/mammotion/devices/base.py +10 -10
  15. pymammotion/mammotion/devices/mammotion.py +18 -14
  16. pymammotion/mammotion/devices/mammotion_bluetooth.py +2 -3
  17. pymammotion/mammotion/devices/mammotion_cloud.py +1 -2
  18. pymammotion/mqtt/linkkit/__init__.py +5 -0
  19. pymammotion/mqtt/linkkit/h2client.py +585 -0
  20. pymammotion/mqtt/linkkit/linkkit.py +3020 -0
  21. pymammotion/mqtt/mammotion_mqtt.py +2 -2
  22. pymammotion/proto/__init__.py +2174 -1
  23. pymammotion/proto/luba_mul_pb2.py +8 -8
  24. pymammotion/proto/luba_mul_pb2.pyi +1 -0
  25. pymammotion/proto/mctrl_nav.proto +3 -3
  26. pymammotion/proto/mctrl_nav_pb2.py +69 -67
  27. pymammotion/proto/mctrl_nav_pb2.pyi +13 -5
  28. pymammotion/proto/mctrl_sys_pb2.py +41 -37
  29. pymammotion/proto/mctrl_sys_pb2.pyi +34 -11
  30. pymammotion/utility/device_config.py +2 -2
  31. {pymammotion-0.4.0b7.dist-info → pymammotion-0.4.1.dist-info}/METADATA +2 -3
  32. {pymammotion-0.4.0b7.dist-info → pymammotion-0.4.1.dist-info}/RECORD +34 -41
  33. pymammotion/proto/basestation.py +0 -59
  34. pymammotion/proto/common.py +0 -12
  35. pymammotion/proto/dev_net.py +0 -381
  36. pymammotion/proto/luba_msg.py +0 -81
  37. pymammotion/proto/luba_mul.py +0 -77
  38. pymammotion/proto/mctrl_driver.py +0 -100
  39. pymammotion/proto/mctrl_nav.py +0 -664
  40. pymammotion/proto/mctrl_ota.py +0 -48
  41. pymammotion/proto/mctrl_pept.py +0 -41
  42. pymammotion/proto/mctrl_sys.py +0 -574
  43. {pymammotion-0.4.0b7.dist-info → pymammotion-0.4.1.dist-info}/LICENSE +0 -0
  44. {pymammotion-0.4.0b7.dist-info → pymammotion-0.4.1.dist-info}/WHEEL +0 -0
@@ -2,17 +2,16 @@
2
2
  from abc import ABC
3
3
 
4
4
  from pymammotion.mammotion.commands.abstract_message import AbstractMessage
5
- from pymammotion.proto import luba_msg_pb2, mctrl_ota_pb2
6
- from pymammotion.proto.luba_msg import MsgCmdType, MsgDevice
5
+ from pymammotion.proto import GetInfoReq, InfoType, LubaMsg, MctlOta, MsgAttr, MsgCmdType, MsgDevice
7
6
 
8
7
 
9
8
  class MessageOta(AbstractMessage, ABC):
10
9
  def send_order_msg_ota(self, ota):
11
- luba_msg = luba_msg_pb2.LubaMsg(
12
- msgtype=luba_msg_pb2.MSG_CMD_TYPE_EMBED_OTA,
13
- sender=luba_msg_pb2.DEV_MOBILEAPP,
14
- rcver=self.get_msg_device(MsgCmdType.MSG_CMD_TYPE_EMBED_OTA, MsgDevice.DEV_MAINCTL),
15
- msgattr=luba_msg_pb2.MSG_ATTR_REQ,
10
+ luba_msg = LubaMsg(
11
+ msgtype=MsgCmdType.EMBED_OTA,
12
+ sender=MsgDevice.DEV_MOBILEAPP,
13
+ rcver=self.get_msg_device(MsgCmdType.EMBED_OTA, MsgDevice.DEV_MAINCTL),
14
+ msgattr=MsgAttr.MSG_ATTR_REQ,
16
15
  seqs=1,
17
16
  version=1,
18
17
  subtype=1,
@@ -22,17 +21,13 @@ class MessageOta(AbstractMessage, ABC):
22
21
  return luba_msg.SerializeToString()
23
22
 
24
23
  def get_device_ota_info(self, log_type: int):
25
- todev_get_info_req = mctrl_ota_pb2.MctlOta(
26
- todev_get_info_req=mctrl_ota_pb2.getInfoReq(type=mctrl_ota_pb2.IT_OTA)
27
- )
24
+ todev_get_info_req = MctlOta(todev_get_info_req=GetInfoReq(type=InfoType.IT_OTA))
28
25
 
29
26
  print("===Send command to get upgrade details===logType:" + str(log_type))
30
27
  return self.send_order_msg_ota(todev_get_info_req)
31
28
 
32
- def get_device_info_new(self):
29
+ def get_device_info_new(self) -> bytes:
33
30
  """New device call for OTA upgrade information."""
34
- todev_get_info_req = mctrl_ota_pb2.MctlOta(
35
- todev_get_info_req=mctrl_ota_pb2.getInfoReq(type=mctrl_ota_pb2.IT_BASE)
36
- )
31
+ todev_get_info_req = MctlOta(todev_get_info_req=GetInfoReq(type=InfoType.IT_BASE))
37
32
  print("Send to get OTA upgrade information", "Get device information")
38
33
  return self.send_order_msg_ota(todev_get_info_req)
@@ -6,12 +6,15 @@ import time
6
6
  from pymammotion import logger
7
7
  from pymammotion.mammotion.commands.abstract_message import AbstractMessage
8
8
  from pymammotion.mammotion.commands.messages.navigation import MessageNavigation
9
- from pymammotion.proto.luba_msg import LubaMsg, MsgAttr, MsgCmdType, MsgDevice
10
- from pymammotion.proto.mctrl_sys import (
9
+ from pymammotion.proto import (
11
10
  DeviceProductTypeInfoT,
12
11
  LoraCfgReq,
12
+ LubaMsg,
13
13
  MctlSys,
14
14
  MCtrlSimulationCmdData,
15
+ MsgAttr,
16
+ MsgCmdType,
17
+ MsgDevice,
15
18
  ReportInfoCfg,
16
19
  RptAct,
17
20
  RptInfoType,
@@ -26,12 +29,12 @@ from pymammotion.utility.device_type import DeviceType
26
29
  class MessageSystem(AbstractMessage, ABC):
27
30
  messageNavigation: MessageNavigation = MessageNavigation()
28
31
 
29
- def send_order_msg_sys(self, sys):
32
+ def send_order_msg_sys(self, sys) -> bytes:
30
33
  luba_msg = LubaMsg(
31
- msgtype=MsgCmdType.MSG_CMD_TYPE_EMBED_SYS,
32
- msgattr=MsgAttr.MSG_ATTR_REQ,
34
+ msgtype=MsgCmdType.EMBED_SYS,
35
+ msgattr=MsgAttr.REQ,
33
36
  sender=MsgDevice.DEV_MOBILEAPP,
34
- rcver=self.get_msg_device(MsgCmdType.MSG_CMD_TYPE_EMBED_SYS, MsgDevice.DEV_MAINCTL),
37
+ rcver=self.get_msg_device(MsgCmdType.EMBED_SYS, MsgDevice.DEV_MAINCTL),
35
38
  sys=sys,
36
39
  seqs=1,
37
40
  version=1,
@@ -42,10 +45,10 @@ class MessageSystem(AbstractMessage, ABC):
42
45
  return luba_msg.SerializeToString()
43
46
 
44
47
  @staticmethod
45
- def send_order_msg_sys_legacy(sys):
48
+ def send_order_msg_sys_legacy(sys) -> bytes:
46
49
  luba_msg = LubaMsg(
47
- msgtype=MsgCmdType.MSG_CMD_TYPE_EMBED_SYS,
48
- msgattr=MsgAttr.MSG_ATTR_REQ,
50
+ msgtype=MsgCmdType.EMBED_SYS,
51
+ msgattr=MsgAttr.REQ,
49
52
  sender=MsgDevice.DEV_MOBILEAPP,
50
53
  rcver=MsgDevice.DEV_MAINCTL,
51
54
  sys=sys,
@@ -57,7 +60,7 @@ class MessageSystem(AbstractMessage, ABC):
57
60
 
58
61
  return luba_msg.SerializeToString()
59
62
 
60
- def reset_system(self):
63
+ def reset_system(self) -> bytes:
61
64
  build = MctlSys(todev_reset_system=1)
62
65
  logger.debug("Send command - send factory reset")
63
66
  return self.send_order_msg_sys(build)
@@ -102,7 +105,7 @@ class MessageSystem(AbstractMessage, ABC):
102
105
  is_sidelight}, operate:{operate}, timeCtrlLight:{build}")
103
106
  return self.send_order_msg_sys(build2)
104
107
 
105
- def test_tool_order_to_sys(self, sub_cmd: int, param_id: int, param_value: list[int]):
108
+ def test_tool_order_to_sys(self, sub_cmd: int, param_id: int, param_value: list[int]) -> bytes:
106
109
  build = MCtrlSimulationCmdData(sub_cmd=sub_cmd, param_id=param_id, param_value=param_value)
107
110
  logger.debug(f"Send tool test command: subCmd={sub_cmd}, param_id:{
108
111
  param_id}, param_value={param_value}")
@@ -111,31 +114,39 @@ class MessageSystem(AbstractMessage, ABC):
111
114
  param_id}, param_value={param_value}")
112
115
  return self.send_order_msg_sys(build2)
113
116
 
114
- def read_and_set_rtk_paring_code(self, op: int, cgf: str | None = None):
117
+ def read_and_set_rtk_paring_code(self, op: int, cgf: str | None = None) -> bytes:
115
118
  logger.debug(f"Send read and write base station configuration quality op:{
116
119
  op}, cgf:{cgf}")
117
120
  return self.send_order_msg_sys(MctlSys(todev_lora_cfg_req=LoraCfgReq(op=op, cfg=cgf)))
118
121
 
119
- def allpowerfull_rw(self, id: int, context: int, rw: int) -> bytes:
120
- if (id == 6 or id == 3 or id == 7) and DeviceType.is_luba_2(self.get_device_name()):
121
- return self.messageNavigation.allpowerfull_rw_adapter_x3(id, context, rw)
122
- build = MctlSys(bidire_comm_cmd=SysCommCmd(id=id, context=context, rw=rw))
123
- logger.debug(f"Send command - 9 general read and write command id={id}, context={context}, rw={rw}")
124
- if id == 5:
122
+ def allpowerfull_rw(self, rw_id: int, context: int, rw: int) -> bytes:
123
+ if (rw_id == 6 or rw_id == 3 or rw_id == 7) and DeviceType.is_luba_2(self.get_device_name()):
124
+ return self.messageNavigation.allpowerfull_rw_adapter_x3(rw_id, context, rw)
125
+ build = MctlSys(bidire_comm_cmd=SysCommCmd(id=rw_id, context=context, rw=rw))
126
+ logger.debug(f"Send command - 9 general read and write command id={rw_id}, context={context}, rw={rw}")
127
+ if rw_id == 5:
125
128
  # TODO investigate if the original code makes any difference to this call.
126
129
  """
127
- LubaMsgOuterClass.LubaMsg.Builder protoBufBuilderSet = getProtoBufBuilderSet(LubaMsgOuterClass.MsgCmdType.MSG_CMD_TYPE_EMBED_SYS, LubaMsgOuterClass.MsgDevice.DEV_MAINCTL, LubaMsgOuterClass.MsgAttr.MSG_ATTR_REQ);
130
+ LubaMsgOuterClass.LubaMsg.Builder protoBufBuilderSet = getProtoBufBuilderSet(LubaMsgOuterClass.MsgCmdType.EMBED_SYS, LubaMsgOuterClass.MsgDevice.DEV_MAINCTL, LubaMsgOuterClass.MsgAttr.REQ);
128
131
  protoBufBuilderSet.setSys(build);
129
132
  sendMsg(protoBufBuilderSet, 122, true, "发送指令--9通用读写命令id=" + i + ",context=" + i2 + ",rw=" + i3);
130
133
  """
131
134
  return self.send_order_msg_sys(build)
132
135
  return self.send_order_msg_sys(build)
133
136
 
134
- def traverse_mode(self, id: int) -> bytes:
137
+ def traverse_mode(self, context: int) -> bytes:
135
138
  """Sets the traversal mode back to charger."""
139
+ # setReChargeMode
136
140
  # 0 direct
137
141
  # 1 follow the perimeter
138
- return self.allpowerfull_rw(7, id, 1)
142
+ return self.allpowerfull_rw(7, context, 1)
143
+
144
+ def turning_mode(self, context: int) -> bytes:
145
+ """Sets the traversal mode back to charger."""
146
+ # setTurnAroundMode
147
+ # 0 multipoint turn
148
+ # 1 zero turn
149
+ return self.allpowerfull_rw(6, context, 1)
139
150
 
140
151
  # Commented out as not needed and too many refs to try fix up
141
152
  # def factory_test_order(self, test_id: int, test_duration: int, expect: str):
@@ -298,10 +309,10 @@ class MessageSystem(AbstractMessage, ABC):
298
309
  mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_VISION_STATISTIC)
299
310
 
300
311
  luba_msg = LubaMsg(
301
- msgtype=MsgCmdType.MSG_CMD_TYPE_EMBED_SYS,
312
+ msgtype=MsgCmdType.EMBED_SYS,
302
313
  sender=MsgDevice.DEV_MOBILEAPP,
303
314
  rcver=MsgDevice.DEV_MAINCTL,
304
- msgattr=MsgAttr.MSG_ATTR_REQ,
315
+ msgattr=MsgAttr.REQ,
305
316
  seqs=1,
306
317
  version=1,
307
318
  subtype=1,
@@ -334,10 +345,10 @@ class MessageSystem(AbstractMessage, ABC):
334
345
  mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_BASESTATION_INFO)
335
346
 
336
347
  luba_msg = LubaMsg(
337
- msgtype=MsgCmdType.MSG_CMD_TYPE_EMBED_SYS,
348
+ msgtype=MsgCmdType.EMBED_SYS,
338
349
  sender=MsgDevice.DEV_MOBILEAPP,
339
350
  rcver=MsgDevice.DEV_MAINCTL,
340
- msgattr=MsgAttr.MSG_ATTR_REQ,
351
+ msgattr=MsgAttr.REQ,
341
352
  seqs=1,
342
353
  version=1,
343
354
  subtype=1,
@@ -3,19 +3,17 @@ from abc import ABC
3
3
  import time
4
4
 
5
5
  from pymammotion.mammotion.commands.abstract_message import AbstractMessage
6
- from pymammotion.proto import luba_msg_pb2, luba_mul_pb2
7
- from pymammotion.proto.luba_msg import MsgAttr, MsgCmdType, MsgDevice
8
- from pymammotion.proto.luba_mul import MUL_CAMERA_POSITION
6
+ from pymammotion.proto import LubaMsg, MsgAttr, MsgCmdType, MsgDevice, MulCameraPosition, MulSetVideo, SocMul
9
7
  from pymammotion.utility.device_type import DeviceType
10
8
 
11
9
 
12
10
  class MessageVideo(AbstractMessage, ABC):
13
11
  async def send_order_msg_video(self, mul):
14
- luba_msg = luba_msg_pb2.LubaMsg(
15
- msgtype=luba_msg_pb2.MSG_CMD_TYPE_MUL,
16
- msgattr=MsgAttr.MSG_ATTR_REQ,
17
- sender=luba_msg_pb2.DEV_MOBILEAPP,
18
- rcver=self.get_msg_device(MsgCmdType.MSG_CMD_TYPE_MUL, MsgDevice.SOC_MODULE_MULTIMEDIA),
12
+ luba_msg = LubaMsg(
13
+ msgtype=MsgCmdType.MUL,
14
+ msgattr=MsgAttr.REQ,
15
+ sender=MsgDevice.DEV_MOBILEAPP,
16
+ rcver=self.get_msg_device(MsgCmdType.MUL, MsgDevice.SOC_MODULE_MULTIMEDIA),
19
17
  mul=mul,
20
18
  seqs=1,
21
19
  version=1,
@@ -26,6 +24,6 @@ class MessageVideo(AbstractMessage, ABC):
26
24
  return luba_msg.SerializeToString()
27
25
 
28
26
  def device_agora_join_channel_with_position(self, enter_state: int):
29
- position = MUL_CAMERA_POSITION.ALL if DeviceType.is_yuka(self.get_device_name()) else MUL_CAMERA_POSITION.LEFT
30
- mctl_sys = luba_mul_pb2.SocMul(set_video=luba_mul_pb2.MulSetVideo(position=position, vi_switch=enter_state))
27
+ position = MulCameraPosition.ALL if DeviceType.is_yuka(self.get_device_name()) else MulCameraPosition.LEFT
28
+ mctl_sys = SocMul(set_video=MulSetVideo(position=position, vi_switch=enter_state))
31
29
  return self.send_order_msg_video(mctl_sys)
@@ -10,8 +10,8 @@ from pymammotion.data.model import RegionData
10
10
  from pymammotion.data.model.device import MowingDevice
11
11
  from pymammotion.data.model.raw_data import RawMowerData
12
12
  from pymammotion.data.state_manager import StateManager
13
- from pymammotion.proto.luba_msg import LubaMsg
14
- from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
13
+ from pymammotion.proto import LubaMsg, NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
14
+ from pymammotion.utility.device_type import DeviceType
15
15
 
16
16
  _LOGGER = logging.getLogger(__name__)
17
17
 
@@ -198,13 +198,13 @@ class MammotionBaseDevice:
198
198
  await self.queue_command("get_device_product_model")
199
199
  await self.queue_command("get_report_cfg")
200
200
  """RTK and dock location."""
201
- await self.queue_command("allpowerfull_rw", id=5, context=1, rw=1)
201
+ await self.queue_command("allpowerfull_rw", rw_id=5, context=1, rw=1)
202
202
  await self.async_read_settings()
203
203
 
204
204
  async def start_map_sync(self) -> None:
205
205
  """Start sync of map data."""
206
206
 
207
- if self._cloud_device and len(self.mower.map.area_name) == 0:
207
+ if self._cloud_device and len(self.mower.map.area_name) == 0 and not DeviceType.is_luba1(self.mower.name):
208
208
  await self.queue_command("get_area_name_list", device_id=self._cloud_device.iotId)
209
209
 
210
210
  await self.queue_command("read_plan", sub_cmd=2, plan_index=0)
@@ -222,11 +222,11 @@ class MammotionBaseDevice:
222
222
 
223
223
  async def async_read_settings(self) -> None:
224
224
  """Read settings from device."""
225
- await self.queue_command("allpowerfull_rw", id=3, context=1, rw=0)
226
- await self.queue_command("allpowerfull_rw", id=4, context=1, rw=0)
227
- await self.queue_command("allpowerfull_rw", id=6, context=1, rw=0)
225
+ await self.queue_command("allpowerfull_rw", rw_id=3, context=1, rw=0)
226
+ await self.queue_command("allpowerfull_rw", rw_id=4, context=1, rw=0)
227
+ await self.queue_command("allpowerfull_rw", rw_id=6, context=1, rw=0)
228
228
  # traversal mode
229
- await self.queue_command("allpowerfull_rw", id=7, context=1, rw=0)
229
+ await self.queue_command("allpowerfull_rw", rw_id=7, context=1, rw=0)
230
230
 
231
231
  await self.queue_command("read_and_set_sidelight", is_sidelight=True, operate=1)
232
232
 
@@ -234,8 +234,8 @@ class MammotionBaseDevice:
234
234
 
235
235
  async def async_get_errors(self) -> None:
236
236
  """Error codes."""
237
- await self.queue_command("allpowerfull_rw", id=5, rw=1, context=2)
238
- await self.queue_command("allpowerfull_rw", id=5, rw=1, context=3)
237
+ await self.queue_command("allpowerfull_rw", rw_id=5, rw=1, context=2)
238
+ await self.queue_command("allpowerfull_rw", rw_id=5, rw=1, context=3)
239
239
 
240
240
  async def command(self, key: str, **kwargs):
241
241
  """Send a command to the device."""
@@ -34,6 +34,8 @@ class ConnectionPreference(Enum):
34
34
 
35
35
  class MammotionMixedDeviceManager:
36
36
  preference: ConnectionPreference
37
+ _ble_device: MammotionBaseBLEDevice | None = None
38
+ _cloud_device: MammotionBaseCloudDevice | None = None
37
39
 
38
40
  def __init__(
39
41
  self,
@@ -45,8 +47,7 @@ class MammotionMixedDeviceManager:
45
47
  ) -> None:
46
48
  self.name = name
47
49
  self._state_manager = StateManager(MowingDevice())
48
- self._ble_device: MammotionBaseBLEDevice | None = None
49
- self._cloud_device: MammotionBaseCloudDevice | None = None
50
+ self._state_manager.get_device().name = name
50
51
  self.add_ble(ble_device)
51
52
  self.add_cloud(cloud_device, mqtt)
52
53
  self.preference = preference
@@ -160,7 +161,7 @@ class Mammotion:
160
161
  device_manager = MammotionDeviceManager()
161
162
  mqtt_list: dict[str, MammotionCloud] = dict()
162
163
 
163
- _instance: Mammotion = None
164
+ _instance: Mammotion | None = None
164
165
 
165
166
  def __new__(cls, *args: Any, **kwargs: Any):
166
167
  if not cls._instance:
@@ -213,14 +214,17 @@ class Mammotion:
213
214
  for device in mqtt_client.cloud_client.devices_by_account_response.data.data:
214
215
  mower_device = self.device_manager.get_device(device.deviceName)
215
216
  if device.deviceName.startswith(("Luba-", "Yuka-")) and mower_device is None:
216
- self.device_manager.add_device(
217
- MammotionMixedDeviceManager(
218
- name=device.deviceName,
219
- cloud_device=device,
220
- mqtt=mqtt_client,
221
- preference=ConnectionPreference.WIFI,
222
- )
217
+ mixed_device = MammotionMixedDeviceManager(
218
+ name=device.deviceName,
219
+ cloud_device=device,
220
+ mqtt=mqtt_client,
221
+ preference=ConnectionPreference.WIFI,
223
222
  )
223
+ mixed_device.mower_state.mower_state.product_key = device.productKey
224
+ mixed_device.mower_state.mower_state.model = (
225
+ device.productName if device.productModel is None else device.productModel
226
+ )
227
+ self.device_manager.add_device(mixed_device)
224
228
  elif device.deviceName.startswith(("Luba-", "Yuka-")) and mower_device:
225
229
  if mower_device.cloud() is None:
226
230
  mower_device.add_cloud(cloud_device=device, mqtt=mqtt_client)
@@ -264,7 +268,7 @@ class Mammotion:
264
268
  """Send a command to the device."""
265
269
  device = self.get_device_by_name(name)
266
270
  if device:
267
- if device.preference is ConnectionPreference.BLUETOOTH:
271
+ if device.preference is ConnectionPreference.BLUETOOTH and device.has_ble():
268
272
  return await device.ble().command(key)
269
273
  if device.preference is ConnectionPreference.WIFI:
270
274
  return await device.cloud().command(key)
@@ -274,7 +278,7 @@ class Mammotion:
274
278
  """Send a command with args to the device."""
275
279
  device = self.get_device_by_name(name)
276
280
  if device:
277
- if device.preference is ConnectionPreference.BLUETOOTH:
281
+ if device.preference is ConnectionPreference.BLUETOOTH and device.has_ble():
278
282
  return await device.ble().command(key, **kwargs)
279
283
  if device.preference is ConnectionPreference.WIFI:
280
284
  return await device.cloud().command(key, **kwargs)
@@ -283,7 +287,7 @@ class Mammotion:
283
287
  async def start_sync(self, name: str, retry: int):
284
288
  device = self.get_device_by_name(name)
285
289
  if device:
286
- if device.preference is ConnectionPreference.BLUETOOTH:
290
+ if device.preference is ConnectionPreference.BLUETOOTH and device.has_ble():
287
291
  return await device.ble().start_sync(retry)
288
292
  if device.preference is ConnectionPreference.WIFI:
289
293
  return await device.cloud().start_sync(retry)
@@ -292,7 +296,7 @@ class Mammotion:
292
296
  async def start_map_sync(self, name: str):
293
297
  device = self.get_device_by_name(name)
294
298
  if device:
295
- if device.preference is ConnectionPreference.BLUETOOTH:
299
+ if device.preference is ConnectionPreference.BLUETOOTH and device.has_ble():
296
300
  return await device.ble().start_map_sync()
297
301
  if device.preference is ConnectionPreference.WIFI:
298
302
  return await device.cloud().start_map_sync()
@@ -18,8 +18,7 @@ from pymammotion.bluetooth import BleMessage
18
18
  from pymammotion.data.state_manager import StateManager
19
19
  from pymammotion.mammotion.commands.mammotion_command import MammotionCommand
20
20
  from pymammotion.mammotion.devices.base import MammotionBaseDevice
21
- from pymammotion.proto import has_field
22
- from pymammotion.proto.luba_msg import LubaMsg
21
+ from pymammotion.proto import LubaMsg, has_field
23
22
 
24
23
  DBUS_ERROR_BACKOFF_TIME = 0.25
25
24
 
@@ -334,7 +333,7 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
334
333
  _LOGGER.exception("Error parsing message %s", data)
335
334
  data = b""
336
335
  finally:
337
- self._message.clearNotification()
336
+ self._message.clear_notification()
338
337
 
339
338
  _LOGGER.debug("%s: Received notification: %s", self.name, data)
340
339
  else:
@@ -20,8 +20,7 @@ from pymammotion.event.event import DataEvent
20
20
  from pymammotion.mammotion.commands.mammotion_command import MammotionCommand
21
21
  from pymammotion.mammotion.devices.base import MammotionBaseDevice
22
22
  from pymammotion.mqtt.mammotion_future import MammotionFuture
23
- from pymammotion.proto import has_field
24
- from pymammotion.proto.luba_msg import LubaMsg
23
+ from pymammotion.proto import LubaMsg, has_field
25
24
 
26
25
  _LOGGER = logging.getLogger(__name__)
27
26
 
@@ -0,0 +1,5 @@
1
+ """Package for linkkit."""
2
+
3
+ from .linkkit import LinkKit
4
+
5
+ __all__ = ["LinkKit"]