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,157 @@
1
+ """MowingDevice class to wrap around the betterproto dataclasses."""
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from pyluba.proto.dev_net import DevNet
6
+ from pyluba.proto.luba_msg import LubaMsg
7
+ from pyluba.proto.luba_mul import SocMul
8
+ from pyluba.proto.mctrl_driver import MctlDriver
9
+ from pyluba.proto.mctrl_nav import MctlNav
10
+ from pyluba.proto.mctrl_ota import MctlOta
11
+ from pyluba.proto.mctrl_pept import MctlPept
12
+ from pyluba.proto.mctrl_sys import MctlSys
13
+
14
+
15
+ @dataclass
16
+ class MowingDevice:
17
+ """Wraps the betterproto dataclasses so we can bypass the groups for keeping all data."""
18
+
19
+ device: LubaMsg
20
+
21
+ @classmethod
22
+ def from_raw(cls, raw: dict) -> "MowingDevice":
23
+ """Take in raw data to hold in the betterproto dataclass."""
24
+ return MowingDevice(device=LubaMsg(**raw))
25
+
26
+ @property
27
+ def net(self):
28
+ """Will return a wrapped betterproto of net."""
29
+ return DevNetData(net=self.device.net)
30
+
31
+ @property
32
+ def sys(self):
33
+ """Will return a wrapped betterproto of sys."""
34
+ return SysData(sys=self.device.sys)
35
+
36
+ @property
37
+ def nav(self):
38
+ """Will return a wrapped betterproto of nav."""
39
+ return NavData(nav=self.device.nav)
40
+
41
+ @property
42
+ def driver(self):
43
+ """Will return a wrapped betterproto of driver."""
44
+ return DriverData(driver=self.device.driver)
45
+
46
+ @property
47
+ def mul(self):
48
+ """Will return a wrapped betterproto of mul."""
49
+ return MulData(mul=self.device.mul)
50
+
51
+ @property
52
+ def ota(self):
53
+ """Will return a wrapped betterproto of ota."""
54
+ return OtaData(ota=self.device.ota)
55
+
56
+ @property
57
+ def pept(self):
58
+ """Will return a wrapped betterproto of pept."""
59
+ return PeptData(pept=self.device.pept)
60
+
61
+
62
+ @dataclass
63
+ class DevNetData:
64
+ """Wrapping class around LubaMsg to return a dataclass from the raw dict."""
65
+
66
+ net: DevNet
67
+
68
+ def __getattr__(self, item):
69
+ """Intercept call to get net in dict and return a betterproto dataclass."""
70
+ if not isinstance(self.net[item], dict):
71
+ return self.net[item]
72
+
73
+ return DevNet().__getattribute__(item).from_dict(value=self.net[item])
74
+
75
+
76
+ @dataclass
77
+ class SysData:
78
+ """Wrapping class around LubaMsg to return a dataclass from the raw dict."""
79
+
80
+ sys: MctlSys
81
+
82
+ def __getattr__(self, item):
83
+ """Intercept call to get net in dict and return a betterproto dataclass."""
84
+ if not isinstance(self.sys[item], dict):
85
+ return self.sys[item]
86
+
87
+ return MctlSys().__getattribute__(item).from_dict(value=self.sys[item])
88
+
89
+
90
+ @dataclass
91
+ class NavData:
92
+ """Wrapping class around LubaMsg to return a dataclass from the raw dict."""
93
+
94
+ nav: MctlNav
95
+
96
+ def __getattr__(self, item):
97
+ """Intercept call to get nav in dict and return a betterproto dataclass."""
98
+ if not isinstance(self.nav[item], dict):
99
+ return self.nav[item]
100
+
101
+ return MctlNav().__getattribute__(item).from_dict(value=self.nav[item])
102
+
103
+
104
+ @dataclass
105
+ class DriverData:
106
+ """Wrapping class around LubaMsg to return a dataclass from the raw dict."""
107
+
108
+ driver: MctlDriver
109
+
110
+ def __getattr__(self, item):
111
+ """Intercept call to get driver in dict and return a betterproto dataclass."""
112
+ if not isinstance(self.driver[item], dict):
113
+ return self.driver[item]
114
+
115
+ return MctlDriver().__getattribute__(item).from_dict(value=self.driver[item])
116
+
117
+
118
+ @dataclass
119
+ class MulData:
120
+ """Wrapping class around LubaMsg to return a dataclass from the raw dict."""
121
+
122
+ mul: SocMul
123
+
124
+ def __getattr__(self, item):
125
+ """Intercept call to get mul in dict and return a betterproto dataclass."""
126
+ if not isinstance(self.mul[item], dict):
127
+ return self.mul[item]
128
+
129
+ return SocMul().__getattribute__(item).from_dict(value=self.mul[item])
130
+
131
+
132
+ @dataclass
133
+ class OtaData:
134
+ """Wrapping class around LubaMsg to return a dataclass from the raw dict."""
135
+
136
+ ota: MctlOta
137
+
138
+ def __getattr__(self, item):
139
+ """Intercept call to get ota in dict and return a betterproto dataclass."""
140
+ if not isinstance(self.ota[item], dict):
141
+ return self.ota[item]
142
+
143
+ return MctlOta().__getattribute__(item).from_dict(value=self.ota[item])
144
+
145
+
146
+ @dataclass
147
+ class PeptData:
148
+ """Wrapping class around LubaMsg to return a dataclass from the raw dict."""
149
+
150
+ pept: MctlPept
151
+
152
+ def __getattr__(self, item):
153
+ """Intercept call to get pept in dict and return a betterproto dataclass."""
154
+ if not isinstance(self.pept[item], dict):
155
+ return self.pept[item]
156
+
157
+ return MctlPept().__getattribute__(item).from_dict(value=self.pept[item])
@@ -0,0 +1,67 @@
1
+ from enum import Enum
2
+
3
+
4
+ class PositionMode(Enum):
5
+ FIX = 0
6
+ SINGLE = 1
7
+ FLOAT = 2
8
+ NONE = 3
9
+ UNKNOWN = 4
10
+
11
+ @staticmethod
12
+ def from_value(value):
13
+ if value == 0:
14
+ return PositionMode.FIX
15
+ elif value == 1:
16
+ return PositionMode.SINGLE
17
+ elif value == 2:
18
+ return PositionMode.FLOAT
19
+ elif value == 3:
20
+ return PositionMode.NONE
21
+ else:
22
+ return PositionMode.UNKNOWN
23
+
24
+ def __str__(self):
25
+ if self == PositionMode.FIX:
26
+ return "Fix"
27
+ elif self == PositionMode.SINGLE:
28
+ return "Single"
29
+ elif self == PositionMode.FLOAT:
30
+ return "Float"
31
+ elif self == PositionMode.NONE:
32
+ return "None"
33
+ else:
34
+ return "-"
35
+
36
+
37
+ class RTKStatus(Enum):
38
+ NONE = 0
39
+ SINGLE = 1
40
+ FIX = 4
41
+ FLOAT = 5
42
+ UNKNOWN = 6
43
+
44
+ @staticmethod
45
+ def from_value(value):
46
+ if value == 0:
47
+ return RTKStatus.NONE
48
+ elif value == 1 or value == 2:
49
+ return RTKStatus.SINGLE
50
+ elif value == 4:
51
+ return RTKStatus.FIX
52
+ elif value == 5:
53
+ return RTKStatus.FLOAT
54
+ else:
55
+ return RTKStatus.UNKNOWN
56
+
57
+ def __str__(self):
58
+ if self == RTKStatus.NONE:
59
+ return "None"
60
+ elif self == RTKStatus.SINGLE:
61
+ return "Single"
62
+ elif self == RTKStatus.FIX:
63
+ return "Fix"
64
+ elif self == RTKStatus.FLOAT:
65
+ return "Float"
66
+ else:
67
+ return "Unknown"
@@ -0,0 +1,48 @@
1
+ class ExecuteBorderParams:
2
+ """generated source for class ExecuteBorderParamsBean"""
3
+
4
+ border = list()
5
+ currentFrame = 0
6
+ jobIndex = ""
7
+
8
+ def __init__(self, i, str_, list_):
9
+ """Generated source for method __init__"""
10
+ self.currentFrame = i
11
+ self.border = list_
12
+ self.jobIndex = str_
13
+
14
+ def get_current_frame(self):
15
+ """Generated source for method getCurrentFrame"""
16
+ return self.currentFrame
17
+
18
+ def set_current_frame(self, i):
19
+ """Generated source for method setCurrentFrame"""
20
+ self.currentFrame = i
21
+
22
+ def get_job_index(self):
23
+ """Generated source for method getJobIndex"""
24
+ return self.jobIndex
25
+
26
+ def set_job_index(self, str_):
27
+ """Generated source for method setJobIndex"""
28
+ self.jobIndex = str_
29
+
30
+ def get_border(self):
31
+ """Generated source for method getBorder"""
32
+ return self.border
33
+
34
+ def set_border(self, border_list):
35
+ """Generated source for method setBorder"""
36
+ self.border = border_list
37
+
38
+ def __str__(self):
39
+ """Generated source for method toString"""
40
+ return (
41
+ "ExecuteBorderParamsBean{currentFrame="
42
+ + self.currentFrame
43
+ + ", jobIndex='"
44
+ + self.jobIndex
45
+ + "', border="
46
+ + self.border
47
+ + "}"
48
+ )
@@ -0,0 +1,36 @@
1
+ from jsonic.serializable import Serializable
2
+
3
+ from .excute_boarder_params import ExecuteBorderParams
4
+
5
+
6
+ class ExecuteBorder(Serializable):
7
+ """generated source for class ExecuteBorderBean"""
8
+
9
+ cmd = 0
10
+ params = ExecuteBorderParams(None, None, None)
11
+
12
+ def __init__(self, i, execute_border_params: ExecuteBorderParams):
13
+ """Generated source for method __init__"""
14
+ super().__init__()
15
+ self.cmd = i
16
+ self.params = execute_border_params
17
+
18
+ def get_cmd(self):
19
+ """Generated source for method getCmd"""
20
+ return self.cmd
21
+
22
+ def set_cmd(self, i):
23
+ """Generated source for method setCmd"""
24
+ self.cmd = i
25
+
26
+ def get_params(self):
27
+ """Generated source for method getParams"""
28
+ return self.params
29
+
30
+ def set_params(self, execute_border_params):
31
+ """Generated source for method setParams"""
32
+ self.params = execute_border_params
33
+
34
+ def __str__(self):
35
+ """Generated source for method toString"""
36
+ return "ExecuteBean{cmd=" + self.cmd + ", params=" + self.params + "}"
@@ -0,0 +1,133 @@
1
+ import logging
2
+ from typing import List
3
+
4
+ logger = logging.getLogger(__name__)
5
+
6
+
7
+ class GenerateRouteInformation:
8
+ """Creates a model for generating route information and mowing plan before starting a job."""
9
+
10
+ def __init__(
11
+ self,
12
+ one_hashs: List[int],
13
+ job_mode: int,
14
+ channel_width: int,
15
+ speed: float,
16
+ ultra_wave: int,
17
+ channel_mode: int,
18
+ rain_tactics: int,
19
+ toward: int,
20
+ knife_height: int,
21
+ path_order: str,
22
+ toward_included_angle: int,
23
+ ):
24
+ self.path_order = ""
25
+ self.toward_mode = 0
26
+ self.one_hashs = one_hashs
27
+ self.rain_tactics = rain_tactics
28
+ self.job_mode = job_mode
29
+ self.knife_height = knife_height
30
+ self.speed = speed
31
+ self.ultra_wave = ultra_wave
32
+ self.channel_width = channel_width
33
+ self.channel_mode = channel_mode
34
+ self.toward = toward
35
+ self.edge_mode = rain_tactics
36
+ self.path_order = path_order
37
+ self.toward_included_angle = toward_included_angle
38
+ logger.debug(
39
+ f"Mode route command parameters jobMode={job_mode}//channelWidth={channel_width}//speed={speed}//UltraWave={ultra_wave}//channelMode={channel_mode}//edgeMode={rain_tactics}//knifeHeight={knife_height} pathOrder:{path_order.encode('utf-8')}"
40
+ )
41
+
42
+ def get_job_id(self) -> int:
43
+ return self.job_id
44
+
45
+ def set_job_id(self, job_id: int) -> None:
46
+ self.job_id = job_id
47
+
48
+ def get_job_ver(self) -> int:
49
+ return self.job_ver
50
+
51
+ def set_job_ver(self, job_ver: int) -> None:
52
+ self.job_ver = job_ver
53
+
54
+ def get_rain_tactics(self) -> int:
55
+ return self.rain_tactics
56
+
57
+ def set_rain_tactics(self, rain_tactics: int) -> None:
58
+ self.rain_tactics = rain_tactics
59
+
60
+ def get_job_mode(self) -> int:
61
+ return self.job_mode
62
+
63
+ def set_job_mode(self, job_mode: int) -> None:
64
+ self.job_mode = job_mode
65
+
66
+ def get_knife_height(self) -> int:
67
+ return self.knife_height
68
+
69
+ def set_knife_height(self, knife_height: int) -> None:
70
+ self.knife_height = knife_height
71
+
72
+ def get_speed(self) -> float:
73
+ return self.speed
74
+
75
+ def set_speed(self, speed: float) -> None:
76
+ self.speed = speed
77
+
78
+ def get_ultra_wave(self) -> int:
79
+ return self.ultra_wave
80
+
81
+ def set_ultra_wave(self, ultra_wave: int) -> None:
82
+ self.ultra_wave = ultra_wave
83
+
84
+ def get_channel_width(self) -> int:
85
+ return self.channel_width
86
+
87
+ def set_channel_width(self, channel_width: int) -> None:
88
+ self.channel_width = channel_width
89
+
90
+ def get_channel_mode(self) -> int:
91
+ return self.channel_mode
92
+
93
+ def set_channel_mode(self, channel_mode: int) -> None:
94
+ self.channel_mode = channel_mode
95
+
96
+ def get_toward(self) -> int:
97
+ return self.toward
98
+
99
+ def set_toward(self, toward: int) -> None:
100
+ self.toward = toward
101
+
102
+ def get_one_hashs(self) -> List[int]:
103
+ return self.one_hashs if self.one_hashs else []
104
+
105
+ def set_one_hashs(self, one_hashs: List[int]) -> None:
106
+ self.one_hashs = one_hashs
107
+
108
+ def get_path_order(self) -> str:
109
+ return self.path_order
110
+
111
+ def set_path_order(self, path_order: str) -> None:
112
+ self.path_order = path_order
113
+
114
+ def get_toward_included_angle(self) -> int:
115
+ return self.toward_included_angle
116
+
117
+ def set_toward_included_angle(self, toward_included_angle: int) -> None:
118
+ self.toward_included_angle = toward_included_angle
119
+
120
+ def get_toward_mode(self) -> int:
121
+ return self.toward_mode
122
+
123
+ def get_edge_mode(self) -> int:
124
+ return self.edge_mode
125
+
126
+ def set_edge_mode(self, edge_mode: int) -> None:
127
+ self.edge_mode = edge_mode
128
+
129
+ def __str__(self) -> str:
130
+ try:
131
+ return f"GenerateRouteInformation{{oneHashs={self.one_hashs}, jobId={self.job_id}, jobVer={self.job_ver}, rainTactics={self.rain_tactics}, jobMode={self.job_mode}, knifeHeight={self.knife_height}, speed={self.speed}, UltraWave={self.ultra_wave}, channelWidth={self.channel_width}, channelMode={self.channel_mode}, toward={self.toward}, pathOrder='{self.path_order.encode('utf-8')}', edgeMode={self.edge_mode}, towardIncludedAngle={self.toward_included_angle}}}"
132
+ except Exception as e:
133
+ return str(e)
@@ -0,0 +1,17 @@
1
+ import typing
2
+
3
+
4
+ class HashList:
5
+ def __init__(self):
6
+ self.pver: int = 0
7
+ self.subCmd: int = 0
8
+ self.totalFrame: int = 0
9
+ self.currentFrame: int = 0
10
+ self.dataHash: int = 0
11
+ self.path: typing.List[int] = []
12
+
13
+ def __str__(self) -> str:
14
+ return (
15
+ f"HashBean{{pver={self.pver}, subCmd={self.subCmd}, totalFrame={self.totalFrame}, "
16
+ + f"currentFrame={self.currentFrame}, dataHash={self.dataHash}, path={self.path}}}"
17
+ )
@@ -0,0 +1,37 @@
1
+ from enum import IntEnum
2
+
3
+
4
+ class CuttingMode(IntEnum):
5
+ """job_mode"""
6
+
7
+ single_grid = 0
8
+ double_grid = 1
9
+ segment_grid = 2
10
+ no_grid = 3
11
+
12
+
13
+ class BorderPatrolMode(IntEnum):
14
+ """"""
15
+
16
+ none = 0
17
+ one = 1
18
+ two = 2
19
+ three = 3
20
+ four = 4
21
+
22
+
23
+ class ObstacleLapsMode(IntEnum):
24
+ """mowingLaps"""
25
+
26
+ none = 0
27
+ one = 1
28
+ two = 2
29
+ three = 3
30
+ four = 4
31
+
32
+
33
+ class MowOrder(IntEnum):
34
+ """path_order"""
35
+
36
+ border_first = 0
37
+ grid_first = 1
@@ -0,0 +1,58 @@
1
+ from typing import List
2
+
3
+
4
+ class Plan:
5
+ def __init__(self):
6
+ self.pver: int = 0
7
+ self.sub_cmd: int = 0
8
+ self.area: int = 0
9
+ self.work_time: int = 0
10
+ self.version: str = ""
11
+ self.id: str = ""
12
+ self.user_id: str = ""
13
+ self.device_id: str = ""
14
+ self.plan_id: str = ""
15
+ self.task_id: str = ""
16
+ self.job_id: str = ""
17
+ self.start_time: str = ""
18
+ self.end_time: str = ""
19
+ self.week: int = 0
20
+ self.knife_height: int = 0
21
+ self.model: int = 0
22
+ self.edge_mode: int = 0
23
+ self.required_time: int = 0
24
+ self.route_angle: int = 0
25
+ self.route_model: int = 0
26
+ self.route_spacing: int = 0
27
+ self.ultrasonic_barrier: int = 0
28
+ self.total_plan_num: int = 0
29
+ self.plan_index: int = 0
30
+ self.result: int = 0
31
+ self.speed: float = 0.0
32
+ self.task_name: str = ""
33
+ self.job_name: str = ""
34
+ self.zone_hashs: List[int] = []
35
+ self.reserved: str = ""
36
+ self.weeks: List[int] = []
37
+ self.start_date: str = ""
38
+ self.end_date: str = ""
39
+ self.job_type: int = 0
40
+ self.interval_days: int = 0
41
+ self.count_down: int = 0
42
+ self.is_enable: bool = True
43
+ self.is_mow_work: bool = True
44
+ self.is_sweeping_work: bool = True
45
+ self.mowing_laps: int = 0
46
+ self.path_order: int = 0
47
+ self.demond_angle: int = 90
48
+
49
+ def __str__(self):
50
+ return f"Plan(pver={self.pver}, sub_cmd={self.sub_cmd}, area={self.area}, work_time={self.work_time}, version='{self.version}', id='{self.id}', user_id='{self.user_id}', device_id='{self.device_id}', plan_id='{self.plan_id}', task_id='{self.task_id}', job_id='{self.job_id}', start_time='{self.start_time}', end_time='{self.end_time}', week={self.week}, knife_height={self.knife_height}, model={self.model}, edge_mode={self.edge_mode}, required_time={self.required_time}, route_angle={self.route_angle}, route_model={self.route_model}, route_spacing={self.route_spacing}, ultrasonic_barrier={self.ultrasonic_barrier}, total_plan_num={self.total_plan_num}, plan_index={self.plan_index}, result={self.result}, speed={self.speed}, task_name='{self.task_name}', job_name='{self.job_name}', zone_hashs={self.zone_hashs}, reserved='{self.reserved}', weeks={self.weeks}, start_date='{self.start_date}', end_date='{self.end_date}', job_type={self.job_type}, interval_days={self.interval_days}, count_down={self.count_down}, is_enable={self.is_enable}, mowing_laps={self.mowing_laps}, path_order={self.path_order}, demond_angle={self.demond_angle}, is_mow_work={self.is_mow_work}, is_sweeping_work={self.is_sweeping_work})"
51
+
52
+ def __eq__(self, other):
53
+ if isinstance(other, Plan):
54
+ return self.plan_id == other.plan_id
55
+ return False
56
+
57
+ def __hash__(self):
58
+ return hash(self.plan_id)
@@ -0,0 +1,45 @@
1
+ from dataclasses import dataclass
2
+ from enum import Enum
3
+
4
+
5
+ class RTKStatus(Enum):
6
+ NONE = 0
7
+ BAD = 1
8
+ FINE = 4
9
+
10
+
11
+ @dataclass
12
+ class RapidState:
13
+ pos_x: float
14
+ pos_y: float
15
+ rtk_status: RTKStatus
16
+ toward: float
17
+ satellites_total: int
18
+ satellites_l2: int
19
+ rtk_age: float
20
+ lat_std: float
21
+ lon_std: float
22
+ pos_type: int
23
+ zone_hash: int
24
+ pos_level: int
25
+
26
+ @classmethod
27
+ def from_raw(cls, raw: list[int]) -> "RapidState":
28
+ return RapidState(
29
+ rtk_status=RTKStatus.FINE
30
+ if raw[0] == 4
31
+ else RTKStatus.BAD
32
+ if raw[0] in (1, 5)
33
+ else RTKStatus.NONE,
34
+ pos_level=raw[1],
35
+ satellites_total=raw[2],
36
+ rtk_age=raw[3] / 10000,
37
+ lat_std=raw[4] / 10000,
38
+ lon_std=raw[5] / 10000,
39
+ satellites_l2=raw[6],
40
+ pos_x=raw[7] / 10000,
41
+ pos_y=raw[8] / 10000,
42
+ toward=raw[9] / 10000,
43
+ pos_type=raw[10],
44
+ zone_hash=raw[11],
45
+ )