pymammotion 0.2.47__py3-none-any.whl → 0.2.48__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.
- pymammotion/data/model/hash_list.py +32 -6
- pymammotion/data/state_manager.py +1 -1
- pymammotion/mammotion/devices/base.py +16 -15
- pymammotion/mammotion/devices/mammotion.py +2 -2
- {pymammotion-0.2.47.dist-info → pymammotion-0.2.48.dist-info}/METADATA +1 -1
- {pymammotion-0.2.47.dist-info → pymammotion-0.2.48.dist-info}/RECORD +8 -8
- {pymammotion-0.2.47.dist-info → pymammotion-0.2.48.dist-info}/LICENSE +0 -0
- {pymammotion-0.2.47.dist-info → pymammotion-0.2.48.dist-info}/WHEEL +0 -0
@@ -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
|
6
|
+
from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck
|
7
7
|
|
8
8
|
|
9
9
|
class PathType(IntEnum):
|
@@ -20,6 +20,12 @@ class FrameList(DataClassORJSONMixin):
|
|
20
20
|
data: list[NavGetCommDataAck]
|
21
21
|
|
22
22
|
|
23
|
+
@dataclass
|
24
|
+
class RootHashList(DataClassORJSONMixin):
|
25
|
+
total_frame: int
|
26
|
+
data: list[NavGetHashListAck]
|
27
|
+
|
28
|
+
|
23
29
|
@dataclass
|
24
30
|
class AreaHashNameList(DataClassORJSONMixin):
|
25
31
|
"""Wrapper so we can serialize to and from dict."""
|
@@ -35,18 +41,38 @@ class HashList(DataClassORJSONMixin):
|
|
35
41
|
hashlist for all our hashIDs for verification
|
36
42
|
"""
|
37
43
|
|
44
|
+
root_hash_list: RootHashList = field(default_factory=RootHashList)
|
38
45
|
area: dict = field(default_factory=dict) # type 0
|
39
46
|
path: dict = field(default_factory=dict) # type 2
|
40
47
|
obstacle: dict = field(default_factory=dict) # type 1
|
41
|
-
hashlist: list[int] = field(default_factory=list)
|
42
48
|
area_name: list[AreaHashNameList] = field(default_factory=list)
|
43
49
|
|
44
|
-
def
|
45
|
-
self.hashlist = [x for x in hashlist if not (x in self.hashlist or self.hashlist.append(x))]
|
50
|
+
def update_hash_lists(self, hashlist: list[int]) -> None:
|
46
51
|
self.area = {hash_id: frames for hash_id, frames in self.area.items() if hash_id in hashlist}
|
47
52
|
self.path = {hash_id: frames for hash_id, frames in self.path.items() if hash_id in hashlist}
|
48
53
|
self.obstacle = {hash_id: frames for hash_id, frames in self.obstacle.items() if hash_id in hashlist}
|
49
54
|
|
55
|
+
@property
|
56
|
+
def hashlist(self) -> list[int]:
|
57
|
+
return [i for obj in self.root_hash_list.data for i in obj.data_couple]
|
58
|
+
|
59
|
+
def update_root_hash_list(self, hash_list: NavGetHashListAck) -> None:
|
60
|
+
self.root_hash_list.total_frame = hash_list.total_frame
|
61
|
+
|
62
|
+
for index, obj in enumerate(self.root_hash_list.data):
|
63
|
+
if obj.current_frame == hash_list.current_frame:
|
64
|
+
# Replace the item if current_frame matches
|
65
|
+
self.root_hash_list.data[index] = hash_list
|
66
|
+
self.update_hash_lists(self.hashlist)
|
67
|
+
return
|
68
|
+
|
69
|
+
# If no match was found, append the new item
|
70
|
+
self.root_hash_list.data.append(hash_list)
|
71
|
+
self.update_hash_lists(self.hashlist)
|
72
|
+
|
73
|
+
def missing_hash_frame(self):
|
74
|
+
return self._find_missing_frames(self.root_hash_list)
|
75
|
+
|
50
76
|
def missing_frame(self, hash_data: NavGetCommDataAck) -> list[int]:
|
51
77
|
if hash_data.type == PathType.AREA:
|
52
78
|
return self._find_missing_frames(self.area.get(hash_data.hash))
|
@@ -62,7 +88,7 @@ class HashList(DataClassORJSONMixin):
|
|
62
88
|
if hash_data.type == PathType.AREA:
|
63
89
|
existing_name = next((area for area in self.area_name if area.hash == hash_data.hash), None)
|
64
90
|
if not existing_name:
|
65
|
-
self.area_name.append(
|
91
|
+
self.area_name.append(AreaHashNameList(name=f"area {len(self.area_name)+1}", hash=hash_data.hash))
|
66
92
|
return self._add_hash_data(self.area, hash_data)
|
67
93
|
|
68
94
|
if hash_data.type == PathType.OBSTACLE:
|
@@ -72,7 +98,7 @@ class HashList(DataClassORJSONMixin):
|
|
72
98
|
return self._add_hash_data(self.path, hash_data)
|
73
99
|
|
74
100
|
@staticmethod
|
75
|
-
def _find_missing_frames(frame_list: FrameList) -> list[int]:
|
101
|
+
def _find_missing_frames(frame_list: FrameList | RootHashList) -> list[int]:
|
76
102
|
if frame_list.total_frame == len(frame_list.data):
|
77
103
|
return []
|
78
104
|
number_list = list(range(1, frame_list.total_frame + 1))
|
@@ -62,7 +62,7 @@ class StateManager:
|
|
62
62
|
match nav_msg[0]:
|
63
63
|
case "toapp_gethash_ack":
|
64
64
|
hashlist_ack: NavGetHashListAck = nav_msg[1]
|
65
|
-
self._device.map.
|
65
|
+
self._device.map.update_root_hash_list(hashlist_ack)
|
66
66
|
await self.gethash_ack_callback(nav_msg[1])
|
67
67
|
case "toapp_get_commondata_ack":
|
68
68
|
common_data: NavGetCommDataAck = nav_msg[1]
|
@@ -9,7 +9,6 @@ from pymammotion.aliyun.model.dev_by_account_response import Device
|
|
9
9
|
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
|
-
from pymammotion.proto import has_field
|
13
12
|
from pymammotion.proto.luba_msg import LubaMsg
|
14
13
|
from pymammotion.proto.mctrl_nav import NavGetCommDataAck, NavGetHashListAck
|
15
14
|
|
@@ -55,7 +54,15 @@ class MammotionBaseDevice:
|
|
55
54
|
|
56
55
|
async def datahash_response(self, hash_ack: NavGetHashListAck) -> None:
|
57
56
|
"""Handle datahash responses."""
|
58
|
-
|
57
|
+
current_frame = hash_ack.current_frame
|
58
|
+
|
59
|
+
missing_frames = self.mower.map.missing_hash_frame()
|
60
|
+
if len(missing_frames) == 0:
|
61
|
+
return await self.queue_command("synchronize_hash_data", hash_num=self.mower.map.hashlist)
|
62
|
+
|
63
|
+
if current_frame != missing_frames[0] - 1:
|
64
|
+
current_frame = missing_frames[0] - 1
|
65
|
+
await self.queue_command("get_hash_response", total_frame=hash_ack.total_frame, current_frame=current_frame)
|
59
66
|
|
60
67
|
async def commdata_response(self, common_data: NavGetCommDataAck) -> None:
|
61
68
|
"""Handle common data responses."""
|
@@ -66,7 +73,7 @@ class MammotionBaseDevice:
|
|
66
73
|
if len(missing_frames) == 0:
|
67
74
|
# get next in hash ack list
|
68
75
|
|
69
|
-
data_hash = find_next_integer(self.mower.
|
76
|
+
data_hash = find_next_integer(self.mower.map.hashlist, common_data.hash)
|
70
77
|
if data_hash is None:
|
71
78
|
return
|
72
79
|
|
@@ -201,22 +208,16 @@ class MammotionBaseDevice:
|
|
201
208
|
|
202
209
|
async def start_map_sync(self) -> None:
|
203
210
|
"""Start sync of map data."""
|
204
|
-
try:
|
205
|
-
# work out why this crashes sometimes for better proto
|
206
211
|
|
207
|
-
|
208
|
-
|
209
|
-
except Exception:
|
210
|
-
"""Do nothing for now."""
|
212
|
+
if self._cloud_device and len(self.mower.map.area_name) == 0:
|
213
|
+
await self.queue_command("get_area_name_list", device_id=self._cloud_device.iotId)
|
211
214
|
|
212
215
|
await self.queue_command("read_plan", sub_cmd=2, plan_index=0)
|
213
216
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
for data_hash in self.mower.nav.toapp_gethash_ack.data_couple:
|
219
|
-
await self.queue_command("synchronize_hash_data", hash_num=data_hash)
|
217
|
+
await self.queue_command("get_all_boundary_hash_list", sub_cmd=0)
|
218
|
+
await self.queue_command("get_hash_response", total_frame=1, current_frame=1)
|
219
|
+
for data_hash in self.mower.map.hashlist:
|
220
|
+
await self.queue_command("synchronize_hash_data", hash_num=data_hash)
|
220
221
|
|
221
222
|
# sub_cmd 3 is job hashes??
|
222
223
|
# sub_cmd 4 is dump location (yuka)
|
@@ -247,8 +247,8 @@ class Mammotion:
|
|
247
247
|
await loop.run_in_executor(None, cloud_client.list_binding_by_account)
|
248
248
|
return cloud_client
|
249
249
|
|
250
|
-
def remove_device(self, name: str) -> None:
|
251
|
-
self.devices.remove_device(name)
|
250
|
+
async def remove_device(self, name: str) -> None:
|
251
|
+
await self.devices.remove_device(name)
|
252
252
|
|
253
253
|
def get_device_by_name(self, name: str) -> MammotionMixedDeviceManager:
|
254
254
|
return self.devices.get_device(name)
|
@@ -28,7 +28,7 @@ pymammotion/data/model/enums.py,sha256=EpKmO8yVUZyEnTY4yH0DMMVKYNQM42zpW1maUu0i3
|
|
28
28
|
pymammotion/data/model/excute_boarder_params.py,sha256=9CpUqrygcle1C_1hDW-riLmm4map4ZbE842NXjcomEI,1394
|
29
29
|
pymammotion/data/model/execute_boarder.py,sha256=9rd_h4fbcsXxgnLOd2rO2hWyD1abnTGc47QTEpp8DD0,1103
|
30
30
|
pymammotion/data/model/generate_route_information.py,sha256=MkUBoqGtCAKmiVQ4Q1pEoDVHZs5uLIo7vhfWT4nGbtY,801
|
31
|
-
pymammotion/data/model/hash_list.py,sha256=
|
31
|
+
pymammotion/data/model/hash_list.py,sha256=CJfWRX_BwZlwGL06moePvuhc7eimsVNFLfFA8Gyhl0U,4360
|
32
32
|
pymammotion/data/model/location.py,sha256=PwmITejfI4pm7PI4rzqSuuHetwle6IJr_CV95435s2M,871
|
33
33
|
pymammotion/data/model/mowing_modes.py,sha256=5TrHSijUyPtIDWpNtgzx_vFQukRJWRz4gIrUaXggKPw,827
|
34
34
|
pymammotion/data/model/plan.py,sha256=mcadkSL7fQXy0iJ0q786I3GEQY4i6kmQXfW6Ri69lcQ,2906
|
@@ -39,7 +39,7 @@ pymammotion/data/mqtt/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdr
|
|
39
39
|
pymammotion/data/mqtt/event.py,sha256=plt53w3kHulB_MfbkxK9j7AfdQ5ahVU2s4kiQMoLio4,4612
|
40
40
|
pymammotion/data/mqtt/properties.py,sha256=HkBPghr26L9_b4QaOi1DtPgb0UoPIOGSe9wb3kgnM6Y,2815
|
41
41
|
pymammotion/data/mqtt/status.py,sha256=zqnlo-MzejEQZszl0i0Wucoc3E76x6UtI9JLxoBnu54,1067
|
42
|
-
pymammotion/data/state_manager.py,sha256=
|
42
|
+
pymammotion/data/state_manager.py,sha256=bGZXaiIosNTrN0L8DmddLqL2MRKbixKmyd2XFiZMCTE,4101
|
43
43
|
pymammotion/event/__init__.py,sha256=mgATR6vPHACNQ-0zH5fi7NdzeTCDV1CZyaWPmtUusi8,115
|
44
44
|
pymammotion/event/event.py,sha256=UzYnxV5DfvMDK3E06UvSzvzuBbaXOOUwO6xYt_zn9To,2034
|
45
45
|
pymammotion/http/_init_.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -60,8 +60,8 @@ pymammotion/mammotion/commands/messages/video.py,sha256=_8lJsU4sLm2CGnc7RDkueA0A
|
|
60
60
|
pymammotion/mammotion/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
61
61
|
pymammotion/mammotion/control/joystick.py,sha256=QfBVxM_gxpWsZAGO90whtgxCI2tIZ3TTad9wHIPsU9s,5640
|
62
62
|
pymammotion/mammotion/devices/__init__.py,sha256=f2qQFPgLGmV85W2hSlMUh5BYuht9o_Ar_JEAAMD4fsE,102
|
63
|
-
pymammotion/mammotion/devices/base.py,sha256=
|
64
|
-
pymammotion/mammotion/devices/mammotion.py,sha256=
|
63
|
+
pymammotion/mammotion/devices/base.py,sha256=o3G-A6JciBq2AUZaPdHtp6q9pp3blOxYb1ySI3Fg_Gk,9717
|
64
|
+
pymammotion/mammotion/devices/mammotion.py,sha256=ForzwnQu1IRxtwsFMHAudFCtOAUJC01BcX5RK7dYYcs,12295
|
65
65
|
pymammotion/mammotion/devices/mammotion_bluetooth.py,sha256=nyO7pkKgAoRPs-28ESf6ee-y3G5JTYRO-MCp4wKPMlE,17476
|
66
66
|
pymammotion/mammotion/devices/mammotion_cloud.py,sha256=Q1Il0nCxH-8utg_9AKAY3HxuuhB78uHZV4yVpZ4k1TI,11282
|
67
67
|
pymammotion/mqtt/__init__.py,sha256=Ocs5e-HLJvTuDpVXyECEsWIvwsUaxzj7lZ9mSYutNDY,105
|
@@ -118,7 +118,7 @@ pymammotion/utility/map.py,sha256=GYscVMg2cX3IPlNpCBNHDW0S55yS1WGRf1iHnNZ7TfQ,22
|
|
118
118
|
pymammotion/utility/movement.py,sha256=N75oAoAgFydqoaOedYIxGUHmuTCtPzAOtb-d_29tpfI,615
|
119
119
|
pymammotion/utility/periodic.py,sha256=MbeSb9cfhxzYmdT_RiE0dZe3H9IfbQW_zSqhmSX2RUc,3321
|
120
120
|
pymammotion/utility/rocker_util.py,sha256=6tX7sS87qoQC_tsxbx3NLL-HgS08wtzXiZkhDiz7uo0,7179
|
121
|
-
pymammotion-0.2.
|
122
|
-
pymammotion-0.2.
|
123
|
-
pymammotion-0.2.
|
124
|
-
pymammotion-0.2.
|
121
|
+
pymammotion-0.2.48.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
122
|
+
pymammotion-0.2.48.dist-info/METADATA,sha256=a0GU3o4x1fZ0_4a_iu37n0dDV2pco5d0iyOHexO74No,4052
|
123
|
+
pymammotion-0.2.48.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
124
|
+
pymammotion-0.2.48.dist-info/RECORD,,
|
File without changes
|
File without changes
|