pymammotion 0.4.17__tar.gz → 0.4.18__tar.gz
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-0.4.17 → pymammotion-0.4.18}/PKG-INFO +1 -1
- pymammotion-0.4.18/pymammotion/aliyun/client.py +230 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/cloud_gateway.py +26 -20
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/http/http.py +9 -2
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/devices/base.py +1 -1
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/devices/mammotion.py +21 -11
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/devices/mammotion_bluetooth.py +0 -1
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/devices/mammotion_cloud.py +4 -4
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pyproject.toml +1 -1
- {pymammotion-0.4.17 → pymammotion-0.4.18}/LICENSE +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/README.md +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/aep_response.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/connect_response.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/dev_by_account_response.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/login_by_oauth_response.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/regions_response.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/session_by_authcode_response.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/stream_subscription_response.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/tmp_constant.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/ble.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/ble_message.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/const.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/data/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/data/convert.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/data/framectrldata.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/data/notifydata.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/model/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/bluetooth/model/atomic_integer.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/const.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/account.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/device.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/device_config.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/device_info.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/device_limits.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/enums.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/excute_boarder_params.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/execute_boarder.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/generate_route_information.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/hash_list.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/location.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/mowing_modes.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/plan.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/rapid_state.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/raw_data.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/region_data.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/report_info.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/mqtt/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/mqtt/event.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/mqtt/properties.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/mqtt/status.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/state_manager.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/event/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/event/event.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/http/_init_.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/http/encryption.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/http/model/http.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/abstract_message.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/mammotion_command.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/driver.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/media.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/navigation.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/network.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/ota.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/system.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/video.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/control/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/control/joystick.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/devices/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mqtt/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mqtt/linkkit/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mqtt/linkkit/h2client.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mqtt/linkkit/linkkit.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mqtt/mammotion_future.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mqtt/mammotion_mqtt.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/basestation.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/basestation_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/basestation_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/common.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/common_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/common_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/dev_net.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/dev_net_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/dev_net_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/luba_msg.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/luba_msg_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/luba_msg_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/luba_mul.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/luba_mul_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/luba_mul_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_driver.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_driver_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_driver_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_nav.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_nav_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_nav_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_ota.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_ota_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_ota_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_pept.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_pept_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_pept_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_sys.proto +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_sys_pb2.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/proto/mctrl_sys_pb2.pyi +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/py.typed +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/constant/__init__.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/constant/device_constant.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/conversions.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/datatype_converter.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/device_config.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/device_type.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/map.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/movement.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/periodic.py +0 -0
- {pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/utility/rocker_util.py +0 -0
@@ -0,0 +1,230 @@
|
|
1
|
+
import time
|
2
|
+
|
3
|
+
from Tea.core import TeaCore
|
4
|
+
from Tea.exceptions import UnretryableException
|
5
|
+
from Tea.request import TeaRequest
|
6
|
+
|
7
|
+
try:
|
8
|
+
from typing import Dict
|
9
|
+
except ImportError:
|
10
|
+
pass
|
11
|
+
|
12
|
+
from alibabacloud_apigateway_util.client import Client as APIGatewayUtilClient
|
13
|
+
from alibabacloud_tea_util.client import Client as UtilClient
|
14
|
+
|
15
|
+
|
16
|
+
class Client:
|
17
|
+
"""test"""
|
18
|
+
|
19
|
+
_app_key = None # type: str
|
20
|
+
_app_secret = None # type: str
|
21
|
+
_protocol = None # type: str
|
22
|
+
_user_agent = None # type: str
|
23
|
+
_read_timeout = None # type: int
|
24
|
+
_connect_timeout = None # type: int
|
25
|
+
_http_proxy = None # type: str
|
26
|
+
_https_proxy = None # type: str
|
27
|
+
_no_proxy = None # type: str
|
28
|
+
_max_idle_conns = None # type: int
|
29
|
+
_domain = None # type: str
|
30
|
+
|
31
|
+
def __init__(self, config) -> None:
|
32
|
+
self._domain = config.domain
|
33
|
+
self._app_key = config.app_key
|
34
|
+
self._app_secret = config.app_secret
|
35
|
+
self._protocol = config.protocol
|
36
|
+
self._read_timeout = config.read_timeout
|
37
|
+
self._connect_timeout = config.connect_timeout
|
38
|
+
self._http_proxy = config.http_proxy
|
39
|
+
self._https_proxy = config.https_proxy
|
40
|
+
self._no_proxy = config.no_proxy
|
41
|
+
self._max_idle_conns = config.max_idle_conns
|
42
|
+
|
43
|
+
def do_request(self, pathname, protocol, method, header, body, runtime):
|
44
|
+
"""Send request
|
45
|
+
|
46
|
+
@type pathname: str
|
47
|
+
@param pathname: the url path
|
48
|
+
|
49
|
+
@type protocol: str
|
50
|
+
@param protocol: http or https
|
51
|
+
|
52
|
+
@type method: str
|
53
|
+
@param method: example GET
|
54
|
+
|
55
|
+
@type header: Dict[str, str]
|
56
|
+
@param header: request header
|
57
|
+
|
58
|
+
@type body: iot_api_gateway_models.IoTApiRequest
|
59
|
+
@param body: the object of IoTApiRequest
|
60
|
+
|
61
|
+
@type runtime: util_models.RuntimeOptions
|
62
|
+
@param runtime: which controls some details of call api, such as retry times
|
63
|
+
|
64
|
+
@rtype: TeaResponse
|
65
|
+
@return: the response
|
66
|
+
"""
|
67
|
+
body.validate()
|
68
|
+
runtime.validate()
|
69
|
+
_runtime = {
|
70
|
+
"timeouted": "retry",
|
71
|
+
"readTimeout": UtilClient.default_number(runtime.read_timeout, self._read_timeout),
|
72
|
+
"connectTimeout": UtilClient.default_number(runtime.connect_timeout, self._connect_timeout),
|
73
|
+
"httpProxy": UtilClient.default_string(runtime.http_proxy, self._http_proxy),
|
74
|
+
"httpsProxy": UtilClient.default_string(runtime.https_proxy, self._https_proxy),
|
75
|
+
"noProxy": UtilClient.default_string(runtime.no_proxy, self._no_proxy),
|
76
|
+
"maxIdleConns": UtilClient.default_number(runtime.max_idle_conns, self._max_idle_conns),
|
77
|
+
"retry": {
|
78
|
+
"retryable": runtime.autoretry,
|
79
|
+
"maxAttempts": UtilClient.default_number(runtime.max_attempts, 3),
|
80
|
+
},
|
81
|
+
"backoff": {
|
82
|
+
"policy": UtilClient.default_string(runtime.backoff_policy, "no"),
|
83
|
+
"period": UtilClient.default_number(runtime.backoff_period, 1),
|
84
|
+
},
|
85
|
+
"ignoreSSL": runtime.ignore_ssl,
|
86
|
+
}
|
87
|
+
_last_request = None
|
88
|
+
_last_exception = None
|
89
|
+
_now = time.time()
|
90
|
+
_retry_times = 0
|
91
|
+
while TeaCore.allow_retry(_runtime.get("retry"), _retry_times, _now):
|
92
|
+
if _retry_times > 0:
|
93
|
+
_backoff_time = TeaCore.get_backoff_time(_runtime.get("backoff"), _retry_times)
|
94
|
+
if _backoff_time > 0:
|
95
|
+
TeaCore.sleep(_backoff_time)
|
96
|
+
_retry_times = _retry_times + 1
|
97
|
+
try:
|
98
|
+
_request = TeaRequest()
|
99
|
+
_request.protocol = UtilClient.default_string(self._protocol, protocol)
|
100
|
+
_request.method = UtilClient.default_string(method, "POST")
|
101
|
+
_request.pathname = pathname
|
102
|
+
_request.headers = TeaCore.merge(
|
103
|
+
{
|
104
|
+
"host": self._domain,
|
105
|
+
"date": UtilClient.get_date_utcstring(),
|
106
|
+
"x-ca-nonce": UtilClient.get_nonce(),
|
107
|
+
"x-ca-key": self._app_key,
|
108
|
+
"x-ca-signaturemethod": "HmacSHA256",
|
109
|
+
"accept": "application/json",
|
110
|
+
"user-agent": self.get_user_agent(),
|
111
|
+
},
|
112
|
+
header,
|
113
|
+
)
|
114
|
+
if UtilClient.empty(body.id):
|
115
|
+
body.id = UtilClient.get_nonce()
|
116
|
+
if not UtilClient.is_unset(body):
|
117
|
+
_request.headers["content-type"] = "application/octet-stream"
|
118
|
+
_request.headers["content-md5"] = APIGatewayUtilClient.get_content_md5(
|
119
|
+
UtilClient.to_jsonstring(TeaCore.to_map(body))
|
120
|
+
)
|
121
|
+
_request.body = UtilClient.to_jsonstring(TeaCore.to_map(body))
|
122
|
+
_request.headers["x-ca-signature"] = APIGatewayUtilClient.get_signature(_request, self._app_secret)
|
123
|
+
_last_request = _request
|
124
|
+
_response = TeaCore.do_action(_request, _runtime)
|
125
|
+
return _response
|
126
|
+
except Exception as e:
|
127
|
+
if TeaCore.is_retryable(e):
|
128
|
+
_last_exception = e
|
129
|
+
continue
|
130
|
+
raise e
|
131
|
+
raise UnretryableException(_last_request, _last_exception)
|
132
|
+
|
133
|
+
async def async_do_request(self, pathname, protocol, method, header, body, runtime):
|
134
|
+
"""Send request
|
135
|
+
|
136
|
+
@type pathname: str
|
137
|
+
@param pathname: the url path
|
138
|
+
|
139
|
+
@type protocol: str
|
140
|
+
@param protocol: http or https
|
141
|
+
|
142
|
+
@type method: str
|
143
|
+
@param method: example GET
|
144
|
+
|
145
|
+
@type header: Dict[str, str]
|
146
|
+
@param header: request header
|
147
|
+
|
148
|
+
@type body: iot_api_gateway_models.IoTApiRequest
|
149
|
+
@param body: the object of IoTApiRequest
|
150
|
+
|
151
|
+
@type runtime: util_models.RuntimeOptions
|
152
|
+
@param runtime: which controls some details of call api, such as retry times
|
153
|
+
|
154
|
+
@rtype: TeaResponse
|
155
|
+
@return: the response
|
156
|
+
"""
|
157
|
+
body.validate()
|
158
|
+
runtime.validate()
|
159
|
+
_runtime = {
|
160
|
+
"timeouted": "retry",
|
161
|
+
"readTimeout": UtilClient.default_number(runtime.read_timeout, self._read_timeout),
|
162
|
+
"connectTimeout": UtilClient.default_number(runtime.connect_timeout, self._connect_timeout),
|
163
|
+
"httpProxy": UtilClient.default_string(runtime.http_proxy, self._http_proxy),
|
164
|
+
"httpsProxy": UtilClient.default_string(runtime.https_proxy, self._https_proxy),
|
165
|
+
"noProxy": UtilClient.default_string(runtime.no_proxy, self._no_proxy),
|
166
|
+
"maxIdleConns": UtilClient.default_number(runtime.max_idle_conns, self._max_idle_conns),
|
167
|
+
"retry": {
|
168
|
+
"retryable": runtime.autoretry,
|
169
|
+
"maxAttempts": UtilClient.default_number(runtime.max_attempts, 3),
|
170
|
+
},
|
171
|
+
"backoff": {
|
172
|
+
"policy": UtilClient.default_string(runtime.backoff_policy, "no"),
|
173
|
+
"period": UtilClient.default_number(runtime.backoff_period, 1),
|
174
|
+
},
|
175
|
+
"ignoreSSL": runtime.ignore_ssl,
|
176
|
+
}
|
177
|
+
_last_request = None
|
178
|
+
_last_exception = None
|
179
|
+
_now = time.time()
|
180
|
+
_retry_times = 0
|
181
|
+
while TeaCore.allow_retry(_runtime.get("retry"), _retry_times, _now):
|
182
|
+
if _retry_times > 0:
|
183
|
+
_backoff_time = TeaCore.get_backoff_time(_runtime.get("backoff"), _retry_times)
|
184
|
+
if _backoff_time > 0:
|
185
|
+
TeaCore.sleep(_backoff_time)
|
186
|
+
_retry_times = _retry_times + 1
|
187
|
+
try:
|
188
|
+
_request = TeaRequest()
|
189
|
+
_request.protocol = UtilClient.default_string(self._protocol, protocol)
|
190
|
+
_request.method = UtilClient.default_string(method, "POST")
|
191
|
+
_request.pathname = pathname
|
192
|
+
_request.headers = TeaCore.merge(
|
193
|
+
{
|
194
|
+
"host": self._domain,
|
195
|
+
"date": UtilClient.get_date_utcstring(),
|
196
|
+
"x-ca-nonce": UtilClient.get_nonce(),
|
197
|
+
"x-ca-key": self._app_key,
|
198
|
+
"x-ca-signaturemethod": "HmacSHA256",
|
199
|
+
"accept": "application/json",
|
200
|
+
"user-agent": self.get_user_agent(),
|
201
|
+
},
|
202
|
+
header,
|
203
|
+
)
|
204
|
+
if UtilClient.empty(body.id):
|
205
|
+
body.id = UtilClient.get_nonce()
|
206
|
+
if not UtilClient.is_unset(body):
|
207
|
+
_request.headers["content-type"] = "application/octet-stream"
|
208
|
+
_request.headers["content-md5"] = APIGatewayUtilClient.get_content_md5(
|
209
|
+
UtilClient.to_jsonstring(TeaCore.to_map(body))
|
210
|
+
)
|
211
|
+
_request.body = UtilClient.to_jsonstring(TeaCore.to_map(body))
|
212
|
+
_request.headers["x-ca-signature"] = APIGatewayUtilClient.get_signature(_request, self._app_secret)
|
213
|
+
_last_request = _request
|
214
|
+
_response = await TeaCore.async_do_action(_request, _runtime)
|
215
|
+
return _response
|
216
|
+
except Exception as e:
|
217
|
+
if TeaCore.is_retryable(e):
|
218
|
+
_last_exception = e
|
219
|
+
continue
|
220
|
+
raise e
|
221
|
+
raise UnretryableException(_last_request, _last_exception)
|
222
|
+
|
223
|
+
def get_user_agent(self):
|
224
|
+
"""Get user agent
|
225
|
+
|
226
|
+
@rtype: str
|
227
|
+
@return: user agent
|
228
|
+
"""
|
229
|
+
user_agent = UtilClient.get_user_agent(self._user_agent)
|
230
|
+
return user_agent
|
@@ -12,12 +12,12 @@ import time
|
|
12
12
|
import uuid
|
13
13
|
|
14
14
|
from aiohttp import ClientSession
|
15
|
-
from alibabacloud_iot_api_gateway.client import Client
|
16
15
|
from alibabacloud_iot_api_gateway.models import CommonParams, Config, IoTApiRequest
|
17
16
|
from alibabacloud_tea_util.client import Client as UtilClient
|
18
17
|
from alibabacloud_tea_util.models import RuntimeOptions
|
19
18
|
from Tea.exceptions import UnretryableException
|
20
19
|
|
20
|
+
from pymammotion.aliyun.client import Client
|
21
21
|
from pymammotion.aliyun.model.aep_response import AepResponse
|
22
22
|
from pymammotion.aliyun.model.connect_response import ConnectResponse
|
23
23
|
from pymammotion.aliyun.model.dev_by_account_response import ListingDevByAccountResponse
|
@@ -102,6 +102,7 @@ class CloudIOTGateway:
|
|
102
102
|
dev_by_account: ListingDevByAccountResponse | None = None,
|
103
103
|
) -> None:
|
104
104
|
"""Initialize the CloudIOTGateway."""
|
105
|
+
self._iot_token_issued_at = None
|
105
106
|
self.mammotion_http: MammotionHTTP | None = None
|
106
107
|
self._app_key = APP_KEY
|
107
108
|
self._app_secret = APP_SECRET
|
@@ -144,7 +145,7 @@ class CloudIOTGateway:
|
|
144
145
|
hashlib.sha1,
|
145
146
|
).hexdigest()
|
146
147
|
|
147
|
-
def get_region(self, country_code: str, auth_code: str):
|
148
|
+
async def get_region(self, country_code: str, auth_code: str):
|
148
149
|
"""Get the region based on country code and auth code."""
|
149
150
|
|
150
151
|
if self._region_response is not None:
|
@@ -171,7 +172,9 @@ class CloudIOTGateway:
|
|
171
172
|
)
|
172
173
|
|
173
174
|
# send request
|
174
|
-
response = client.
|
175
|
+
response = await client.async_do_request(
|
176
|
+
"/living/account/region/get", "https", "POST", None, body, RuntimeOptions()
|
177
|
+
)
|
175
178
|
logger.debug(response.status_message)
|
176
179
|
logger.debug(response.headers)
|
177
180
|
logger.debug(response.status_code)
|
@@ -191,7 +194,7 @@ class CloudIOTGateway:
|
|
191
194
|
|
192
195
|
return response.body
|
193
196
|
|
194
|
-
def aep_handle(self):
|
197
|
+
async def aep_handle(self):
|
195
198
|
"""Handle AEP authentication."""
|
196
199
|
aep_domain = self.domain
|
197
200
|
|
@@ -230,7 +233,7 @@ class CloudIOTGateway:
|
|
230
233
|
)
|
231
234
|
|
232
235
|
# send request
|
233
|
-
response = client.
|
236
|
+
response = await client.async_do_request("/app/aepauth/handle", "https", "POST", None, body, RuntimeOptions())
|
234
237
|
logger.debug(response.status_message)
|
235
238
|
logger.debug(response.headers)
|
236
239
|
logger.debug(response.status_code)
|
@@ -395,7 +398,7 @@ class CloudIOTGateway:
|
|
395
398
|
return self._login_by_oauth_response
|
396
399
|
raise LoginException(data)
|
397
400
|
|
398
|
-
def session_by_auth_code(self):
|
401
|
+
async def session_by_auth_code(self):
|
399
402
|
"""Create a session by auth code."""
|
400
403
|
config = Config(
|
401
404
|
app_key=self._app_key,
|
@@ -420,7 +423,7 @@ class CloudIOTGateway:
|
|
420
423
|
)
|
421
424
|
|
422
425
|
# send request
|
423
|
-
response = client.
|
426
|
+
response = await client.async_do_request(
|
424
427
|
"/account/createSessionByAuthCode",
|
425
428
|
"https",
|
426
429
|
"POST",
|
@@ -452,7 +455,7 @@ class CloudIOTGateway:
|
|
452
455
|
|
453
456
|
return response.body
|
454
457
|
|
455
|
-
def sign_out(self) -> None:
|
458
|
+
async def sign_out(self) -> None:
|
456
459
|
config = Config(
|
457
460
|
app_key=self._app_key,
|
458
461
|
app_secret=self._app_secret,
|
@@ -476,7 +479,7 @@ class CloudIOTGateway:
|
|
476
479
|
|
477
480
|
# send request
|
478
481
|
# possibly need to do this ourselves
|
479
|
-
response = client.
|
482
|
+
response = await client.async_do_request(
|
480
483
|
"/iotx/account/invalidSession",
|
481
484
|
"https",
|
482
485
|
"POST",
|
@@ -497,7 +500,7 @@ class CloudIOTGateway:
|
|
497
500
|
logger.debug(response_body_dict)
|
498
501
|
return response_body_dict
|
499
502
|
|
500
|
-
def check_or_refresh_session(self):
|
503
|
+
async def check_or_refresh_session(self):
|
501
504
|
"""Check or refresh the session."""
|
502
505
|
logger.debug("Trying to refresh token")
|
503
506
|
config = Config(
|
@@ -523,7 +526,7 @@ class CloudIOTGateway:
|
|
523
526
|
|
524
527
|
# send request
|
525
528
|
# possibly need to do this ourselves
|
526
|
-
response = client.
|
529
|
+
response = await client.async_do_request(
|
527
530
|
"/account/checkOrRefreshSession",
|
528
531
|
"https",
|
529
532
|
"POST",
|
@@ -544,7 +547,7 @@ class CloudIOTGateway:
|
|
544
547
|
|
545
548
|
if int(response_body_dict.get("code")) != 200:
|
546
549
|
logger.error(response_body_dict)
|
547
|
-
self.sign_out()
|
550
|
+
await self.sign_out()
|
548
551
|
raise CheckSessionException("Error check or refresh token: " + response_body_dict.__str__())
|
549
552
|
|
550
553
|
session = SessionByAuthCodeResponse.from_dict(response_body_dict)
|
@@ -562,7 +565,7 @@ class CloudIOTGateway:
|
|
562
565
|
self._session_by_authcode_response = session
|
563
566
|
self._iot_token_issued_at = int(time.time())
|
564
567
|
|
565
|
-
def list_binding_by_account(self) -> ListingDevByAccountResponse:
|
568
|
+
async def list_binding_by_account(self) -> ListingDevByAccountResponse:
|
566
569
|
"""List bindings by account."""
|
567
570
|
config = Config(
|
568
571
|
app_key=self._app_key,
|
@@ -586,7 +589,9 @@ class CloudIOTGateway:
|
|
586
589
|
)
|
587
590
|
|
588
591
|
# send request
|
589
|
-
response = client.
|
592
|
+
response = await client.async_do_request(
|
593
|
+
"/uc/listBindingByAccount", "https", "POST", None, body, RuntimeOptions()
|
594
|
+
)
|
590
595
|
logger.debug(response.status_message)
|
591
596
|
logger.debug(response.headers)
|
592
597
|
logger.debug(response.status_code)
|
@@ -604,7 +609,7 @@ class CloudIOTGateway:
|
|
604
609
|
self._devices_by_account_response = ListingDevByAccountResponse.from_dict(response_body_dict)
|
605
610
|
return self._devices_by_account_response
|
606
611
|
|
607
|
-
def list_binding_by_dev(self, iot_id: str):
|
612
|
+
async def list_binding_by_dev(self, iot_id: str):
|
608
613
|
config = Config(
|
609
614
|
app_key=self._app_key,
|
610
615
|
app_secret=self._app_secret,
|
@@ -627,7 +632,7 @@ class CloudIOTGateway:
|
|
627
632
|
)
|
628
633
|
|
629
634
|
# send request
|
630
|
-
response = client.
|
635
|
+
response = await client.async_do_request("/uc/listBindingByDev", "https", "POST", None, body, RuntimeOptions())
|
631
636
|
logger.debug(response.status_message)
|
632
637
|
logger.debug(response.headers)
|
633
638
|
logger.debug(response.status_code)
|
@@ -645,7 +650,7 @@ class CloudIOTGateway:
|
|
645
650
|
self._devices_by_account_response = ListingDevByAccountResponse.from_dict(response_body_dict)
|
646
651
|
return self._devices_by_account_response
|
647
652
|
|
648
|
-
def send_cloud_command(self, iot_id: str, command: bytes) -> str:
|
653
|
+
async def send_cloud_command(self, iot_id: str, command: bytes) -> str:
|
649
654
|
"""Send a cloud command to the specified IoT device."""
|
650
655
|
|
651
656
|
if command is None:
|
@@ -659,7 +664,7 @@ class CloudIOTGateway:
|
|
659
664
|
if self._iot_token_issued_at + self._session_by_authcode_response.data.refreshTokenExpire > (
|
660
665
|
int(time.time())
|
661
666
|
):
|
662
|
-
self.check_or_refresh_session()
|
667
|
+
await self.check_or_refresh_session()
|
663
668
|
else:
|
664
669
|
raise AuthRefreshException("Refresh token expired. Please re-login")
|
665
670
|
|
@@ -694,7 +699,8 @@ class CloudIOTGateway:
|
|
694
699
|
)
|
695
700
|
logger.debug(self.converter.printBase64Binary(command))
|
696
701
|
# send request
|
697
|
-
|
702
|
+
runtime_options = RuntimeOptions(autoretry=True, backoff_policy="yes")
|
703
|
+
response = await client.async_do_request("/thing/service/invoke", "https", "POST", None, body, runtime_options)
|
698
704
|
logger.debug(response.status_message)
|
699
705
|
logger.debug(response.headers)
|
700
706
|
logger.debug(response.status_code)
|
@@ -716,7 +722,7 @@ class CloudIOTGateway:
|
|
716
722
|
|
717
723
|
if response_body_dict.get("code") == 29003:
|
718
724
|
logger.debug(self._session_by_authcode_response.data.identityId)
|
719
|
-
self.sign_out()
|
725
|
+
await self.sign_out()
|
720
726
|
raise SetupException(response_body_dict.get("code"), iot_id)
|
721
727
|
if response_body_dict.get("code") == 6205:
|
722
728
|
raise DeviceOfflineException(response_body_dict.get("code"), iot_id)
|
@@ -13,6 +13,8 @@ class MammotionHTTP:
|
|
13
13
|
def __init__(self) -> None:
|
14
14
|
self.code = None
|
15
15
|
self.msg = None
|
16
|
+
self.account = None
|
17
|
+
self._password = None
|
16
18
|
self.response: Response | None = None
|
17
19
|
self.login_info: LoginResponseData | None = None
|
18
20
|
self._headers = {"User-Agent": "okhttp/3.14.9", "App-Version": "google Pixel 2 XL taimen-Android 11,1.11.332"}
|
@@ -106,7 +108,12 @@ class MammotionHTTP:
|
|
106
108
|
# Assuming the data format matches the expected structure
|
107
109
|
return Response[StreamSubscriptionResponse].from_dict(data)
|
108
110
|
|
109
|
-
async def
|
111
|
+
async def refresh_login(self) -> Response[LoginResponseData]:
|
112
|
+
return await self.login(self.account, self._password)
|
113
|
+
|
114
|
+
async def login(self, account: str, password: str) -> Response[LoginResponseData]:
|
115
|
+
self.account = account
|
116
|
+
self._password = password
|
110
117
|
async with ClientSession(MAMMOTION_DOMAIN) as session:
|
111
118
|
async with session.post(
|
112
119
|
"/oauth/token",
|
@@ -118,7 +125,7 @@ class MammotionHTTP:
|
|
118
125
|
"Ec-Version": "v1",
|
119
126
|
},
|
120
127
|
params=dict(
|
121
|
-
username=self.encryption_utils.encryption_by_aes(
|
128
|
+
username=self.encryption_utils.encryption_by_aes(account),
|
122
129
|
password=self.encryption_utils.encryption_by_aes(password),
|
123
130
|
client_id=self.encryption_utils.encryption_by_aes(MAMMOTION_CLIENT_ID),
|
124
131
|
client_secret=self.encryption_utils.encryption_by_aes(MAMMOTION_CLIENT_SECRET),
|
@@ -229,7 +229,7 @@ class MammotionBaseDevice:
|
|
229
229
|
# sub_cmd 4 is dump location (yuka)
|
230
230
|
# jobs list
|
231
231
|
#
|
232
|
-
|
232
|
+
await self.queue_command("get_all_boundary_hash_list", sub_cmd=3)
|
233
233
|
|
234
234
|
async def async_read_settings(self) -> None:
|
235
235
|
"""Read settings from device."""
|
@@ -187,6 +187,18 @@ class Mammotion:
|
|
187
187
|
cloud_client = await self.login(account, password)
|
188
188
|
await self.initiate_cloud_connection(account, cloud_client)
|
189
189
|
|
190
|
+
async def refresh_login(self, account: str) -> None:
|
191
|
+
async with self._login_lock:
|
192
|
+
exists: MammotionCloud | None = self.mqtt_list.get(account)
|
193
|
+
if not exists:
|
194
|
+
return
|
195
|
+
mammotion_http = exists.cloud_client.mammotion_http
|
196
|
+
await mammotion_http.refresh_login()
|
197
|
+
await self.connect_iot(mammotion_http, exists.cloud_client)
|
198
|
+
if not exists.is_connected():
|
199
|
+
loop = asyncio.get_running_loop()
|
200
|
+
await loop.run_in_executor(None, exists.connect_async)
|
201
|
+
|
190
202
|
async def initiate_cloud_connection(self, account: str, cloud_client: CloudIOTGateway) -> None:
|
191
203
|
loop = asyncio.get_running_loop()
|
192
204
|
if mqtt := self.mqtt_list.get(account):
|
@@ -242,21 +254,19 @@ class Mammotion:
|
|
242
254
|
cloud_client = CloudIOTGateway()
|
243
255
|
mammotion_http = MammotionHTTP()
|
244
256
|
await mammotion_http.login(account, password)
|
257
|
+
await cloud_client.list_binding_by_account()
|
258
|
+
await self.connect_iot(mammotion_http, cloud_client)
|
259
|
+
return cloud_client
|
260
|
+
|
261
|
+
@staticmethod
|
262
|
+
async def connect_iot(mammotion_http: MammotionHTTP, cloud_client: CloudIOTGateway) -> None:
|
245
263
|
country_code = mammotion_http.login_info.userInformation.domainAbbreviation
|
246
|
-
_LOGGER.debug("CountryCode: " + country_code)
|
247
|
-
_LOGGER.debug("AuthCode: " + mammotion_http.login_info.authorization_code)
|
248
264
|
cloud_client.set_http(mammotion_http)
|
249
|
-
|
250
|
-
await loop.run_in_executor(
|
251
|
-
None, cloud_client.get_region, country_code, mammotion_http.login_info.authorization_code
|
252
|
-
)
|
265
|
+
await cloud_client.get_region(country_code, mammotion_http.login_info.authorization_code)
|
253
266
|
await cloud_client.connect()
|
254
267
|
await cloud_client.login_by_oauth(country_code, mammotion_http.login_info.authorization_code)
|
255
|
-
await
|
256
|
-
await
|
257
|
-
|
258
|
-
await loop.run_in_executor(None, cloud_client.list_binding_by_account)
|
259
|
-
return cloud_client
|
268
|
+
await cloud_client.aep_handle()
|
269
|
+
await cloud_client.session_by_auth_code()
|
260
270
|
|
261
271
|
async def remove_device(self, name: str) -> None:
|
262
272
|
await self.device_manager.remove_device(name)
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/devices/mammotion_bluetooth.py
RENAMED
@@ -106,7 +106,6 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
|
|
106
106
|
|
107
107
|
async def _ble_sync(self) -> None:
|
108
108
|
if self._client is not None and self._client.is_connected:
|
109
|
-
_LOGGER.debug("BLE SYNC")
|
110
109
|
command_bytes = self._commands.send_todev_ble_sync(2)
|
111
110
|
await self._message.post_custom_data_bytes(command_bytes)
|
112
111
|
|
@@ -65,8 +65,8 @@ class MammotionCloud:
|
|
65
65
|
def connect_async(self) -> None:
|
66
66
|
self._mqtt_client.connect_async()
|
67
67
|
|
68
|
-
def send_command(self, iot_id: str, command: bytes) -> None:
|
69
|
-
self._mqtt_client.get_cloud_client().send_cloud_command(iot_id, command)
|
68
|
+
async def send_command(self, iot_id: str, command: bytes) -> None:
|
69
|
+
await self._mqtt_client.get_cloud_client().send_cloud_command(iot_id, command)
|
70
70
|
|
71
71
|
async def on_connected(self) -> None:
|
72
72
|
"""Callback for when MQTT connects."""
|
@@ -102,7 +102,7 @@ class MammotionCloud:
|
|
102
102
|
self._key = key
|
103
103
|
_LOGGER.debug("Sending command: %s", key)
|
104
104
|
|
105
|
-
await self.
|
105
|
+
await self._mqtt_client.get_cloud_client().send_cloud_command(iot_id, command)
|
106
106
|
future = MammotionFuture(iot_id)
|
107
107
|
self._waiting_queue.append(future)
|
108
108
|
timeout = 5
|
@@ -244,7 +244,7 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
|
|
244
244
|
command_bytes = self._commands.send_todev_ble_sync(3)
|
245
245
|
loop = asyncio.get_running_loop()
|
246
246
|
try:
|
247
|
-
await
|
247
|
+
await self._mqtt.send_command(self.iot_id, command_bytes)
|
248
248
|
except (CheckSessionException, SetupException):
|
249
249
|
self._ble_sync_task.cancel()
|
250
250
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/dev_by_account_response.py
RENAMED
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/login_by_oauth_response.py
RENAMED
File without changes
|
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/session_by_authcode_response.py
RENAMED
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/aliyun/model/stream_subscription_response.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/data/model/generate_route_information.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/abstract_message.py
RENAMED
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/mammotion_command.py
RENAMED
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/navigation.py
RENAMED
File without changes
|
{pymammotion-0.4.17 → pymammotion-0.4.18}/pymammotion/mammotion/commands/messages/network.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|