pymammotion 0.4.0a4__py3-none-any.whl → 0.4.0a6__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/aliyun/cloud_gateway.py +7 -1
- pymammotion/data/model/device.py +29 -5
- pymammotion/data/model/device_info.py +13 -0
- pymammotion/data/state_manager.py +13 -8
- pymammotion/mqtt/linkkit/__init__.py +1 -1
- pymammotion/mqtt/linkkit/h2client.py +171 -135
- pymammotion/mqtt/linkkit/linkkit.py +448 -451
- pymammotion/mqtt/mammotion_mqtt.py +7 -7
- pymammotion/utility/device_config.py +657 -25
- pymammotion/utility/device_type.py +13 -1
- {pymammotion-0.4.0a4.dist-info → pymammotion-0.4.0a6.dist-info}/METADATA +3 -1
- {pymammotion-0.4.0a4.dist-info → pymammotion-0.4.0a6.dist-info}/RECORD +14 -14
- {pymammotion-0.4.0a4.dist-info → pymammotion-0.4.0a6.dist-info}/LICENSE +0 -0
- {pymammotion-0.4.0a4.dist-info → pymammotion-0.4.0a6.dist-info}/WHEEL +0 -0
@@ -57,6 +57,8 @@ class AuthRefreshException(Exception):
|
|
57
57
|
class DeviceOfflineException(Exception):
|
58
58
|
"""Raise exception when device is offline."""
|
59
59
|
|
60
|
+
class GatewayTimeoutException(Exception):
|
61
|
+
"""Raise exception when the gateway times out."""
|
60
62
|
|
61
63
|
class LoginException(Exception):
|
62
64
|
"""Raise exception when library cannot log in."""
|
@@ -657,7 +659,7 @@ class CloudIOTGateway:
|
|
657
659
|
iot_token=self._session_by_authcode_response.data.iotToken,
|
658
660
|
)
|
659
661
|
|
660
|
-
# TODO move to using
|
662
|
+
# TODO move to using InvokeThingServiceRequest()
|
661
663
|
|
662
664
|
message_id = str(uuid.uuid4())
|
663
665
|
|
@@ -689,6 +691,10 @@ class CloudIOTGateway:
|
|
689
691
|
str(response_body_dict.get("code")),
|
690
692
|
str(response_body_dict.get("message")),
|
691
693
|
)
|
694
|
+
if response_body_dict.get("code") == 20056:
|
695
|
+
logger.debug("Gateway timeout.")
|
696
|
+
raise GatewayTimeoutException(response_body_dict.get("code"))
|
697
|
+
|
692
698
|
if response_body_dict.get("code") == 29003:
|
693
699
|
logger.debug(self._session_by_authcode_response.data.identityId)
|
694
700
|
self.sign_out()
|
pymammotion/data/model/device.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
"""MowingDevice class to wrap around the betterproto dataclasses."""
|
2
2
|
|
3
3
|
from dataclasses import dataclass, field
|
4
|
-
from typing import Optional
|
5
4
|
|
6
5
|
import betterproto
|
7
6
|
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
8
7
|
|
9
8
|
from pymammotion.data.model import HashList, RapidState
|
10
|
-
from pymammotion.data.model.device_info import MowerInfo
|
9
|
+
from pymammotion.data.model.device_info import DeviceFirmwares, MowerInfo
|
11
10
|
from pymammotion.data.model.location import Location
|
12
11
|
from pymammotion.data.model.report_info import ReportData
|
13
12
|
from pymammotion.data.mqtt.properties import ThingPropertiesMessage
|
14
13
|
from pymammotion.http.model.http import ErrorInfo
|
15
14
|
from pymammotion.proto.mctrl_sys import (
|
15
|
+
DeviceFwInfo,
|
16
16
|
MowToAppInfoT,
|
17
17
|
ReportInfoData,
|
18
18
|
SystemRapidStateTunnelMsg,
|
@@ -33,8 +33,9 @@ class MowingDevice(DataClassORJSONMixin):
|
|
33
33
|
location: Location = field(default_factory=Location)
|
34
34
|
mowing_state: RapidState = field(default_factory=RapidState)
|
35
35
|
report_data: ReportData = field(default_factory=ReportData)
|
36
|
+
device_firmwares: DeviceFirmwares = field(default_factory=DeviceFirmwares)
|
36
37
|
err_code_list: list = field(default_factory=list)
|
37
|
-
err_code_list_time:
|
38
|
+
err_code_list_time: list | None = field(default_factory=list)
|
38
39
|
error_codes: dict[str, ErrorInfo] = field(default_factory=dict)
|
39
40
|
|
40
41
|
def buffer(self, buffer_list: SystemUpdateBufMsg) -> None:
|
@@ -84,7 +85,7 @@ class MowingDevice(DataClassORJSONMixin):
|
|
84
85
|
for index, location in enumerate(toapp_report_data.locations):
|
85
86
|
if index == 0 and location.real_pos_y != 0:
|
86
87
|
self.location.position_type = location.pos_type
|
87
|
-
self.location.orientation = location.real_toward / 10000
|
88
|
+
self.location.orientation = int(location.real_toward / 10000)
|
88
89
|
self.location.device = coordinate_converter.enu_to_lla(
|
89
90
|
parse_double(location.real_pos_y, 4.0), parse_double(location.real_pos_x, 4.0)
|
90
91
|
)
|
@@ -93,13 +94,16 @@ class MowingDevice(DataClassORJSONMixin):
|
|
93
94
|
location.zone_hash if self.report_data.dev.sys_status == WorkMode.MODE_WORKING else 0
|
94
95
|
)
|
95
96
|
|
97
|
+
if toapp_report_data.fw_info:
|
98
|
+
self.update_device_firmwares(toapp_report_data.fw_info)
|
99
|
+
|
96
100
|
self.report_data.update(toapp_report_data.to_dict(casing=betterproto.Casing.SNAKE))
|
97
101
|
|
98
102
|
def run_state_update(self, rapid_state: SystemRapidStateTunnelMsg) -> None:
|
99
103
|
coordinate_converter = CoordinateConverter(self.location.RTK.latitude, self.location.RTK.longitude)
|
100
104
|
self.mowing_state = RapidState().from_raw(rapid_state.rapid_state_data)
|
101
105
|
self.location.position_type = self.mowing_state.pos_type
|
102
|
-
self.location.orientation = self.mowing_state.toward / 10000
|
106
|
+
self.location.orientation = int(self.mowing_state.toward / 10000)
|
103
107
|
self.location.device = coordinate_converter.enu_to_lla(
|
104
108
|
parse_double(self.mowing_state.pos_y, 4.0), parse_double(self.mowing_state.pos_x, 4.0)
|
105
109
|
)
|
@@ -113,3 +117,23 @@ class MowingDevice(DataClassORJSONMixin):
|
|
113
117
|
|
114
118
|
def report_missing_data(self) -> None:
|
115
119
|
"""Report missing data so we can refetch it."""
|
120
|
+
|
121
|
+
def update_device_firmwares(self, fw_info: DeviceFwInfo) -> None:
|
122
|
+
"""Sets firmware versions on all parts of the robot or RTK."""
|
123
|
+
for mod in fw_info.mod:
|
124
|
+
match mod.type:
|
125
|
+
case 1:
|
126
|
+
self.device_firmwares.main_controller = mod.version
|
127
|
+
case 3:
|
128
|
+
self.device_firmwares.left_motor_driver = mod.version
|
129
|
+
case 4:
|
130
|
+
self.device_firmwares.right_motor_driver = mod.version
|
131
|
+
case 5:
|
132
|
+
self.device_firmwares.rtk_rover_station = mod.version
|
133
|
+
case 101:
|
134
|
+
# RTK main board
|
135
|
+
self.device_firmwares.main_controller = mod.version
|
136
|
+
case 102:
|
137
|
+
self.device_firmwares.rtk_version = mod.version
|
138
|
+
case 103:
|
139
|
+
self.device_firmwares.lora_version = mod.version
|
@@ -23,3 +23,16 @@ class MowerInfo(DataClassORJSONMixin):
|
|
23
23
|
swversion: str = ""
|
24
24
|
product_key: str = ""
|
25
25
|
model_id: str = ""
|
26
|
+
|
27
|
+
|
28
|
+
@dataclass
|
29
|
+
class DeviceFirmwares(DataClassORJSONMixin):
|
30
|
+
device_version: str = ""
|
31
|
+
left_motor_driver: str = ""
|
32
|
+
lora_version: str = ""
|
33
|
+
main_controller: str = ""
|
34
|
+
model_name: str = ""
|
35
|
+
right_motor_driver: str = ""
|
36
|
+
rtk_rover_station: str = ""
|
37
|
+
rtk_version: str = ""
|
38
|
+
version: str = ""
|
@@ -1,8 +1,9 @@
|
|
1
1
|
"""Manage state from notifications into MowingDevice."""
|
2
2
|
|
3
3
|
import logging
|
4
|
+
from collections.abc import Awaitable, Callable
|
4
5
|
from datetime import datetime
|
5
|
-
from typing import Any
|
6
|
+
from typing import Any
|
6
7
|
|
7
8
|
import betterproto
|
8
9
|
|
@@ -10,7 +11,7 @@ from pymammotion.data.model.device import MowingDevice
|
|
10
11
|
from pymammotion.data.model.device_info import SideLight
|
11
12
|
from pymammotion.data.model.hash_list import AreaHashNameList
|
12
13
|
from pymammotion.data.mqtt.properties import ThingPropertiesMessage
|
13
|
-
from pymammotion.proto.dev_net import WifiIotStatusReport
|
14
|
+
from pymammotion.proto.dev_net import DrvDevInfoResp, WifiIotStatusReport
|
14
15
|
from pymammotion.proto.luba_msg import LubaMsg
|
15
16
|
from pymammotion.proto.mctrl_nav import AppGetAllAreaHashName, NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
|
16
17
|
from pymammotion.proto.mctrl_sys import DeviceProductTypeInfoT, TimeCtrlLight
|
@@ -26,12 +27,10 @@ class StateManager:
|
|
26
27
|
|
27
28
|
def __init__(self, device: MowingDevice) -> None:
|
28
29
|
self._device = device
|
29
|
-
self.gethash_ack_callback:
|
30
|
-
self.get_commondata_ack_callback:
|
31
|
-
|
32
|
-
|
33
|
-
self.on_notification_callback: Optional[Callable[[tuple[str, Any | None]], Awaitable[None]]] = None
|
34
|
-
self.queue_command_callback: Optional[Callable[[str, dict[str, Any]], Awaitable[bytes]]] = None
|
30
|
+
self.gethash_ack_callback: Callable[[NavGetHashListAck], Awaitable[None]] | None = None
|
31
|
+
self.get_commondata_ack_callback: Callable[[NavGetCommDataAck | SvgMessageAckT], Awaitable[None]] | None = None
|
32
|
+
self.on_notification_callback: Callable[[tuple[str, Any | None]], Awaitable[None]] | None = None
|
33
|
+
self.queue_command_callback: Callable[[str, dict[str, Any]], Awaitable[bytes]] | None = None
|
35
34
|
self.last_updated_at = datetime.now()
|
36
35
|
|
37
36
|
def get_device(self) -> MowingDevice:
|
@@ -121,6 +120,12 @@ class StateManager:
|
|
121
120
|
case "toapp_wifi_iot_status":
|
122
121
|
wifi_iot_status: WifiIotStatusReport = net_msg[1]
|
123
122
|
self._device.mower_state.product_key = wifi_iot_status.productkey
|
123
|
+
case "toapp_devinfo_resp":
|
124
|
+
toapp_devinfo_resp: DrvDevInfoResp = net_msg[1]
|
125
|
+
for resp in toapp_devinfo_resp.resp_ids:
|
126
|
+
if resp.res == "DRV_RESULT_SUC":
|
127
|
+
self._device.mower_state.swversion = resp.info
|
128
|
+
self._device.device_firmwares.device_version = resp.info
|
124
129
|
|
125
130
|
def _update_mul_data(self, message) -> None:
|
126
131
|
pass
|