pymammotion 0.4.0a8__tar.gz → 0.4.0b1__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.
Files changed (134) hide show
  1. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/PKG-INFO +2 -2
  2. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/cloud_gateway.py +3 -7
  3. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/model/aep_response.py +1 -2
  4. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/model/dev_by_account_response.py +7 -8
  5. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/model/login_by_oauth_response.py +2 -3
  6. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/model/regions_response.py +3 -3
  7. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/model/session_by_authcode_response.py +1 -2
  8. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/model/stream_subscription_response.py +1 -2
  9. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/ble.py +1 -4
  10. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/ble_message.py +4 -7
  11. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/plan.py +0 -3
  12. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/raw_data.py +1 -2
  13. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/region_data.py +10 -11
  14. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/mqtt/properties.py +1 -1
  15. pymammotion-0.4.0b1/pymammotion/data/state_manager.py +173 -0
  16. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/http/encryption.py +5 -6
  17. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/http/http.py +1 -6
  18. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/http/model/http.py +2 -2
  19. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/messages/network.py +2 -2
  20. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/messages/video.py +3 -6
  21. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/devices/base.py +2 -10
  22. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/devices/mammotion.py +4 -2
  23. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/devices/mammotion_bluetooth.py +9 -0
  24. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/devices/mammotion_cloud.py +11 -3
  25. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mqtt/linkkit/h2client.py +7 -4
  26. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mqtt/linkkit/linkkit.py +2 -2
  27. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pyproject.toml +56 -89
  28. pymammotion-0.4.0a8/pymammotion/data/state_manager.py +0 -147
  29. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/LICENSE +0 -0
  30. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/README.md +0 -0
  31. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/__init__.py +0 -0
  32. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/__init__.py +0 -0
  33. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/model/connect_response.py +0 -0
  34. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/aliyun/tmp_constant.py +0 -0
  35. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/__init__.py +0 -0
  36. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/const.py +0 -0
  37. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/data/__init__.py +0 -0
  38. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/data/convert.py +0 -0
  39. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/data/framectrldata.py +0 -0
  40. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/data/notifydata.py +0 -0
  41. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/model/__init__.py +0 -0
  42. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/bluetooth/model/atomic_integer.py +0 -0
  43. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/const.py +0 -0
  44. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/__init__.py +0 -0
  45. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/__init__.py +0 -0
  46. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/account.py +0 -0
  47. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/device.py +0 -0
  48. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/device_config.py +0 -0
  49. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/device_info.py +0 -0
  50. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/device_limits.py +0 -0
  51. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/enums.py +0 -0
  52. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/excute_boarder_params.py +0 -0
  53. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/execute_boarder.py +0 -0
  54. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/generate_route_information.py +1 -1
  55. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/hash_list.py +0 -0
  56. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/location.py +0 -0
  57. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/mowing_modes.py +0 -0
  58. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/rapid_state.py +0 -0
  59. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/model/report_info.py +0 -0
  60. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/mqtt/__init__.py +0 -0
  61. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/mqtt/event.py +0 -0
  62. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/data/mqtt/status.py +0 -0
  63. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/event/__init__.py +0 -0
  64. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/event/event.py +0 -0
  65. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/http/_init_.py +0 -0
  66. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/__init__.py +0 -0
  67. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/__init__.py +0 -0
  68. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/abstract_message.py +0 -0
  69. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/mammotion_command.py +0 -0
  70. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/messages/__init__.py +0 -0
  71. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/messages/driver.py +1 -1
  72. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/messages/media.py +0 -0
  73. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/messages/navigation.py +1 -1
  74. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/messages/ota.py +0 -0
  75. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/commands/messages/system.py +1 -1
  76. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/control/__init__.py +0 -0
  77. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/control/joystick.py +0 -0
  78. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mammotion/devices/__init__.py +0 -0
  79. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mqtt/__init__.py +0 -0
  80. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mqtt/linkkit/__init__.py +0 -0
  81. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mqtt/mammotion_future.py +0 -0
  82. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/mqtt/mammotion_mqtt.py +1 -1
  83. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/__init__.py +0 -0
  84. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/basestation.proto +0 -0
  85. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/basestation.py +0 -0
  86. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/basestation_pb2.py +0 -0
  87. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/basestation_pb2.pyi +0 -0
  88. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/common.proto +0 -0
  89. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/common.py +0 -0
  90. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/common_pb2.py +0 -0
  91. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/common_pb2.pyi +0 -0
  92. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/dev_net.proto +0 -0
  93. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/dev_net.py +0 -0
  94. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/dev_net_pb2.py +0 -0
  95. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/dev_net_pb2.pyi +0 -0
  96. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/luba_msg.proto +0 -0
  97. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/luba_msg.py +0 -0
  98. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/luba_msg_pb2.py +0 -0
  99. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/luba_msg_pb2.pyi +0 -0
  100. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/luba_mul.proto +0 -0
  101. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/luba_mul.py +0 -0
  102. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/luba_mul_pb2.py +0 -0
  103. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/luba_mul_pb2.pyi +0 -0
  104. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_driver.proto +0 -0
  105. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_driver.py +0 -0
  106. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_driver_pb2.py +0 -0
  107. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_driver_pb2.pyi +0 -0
  108. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_nav.proto +0 -0
  109. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_nav.py +0 -0
  110. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_nav_pb2.py +0 -0
  111. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_nav_pb2.pyi +0 -0
  112. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_ota.proto +0 -0
  113. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_ota.py +0 -0
  114. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_ota_pb2.py +0 -0
  115. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_ota_pb2.pyi +0 -0
  116. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_pept.proto +0 -0
  117. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_pept.py +0 -0
  118. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_pept_pb2.py +0 -0
  119. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_pept_pb2.pyi +0 -0
  120. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_sys.proto +0 -0
  121. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_sys.py +0 -0
  122. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_sys_pb2.py +0 -0
  123. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/proto/mctrl_sys_pb2.pyi +0 -0
  124. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/py.typed +0 -0
  125. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/constant/__init__.py +0 -0
  126. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/constant/device_constant.py +0 -0
  127. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/conversions.py +0 -0
  128. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/datatype_converter.py +0 -0
  129. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/device_config.py +0 -0
  130. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/device_type.py +0 -0
  131. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/map.py +0 -0
  132. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/movement.py +0 -0
  133. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/periodic.py +0 -0
  134. {pymammotion-0.4.0a8 → pymammotion-0.4.0b1}/pymammotion/utility/rocker_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pymammotion
3
- Version: 0.4.0a8
3
+ Version: 0.4.0b1
4
4
  Summary:
5
5
  License: GPL-3.0
6
6
  Author: Michael Arthur
@@ -25,7 +25,7 @@ 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 (==2.1.0)
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
@@ -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
@@ -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: Optional[str] = None
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: Optional[str] = None
27
- description: Optional[str] = None
28
- productImage: Optional[str] = None
29
- categoryImage: Optional[str] = None
30
- productModel: Optional[str] = None
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: Optional[Data]
48
- id: Optional[str] = None
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: Optional[str] = None
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: Optional[str] = None
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 Optional, TypeVar
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: Optional[str] = None
26
- msg: Optional[str] = None
25
+ id: str | None = None
26
+ msg: str | None = None
27
27
 
28
28
  class Config(BaseConfig):
29
29
  omit_default = True
@@ -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: Optional[SessionOauthToken] = None
18
+ data: SessionOauthToken | None = None
@@ -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: List[Camera]
15
+ cameras: list[Camera]
17
16
  channelName: str
18
17
  token: str
19
18
  uid: int
@@ -1,10 +1,7 @@
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
 
@@ -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,9 +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
- )
19
+ from pymammotion.proto import dev_net_pb2
23
20
  from pymammotion.proto.luba_msg import LubaMsg, MsgAttr, MsgCmdType, MsgDevice
24
21
  from pymammotion.utility.constant.device_constant import bleOrderCmd
25
22
 
@@ -656,7 +653,7 @@ class BleMessage:
656
653
  return byteOS.getvalue()
657
654
 
658
655
  @staticmethod
659
- def calc_crc(initial: int, data: Union[bytes, bytearray]) -> int:
656
+ def calc_crc(initial: int, data: bytes | bytearray) -> int:
660
657
  """Calculate CRC value for given initial value and byte array.
661
658
 
662
659
  Args:
@@ -1,6 +1,3 @@
1
- from typing import List
2
-
3
-
4
1
  class Plan:
5
2
  def __init__(self) -> None:
6
3
  self.pver: int = 0
@@ -1,5 +1,4 @@
1
1
  from dataclasses import dataclass, field
2
- from typing import Optional
3
2
 
4
3
  from mashumaro.mixins.orjson import DataClassORJSONMixin
5
4
 
@@ -15,7 +14,7 @@ from pymammotion.proto.mctrl_sys import MctlSys
15
14
 
16
15
  @dataclass
17
16
  class RawMowerData:
18
- raw: Optional[LubaMsg] = field(default_factory=LubaMsg)
17
+ raw: LubaMsg | None = field(default_factory=LubaMsg)
19
18
 
20
19
  @classmethod
21
20
  def from_raw(cls, raw: dict) -> "RawMowerData":
@@ -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
 
@@ -7,14 +6,14 @@ from mashumaro.mixins.orjson import DataClassORJSONMixin
7
6
  @dataclass
8
7
  class RegionData(DataClassORJSONMixin):
9
8
  def __init__(self) -> None:
10
- self.hash: Optional[int] = None
9
+ self.hash: int | None = None
11
10
  self.action: int = 0
12
11
  self.current_frame: int = 0
13
- self.data_hash: Optional[int] = None
12
+ self.data_hash: int | None = None
14
13
  self.data_len: int = 0
15
- self.p_hash_a: Optional[int] = None
16
- self.p_hash_b: Optional[int] = None
17
- self.path: Optional[list[list[float]]] = None
14
+ self.p_hash_a: int | None = None
15
+ self.p_hash_b: int | None = None
16
+ self.path: list[list[float]] | None = None
18
17
  self.pver: int = 0
19
18
  self.result: int = 0
20
19
  self.sub_cmd: int = 0
@@ -72,31 +71,31 @@ class RegionData(DataClassORJSONMixin):
72
71
  def set_current_frame(self, current_frame: int) -> None:
73
72
  self.current_frame = current_frame
74
73
 
75
- def get_path(self) -> Optional[list[list[float]]]:
74
+ def get_path(self) -> list[list[float]] | None:
76
75
  return self.path
77
76
 
78
77
  def set_path(self, path: list[list[float]]) -> None:
79
78
  self.path = path
80
79
 
81
- def get_hash(self) -> Optional[int]:
80
+ def get_hash(self) -> int | None:
82
81
  return self.hash
83
82
 
84
83
  def set_data_hash(self, data_hash: int) -> None:
85
84
  self.data_hash = data_hash
86
85
 
87
- def get_data_hash(self) -> Optional[int]:
86
+ def get_data_hash(self) -> int | None:
88
87
  return self.data_hash
89
88
 
90
89
  def set_p_hash_a(self, p_hash_a: int) -> None:
91
90
  self.p_hash_a = p_hash_a
92
91
 
93
- def get_p_hash_a(self) -> Optional[int]:
92
+ def get_p_hash_a(self) -> int | None:
94
93
  return self.p_hash_a
95
94
 
96
95
  def set_p_hash_b(self, p_hash_b: int) -> None:
97
96
  self.p_hash_b = p_hash_b
98
97
 
99
- def get_p_hash_b(self) -> Optional[int]:
98
+ def get_p_hash_b(self) -> int | None:
100
99
  return self.p_hash_b
101
100
 
102
101
  def __str__(self) -> str:
@@ -116,7 +116,7 @@ Items = Union[
116
116
  @dataclass
117
117
  class Item:
118
118
  time: int
119
- value: Union[int, float, str, dict[str, Any]] # Depending on the type of value
119
+ value: int | float | str | dict[str, Any] # Depending on the type of value
120
120
 
121
121
 
122
122
  @dataclass
@@ -0,0 +1,173 @@
1
+ """Manage state from notifications into MowingDevice."""
2
+
3
+ from collections.abc import Awaitable, Callable
4
+ from datetime import datetime
5
+ import logging
6
+ from typing import Any
7
+
8
+ import betterproto
9
+
10
+ from pymammotion.data.model.device import MowingDevice
11
+ from pymammotion.data.model.device_info import SideLight
12
+ from pymammotion.data.model.hash_list import AreaHashNameList
13
+ from pymammotion.data.mqtt.properties import ThingPropertiesMessage
14
+ from pymammotion.data.mqtt.status import ThingStatusMessage
15
+ from pymammotion.proto.dev_net import DrvDevInfoResp, WifiIotStatusReport
16
+ from pymammotion.proto.luba_msg import LubaMsg
17
+ from pymammotion.proto.mctrl_nav import AppGetAllAreaHashName, NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
18
+ from pymammotion.proto.mctrl_sys import DeviceProductTypeInfoT, TimeCtrlLight
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class StateManager:
24
+ """Manage state."""
25
+
26
+ _device: MowingDevice
27
+ last_updated_at: datetime = datetime.now()
28
+
29
+ def __init__(self, device: MowingDevice) -> None:
30
+ self._device = device
31
+ self.cloud_gethash_ack_callback: Callable[[NavGetHashListAck], Awaitable[None]] | None = None
32
+ self.cloud_get_commondata_ack_callback: Callable[[NavGetCommDataAck | SvgMessageAckT], Awaitable[None]] | None = None
33
+ self.cloud_on_notification_callback: Callable[[tuple[str, Any | None]], Awaitable[None]] | None = None
34
+
35
+ # possibly don't need anymore
36
+ self.cloud_queue_command_callback: Callable[[str, dict[str, Any]], Awaitable[bytes]] | None = None
37
+
38
+ self.ble_gethash_ack_callback: Callable[[NavGetHashListAck], Awaitable[None]] | None = None
39
+ self.ble_get_commondata_ack_callback: Callable[[NavGetCommDataAck | SvgMessageAckT], Awaitable[None]] | None = None
40
+ self.ble_on_notification_callback: Callable[[tuple[str, Any | None]], Awaitable[None]] | None = None
41
+
42
+ # possibly don't need anymore
43
+ self.ble_queue_command_callback: Callable[[str, dict[str, Any]], Awaitable[bytes]] | None = None
44
+ self.last_updated_at = datetime.now()
45
+
46
+ def get_device(self) -> MowingDevice:
47
+ """Get device."""
48
+ return self._device
49
+
50
+ def set_device(self, device: MowingDevice) -> None:
51
+ """Set device."""
52
+ self._device = device
53
+
54
+ async def properties(self, properties: ThingPropertiesMessage) -> None:
55
+ self._device.mqtt_properties = properties
56
+
57
+ async def status(self, status: ThingStatusMessage) -> None:
58
+ if not self._device.online:
59
+ self._device.online = True
60
+ self._device.status_properties = status
61
+
62
+ @property
63
+ def online(self) -> bool:
64
+ return self._device.online
65
+
66
+ @online.setter
67
+ def online(self, value: bool) -> None:
68
+ self._device.online = value
69
+
70
+ async def gethash_ack_callback(self, msg: NavGetHashListAck):
71
+ if self.cloud_gethash_ack_callback:
72
+ await self.cloud_gethash_ack_callback(msg)
73
+ if self.ble_gethash_ack_callback:
74
+ await self.ble_gethash_ack_callback(msg)
75
+
76
+ async def on_notification_callback(self, res: tuple[str, Any | None]):
77
+ if self.cloud_on_notification_callback:
78
+ await self.cloud_on_notification_callback(res)
79
+ if self.ble_on_notification_callback:
80
+ await self.ble_on_notification_callback(res)
81
+
82
+ async def get_commondata_ack_callback(self, comm_data: NavGetCommDataAck | SvgMessageAckT):
83
+ if self.cloud_get_commondata_ack_callback:
84
+ await self.cloud_get_commondata_ack_callback(comm_data)
85
+ if self.ble_get_commondata_ack_callback:
86
+ await self.ble_get_commondata_ack_callback(comm_data)
87
+
88
+ async def notification(self, message: LubaMsg) -> None:
89
+ """Handle protobuf notifications."""
90
+ res = betterproto.which_one_of(message, "LubaSubMsg")
91
+ self.last_updated_at = datetime.now()
92
+
93
+ match res[0]:
94
+ case "nav":
95
+ await self._update_nav_data(message)
96
+ case "sys":
97
+ await self._update_sys_data(message)
98
+ case "driver":
99
+ self._update_driver_data(message)
100
+ case "net":
101
+ self._update_net_data(message)
102
+ case "mul":
103
+ self._update_mul_data(message)
104
+ case "ota":
105
+ self._update_ota_data(message)
106
+
107
+ await self.on_notification_callback(res)
108
+
109
+ async def _update_nav_data(self, message) -> None:
110
+ """Update nav data."""
111
+ nav_msg = betterproto.which_one_of(message.nav, "SubNavMsg")
112
+ match nav_msg[0]:
113
+ case "toapp_gethash_ack":
114
+ hashlist_ack: NavGetHashListAck = nav_msg[1]
115
+ self._device.map.update_root_hash_list(hashlist_ack)
116
+ await self.gethash_ack_callback(nav_msg[1])
117
+ case "toapp_get_commondata_ack":
118
+ common_data: NavGetCommDataAck = nav_msg[1]
119
+ updated = self._device.map.update(common_data)
120
+ if updated:
121
+ await self.get_commondata_ack_callback(common_data)
122
+ case "toapp_svg_msg":
123
+ common_data: SvgMessageAckT = nav_msg[1]
124
+ updated = self._device.map.update(common_data)
125
+ if updated:
126
+ await self.get_commondata_ack_callback(common_data)
127
+
128
+ case "toapp_all_hash_name":
129
+ hash_names: AppGetAllAreaHashName = nav_msg[1]
130
+ converted_list = [AreaHashNameList(name=item.name, hash=item.hash) for item in hash_names.hashnames]
131
+ self._device.map.area_name = converted_list
132
+
133
+ async def _update_sys_data(self, message) -> None:
134
+ """Update system."""
135
+ sys_msg = betterproto.which_one_of(message.sys, "SubSysMsg")
136
+ match sys_msg[0]:
137
+ case "system_update_buf":
138
+ self._device.buffer(sys_msg[1])
139
+ case "toapp_report_data":
140
+ self._device.update_report_data(sys_msg[1])
141
+ case "mow_to_app_info":
142
+ self._device.mow_info(sys_msg[1])
143
+ case "system_tard_state_tunnel":
144
+ self._device.run_state_update(sys_msg[1])
145
+ case "todev_time_ctrl_light":
146
+ ctrl_light: TimeCtrlLight = sys_msg[1]
147
+ side_led: SideLight = SideLight.from_dict(ctrl_light.to_dict(casing=betterproto.Casing.SNAKE))
148
+ self._device.mower_state.side_led = side_led
149
+ case "device_product_type_info":
150
+ device_product_type: DeviceProductTypeInfoT = sys_msg[1]
151
+ self._device.mower_state.model_id = device_product_type.main_product_type
152
+
153
+ def _update_driver_data(self, message) -> None:
154
+ pass
155
+
156
+ def _update_net_data(self, message) -> None:
157
+ net_msg = betterproto.which_one_of(message.net, "NetSubType")
158
+ match net_msg[0]:
159
+ case "toapp_wifi_iot_status":
160
+ wifi_iot_status: WifiIotStatusReport = net_msg[1]
161
+ self._device.mower_state.product_key = wifi_iot_status.productkey
162
+ case "toapp_devinfo_resp":
163
+ toapp_devinfo_resp: DrvDevInfoResp = net_msg[1]
164
+ for resp in toapp_devinfo_resp.resp_ids:
165
+ if resp.res == "DRV_RESULT_SUC":
166
+ self._device.mower_state.swversion = resp.info
167
+ self._device.device_firmwares.device_version = resp.info
168
+
169
+ def _update_mul_data(self, message) -> None:
170
+ pass
171
+
172
+ def _update_ota_data(self, message) -> None:
173
+ pass
@@ -2,7 +2,6 @@ import base64
2
2
  import logging
3
3
  import secrets
4
4
  import string
5
- from typing import Optional
6
5
 
7
6
  from cryptography.hazmat.backends import default_backend
8
7
  from cryptography.hazmat.primitives import padding, serialization
@@ -50,7 +49,7 @@ class EncryptionUtils:
50
49
  private_key_bytes = base64.b64decode(EncryptionUtils.PRIVATE_KEY)
51
50
  return serialization.load_der_private_key(private_key_bytes, password=None, backend=default_backend())
52
51
  except Exception as e:
53
- raise Exception(f"Failed to load private key: {str(e)}")
52
+ raise Exception(f"Failed to load private key: {e!s}")
54
53
 
55
54
  @staticmethod
56
55
  def load_public_key(is_production: bool = True):
@@ -65,7 +64,7 @@ class EncryptionUtils:
65
64
  public_key_bytes = base64.b64decode(key_string)
66
65
  return serialization.load_der_public_key(public_key_bytes, backend=default_backend())
67
66
  except Exception as e:
68
- raise Exception(f"Failed to load public key: {str(e)}")
67
+ raise Exception(f"Failed to load public key: {e!s}")
69
68
 
70
69
  @staticmethod
71
70
  def encrypt(plaintext: str, key: str, iv: str) -> str:
@@ -104,7 +103,7 @@ class EncryptionUtils:
104
103
  return base64.b64encode(encrypted_bytes).decode("utf-8")
105
104
 
106
105
  except Exception as e:
107
- raise Exception(f"Encryption failed: {str(e)}")
106
+ raise Exception(f"Encryption failed: {e!s}")
108
107
 
109
108
  def encryption_by_aes(self, text: str) -> str:
110
109
  """Encrypt text using AES with class-level key and IV
@@ -123,10 +122,10 @@ class EncryptionUtils:
123
122
  return encrypted
124
123
 
125
124
  except Exception as e:
126
- _LOGGER.error(f"Encryption failed: {str(e)}")
125
+ _LOGGER.error(f"Encryption failed: {e!s}")
127
126
  return None
128
127
 
129
- def encrypt_by_public_key(self) -> Optional[str]:
128
+ def encrypt_by_public_key(self) -> str | None:
130
129
  """Encrypt data using RSA public key.
131
130
 
132
131
  Args:
@@ -4,12 +4,7 @@ from typing import cast
4
4
  from aiohttp import ClientSession
5
5
 
6
6
  from pymammotion.aliyun.model.stream_subscription_response import StreamSubscriptionResponse
7
- from pymammotion.const import (
8
- MAMMOTION_API_DOMAIN,
9
- MAMMOTION_CLIENT_ID,
10
- MAMMOTION_CLIENT_SECRET,
11
- MAMMOTION_DOMAIN,
12
- )
7
+ from pymammotion.const import MAMMOTION_API_DOMAIN, MAMMOTION_CLIENT_ID, MAMMOTION_CLIENT_SECRET, MAMMOTION_DOMAIN
13
8
  from pymammotion.http.encryption import EncryptionUtils
14
9
  from pymammotion.http.model.http import ErrorInfo, LoginResponseData, Response
15
10
 
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import Generic, Literal, Optional, TypeVar
2
+ from typing import Generic, Literal, TypeVar
3
3
 
4
4
  from mashumaro import DataClassDictMixin
5
5
  from mashumaro.config import BaseConfig
@@ -83,7 +83,7 @@ class LoginResponseUserInformation(DataClassORJSONMixin):
83
83
  userId: str
84
84
  userAccount: str
85
85
  authType: str
86
- email: Optional[str] = None
86
+ email: str | None = None
87
87
 
88
88
  class Config(BaseConfig):
89
89
  omit_none = True
@@ -1,6 +1,6 @@
1
1
  # === sendOrderMsg_Net ===
2
- import time
3
2
  from abc import ABC
3
+ import time
4
4
 
5
5
  from pymammotion import logger
6
6
  from pymammotion.mammotion.commands.abstract_message import AbstractMessage
@@ -193,7 +193,7 @@ class MessageNetwork(AbstractMessage, ABC):
193
193
  def wifi_connectinfo_update2(self) -> None:
194
194
  hash_map = {"getMsgCmd": 1}
195
195
  # self.post_custom_data(self.get_json_string(
196
- # 68, hash_map)) # ToDo: Fix this
196
+ # 68, hash_map)) # TODO: Fix this
197
197
 
198
198
  def get_record_wifi_list(self) -> bytes:
199
199
  build = DevNet(todev_ble_sync=1, todev__wifi_list_upload=DrvWifiList())
@@ -1,10 +1,11 @@
1
1
  # === sendOrderMsg_Video ===
2
- import time
3
2
  from abc import ABC
3
+ import time
4
4
 
5
5
  from pymammotion.mammotion.commands.abstract_message import AbstractMessage
6
6
  from pymammotion.proto import luba_msg_pb2, luba_mul_pb2
7
7
  from pymammotion.proto.luba_msg import MsgAttr, MsgCmdType, MsgDevice
8
+ from pymammotion.proto.luba_mul import MUL_CAMERA_POSITION
8
9
  from pymammotion.utility.device_type import DeviceType
9
10
 
10
11
 
@@ -25,10 +26,6 @@ class MessageVideo(AbstractMessage, ABC):
25
26
  return luba_msg.SerializeToString()
26
27
 
27
28
  def device_agora_join_channel_with_position(self, enter_state: int):
28
- position = (
29
- luba_mul_pb2.MUL_CAMERA_POSITION.ALL
30
- if DeviceType.is_yuka(self.get_device_name())
31
- else luba_mul_pb2.MUL_CAMERA_POSITION.LEFT
32
- )
29
+ position = MUL_CAMERA_POSITION.ALL if DeviceType.is_yuka(self.get_device_name()) else MUL_CAMERA_POSITION.LEFT
33
30
  mctl_sys = luba_mul_pb2.SocMul(set_video=luba_mul_pb2.MulSetVideo(position=position, vi_switch=enter_state))
34
31
  return self.send_order_msg_video(mctl_sys)
@@ -1,7 +1,7 @@
1
+ from abc import abstractmethod
1
2
  import asyncio
2
3
  import logging
3
- from abc import abstractmethod
4
- from typing import Any, Awaitable, Callable
4
+ from typing import Any
5
5
 
6
6
  import betterproto
7
7
 
@@ -40,17 +40,9 @@ class MammotionBaseDevice:
40
40
  self._state_manager = state_manager
41
41
  self._raw_data = dict()
42
42
  self._raw_mower_data: RawMowerData = RawMowerData()
43
- self._state_manager.gethash_ack_callback = self.datahash_response
44
- self._state_manager.get_commondata_ack_callback = self.commdata_response
45
43
  self._notify_future: asyncio.Future[bytes] | None = None
46
44
  self._cloud_device = cloud_device
47
45
 
48
- def set_notification_callback(self, func: Callable[[tuple[str, Any | None]], Awaitable[None]]) -> None:
49
- self._state_manager.on_notification_callback = func
50
-
51
- def set_queue_callback(self, func: Callable[[str, dict[str, Any]], Awaitable[bytes]]) -> None:
52
- self._state_manager.queue_command_callback = func
53
-
54
46
  async def datahash_response(self, hash_ack: NavGetHashListAck) -> None:
55
47
  """Handle datahash responses."""
56
48
  current_frame = hash_ack.current_frame
@@ -3,8 +3,8 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
- import logging
7
6
  from enum import Enum
7
+ import logging
8
8
  from typing import Any
9
9
 
10
10
  from bleak.backends.device import BLEDevice
@@ -296,7 +296,9 @@ class Mammotion:
296
296
  device = self.get_device_by_name(name)
297
297
  if device.preference is ConnectionPreference.WIFI:
298
298
  if device.has_cloud():
299
- _stream_response = await device.cloud().mqtt.cloud_client.get_stream_subscription(device.cloud().iot_id)
299
+ _stream_response = await device.cloud().mqtt.cloud_client.mammotion_http.get_stream_subscription(
300
+ device.cloud().iot_id
301
+ )
300
302
  _LOGGER.debug(_stream_response)
301
303
  return _stream_response
302
304