pymammotion 0.2.28__py3-none-any.whl → 0.2.30__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 +12 -9
- pymammotion/aliyun/cloud_gateway.py +57 -39
- pymammotion/aliyun/cloud_service.py +3 -3
- pymammotion/aliyun/dataclass/dev_by_account_response.py +1 -2
- pymammotion/aliyun/dataclass/session_by_authcode_response.py +1 -0
- pymammotion/bluetooth/ble.py +6 -6
- pymammotion/bluetooth/ble_message.py +30 -16
- pymammotion/bluetooth/data/convert.py +1 -1
- pymammotion/bluetooth/data/framectrldata.py +1 -1
- pymammotion/bluetooth/data/notifydata.py +6 -6
- pymammotion/const.py +1 -0
- pymammotion/data/model/__init__.py +2 -0
- pymammotion/data/model/account.py +1 -1
- pymammotion/data/model/device.py +31 -24
- pymammotion/data/model/device_config.py +71 -0
- pymammotion/data/model/enums.py +4 -4
- pymammotion/data/model/excute_boarder_params.py +5 -5
- pymammotion/data/model/execute_boarder.py +4 -4
- pymammotion/data/model/generate_route_information.py +18 -124
- pymammotion/data/model/hash_list.py +4 -7
- pymammotion/data/model/location.py +3 -3
- pymammotion/data/model/mowing_modes.py +1 -1
- pymammotion/data/model/plan.py +4 -4
- pymammotion/data/model/region_data.py +4 -4
- pymammotion/data/model/report_info.py +1 -1
- pymammotion/data/mqtt/event.py +8 -3
- pymammotion/data/state_manager.py +13 -12
- pymammotion/event/event.py +14 -14
- pymammotion/http/http.py +33 -45
- pymammotion/http/model/http.py +75 -0
- pymammotion/mammotion/commands/messages/driver.py +20 -23
- pymammotion/mammotion/commands/messages/navigation.py +47 -48
- pymammotion/mammotion/commands/messages/network.py +17 -35
- pymammotion/mammotion/commands/messages/system.py +6 -7
- pymammotion/mammotion/control/joystick.py +11 -10
- pymammotion/mammotion/devices/__init__.py +2 -2
- pymammotion/mammotion/devices/base.py +248 -0
- pymammotion/mammotion/devices/mammotion.py +52 -1042
- pymammotion/mammotion/devices/mammotion_bluetooth.py +447 -0
- pymammotion/mammotion/devices/mammotion_cloud.py +244 -0
- pymammotion/mqtt/mammotion_future.py +3 -2
- pymammotion/mqtt/mammotion_mqtt.py +23 -23
- pymammotion/proto/__init__.py +6 -0
- pymammotion/utility/constant/__init__.py +3 -1
- pymammotion/utility/conversions.py +1 -1
- pymammotion/utility/datatype_converter.py +9 -9
- pymammotion/utility/device_type.py +47 -18
- pymammotion/utility/map.py +2 -2
- pymammotion/utility/movement.py +2 -1
- pymammotion/utility/periodic.py +5 -5
- pymammotion/utility/rocker_util.py +1 -1
- {pymammotion-0.2.28.dist-info → pymammotion-0.2.30.dist-info}/METADATA +3 -1
- {pymammotion-0.2.28.dist-info → pymammotion-0.2.30.dist-info}/RECORD +55 -51
- {pymammotion-0.2.28.dist-info → pymammotion-0.2.30.dist-info}/LICENSE +0 -0
- {pymammotion-0.2.28.dist-info → pymammotion-0.2.30.dist-info}/WHEEL +0 -0
pymammotion/__init__.py
CHANGED
@@ -8,15 +8,16 @@ import asyncio
|
|
8
8
|
import logging
|
9
9
|
import os
|
10
10
|
|
11
|
+
from pymammotion.aliyun.cloud_gateway import CloudIOTGateway
|
12
|
+
|
11
13
|
# works outside HA on its own
|
12
|
-
from pymammotion.bluetooth.ble import
|
14
|
+
from pymammotion.bluetooth.ble import MammotionBLE
|
13
15
|
from pymammotion.http.http import MammotionHTTP, connect_http
|
14
16
|
|
15
17
|
# TODO make a working device that will work outside HA too.
|
16
|
-
from pymammotion.mammotion.devices import MammotionBaseBLEDevice
|
17
18
|
from pymammotion.mqtt import MammotionMQTT
|
18
19
|
|
19
|
-
__all__ = ["
|
20
|
+
__all__ = ["MammotionBLE", "MammotionHTTP", "connect_http", "MammotionMQTT"]
|
20
21
|
|
21
22
|
logger = logging.getLogger(__name__)
|
22
23
|
|
@@ -32,13 +33,15 @@ if __name__ == "__main__":
|
|
32
33
|
CLIENT_ID = os.environ.get("CLIENT_ID")
|
33
34
|
IOT_TOKEN = os.environ.get("IOT_TOKEN")
|
34
35
|
REGION = os.environ.get("REGION")
|
36
|
+
cloud_client = CloudIOTGateway()
|
35
37
|
luba = MammotionMQTT(
|
36
|
-
iot_token=IOT_TOKEN,
|
37
|
-
region_id=REGION,
|
38
|
-
product_key=PRODUCT_KEY,
|
39
|
-
device_name=DEVICE_NAME,
|
40
|
-
device_secret=DEVICE_SECRET,
|
41
|
-
client_id=CLIENT_ID,
|
38
|
+
iot_token=IOT_TOKEN or "",
|
39
|
+
region_id=REGION or "",
|
40
|
+
product_key=PRODUCT_KEY or "",
|
41
|
+
device_name=DEVICE_NAME or "",
|
42
|
+
device_secret=DEVICE_SECRET or "",
|
43
|
+
client_id=CLIENT_ID or "",
|
44
|
+
cloud_client=cloud_client,
|
42
45
|
)
|
43
46
|
luba.connect_async()
|
44
47
|
|
@@ -17,7 +17,6 @@ from alibabacloud_iot_api_gateway.models import CommonParams, Config, IoTApiRequ
|
|
17
17
|
from alibabacloud_tea_util.client import Client as UtilClient
|
18
18
|
from alibabacloud_tea_util.models import RuntimeOptions
|
19
19
|
|
20
|
-
from pymammotion.http.http import MammotionHTTP
|
21
20
|
from pymammotion.aliyun.dataclass.aep_response import AepResponse
|
22
21
|
from pymammotion.aliyun.dataclass.connect_response import ConnectResponse
|
23
22
|
from pymammotion.aliyun.dataclass.dev_by_account_response import (
|
@@ -29,6 +28,7 @@ from pymammotion.aliyun.dataclass.session_by_authcode_response import (
|
|
29
28
|
SessionByAuthCodeResponse,
|
30
29
|
)
|
31
30
|
from pymammotion.const import ALIYUN_DOMAIN, APP_KEY, APP_SECRET, APP_VERSION
|
31
|
+
from pymammotion.http.http import MammotionHTTP
|
32
32
|
from pymammotion.utility.datatype_converter import DatatypeConverter
|
33
33
|
|
34
34
|
logger = getLogger(__name__)
|
@@ -49,15 +49,19 @@ MOVE_HEADERS = (
|
|
49
49
|
class SetupException(Exception):
|
50
50
|
pass
|
51
51
|
|
52
|
+
|
52
53
|
class AuthRefreshException(Exception):
|
53
54
|
"""Raise exception when library cannot refresh token."""
|
54
55
|
|
56
|
+
|
55
57
|
class DeviceOfflineException(Exception):
|
56
58
|
"""Raise exception when device is offline."""
|
57
59
|
|
60
|
+
|
58
61
|
class LoginException(Exception):
|
59
62
|
"""Raise exception when library cannot log in."""
|
60
63
|
|
64
|
+
|
61
65
|
class CloudIOTGateway:
|
62
66
|
"""Class for interacting with Aliyun Cloud IoT Gateway."""
|
63
67
|
|
@@ -72,11 +76,19 @@ class CloudIOTGateway:
|
|
72
76
|
_devices_by_account_response: ListingDevByAccountResponse | None = None
|
73
77
|
_region_response = None
|
74
78
|
|
75
|
-
_iot_token_issued_at
|
79
|
+
_iot_token_issued_at: int = None
|
76
80
|
|
77
81
|
converter = DatatypeConverter()
|
78
82
|
|
79
|
-
def __init__(
|
83
|
+
def __init__(
|
84
|
+
self,
|
85
|
+
connect_response: ConnectResponse | None = None,
|
86
|
+
login_by_oauth_response: LoginByOAuthResponse | None = None,
|
87
|
+
aep_response: AepResponse | None = None,
|
88
|
+
session_by_authcode_response: SessionByAuthCodeResponse | None = None,
|
89
|
+
region_response: RegionResponse | None = None,
|
90
|
+
dev_by_account: ListingDevByAccountResponse | None = None,
|
91
|
+
) -> None:
|
80
92
|
"""Initialize the CloudIOTGateway."""
|
81
93
|
self.mammotion_http: MammotionHTTP | None = None
|
82
94
|
self._app_key = APP_KEY
|
@@ -94,13 +106,13 @@ class CloudIOTGateway:
|
|
94
106
|
self._devices_by_account_response = dev_by_account
|
95
107
|
|
96
108
|
@staticmethod
|
97
|
-
def generate_random_string(length):
|
109
|
+
def generate_random_string(length: int):
|
98
110
|
"""Generate a random string of specified length."""
|
99
111
|
characters = string.ascii_letters + string.digits
|
100
112
|
return "".join(random.choice(characters) for _ in range(length))
|
101
113
|
|
102
114
|
@staticmethod
|
103
|
-
def generate_hardware_string(length) -> str:
|
115
|
+
def generate_hardware_string(length: int) -> str:
|
104
116
|
"""Generate hardware string that is consistent per device."""
|
105
117
|
hashed_uuid = hashlib.sha1(f"{uuid.getnode()}".encode()).hexdigest()
|
106
118
|
return "".join(itertools.islice(itertools.cycle(hashed_uuid), length))
|
@@ -120,24 +132,6 @@ class CloudIOTGateway:
|
|
120
132
|
hashlib.sha1,
|
121
133
|
).hexdigest()
|
122
134
|
|
123
|
-
def get_connect_response(self):
|
124
|
-
return self._connect_response
|
125
|
-
|
126
|
-
def get_login_by_oauth_response(self):
|
127
|
-
return self._login_by_oauth_response
|
128
|
-
|
129
|
-
def get_aep_response(self):
|
130
|
-
return self._aep_response
|
131
|
-
|
132
|
-
def get_session_by_authcode_response(self):
|
133
|
-
return self._session_by_authcode_response
|
134
|
-
|
135
|
-
def get_devices_by_account_response(self):
|
136
|
-
return self._devices_by_account_response
|
137
|
-
|
138
|
-
def get_region_response(self):
|
139
|
-
return self._region_response
|
140
|
-
|
141
135
|
def get_region(self, country_code: str, auth_code: str):
|
142
136
|
"""Get the region based on country code and auth code."""
|
143
137
|
config = Config(
|
@@ -376,11 +370,8 @@ class CloudIOTGateway:
|
|
376
370
|
async with session.post(
|
377
371
|
f"https://{region_url}/api/prd/loginbyoauth.json",
|
378
372
|
headers=headers,
|
379
|
-
data={
|
380
|
-
'loginByOauthRequest': json.dumps(_bodyParam, separators=(",", ":"))
|
381
|
-
}
|
373
|
+
data={"loginByOauthRequest": json.dumps(_bodyParam, separators=(",", ":"))},
|
382
374
|
) as resp:
|
383
|
-
|
384
375
|
data = await resp.json()
|
385
376
|
logger.debug(data)
|
386
377
|
if resp.status == 200:
|
@@ -441,7 +432,7 @@ class CloudIOTGateway:
|
|
441
432
|
raise Exception("Error in creating session: " + response_body_str)
|
442
433
|
|
443
434
|
self._session_by_authcode_response = session_by_auth
|
444
|
-
self._iot_token_issued_at
|
435
|
+
self._iot_token_issued_at = int(time.time())
|
445
436
|
|
446
437
|
return response.body
|
447
438
|
|
@@ -491,18 +482,23 @@ class CloudIOTGateway:
|
|
491
482
|
response_body_dict = json.loads(response_body_str)
|
492
483
|
|
493
484
|
if int(response_body_dict.get("code")) != 200:
|
494
|
-
|
485
|
+
logger.error(response_body_dict)
|
486
|
+
raise Exception("Error check or refresh token: " + response_body_dict.__str__())
|
495
487
|
|
496
488
|
session = SessionByAuthCodeResponse.from_dict(response_body_dict)
|
497
489
|
session_data = session.data
|
498
490
|
|
499
|
-
if
|
491
|
+
if (
|
492
|
+
session_data.identityId is None
|
493
|
+
or session_data.refreshTokenExpire is None
|
494
|
+
or session_data.iotToken is None
|
495
|
+
or session_data.iotTokenExpire is None
|
496
|
+
or session_data.refreshToken is None
|
497
|
+
):
|
500
498
|
raise Exception("Error check or refresh token: Parameters not correct")
|
501
499
|
|
502
500
|
self._session_by_authcode_response = session
|
503
|
-
self._iot_token_issued_at
|
504
|
-
|
505
|
-
|
501
|
+
self._iot_token_issued_at = int(time.time())
|
506
502
|
|
507
503
|
def list_binding_by_account(self) -> ListingDevByAccountResponse:
|
508
504
|
"""List bindings by account."""
|
@@ -550,14 +546,16 @@ class CloudIOTGateway:
|
|
550
546
|
"""Send a cloud command to the specified IoT device."""
|
551
547
|
|
552
548
|
"""Check if iotToken is expired"""
|
553
|
-
if self._iot_token_issued_at + self._session_by_authcode_response.data.iotTokenExpire <= (
|
549
|
+
if self._iot_token_issued_at + self._session_by_authcode_response.data.iotTokenExpire <= (
|
550
|
+
int(time.time()) + (5 * 3600)
|
551
|
+
):
|
554
552
|
"""Token expired - Try to refresh - Check if refreshToken is not expired"""
|
555
|
-
if self._iot_token_issued_at + self._session_by_authcode_response.data.refreshTokenExpire > (
|
553
|
+
if self._iot_token_issued_at + self._session_by_authcode_response.data.refreshTokenExpire > (
|
554
|
+
int(time.time())
|
555
|
+
):
|
556
556
|
self.check_or_refresh_session()
|
557
557
|
else:
|
558
558
|
raise AuthRefreshException("Refresh token expired. Please re-login")
|
559
|
-
|
560
|
-
|
561
559
|
|
562
560
|
config = Config(
|
563
561
|
app_key=self._app_key,
|
@@ -614,8 +612,28 @@ class CloudIOTGateway:
|
|
614
612
|
return message_id
|
615
613
|
|
616
614
|
@property
|
617
|
-
def
|
615
|
+
def devices_by_account_response(self):
|
618
616
|
return self._devices_by_account_response
|
619
617
|
|
620
|
-
def set_http(self, mammotion_http):
|
618
|
+
def set_http(self, mammotion_http) -> None:
|
621
619
|
self.mammotion_http = mammotion_http
|
620
|
+
|
621
|
+
@property
|
622
|
+
def region_response(self):
|
623
|
+
return self._region_response
|
624
|
+
|
625
|
+
@property
|
626
|
+
def aep_response(self):
|
627
|
+
return self._aep_response
|
628
|
+
|
629
|
+
@property
|
630
|
+
def session_by_authcode_response(self):
|
631
|
+
return self._session_by_authcode_response
|
632
|
+
|
633
|
+
@property
|
634
|
+
def client_id(self):
|
635
|
+
return self._client_id
|
636
|
+
|
637
|
+
@property
|
638
|
+
def login_by_oath_response(self):
|
639
|
+
return self._login_by_oauth_response
|
@@ -10,7 +10,7 @@ from aliyunsdkiot.request.v20180120.InvokeThingServiceRequest import (
|
|
10
10
|
class CloudService:
|
11
11
|
# com.aliyun.iot.aep.sdk
|
12
12
|
# https://domestic.mammotion.com/privacy/ - lists all aliyun packages
|
13
|
-
def __init__(self):
|
13
|
+
def __init__(self) -> None:
|
14
14
|
self.selectDeviceIOTID = ""
|
15
15
|
accessKeyId = "<your accessKey>"
|
16
16
|
accessKeySecret = "<your accessSecret>"
|
@@ -31,7 +31,7 @@ class CloudService:
|
|
31
31
|
|
32
32
|
"""
|
33
33
|
|
34
|
-
def invoke_thing_service(self, data: bytearray):
|
34
|
+
def invoke_thing_service(self, data: bytearray) -> None:
|
35
35
|
base64_encoded = base64.b64encode(data).decode("utf-8")
|
36
36
|
|
37
37
|
# Create a dictionary structure
|
@@ -53,7 +53,7 @@ class CloudService:
|
|
53
53
|
# python2: print(response)
|
54
54
|
print(response)
|
55
55
|
|
56
|
-
def get_device_status(self):
|
56
|
+
def get_device_status(self) -> None:
|
57
57
|
request = GetDeviceStatusRequest()
|
58
58
|
request.set_accept_format("json")
|
59
59
|
|
@@ -29,7 +29,6 @@ class Device(DataClassORJSONMixin):
|
|
29
29
|
categoryImage: Optional[str] = None
|
30
30
|
productModel: Optional[str] = None
|
31
31
|
|
32
|
-
|
33
32
|
class Config(BaseConfig):
|
34
33
|
omit_default = True
|
35
34
|
|
@@ -37,7 +36,7 @@ class Device(DataClassORJSONMixin):
|
|
37
36
|
@dataclass
|
38
37
|
class Data(DataClassORJSONMixin):
|
39
38
|
total: int
|
40
|
-
data:
|
39
|
+
data: list[Device]
|
41
40
|
pageNo: int
|
42
41
|
pageSize: int
|
43
42
|
|
pymammotion/bluetooth/ble.py
CHANGED
@@ -11,16 +11,16 @@ from pymammotion.event.event import BleNotificationEvent
|
|
11
11
|
address = "90:38:0C:6E:EE:9E"
|
12
12
|
|
13
13
|
|
14
|
-
class
|
14
|
+
class MammotionBLE:
|
15
15
|
client: BleakClient
|
16
16
|
|
17
|
-
def __init__(self, bleEvt: BleNotificationEvent):
|
17
|
+
def __init__(self, bleEvt: BleNotificationEvent) -> None:
|
18
18
|
self._bleEvt = bleEvt
|
19
19
|
|
20
20
|
async def scanForLubaAndConnect(self) -> bool:
|
21
21
|
scanner = BleakScanner()
|
22
22
|
|
23
|
-
def scanCallback(device, advertising_data):
|
23
|
+
def scanCallback(device, advertising_data) -> bool:
|
24
24
|
# TODO: do something with incoming data
|
25
25
|
print(device)
|
26
26
|
print(advertising_data)
|
@@ -46,18 +46,18 @@ class LubaBLE:
|
|
46
46
|
if self.client is not None:
|
47
47
|
return await self.client.disconnect()
|
48
48
|
|
49
|
-
async def notification_handler(self, _characteristic: BleakGATTCharacteristic, data: bytearray):
|
49
|
+
async def notification_handler(self, _characteristic: BleakGATTCharacteristic, data: bytearray) -> None:
|
50
50
|
"""Simple notification handler which prints the data received."""
|
51
51
|
await self._bleEvt.BleNotification(data)
|
52
52
|
|
53
|
-
def service_changed_handler(self, characteristic: BleakGATTCharacteristic, data: bytearray):
|
53
|
+
def service_changed_handler(self, characteristic: BleakGATTCharacteristic, data: bytearray) -> None:
|
54
54
|
"""Simple notification handler which prints the data received."""
|
55
55
|
print(f"Response 2 {characteristic.description}: {data}")
|
56
56
|
print(data.decode("utf-8"))
|
57
57
|
# BlufiNotifyData
|
58
58
|
# run an event handler back to somewhere
|
59
59
|
|
60
|
-
async def notifications(self):
|
60
|
+
async def notifications(self) -> None:
|
61
61
|
if self.client.is_connected:
|
62
62
|
await self.client.start_notify(UUID_NOTIFICATION_CHARACTERISTIC, self.notification_handler)
|
63
63
|
await self.client.start_notify(SERVICE_CHANGED_CHARACTERISTIC, self.service_changed_handler)
|
@@ -51,14 +51,14 @@ class BleMessage:
|
|
51
51
|
notification: BlufiNotifyData
|
52
52
|
messageNavigation: MessageNavigation = MessageNavigation()
|
53
53
|
|
54
|
-
def __init__(self, client: BleakClient):
|
54
|
+
def __init__(self, client: BleakClient) -> None:
|
55
55
|
self.client = client
|
56
56
|
self.mSendSequence = itertools.count()
|
57
57
|
self.mReadSequence = itertools.count()
|
58
58
|
self.mAck = queue.Queue()
|
59
59
|
self.notification = BlufiNotifyData()
|
60
60
|
|
61
|
-
async def get_device_version_main(self):
|
61
|
+
async def get_device_version_main(self) -> None:
|
62
62
|
commEsp = dev_net_pb2.DevNet(todev_devinfo_req=dev_net_pb2.DrvDevInfoReq())
|
63
63
|
|
64
64
|
for i in range(1, 8):
|
@@ -75,24 +75,38 @@ class BleMessage:
|
|
75
75
|
lubaMsg.subtype = 1
|
76
76
|
lubaMsg.net.CopyFrom(commEsp)
|
77
77
|
byte_arr = lubaMsg.SerializeToString()
|
78
|
-
await self.
|
78
|
+
await self.post_custom_data_bytes(byte_arr)
|
79
79
|
|
80
|
-
async def get_task(self):
|
80
|
+
async def get_task(self) -> None:
|
81
81
|
hash_map = {"pver": 1, "subCmd": 2, "result": 0}
|
82
|
-
await self.
|
82
|
+
await self.post_custom_data(self.get_json_string(bleOrderCmd.task, hash_map))
|
83
83
|
|
84
|
-
async def send_ble_alive(self):
|
84
|
+
async def send_ble_alive(self) -> None:
|
85
85
|
hash_map = {"ctrl": 1}
|
86
|
-
await self.
|
86
|
+
await self.post_custom_data(self.get_json_string(bleOrderCmd.bleAlive, hash_map))
|
87
87
|
|
88
|
-
def
|
88
|
+
def get_json_string(self, cmd: int, hash_map: dict[str, object]) -> str:
|
89
|
+
jSONObject = {}
|
90
|
+
try:
|
91
|
+
jSONObject["cmd"] = cmd
|
92
|
+
jSONObject[tmp_constant.REQUEST_ID] = int(time.time())
|
93
|
+
jSONObject2 = {}
|
94
|
+
for key, value in hash_map.items():
|
95
|
+
jSONObject2[key] = value
|
96
|
+
jSONObject["params"] = jSONObject2
|
97
|
+
return json.dumps(jSONObject)
|
98
|
+
except Exception as e:
|
99
|
+
print(e)
|
100
|
+
return ""
|
101
|
+
|
102
|
+
def clearNotification(self) -> None:
|
89
103
|
self.notification = None
|
90
104
|
self.notification = BlufiNotifyData()
|
91
105
|
|
92
106
|
# async def get_device_info(self):
|
93
107
|
# await self.postCustomData(self.getJsonString(bleOrderCmd.getDeviceInfo))
|
94
108
|
|
95
|
-
async def send_device_info(self):
|
109
|
+
async def send_device_info(self) -> None:
|
96
110
|
"""Currently not called"""
|
97
111
|
luba_msg = luba_msg_pb2.LubaMsg(
|
98
112
|
msgtype=luba_msg_pb2.MsgCmdType.MSG_CMD_TYPE_ESP,
|
@@ -107,7 +121,7 @@ class BleMessage:
|
|
107
121
|
byte_arr = luba_msg.SerializeToString()
|
108
122
|
await self.post_custom_data_bytes(byte_arr)
|
109
123
|
|
110
|
-
async def requestDeviceStatus(self):
|
124
|
+
async def requestDeviceStatus(self) -> None:
|
111
125
|
request = False
|
112
126
|
type = self.messageNavigation.getTypeValue(0, 5)
|
113
127
|
try:
|
@@ -121,7 +135,7 @@ class BleMessage:
|
|
121
135
|
# if not request:
|
122
136
|
# onStatusResponse(BlufiCallback.CODE_WRITE_DATA_FAILED, null)
|
123
137
|
|
124
|
-
async def requestDeviceVersion(self):
|
138
|
+
async def requestDeviceVersion(self) -> None:
|
125
139
|
request = False
|
126
140
|
type = self.messageNavigation.getTypeValue(0, 7)
|
127
141
|
try:
|
@@ -132,7 +146,7 @@ class BleMessage:
|
|
132
146
|
request = False
|
133
147
|
_LOGGER.error(err)
|
134
148
|
|
135
|
-
async def sendBorderPackage(self, executeBorder: ExecuteBorder):
|
149
|
+
async def sendBorderPackage(self, executeBorder: ExecuteBorder) -> None:
|
136
150
|
await self.messageNavigation.post_custom_data(serialize(executeBorder))
|
137
151
|
|
138
152
|
async def gatt_write(self, data: bytes) -> None:
|
@@ -226,7 +240,7 @@ class BleMessage:
|
|
226
240
|
return dataBytes
|
227
241
|
return await self._parseDataData(subType, dataBytes)
|
228
242
|
|
229
|
-
def _parseCtrlData(self, subType: int, data: bytes):
|
243
|
+
def _parseCtrlData(self, subType: int, data: bytes) -> None:
|
230
244
|
pass
|
231
245
|
# self._parseAck(data)
|
232
246
|
|
@@ -303,7 +317,7 @@ class BleMessage:
|
|
303
317
|
def generateSendSequence(self):
|
304
318
|
return next(self.mSendSequence) & 255
|
305
319
|
|
306
|
-
async def post_custom_data_bytes(self, data: bytes):
|
320
|
+
async def post_custom_data_bytes(self, data: bytes) -> None:
|
307
321
|
if data == None:
|
308
322
|
return
|
309
323
|
type_val = self.getTypeValue(1, 19)
|
@@ -315,7 +329,7 @@ class BleMessage:
|
|
315
329
|
except Exception as err:
|
316
330
|
_LOGGER.debug(err)
|
317
331
|
|
318
|
-
async def post_custom_data(self, data_str: str):
|
332
|
+
async def post_custom_data(self, data_str: str) -> None:
|
319
333
|
data = data_str.encode()
|
320
334
|
if data == None:
|
321
335
|
return
|
@@ -389,7 +403,7 @@ class BleMessage:
|
|
389
403
|
require_ack: bool,
|
390
404
|
hasFrag: bool,
|
391
405
|
sequence: int,
|
392
|
-
data: bytes,
|
406
|
+
data: bytes | None,
|
393
407
|
) -> bytes:
|
394
408
|
byteOS = BytesIO()
|
395
409
|
dataLength = 0 if data == None else len(data)
|
@@ -14,7 +14,7 @@ def parse_custom_data(data: bytes):
|
|
14
14
|
print(err)
|
15
15
|
|
16
16
|
|
17
|
-
def store_sys_data(sys):
|
17
|
+
def store_sys_data(sys) -> None:
|
18
18
|
if sys.HasField("systemTardStateTunnel"):
|
19
19
|
tard_state_data_list = sys.systemTardStateTunnel.tard_state_data
|
20
20
|
longValue8 = tard_state_data_list[0]
|
@@ -6,7 +6,7 @@ from io import BytesIO
|
|
6
6
|
class BlufiNotifyData:
|
7
7
|
"""generated source for class BlufiNotifyData"""
|
8
8
|
|
9
|
-
def __init__(self):
|
9
|
+
def __init__(self) -> None:
|
10
10
|
self.mDataOS = BytesIO()
|
11
11
|
self.mFrameCtrlValue = 0
|
12
12
|
self.mPkgType = 0
|
@@ -18,7 +18,7 @@ class BlufiNotifyData:
|
|
18
18
|
return self.mTypeValue
|
19
19
|
|
20
20
|
# JADX INFO: Access modifiers changed from: package-private
|
21
|
-
def setType(self, i):
|
21
|
+
def setType(self, i) -> None:
|
22
22
|
"""Generated source for method setType"""
|
23
23
|
self.mTypeValue = i
|
24
24
|
|
@@ -28,7 +28,7 @@ class BlufiNotifyData:
|
|
28
28
|
return self.mPkgType
|
29
29
|
|
30
30
|
# JADX INFO: Access modifiers changed from: package-private
|
31
|
-
def setPkgType(self, i):
|
31
|
+
def setPkgType(self, i) -> None:
|
32
32
|
"""Generated source for method setPkgType"""
|
33
33
|
self.mPkgType = i
|
34
34
|
|
@@ -38,7 +38,7 @@ class BlufiNotifyData:
|
|
38
38
|
return self.mSubType
|
39
39
|
|
40
40
|
# JADX INFO: Access modifiers changed from: package-private
|
41
|
-
def setSubType(self, i):
|
41
|
+
def setSubType(self, i) -> None:
|
42
42
|
"""Generated source for method setSubType"""
|
43
43
|
self.mSubType = i
|
44
44
|
|
@@ -47,12 +47,12 @@ class BlufiNotifyData:
|
|
47
47
|
return self.mFrameCtrlValue
|
48
48
|
|
49
49
|
# JADX INFO: Access modifiers changed from: package-private
|
50
|
-
def setFrameCtrl(self, i):
|
50
|
+
def setFrameCtrl(self, i) -> None:
|
51
51
|
"""Generated source for method setFrameCtrl"""
|
52
52
|
self.mFrameCtrlValue = i
|
53
53
|
|
54
54
|
# JADX INFO: Access modifiers changed from: package-private
|
55
|
-
def addData(self, bArr, i):
|
55
|
+
def addData(self, bArr, i) -> None:
|
56
56
|
"""Generated source for method addData"""
|
57
57
|
self.mDataOS.write(bArr[i:])
|
58
58
|
|
pymammotion/const.py
CHANGED
@@ -5,5 +5,6 @@ APP_SECRET = "1ba85698bb10e19c6437413b61ba3445"
|
|
5
5
|
APP_VERSION = "1.11.130"
|
6
6
|
ALIYUN_DOMAIN = "api.link.aliyun.com"
|
7
7
|
MAMMOTION_DOMAIN = "https://id.mammotion.com"
|
8
|
+
MAMMOTION_API_DOMAIN = "https://domestic.mammotion.com"
|
8
9
|
MAMMOTION_CLIENT_ID = "MADKALUBAS"
|
9
10
|
MAMMOTION_CLIENT_SECRET = "GshzGRZJjuMUgd2sYHM7"
|