pymammotion 0.3.8__tar.gz → 0.4.0__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.3.8 → pymammotion-0.4.0}/PKG-INFO +9 -9
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/__init__.py +2 -2
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/cloud_gateway.py +12 -9
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/aep_response.py +1 -2
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/dev_by_account_response.py +7 -8
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/login_by_oauth_response.py +2 -3
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/regions_response.py +3 -3
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/session_by_authcode_response.py +1 -2
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/stream_subscription_response.py +1 -2
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/ble.py +5 -5
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/ble_message.py +9 -13
- pymammotion-0.4.0/pymammotion/data/model/device.py +136 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/device_config.py +0 -10
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/device_info.py +13 -0
- pymammotion-0.4.0/pymammotion/data/model/device_limits.py +49 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/hash_list.py +6 -2
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/plan.py +0 -3
- pymammotion-0.4.0/pymammotion/data/model/raw_data.py +215 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/region_data.py +10 -11
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/report_info.py +1 -1
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/mqtt/event.py +18 -14
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/mqtt/properties.py +1 -1
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/mqtt/status.py +1 -1
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/state_manager.py +83 -23
- pymammotion-0.4.0/pymammotion/http/encryption.py +220 -0
- pymammotion-0.4.0/pymammotion/http/http.py +142 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/http/model/http.py +2 -2
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/abstract_message.py +2 -2
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/messages/driver.py +28 -21
- pymammotion-0.4.0/pymammotion/mammotion/commands/messages/media.py +30 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/messages/navigation.py +14 -11
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/messages/network.py +15 -12
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/messages/ota.py +9 -14
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/messages/system.py +27 -24
- pymammotion-0.4.0/pymammotion/mammotion/commands/messages/video.py +29 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/devices/base.py +7 -14
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/devices/mammotion.py +22 -13
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/devices/mammotion_bluetooth.py +15 -4
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/devices/mammotion_cloud.py +30 -12
- pymammotion-0.4.0/pymammotion/mqtt/linkkit/__init__.py +5 -0
- pymammotion-0.4.0/pymammotion/mqtt/linkkit/h2client.py +585 -0
- pymammotion-0.4.0/pymammotion/mqtt/linkkit/linkkit.py +3020 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mqtt/mammotion_mqtt.py +13 -9
- pymammotion-0.4.0/pymammotion/proto/__init__.py +2181 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/luba_mul.proto +1 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/luba_mul_pb2.py +8 -8
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/luba_mul_pb2.pyi +1 -0
- pymammotion-0.4.0/pymammotion/proto/mctrl_nav_pb2.py +130 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_nav_pb2.pyi +13 -5
- pymammotion-0.4.0/pymammotion/proto/mctrl_sys_pb2.py +146 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_sys_pb2.pyi +34 -11
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/constant/device_constant.py +14 -5
- pymammotion-0.4.0/pymammotion/utility/device_config.py +754 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/device_type.py +64 -16
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pyproject.toml +73 -100
- pymammotion-0.3.8/pymammotion/aliyun/cloud_service.py +0 -65
- pymammotion-0.3.8/pymammotion/data/model/device.py +0 -333
- pymammotion-0.3.8/pymammotion/http/http.py +0 -89
- pymammotion-0.3.8/pymammotion/mammotion/commands/messages/media.py +0 -34
- pymammotion-0.3.8/pymammotion/mammotion/commands/messages/video.py +0 -34
- pymammotion-0.3.8/pymammotion/proto/__init__.py +0 -6
- pymammotion-0.3.8/pymammotion/proto/basestation.py +0 -59
- pymammotion-0.3.8/pymammotion/proto/common.py +0 -12
- pymammotion-0.3.8/pymammotion/proto/dev_net.py +0 -381
- pymammotion-0.3.8/pymammotion/proto/luba_msg.py +0 -81
- pymammotion-0.3.8/pymammotion/proto/luba_mul.py +0 -76
- pymammotion-0.3.8/pymammotion/proto/mctrl_driver.py +0 -100
- pymammotion-0.3.8/pymammotion/proto/mctrl_nav.py +0 -664
- pymammotion-0.3.8/pymammotion/proto/mctrl_nav_pb2.py +0 -128
- pymammotion-0.3.8/pymammotion/proto/mctrl_ota.py +0 -48
- pymammotion-0.3.8/pymammotion/proto/mctrl_pept.py +0 -41
- pymammotion-0.3.8/pymammotion/proto/mctrl_sys.py +0 -574
- pymammotion-0.3.8/pymammotion/proto/mctrl_sys_pb2.py +0 -142
- {pymammotion-0.3.8 → pymammotion-0.4.0}/LICENSE +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/README.md +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/connect_response.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/tmp_constant.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/const.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/data/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/data/convert.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/data/framectrldata.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/data/notifydata.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/model/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/bluetooth/model/atomic_integer.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/const.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/account.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/enums.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/excute_boarder_params.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/execute_boarder.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/generate_route_information.py +1 -1
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/location.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/mowing_modes.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/model/rapid_state.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/data/mqtt/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/event/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/event/event.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/http/_init_.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/mammotion_command.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/commands/messages/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/control/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/control/joystick.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mammotion/devices/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mqtt/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/mqtt/mammotion_future.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/basestation.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/basestation_pb2.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/basestation_pb2.pyi +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/common.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/common_pb2.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/common_pb2.pyi +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/dev_net.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/dev_net_pb2.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/dev_net_pb2.pyi +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/luba_msg.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/luba_msg_pb2.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/luba_msg_pb2.pyi +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_driver.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_driver_pb2.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_driver_pb2.pyi +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_nav.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_ota.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_ota_pb2.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_ota_pb2.pyi +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_pept.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_pept_pb2.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_pept_pb2.pyi +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/proto/mctrl_sys.proto +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/py.typed +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/constant/__init__.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/conversions.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/datatype_converter.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/map.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/movement.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/periodic.py +0 -0
- {pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/utility/rocker_util.py +0 -0
@@ -1,12 +1,12 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: pymammotion
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.4.0
|
4
4
|
Summary:
|
5
|
-
License:
|
5
|
+
License: GPL-3.0
|
6
6
|
Author: Michael Arthur
|
7
7
|
Author-email: michael@jumblesoft.co.nz
|
8
|
-
Requires-Python: >=3.10
|
9
|
-
Classifier: License ::
|
8
|
+
Requires-Python: >=3.10
|
9
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
@@ -15,17 +15,17 @@ Requires-Dist: aiohttp (>=3.9.1,<4.0.0)
|
|
15
15
|
Requires-Dist: alibabacloud-apigateway-util (>=0.0.2,<0.0.3)
|
16
16
|
Requires-Dist: alibabacloud-iot-api-gateway (>=0.0.4,<0.0.5)
|
17
17
|
Requires-Dist: alicloud-gateway-iot (>=1.0.0,<2.0.0)
|
18
|
-
Requires-Dist: aliyun-iot-linkkit (>=1.2.12,<2.0.0)
|
19
|
-
Requires-Dist: aliyun-python-sdk-iot (>=8.57.0,<9.0.0)
|
20
18
|
Requires-Dist: async-timeout (>=4.0.3,<5.0.0)
|
21
|
-
Requires-Dist: betterproto (>=
|
19
|
+
Requires-Dist: betterproto (>=2.0.0b7,<3.0.0)
|
22
20
|
Requires-Dist: bleak (>=0.21.0)
|
23
21
|
Requires-Dist: bleak-retry-connector (>=3.5.0,<4.0.0)
|
22
|
+
Requires-Dist: crcmod (>=1.7,<2.0)
|
23
|
+
Requires-Dist: cryptography (>=43.0.1)
|
24
24
|
Requires-Dist: jsonic (>=1.0.0,<2.0.0)
|
25
25
|
Requires-Dist: mashumaro (>=3.13,<4.0)
|
26
26
|
Requires-Dist: numpy (>=1.26.0)
|
27
27
|
Requires-Dist: orjson (>=3.9.15,<4.0.0)
|
28
|
-
Requires-Dist: paho-mqtt (>=1.
|
28
|
+
Requires-Dist: paho-mqtt (>=2.1.0,<3.0.0)
|
29
29
|
Requires-Dist: protobuf (>=4.23.1)
|
30
30
|
Requires-Dist: py-jsonic (>=0.0.2,<0.0.3)
|
31
31
|
Description-Content-Type: text/markdown
|
@@ -12,7 +12,7 @@ from pymammotion.aliyun.cloud_gateway import CloudIOTGateway
|
|
12
12
|
|
13
13
|
# works outside HA on its own
|
14
14
|
from pymammotion.bluetooth.ble import MammotionBLE
|
15
|
-
from pymammotion.http.http import MammotionHTTP
|
15
|
+
from pymammotion.http.http import MammotionHTTP
|
16
16
|
|
17
17
|
# TODO make a working device that will work outside HA too.
|
18
18
|
from pymammotion.mqtt import MammotionMQTT
|
@@ -20,7 +20,7 @@ from pymammotion.mqtt import MammotionMQTT
|
|
20
20
|
logger = logging.getLogger(__name__)
|
21
21
|
|
22
22
|
|
23
|
-
__all__ = ["MammotionBLE", "MammotionHTTP", "
|
23
|
+
__all__ = ["MammotionBLE", "MammotionHTTP", "MammotionMQTT", "logger"]
|
24
24
|
|
25
25
|
|
26
26
|
# TODO provide interface to pick between mqtt/cloud/bluetooth
|
@@ -5,11 +5,11 @@ import hashlib
|
|
5
5
|
import hmac
|
6
6
|
import itertools
|
7
7
|
import json
|
8
|
+
from logging import getLogger
|
8
9
|
import random
|
9
10
|
import string
|
10
11
|
import time
|
11
12
|
import uuid
|
12
|
-
from logging import getLogger
|
13
13
|
|
14
14
|
from aiohttp import ClientSession
|
15
15
|
from alibabacloud_iot_api_gateway.client import Client
|
@@ -19,14 +19,10 @@ from alibabacloud_tea_util.models import RuntimeOptions
|
|
19
19
|
|
20
20
|
from pymammotion.aliyun.model.aep_response import AepResponse
|
21
21
|
from pymammotion.aliyun.model.connect_response import ConnectResponse
|
22
|
-
from pymammotion.aliyun.model.dev_by_account_response import
|
23
|
-
ListingDevByAccountResponse,
|
24
|
-
)
|
22
|
+
from pymammotion.aliyun.model.dev_by_account_response import ListingDevByAccountResponse
|
25
23
|
from pymammotion.aliyun.model.login_by_oauth_response import LoginByOAuthResponse
|
26
24
|
from pymammotion.aliyun.model.regions_response import RegionResponse
|
27
|
-
from pymammotion.aliyun.model.session_by_authcode_response import
|
28
|
-
SessionByAuthCodeResponse,
|
29
|
-
)
|
25
|
+
from pymammotion.aliyun.model.session_by_authcode_response import SessionByAuthCodeResponse
|
30
26
|
from pymammotion.const import ALIYUN_DOMAIN, APP_KEY, APP_SECRET, APP_VERSION
|
31
27
|
from pymammotion.http.http import MammotionHTTP
|
32
28
|
from pymammotion.utility.datatype_converter import DatatypeConverter
|
@@ -58,6 +54,10 @@ class DeviceOfflineException(Exception):
|
|
58
54
|
"""Raise exception when device is offline."""
|
59
55
|
|
60
56
|
|
57
|
+
class GatewayTimeoutException(Exception):
|
58
|
+
"""Raise exception when the gateway times out."""
|
59
|
+
|
60
|
+
|
61
61
|
class LoginException(Exception):
|
62
62
|
"""Raise exception when library cannot log in."""
|
63
63
|
|
@@ -657,7 +657,7 @@ class CloudIOTGateway:
|
|
657
657
|
iot_token=self._session_by_authcode_response.data.iotToken,
|
658
658
|
)
|
659
659
|
|
660
|
-
# TODO move to using
|
660
|
+
# TODO move to using InvokeThingServiceRequest()
|
661
661
|
|
662
662
|
message_id = str(uuid.uuid4())
|
663
663
|
|
@@ -689,13 +689,16 @@ class CloudIOTGateway:
|
|
689
689
|
str(response_body_dict.get("code")),
|
690
690
|
str(response_body_dict.get("message")),
|
691
691
|
)
|
692
|
+
if response_body_dict.get("code") == 20056:
|
693
|
+
logger.debug("Gateway timeout.")
|
694
|
+
raise GatewayTimeoutException(response_body_dict.get("code"))
|
695
|
+
|
692
696
|
if response_body_dict.get("code") == 29003:
|
693
697
|
logger.debug(self._session_by_authcode_response.data.identityId)
|
694
698
|
self.sign_out()
|
695
699
|
raise SetupException(response_body_dict.get("code"))
|
696
700
|
if response_body_dict.get("code") == 6205:
|
697
701
|
raise DeviceOfflineException(response_body_dict.get("code"))
|
698
|
-
"""Device is offline."""
|
699
702
|
|
700
703
|
return message_id
|
701
704
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from mashumaro.config import BaseConfig
|
5
4
|
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
@@ -16,7 +15,7 @@ class DeviceData(DataClassORJSONMixin):
|
|
16
15
|
class AepResponse(DataClassORJSONMixin):
|
17
16
|
code: int
|
18
17
|
data: DeviceData
|
19
|
-
id:
|
18
|
+
id: str | None = None
|
20
19
|
|
21
20
|
class Config(BaseConfig):
|
22
21
|
omit_default = True
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from mashumaro.config import BaseConfig
|
5
4
|
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
@@ -23,11 +22,11 @@ class Device(DataClassORJSONMixin):
|
|
23
22
|
identityId: str
|
24
23
|
thingType: str
|
25
24
|
status: int
|
26
|
-
nickName:
|
27
|
-
description:
|
28
|
-
productImage:
|
29
|
-
categoryImage:
|
30
|
-
productModel:
|
25
|
+
nickName: str | None = None
|
26
|
+
description: str | None = None
|
27
|
+
productImage: str | None = None
|
28
|
+
categoryImage: str | None = None
|
29
|
+
productModel: str | None = None
|
31
30
|
|
32
31
|
class Config(BaseConfig):
|
33
32
|
omit_default = True
|
@@ -44,5 +43,5 @@ class Data(DataClassORJSONMixin):
|
|
44
43
|
@dataclass
|
45
44
|
class ListingDevByAccountResponse(DataClassORJSONMixin):
|
46
45
|
code: int
|
47
|
-
data:
|
48
|
-
id:
|
46
|
+
data: Data | None
|
47
|
+
id: str | None = None
|
@@ -1,5 +1,4 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
5
4
|
|
@@ -18,7 +17,7 @@ class OpenAccount(DataClassORJSONMixin):
|
|
18
17
|
domainId: int
|
19
18
|
enableDevice: str
|
20
19
|
status: int
|
21
|
-
country:
|
20
|
+
country: str | None = None
|
22
21
|
|
23
22
|
|
24
23
|
@dataclass
|
@@ -54,7 +53,7 @@ class InnerData(DataClassORJSONMixin):
|
|
54
53
|
subCode: int
|
55
54
|
message: str
|
56
55
|
successful: str
|
57
|
-
deviceId:
|
56
|
+
deviceId: str | None = None
|
58
57
|
|
59
58
|
|
60
59
|
@dataclass
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import
|
2
|
+
from typing import TypeVar
|
3
3
|
|
4
4
|
from mashumaro.config import BaseConfig
|
5
5
|
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
@@ -22,8 +22,8 @@ class RegionResponseData(DataClassORJSONMixin):
|
|
22
22
|
class RegionResponse(DataClassORJSONMixin):
|
23
23
|
data: RegionResponseData
|
24
24
|
code: int
|
25
|
-
id:
|
26
|
-
msg:
|
25
|
+
id: str | None = None
|
26
|
+
msg: str | None = None
|
27
27
|
|
28
28
|
class Config(BaseConfig):
|
29
29
|
omit_default = True
|
{pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/session_by_authcode_response.py
RENAMED
@@ -1,5 +1,4 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import Optional
|
3
2
|
|
4
3
|
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
5
4
|
|
@@ -16,4 +15,4 @@ class SessionOauthToken(DataClassORJSONMixin):
|
|
16
15
|
@dataclass
|
17
16
|
class SessionByAuthCodeResponse(DataClassORJSONMixin):
|
18
17
|
code: int
|
19
|
-
data:
|
18
|
+
data: SessionOauthToken | None = None
|
{pymammotion-0.3.8 → pymammotion-0.4.0}/pymammotion/aliyun/model/stream_subscription_response.py
RENAMED
@@ -1,5 +1,4 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import List
|
3
2
|
|
4
3
|
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
5
4
|
|
@@ -13,7 +12,7 @@ class Camera(DataClassORJSONMixin):
|
|
13
12
|
@dataclass
|
14
13
|
class StreamSubscriptionResponse(DataClassORJSONMixin):
|
15
14
|
appid: str
|
16
|
-
cameras:
|
15
|
+
cameras: list[Camera]
|
17
16
|
channelName: str
|
18
17
|
token: str
|
19
18
|
uid: int
|
@@ -1,14 +1,13 @@
|
|
1
1
|
from bleak import BleakClient, BleakScanner, BLEDevice
|
2
2
|
from bleak.backends.characteristic import BleakGATTCharacteristic
|
3
3
|
|
4
|
-
from pymammotion.bluetooth.const import
|
5
|
-
SERVICE_CHANGED_CHARACTERISTIC,
|
6
|
-
UUID_NOTIFICATION_CHARACTERISTIC,
|
7
|
-
)
|
4
|
+
from pymammotion.bluetooth.const import SERVICE_CHANGED_CHARACTERISTIC, UUID_NOTIFICATION_CHARACTERISTIC
|
8
5
|
from pymammotion.event.event import BleNotificationEvent
|
9
6
|
|
10
7
|
|
11
8
|
class MammotionBLE:
|
9
|
+
"""Class for basic ble connections to mowers."""
|
10
|
+
|
12
11
|
client: BleakClient
|
13
12
|
|
14
13
|
def __init__(self, bleEvt: BleNotificationEvent) -> None:
|
@@ -60,5 +59,6 @@ class MammotionBLE:
|
|
60
59
|
await self.client.start_notify(UUID_NOTIFICATION_CHARACTERISTIC, self.notification_handler)
|
61
60
|
await self.client.start_notify(SERVICE_CHANGED_CHARACTERISTIC, self.service_changed_handler)
|
62
61
|
|
63
|
-
def
|
62
|
+
def get_client(self):
|
63
|
+
"""Returns the ble client."""
|
64
64
|
return self.client
|
@@ -1,12 +1,11 @@
|
|
1
|
+
from asyncio import sleep
|
2
|
+
from io import BytesIO
|
1
3
|
import itertools
|
2
4
|
import json
|
3
5
|
import logging
|
4
6
|
import queue
|
5
7
|
import sys
|
6
8
|
import time
|
7
|
-
from asyncio import sleep
|
8
|
-
from io import BytesIO
|
9
|
-
from typing import Union
|
10
9
|
|
11
10
|
from bleak import BleakClient
|
12
11
|
from jsonic.serializable import serialize
|
@@ -17,10 +16,7 @@ from pymammotion.bluetooth.data.framectrldata import FrameCtrlData
|
|
17
16
|
from pymammotion.bluetooth.data.notifydata import BlufiNotifyData
|
18
17
|
from pymammotion.bluetooth.model.atomic_integer import AtomicInteger
|
19
18
|
from pymammotion.data.model.execute_boarder import ExecuteBorder
|
20
|
-
from pymammotion.proto import
|
21
|
-
dev_net_pb2,
|
22
|
-
)
|
23
|
-
from pymammotion.proto.luba_msg import LubaMsg, MsgAttr, MsgCmdType, MsgDevice
|
19
|
+
from pymammotion.proto import DevNet, DrvDevInfoReq, LubaMsg, MsgAttr, MsgCmdType, MsgDevice
|
24
20
|
from pymammotion.utility.constant.device_constant import bleOrderCmd
|
25
21
|
|
26
22
|
_LOGGER = logging.getLogger(__name__)
|
@@ -320,7 +316,7 @@ class BleMessage:
|
|
320
316
|
hash_map = {"ctrl": 1}
|
321
317
|
await self.post_custom_data(self.get_json_string(bleOrderCmd.bleAlive, hash_map))
|
322
318
|
|
323
|
-
def get_json_string(self, cmd: int, hash_map: dict[str,
|
319
|
+
def get_json_string(self, cmd: int, hash_map: dict[str, int]) -> str:
|
324
320
|
jSONObject = {}
|
325
321
|
try:
|
326
322
|
jSONObject["cmd"] = cmd
|
@@ -334,7 +330,7 @@ class BleMessage:
|
|
334
330
|
print(e)
|
335
331
|
return ""
|
336
332
|
|
337
|
-
def
|
333
|
+
def clear_notification(self) -> None:
|
338
334
|
self.notification = None
|
339
335
|
self.notification = BlufiNotifyData()
|
340
336
|
|
@@ -344,14 +340,14 @@ class BleMessage:
|
|
344
340
|
async def send_device_info(self) -> None:
|
345
341
|
"""Currently not called"""
|
346
342
|
luba_msg = LubaMsg(
|
347
|
-
msgtype=MsgCmdType.
|
343
|
+
msgtype=MsgCmdType.ESP,
|
348
344
|
sender=MsgDevice.DEV_MOBILEAPP,
|
349
345
|
rcver=MsgDevice.DEV_COMM_ESP,
|
350
|
-
msgattr=MsgAttr.
|
346
|
+
msgattr=MsgAttr.REQ,
|
351
347
|
seqs=1,
|
352
348
|
version=1,
|
353
349
|
subtype=1,
|
354
|
-
net=
|
350
|
+
net=DevNet(todev_ble_sync=1, todev_devinfo_req=DrvDevInfoReq()),
|
355
351
|
)
|
356
352
|
byte_arr = luba_msg.SerializeToString()
|
357
353
|
await self.post_custom_data_bytes(byte_arr)
|
@@ -656,7 +652,7 @@ class BleMessage:
|
|
656
652
|
return byteOS.getvalue()
|
657
653
|
|
658
654
|
@staticmethod
|
659
|
-
def calc_crc(initial: int, data:
|
655
|
+
def calc_crc(initial: int, data: bytes | bytearray) -> int:
|
660
656
|
"""Calculate CRC value for given initial value and byte array.
|
661
657
|
|
662
658
|
Args:
|
@@ -0,0 +1,136 @@
|
|
1
|
+
"""MowingDevice class to wrap around the betterproto dataclasses."""
|
2
|
+
|
3
|
+
from dataclasses import dataclass, field
|
4
|
+
|
5
|
+
import betterproto
|
6
|
+
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
7
|
+
|
8
|
+
from pymammotion.data.model import HashList, RapidState
|
9
|
+
from pymammotion.data.model.device_info import DeviceFirmwares, MowerInfo
|
10
|
+
from pymammotion.data.model.location import Location
|
11
|
+
from pymammotion.data.model.report_info import ReportData
|
12
|
+
from pymammotion.data.mqtt.properties import ThingPropertiesMessage
|
13
|
+
from pymammotion.data.mqtt.status import ThingStatusMessage
|
14
|
+
from pymammotion.http.model.http import ErrorInfo
|
15
|
+
from pymammotion.proto import DeviceFwInfo, MowToAppInfoT, ReportInfoData, SystemRapidStateTunnelMsg, SystemUpdateBufMsg
|
16
|
+
from pymammotion.utility.constant import WorkMode
|
17
|
+
from pymammotion.utility.conversions import parse_double
|
18
|
+
from pymammotion.utility.map import CoordinateConverter
|
19
|
+
|
20
|
+
|
21
|
+
@dataclass
|
22
|
+
class MowingDevice(DataClassORJSONMixin):
|
23
|
+
"""Wraps the betterproto dataclasses, so we can bypass the groups for keeping all data."""
|
24
|
+
|
25
|
+
online: bool = True
|
26
|
+
mower_state: MowerInfo = field(default_factory=MowerInfo)
|
27
|
+
mqtt_properties: ThingPropertiesMessage | None = None
|
28
|
+
status_properties: ThingStatusMessage | None = None
|
29
|
+
map: HashList = field(default_factory=HashList)
|
30
|
+
location: Location = field(default_factory=Location)
|
31
|
+
mowing_state: RapidState = field(default_factory=RapidState)
|
32
|
+
report_data: ReportData = field(default_factory=ReportData)
|
33
|
+
device_firmwares: DeviceFirmwares = field(default_factory=DeviceFirmwares)
|
34
|
+
err_code_list: list = field(default_factory=list)
|
35
|
+
err_code_list_time: list | None = field(default_factory=list)
|
36
|
+
error_codes: dict[str, ErrorInfo] = field(default_factory=dict)
|
37
|
+
|
38
|
+
def buffer(self, buffer_list: SystemUpdateBufMsg) -> None:
|
39
|
+
"""Update the device based on which buffer we are reading from."""
|
40
|
+
match buffer_list.update_buf_data[0]:
|
41
|
+
case 1:
|
42
|
+
# 4 speed
|
43
|
+
self.location.RTK.latitude = parse_double(buffer_list.update_buf_data[5], 8.0)
|
44
|
+
self.location.RTK.longitude = parse_double(buffer_list.update_buf_data[6], 8.0)
|
45
|
+
self.location.dock.latitude = parse_double(buffer_list.update_buf_data[7], 4.0)
|
46
|
+
self.location.dock.longitude = parse_double(buffer_list.update_buf_data[8], 4.0)
|
47
|
+
self.location.dock.rotation = buffer_list.update_buf_data[3] + 180
|
48
|
+
case 2:
|
49
|
+
self.err_code_list.clear()
|
50
|
+
self.err_code_list_time.clear()
|
51
|
+
self.err_code_list.extend(
|
52
|
+
[
|
53
|
+
buffer_list.update_buf_data[3],
|
54
|
+
buffer_list.update_buf_data[5],
|
55
|
+
buffer_list.update_buf_data[7],
|
56
|
+
buffer_list.update_buf_data[9],
|
57
|
+
buffer_list.update_buf_data[11],
|
58
|
+
buffer_list.update_buf_data[13],
|
59
|
+
buffer_list.update_buf_data[15],
|
60
|
+
buffer_list.update_buf_data[17],
|
61
|
+
buffer_list.update_buf_data[19],
|
62
|
+
buffer_list.update_buf_data[21],
|
63
|
+
]
|
64
|
+
)
|
65
|
+
self.err_code_list_time.extend(
|
66
|
+
[
|
67
|
+
buffer_list.update_buf_data[4],
|
68
|
+
buffer_list.update_buf_data[6],
|
69
|
+
buffer_list.update_buf_data[8],
|
70
|
+
buffer_list.update_buf_data[10],
|
71
|
+
buffer_list.update_buf_data[12],
|
72
|
+
buffer_list.update_buf_data[14],
|
73
|
+
buffer_list.update_buf_data[16],
|
74
|
+
buffer_list.update_buf_data[18],
|
75
|
+
buffer_list.update_buf_data[20],
|
76
|
+
buffer_list.update_buf_data[22],
|
77
|
+
]
|
78
|
+
)
|
79
|
+
|
80
|
+
def update_report_data(self, toapp_report_data: ReportInfoData) -> None:
|
81
|
+
coordinate_converter = CoordinateConverter(self.location.RTK.latitude, self.location.RTK.longitude)
|
82
|
+
for index, location in enumerate(toapp_report_data.locations):
|
83
|
+
if index == 0 and location.real_pos_y != 0:
|
84
|
+
self.location.position_type = location.pos_type
|
85
|
+
self.location.orientation = int(location.real_toward / 10000)
|
86
|
+
self.location.device = coordinate_converter.enu_to_lla(
|
87
|
+
parse_double(location.real_pos_y, 4.0), parse_double(location.real_pos_x, 4.0)
|
88
|
+
)
|
89
|
+
if location.zone_hash:
|
90
|
+
self.location.work_zone = (
|
91
|
+
location.zone_hash if self.report_data.dev.sys_status == WorkMode.MODE_WORKING else 0
|
92
|
+
)
|
93
|
+
|
94
|
+
if toapp_report_data.fw_info:
|
95
|
+
self.update_device_firmwares(toapp_report_data.fw_info)
|
96
|
+
|
97
|
+
self.report_data.update(toapp_report_data.to_dict(casing=betterproto.Casing.SNAKE))
|
98
|
+
|
99
|
+
def run_state_update(self, rapid_state: SystemRapidStateTunnelMsg) -> None:
|
100
|
+
coordinate_converter = CoordinateConverter(self.location.RTK.latitude, self.location.RTK.longitude)
|
101
|
+
self.mowing_state = RapidState().from_raw(rapid_state.rapid_state_data)
|
102
|
+
self.location.position_type = self.mowing_state.pos_type
|
103
|
+
self.location.orientation = int(self.mowing_state.toward / 10000)
|
104
|
+
self.location.device = coordinate_converter.enu_to_lla(
|
105
|
+
parse_double(self.mowing_state.pos_y, 4.0), parse_double(self.mowing_state.pos_x, 4.0)
|
106
|
+
)
|
107
|
+
if self.mowing_state.zone_hash:
|
108
|
+
self.location.work_zone = (
|
109
|
+
self.mowing_state.zone_hash if self.report_data.dev.sys_status == WorkMode.MODE_WORKING else 0
|
110
|
+
)
|
111
|
+
|
112
|
+
def mow_info(self, toapp_mow_info: MowToAppInfoT) -> None:
|
113
|
+
pass
|
114
|
+
|
115
|
+
def report_missing_data(self) -> None:
|
116
|
+
"""Report missing data so we can refetch it."""
|
117
|
+
|
118
|
+
def update_device_firmwares(self, fw_info: DeviceFwInfo) -> None:
|
119
|
+
"""Sets firmware versions on all parts of the robot or RTK."""
|
120
|
+
for mod in fw_info.mod:
|
121
|
+
match mod.type:
|
122
|
+
case 1:
|
123
|
+
self.device_firmwares.main_controller = mod.version
|
124
|
+
case 3:
|
125
|
+
self.device_firmwares.left_motor_driver = mod.version
|
126
|
+
case 4:
|
127
|
+
self.device_firmwares.right_motor_driver = mod.version
|
128
|
+
case 5:
|
129
|
+
self.device_firmwares.rtk_rover_station = mod.version
|
130
|
+
case 101:
|
131
|
+
# RTK main board
|
132
|
+
self.device_firmwares.main_controller = mod.version
|
133
|
+
case 102:
|
134
|
+
self.device_firmwares.rtk_version = mod.version
|
135
|
+
case 103:
|
136
|
+
self.device_firmwares.lora_version = mod.version
|
@@ -5,16 +5,6 @@ from mashumaro.mixins.orjson import DataClassORJSONMixin
|
|
5
5
|
from pymammotion.utility.device_type import DeviceType
|
6
6
|
|
7
7
|
|
8
|
-
@dataclass
|
9
|
-
class DeviceLimits(DataClassORJSONMixin):
|
10
|
-
blade_height_min: int = 30
|
11
|
-
blade_height_max: int = 100
|
12
|
-
working_speed_min: float = 0.2
|
13
|
-
working_speed_max: float = 1.2
|
14
|
-
working_path_min: int = 15
|
15
|
-
working_path_max: int = 35
|
16
|
-
|
17
|
-
|
18
8
|
@dataclass
|
19
9
|
class OperationSettings(DataClassORJSONMixin):
|
20
10
|
"""Operation settings for a device."""
|
@@ -23,3 +23,16 @@ class MowerInfo(DataClassORJSONMixin):
|
|
23
23
|
swversion: str = ""
|
24
24
|
product_key: str = ""
|
25
25
|
model_id: str = ""
|
26
|
+
sub_model_id: str = ""
|
27
|
+
|
28
|
+
|
29
|
+
@dataclass
|
30
|
+
class DeviceFirmwares(DataClassORJSONMixin):
|
31
|
+
device_version: str = ""
|
32
|
+
left_motor_driver: str = ""
|
33
|
+
lora_version: str = ""
|
34
|
+
main_controller: str = ""
|
35
|
+
model_name: str = ""
|
36
|
+
right_motor_driver: str = ""
|
37
|
+
rtk_rover_station: str = ""
|
38
|
+
rtk_version: str = ""
|
@@ -0,0 +1,49 @@
|
|
1
|
+
from dataclasses import dataclass, field
|
2
|
+
|
3
|
+
|
4
|
+
@dataclass
|
5
|
+
class RangeLimit:
|
6
|
+
min: float
|
7
|
+
max: float
|
8
|
+
|
9
|
+
|
10
|
+
@dataclass
|
11
|
+
class DeviceLimits:
|
12
|
+
cutter_height: RangeLimit = field(default_factory=RangeLimit)
|
13
|
+
working_speed: RangeLimit = field(default_factory=RangeLimit)
|
14
|
+
working_path: RangeLimit = field(default_factory=RangeLimit)
|
15
|
+
work_area_num_max: int = 60
|
16
|
+
display_image_type: int = 0
|
17
|
+
|
18
|
+
def to_dict(self) -> dict:
|
19
|
+
"""Convert the device limits to a dictionary format."""
|
20
|
+
return {
|
21
|
+
"cutter_height": {"min": self.cutter_height.min, "max": self.cutter_height.max},
|
22
|
+
"working_speed": {"min": self.working_speed.min, "max": self.working_speed.max},
|
23
|
+
"working_path": {"min": self.working_path.min, "max": self.working_path.max},
|
24
|
+
"work_area_num_max": self.work_area_num_max,
|
25
|
+
"display_image_type": self.display_image_type,
|
26
|
+
}
|
27
|
+
|
28
|
+
@classmethod
|
29
|
+
def from_dict(cls, data: dict) -> "DeviceLimits":
|
30
|
+
"""Create a DeviceLimits instance from a dictionary."""
|
31
|
+
return cls(
|
32
|
+
cutter_height=RangeLimit(min=data["cutter_height"]["min"], max=data["cutter_height"]["max"]),
|
33
|
+
working_speed=RangeLimit(min=data["working_speed"]["min"], max=data["working_speed"]["max"]),
|
34
|
+
working_path=RangeLimit(min=data["working_path"]["min"], max=data["working_path"]["max"]),
|
35
|
+
work_area_num_max=data["work_area_num_max"],
|
36
|
+
display_image_type=data["display_image_type"],
|
37
|
+
)
|
38
|
+
|
39
|
+
def validate(self) -> bool:
|
40
|
+
"""Validate that all ranges are logical (min <= max)."""
|
41
|
+
return all(
|
42
|
+
[
|
43
|
+
self.cutter_height.min <= self.cutter_height.max,
|
44
|
+
self.working_speed.min <= self.working_speed.max,
|
45
|
+
self.working_path.min <= self.working_path.max,
|
46
|
+
self.work_area_num_max > 0,
|
47
|
+
self.display_image_type in (0, 1),
|
48
|
+
]
|
49
|
+
)
|
@@ -3,7 +3,7 @@ from enum import IntEnum
|
|
3
3
|
|
4
4
|
from mashumaro.mixins.orjson import DataClassORJSONMixin
|
5
5
|
|
6
|
-
from pymammotion.proto
|
6
|
+
from pymammotion.proto import NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
|
7
7
|
|
8
8
|
|
9
9
|
class PathType(IntEnum):
|
@@ -93,7 +93,7 @@ class HashList(DataClassORJSONMixin):
|
|
93
93
|
# If no match was found, append the new item
|
94
94
|
self.root_hash_list.data.append(hash_list)
|
95
95
|
|
96
|
-
def missing_hash_frame(self):
|
96
|
+
def missing_hash_frame(self) -> list[int]:
|
97
97
|
return self._find_missing_frames(self.root_hash_list)
|
98
98
|
|
99
99
|
def missing_frame(self, hash_data: NavGetCommDataAck | SvgMessageAckT) -> list[int]:
|
@@ -112,6 +112,8 @@ class HashList(DataClassORJSONMixin):
|
|
112
112
|
if hash_data.type == PathType.SVG:
|
113
113
|
return self._find_missing_frames(self.svg.get(hash_data.data_hash))
|
114
114
|
|
115
|
+
return []
|
116
|
+
|
115
117
|
def update(self, hash_data: NavGetCommDataAck | SvgMessageAckT) -> bool:
|
116
118
|
"""Update the map data."""
|
117
119
|
if hash_data.type == PathType.AREA:
|
@@ -133,6 +135,8 @@ class HashList(DataClassORJSONMixin):
|
|
133
135
|
if hash_data.type == PathType.SVG:
|
134
136
|
return self._add_hash_data(self.svg, hash_data)
|
135
137
|
|
138
|
+
return False
|
139
|
+
|
136
140
|
@staticmethod
|
137
141
|
def _find_missing_frames(frame_list: FrameList | RootHashList) -> list[int]:
|
138
142
|
if frame_list.total_frame == len(frame_list.data):
|