pymammotion 0.2.62__py3-none-any.whl → 0.2.64__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.
@@ -141,17 +141,17 @@ class BleMessage:
141
141
  # Log.d(TAG, "parseNotification Notification= " + Arrays.toString(response));
142
142
  # }
143
143
  if len(response) >= 4:
144
- sequence = int(response[2]) # toInt
145
- if sequence != next(self.mReadSequence):
146
- _LOGGER.debug(
147
- "parseNotification read sequence wrong",
148
- sequence,
149
- self.mReadSequence,
150
- )
151
- self.mReadSequence = itertools.count(start=sequence)
152
- # this is questionable
153
- # self.mReadSequence = sequence
154
- # self.mReadSequence_2.incrementAndGet()
144
+ # sequence = int(response[2]) # toInt
145
+ # if sequence != next(self.mReadSequence):
146
+ # _LOGGER.debug(
147
+ # "parseNotification read sequence wrong",
148
+ # sequence,
149
+ # self.mReadSequence,
150
+ # )
151
+ # self.mReadSequence = itertools.count(start=sequence)
152
+ # this is questionable
153
+ # self.mReadSequence = sequence
154
+ # self.mReadSequence_2.incrementAndGet()
155
155
 
156
156
  # LogUtil.m7773e(self.mGatt.getDevice().getName() + "打印丢包率", self.mReadSequence_2 + "/" + self.mReadSequence_1);
157
157
  pkt_type = int(response[0]) # toInt
@@ -36,7 +36,7 @@ class MowingDevice(DataClassORJSONMixin):
36
36
  """Wraps the betterproto dataclasses, so we can bypass the groups for keeping all data."""
37
37
 
38
38
  mower_state: MowerInfo = field(default_factory=MowerInfo)
39
- mqtt_properties: ThingPropertiesMessage = field(default_factory=ThingPropertiesMessage)
39
+ mqtt_properties: ThingPropertiesMessage | None = None
40
40
  map: HashList = field(default_factory=HashList)
41
41
  location: Location = field(default_factory=Location)
42
42
  mowing_state: RapidState = field(default_factory=RapidState)
@@ -3,7 +3,7 @@ from enum import IntEnum
3
3
 
4
4
  from mashumaro.mixins.orjson import DataClassORJSONMixin
5
5
 
6
- from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck
6
+ from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
7
7
 
8
8
 
9
9
  class PathType(IntEnum):
@@ -13,12 +13,13 @@ class PathType(IntEnum):
13
13
  OBSTACLE = 1
14
14
  PATH = 2
15
15
  DUMP = 12
16
+ SVG = 13
16
17
 
17
18
 
18
19
  @dataclass
19
20
  class FrameList(DataClassORJSONMixin):
20
21
  total_frame: int
21
- data: list[NavGetCommDataAck]
22
+ data: list[NavGetCommDataAck | SvgMessageAckT]
22
23
 
23
24
 
24
25
  @dataclass
@@ -52,6 +53,7 @@ class HashList(DataClassORJSONMixin):
52
53
  path: dict = field(default_factory=dict) # type 2
53
54
  obstacle: dict = field(default_factory=dict) # type 1
54
55
  dump: dict = field(default_factory=dict) # type 12?
56
+ svg: dict = field(default_factory=dict) # type 13
55
57
  area_name: list[AreaHashNameList] = field(default_factory=list)
56
58
 
57
59
  def update_hash_lists(self, hashlist: list[int]) -> None:
@@ -59,6 +61,7 @@ class HashList(DataClassORJSONMixin):
59
61
  self.path = {hash_id: frames for hash_id, frames in self.path.items() if hash_id in hashlist}
60
62
  self.obstacle = {hash_id: frames for hash_id, frames in self.obstacle.items() if hash_id in hashlist}
61
63
  self.dump = {hash_id: frames for hash_id, frames in self.dump.items() if hash_id in hashlist}
64
+ self.svg = {hash_id: frames for hash_id, frames in self.svg.items() if hash_id in hashlist}
62
65
 
63
66
  @property
64
67
  def hashlist(self) -> list[int]:
@@ -72,7 +75,10 @@ class HashList(DataClassORJSONMixin):
72
75
  i
73
76
  for obj in self.root_hash_list.data
74
77
  for i in obj.data_couple
75
- if i not in set(self.area.keys()).union(self.path.keys(), self.obstacle.keys(), self.dump.keys())
78
+ if i
79
+ not in set(self.area.keys()).union(
80
+ self.path.keys(), self.obstacle.keys(), self.dump.keys(), self.svg.keys()
81
+ )
76
82
  ]
77
83
 
78
84
  def update_root_hash_list(self, hash_list: NavGetHashListAck) -> None:
@@ -90,7 +96,7 @@ class HashList(DataClassORJSONMixin):
90
96
  def missing_hash_frame(self):
91
97
  return self._find_missing_frames(self.root_hash_list)
92
98
 
93
- def missing_frame(self, hash_data: NavGetCommDataAck) -> list[int]:
99
+ def missing_frame(self, hash_data: NavGetCommDataAck | SvgMessageAckT) -> list[int]:
94
100
  if hash_data.type == PathType.AREA:
95
101
  return self._find_missing_frames(self.area.get(hash_data.hash))
96
102
 
@@ -103,12 +109,16 @@ class HashList(DataClassORJSONMixin):
103
109
  if hash_data.type == PathType.DUMP:
104
110
  return self._find_missing_frames(self.dump.get(hash_data.hash))
105
111
 
106
- def update(self, hash_data: NavGetCommDataAck) -> bool:
112
+ if hash_data.type == PathType.SVG:
113
+ return self._find_missing_frames(self.svg.get(hash_data.data_hash))
114
+
115
+ def update(self, hash_data: NavGetCommDataAck | SvgMessageAckT) -> bool:
107
116
  """Update the map data."""
108
117
  if hash_data.type == PathType.AREA:
109
118
  existing_name = next((area for area in self.area_name if area.hash == hash_data.hash), None)
110
119
  if not existing_name:
111
- self.area_name.append(AreaHashNameList(name=f"area {len(self.area_name)+1}", hash=hash_data.hash))
120
+ name = f"area {len(self.area_name)+1}" if hash_data.area_label is None else hash_data.area_label.label
121
+ self.area_name.append(AreaHashNameList(name=name, hash=hash_data.hash))
112
122
  return self._add_hash_data(self.area, hash_data)
113
123
 
114
124
  if hash_data.type == PathType.OBSTACLE:
@@ -120,6 +130,9 @@ class HashList(DataClassORJSONMixin):
120
130
  if hash_data.type == PathType.DUMP:
121
131
  return self._add_hash_data(self.dump, hash_data)
122
132
 
133
+ if hash_data.type == PathType.SVG:
134
+ return self._add_hash_data(self.svg, hash_data)
135
+
123
136
  @staticmethod
124
137
  def _find_missing_frames(frame_list: FrameList | RootHashList) -> list[int]:
125
138
  if frame_list.total_frame == len(frame_list.data):
@@ -131,7 +144,17 @@ class HashList(DataClassORJSONMixin):
131
144
  return missing_numbers
132
145
 
133
146
  @staticmethod
134
- def _add_hash_data(hash_dict: dict, hash_data: NavGetCommDataAck) -> bool:
147
+ def _add_hash_data(hash_dict: dict, hash_data: NavGetCommDataAck | SvgMessageAckT) -> bool:
148
+ if isinstance(hash_data, SvgMessageAckT):
149
+ if hash_dict.get(hash_data.data_hash) is None:
150
+ hash_dict[hash_data.data_hash] = FrameList(total_frame=hash_data.total_frame, data=[hash_data])
151
+ return True
152
+
153
+ if hash_data not in hash_dict[hash_data.data_hash].data:
154
+ hash_dict[hash_data.data_hash].data.append(hash_data)
155
+ return True
156
+ return False
157
+
135
158
  if hash_dict.get(hash_data.hash) is None:
136
159
  hash_dict[hash_data.hash] = FrameList(total_frame=hash_data.total_frame, data=[hash_data])
137
160
  return True
@@ -6,16 +6,14 @@ from typing import Any, Awaitable, Callable, Optional
6
6
 
7
7
  import betterproto
8
8
 
9
- from pymammotion.proto.dev_net import WifiIotStatusReport
10
- from pymammotion.aliyun.cloud_gateway import SetupException
11
9
  from pymammotion.data.model.device import MowingDevice
12
10
  from pymammotion.data.model.device_info import SideLight
13
11
  from pymammotion.data.model.hash_list import AreaHashNameList
14
12
  from pymammotion.data.mqtt.properties import ThingPropertiesMessage
13
+ from pymammotion.proto.dev_net import WifiIotStatusReport
15
14
  from pymammotion.proto.luba_msg import LubaMsg
16
- from pymammotion.proto.mctrl_nav import AppGetAllAreaHashName, NavGetCommDataAck, NavGetHashListAck
17
- from pymammotion.proto.mctrl_sys import TimeCtrlLight, DeviceProductTypeInfoT
18
- from pymammotion.utility.constant import WorkMode
15
+ from pymammotion.proto.mctrl_nav import AppGetAllAreaHashName, NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
16
+ from pymammotion.proto.mctrl_sys import DeviceProductTypeInfoT, TimeCtrlLight
19
17
 
20
18
  logger = logging.getLogger(__name__)
21
19
 
@@ -29,7 +27,9 @@ class StateManager:
29
27
  def __init__(self, device: MowingDevice) -> None:
30
28
  self._device = device
31
29
  self.gethash_ack_callback: Optional[Callable[[NavGetHashListAck], Awaitable[None]]] = None
32
- self.get_commondata_ack_callback: Optional[Callable[[NavGetCommDataAck], Awaitable[None]]] = None
30
+ self.get_commondata_ack_callback: Optional[Callable[[NavGetCommDataAck | SvgMessageAckT], Awaitable[None]]] = (
31
+ None
32
+ )
33
33
  self.on_notification_callback: Optional[Callable[[], Awaitable[None]]] = None
34
34
  self.queue_command_callback: Optional[Callable[[str, dict[str, Any]], Awaitable[bytes]]] = None
35
35
  self.last_updated_at = datetime.now()
@@ -81,6 +81,12 @@ class StateManager:
81
81
  updated = self._device.map.update(common_data)
82
82
  if updated:
83
83
  await self.get_commondata_ack_callback(common_data)
84
+ case "toapp_svg_msg":
85
+ common_data: SvgMessageAckT = nav_msg[1]
86
+ updated = self._device.map.update(common_data)
87
+ if updated:
88
+ await self.get_commondata_ack_callback(common_data)
89
+
84
90
  case "toapp_all_hash_name":
85
91
  hash_names: AppGetAllAreaHashName = nav_msg[1]
86
92
  converted_list = [AreaHashNameList(name=item.name, hash=item.hash) for item in hash_names.hashnames]
@@ -94,13 +100,6 @@ class StateManager:
94
100
  self._device.buffer(sys_msg[1])
95
101
  case "toapp_report_data":
96
102
  self._device.update_report_data(sys_msg[1])
97
- if self.queue_command_callback:
98
- if self._device.sys.toapp_report_data.dev.sys_status != WorkMode.MODE_WORKING:
99
- try:
100
- await self.queue_command_callback("get_report_cfg_stop")
101
- except SetupException as exc:
102
- # can't do anything about it yet
103
- logger.debug(exc)
104
103
  case "mow_to_app_info":
105
104
  self._device.mow_info(sys_msg[1])
106
105
  case "system_tard_state_tunnel":
@@ -10,7 +10,7 @@ from pymammotion.data.model import RegionData
10
10
  from pymammotion.data.model.device import MowingDevice
11
11
  from pymammotion.data.state_manager import StateManager
12
12
  from pymammotion.proto.luba_msg import LubaMsg
13
- from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck
13
+ from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
14
14
 
15
15
  _LOGGER = logging.getLogger(__name__)
16
16
 
@@ -65,7 +65,7 @@ class MammotionBaseDevice:
65
65
  current_frame = missing_frames[0] - 1
66
66
  await self.queue_command("get_hash_response", total_frame=hash_ack.total_frame, current_frame=current_frame)
67
67
 
68
- async def commdata_response(self, common_data: NavGetCommDataAck) -> None:
68
+ async def commdata_response(self, common_data: NavGetCommDataAck | SvgMessageAckT) -> None:
69
69
  """Handle common data responses."""
70
70
  total_frame = common_data.total_frame
71
71
  current_frame = common_data.current_frame
@@ -84,8 +84,8 @@ class MammotionBaseDevice:
84
84
  current_frame = missing_frames[0] - 1
85
85
 
86
86
  region_data = RegionData()
87
- region_data.hash = common_data.hash
88
- region_data.action = common_data.action
87
+ region_data.hash = common_data.data_hash if isinstance(common_data, SvgMessageAckT) else common_data.hash
88
+ region_data.action = common_data.action if isinstance(common_data, NavGetCommDataAck) else None
89
89
  region_data.type = common_data.type
90
90
  region_data.total_frame = total_frame
91
91
  region_data.current_frame = current_frame
@@ -72,7 +72,7 @@ class MammotionMixedDeviceManager:
72
72
  if self.has_cloud() and self.preference == ConnectionPreference.WIFI:
73
73
  return not self.cloud()._mqtt.command_queue.empty()
74
74
  else:
75
- return False
75
+ return not self.ble().command_queue.empty()
76
76
 
77
77
  def add_ble(self, ble_device: BLEDevice) -> None:
78
78
  if ble_device is not None:
@@ -116,8 +116,9 @@ class MammotionDevices:
116
116
  def get_device(self, mammotion_device_name: str) -> MammotionMixedDeviceManager:
117
117
  return self.devices.get(mammotion_device_name)
118
118
 
119
- async def remove_device(self, name) -> None:
119
+ async def remove_device(self, name: str) -> None:
120
120
  device_for_removal = self.devices.pop(name)
121
+ loop = asyncio.get_running_loop()
121
122
  if device_for_removal.has_cloud():
122
123
  should_disconnect = {
123
124
  device
@@ -125,7 +126,7 @@ class MammotionDevices:
125
126
  if device.cloud() is not None and device.cloud()._mqtt == device_for_removal.cloud()._mqtt
126
127
  }
127
128
  if len(should_disconnect) == 0:
128
- device_for_removal.cloud()._mqtt.disconnect()
129
+ await loop.run_in_executor(None, device_for_removal.cloud().mqtt.disconnect)
129
130
  await device_for_removal.cloud().stop()
130
131
  if device_for_removal.has_ble():
131
132
  await device_for_removal.ble().stop()
@@ -83,17 +83,21 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
83
83
  self._disconnect_timer: asyncio.TimerHandle | None = None
84
84
  self._message: BleMessage | None = None
85
85
  self._commands: MammotionCommand = MammotionCommand(device.name)
86
+ self.command_queue = asyncio.Queue()
86
87
  self._expected_disconnect = False
87
88
  self._connect_lock = asyncio.Lock()
88
89
  self._operation_lock = asyncio.Lock()
89
90
  self._key: str | None = None
90
91
  self.set_queue_callback(self.queue_command)
92
+ loop = asyncio.get_event_loop()
93
+ loop.create_task(self.process_queue())
91
94
 
92
95
  def update_device(self, device: BLEDevice) -> None:
93
96
  """Update the BLE device."""
94
97
  self._device = device
95
98
 
96
99
  async def _ble_sync(self) -> None:
100
+ _LOGGER.debug("BLE SYNC")
97
101
  command_bytes = self._commands.send_todev_ble_sync(2)
98
102
  await self._message.post_custom_data_bytes(command_bytes)
99
103
 
@@ -114,10 +118,35 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
114
118
  async def stop(self) -> None:
115
119
  """Stop all tasks and disconnect."""
116
120
  self._ble_sync_task.cancel()
117
- await self._client.disconnect()
121
+ if self._client is not None:
122
+ await self._client.disconnect()
118
123
 
119
124
  async def queue_command(self, key: str, **kwargs: Any) -> bytes | None:
120
- return await self._send_command_with_args(key, **kwargs)
125
+ # Create a future to hold the result
126
+ _LOGGER.debug("Queueing command: %s", key)
127
+ future = asyncio.Future()
128
+ # Put the command in the queue as a tuple (key, command, future)
129
+ command_bytes = getattr(self._commands, key)(**kwargs)
130
+ await self.command_queue.put((key, command_bytes, future))
131
+ # Wait for the future to be resolved
132
+ return await future
133
+ # return await self._send_command_with_args(key, **kwargs)
134
+
135
+ async def process_queue(self) -> None:
136
+ while True:
137
+ # Get the next item from the queue
138
+ key, command, future = await self.command_queue.get()
139
+ try:
140
+ # Process the command using _execute_command_locked
141
+ result = await self._send_command_locked(key, command)
142
+ # Set the result on the future
143
+ future.set_result(result)
144
+ except Exception as ex:
145
+ # Set the exception on the future if something goes wrong
146
+ future.set_exception(ex)
147
+ finally:
148
+ # Mark the task as done
149
+ self.command_queue.task_done()
121
150
 
122
151
  async def _send_command_with_args(self, key: str, **kwargs) -> bytes | None:
123
152
  """Send command to device and read response."""
@@ -255,8 +284,7 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
255
284
  )
256
285
  self._reset_disconnect_timer()
257
286
  await self._start_notify()
258
- command_bytes = self._commands.send_todev_ble_sync(2)
259
- await self._message.post_custom_data_bytes(command_bytes)
287
+ self._ble_sync()
260
288
  self.schedule_ble_sync()
261
289
 
262
290
  async def _send_command_locked(self, key: str, command: bytes) -> bytes:
@@ -9,7 +9,7 @@ from typing import Any, Awaitable, Callable, Optional, cast
9
9
  import betterproto
10
10
 
11
11
  from pymammotion import CloudIOTGateway, MammotionMQTT
12
- from pymammotion.aliyun.cloud_gateway import DeviceOfflineException, SetupException
12
+ from pymammotion.aliyun.cloud_gateway import DeviceOfflineException
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
@@ -182,15 +182,11 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
182
182
  await self.on_ready_callback()
183
183
  except DeviceOfflineException:
184
184
  await self.stop()
185
- except SetupException:
186
- await self.stop()
187
185
 
188
186
  async def on_disconnect(self) -> None:
189
187
  if self._ble_sync_task:
190
188
  self._ble_sync_task.cancel()
191
- loop = asyncio.get_event_loop()
192
189
  self._mqtt.disconnect()
193
- await loop.run_in_executor(None, self._mqtt.cloud_client.sign_out)
194
190
 
195
191
  async def stop(self) -> None:
196
192
  """Stop all tasks and disconnect."""
@@ -199,6 +195,13 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
199
195
  self._mqtt.on_ready_event.remove_subscribers(self.on_ready)
200
196
  self.stopped = True
201
197
 
198
+ async def start(self) -> None:
199
+ await self._ble_sync()
200
+ if self._ble_sync_task is None or self._ble_sync_task.cancelled():
201
+ await self.run_periodic_sync_task()
202
+ self.stopped = False
203
+ self.mqtt.connect_async()
204
+
202
205
  async def _ble_sync(self) -> None:
203
206
  command_bytes = self._commands.send_todev_ble_sync(3)
204
207
  loop = asyncio.get_running_loop()
@@ -150,6 +150,10 @@ message NavGetCommData {
150
150
  string reserved = 11;
151
151
  }
152
152
 
153
+ message AreaLabel {
154
+ string label = 1;
155
+ }
156
+
153
157
  message NavGetCommDataAck {
154
158
  int32 pver = 1;
155
159
  int32 subCmd = 2;
@@ -165,6 +169,7 @@ message NavGetCommDataAck {
165
169
  int32 dataLen = 12;
166
170
  repeated CommDataCouple dataCouple = 13;
167
171
  string reserved = 14;
172
+ AreaLabel areaLabel = 15;
168
173
  }
169
174
 
170
175
  message NavReqCoverPath {
@@ -173,6 +173,9 @@ class NavGetCommData(betterproto.Message):
173
173
  data_hash: int = betterproto.fixed64_field(10)
174
174
  reserved: str = betterproto.string_field(11)
175
175
 
176
+ @dataclass
177
+ class AreaLabel(betterproto.Message):
178
+ label: str = betterproto.string_field(1)
176
179
 
177
180
  @dataclass
178
181
  class NavGetCommDataAck(betterproto.Message):
@@ -190,6 +193,7 @@ class NavGetCommDataAck(betterproto.Message):
190
193
  data_len: int = betterproto.int32_field(12)
191
194
  data_couple: list["CommDataCouple"] = betterproto.message_field(13)
192
195
  reserved: str = betterproto.string_field(14)
196
+ area_label: AreaLabel = betterproto.message_field(15)
193
197
 
194
198
 
195
199
  @dataclass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymammotion
3
- Version: 0.2.62
3
+ Version: 0.2.64
4
4
  Summary:
5
5
  License: GNU-3.0
6
6
  Author: Michael Arthur
@@ -12,7 +12,7 @@ pymammotion/aliyun/model/stream_subscription_response.py,sha256=po765WASQDboVCos
12
12
  pymammotion/aliyun/tmp_constant.py,sha256=M4Hq_lrGB3LZdX6R2XohRPFoK1NDnNV-pTJwJcJ9838,6650
13
13
  pymammotion/bluetooth/__init__.py,sha256=LAl8jqZ1fPh-3mLmViNQsP3s814C1vsocYUa6oSaXt0,36
14
14
  pymammotion/bluetooth/ble.py,sha256=YfkfEK3TLJ8BaidjAXfUVFv8reLCu6U_lYa3Bo0pddw,2449
15
- pymammotion/bluetooth/ble_message.py,sha256=cnUJHfMj9Sf5LOSIgQ5XP4A-Jbc-BjorSS48YfOUCpM,15444
15
+ pymammotion/bluetooth/ble_message.py,sha256=XzsXcKv29GbGAnivYvZLfDOiMVAWsilk70N4TVwFl50,15448
16
16
  pymammotion/bluetooth/const.py,sha256=CCqyHsYbB0BAYjwdhXt_n6eWWxmhlUrAFjvVv57mbvE,1749
17
17
  pymammotion/bluetooth/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  pymammotion/bluetooth/data/convert.py,sha256=6DMwvzVr9FWCoQFIKSI2poFXjISc_m6X59g8FlVO0-o,800
@@ -22,14 +22,14 @@ pymammotion/const.py,sha256=lWRxvTVdXnNHuxqvRkjO5ziK0Ic-fZMM6J2dbe5M6Nc,385
22
22
  pymammotion/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  pymammotion/data/model/__init__.py,sha256=aSyroxYQQS-WMRi6WmWm2js4wLa9nmsi160gx9tts4o,323
24
24
  pymammotion/data/model/account.py,sha256=vJM-KTf2q6eBfVC-UlNHBSmJvqHiCawZ40vnuhXhaz8,140
25
- pymammotion/data/model/device.py,sha256=C0zi5rhmCXPuxpTh-ckzFkAhC1oGQcHUxNb0Li2N1ag,12349
25
+ pymammotion/data/model/device.py,sha256=uta1BzfCIKd7Z0naw7JcEGy273yMdcAJ7pjidfpGhKQ,12315
26
26
  pymammotion/data/model/device_config.py,sha256=SMBrG-rjN58Z59V-ok3wQ0721BQxM9zSdYXI3Q8GFdY,2828
27
27
  pymammotion/data/model/device_info.py,sha256=ahz2xILdSYdX6SIVuVzz8QCfSQLefbQnpXrsiDpBDbY,585
28
28
  pymammotion/data/model/enums.py,sha256=EpKmO8yVUZyEnTY4yH0DMMVKYNQM42zpW1maUu0i3IE,1582
29
29
  pymammotion/data/model/excute_boarder_params.py,sha256=9CpUqrygcle1C_1hDW-riLmm4map4ZbE842NXjcomEI,1394
30
30
  pymammotion/data/model/execute_boarder.py,sha256=9rd_h4fbcsXxgnLOd2rO2hWyD1abnTGc47QTEpp8DD0,1103
31
31
  pymammotion/data/model/generate_route_information.py,sha256=MkUBoqGtCAKmiVQ4Q1pEoDVHZs5uLIo7vhfWT4nGbtY,801
32
- pymammotion/data/model/hash_list.py,sha256=v9zoOhrwr1TMTsyPL-BQSylbqfapmO4l5oIefaW9YHw,5183
32
+ pymammotion/data/model/hash_list.py,sha256=ZPg5d1hy4bPMgPw5JkHujT06LIoEmXn7qSdQW79FF3A,6257
33
33
  pymammotion/data/model/location.py,sha256=PwmITejfI4pm7PI4rzqSuuHetwle6IJr_CV95435s2M,871
34
34
  pymammotion/data/model/mowing_modes.py,sha256=5TrHSijUyPtIDWpNtgzx_vFQukRJWRz4gIrUaXggKPw,827
35
35
  pymammotion/data/model/plan.py,sha256=mcadkSL7fQXy0iJ0q786I3GEQY4i6kmQXfW6Ri69lcQ,2906
@@ -40,7 +40,7 @@ pymammotion/data/mqtt/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdr
40
40
  pymammotion/data/mqtt/event.py,sha256=z6j8t-ZOjEeKjFt7S0wV8vV5L0-iHD3RbwI9hCfzGTY,5044
41
41
  pymammotion/data/mqtt/properties.py,sha256=kvphcjrDuJHuX8Az98-wKeFv_rSmu2Fz9YKLGodGSj0,3759
42
42
  pymammotion/data/mqtt/status.py,sha256=zqnlo-MzejEQZszl0i0Wucoc3E76x6UtI9JLxoBnu54,1067
43
- pymammotion/data/state_manager.py,sha256=Pj5cuaPJVBUkZS_IgGk5StD-gPXxHtrkTeIGe3z3Lik,5577
43
+ pymammotion/data/state_manager.py,sha256=vtBT28-5DY58hJMi_kqOUKnOq6rJ4fx1zX8yU7N96A8,5357
44
44
  pymammotion/event/__init__.py,sha256=mgATR6vPHACNQ-0zH5fi7NdzeTCDV1CZyaWPmtUusi8,115
45
45
  pymammotion/event/event.py,sha256=UzYnxV5DfvMDK3E06UvSzvzuBbaXOOUwO6xYt_zn9To,2034
46
46
  pymammotion/http/_init_.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -61,10 +61,10 @@ pymammotion/mammotion/commands/messages/video.py,sha256=ne1YSuQChaDFfmHgMO5Jc9_O
61
61
  pymammotion/mammotion/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
62
  pymammotion/mammotion/control/joystick.py,sha256=QfBVxM_gxpWsZAGO90whtgxCI2tIZ3TTad9wHIPsU9s,5640
63
63
  pymammotion/mammotion/devices/__init__.py,sha256=f2qQFPgLGmV85W2hSlMUh5BYuht9o_Ar_JEAAMD4fsE,102
64
- pymammotion/mammotion/devices/base.py,sha256=Q5acOJEevJji_fI09R6qbupzvkxGsteJxcWsfTjqLXc,9861
65
- pymammotion/mammotion/devices/mammotion.py,sha256=KRtGSoDY9FxeehOZAlzasmk0fO-2Ru1fkw6McFEovzA,12373
66
- pymammotion/mammotion/devices/mammotion_bluetooth.py,sha256=nyO7pkKgAoRPs-28ESf6ee-y3G5JTYRO-MCp4wKPMlE,17476
67
- pymammotion/mammotion/devices/mammotion_cloud.py,sha256=EbIdtOYOZS6E0RoIDgHJmGBOTjGIKx77ZDtA9BerF-M,11945
64
+ pymammotion/mammotion/devices/base.py,sha256=F_L5aDtY6rgRkk7Q4CwilLenTANW6cBe9zIU3a9HRmA,10020
65
+ pymammotion/mammotion/devices/mammotion.py,sha256=hSO184o1q4ftfLPx9froFPIXk428wGg8Ayw160W3z7c,12482
66
+ pymammotion/mammotion/devices/mammotion_bluetooth.py,sha256=LEaUazTeIsBiqmt3Yhhxcw26VjwJmvbI83xqUycXMOg,18665
67
+ pymammotion/mammotion/devices/mammotion_cloud.py,sha256=MIBdakx7rvfrIqiVcq5Ry1qkqRVp1ykvU20vFW4Dg58,12006
68
68
  pymammotion/mqtt/__init__.py,sha256=Ocs5e-HLJvTuDpVXyECEsWIvwsUaxzj7lZ9mSYutNDY,105
69
69
  pymammotion/mqtt/mammotion_future.py,sha256=_OWqKOlUGl2yT1xOsXFQYpGd-1zQ63OxqXgy7KRQgYc,710
70
70
  pymammotion/mqtt/mammotion_mqtt.py,sha256=LaySave_hf0gU3crUTLqzpdQtxIwK8vu5DM8F8fbU2Y,8748
@@ -93,8 +93,8 @@ pymammotion/proto/mctrl_driver.proto,sha256=I0BncdAa3laeqT17Sn95r_1HuBD3dSc9IVu9
93
93
  pymammotion/proto/mctrl_driver.py,sha256=sseY2MxUtaQZvg7fvbA_gNvtqx9MVDW_rvUcfA2CWVs,2971
94
94
  pymammotion/proto/mctrl_driver_pb2.py,sha256=bfLwZb5Hehb6OIkgFrZMkQ0oTBXoOBxpruszKz-UM1U,3785
95
95
  pymammotion/proto/mctrl_driver_pb2.pyi,sha256=9_rcQELsSeOfeIQMTEFIpeXICpDe3arQeA4kAYWNSWw,5860
96
- pymammotion/proto/mctrl_nav.proto,sha256=FODYEh8AsCgyDVHU3xiFrkxyOjVubY0WRN5Ge2J1GLk,12378
97
- pymammotion/proto/mctrl_nav.py,sha256=_Nss6v10WkYS1z3D6v96L71WZ3FoRqk98s-dwEJpCpA,24888
96
+ pymammotion/proto/mctrl_nav.proto,sha256=eA7oOZw3Uiy4yAeybYjHkWr-FUjqJ498tsYsChm7rpg,12449
97
+ pymammotion/proto/mctrl_nav.py,sha256=okOznE_1dCi1yE5sSdQNKWkgI8CpbGRxMAISL5zqiT4,25040
98
98
  pymammotion/proto/mctrl_nav_pb2.py,sha256=LAHfEmGfNVZCN6vuLSZF6s2wd1Qk-siaWe4mdPWPdxc,24213
99
99
  pymammotion/proto/mctrl_nav_pb2.pyi,sha256=qmGYfKh2o63e5ppl9QIWnwDbmGVUVOf7EqhC9ApE5fg,51336
100
100
  pymammotion/proto/mctrl_ota.proto,sha256=4iHr-v1R0QiNndCnv3b6mhXiERLukB67ZzhTgt1iMc0,629
@@ -119,7 +119,7 @@ pymammotion/utility/map.py,sha256=GYscVMg2cX3IPlNpCBNHDW0S55yS1WGRf1iHnNZ7TfQ,22
119
119
  pymammotion/utility/movement.py,sha256=N75oAoAgFydqoaOedYIxGUHmuTCtPzAOtb-d_29tpfI,615
120
120
  pymammotion/utility/periodic.py,sha256=MbeSb9cfhxzYmdT_RiE0dZe3H9IfbQW_zSqhmSX2RUc,3321
121
121
  pymammotion/utility/rocker_util.py,sha256=6tX7sS87qoQC_tsxbx3NLL-HgS08wtzXiZkhDiz7uo0,7179
122
- pymammotion-0.2.62.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
123
- pymammotion-0.2.62.dist-info/METADATA,sha256=6UplkWzRMBFIE91ezexuQlA-QNGxHuTChMkbbTYWrEg,3874
124
- pymammotion-0.2.62.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
125
- pymammotion-0.2.62.dist-info/RECORD,,
122
+ pymammotion-0.2.64.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
123
+ pymammotion-0.2.64.dist-info/METADATA,sha256=ec2w7EIHw4XtPgo1Av7CRA1DQmtmisFM0v286zCIs2Q,3874
124
+ pymammotion-0.2.64.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
125
+ pymammotion-0.2.64.dist-info/RECORD,,