pymammotion 0.5.69__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/__init__.py +53 -0
- pymammotion/agora/__init__.py +0 -0
- pymammotion/agora/agora_api.py +755 -0
- pymammotion/agora/agora_rtc_capabilities.py +748 -0
- pymammotion/agora/agora_websockets.py +1175 -0
- pymammotion/aliyun/__init__.py +1 -0
- pymammotion/aliyun/client.py +235 -0
- pymammotion/aliyun/cloud_gateway.py +982 -0
- pymammotion/aliyun/model/aep_response.py +21 -0
- pymammotion/aliyun/model/connect_response.py +51 -0
- pymammotion/aliyun/model/dev_by_account_response.py +195 -0
- pymammotion/aliyun/model/login_by_oauth_response.py +64 -0
- pymammotion/aliyun/model/regions_response.py +29 -0
- pymammotion/aliyun/model/session_by_authcode_response.py +19 -0
- pymammotion/aliyun/model/thing_response.py +12 -0
- pymammotion/aliyun/regions.py +62 -0
- pymammotion/aliyun/tea/core.py +297 -0
- pymammotion/aliyun/tmp_constant.py +171 -0
- pymammotion/bluetooth/__init__.py +1 -0
- pymammotion/bluetooth/ble.py +62 -0
- pymammotion/bluetooth/ble_message.py +676 -0
- pymammotion/bluetooth/const.py +27 -0
- pymammotion/bluetooth/data/__init__.py +0 -0
- pymammotion/bluetooth/data/convert.py +25 -0
- pymammotion/bluetooth/data/framectrldata.py +40 -0
- pymammotion/bluetooth/data/notifydata.py +62 -0
- pymammotion/bluetooth/model/__init__.py +0 -0
- pymammotion/bluetooth/model/atomic_integer.py +54 -0
- pymammotion/const.py +13 -0
- pymammotion/data/__init__.py +0 -0
- pymammotion/data/model/__init__.py +8 -0
- pymammotion/data/model/account.py +8 -0
- pymammotion/data/model/device.py +192 -0
- pymammotion/data/model/device_config.py +72 -0
- pymammotion/data/model/device_info.py +60 -0
- pymammotion/data/model/device_limits.py +49 -0
- pymammotion/data/model/enums.py +77 -0
- pymammotion/data/model/errors.py +12 -0
- pymammotion/data/model/events.py +14 -0
- pymammotion/data/model/generate_geojson.py +565 -0
- pymammotion/data/model/generate_route_information.py +26 -0
- pymammotion/data/model/hash_list.py +475 -0
- pymammotion/data/model/location.py +36 -0
- pymammotion/data/model/mowing_modes.py +77 -0
- pymammotion/data/model/rapid_state.py +45 -0
- pymammotion/data/model/raw_data.py +215 -0
- pymammotion/data/model/region_data.py +102 -0
- pymammotion/data/model/report_info.py +182 -0
- pymammotion/data/model/work.py +27 -0
- pymammotion/data/mower_state_manager.py +369 -0
- pymammotion/data/mqtt/__init__.py +1 -0
- pymammotion/data/mqtt/event.py +227 -0
- pymammotion/data/mqtt/mammotion_properties.py +276 -0
- pymammotion/data/mqtt/properties.py +203 -0
- pymammotion/data/mqtt/status.py +57 -0
- pymammotion/event/__init__.py +6 -0
- pymammotion/event/event.py +96 -0
- pymammotion/homeassistant/__init__.py +3 -0
- pymammotion/homeassistant/mower_api.py +514 -0
- pymammotion/homeassistant/rtk_api.py +54 -0
- pymammotion/http/__init__.py +0 -0
- pymammotion/http/encryption.py +220 -0
- pymammotion/http/http.py +673 -0
- pymammotion/http/model/__init__.py +0 -0
- pymammotion/http/model/camera_stream.py +31 -0
- pymammotion/http/model/http.py +249 -0
- pymammotion/http/model/response_factory.py +61 -0
- pymammotion/http/model/rtk.py +16 -0
- pymammotion/mammotion/__init__.py +0 -0
- pymammotion/mammotion/commands/__init__.py +0 -0
- pymammotion/mammotion/commands/abstract_message.py +24 -0
- pymammotion/mammotion/commands/mammotion_command.py +81 -0
- pymammotion/mammotion/commands/messages/__init__.py +0 -0
- pymammotion/mammotion/commands/messages/basestation.py +43 -0
- pymammotion/mammotion/commands/messages/driver.py +122 -0
- pymammotion/mammotion/commands/messages/media.py +87 -0
- pymammotion/mammotion/commands/messages/navigation.py +564 -0
- pymammotion/mammotion/commands/messages/network.py +205 -0
- pymammotion/mammotion/commands/messages/ota.py +38 -0
- pymammotion/mammotion/commands/messages/system.py +330 -0
- pymammotion/mammotion/commands/messages/video.py +33 -0
- pymammotion/mammotion/control/__init__.py +0 -0
- pymammotion/mammotion/control/joystick.py +145 -0
- pymammotion/mammotion/devices/__init__.py +29 -0
- pymammotion/mammotion/devices/base.py +163 -0
- pymammotion/mammotion/devices/mammotion.py +571 -0
- pymammotion/mammotion/devices/mammotion_bluetooth.py +496 -0
- pymammotion/mammotion/devices/mammotion_cloud.py +355 -0
- pymammotion/mammotion/devices/mammotion_mower_ble.py +48 -0
- pymammotion/mammotion/devices/mammotion_mower_cloud.py +39 -0
- pymammotion/mammotion/devices/managers/managers.py +81 -0
- pymammotion/mammotion/devices/mower_device.py +120 -0
- pymammotion/mammotion/devices/mower_manager.py +107 -0
- pymammotion/mammotion/devices/rtk_ble.py +89 -0
- pymammotion/mammotion/devices/rtk_cloud.py +115 -0
- pymammotion/mammotion/devices/rtk_device.py +50 -0
- pymammotion/mammotion/devices/rtk_manager.py +125 -0
- pymammotion/mqtt/__init__.py +6 -0
- pymammotion/mqtt/aliyun_mqtt.py +237 -0
- pymammotion/mqtt/linkkit/__init__.py +5 -0
- pymammotion/mqtt/linkkit/h2client.py +585 -0
- pymammotion/mqtt/linkkit/linkkit.py +3025 -0
- pymammotion/mqtt/mammotion_future.py +26 -0
- pymammotion/mqtt/mammotion_mqtt.py +214 -0
- pymammotion/mqtt/mqtt_models.py +66 -0
- pymammotion/proto/__init__.py +4841 -0
- pymammotion/proto/basestation.proto +51 -0
- pymammotion/proto/basestation_pb2.py +35 -0
- pymammotion/proto/basestation_pb2.pyi +89 -0
- pymammotion/proto/common.proto +7 -0
- pymammotion/proto/common_pb2.py +25 -0
- pymammotion/proto/common_pb2.pyi +13 -0
- pymammotion/proto/dev_net.proto +321 -0
- pymammotion/proto/dev_net_pb2.py +111 -0
- pymammotion/proto/dev_net_pb2.pyi +515 -0
- pymammotion/proto/luba_msg.proto +76 -0
- pymammotion/proto/luba_msg_pb2.py +41 -0
- pymammotion/proto/luba_msg_pb2.pyi +97 -0
- pymammotion/proto/luba_mul.proto +129 -0
- pymammotion/proto/luba_mul_pb2.py +61 -0
- pymammotion/proto/luba_mul_pb2.pyi +178 -0
- pymammotion/proto/mctrl_driver.proto +107 -0
- pymammotion/proto/mctrl_driver_pb2.py +57 -0
- pymammotion/proto/mctrl_driver_pb2.pyi +167 -0
- pymammotion/proto/mctrl_nav.proto +591 -0
- pymammotion/proto/mctrl_nav_pb2.py +136 -0
- pymammotion/proto/mctrl_nav_pb2.pyi +1067 -0
- pymammotion/proto/mctrl_ota.proto +80 -0
- pymammotion/proto/mctrl_ota_pb2.py +45 -0
- pymammotion/proto/mctrl_ota_pb2.pyi +128 -0
- pymammotion/proto/mctrl_pept.proto +34 -0
- pymammotion/proto/mctrl_pept_pb2.py +33 -0
- pymammotion/proto/mctrl_pept_pb2.pyi +58 -0
- pymammotion/proto/mctrl_sys.proto +741 -0
- pymammotion/proto/mctrl_sys_pb2.py +206 -0
- pymammotion/proto/mctrl_sys_pb2.pyi +1213 -0
- pymammotion/proto/message_pool.py +3 -0
- pymammotion/proto/py.typed +0 -0
- pymammotion/py.typed +0 -0
- pymammotion/utility/constant/__init__.py +3 -0
- pymammotion/utility/constant/device_constant.py +315 -0
- pymammotion/utility/conversions.py +5 -0
- pymammotion/utility/datatype_converter.py +124 -0
- pymammotion/utility/device_config.py +755 -0
- pymammotion/utility/device_type.py +489 -0
- pymammotion/utility/map.py +259 -0
- pymammotion/utility/movement.py +18 -0
- pymammotion/utility/mur_mur_hash.py +159 -0
- pymammotion/utility/periodic.py +106 -0
- pymammotion/utility/rocker_util.py +194 -0
- pymammotion-0.5.69.dist-info/METADATA +93 -0
- pymammotion-0.5.69.dist-info/RECORD +154 -0
- pymammotion-0.5.69.dist-info/WHEEL +4 -0
- pymammotion-0.5.69.dist-info/licenses/LICENSE +674 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import logging
|
|
3
|
+
import secrets
|
|
4
|
+
import string
|
|
5
|
+
|
|
6
|
+
from cryptography.hazmat.backends import default_backend
|
|
7
|
+
from cryptography.hazmat.primitives import padding, serialization
|
|
8
|
+
from cryptography.hazmat.primitives.asymmetric import padding as rsa_padding
|
|
9
|
+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
10
|
+
|
|
11
|
+
_LOGGER = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class EncryptionUtils:
|
|
15
|
+
PRIVATE_KEY = """MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOFizbd1fC5XNKJ89u0XNvPZNR/L
|
|
16
|
+
0h547iSWjOCuvvMu76ZSaS3/Tu2C1C+XmlnmBWTyY4ON+xECiNUXm/aWQ3P0g+wf60zjPbNzgL2Q
|
|
17
|
+
7njXJG6wka4KkbdQxUdS0TTpL256LnV1LsG855bsbJIJiQPbfUq6HbB5xH7sXdrmFu1DAgMBAAEC
|
|
18
|
+
gYEAoT2TGE1ncquWjyxBZup1uMvKkp25C23OSMSfslmxZ75LWjyY3HxK1eYDsKyPkwLZFxfFE6du
|
|
19
|
+
VwPuKiyCuk1ToPfnb4niTGzXPyC2PbO4SFrWL8n1YZ80M0bfTGI9dMCZvpmZJ41WYUsBaf2374lt
|
|
20
|
+
oEiDEHJp7MeXk/970xiKP1ECQQD65rLHk840q+FZS6kZVexJucPZj/YAII6klU1E20ctioe8Pi5m
|
|
21
|
+
WSPqclH27/t4FqdvP7tFqaavyXg+CEQpxmxLAkEA5fddDuzcjWgF9pl9fP7/baFMYjUS9z1Vc3gx
|
|
22
|
+
CnvAgCnv71wjDQhvsUc6sAiidsBGFDyud06RyyLcOlQchMb36QJBAIui/Xjpn+fciQxjeXcqRNk7
|
|
23
|
+
U+6vml+zvu+GUHyz9Uc5RBXWHYjEr6J5gXiHU1MgeIsH0zgQFT7cR9luTFFbp0UCQFIntfogCocG
|
|
24
|
+
E6NOoHMoUi5jQnuPRHBJXB69YJ/DKDlhQhN8EhWU3voxXTkITKop9J9EMnvy+MjecljwNaQFxQkC
|
|
25
|
+
QB9lz67iDe9Gj8NxSElVZxUm9EfbL1RPqTZPx/lADR06CPB8pP3Bl5/5/5RGzc+UTZ+wX5GWKvC7
|
|
26
|
+
zUJaROxQB+E=""".replace(" ", "")
|
|
27
|
+
|
|
28
|
+
PUBLIC_KEY_PROD = """MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApLbeSgOvnwLTWbhaBQWNnnHMtSDAi
|
|
29
|
+
Gz0PEDbrtd1tLYoO0hukW5PSa6eHykch0Hc6etiqEx1xziS+vNf+iOXds70I4htaYit6yRToZlQ
|
|
30
|
+
Mim3DQxaZX68nIHIZogur0zGv9U8j01v5l/rHRxyDdlVx3+JkBg6Cqx4U1PXEnAJriqcyg0B8Gm
|
|
31
|
+
V8Lnmfng+aJLRyq5MkhstYCRv9AsmWu8NpZDJ1ffbkaS02Z9/wpubXTiFP6DG3V2mDw2VvzEcHi
|
|
32
|
+
cchw49oXmTi92yui+kBgSYlNygssOAyU6H071AfmRUeH3+TsV5u5rg+bCiKyHemVmcKdd3hhZB+
|
|
33
|
+
HjA8o3On6rg5wIDAQAB""".replace(" ", "")
|
|
34
|
+
|
|
35
|
+
PUBLIC_KEY_TEST = """MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC1nAzH31arNBmYKvTlvKgkxI1MIr4HpfLbmM
|
|
36
|
+
XPIhd8D/cXB0dYY1ppUq4a/ezq41YShN88e0elyZgqdnFrkhiLpnKWa7jXtVRgXi9eS18PLO8ns
|
|
37
|
+
eHude9URaj7relK1AZ0xovKsbLKHd01PpmngLXZfnKA06J2ru/zH+cnpXdy8QIDAQAB""".replace(" ", "")
|
|
38
|
+
|
|
39
|
+
def __init__(self) -> None:
|
|
40
|
+
self.AES_PASW = self.get_aes_key() # Get from previous implementation
|
|
41
|
+
self.IV = self.get_iv() # Get from previous implementation
|
|
42
|
+
self._public_key = self.load_public_key()
|
|
43
|
+
self._private_key = self.load_private_key()
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def load_private_key():
|
|
47
|
+
"""Load the private key from base64 encoded string"""
|
|
48
|
+
try:
|
|
49
|
+
private_key_bytes = base64.b64decode(EncryptionUtils.PRIVATE_KEY)
|
|
50
|
+
return serialization.load_der_private_key(private_key_bytes, password=None, backend=default_backend())
|
|
51
|
+
except Exception as e:
|
|
52
|
+
raise Exception(f"Failed to load private key: {e!s}")
|
|
53
|
+
|
|
54
|
+
@staticmethod
|
|
55
|
+
def load_public_key(is_production: bool = True):
|
|
56
|
+
"""Load the public key from base64 encoded string
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
is_production (bool): If True, uses production key, else uses test key
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
try:
|
|
63
|
+
key_string = EncryptionUtils.PUBLIC_KEY_PROD if is_production else EncryptionUtils.PUBLIC_KEY_TEST
|
|
64
|
+
public_key_bytes = base64.b64decode(key_string)
|
|
65
|
+
return serialization.load_der_public_key(public_key_bytes, backend=default_backend())
|
|
66
|
+
except Exception as e:
|
|
67
|
+
raise Exception(f"Failed to load public key: {e!s}")
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def encrypt(plaintext: str, key: str, iv: str) -> str:
|
|
71
|
+
"""Encrypt text using AES/CBC/PKCS5Padding
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
plaintext (str): Text to encrypt
|
|
75
|
+
key (str): Encryption key
|
|
76
|
+
iv (str): Initialization vector
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
str: Base64 encoded encrypted string
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
Exception: If encryption fails
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
try:
|
|
86
|
+
# Convert strings to bytes
|
|
87
|
+
plaintext_bytes = plaintext.encode("utf-8")
|
|
88
|
+
key_bytes = key.encode("utf-8")
|
|
89
|
+
iv_bytes = iv.encode("utf-8")
|
|
90
|
+
|
|
91
|
+
# Create padder
|
|
92
|
+
padder = padding.PKCS7(128).padder()
|
|
93
|
+
padded_data = padder.update(plaintext_bytes) + padder.finalize()
|
|
94
|
+
|
|
95
|
+
# Create cipher
|
|
96
|
+
cipher = Cipher(algorithms.AES(key_bytes), modes.CBC(iv_bytes), backend=default_backend())
|
|
97
|
+
|
|
98
|
+
# Encrypt
|
|
99
|
+
encryptor = cipher.encryptor()
|
|
100
|
+
encrypted_bytes = encryptor.update(padded_data) + encryptor.finalize()
|
|
101
|
+
|
|
102
|
+
# Encode to base64
|
|
103
|
+
return base64.b64encode(encrypted_bytes).decode("utf-8")
|
|
104
|
+
|
|
105
|
+
except Exception as e:
|
|
106
|
+
raise Exception(f"Encryption failed: {e!s}")
|
|
107
|
+
|
|
108
|
+
def encryption_by_aes(self, text: str) -> str:
|
|
109
|
+
"""Encrypt text using AES with class-level key and IV
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
text (str): Text to encrypt
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
str: Encrypted text or None if encryption fails
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
try:
|
|
119
|
+
# Perform encryption
|
|
120
|
+
encrypted = self.encrypt(text, self.AES_PASW, self.IV)
|
|
121
|
+
|
|
122
|
+
return encrypted
|
|
123
|
+
|
|
124
|
+
except Exception as e:
|
|
125
|
+
_LOGGER.error(f"Encryption failed: {e!s}")
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
def encrypt_by_public_key(self) -> str | None:
|
|
129
|
+
"""Encrypt data using RSA public key.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Optional[str]: Base64 encoded encrypted data or None if encryption fails
|
|
135
|
+
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
data = f"{self.AES_PASW},{self.IV}"
|
|
139
|
+
|
|
140
|
+
if not self._public_key:
|
|
141
|
+
_LOGGER.error("Public key not initialized")
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
# Convert input string to bytes
|
|
146
|
+
data_bytes = data.encode("utf-8")
|
|
147
|
+
|
|
148
|
+
# Encrypt the data padding.PKCS7(128).padder()
|
|
149
|
+
encrypted_bytes = self._public_key.encrypt(data_bytes, rsa_padding.PKCS1v15())
|
|
150
|
+
|
|
151
|
+
# Convert to base64 string
|
|
152
|
+
encrypted_str = base64.b64encode(encrypted_bytes).decode("utf-8")
|
|
153
|
+
_LOGGER.debug("Data encrypted successfully")
|
|
154
|
+
|
|
155
|
+
return encrypted_str
|
|
156
|
+
|
|
157
|
+
except Exception as err:
|
|
158
|
+
_LOGGER.error("Encryption failed: %s", str(err))
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
@staticmethod
|
|
162
|
+
def get_random_string(length: int) -> str:
|
|
163
|
+
"""Generate a random string of specified length using alphanumeric characters.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
length (int): The desired length of the random string
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
str: A random alphanumeric string of specified length
|
|
170
|
+
|
|
171
|
+
Raises:
|
|
172
|
+
ValueError: If length is less than 1
|
|
173
|
+
|
|
174
|
+
"""
|
|
175
|
+
if length < 1:
|
|
176
|
+
raise ValueError("Length must be positive")
|
|
177
|
+
|
|
178
|
+
charset = string.ascii_letters + string.digits
|
|
179
|
+
return "".join(secrets.choice(charset) for _ in range(length))
|
|
180
|
+
|
|
181
|
+
@staticmethod
|
|
182
|
+
def get_random_int(length: int) -> str:
|
|
183
|
+
"""Generate a random string of specified length containing only digits.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
length (int): The desired length of the random number string
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
str: A string of random digits of specified length
|
|
190
|
+
|
|
191
|
+
Raises:
|
|
192
|
+
ValueError: If length is less than 1
|
|
193
|
+
|
|
194
|
+
"""
|
|
195
|
+
if length < 1:
|
|
196
|
+
raise ValueError("Length must be positive")
|
|
197
|
+
|
|
198
|
+
return "".join(secrets.choice(string.digits) for _ in range(length))
|
|
199
|
+
|
|
200
|
+
@staticmethod
|
|
201
|
+
def get_aes_key() -> str:
|
|
202
|
+
"""Generate a random AES key of 16 characters using alphanumeric characters.
|
|
203
|
+
Matches Java implementation behavior.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
str: A 16-character random string for AES key
|
|
207
|
+
|
|
208
|
+
"""
|
|
209
|
+
return EncryptionUtils.get_random_string(16)
|
|
210
|
+
|
|
211
|
+
@staticmethod
|
|
212
|
+
def get_iv() -> str:
|
|
213
|
+
"""Generate a random initialization vector of 16 digits.
|
|
214
|
+
Matches Java implementation behavior.
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
str: A 16-digit random string for initialization vector
|
|
218
|
+
|
|
219
|
+
"""
|
|
220
|
+
return EncryptionUtils.get_random_int(16)
|