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.
@@ -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 InvokeThingServiceRequest()
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()
@@ -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: Optional[list] = field(default_factory=list)
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, Awaitable, Callable, Optional
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: Optional[Callable[[NavGetHashListAck], Awaitable[None]]] = None
30
- self.get_commondata_ack_callback: Optional[Callable[[NavGetCommDataAck | SvgMessageAckT], Awaitable[None]]] = (
31
- None
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
@@ -2,4 +2,4 @@
2
2
 
3
3
  from .linkkit import LinkKit
4
4
 
5
- __all__ = ["LinkKit"]
5
+ __all__ = ["LinkKit"]