pymammotion 0.2.62__py3-none-any.whl → 0.5.51__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.
Potentially problematic release.
This version of pymammotion might be problematic. Click here for more details.
- pymammotion/__init__.py +9 -6
- pymammotion/aliyun/client.py +235 -0
- pymammotion/aliyun/cloud_gateway.py +320 -69
- pymammotion/aliyun/model/aep_response.py +1 -2
- pymammotion/aliyun/model/dev_by_account_response.py +170 -23
- pymammotion/aliyun/model/login_by_oauth_response.py +2 -3
- pymammotion/aliyun/model/regions_response.py +3 -3
- pymammotion/aliyun/model/session_by_authcode_response.py +2 -2
- pymammotion/aliyun/model/thing_response.py +12 -0
- pymammotion/aliyun/regions.py +62 -0
- pymammotion/aliyun/tea/core.py +297 -0
- pymammotion/bluetooth/ble.py +11 -15
- pymammotion/bluetooth/ble_message.py +389 -106
- pymammotion/bluetooth/model/atomic_integer.py +54 -0
- pymammotion/const.py +3 -0
- pymammotion/data/model/__init__.py +1 -2
- pymammotion/data/model/device.py +92 -240
- pymammotion/data/model/device_config.py +10 -24
- pymammotion/data/model/device_info.py +35 -0
- pymammotion/data/model/device_limits.py +49 -0
- pymammotion/data/model/enums.py +12 -2
- pymammotion/data/model/errors.py +12 -0
- pymammotion/data/model/events.py +14 -0
- pymammotion/data/model/generate_geojson.py +521 -0
- pymammotion/data/model/generate_route_information.py +3 -4
- pymammotion/data/model/hash_list.py +384 -48
- pymammotion/data/model/location.py +4 -4
- pymammotion/data/model/mowing_modes.py +24 -1
- pymammotion/data/model/raw_data.py +215 -0
- pymammotion/data/model/region_data.py +10 -11
- pymammotion/data/model/report_info.py +62 -6
- pymammotion/data/model/work.py +27 -0
- pymammotion/data/mower_state_manager.py +316 -0
- pymammotion/data/mqtt/event.py +73 -28
- pymammotion/data/mqtt/mammotion_properties.py +257 -0
- pymammotion/data/mqtt/properties.py +93 -78
- pymammotion/data/mqtt/status.py +18 -17
- pymammotion/event/event.py +32 -8
- pymammotion/homeassistant/__init__.py +3 -0
- pymammotion/homeassistant/mower_api.py +484 -0
- pymammotion/homeassistant/rtk_api.py +54 -0
- pymammotion/http/__init__.py +0 -0
- pymammotion/http/encryption.py +220 -0
- pymammotion/http/http.py +652 -44
- pymammotion/http/model/__init__.py +0 -0
- pymammotion/{aliyun/model/stream_subscription_response.py → http/model/camera_stream.py} +14 -2
- pymammotion/http/model/http.py +160 -9
- pymammotion/http/model/response_factory.py +61 -0
- pymammotion/http/model/rtk.py +16 -0
- pymammotion/mammotion/commands/abstract_message.py +7 -5
- pymammotion/mammotion/commands/mammotion_command.py +32 -3
- pymammotion/mammotion/commands/messages/basestation.py +43 -0
- pymammotion/mammotion/commands/messages/driver.py +61 -29
- pymammotion/mammotion/commands/messages/media.py +68 -15
- pymammotion/mammotion/commands/messages/navigation.py +61 -25
- pymammotion/mammotion/commands/messages/network.py +93 -100
- pymammotion/mammotion/commands/messages/ota.py +18 -18
- pymammotion/mammotion/commands/messages/system.py +97 -72
- pymammotion/mammotion/commands/messages/video.py +17 -12
- pymammotion/mammotion/devices/__init__.py +27 -3
- pymammotion/mammotion/devices/base.py +50 -127
- pymammotion/mammotion/devices/mammotion.py +447 -212
- pymammotion/mammotion/devices/mammotion_bluetooth.py +105 -60
- pymammotion/mammotion/devices/mammotion_cloud.py +157 -105
- pymammotion/mammotion/devices/mammotion_mower_ble.py +49 -0
- pymammotion/mammotion/devices/mammotion_mower_cloud.py +39 -0
- pymammotion/mammotion/devices/managers/managers.py +81 -0
- pymammotion/mammotion/devices/mower_device.py +124 -0
- pymammotion/mammotion/devices/mower_manager.py +107 -0
- pymammotion/mammotion/devices/rtk_ble.py +89 -0
- pymammotion/mammotion/devices/rtk_cloud.py +113 -0
- pymammotion/mammotion/devices/rtk_device.py +50 -0
- pymammotion/mammotion/devices/rtk_manager.py +122 -0
- pymammotion/mqtt/__init__.py +2 -1
- pymammotion/mqtt/aliyun_mqtt.py +232 -0
- pymammotion/mqtt/linkkit/__init__.py +5 -0
- pymammotion/mqtt/linkkit/h2client.py +585 -0
- pymammotion/mqtt/linkkit/linkkit.py +3023 -0
- pymammotion/mqtt/mammotion_mqtt.py +176 -169
- pymammotion/mqtt/mqtt_models.py +66 -0
- pymammotion/proto/__init__.py +4839 -4
- pymammotion/proto/basestation.proto +8 -0
- pymammotion/proto/basestation_pb2.py +11 -9
- pymammotion/proto/basestation_pb2.pyi +16 -2
- pymammotion/proto/dev_net.proto +79 -55
- pymammotion/proto/dev_net_pb2.py +60 -56
- pymammotion/proto/dev_net_pb2.pyi +49 -6
- pymammotion/proto/luba_msg.proto +2 -1
- pymammotion/proto/luba_msg_pb2.py +6 -6
- pymammotion/proto/luba_msg_pb2.pyi +1 -0
- pymammotion/proto/luba_mul.proto +62 -1
- pymammotion/proto/luba_mul_pb2.py +38 -22
- pymammotion/proto/luba_mul_pb2.pyi +94 -7
- pymammotion/proto/mctrl_driver.proto +44 -4
- pymammotion/proto/mctrl_driver_pb2.py +26 -14
- pymammotion/proto/mctrl_driver_pb2.pyi +66 -11
- pymammotion/proto/mctrl_nav.proto +97 -51
- pymammotion/proto/mctrl_nav_pb2.py +75 -67
- pymammotion/proto/mctrl_nav_pb2.pyi +142 -56
- pymammotion/proto/mctrl_ota.proto +40 -2
- pymammotion/proto/mctrl_ota_pb2.py +23 -13
- pymammotion/proto/mctrl_ota_pb2.pyi +67 -4
- pymammotion/proto/mctrl_pept.proto +8 -3
- pymammotion/proto/mctrl_pept_pb2.py +8 -6
- pymammotion/proto/mctrl_pept_pb2.pyi +14 -6
- pymammotion/proto/mctrl_sys.proto +325 -86
- pymammotion/proto/mctrl_sys_pb2.py +162 -98
- pymammotion/proto/mctrl_sys_pb2.pyi +451 -25
- pymammotion/proto/message_pool.py +3 -0
- pymammotion/proto/py.typed +0 -0
- pymammotion/utility/constant/device_constant.py +65 -21
- pymammotion/utility/datatype_converter.py +13 -12
- pymammotion/utility/device_config.py +755 -0
- pymammotion/utility/device_type.py +218 -21
- pymammotion/utility/map.py +238 -51
- pymammotion/utility/mur_mur_hash.py +159 -0
- {pymammotion-0.2.62.dist-info → pymammotion-0.5.51.dist-info}/METADATA +27 -31
- pymammotion-0.5.51.dist-info/RECORD +152 -0
- {pymammotion-0.2.62.dist-info → pymammotion-0.5.51.dist-info}/WHEEL +1 -1
- pymammotion/aliyun/cloud_service.py +0 -65
- pymammotion/data/model/plan.py +0 -58
- pymammotion/data/state_manager.py +0 -130
- pymammotion/proto/basestation.py +0 -59
- pymammotion/proto/common.py +0 -12
- pymammotion/proto/dev_net.py +0 -381
- pymammotion/proto/luba_msg.py +0 -81
- pymammotion/proto/luba_mul.py +0 -76
- pymammotion/proto/mctrl_driver.py +0 -100
- pymammotion/proto/mctrl_nav.py +0 -660
- pymammotion/proto/mctrl_ota.py +0 -48
- pymammotion/proto/mctrl_pept.py +0 -41
- pymammotion/proto/mctrl_sys.py +0 -574
- pymammotion-0.2.62.dist-info/RECORD +0 -125
- /pymammotion/{http/_init_.py → bluetooth/model/__init__.py} +0 -0
- {pymammotion-0.2.62.dist-info → pymammotion-0.5.51.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
# === sendOrderMsg_Sys ===
|
|
2
|
-
import datetime
|
|
3
2
|
from abc import ABC
|
|
3
|
+
import datetime
|
|
4
|
+
import time
|
|
4
5
|
|
|
5
6
|
from pymammotion import logger
|
|
6
7
|
from pymammotion.mammotion.commands.abstract_message import AbstractMessage
|
|
7
|
-
from pymammotion.
|
|
8
|
-
from pymammotion.proto.luba_msg import LubaMsg, MsgAttr, MsgCmdType, MsgDevice
|
|
9
|
-
from pymammotion.proto.mctrl_sys import (
|
|
8
|
+
from pymammotion.proto import (
|
|
10
9
|
DeviceProductTypeInfoT,
|
|
11
10
|
LoraCfgReq,
|
|
11
|
+
LubaMsg,
|
|
12
12
|
MctlSys,
|
|
13
13
|
MCtrlSimulationCmdData,
|
|
14
|
+
MsgAttr,
|
|
15
|
+
MsgCmdType,
|
|
16
|
+
MsgDevice,
|
|
14
17
|
ReportInfoCfg,
|
|
15
18
|
RptAct,
|
|
16
19
|
RptInfoType,
|
|
@@ -19,38 +22,45 @@ from pymammotion.proto.mctrl_sys import (
|
|
|
19
22
|
SysSetDateTime,
|
|
20
23
|
TimeCtrlLight,
|
|
21
24
|
)
|
|
22
|
-
from pymammotion.utility.device_type import DeviceType
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
class MessageSystem(AbstractMessage, ABC):
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def send_order_msg_sys(self, sys):
|
|
28
|
+
def send_order_msg_sys(self, sys) -> bytes:
|
|
29
29
|
luba_msg = LubaMsg(
|
|
30
|
-
msgtype=MsgCmdType.
|
|
30
|
+
msgtype=MsgCmdType.EMBED_SYS,
|
|
31
|
+
msgattr=MsgAttr.REQ,
|
|
31
32
|
sender=MsgDevice.DEV_MOBILEAPP,
|
|
32
|
-
rcver=self.get_msg_device(MsgCmdType.
|
|
33
|
+
rcver=self.get_msg_device(MsgCmdType.EMBED_SYS, MsgDevice.DEV_MAINCTL),
|
|
33
34
|
sys=sys,
|
|
35
|
+
seqs=self.seqs.increment_and_get() & 255,
|
|
36
|
+
version=1,
|
|
37
|
+
subtype=self.user_account,
|
|
38
|
+
timestamp=round(time.time() * 1000),
|
|
34
39
|
)
|
|
35
40
|
|
|
36
41
|
return luba_msg.SerializeToString()
|
|
37
42
|
|
|
38
|
-
def send_order_msg_sys_legacy(self, sys):
|
|
43
|
+
def send_order_msg_sys_legacy(self, sys) -> bytes:
|
|
39
44
|
luba_msg = LubaMsg(
|
|
40
|
-
msgtype=MsgCmdType.
|
|
45
|
+
msgtype=MsgCmdType.EMBED_SYS,
|
|
46
|
+
msgattr=MsgAttr.REQ,
|
|
41
47
|
sender=MsgDevice.DEV_MOBILEAPP,
|
|
42
48
|
rcver=MsgDevice.DEV_MAINCTL,
|
|
43
49
|
sys=sys,
|
|
50
|
+
seqs=self.seqs.increment_and_get() & 255,
|
|
51
|
+
version=1,
|
|
52
|
+
subtype=self.user_account,
|
|
53
|
+
timestamp=round(time.time() * 1000),
|
|
44
54
|
)
|
|
45
55
|
|
|
46
56
|
return luba_msg.SerializeToString()
|
|
47
57
|
|
|
48
|
-
def reset_system(self):
|
|
58
|
+
def reset_system(self) -> bytes:
|
|
49
59
|
build = MctlSys(todev_reset_system=1)
|
|
50
60
|
logger.debug("Send command - send factory reset")
|
|
51
61
|
return self.send_order_msg_sys(build)
|
|
52
62
|
|
|
53
|
-
def set_blade_control(self, on_off: int):
|
|
63
|
+
def set_blade_control(self, on_off: int) -> bytes:
|
|
54
64
|
mctlsys = MctlSys()
|
|
55
65
|
sys_knife_control = SysKnifeControl()
|
|
56
66
|
sys_knife_control.knife_status = on_off
|
|
@@ -58,10 +68,10 @@ class MessageSystem(AbstractMessage, ABC):
|
|
|
58
68
|
|
|
59
69
|
return self.send_order_msg_sys(mctlsys)
|
|
60
70
|
|
|
61
|
-
def get_device_product_model(self):
|
|
62
|
-
return self.send_order_msg_sys(MctlSys(device_product_type_info=DeviceProductTypeInfoT()))
|
|
71
|
+
def get_device_product_model(self) -> bytes:
|
|
72
|
+
return self.send_order_msg_sys(MctlSys(device_product_type_info=DeviceProductTypeInfoT(result=1)))
|
|
63
73
|
|
|
64
|
-
def read_and_set_sidelight(self, is_sidelight: bool, operate: int):
|
|
74
|
+
def read_and_set_sidelight(self, is_sidelight: bool, operate: int) -> bytes:
|
|
65
75
|
"""Read state of sidelight as well as set it."""
|
|
66
76
|
if is_sidelight:
|
|
67
77
|
build = TimeCtrlLight(
|
|
@@ -90,7 +100,7 @@ class MessageSystem(AbstractMessage, ABC):
|
|
|
90
100
|
is_sidelight}, operate:{operate}, timeCtrlLight:{build}")
|
|
91
101
|
return self.send_order_msg_sys(build2)
|
|
92
102
|
|
|
93
|
-
def test_tool_order_to_sys(self, sub_cmd: int, param_id: int, param_value: list[int]):
|
|
103
|
+
def test_tool_order_to_sys(self, sub_cmd: int, param_id: int, param_value: list[int]) -> bytes:
|
|
94
104
|
build = MCtrlSimulationCmdData(sub_cmd=sub_cmd, param_id=param_id, param_value=param_value)
|
|
95
105
|
logger.debug(f"Send tool test command: subCmd={sub_cmd}, param_id:{
|
|
96
106
|
param_id}, param_value={param_value}")
|
|
@@ -99,20 +109,14 @@ class MessageSystem(AbstractMessage, ABC):
|
|
|
99
109
|
param_id}, param_value={param_value}")
|
|
100
110
|
return self.send_order_msg_sys(build2)
|
|
101
111
|
|
|
102
|
-
def read_and_set_rtk_paring_code(self, op: int, cgf: str | None = None):
|
|
112
|
+
def read_and_set_rtk_paring_code(self, op: int, cgf: str | None = None) -> bytes:
|
|
103
113
|
logger.debug(f"Send read and write base station configuration quality op:{
|
|
104
114
|
op}, cgf:{cgf}")
|
|
105
115
|
return self.send_order_msg_sys(MctlSys(todev_lora_cfg_req=LoraCfgReq(op=op, cfg=cgf)))
|
|
106
116
|
|
|
107
|
-
def allpowerfull_rw(self,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return
|
|
111
|
-
build = MctlSys(bidire_comm_cmd=SysCommCmd(id=id, context=context, rw=rw))
|
|
112
|
-
logger.debug(f"Send command - 9 general read and write command id={id}, context={context}, rw={rw}")
|
|
113
|
-
if id == 5:
|
|
114
|
-
# This logic doesnt make snese, but its what they had so..
|
|
115
|
-
return self.send_order_msg_sys(build)
|
|
117
|
+
def allpowerfull_rw(self, rw_id: int, context: int, rw: int) -> bytes:
|
|
118
|
+
build = MctlSys(bidire_comm_cmd=SysCommCmd(id=rw_id, context=context, rw=rw))
|
|
119
|
+
logger.debug(f"Send command - 9 general read and write command id={rw_id}, context={context}, rw={rw}")
|
|
116
120
|
return self.send_order_msg_sys(build)
|
|
117
121
|
|
|
118
122
|
# Commented out as not needed and too many refs to try fix up
|
|
@@ -175,7 +179,8 @@ class MessageSystem(AbstractMessage, ABC):
|
|
|
175
179
|
# test_id}, testDuration={test_duration}", "Factory tool logger.debug222", True)
|
|
176
180
|
# return self.send_order_msg_sys(build2)
|
|
177
181
|
|
|
178
|
-
def send_sys_set_date_time(self):
|
|
182
|
+
def send_sys_set_date_time(self) -> bytes:
|
|
183
|
+
# TODO get HA timezone
|
|
179
184
|
calendar = datetime.datetime.now()
|
|
180
185
|
i = calendar.year
|
|
181
186
|
i2 = calendar.month
|
|
@@ -209,9 +214,12 @@ class MessageSystem(AbstractMessage, ABC):
|
|
|
209
214
|
)
|
|
210
215
|
return self.send_order_msg_sys(build)
|
|
211
216
|
|
|
212
|
-
def get_device_version_info(self):
|
|
217
|
+
def get_device_version_info(self) -> bytes:
|
|
213
218
|
return self.send_order_msg_sys(MctlSys(todev_get_dev_fw_info=1))
|
|
214
219
|
|
|
220
|
+
def read_and_set_rtk_pairing_code(self, op: int, cfg: str) -> bytes:
|
|
221
|
+
return self.send_order_msg_sys(MctlSys(todev_lora_cfg_req=LoraCfgReq(op=op, cfg=cfg)))
|
|
222
|
+
|
|
215
223
|
# === sendOrderMsg_Sys2 ===
|
|
216
224
|
|
|
217
225
|
def request_iot_sys(
|
|
@@ -234,12 +242,26 @@ class MessageSystem(AbstractMessage, ABC):
|
|
|
234
242
|
)
|
|
235
243
|
)
|
|
236
244
|
logger.debug(f"Send command==== IOT slim data Act {
|
|
237
|
-
build.todev_report_cfg.act}
|
|
245
|
+
build.todev_report_cfg.act}")
|
|
238
246
|
return self.send_order_msg_sys_legacy(build)
|
|
239
247
|
|
|
248
|
+
def get_maintenance(self) -> bytes:
|
|
249
|
+
return self.request_iot_sys(
|
|
250
|
+
rpt_act=RptAct.RPT_START,
|
|
251
|
+
rpt_info_type=[
|
|
252
|
+
RptInfoType.RIT_MAINTAIN,
|
|
253
|
+
RptInfoType.RIT_BASESTATION_INFO,
|
|
254
|
+
RptInfoType.RIT_FW_INFO,
|
|
255
|
+
],
|
|
256
|
+
timeout=1000,
|
|
257
|
+
period=1000,
|
|
258
|
+
no_change_period=2000,
|
|
259
|
+
count=3,
|
|
260
|
+
)
|
|
261
|
+
|
|
240
262
|
def get_report_cfg_stop(self, timeout: int = 10000, period: int = 1000, no_change_period: int = 1000):
|
|
241
263
|
# TODO use send_order_msg_sys_legacy
|
|
242
|
-
|
|
264
|
+
mctl_sys = MctlSys(
|
|
243
265
|
todev_report_cfg=ReportInfoCfg(
|
|
244
266
|
act=RptAct.RPT_STOP,
|
|
245
267
|
timeout=timeout,
|
|
@@ -249,30 +271,32 @@ class MessageSystem(AbstractMessage, ABC):
|
|
|
249
271
|
)
|
|
250
272
|
)
|
|
251
273
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_VISION_STATISTIC)
|
|
274
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_CONNECT)
|
|
275
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_RTK)
|
|
276
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_DEV_LOCAL)
|
|
277
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_WORK)
|
|
278
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_DEV_STA)
|
|
279
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_VISION_POINT)
|
|
280
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_VIO)
|
|
281
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_VISION_STATISTIC)
|
|
261
282
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
283
|
+
luba_msg = LubaMsg(
|
|
284
|
+
msgtype=MsgCmdType.EMBED_SYS,
|
|
285
|
+
sender=MsgDevice.DEV_MOBILEAPP,
|
|
286
|
+
rcver=MsgDevice.DEV_MAINCTL,
|
|
287
|
+
msgattr=MsgAttr.REQ,
|
|
288
|
+
seqs=self.seqs.increment_and_get() & 255,
|
|
289
|
+
version=1,
|
|
290
|
+
subtype=self.user_account,
|
|
291
|
+
sys=mctl_sys,
|
|
292
|
+
timestamp=round(time.time() * 1000),
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
return luba_msg.SerializeToString()
|
|
272
296
|
|
|
273
297
|
def get_report_cfg(self, timeout: int = 10000, period: int = 1000, no_change_period: int = 2000):
|
|
274
298
|
# TODO use send_order_msg_sys_legacy
|
|
275
|
-
|
|
299
|
+
mctl_sys = MctlSys(
|
|
276
300
|
todev_report_cfg=ReportInfoCfg(
|
|
277
301
|
act=RptAct.RPT_START,
|
|
278
302
|
timeout=timeout,
|
|
@@ -282,24 +306,25 @@ class MessageSystem(AbstractMessage, ABC):
|
|
|
282
306
|
)
|
|
283
307
|
)
|
|
284
308
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_BASESTATION_INFO)
|
|
309
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_CONNECT)
|
|
310
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_RTK)
|
|
311
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_DEV_LOCAL)
|
|
312
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_WORK)
|
|
313
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_DEV_STA)
|
|
314
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_VISION_POINT)
|
|
315
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_VIO)
|
|
316
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_VISION_STATISTIC)
|
|
317
|
+
mctl_sys.todev_report_cfg.sub.append(RptInfoType.RIT_BASESTATION_INFO)
|
|
295
318
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
319
|
+
luba_msg = LubaMsg(
|
|
320
|
+
msgtype=MsgCmdType.EMBED_SYS,
|
|
321
|
+
sender=MsgDevice.DEV_MOBILEAPP,
|
|
322
|
+
rcver=MsgDevice.DEV_MAINCTL,
|
|
323
|
+
msgattr=MsgAttr.REQ,
|
|
324
|
+
seqs=self.seqs.increment_and_get() & 255,
|
|
325
|
+
version=1,
|
|
326
|
+
subtype=self.user_account,
|
|
327
|
+
sys=mctl_sys,
|
|
328
|
+
timestamp=round(time.time() * 1000),
|
|
329
|
+
)
|
|
330
|
+
return luba_msg.SerializeToString()
|
|
@@ -1,28 +1,33 @@
|
|
|
1
1
|
# === sendOrderMsg_Video ===
|
|
2
2
|
from abc import ABC
|
|
3
|
+
import time
|
|
3
4
|
|
|
4
5
|
from pymammotion.mammotion.commands.abstract_message import AbstractMessage
|
|
5
|
-
from pymammotion.proto import
|
|
6
|
-
from pymammotion.proto.luba_msg import MsgCmdType, MsgDevice
|
|
6
|
+
from pymammotion.proto import LubaMsg, MsgAttr, MsgCmdType, MsgDevice, MulCameraPosition, MulSetVideo, SocMul
|
|
7
7
|
from pymammotion.utility.device_type import DeviceType
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class MessageVideo(AbstractMessage, ABC):
|
|
11
|
-
|
|
12
|
-
luba_msg =
|
|
13
|
-
msgtype=
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
def send_order_msg_video(self, mul: SocMul):
|
|
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),
|
|
16
17
|
mul=mul,
|
|
18
|
+
seqs=self.seqs.increment_and_get() & 255,
|
|
19
|
+
version=1,
|
|
20
|
+
subtype=self.user_account,
|
|
21
|
+
timestamp=round(time.time() * 1000),
|
|
17
22
|
)
|
|
18
23
|
|
|
19
24
|
return luba_msg.SerializeToString()
|
|
20
25
|
|
|
21
26
|
def device_agora_join_channel_with_position(self, enter_state: int):
|
|
22
27
|
position = (
|
|
23
|
-
|
|
24
|
-
if DeviceType.
|
|
25
|
-
else
|
|
28
|
+
MulCameraPosition.ALL
|
|
29
|
+
if DeviceType.value_of_str(self.get_device_name()).get_value() == DeviceType.LUBA_YUKA.get_value()
|
|
30
|
+
else MulCameraPosition.LEFT
|
|
26
31
|
)
|
|
27
|
-
|
|
28
|
-
return self.send_order_msg_video(
|
|
32
|
+
soc_mul = SocMul(set_video=MulSetVideo(position=position, vi_switch=enter_state))
|
|
33
|
+
return self.send_order_msg_video(soc_mul)
|
|
@@ -1,5 +1,29 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Mammotion devices module."""
|
|
2
2
|
|
|
3
|
-
from .mammotion import
|
|
3
|
+
from .mammotion import Mammotion, MammotionDeviceManager
|
|
4
|
+
from .mammotion_bluetooth import MammotionBaseBLEDevice
|
|
5
|
+
from .mammotion_cloud import MammotionBaseCloudDevice, MammotionCloud
|
|
6
|
+
from .mammotion_mower_ble import MammotionMowerBLEDevice
|
|
7
|
+
from .mammotion_mower_cloud import MammotionMowerCloudDevice
|
|
8
|
+
from .mower_device import MammotionMowerDevice
|
|
9
|
+
from .mower_manager import MammotionMowerDeviceManager
|
|
10
|
+
from .rtk_ble import MammotionRTKBLEDevice
|
|
11
|
+
from .rtk_cloud import MammotionRTKCloudDevice
|
|
12
|
+
from .rtk_device import MammotionRTKDevice
|
|
13
|
+
from .rtk_manager import MammotionRTKDeviceManager
|
|
4
14
|
|
|
5
|
-
__all__ = [
|
|
15
|
+
__all__ = [
|
|
16
|
+
"Mammotion",
|
|
17
|
+
"MammotionDeviceManager",
|
|
18
|
+
"MammotionMowerDeviceManager",
|
|
19
|
+
"MammotionBaseBLEDevice",
|
|
20
|
+
"MammotionBaseCloudDevice",
|
|
21
|
+
"MammotionCloud",
|
|
22
|
+
"MammotionMowerBLEDevice",
|
|
23
|
+
"MammotionMowerCloudDevice",
|
|
24
|
+
"MammotionMowerDevice",
|
|
25
|
+
"MammotionRTKBLEDevice",
|
|
26
|
+
"MammotionRTKCloudDevice",
|
|
27
|
+
"MammotionRTKDevice",
|
|
28
|
+
"MammotionRTKDeviceManager",
|
|
29
|
+
]
|
|
@@ -1,100 +1,35 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
1
2
|
import asyncio
|
|
2
3
|
import logging
|
|
3
|
-
from
|
|
4
|
-
from typing import Any, Awaitable, Callable
|
|
4
|
+
from typing import Any
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import betterproto2
|
|
7
7
|
|
|
8
8
|
from pymammotion.aliyun.model.dev_by_account_response import Device
|
|
9
|
-
from pymammotion.data.model import RegionData
|
|
10
9
|
from pymammotion.data.model.device import MowingDevice
|
|
11
|
-
from pymammotion.data.
|
|
12
|
-
from pymammotion.
|
|
13
|
-
from pymammotion.proto
|
|
10
|
+
from pymammotion.data.model.raw_data import RawMowerData
|
|
11
|
+
from pymammotion.data.mower_state_manager import MowerStateManager
|
|
12
|
+
from pymammotion.proto import LubaMsg
|
|
14
13
|
|
|
15
14
|
_LOGGER = logging.getLogger(__name__)
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
try:
|
|
20
|
-
# Find the index of the current integer
|
|
21
|
-
current_index = lst.index(current_hash)
|
|
22
|
-
|
|
23
|
-
# Check if there is a next integer in the list
|
|
24
|
-
if current_index + 1 < len(lst):
|
|
25
|
-
return lst[current_index + 1]
|
|
26
|
-
else:
|
|
27
|
-
return None # Or raise an exception or handle it in some other way
|
|
28
|
-
except ValueError:
|
|
29
|
-
# Handle the case where current_int is not in the list
|
|
30
|
-
return None # Or raise an exception or handle it in some other way
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class MammotionBaseDevice:
|
|
17
|
+
class MammotionBaseDevice(ABC):
|
|
34
18
|
"""Base class for Mammotion devices."""
|
|
35
19
|
|
|
36
|
-
|
|
37
|
-
_cloud_device: Device | None = None
|
|
38
|
-
|
|
39
|
-
def __init__(self, device: MowingDevice, cloud_device: Device | None = None) -> None:
|
|
20
|
+
def __init__(self, state_manager: MowerStateManager, cloud_device: Device) -> None:
|
|
40
21
|
"""Initialize MammotionBaseDevice."""
|
|
41
22
|
self.loop = asyncio.get_event_loop()
|
|
42
|
-
self.
|
|
43
|
-
self.
|
|
44
|
-
self.
|
|
45
|
-
self._state_manager.get_commondata_ack_callback = self.commdata_response
|
|
23
|
+
self._state_manager = state_manager
|
|
24
|
+
self._raw_data = dict()
|
|
25
|
+
self._raw_mower_data: RawMowerData = RawMowerData()
|
|
46
26
|
self._notify_future: asyncio.Future[bytes] | None = None
|
|
47
27
|
self._cloud_device = cloud_device
|
|
48
28
|
|
|
49
|
-
def set_notification_callback(self, func: Callable[[], Awaitable[None]]) -> None:
|
|
50
|
-
self._state_manager.on_notification_callback = func
|
|
51
|
-
|
|
52
|
-
def set_queue_callback(self, func: Callable[[str, dict[str, Any]], Awaitable[bytes]]) -> None:
|
|
53
|
-
self._state_manager.queue_command_callback = func
|
|
54
|
-
|
|
55
|
-
async def datahash_response(self, hash_ack: NavGetHashListAck) -> None:
|
|
56
|
-
"""Handle datahash responses."""
|
|
57
|
-
current_frame = hash_ack.current_frame
|
|
58
|
-
|
|
59
|
-
missing_frames = self.mower.map.missing_hash_frame()
|
|
60
|
-
if len(missing_frames) == 0:
|
|
61
|
-
data_hash = self.mower.map.missing_hashlist.pop()
|
|
62
|
-
return await self.queue_command("synchronize_hash_data", hash_num=data_hash)
|
|
63
|
-
|
|
64
|
-
if current_frame != missing_frames[0] - 1:
|
|
65
|
-
current_frame = missing_frames[0] - 1
|
|
66
|
-
await self.queue_command("get_hash_response", total_frame=hash_ack.total_frame, current_frame=current_frame)
|
|
67
|
-
|
|
68
|
-
async def commdata_response(self, common_data: NavGetCommDataAck) -> None:
|
|
69
|
-
"""Handle common data responses."""
|
|
70
|
-
total_frame = common_data.total_frame
|
|
71
|
-
current_frame = common_data.current_frame
|
|
72
|
-
|
|
73
|
-
missing_frames = self.mower.map.missing_frame(common_data)
|
|
74
|
-
if len(missing_frames) == 0:
|
|
75
|
-
# get next in hash ack list
|
|
76
|
-
|
|
77
|
-
data_hash = self.mower.map.missing_hashlist.pop() if len(self.mower.map.missing_hashlist) > 0 else None
|
|
78
|
-
if data_hash is None:
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
await self.queue_command("synchronize_hash_data", hash_num=data_hash)
|
|
82
|
-
else:
|
|
83
|
-
if current_frame != missing_frames[0] - 1:
|
|
84
|
-
current_frame = missing_frames[0] - 1
|
|
85
|
-
|
|
86
|
-
region_data = RegionData()
|
|
87
|
-
region_data.hash = common_data.hash
|
|
88
|
-
region_data.action = common_data.action
|
|
89
|
-
region_data.type = common_data.type
|
|
90
|
-
region_data.total_frame = total_frame
|
|
91
|
-
region_data.current_frame = current_frame
|
|
92
|
-
await self.queue_command("get_regional_data", regional_data=region_data)
|
|
93
|
-
|
|
94
29
|
def _update_raw_data(self, data: bytes) -> None:
|
|
95
30
|
"""Update raw and model data from notifications."""
|
|
96
31
|
tmp_msg = LubaMsg().parse(data)
|
|
97
|
-
res =
|
|
32
|
+
res = betterproto2.which_one_of(tmp_msg, "LubaSubMsg")
|
|
98
33
|
match res[0]:
|
|
99
34
|
case "nav":
|
|
100
35
|
self._update_nav_data(tmp_msg)
|
|
@@ -109,11 +44,11 @@ class MammotionBaseDevice:
|
|
|
109
44
|
case "ota":
|
|
110
45
|
self._update_ota_data(tmp_msg)
|
|
111
46
|
|
|
112
|
-
self.
|
|
47
|
+
self._raw_mower_data.update_raw(self._raw_data)
|
|
113
48
|
|
|
114
49
|
def _update_nav_data(self, tmp_msg) -> None:
|
|
115
50
|
"""Update navigation data."""
|
|
116
|
-
nav_sub_msg =
|
|
51
|
+
nav_sub_msg = betterproto2.which_one_of(tmp_msg.nav, "SubNavMsg")
|
|
117
52
|
if nav_sub_msg[1] is None:
|
|
118
53
|
_LOGGER.debug("Sub message was NoneType %s", nav_sub_msg[0])
|
|
119
54
|
return
|
|
@@ -121,32 +56,32 @@ class MammotionBaseDevice:
|
|
|
121
56
|
if isinstance(nav_sub_msg[1], int):
|
|
122
57
|
nav[nav_sub_msg[0]] = nav_sub_msg[1]
|
|
123
58
|
else:
|
|
124
|
-
nav[nav_sub_msg[0]] = nav_sub_msg[1].to_dict(casing=
|
|
59
|
+
nav[nav_sub_msg[0]] = nav_sub_msg[1].to_dict(casing=betterproto2.Casing.SNAKE)
|
|
125
60
|
self._raw_data["nav"] = nav
|
|
126
61
|
|
|
127
|
-
def _update_sys_data(self, tmp_msg) -> None:
|
|
62
|
+
def _update_sys_data(self, tmp_msg: LubaMsg) -> None:
|
|
128
63
|
"""Update system data."""
|
|
129
|
-
sys_sub_msg =
|
|
64
|
+
sys_sub_msg = betterproto2.which_one_of(tmp_msg.sys, "SubSysMsg")
|
|
130
65
|
if sys_sub_msg[1] is None:
|
|
131
66
|
_LOGGER.debug("Sub message was NoneType %s", sys_sub_msg[0])
|
|
132
67
|
return
|
|
133
68
|
sys = self._raw_data.get("sys", {})
|
|
134
|
-
sys[sys_sub_msg[0]] = sys_sub_msg[1].to_dict(casing=
|
|
69
|
+
sys[sys_sub_msg[0]] = sys_sub_msg[1].to_dict(casing=betterproto2.Casing.SNAKE)
|
|
135
70
|
self._raw_data["sys"] = sys
|
|
136
71
|
|
|
137
|
-
def _update_driver_data(self, tmp_msg) -> None:
|
|
72
|
+
def _update_driver_data(self, tmp_msg: LubaMsg) -> None:
|
|
138
73
|
"""Update driver data."""
|
|
139
|
-
drv_sub_msg =
|
|
74
|
+
drv_sub_msg = betterproto2.which_one_of(tmp_msg.driver, "SubDrvMsg")
|
|
140
75
|
if drv_sub_msg[1] is None:
|
|
141
76
|
_LOGGER.debug("Sub message was NoneType %s", drv_sub_msg[0])
|
|
142
77
|
return
|
|
143
78
|
drv = self._raw_data.get("driver", {})
|
|
144
|
-
drv[drv_sub_msg[0]] = drv_sub_msg[1].to_dict(casing=
|
|
79
|
+
drv[drv_sub_msg[0]] = drv_sub_msg[1].to_dict(casing=betterproto2.Casing.SNAKE)
|
|
145
80
|
self._raw_data["driver"] = drv
|
|
146
81
|
|
|
147
|
-
def _update_net_data(self, tmp_msg) -> None:
|
|
82
|
+
def _update_net_data(self, tmp_msg: LubaMsg) -> None:
|
|
148
83
|
"""Update network data."""
|
|
149
|
-
net_sub_msg =
|
|
84
|
+
net_sub_msg = betterproto2.which_one_of(tmp_msg.net, "NetSubType")
|
|
150
85
|
if net_sub_msg[1] is None:
|
|
151
86
|
_LOGGER.debug("Sub message was NoneType %s", net_sub_msg[0])
|
|
152
87
|
return
|
|
@@ -154,27 +89,27 @@ class MammotionBaseDevice:
|
|
|
154
89
|
if isinstance(net_sub_msg[1], int):
|
|
155
90
|
net[net_sub_msg[0]] = net_sub_msg[1]
|
|
156
91
|
else:
|
|
157
|
-
net[net_sub_msg[0]] = net_sub_msg[1].to_dict(casing=
|
|
92
|
+
net[net_sub_msg[0]] = net_sub_msg[1].to_dict(casing=betterproto2.Casing.SNAKE)
|
|
158
93
|
self._raw_data["net"] = net
|
|
159
94
|
|
|
160
|
-
def _update_mul_data(self, tmp_msg) -> None:
|
|
95
|
+
def _update_mul_data(self, tmp_msg: LubaMsg) -> None:
|
|
161
96
|
"""Update mul data."""
|
|
162
|
-
mul_sub_msg =
|
|
97
|
+
mul_sub_msg = betterproto2.which_one_of(tmp_msg.mul, "SubMul")
|
|
163
98
|
if mul_sub_msg[1] is None:
|
|
164
99
|
_LOGGER.debug("Sub message was NoneType %s", mul_sub_msg[0])
|
|
165
100
|
return
|
|
166
101
|
mul = self._raw_data.get("mul", {})
|
|
167
|
-
mul[mul_sub_msg[0]] = mul_sub_msg[1].to_dict(casing=
|
|
102
|
+
mul[mul_sub_msg[0]] = mul_sub_msg[1].to_dict(casing=betterproto2.Casing.SNAKE)
|
|
168
103
|
self._raw_data["mul"] = mul
|
|
169
104
|
|
|
170
|
-
def _update_ota_data(self, tmp_msg) -> None:
|
|
105
|
+
def _update_ota_data(self, tmp_msg: LubaMsg) -> None:
|
|
171
106
|
"""Update OTA data."""
|
|
172
|
-
ota_sub_msg =
|
|
107
|
+
ota_sub_msg = betterproto2.which_one_of(tmp_msg.ota, "SubOtaMsg")
|
|
173
108
|
if ota_sub_msg[1] is None:
|
|
174
109
|
_LOGGER.debug("Sub message was NoneType %s", ota_sub_msg[0])
|
|
175
110
|
return
|
|
176
111
|
ota = self._raw_data.get("ota", {})
|
|
177
|
-
ota[ota_sub_msg[0]] = ota_sub_msg[1].to_dict(casing=
|
|
112
|
+
ota[ota_sub_msg[0]] = ota_sub_msg[1].to_dict(casing=betterproto2.Casing.SNAKE)
|
|
178
113
|
self._raw_data["ota"] = ota
|
|
179
114
|
|
|
180
115
|
@property
|
|
@@ -188,53 +123,41 @@ class MammotionBaseDevice:
|
|
|
188
123
|
return self._state_manager.get_device()
|
|
189
124
|
|
|
190
125
|
@abstractmethod
|
|
191
|
-
async def queue_command(self, key: str, **kwargs:
|
|
126
|
+
async def queue_command(self, key: str, **kwargs: Any) -> None:
|
|
192
127
|
"""Queue commands to mower."""
|
|
193
128
|
|
|
194
129
|
@abstractmethod
|
|
195
|
-
async def _ble_sync(self):
|
|
130
|
+
async def _ble_sync(self) -> None:
|
|
196
131
|
"""Send ble sync command every 3 seconds or sooner."""
|
|
197
132
|
|
|
198
133
|
@abstractmethod
|
|
199
|
-
def stop(self):
|
|
134
|
+
def stop(self) -> None:
|
|
200
135
|
"""Stop everything ready for destroying."""
|
|
201
136
|
|
|
202
|
-
async def
|
|
203
|
-
"""
|
|
204
|
-
|
|
205
|
-
await self.queue_command("
|
|
206
|
-
|
|
207
|
-
""
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
""
|
|
212
|
-
|
|
213
|
-
if self._cloud_device and len(self.mower.map.area_name) == 0:
|
|
214
|
-
await self.queue_command("get_area_name_list", device_id=self._cloud_device.iotId)
|
|
215
|
-
|
|
216
|
-
await self.queue_command("read_plan", sub_cmd=2, plan_index=0)
|
|
137
|
+
async def async_read_settings(self) -> None:
|
|
138
|
+
"""Read settings from device."""
|
|
139
|
+
# no cutting in rain nav_sys_param_cmd (id 3 context 1/0)
|
|
140
|
+
await self.queue_command("read_write_device", rw_id=3, context=1, rw=0)
|
|
141
|
+
# ??
|
|
142
|
+
await self.queue_command("read_write_device", rw_id=4, context=1, rw=0)
|
|
143
|
+
# turning mode nav_sys_param_cmd (id 6, context 1/0)
|
|
144
|
+
await self.queue_command("read_write_device", rw_id=6, context=1, rw=0)
|
|
145
|
+
# traversal mode
|
|
146
|
+
await self.queue_command("read_write_device", rw_id=7, context=1, rw=0)
|
|
217
147
|
|
|
218
|
-
await self.queue_command("
|
|
219
|
-
await self.queue_command("get_hash_response", total_frame=1, current_frame=1)
|
|
220
|
-
if len(self.mower.map.missing_hashlist) > 0:
|
|
221
|
-
data_hash = self.mower.map.missing_hashlist.pop()
|
|
222
|
-
await self.queue_command("synchronize_hash_data", hash_num=data_hash)
|
|
148
|
+
await self.queue_command("read_and_set_sidelight", is_sidelight=True, operate=1)
|
|
223
149
|
|
|
224
|
-
|
|
225
|
-
# sub_cmd 4 is dump location (yuka)
|
|
226
|
-
# jobs list
|
|
227
|
-
# hash_list_result = await self._send_command_with_args("get_all_boundary_hash_list", sub_cmd=3)
|
|
150
|
+
await self.queue_command("read_and_set_rtk_pairing_code", op=1, cfg="")
|
|
228
151
|
|
|
229
152
|
async def async_get_errors(self) -> None:
|
|
230
153
|
"""Error codes."""
|
|
231
|
-
await self.queue_command("
|
|
232
|
-
await self.queue_command("
|
|
154
|
+
await self.queue_command("read_write_device", rw_id=5, rw=1, context=2)
|
|
155
|
+
await self.queue_command("read_write_device", rw_id=5, rw=1, context=3)
|
|
233
156
|
|
|
234
|
-
async def command(self, key: str, **kwargs):
|
|
157
|
+
async def command(self, key: str, **kwargs: Any) -> None:
|
|
235
158
|
"""Send a command to the device."""
|
|
236
|
-
|
|
159
|
+
await self.queue_command(key, **kwargs)
|
|
237
160
|
|
|
238
161
|
@property
|
|
239
|
-
def state_manager(self):
|
|
162
|
+
def state_manager(self) -> MowerStateManager:
|
|
240
163
|
return self._state_manager
|