pymammotion 0.0.37__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.

Files changed (106) hide show
  1. pymammotion/__init__.py +43 -0
  2. pymammotion/aliyun/cloud_gateway.py +549 -0
  3. pymammotion/aliyun/cloud_service.py +65 -0
  4. pymammotion/aliyun/dataclass/aep_response.py +18 -0
  5. pymammotion/aliyun/dataclass/connect_response.py +51 -0
  6. pymammotion/aliyun/dataclass/dev_by_account_response.py +43 -0
  7. pymammotion/aliyun/dataclass/login_by_oauth_response.py +65 -0
  8. pymammotion/aliyun/dataclass/regions_response.py +26 -0
  9. pymammotion/aliyun/dataclass/session_by_authcode_response.py +18 -0
  10. pymammotion/aliyun/tmp_constant.py +175 -0
  11. pymammotion/bluetooth/__init__.py +1 -0
  12. pymammotion/bluetooth/ble.py +74 -0
  13. pymammotion/bluetooth/ble_message.py +430 -0
  14. pymammotion/bluetooth/const.py +27 -0
  15. pymammotion/bluetooth/data/__init__.py +0 -0
  16. pymammotion/bluetooth/data/convert.py +26 -0
  17. pymammotion/bluetooth/data/framectrldata.py +40 -0
  18. pymammotion/bluetooth/data/notifydata.py +63 -0
  19. pymammotion/const.py +9 -0
  20. pymammotion/data/__init__.py +0 -0
  21. pymammotion/data/model/__init__.py +8 -0
  22. pymammotion/data/model/device.py +157 -0
  23. pymammotion/data/model/enums.py +67 -0
  24. pymammotion/data/model/excute_boarder_params.py +48 -0
  25. pymammotion/data/model/execute_boarder.py +36 -0
  26. pymammotion/data/model/generate_route_information.py +133 -0
  27. pymammotion/data/model/hash_list.py +17 -0
  28. pymammotion/data/model/mowing_modes.py +37 -0
  29. pymammotion/data/model/plan.py +58 -0
  30. pymammotion/data/model/rapid_state.py +45 -0
  31. pymammotion/data/model/region_data.py +99 -0
  32. pymammotion/data/mqtt/__init__.py +1 -0
  33. pymammotion/data/mqtt/event.py +90 -0
  34. pymammotion/data/mqtt/properties.py +140 -0
  35. pymammotion/data/mqtt/status.py +52 -0
  36. pymammotion/event/__init__.py +6 -0
  37. pymammotion/event/event.py +50 -0
  38. pymammotion/http/_init_.py +0 -0
  39. pymammotion/http/http.py +76 -0
  40. pymammotion/luba/_init_.py +0 -0
  41. pymammotion/luba/base.py +52 -0
  42. pymammotion/mammotion/__init__.py +0 -0
  43. pymammotion/mammotion/commands/__init__.py +0 -0
  44. pymammotion/mammotion/commands/abstract_message.py +7 -0
  45. pymammotion/mammotion/commands/mammotion_command.py +34 -0
  46. pymammotion/mammotion/commands/messages/__init__.py +0 -0
  47. pymammotion/mammotion/commands/messages/driver.py +108 -0
  48. pymammotion/mammotion/commands/messages/media.py +36 -0
  49. pymammotion/mammotion/commands/messages/navigation.py +535 -0
  50. pymammotion/mammotion/commands/messages/network.py +236 -0
  51. pymammotion/mammotion/commands/messages/ota.py +34 -0
  52. pymammotion/mammotion/commands/messages/system.py +266 -0
  53. pymammotion/mammotion/commands/messages/video.py +27 -0
  54. pymammotion/mammotion/control/__init__.py +0 -0
  55. pymammotion/mammotion/control/joystick.py +184 -0
  56. pymammotion/mammotion/devices/__init__.py +1 -0
  57. pymammotion/mammotion/devices/luba.py +564 -0
  58. pymammotion/mqtt/mqtt.py +230 -0
  59. pymammotion/proto/__init__.py +0 -0
  60. pymammotion/proto/common.proto +7 -0
  61. pymammotion/proto/common.py +12 -0
  62. pymammotion/proto/common_pb2.py +25 -0
  63. pymammotion/proto/common_pb2.pyi +13 -0
  64. pymammotion/proto/dev_net.proto +297 -0
  65. pymammotion/proto/dev_net.py +381 -0
  66. pymammotion/proto/dev_net_pb2.py +107 -0
  67. pymammotion/proto/dev_net_pb2.pyi +472 -0
  68. pymammotion/proto/luba_msg.proto +73 -0
  69. pymammotion/proto/luba_msg.py +80 -0
  70. pymammotion/proto/luba_msg_pb2.py +40 -0
  71. pymammotion/proto/luba_msg_pb2.pyi +93 -0
  72. pymammotion/proto/luba_mul.proto +68 -0
  73. pymammotion/proto/luba_mul.py +76 -0
  74. pymammotion/proto/luba_mul_pb2.py +45 -0
  75. pymammotion/proto/luba_mul_pb2.pyi +91 -0
  76. pymammotion/proto/mctrl_driver.proto +67 -0
  77. pymammotion/proto/mctrl_driver.py +100 -0
  78. pymammotion/proto/mctrl_driver_pb2.py +45 -0
  79. pymammotion/proto/mctrl_driver_pb2.pyi +112 -0
  80. pymammotion/proto/mctrl_nav.proto +485 -0
  81. pymammotion/proto/mctrl_nav.py +589 -0
  82. pymammotion/proto/mctrl_nav_pb2.py +116 -0
  83. pymammotion/proto/mctrl_nav_pb2.pyi +875 -0
  84. pymammotion/proto/mctrl_ota.proto +42 -0
  85. pymammotion/proto/mctrl_ota.py +48 -0
  86. pymammotion/proto/mctrl_ota_pb2.py +35 -0
  87. pymammotion/proto/mctrl_ota_pb2.pyi +65 -0
  88. pymammotion/proto/mctrl_pept.proto +29 -0
  89. pymammotion/proto/mctrl_pept.py +41 -0
  90. pymammotion/proto/mctrl_pept_pb2.py +31 -0
  91. pymammotion/proto/mctrl_pept_pb2.pyi +50 -0
  92. pymammotion/proto/mctrl_sys.proto +487 -0
  93. pymammotion/proto/mctrl_sys.py +574 -0
  94. pymammotion/proto/mctrl_sys_pb2.py +142 -0
  95. pymammotion/proto/mctrl_sys_pb2.pyi +787 -0
  96. pymammotion/py.typed +0 -0
  97. pymammotion/utility/constant/__init__.py +1 -0
  98. pymammotion/utility/constant/device_constant.py +238 -0
  99. pymammotion/utility/datatype_converter.py +80 -0
  100. pymammotion/utility/device_type.py +152 -0
  101. pymammotion/utility/periodic.py +41 -0
  102. pymammotion/utility/rocker_util.py +135 -0
  103. pymammotion-0.0.37.dist-info/LICENSE +674 -0
  104. pymammotion-0.0.37.dist-info/METADATA +92 -0
  105. pymammotion-0.0.37.dist-info/RECORD +106 -0
  106. pymammotion-0.0.37.dist-info/WHEEL +4 -0
@@ -0,0 +1,99 @@
1
+ from typing import List, Optional
2
+
3
+
4
+ class RegionData:
5
+ def __init__(self):
6
+ self.hash: Optional[int] = None
7
+ self.action: int = 0
8
+ self.current_frame: int = 0
9
+ self.data_hash: Optional[int] = None
10
+ self.data_len: int = 0
11
+ self.p_hash_a: Optional[int] = None
12
+ self.p_hash_b: Optional[int] = None
13
+ self.path: Optional[List[List[float]]] = None
14
+ self.pver: int = 0
15
+ self.result: int = 0
16
+ self.sub_cmd: int = 0
17
+ self.total_frame: int = 0
18
+ self.type: int = 0
19
+
20
+ def set_hash(self, hash: int) -> None:
21
+ self.hash = hash
22
+
23
+ def get_data_len(self) -> int:
24
+ return self.data_len
25
+
26
+ def set_data_len(self, data_len: int) -> None:
27
+ self.data_len = data_len
28
+
29
+ def get_pver(self) -> int:
30
+ return self.pver
31
+
32
+ def set_pver(self, pver: int) -> None:
33
+ self.pver = pver
34
+
35
+ def get_sub_cmd(self) -> int:
36
+ return self.sub_cmd
37
+
38
+ def set_sub_cmd(self, sub_cmd: int) -> None:
39
+ self.sub_cmd = sub_cmd
40
+
41
+ def get_result(self) -> int:
42
+ return self.result
43
+
44
+ def set_result(self, result: int) -> None:
45
+ self.result = result
46
+
47
+ def get_action(self) -> int:
48
+ return self.action
49
+
50
+ def set_action(self, action: int) -> None:
51
+ self.action = action
52
+
53
+ def get_type(self) -> int:
54
+ return self.type
55
+
56
+ def set_type(self, type: int) -> None:
57
+ self.type = type
58
+
59
+ def get_total_frame(self) -> int:
60
+ return self.total_frame
61
+
62
+ def set_total_frame(self, total_frame: int) -> None:
63
+ self.total_frame = total_frame
64
+
65
+ def get_current_frame(self) -> int:
66
+ return self.current_frame
67
+
68
+ def set_current_frame(self, current_frame: int) -> None:
69
+ self.current_frame = current_frame
70
+
71
+ def get_path(self) -> Optional[List[List[float]]]:
72
+ return self.path
73
+
74
+ def set_path(self, path: List[List[float]]) -> None:
75
+ self.path = path
76
+
77
+ def get_hash(self) -> Optional[int]:
78
+ return self.hash
79
+
80
+ def set_data_hash(self, data_hash: int) -> None:
81
+ self.data_hash = data_hash
82
+
83
+ def get_data_hash(self) -> Optional[int]:
84
+ return self.data_hash
85
+
86
+ def set_p_hash_a(self, p_hash_a: int) -> None:
87
+ self.p_hash_a = p_hash_a
88
+
89
+ def get_p_hash_a(self) -> Optional[int]:
90
+ return self.p_hash_a
91
+
92
+ def set_p_hash_b(self, p_hash_b: int) -> None:
93
+ self.p_hash_b = p_hash_b
94
+
95
+ def get_p_hash_b(self) -> Optional[int]:
96
+ return self.p_hash_b
97
+
98
+ def __str__(self) -> str:
99
+ return f"RegionData{{pver={self.pver}, sub_cmd={self.sub_cmd}, result={self.result}, action={self.action}, type={self.type}, Hash={self.hash}, total_frame={self.total_frame}, current_frame={self.current_frame}, data_hash={self.data_hash}, p_hash_a={self.p_hash_a}, p_hash_b={self.p_hash_b}, data_len={self.data_len}, path={self.path}}}"
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,90 @@
1
+ from base64 import b64decode
2
+ from dataclasses import dataclass
3
+ from typing import Any, Literal, Union
4
+
5
+ from google.protobuf import json_format
6
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
7
+ from mashumaro.types import SerializableType
8
+
9
+ from pyluba.proto import luba_msg_pb2
10
+
11
+
12
+ class Base64EncodedProtobuf(SerializableType):
13
+ def __init__(self, proto: str):
14
+ self.proto = proto
15
+
16
+ def _serialize(self):
17
+ return self.proto
18
+
19
+ @classmethod
20
+ def _deserialize(cls, value):
21
+ return cls(*value)
22
+
23
+ @classmethod
24
+ def __get_validators__(cls):
25
+ yield cls.validate
26
+
27
+ @classmethod
28
+ def validate(cls, v: str):
29
+ if not isinstance(v, str):
30
+ raise TypeError("string required")
31
+ binary = b64decode(v, validate=True)
32
+ data = luba_msg_pb2.LubaMsg()
33
+ data.ParseFromString(binary)
34
+ return json_format.MessageToDict(data)
35
+
36
+
37
+ @dataclass
38
+ class DeviceProtobufMsgEventValue(DataClassORJSONMixin):
39
+ content: Base64EncodedProtobuf
40
+
41
+
42
+ @dataclass
43
+ class DeviceWarningEventValue(DataClassORJSONMixin):
44
+ # TODO: enum for error codes
45
+ # (see resources/res/values-en-rUS/strings.xml in APK)
46
+ code: int
47
+
48
+
49
+ @dataclass
50
+ class GeneralParams(DataClassORJSONMixin):
51
+ identifier: str
52
+ groupIdList: list[str]
53
+ groupId: str
54
+ categoryKey: Literal["LawnMower"]
55
+ batchId: str
56
+ gmtCreate: int
57
+ productKey: str
58
+ type: str
59
+ deviceName: str
60
+ iotId: str
61
+ checkLevel: int
62
+ namespace: str
63
+ tenantId: str
64
+ name: str
65
+ thingType: Literal["DEVICE"]
66
+ time: int
67
+ tenantInstanceId: str
68
+ value: Any
69
+
70
+
71
+ @dataclass
72
+ class DeviceProtobufMsgEventParams(GeneralParams):
73
+ identifier: Literal["device_protobuf_msg_event"]
74
+ type: Literal["info"]
75
+ value: DeviceProtobufMsgEventValue
76
+
77
+
78
+ @dataclass
79
+ class DeviceWarningEventParams(GeneralParams):
80
+ identifier: Literal["device_warning_event"]
81
+ type: Literal["alert"]
82
+ value: DeviceWarningEventValue
83
+
84
+
85
+ @dataclass
86
+ class ThingEventMessage(DataClassORJSONMixin):
87
+ method: Literal["thing.events"]
88
+ id: str
89
+ params: Union[DeviceProtobufMsgEventParams, DeviceWarningEventParams]
90
+ version: Literal["1.0"]
@@ -0,0 +1,140 @@
1
+ from dataclasses import dataclass
2
+ from typing import Generic, Literal, TypeVar, Union
3
+
4
+ from mashumaro import DataClassDictMixin
5
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
6
+
7
+ DataT = TypeVar("DataT")
8
+
9
+
10
+ @dataclass
11
+ class Item(DataClassDictMixin, Generic[DataT]):
12
+ time: int
13
+ value: DataT
14
+
15
+
16
+ @dataclass
17
+ class BatteryPercentageItems(DataClassORJSONMixin):
18
+ batteryPercentage: Item[int]
19
+
20
+
21
+ @dataclass
22
+ class BMSHardwareVersionItems(DataClassORJSONMixin):
23
+ bmsHardwareVersion: Item[str]
24
+
25
+
26
+ @dataclass
27
+ class CoordinateItems(DataClassORJSONMixin):
28
+ coordinate: Item[str] # '{"lon":0.303903,"lat":1.051868}'
29
+
30
+
31
+ @dataclass
32
+ class DeviceStateItems(DataClassORJSONMixin):
33
+ deviceState: Item[int]
34
+
35
+
36
+ @dataclass
37
+ class DeviceVersionItems(DataClassORJSONMixin):
38
+ deviceVersion: Item[str]
39
+
40
+
41
+ @dataclass
42
+ class DeviceVersionInfoItems(DataClassORJSONMixin):
43
+ deviceVersionInfo: Item[str]
44
+
45
+
46
+ @dataclass
47
+ class ESP32VersionItems(DataClassORJSONMixin):
48
+ esp32Version: Item[str]
49
+
50
+
51
+ @dataclass
52
+ class LeftMotorBootVersionItems(DataClassORJSONMixin):
53
+ leftMotorBootVersion: Item[str]
54
+
55
+
56
+ @dataclass
57
+ class LeftMotorVersionItems(DataClassORJSONMixin):
58
+ leftMotorVersion: Item[str]
59
+
60
+
61
+ @dataclass
62
+ class MCBootVersionItems(DataClassORJSONMixin):
63
+ mcBootVersion: Item[str]
64
+
65
+
66
+ @dataclass
67
+ class NetworkInfoItems(DataClassORJSONMixin):
68
+ networkInfo: Item[str]
69
+
70
+
71
+ @dataclass
72
+ class RightMotorBootVersionItems(DataClassORJSONMixin):
73
+ rightMotorBootVersion: Item[str]
74
+
75
+
76
+ @dataclass
77
+ class RightMotorVersionItems(DataClassORJSONMixin):
78
+ rightMotorVersion: Item[str]
79
+
80
+
81
+ @dataclass
82
+ class RTKVersionItems(DataClassORJSONMixin):
83
+ rtkVersion: Item[str]
84
+
85
+
86
+ @dataclass
87
+ class StationRTKVersionItems(DataClassORJSONMixin):
88
+ stationRtkVersion: Item[str]
89
+
90
+
91
+ @dataclass
92
+ class STM32H7VersionItems(DataClassORJSONMixin):
93
+ stm32H7Version: Item[str]
94
+
95
+
96
+ Items = Union[
97
+ BatteryPercentageItems,
98
+ BMSHardwareVersionItems,
99
+ CoordinateItems,
100
+ DeviceStateItems,
101
+ DeviceVersionItems,
102
+ DeviceVersionInfoItems,
103
+ ESP32VersionItems,
104
+ LeftMotorBootVersionItems,
105
+ LeftMotorVersionItems,
106
+ MCBootVersionItems,
107
+ NetworkInfoItems,
108
+ RightMotorBootVersionItems,
109
+ RightMotorVersionItems,
110
+ RTKVersionItems,
111
+ StationRTKVersionItems,
112
+ STM32H7VersionItems,
113
+ ]
114
+
115
+
116
+ @dataclass
117
+ class Params(DataClassORJSONMixin):
118
+ checkFailedData: dict
119
+ groupIdList: list[str]
120
+ groupId: str
121
+ categoryKey: Literal["LawnMower"]
122
+ batchId: str
123
+ gmtCreate: int
124
+ productKey: str
125
+ deviceName: str
126
+ iotId: str
127
+ checkLevel: int
128
+ namespace: str
129
+ tenantId: str
130
+ thingType: Literal["DEVICE"]
131
+ items: Items
132
+ tenantInstanceId: str
133
+
134
+
135
+ @dataclass
136
+ class ThingPropertiesMessage(DataClassORJSONMixin):
137
+ method: Literal["thing.properties"]
138
+ id: str
139
+ params: Params
140
+ version: Literal["1.0"]
@@ -0,0 +1,52 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+ from typing import Literal
4
+
5
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
6
+
7
+
8
+ @dataclass
9
+ class GroupIdListItem(DataClassORJSONMixin):
10
+ groupId: str
11
+ groupType: Literal["ISOLATION"]
12
+
13
+
14
+ # are there other values?
15
+ class StatusType(Enum):
16
+ CONNECTED = 1
17
+ DISCONNECTED = 3
18
+
19
+
20
+ @dataclass
21
+ class Status(DataClassORJSONMixin):
22
+ time: int
23
+ value: StatusType
24
+
25
+
26
+ @dataclass
27
+ class Params(DataClassORJSONMixin):
28
+ groupIdList: list[GroupIdListItem]
29
+ netType: Literal["NET_WIFI"]
30
+ activeTime: int
31
+ ip: str
32
+ aliyunCommodityCode: Literal["iothub_senior"]
33
+ categoryKey: Literal["LawnMower"]
34
+ nodeType: Literal["DEVICE"]
35
+ productKey: str
36
+ statusLast: int
37
+ deviceName: str
38
+ iotId: str
39
+ namespace: str
40
+ tenantId: str
41
+ thingType: Literal["DEVICE"]
42
+ tenantInstanceId: str
43
+ categoryId: int
44
+ status: Status
45
+
46
+
47
+ @dataclass
48
+ class ThingStatusMessage(DataClassORJSONMixin):
49
+ method: Literal["thing.status"]
50
+ id: str
51
+ params: Params
52
+ version: Literal["1.0"]
@@ -0,0 +1,6 @@
1
+ # __init__.py
2
+
3
+ # version of Luba Desktop
4
+ __version__ = "0.0.1"
5
+
6
+ from .event import BleNotificationEvent, MoveEvent
@@ -0,0 +1,50 @@
1
+ import asyncio
2
+
3
+
4
+ class Event:
5
+ def __init__(self):
6
+ self.__eventhandlers = []
7
+
8
+ def __iadd__(self, handler):
9
+ self.__eventhandlers.append(handler)
10
+ return self
11
+
12
+ def __isub__(self, handler):
13
+ self.__eventhandlers.remove(handler)
14
+ return self
15
+
16
+ async def __call__(self, *args, **kwargs):
17
+ await asyncio.gather(
18
+ *[handler(*args, **kwargs) for handler in self.__eventhandlers]
19
+ )
20
+
21
+
22
+ class MoveEvent:
23
+ def __init__(self):
24
+ self.OnMoveFinished = Event()
25
+
26
+ async def MoveFinished(self):
27
+ # This function will be executed once blufi finishes after a movement command and will
28
+ # raise an event
29
+ await self.OnMoveFinished()
30
+
31
+ def AddSubscribersForMoveFinishedEvent(self, objMethod):
32
+ self.OnMoveFinished += objMethod
33
+
34
+ def RemoveSubscribersForMoveFinishedEvent(self, objMethod):
35
+ self.OnMoveFinished -= objMethod
36
+
37
+
38
+ class BleNotificationEvent:
39
+ def __init__(self):
40
+ self.OnBleNotification = Event()
41
+
42
+ async def BleNotification(self, data: bytearray):
43
+ # This function will be executed when data is received.
44
+ await self.OnBleNotification(data)
45
+
46
+ def AddSubscribersForBleNotificationEvent(self, objMethod):
47
+ self.OnBleNotification += objMethod
48
+
49
+ def RemoveSubscribersForBleNotificationEvent(self, objMethod):
50
+ self.OnBleNotification -= objMethod
File without changes
@@ -0,0 +1,76 @@
1
+ from dataclasses import dataclass
2
+ from typing import Generic, Literal, TypeVar
3
+
4
+ from aiohttp import ClientSession
5
+ from mashumaro import DataClassDictMixin
6
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
7
+
8
+ from pyluba.const import MAMMOTION_CLIENT_ID, MAMMOTION_CLIENT_SECRET, MAMMOTION_DOMAIN
9
+
10
+ DataT = TypeVar("DataT")
11
+
12
+
13
+ @dataclass
14
+ class Response(DataClassDictMixin, Generic[DataT]):
15
+ data: DataT
16
+ code: int
17
+ msg: str
18
+
19
+
20
+ @dataclass
21
+ class LoginResponseUserInformation(DataClassORJSONMixin):
22
+ areaCode: str
23
+ domainAbbreviation: str
24
+ email: str
25
+ userId: str
26
+ userAccount: str
27
+ authType: str
28
+
29
+
30
+ @dataclass
31
+ class LoginResponseData(DataClassORJSONMixin):
32
+ access_token: str
33
+ token_type: Literal["bearer"]
34
+ refresh_token: str
35
+ expires_in: int
36
+ scope: Literal["read"]
37
+ grant_type: Literal["password"]
38
+ authorization_code: str
39
+ userInformation: LoginResponseUserInformation
40
+ jti: str
41
+
42
+
43
+ class LubaHTTP:
44
+ def __init__(self, session: ClientSession, login: LoginResponseData):
45
+ self._session = session
46
+ self._session.headers["Authorization"] = f"Bearer {login.access_token}"
47
+ self._login = login
48
+
49
+ @classmethod
50
+ async def login(
51
+ cls, session: ClientSession, username: str, password: str
52
+ ) -> Response[LoginResponseData]:
53
+ async with session.post(
54
+ "/user-server/v1/user/oauth/token",
55
+ params=dict(
56
+ username=username,
57
+ password=password,
58
+ client_id=MAMMOTION_CLIENT_ID,
59
+ client_secret=MAMMOTION_CLIENT_SECRET,
60
+ grant_type="password",
61
+ ),
62
+ ) as resp:
63
+ data = await resp.json()
64
+ print(data)
65
+ # TODO catch errors from mismatch user / password
66
+ # Assuming the data format matches the expected structure
67
+ login_response_data = LoginResponseData.from_dict(data["data"])
68
+ return Response(
69
+ data=login_response_data, code=data["code"], msg=data["msg"]
70
+ )
71
+
72
+
73
+ async def connect_http(username: str, password: str) -> LubaHTTP:
74
+ async with ClientSession(MAMMOTION_DOMAIN) as session:
75
+ login_response = await LubaHTTP.login(session, username, password)
76
+ return LubaHTTP(session, login_response.data)
File without changes
@@ -0,0 +1,52 @@
1
+ from typing import Callable, Optional
2
+
3
+ from pyluba.data.model.rapid_state import RapidState, RTKStatus
4
+ from pyluba.data.mqtt.status import StatusType
5
+
6
+
7
+ class BaseLuba:
8
+ def __init__(self):
9
+ self._rapid_state: Optional[RapidState] = None
10
+ self.on_pos_change: Optional[Callable[[float, float, float], None]] = None
11
+ self.on_rtk_change: Optional[Callable[[RTKStatus, float, int, int], None]] = (
12
+ None
13
+ )
14
+
15
+ self.on_warning: Optional[Callable[[int], None]] = None
16
+
17
+ self._status: Optional[StatusType] = None
18
+ self.on_status_change: Optional[Callable[[StatusType], None]] = None
19
+
20
+ def _set_rapid_state(self, state: RapidState):
21
+ old_state = self._rapid_state
22
+ self._rapid_state = state
23
+ if old_state:
24
+ if (
25
+ old_state.pos_x != state.pos_x
26
+ or old_state.pos_y != state.pos_y
27
+ or old_state.toward != state.toward
28
+ ):
29
+ if self.on_pos_change:
30
+ self.on_pos_change(state.pos_x, state.pos_y, state.toward)
31
+ if (
32
+ old_state.rtk_status != state.rtk_status
33
+ or old_state.rtk_age != state.rtk_age
34
+ or old_state.satellites_total != state.satellites_total
35
+ or old_state.satellites_l2 != state.satellites_l2
36
+ ):
37
+ if self.on_rtk_change:
38
+ self.on_rtk_change(
39
+ state.rtk_status,
40
+ state.rtk_age,
41
+ state.satellites_total,
42
+ state.satellites_l2,
43
+ )
44
+
45
+ def _set_status(self, status: StatusType):
46
+ self._status = status
47
+ if self.on_status_change:
48
+ self.on_status_change(status)
49
+
50
+ @property
51
+ def status(self) -> Optional[StatusType]:
52
+ return self._status
File without changes
File without changes
@@ -0,0 +1,7 @@
1
+ from abc import abstractmethod
2
+
3
+
4
+ class AbstractMessage:
5
+ @abstractmethod
6
+ def get_device_name(self) -> str:
7
+ """Get device name."""
@@ -0,0 +1,34 @@
1
+ from pyluba.mammotion.commands.messages.navigation import MessageNavigation
2
+ from pyluba.mammotion.commands.messages.network import MessageNetwork
3
+ from pyluba.mammotion.commands.messages.ota import MessageOta
4
+ from pyluba.mammotion.commands.messages.system import MessageSystem
5
+ from pyluba.mammotion.commands.messages.video import MessageVideo
6
+ from pyluba.proto import dev_net_pb2, luba_msg_pb2
7
+
8
+
9
+ class MammotionCommand(
10
+ MessageSystem, MessageNavigation, MessageNetwork, MessageOta, MessageVideo
11
+ ):
12
+ """MQTT commands for Luba."""
13
+
14
+ def __init__(self, device_name: str) -> None:
15
+ self._device_name = device_name
16
+
17
+ def get_device_name(self) -> str:
18
+ """Get device name."""
19
+ return self._device_name
20
+
21
+ """BLE commands for Luba."""
22
+
23
+ def send_todev_ble_sync(self, sync_type: int) -> bytes:
24
+ commEsp = dev_net_pb2.DevNet(todev_ble_sync=sync_type)
25
+
26
+ lubaMsg = luba_msg_pb2.LubaMsg()
27
+ lubaMsg.msgtype = luba_msg_pb2.MSG_CMD_TYPE_ESP
28
+ lubaMsg.sender = luba_msg_pb2.DEV_MOBILEAPP
29
+ lubaMsg.msgattr = luba_msg_pb2.MSG_ATTR_REQ
30
+ lubaMsg.seqs = 1
31
+ lubaMsg.version = 1
32
+ lubaMsg.subtype = 1
33
+ lubaMsg.net.CopyFrom(commEsp)
34
+ return lubaMsg.SerializeToString()
File without changes