pymammotion 0.2.51__tar.gz → 0.2.52__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.
Files changed (125) hide show
  1. {pymammotion-0.2.51 → pymammotion-0.2.52}/PKG-INFO +1 -1
  2. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/cloud_gateway.py +9 -1
  3. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/bluetooth/ble_message.py +0 -19
  4. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/device.py +2 -0
  5. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/hash_list.py +18 -2
  6. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/mqtt/properties.py +45 -1
  7. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/state_manager.py +5 -0
  8. pymammotion-0.2.52/pymammotion/mammotion/commands/abstract_message.py +22 -0
  9. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/mammotion_command.py +4 -1
  10. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/messages/driver.py +2 -3
  11. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/messages/media.py +6 -3
  12. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/messages/navigation.py +0 -10
  13. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/messages/network.py +11 -1
  14. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/messages/ota.py +6 -2
  15. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/messages/system.py +13 -1
  16. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/messages/video.py +5 -2
  17. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/devices/base.py +1 -1
  18. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/devices/mammotion.py +1 -1
  19. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/devices/mammotion_cloud.py +9 -0
  20. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_nav.proto +3 -3
  21. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_sys.proto +15 -1
  22. {pymammotion-0.2.51 → pymammotion-0.2.52}/pyproject.toml +3 -3
  23. pymammotion-0.2.51/pymammotion/mammotion/commands/abstract_message.py +0 -10
  24. {pymammotion-0.2.51 → pymammotion-0.2.52}/LICENSE +0 -0
  25. {pymammotion-0.2.51 → pymammotion-0.2.52}/README.md +0 -0
  26. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/__init__.py +0 -0
  27. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/__init__.py +0 -0
  28. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/cloud_service.py +0 -0
  29. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/model/aep_response.py +0 -0
  30. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/model/connect_response.py +0 -0
  31. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/model/dev_by_account_response.py +0 -0
  32. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/model/login_by_oauth_response.py +0 -0
  33. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/model/regions_response.py +0 -0
  34. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/model/session_by_authcode_response.py +0 -0
  35. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/model/stream_subscription_response.py +0 -0
  36. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/aliyun/tmp_constant.py +0 -0
  37. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/bluetooth/__init__.py +0 -0
  38. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/bluetooth/ble.py +0 -0
  39. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/bluetooth/const.py +0 -0
  40. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/bluetooth/data/__init__.py +0 -0
  41. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/bluetooth/data/convert.py +0 -0
  42. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/bluetooth/data/framectrldata.py +0 -0
  43. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/bluetooth/data/notifydata.py +0 -0
  44. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/const.py +0 -0
  45. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/__init__.py +0 -0
  46. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/__init__.py +0 -0
  47. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/account.py +0 -0
  48. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/device_config.py +0 -0
  49. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/enums.py +0 -0
  50. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/excute_boarder_params.py +0 -0
  51. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/execute_boarder.py +0 -0
  52. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/generate_route_information.py +0 -0
  53. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/location.py +0 -0
  54. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/mowing_modes.py +0 -0
  55. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/plan.py +0 -0
  56. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/rapid_state.py +0 -0
  57. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/region_data.py +0 -0
  58. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/model/report_info.py +0 -0
  59. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/mqtt/__init__.py +0 -0
  60. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/mqtt/event.py +0 -0
  61. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/data/mqtt/status.py +0 -0
  62. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/event/__init__.py +0 -0
  63. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/event/event.py +0 -0
  64. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/http/_init_.py +0 -0
  65. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/http/http.py +0 -0
  66. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/http/model/http.py +0 -0
  67. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/__init__.py +0 -0
  68. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/__init__.py +0 -0
  69. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/commands/messages/__init__.py +0 -0
  70. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/control/__init__.py +0 -0
  71. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/control/joystick.py +0 -0
  72. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/devices/__init__.py +0 -0
  73. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mammotion/devices/mammotion_bluetooth.py +0 -0
  74. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mqtt/__init__.py +0 -0
  75. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mqtt/mammotion_future.py +0 -0
  76. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/mqtt/mammotion_mqtt.py +0 -0
  77. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/__init__.py +0 -0
  78. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/basestation.proto +0 -0
  79. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/basestation.py +0 -0
  80. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/basestation_pb2.py +0 -0
  81. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/basestation_pb2.pyi +0 -0
  82. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/common.proto +0 -0
  83. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/common.py +0 -0
  84. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/common_pb2.py +0 -0
  85. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/common_pb2.pyi +0 -0
  86. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/dev_net.proto +0 -0
  87. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/dev_net.py +0 -0
  88. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/dev_net_pb2.py +0 -0
  89. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/dev_net_pb2.pyi +0 -0
  90. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/luba_msg.proto +0 -0
  91. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/luba_msg.py +0 -0
  92. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/luba_msg_pb2.py +0 -0
  93. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/luba_msg_pb2.pyi +0 -0
  94. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/luba_mul.proto +0 -0
  95. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/luba_mul.py +0 -0
  96. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/luba_mul_pb2.py +0 -0
  97. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/luba_mul_pb2.pyi +0 -0
  98. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_driver.proto +0 -0
  99. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_driver.py +0 -0
  100. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_driver_pb2.py +0 -0
  101. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_driver_pb2.pyi +0 -0
  102. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_nav.py +0 -0
  103. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_nav_pb2.py +0 -0
  104. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_nav_pb2.pyi +0 -0
  105. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_ota.proto +0 -0
  106. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_ota.py +0 -0
  107. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_ota_pb2.py +0 -0
  108. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_ota_pb2.pyi +0 -0
  109. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_pept.proto +0 -0
  110. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_pept.py +0 -0
  111. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_pept_pb2.py +0 -0
  112. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_pept_pb2.pyi +0 -0
  113. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_sys.py +0 -0
  114. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_sys_pb2.py +0 -0
  115. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/proto/mctrl_sys_pb2.pyi +0 -0
  116. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/py.typed +0 -0
  117. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/utility/constant/__init__.py +0 -0
  118. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/utility/constant/device_constant.py +0 -0
  119. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/utility/conversions.py +0 -0
  120. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/utility/datatype_converter.py +0 -0
  121. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/utility/device_type.py +0 -0
  122. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/utility/map.py +0 -0
  123. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/utility/movement.py +0 -0
  124. {pymammotion-0.2.51 → pymammotion-0.2.52}/pymammotion/utility/periodic.py +0 -0
  125. {pymammotion-0.2.51 → pymammotion-0.2.52}/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.51
3
+ Version: 0.2.52
4
4
  Summary:
5
5
  License: GNU-3.0
6
6
  Author: Michael Arthur
@@ -62,6 +62,10 @@ class LoginException(Exception):
62
62
  """Raise exception when library cannot log in."""
63
63
 
64
64
 
65
+ class CheckSessionException(Exception):
66
+ """Raise exception when checking session results in a failure."""
67
+
68
+
65
69
  class CloudIOTGateway:
66
70
  """Class for interacting with Aliyun Cloud IoT Gateway."""
67
71
 
@@ -528,7 +532,7 @@ class CloudIOTGateway:
528
532
 
529
533
  if int(response_body_dict.get("code")) != 200:
530
534
  logger.error(response_body_dict)
531
- raise Exception("Error check or refresh token: " + response_body_dict.__str__())
535
+ raise CheckSessionException("Error check or refresh token: " + response_body_dict.__str__())
532
536
 
533
537
  session = SessionByAuthCodeResponse.from_dict(response_body_dict)
534
538
  session_data = session.data
@@ -725,3 +729,7 @@ class CloudIOTGateway:
725
729
  @property
726
730
  def login_by_oauth_response(self):
727
731
  return self._login_by_oauth_response
732
+
733
+ @property
734
+ def connect_response(self):
735
+ return self._connect_response
@@ -56,25 +56,6 @@ class BleMessage:
56
56
  self.mAck = queue.Queue()
57
57
  self.notification = BlufiNotifyData()
58
58
 
59
- async def get_device_version_main(self) -> None:
60
- commEsp = dev_net_pb2.DevNet(todev_devinfo_req=dev_net_pb2.DrvDevInfoReq())
61
-
62
- for i in range(1, 8):
63
- if i == 1:
64
- commEsp.todev_devinfo_req.req_ids.add(id=i, type=6)
65
- commEsp.todev_devinfo_req.req_ids.add(id=i, type=3)
66
-
67
- lubaMsg = luba_msg_pb2.LubaMsg()
68
- lubaMsg.msgtype = luba_msg_pb2.MSG_CMD_TYPE_ESP
69
- lubaMsg.sender = luba_msg_pb2.DEV_MOBILEAPP
70
- lubaMsg.msgattr = luba_msg_pb2.MSG_ATTR_REQ
71
- lubaMsg.seqs = 1
72
- lubaMsg.version = 1
73
- lubaMsg.subtype = 1
74
- lubaMsg.net.CopyFrom(commEsp)
75
- byte_arr = lubaMsg.SerializeToString()
76
- await self.post_custom_data_bytes(byte_arr)
77
-
78
59
  async def get_task(self) -> None:
79
60
  hash_map = {"pver": 1, "subCmd": 2, "result": 0}
80
61
  await self.post_custom_data(self.get_json_string(bleOrderCmd.task, hash_map))
@@ -10,6 +10,7 @@ from pymammotion.data.model import HashList, RapidState
10
10
  from pymammotion.data.model.device_config import DeviceLimits
11
11
  from pymammotion.data.model.location import Location
12
12
  from pymammotion.data.model.report_info import ReportData
13
+ from pymammotion.data.mqtt.properties import ThingPropertiesMessage
13
14
  from pymammotion.proto.dev_net import DevNet
14
15
  from pymammotion.proto.luba_msg import LubaMsg
15
16
  from pymammotion.proto.luba_mul import SocMul
@@ -33,6 +34,7 @@ from pymammotion.utility.map import CoordinateConverter
33
34
  class MowingDevice(DataClassORJSONMixin):
34
35
  """Wraps the betterproto dataclasses, so we can bypass the groups for keeping all data."""
35
36
 
37
+ mqtt_properties: ThingPropertiesMessage | None = None
36
38
  map: HashList = field(default_factory=HashList)
37
39
  location: Location = field(default_factory=Location)
38
40
  mowing_state: RapidState = field(default_factory=RapidState)
@@ -12,6 +12,7 @@ class PathType(IntEnum):
12
12
  AREA = 0
13
13
  OBSTACLE = 1
14
14
  PATH = 2
15
+ DUMP = 12
15
16
 
16
17
 
17
18
  @dataclass
@@ -20,10 +21,15 @@ class FrameList(DataClassORJSONMixin):
20
21
  data: list[NavGetCommDataAck]
21
22
 
22
23
 
24
+ @dataclass
25
+ class NavGetHashListData(DataClassORJSONMixin, NavGetHashListAck):
26
+ """Dataclass for NavGetHashListData."""
27
+
28
+
23
29
  @dataclass
24
30
  class RootHashList(DataClassORJSONMixin):
25
31
  total_frame: int = 0
26
- data: list[NavGetHashListAck] = list
32
+ data: list[NavGetHashListAck] = field(default_factory=list)
27
33
 
28
34
 
29
35
  @dataclass
@@ -45,15 +51,19 @@ class HashList(DataClassORJSONMixin):
45
51
  area: dict = field(default_factory=dict) # type 0
46
52
  path: dict = field(default_factory=dict) # type 2
47
53
  obstacle: dict = field(default_factory=dict) # type 1
54
+ dump: dict = field(default_factory=dict) # type 12?
48
55
  area_name: list[AreaHashNameList] = field(default_factory=list)
49
56
 
50
57
  def update_hash_lists(self, hashlist: list[int]) -> None:
51
58
  self.area = {hash_id: frames for hash_id, frames in self.area.items() if hash_id in hashlist}
52
59
  self.path = {hash_id: frames for hash_id, frames in self.path.items() if hash_id in hashlist}
53
60
  self.obstacle = {hash_id: frames for hash_id, frames in self.obstacle.items() if hash_id in hashlist}
61
+ self.dump = {hash_id: frames for hash_id, frames in self.dump.items() if hash_id in hashlist}
54
62
 
55
63
  @property
56
64
  def hashlist(self) -> list[int]:
65
+ if len(self.root_hash_list.data) == 0:
66
+ return []
57
67
  return [i for obj in self.root_hash_list.data for i in obj.data_couple]
58
68
 
59
69
  @property
@@ -62,7 +72,7 @@ class HashList(DataClassORJSONMixin):
62
72
  i
63
73
  for obj in self.root_hash_list.data
64
74
  for i in obj.data_couple
65
- if i not in set(self.area.keys()).union(self.path.keys(), self.obstacle.keys())
75
+ if i not in set(self.area.keys()).union(self.path.keys(), self.obstacle.keys(), self.dump.keys())
66
76
  ]
67
77
 
68
78
  def update_root_hash_list(self, hash_list: NavGetHashListAck) -> None:
@@ -92,6 +102,9 @@ class HashList(DataClassORJSONMixin):
92
102
  if hash_data.type == PathType.PATH:
93
103
  return self._find_missing_frames(self.path.get(hash_data.hash))
94
104
 
105
+ if hash_data.type == PathType.DUMP:
106
+ return self._find_missing_frames(self.dump.get(hash_data.hash))
107
+
95
108
  def update(self, hash_data: NavGetCommDataAck) -> bool:
96
109
  """Update the map data."""
97
110
  if hash_data.type == PathType.AREA:
@@ -106,6 +119,9 @@ class HashList(DataClassORJSONMixin):
106
119
  if hash_data.type == PathType.PATH:
107
120
  return self._add_hash_data(self.path, hash_data)
108
121
 
122
+ if hash_data.type == PathType.DUMP:
123
+ return self._add_hash_data(self.dump, hash_data)
124
+
109
125
  @staticmethod
110
126
  def _find_missing_frames(frame_list: FrameList | RootHashList) -> list[int]:
111
127
  if frame_list.total_frame == len(frame_list.data):
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import Generic, Literal, TypeVar, Union
2
+ from typing import Any, Generic, Literal, TypeVar, Union
3
3
 
4
4
  from mashumaro import DataClassDictMixin
5
5
  from mashumaro.mixins.orjson import DataClassORJSONMixin
@@ -113,18 +113,62 @@ Items = Union[
113
113
  ]
114
114
 
115
115
 
116
+ @dataclass
117
+ class Item:
118
+ time: int
119
+ value: Union[int, float, str, dict[str, Any]] # Depending on the type of value
120
+
121
+
122
+ @dataclass
123
+ class Items:
124
+ iotState: Item
125
+ extMod: Item
126
+ deviceVersionInfo: Item
127
+ leftMotorBootVersion: Item
128
+ knifeHeight: Item
129
+ rtMrMod: Item
130
+ iotMsgHz: Item
131
+ iotMsgTotal: Item
132
+ loraRawConfig: Item
133
+ loraGeneralConfig: Item
134
+ leftMotorVersion: Item
135
+ intMod: Item
136
+ coordinate: Item
137
+ bmsVersion: Item
138
+ rightMotorVersion: Item
139
+ stm32H7Version: Item
140
+ rightMotorBootVersion: Item
141
+ deviceVersion: Item
142
+ rtkVersion: Item
143
+ ltMrMod: Item
144
+ networkInfo: Item
145
+ bmsHardwareVersion: Item
146
+ batteryPercentage: Item
147
+ deviceState: Item
148
+ deviceOtherInfo: Item
149
+ mcBootVersion: Item
150
+
151
+
116
152
  @dataclass
117
153
  class Params(DataClassORJSONMixin):
154
+ deviceType: Literal["LawnMower"]
118
155
  checkFailedData: dict
119
156
  groupIdList: list[str]
157
+ _tenantId: str
120
158
  groupId: str
121
159
  categoryKey: Literal["LawnMower"]
122
160
  batchId: str
123
161
  gmtCreate: int
124
162
  productKey: str
163
+ generateTime: int
125
164
  deviceName: str
165
+ _traceId: str
126
166
  iotId: str
167
+ JMSXDeliveryCount: int
127
168
  checkLevel: int
169
+ qos: int
170
+ requestId: str
171
+ _categoryKey: str
128
172
  namespace: str
129
173
  tenantId: str
130
174
  thingType: Literal["DEVICE"]
@@ -7,6 +7,7 @@ import betterproto
7
7
 
8
8
  from pymammotion.data.model.device import MowingDevice
9
9
  from pymammotion.data.model.hash_list import AreaHashNameList
10
+ from pymammotion.data.mqtt.properties import ThingPropertiesMessage
10
11
  from pymammotion.proto.luba_msg import LubaMsg
11
12
  from pymammotion.proto.mctrl_nav import AppGetAllAreaHashName, NavGetCommDataAck, NavGetHashListAck
12
13
  from pymammotion.utility.constant import WorkMode
@@ -34,6 +35,10 @@ class StateManager:
34
35
  """Set device."""
35
36
  self._device = device
36
37
 
38
+ async def properties(self, properties: ThingPropertiesMessage) -> None:
39
+ params = properties.params
40
+ self._device.mqtt_properties = params
41
+
37
42
  async def notification(self, message: LubaMsg) -> None:
38
43
  """Handle protobuf notifications."""
39
44
  res = betterproto.which_one_of(message, "LubaSubMsg")
@@ -0,0 +1,22 @@
1
+ from abc import abstractmethod
2
+
3
+ from pymammotion.proto.luba_msg import MsgCmdType, MsgDevice
4
+ from pymammotion.utility.device_type import DeviceType
5
+
6
+
7
+ class AbstractMessage:
8
+ @abstractmethod
9
+ def get_device_name(self) -> str:
10
+ """Get device name."""
11
+
12
+ def get_device_product_key(self) -> str:
13
+ """Get device name."""
14
+
15
+ def get_msg_device(self, msg_type: MsgCmdType, msg_device: MsgDevice) -> MsgDevice:
16
+ """Changes the rcver name if it's not a luba1."""
17
+ if (
18
+ not DeviceType.is_luba1(self.get_device_name(), self.get_device_product_key())
19
+ and msg_type == MsgCmdType.MSG_CMD_TYPE_NAV
20
+ ):
21
+ return MsgDevice.DEV_NAVIGATION
22
+ return msg_device
@@ -1,4 +1,5 @@
1
1
  from pymammotion.mammotion.commands.messages.driver import MessageDriver
2
+ from pymammotion.mammotion.commands.messages.media import MessageMedia
2
3
  from pymammotion.mammotion.commands.messages.navigation import MessageNavigation
3
4
  from pymammotion.mammotion.commands.messages.network import MessageNetwork
4
5
  from pymammotion.mammotion.commands.messages.ota import MessageOta
@@ -7,7 +8,9 @@ from pymammotion.mammotion.commands.messages.video import MessageVideo
7
8
  from pymammotion.utility.movement import get_percent, transform_both_speeds
8
9
 
9
10
 
10
- class MammotionCommand(MessageSystem, MessageNavigation, MessageNetwork, MessageOta, MessageVideo, MessageDriver):
11
+ class MammotionCommand(
12
+ MessageSystem, MessageNavigation, MessageNetwork, MessageOta, MessageVideo, MessageMedia, MessageDriver
13
+ ):
11
14
  """MQTT commands for Luba."""
12
15
 
13
16
  def __init__(self, device_name: str) -> None:
@@ -11,12 +11,11 @@ logger = getLogger(__name__)
11
11
 
12
12
 
13
13
  class MessageDriver(AbstractMessage, ABC):
14
- @staticmethod
15
- def send_order_msg_driver(driver):
14
+ def send_order_msg_driver(self, driver) -> bytes:
16
15
  return LubaMsg(
17
16
  msgtype=MsgCmdType.MSG_CMD_TYPE_EMBED_DRIVER,
18
17
  sender=MsgDevice.DEV_MOBILEAPP,
19
- rcver=MsgDevice.DEV_MAINCTL,
18
+ rcver=self.get_msg_device(MsgCmdType.MSG_CMD_TYPE_EMBED_DRIVER, MsgDevice.DEV_MAINCTL),
20
19
  msgattr=MsgAttr.MSG_ATTR_REQ,
21
20
  timestamp=round(time.time() * 1000),
22
21
  seqs=1,
@@ -1,15 +1,18 @@
1
1
  # === sendOrderMsg_Media ===
2
+ from abc import ABC
3
+
4
+ from pymammotion.mammotion.commands.abstract_message import AbstractMessage
2
5
  from pymammotion.proto import luba_msg_pb2, luba_mul_pb2
6
+ from pymammotion.proto.luba_msg import MsgCmdType, MsgDevice
3
7
  from pymammotion.proto.luba_mul import MUL_LANGUAGE
4
8
 
5
9
 
6
- class MessageMedia:
7
- @staticmethod
10
+ class MessageMedia(AbstractMessage, ABC):
8
11
  def send_order_msg_media(self, mul):
9
12
  luba_msg = luba_msg_pb2.LubaMsg(
10
13
  msgtype=luba_msg_pb2.MSG_CMD_TYPE_MUL,
11
14
  sender=luba_msg_pb2.DEV_MOBILEAPP,
12
- rcver=luba_msg_pb2.SOC_MODULE_MULTIMEDIA,
15
+ rcver=self.get_msg_device(MsgCmdType.MSG_CMD_TYPE_MUL, MsgDevice.SOC_MODULE_MULTIMEDIA),
13
16
  msgattr=luba_msg_pb2.MSG_ATTR_REQ,
14
17
  seqs=1,
15
18
  version=1,
@@ -25,21 +25,11 @@ from pymammotion.proto.mctrl_nav import (
25
25
  WorkReportCmdData,
26
26
  WorkReportUpdateCmd,
27
27
  )
28
- from pymammotion.utility.device_type import DeviceType
29
28
 
30
29
  logger = logging.getLogger(__name__)
31
30
 
32
31
 
33
32
  class MessageNavigation(AbstractMessage, ABC):
34
- def get_msg_device(self, msg_type: MsgCmdType, msg_device: MsgDevice) -> MsgDevice:
35
- """Changes the rcver name if it's not a luba1."""
36
- if (
37
- not DeviceType.is_luba1(self.get_device_name(), self.get_device_product_key())
38
- and msg_type == MsgCmdType.MSG_CMD_TYPE_NAV
39
- ):
40
- return MsgDevice.DEV_NAVIGATION
41
- return msg_device
42
-
43
33
  def send_order_msg_nav(self, build) -> bytes:
44
34
  luba_msg = LubaMsg(
45
35
  msgtype=MsgCmdType.MSG_CMD_TYPE_NAV,
@@ -26,12 +26,22 @@ class MessageNetwork:
26
26
  comm_esp = dev_net_pb2.DevNet(todev_ble_sync=sync_type)
27
27
  return self.send_order_msg_net(comm_esp)
28
28
 
29
- def get_device_base_info(self):
29
+ def get_device_base_info(self) -> bytes:
30
30
  net = dev_net_pb2.DevNet(todev_devinfo_req=dev_net_pb2.DrvDevInfoReq())
31
31
  net.todev_devinfo_req.req_ids.add(id=1, type=6)
32
32
 
33
33
  return self.send_order_msg_net(net)
34
34
 
35
+ def get_device_version_main(self) -> bytes:
36
+ net = dev_net_pb2.DevNet(todev_devinfo_req=dev_net_pb2.DrvDevInfoReq())
37
+
38
+ for i in range(1, 8):
39
+ if i == 1:
40
+ net.todev_devinfo_req.req_ids.add(id=i, type=6)
41
+ net.todev_devinfo_req.req_ids.add(id=i, type=3)
42
+
43
+ return self.send_order_msg_net(net)
44
+
35
45
  def get_4g_module_info(self) -> bytes:
36
46
  build = dev_net_pb2.DevNet(todev_get_mnet_cfg_req=dev_net_pb2.DevNet().todev_get_mnet_cfg_req)
37
47
  logger.debug("Send command -- Get device 4G network module information")
@@ -1,13 +1,17 @@
1
1
  # === sendOrderMsg_Ota ===
2
+ from abc import ABC
3
+
4
+ from pymammotion.mammotion.commands.abstract_message import AbstractMessage
2
5
  from pymammotion.proto import luba_msg_pb2, mctrl_ota_pb2
6
+ from pymammotion.proto.luba_msg import MsgCmdType, MsgDevice
3
7
 
4
8
 
5
- class MessageOta:
9
+ class MessageOta(AbstractMessage, ABC):
6
10
  def send_order_msg_ota(self, ota):
7
11
  luba_msg = luba_msg_pb2.LubaMsg(
8
12
  msgtype=luba_msg_pb2.MSG_CMD_TYPE_EMBED_OTA,
9
13
  sender=luba_msg_pb2.DEV_MOBILEAPP,
10
- rcver=luba_msg_pb2.DEV_MAINCTL,
14
+ rcver=self.get_msg_device(MsgCmdType.MSG_CMD_TYPE_EMBED_OTA, MsgDevice.DEV_MAINCTL),
11
15
  msgattr=luba_msg_pb2.MSG_ATTR_REQ,
12
16
  seqs=1,
13
17
  version=1,
@@ -26,6 +26,16 @@ class MessageSystem(AbstractMessage, ABC):
26
26
  messageNavigation: MessageNavigation = MessageNavigation()
27
27
 
28
28
  def send_order_msg_sys(self, sys):
29
+ luba_msg = LubaMsg(
30
+ msgtype=MsgCmdType.MSG_CMD_TYPE_EMBED_SYS,
31
+ sender=MsgDevice.DEV_MOBILEAPP,
32
+ rcver=self.get_msg_device(MsgCmdType.MSG_CMD_TYPE_EMBED_SYS, MsgDevice.DEV_MAINCTL),
33
+ sys=sys,
34
+ )
35
+
36
+ return luba_msg.SerializeToString()
37
+
38
+ def send_order_msg_sys_legacy(self, sys):
29
39
  luba_msg = LubaMsg(
30
40
  msgtype=MsgCmdType.MSG_CMD_TYPE_EMBED_SYS,
31
41
  sender=MsgDevice.DEV_MOBILEAPP,
@@ -225,9 +235,10 @@ class MessageSystem(AbstractMessage, ABC):
225
235
  )
226
236
  logger.debug(f"Send command==== IOT slim data Act {
227
237
  build.todev_report_cfg.act} {build}")
228
- return self.send_order_msg_sys(build)
238
+ return self.send_order_msg_sys_legacy(build)
229
239
 
230
240
  def get_report_cfg_stop(self, timeout: int = 10000, period: int = 1000, no_change_period: int = 1000):
241
+ # TODO use send_order_msg_sys_legacy
231
242
  mctlsys = MctlSys(
232
243
  todev_report_cfg=ReportInfoCfg(
233
244
  act=RptAct.RPT_STOP,
@@ -260,6 +271,7 @@ class MessageSystem(AbstractMessage, ABC):
260
271
  return lubaMsg.SerializeToString()
261
272
 
262
273
  def get_report_cfg(self, timeout: int = 10000, period: int = 1000, no_change_period: int = 2000):
274
+ # TODO use send_order_msg_sys_legacy
263
275
  mctlsys = MctlSys(
264
276
  todev_report_cfg=ReportInfoCfg(
265
277
  act=RptAct.RPT_START,
@@ -1,15 +1,18 @@
1
1
  # === sendOrderMsg_Video ===
2
+ from abc import ABC
3
+
2
4
  from pymammotion.mammotion.commands.abstract_message import AbstractMessage
3
5
  from pymammotion.proto import luba_msg_pb2, luba_mul_pb2
6
+ from pymammotion.proto.luba_msg import MsgCmdType, MsgDevice
4
7
  from pymammotion.utility.device_type import DeviceType
5
8
 
6
9
 
7
- class MessageVideo(AbstractMessage):
10
+ class MessageVideo(AbstractMessage, ABC):
8
11
  async def send_order_msg_video(self, mul):
9
12
  luba_msg = luba_msg_pb2.LubaMsg(
10
13
  msgtype=luba_msg_pb2.MSG_CMD_TYPE_MUL,
11
14
  sender=luba_msg_pb2.DEV_MOBILEAPP,
12
- rcver=luba_msg_pb2.SOC_MODULE_MULTIMEDIA,
15
+ rcver=self.get_msg_device(MsgCmdType.MSG_CMD_TYPE_MUL, MsgDevice.SOC_MODULE_MULTIMEDIA),
13
16
  mul=mul,
14
17
  )
15
18
 
@@ -74,7 +74,7 @@ class MammotionBaseDevice:
74
74
  if len(missing_frames) == 0:
75
75
  # get next in hash ack list
76
76
 
77
- data_hash = self.mower.map.missing_hashlist.pop()
77
+ data_hash = self.mower.map.missing_hashlist.pop() if len(self.mower.map.missing_hashlist) > 0 else None
78
78
  if data_hash is None:
79
79
  return
80
80
 
@@ -299,7 +299,7 @@ class Mammotion:
299
299
  _LOGGER.debug(_stream_response)
300
300
  return _stream_response
301
301
 
302
- def mower(self, name: str):
302
+ def mower(self, name: str) -> MowingDevice | None:
303
303
  device = self.get_device_by_name(name)
304
304
  if device:
305
305
  return device.mower_state
@@ -13,6 +13,7 @@ from pymammotion.aliyun.cloud_gateway import DeviceOfflineException, SetupExcept
13
13
  from pymammotion.aliyun.model.dev_by_account_response import Device
14
14
  from pymammotion.data.model.device import MowingDevice
15
15
  from pymammotion.data.mqtt.event import ThingEventMessage
16
+ from pymammotion.data.mqtt.properties import ThingPropertiesMessage
16
17
  from pymammotion.event.event import DataEvent
17
18
  from pymammotion.mammotion.commands.mammotion_command import MammotionCommand
18
19
  from pymammotion.mammotion.devices.base import MammotionBaseDevice
@@ -33,6 +34,7 @@ class MammotionCloud:
33
34
  self.command_queue = asyncio.Queue()
34
35
  self._waiting_queue = deque()
35
36
  self.mqtt_message_event = DataEvent()
37
+ self.mqtt_properties_event = DataEvent()
36
38
  self.on_ready_event = DataEvent()
37
39
  self.on_disconnected_event = DataEvent()
38
40
  self._operation_lock = asyncio.Lock()
@@ -127,6 +129,7 @@ class MammotionCloud:
127
129
  # Call the callbacks for each cloudDevice
128
130
  await self.mqtt_message_event.data_event(event)
129
131
  if event.method == "thing.properties":
132
+ await self.mqtt_properties_event.data_event(event)
130
133
  _LOGGER.debug(event)
131
134
 
132
135
  async def _handle_mqtt_message(self, topic: str, payload: dict) -> None:
@@ -159,6 +162,7 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
159
162
  self._commands: MammotionCommand = MammotionCommand(cloud_device.deviceName)
160
163
  self.currentID = ""
161
164
  self._mqtt.mqtt_message_event.add_subscribers(self._parse_message_for_device)
165
+ self._mqtt.mqtt_properties_event.add_subscribers(self._parse_message_properties_for_device)
162
166
  self._mqtt.on_ready_event.add_subscribers(self.on_ready)
163
167
  self._mqtt.on_disconnected_event.add_subscribers(self.on_disconnect)
164
168
  self.set_queue_callback(self.queue_command)
@@ -247,6 +251,11 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
247
251
  return item
248
252
  return None
249
253
 
254
+ async def _parse_message_properties_for_device(self, event: ThingPropertiesMessage) -> None:
255
+ if event.params.iotId != self.iot_id:
256
+ return
257
+ self.state_manager.properties(event)
258
+
250
259
  async def _parse_message_for_device(self, event: ThingEventMessage) -> None:
251
260
  params = event.params
252
261
  if event.params.iotId != self.iot_id:
@@ -141,7 +141,7 @@ message NavGetCommData {
141
141
  int32 subCmd = 2;
142
142
  int32 action = 3;
143
143
  int32 type = 4;
144
- fixed64 Hash = 5;
144
+ int64 hash = 5;
145
145
  int64 paternalHashA = 6;
146
146
  int64 paternalHashB = 7;
147
147
  int32 totalFrame = 8;
@@ -434,7 +434,7 @@ message NavTaskCtrlAck {
434
434
 
435
435
  message NavMapNameMsg {
436
436
  int32 rw = 1; // Represents RW field
437
- fixed64 hash = 2; // Represents HASH field
437
+ int64 hash = 2; // Represents HASH field
438
438
  string name = 3; // Represents NAME field
439
439
  int32 result = 4; // Represents RESULT field
440
440
  string device_id = 5; // Represents DEVICEID field
@@ -470,7 +470,7 @@ message SvgMessageAckT {
470
470
 
471
471
  message AreaHashName {
472
472
  string name = 2;
473
- fixed64 hash = 1;
473
+ int64 hash = 1;
474
474
  }
475
475
 
476
476
  message AppGetAllAreaHashName {
@@ -131,7 +131,7 @@ message vision_point_msg {
131
131
  }
132
132
 
133
133
  message vision_point_info_msg {
134
- int32 lable = 1;
134
+ int32 label = 1;
135
135
  int32 num = 2;
136
136
  repeated vision_point_msg vision_point = 3;
137
137
  }
@@ -258,6 +258,12 @@ message rpt_lora {
258
258
  int32 lora_connection_status = 5;
259
259
  }
260
260
 
261
+ message mqtt_rtk_connect {
262
+ int32 rtk_switch = 1;
263
+ int32 rtk_channel = 2;
264
+ string rtk_base_num = 3;
265
+ }
266
+
261
267
  message rpt_rtk {
262
268
  int32 status = 1;
263
269
  int32 pos_level = 2;
@@ -271,6 +277,7 @@ message rpt_rtk {
271
277
  int32 co_view_stars = 10;
272
278
  int32 reset = 11;
273
279
  rpt_lora lora_info = 12;
280
+ mqtt_rtk_connect mqtt_rtk_info = 13;
274
281
  }
275
282
 
276
283
  message rpt_dev_location {
@@ -316,6 +323,12 @@ message rpt_connect_status {
316
323
  int32 mnet_rssi = 5;
317
324
  int32 mnet_inet = 6;
318
325
  net_used_type used_net = 7;
326
+ MnetCfg mnet_cfg = 8;
327
+ }
328
+
329
+
330
+ message nav_heading_state_t {
331
+ int32 heading_state = 1;
319
332
  }
320
333
 
321
334
  message rpt_work {
@@ -339,6 +352,7 @@ message rpt_work {
339
352
  int32 man_run_speed = 18;
340
353
  int32 nav_edit_status = 19;
341
354
  int32 knife_height = 20;
355
+ nav_heading_state_t nav_heading_state = 21;
342
356
  }
343
357
 
344
358
  message rpt_maintain {
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "pymammotion"
3
- version = "0.2.51"
3
+ version = "0.2.52"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "pymammotion"
7
- version = "0.2.51"
7
+ version = "0.2.52"
8
8
  license = "GNU-3.0"
9
9
  description = ""
10
10
  readme = "README.md"
@@ -55,7 +55,7 @@ mypy = "^1.10.0"
55
55
  pre-commit = "^3.8.0"
56
56
 
57
57
  [tool.bumpver]
58
- current_version = "0.2.51"
58
+ current_version = "0.2.52"
59
59
  version_pattern = "MAJOR.MINOR.PATCH"
60
60
  commit_message = "Bump version {old_version} -> {new_version}"
61
61
  commit = true
@@ -1,10 +0,0 @@
1
- from abc import abstractmethod
2
-
3
-
4
- class AbstractMessage:
5
- @abstractmethod
6
- def get_device_name(self) -> str:
7
- """Get device name."""
8
-
9
- def get_device_product_key(self) -> str:
10
- """Get device name."""
File without changes
File without changes