pymammotion 0.5.44__tar.gz → 0.5.49__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.

Potentially problematic release.


This version of pymammotion might be problematic. Click here for more details.

Files changed (152) hide show
  1. {pymammotion-0.5.44 → pymammotion-0.5.49}/PKG-INFO +2 -2
  2. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/model/dev_by_account_response.py +32 -62
  3. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/hash_list.py +3 -1
  4. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/homeassistant/mower_api.py +17 -6
  5. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/homeassistant/rtk_api.py +16 -16
  6. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/http/http.py +8 -2
  7. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/mammotion.py +16 -7
  8. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/mower_device.py +8 -5
  9. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/__init__.py +2 -2
  10. pymammotion-0.5.49/pymammotion/proto/mctrl_sys_pb2.py +206 -0
  11. {pymammotion-0.5.44 → pymammotion-0.5.49}/pyproject.toml +14 -14
  12. pymammotion-0.5.44/pymammotion/proto/mctrl_sys_pb2.py +0 -206
  13. {pymammotion-0.5.44 → pymammotion-0.5.49}/.gitignore +0 -0
  14. {pymammotion-0.5.44 → pymammotion-0.5.49}/LICENSE +0 -0
  15. {pymammotion-0.5.44 → pymammotion-0.5.49}/README.md +0 -0
  16. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/__init__.py +0 -0
  17. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/__init__.py +0 -0
  18. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/client.py +0 -0
  19. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/cloud_gateway.py +0 -0
  20. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/model/aep_response.py +0 -0
  21. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/model/connect_response.py +0 -0
  22. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/model/login_by_oauth_response.py +0 -0
  23. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/model/regions_response.py +0 -0
  24. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/model/session_by_authcode_response.py +0 -0
  25. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/model/thing_response.py +0 -0
  26. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/regions.py +0 -0
  27. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/tea/core.py +0 -0
  28. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/aliyun/tmp_constant.py +0 -0
  29. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/__init__.py +0 -0
  30. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/ble.py +0 -0
  31. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/ble_message.py +0 -0
  32. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/const.py +0 -0
  33. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/data/__init__.py +0 -0
  34. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/data/convert.py +0 -0
  35. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/data/framectrldata.py +0 -0
  36. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/data/notifydata.py +0 -0
  37. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/model/__init__.py +0 -0
  38. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/bluetooth/model/atomic_integer.py +0 -0
  39. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/const.py +0 -0
  40. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/__init__.py +0 -0
  41. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/__init__.py +0 -0
  42. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/account.py +0 -0
  43. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/device.py +0 -0
  44. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/device_config.py +0 -0
  45. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/device_info.py +0 -0
  46. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/device_limits.py +0 -0
  47. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/enums.py +0 -0
  48. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/errors.py +0 -0
  49. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/excute_boarder_params.py +0 -0
  50. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/execute_boarder.py +0 -0
  51. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/generate_route_information.py +0 -0
  52. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/location.py +0 -0
  53. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/mowing_modes.py +0 -0
  54. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/rapid_state.py +0 -0
  55. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/raw_data.py +0 -0
  56. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/region_data.py +0 -0
  57. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/report_info.py +0 -0
  58. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/model/work.py +0 -0
  59. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/mower_state_manager.py +0 -0
  60. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/mqtt/__init__.py +0 -0
  61. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/mqtt/event.py +0 -0
  62. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/mqtt/mammotion_properties.py +0 -0
  63. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/mqtt/properties.py +0 -0
  64. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/data/mqtt/status.py +0 -0
  65. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/event/__init__.py +0 -0
  66. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/event/event.py +0 -0
  67. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/homeassistant/__init__.py +0 -0
  68. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/http/__init__.py +0 -0
  69. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/http/encryption.py +0 -0
  70. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/http/model/__init__.py +0 -0
  71. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/http/model/camera_stream.py +0 -0
  72. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/http/model/http.py +0 -0
  73. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/http/model/response_factory.py +0 -0
  74. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/http/model/rtk.py +0 -0
  75. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/__init__.py +0 -0
  76. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/__init__.py +0 -0
  77. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/abstract_message.py +0 -0
  78. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/mammotion_command.py +0 -0
  79. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/__init__.py +0 -0
  80. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/basestation.py +0 -0
  81. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/driver.py +0 -0
  82. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/media.py +0 -0
  83. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/navigation.py +0 -0
  84. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/network.py +0 -0
  85. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/ota.py +0 -0
  86. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/system.py +0 -0
  87. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/commands/messages/video.py +0 -0
  88. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/control/__init__.py +0 -0
  89. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/control/joystick.py +0 -0
  90. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/__init__.py +0 -0
  91. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/base.py +0 -0
  92. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/mammotion_bluetooth.py +0 -0
  93. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/mammotion_cloud.py +0 -0
  94. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/mammotion_mower_ble.py +0 -0
  95. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/mammotion_mower_cloud.py +0 -0
  96. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/managers/managers.py +0 -0
  97. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/mower_manager.py +0 -0
  98. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/rtk_ble.py +0 -0
  99. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/rtk_cloud.py +0 -0
  100. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/rtk_device.py +0 -0
  101. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mammotion/devices/rtk_manager.py +0 -0
  102. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mqtt/__init__.py +0 -0
  103. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mqtt/aliyun_mqtt.py +0 -0
  104. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mqtt/linkkit/__init__.py +0 -0
  105. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mqtt/linkkit/h2client.py +0 -0
  106. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mqtt/linkkit/linkkit.py +0 -0
  107. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mqtt/mammotion_future.py +0 -0
  108. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mqtt/mammotion_mqtt.py +0 -0
  109. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/mqtt/mqtt_models.py +0 -0
  110. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/basestation.proto +0 -0
  111. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/basestation_pb2.py +0 -0
  112. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/basestation_pb2.pyi +0 -0
  113. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/common.proto +0 -0
  114. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/common_pb2.py +0 -0
  115. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/common_pb2.pyi +0 -0
  116. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/dev_net.proto +0 -0
  117. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/dev_net_pb2.py +0 -0
  118. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/dev_net_pb2.pyi +0 -0
  119. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/luba_msg.proto +0 -0
  120. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/luba_msg_pb2.py +0 -0
  121. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/luba_msg_pb2.pyi +0 -0
  122. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/luba_mul.proto +0 -0
  123. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/luba_mul_pb2.py +0 -0
  124. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/luba_mul_pb2.pyi +0 -0
  125. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_driver.proto +0 -0
  126. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_driver_pb2.py +0 -0
  127. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_driver_pb2.pyi +0 -0
  128. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_nav.proto +0 -0
  129. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_nav_pb2.py +0 -0
  130. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_nav_pb2.pyi +0 -0
  131. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_ota.proto +0 -0
  132. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_ota_pb2.py +0 -0
  133. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_ota_pb2.pyi +0 -0
  134. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_pept.proto +0 -0
  135. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_pept_pb2.py +0 -0
  136. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_pept_pb2.pyi +0 -0
  137. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_sys.proto +0 -0
  138. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/mctrl_sys_pb2.pyi +0 -0
  139. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/message_pool.py +0 -0
  140. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/proto/py.typed +0 -0
  141. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/py.typed +0 -0
  142. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/constant/__init__.py +0 -0
  143. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/constant/device_constant.py +0 -0
  144. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/conversions.py +0 -0
  145. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/datatype_converter.py +0 -0
  146. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/device_config.py +0 -0
  147. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/device_type.py +0 -0
  148. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/map.py +0 -0
  149. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/movement.py +0 -0
  150. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/mur_mur_hash.py +0 -0
  151. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/periodic.py +0 -0
  152. {pymammotion-0.5.44 → pymammotion-0.5.49}/pymammotion/utility/rocker_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymammotion
3
- Version: 0.5.44
3
+ Version: 0.5.49
4
4
  Author: jLynx
5
5
  Author-email: Michael Arthur <michael@jumblesoft.co.nz>
6
6
  License-Expression: GPL-3.0
@@ -11,7 +11,7 @@ Requires-Dist: alibabacloud-apigateway-util<0.0.3,>=0.0.2
11
11
  Requires-Dist: alibabacloud-iot-api-gateway<0.0.5,>=0.0.4
12
12
  Requires-Dist: alicloud-gateway-iot<2,>=1.0.0
13
13
  Requires-Dist: async-timeout<5,>=4.0.3
14
- Requires-Dist: betterproto2<0.9,>=0.8.0
14
+ Requires-Dist: betterproto2>=0.9.1
15
15
  Requires-Dist: bleak-retry-connector>=3.5.0
16
16
  Requires-Dist: bleak>=0.21.0
17
17
  Requires-Dist: crcmod~=1.7
@@ -1,7 +1,9 @@
1
1
  from dataclasses import dataclass
2
+ from typing import Annotated, Optional
2
3
 
3
4
  from mashumaro.config import BaseConfig
4
5
  from mashumaro.mixins.orjson import DataClassORJSONMixin
6
+ from mashumaro.types import Alias
5
7
 
6
8
 
7
9
  @dataclass
@@ -9,79 +11,47 @@ class Device(DataClassORJSONMixin):
9
11
  """Unified device model supporting both Device and ShareNotification data"""
10
12
 
11
13
  # Core device fields (from Device model)
12
- gmt_modified: int
13
- node_type: str
14
- device_name: str
15
- product_name: str
14
+ gmt_modified: Annotated[int, Alias("gmtModified")]
15
+ node_type: Annotated[str, Alias("nodeType")]
16
+ device_name: Annotated[str, Alias("deviceName")]
17
+ product_name: Annotated[str, Alias("productName")]
16
18
  status: int
17
- identity_id: str
19
+ identity_id: Annotated[str, Alias("identityId")]
18
20
 
19
21
  # Required fields from original Device model
20
- net_type: str
21
- category_key: str
22
- product_key: str
23
- is_edge_gateway: bool
24
- category_name: str
25
- identity_alias: str
26
- iot_id: str
27
- bind_time: int
22
+ net_type: Annotated[str, Alias("netType")]
23
+ category_key: Annotated[str, Alias("categoryKey")]
24
+ product_key: Annotated[str, Alias("productKey")]
25
+ is_edge_gateway: Annotated[bool, Alias("isEdgeGateway")]
26
+ category_name: Annotated[str, Alias("categoryName")]
27
+ identity_alias: Annotated[str, Alias("identityAlias")]
28
+ iot_id: Annotated[str, Alias("iotId")]
29
+ bind_time: Annotated[int, Alias("bindTime")]
28
30
  owned: int
29
- thing_type: str
31
+ thing_type: Annotated[str, Alias("thingType")]
30
32
 
31
33
  # Optional fields (common to both or nullable)
32
- nick_name: str | None = None
33
- description: str | None = None
34
- product_image: str | None = None
35
- category_image: str | None = None
36
- product_model: str | None = None
34
+ nick_name: Annotated[Optional[str], Alias("nickName")] = None
35
+ description: Optional[str] = None
36
+ product_image: Annotated[Optional[str], Alias("productImage")] = None
37
+ category_image: Annotated[Optional[str], Alias("categoryImage")] = None
38
+ product_model: Annotated[Optional[str], Alias("productModel")] = None
37
39
 
38
40
  # Optional fields from ShareNotification only
39
- target_id: str | None = None
40
- receiver_identity_id: str | None = None
41
- target_type: str | None = None
42
- gmt_create: int | None = None
43
- batch_id: str | None = None
44
- record_id: str | None = None
45
- initiator_identity_id: str | None = None
46
- is_receiver: int | None = None
47
- initiator_alias: str | None = None
48
- receiver_alias: str | None = None
41
+ target_id: Annotated[Optional[str], Alias("targetId")] = None
42
+ receiver_identity_id: Annotated[Optional[str], Alias("receiverIdentityId")] = None
43
+ target_type: Annotated[Optional[str], Alias("targetType")] = None
44
+ gmt_create: Annotated[Optional[int], Alias("gmtCreate")] = None
45
+ batch_id: Annotated[Optional[str], Alias("batchId")] = None
46
+ record_id: Annotated[Optional[str], Alias("recordId")] = None
47
+ initiator_identity_id: Annotated[Optional[str], Alias("initiatorIdentityId")] = None
48
+ is_receiver: Annotated[Optional[int], Alias("isReceiver")] = None
49
+ initiator_alias: Annotated[Optional[str], Alias("initiatorAlias")] = None
50
+ receiver_alias: Annotated[Optional[str], Alias("receiverAlias")] = None
49
51
 
50
52
  class Config(BaseConfig):
51
53
  omit_default = True
52
- serialize_by_alias = True
53
- aliases = {
54
- # Original Device model aliases
55
- "gmt_modified": "gmtModified",
56
- "net_type": "netType",
57
- "category_key": "categoryKey",
58
- "product_key": "productKey",
59
- "node_type": "nodeType",
60
- "is_edge_gateway": "isEdgeGateway",
61
- "device_name": "deviceName",
62
- "category_name": "categoryName",
63
- "identity_alias": "identityAlias",
64
- "product_name": "productName",
65
- "iot_id": "iotId",
66
- "bind_time": "bindTime",
67
- "identity_id": "identityId",
68
- "thing_type": "thingType",
69
- "nick_name": "nickName",
70
- "product_image": "productImage",
71
- "category_image": "categoryImage",
72
- "product_model": "productModel",
73
- # ShareNotification specific aliases
74
- "target_id": "targetId",
75
- "receiver_identity_id": "receiverIdentityId",
76
- "target_type": "targetType",
77
- "gmt_create": "gmtCreate",
78
- "batch_id": "batchId",
79
- "record_id": "recordId",
80
- "initiator_identity_id": "initiatorIdentityId",
81
- "is_receiver": "isReceiver",
82
- "initiator_alias": "initiatorAlias",
83
- "receiver_alias": "receiverAlias",
84
- }
54
+ allow_deserialization_not_by_alias = True
85
55
 
86
56
 
87
57
  # # Alternative: Keep them separate but with a common base class
@@ -440,4 +440,6 @@ class HashList(DataClassORJSONMixin):
440
440
 
441
441
  def invalidate_maps(self, bol_hash: int) -> None:
442
442
  if MurMurHashUtil.hash_unsigned_list(self.hashlist) != bol_hash:
443
- self.root_hash_lists = []
443
+ pass
444
+
445
+ # self.root_hash_lists = []
@@ -27,12 +27,14 @@ class HomeAssistantMowerApi:
27
27
  """API for interacting with Mammotion Mowers for Home Assistant."""
28
28
 
29
29
  def __init__(self) -> None:
30
+ self._plan_lock = asyncio.Lock()
30
31
  self.update_failures = 0
31
32
  self._mammotion = Mammotion()
32
33
  self._map_lock = asyncio.Lock()
33
34
  self._last_call_times: dict[str, datetime] = {}
34
35
  self._call_intervals = {
35
- "check_maps": timedelta(minutes=1),
36
+ "check_maps": timedelta(minutes=5),
37
+ "read_plan": timedelta(minutes=30),
36
38
  "read_settings": timedelta(minutes=5),
37
39
  "get_errors": timedelta(minutes=1),
38
40
  "get_report_cfg": timedelta(seconds=5),
@@ -81,10 +83,19 @@ class HomeAssistantMowerApi:
81
83
  self._map_lock.release()
82
84
 
83
85
  # Check maps periodically
84
- if self._should_call_api("check_maps"):
86
+ if self._should_call_api("check_maps") and not self._map_lock.locked():
85
87
  await self._map_lock.acquire()
86
88
  await self.mammotion.start_map_sync(device_name)
87
89
  self._mark_api_called("check_maps")
90
+ return device.state
91
+
92
+ if self._should_call_api("read_plan"):
93
+ if len(device.state.map.plan) == 0 or list(device.state.map.plan.values())[0].total_plan_num != len(
94
+ device.state.map.plan
95
+ ):
96
+ await self.async_send_command(device_name, "read_plan", sub_cmd=2, plan_index=0)
97
+ self._mark_api_called("read_plan")
98
+ return device.state
88
99
 
89
100
  # Read settings less frequently
90
101
  if self._should_call_api("read_settings"):
@@ -195,8 +206,8 @@ class HomeAssistantMowerApi:
195
206
 
196
207
  def is_online(self, device_name: str) -> bool:
197
208
  if device := self.mammotion.get_device_by_name(device_name):
198
- ble = device.ble
199
- return device.state.online or ble is not None and ble.client.is_connected
209
+ if ble := device.ble:
210
+ return device.state.online or ble is not None and ble.client.is_connected
200
211
  return False
201
212
 
202
213
  async def update_firmware(self, device_name: str, version: str) -> None:
@@ -242,7 +253,7 @@ class HomeAssistantMowerApi:
242
253
  async def async_set_sidelight(self, device_name: str, on_off: int) -> None:
243
254
  """Set Sidelight."""
244
255
  await self.async_send_command(device_name, "read_and_set_sidelight", is_sidelight=bool(on_off), operate=0)
245
- await self.async_read_sidelight()
256
+ await self.async_read_sidelight(device_name)
246
257
 
247
258
  async def async_read_sidelight(self, device_name: str) -> None:
248
259
  """Set Sidelight."""
@@ -414,7 +425,7 @@ class HomeAssistantMowerApi:
414
425
  device = self.mammotion.get_device_by_name(device_name)
415
426
 
416
427
  if work := device.state.work:
417
- operation_settings.areas = work.zone_hashs
428
+ operation_settings.areas = set(work.zone_hashs)
418
429
  operation_settings.toward = work.toward
419
430
  operation_settings.toward_mode = work.toward_mode
420
431
  operation_settings.toward_included_angle = work.toward_included_angle
@@ -20,22 +20,22 @@ class HomeAssistantRTKApi:
20
20
  try:
21
21
  response = await device.cloud_client.get_device_properties(device.iot_id)
22
22
  if response.code == 200:
23
- data = response.data
24
- if ota_progress := data.otaProgress:
25
- device.update_check = CheckDeviceVersion.from_dict(ota_progress.value)
26
- if network_info := data.networkInfo:
27
- network = json.loads(network_info.value)
28
- device.state.wifi_rssi = network["wifi_rssi"]
29
- device.state.wifi_sta_mac = network["wifi_sta_mac"]
30
- device.state.bt_mac = network["bt_mac"]
31
- if coordinate := data.coordinate:
32
- coord_val = json.loads(coordinate.value)
33
- if device.state.lat == 0:
34
- device.state.lat = coord_val["lat"]
35
- if device.state.lon == 0:
36
- device.state.lon = coord_val["lon"]
37
- if device_version := data.deviceVersion:
38
- device.state.device_version = device_version.value
23
+ if data := response.data:
24
+ if ota_progress := data.otaProgress:
25
+ device.state.update_check = CheckDeviceVersion.from_dict(ota_progress.value)
26
+ if network_info := data.networkInfo:
27
+ network = json.loads(network_info.value)
28
+ device.state.wifi_rssi = network["wifi_rssi"]
29
+ device.state.wifi_sta_mac = network["wifi_sta_mac"]
30
+ device.state.bt_mac = network["bt_mac"]
31
+ if coordinate := data.coordinate:
32
+ coord_val = json.loads(coordinate.value)
33
+ if device.state.lat == 0:
34
+ device.state.lat = coord_val["lat"]
35
+ if device.state.lon == 0:
36
+ device.state.lon = coord_val["lon"]
37
+ if device_version := data.deviceVersion:
38
+ device.state.device_version = device_version.value
39
39
  device.state.online = True
40
40
 
41
41
  ota_info = await device.cloud_client.mammotion_http.get_device_ota_firmware([device.state.iot_id])
@@ -129,7 +129,7 @@ class MammotionHTTP:
129
129
  self._response: Response | None = None
130
130
  self.login_info: LoginResponseData | None = None
131
131
  self.jwt_info: JWTTokenInfo = JWTTokenInfo("", "")
132
- self._headers = {"User-Agent": "okhttp/4.9.3", "App-Version": "Home Assistant,1.14.2.29"}
132
+ self._headers = {"User-Agent": "okhttp/4.9.3", "App-Version": "Home Assistant,1.15.6.14"}
133
133
  self.encryption_utils = EncryptionUtils()
134
134
 
135
135
  # Add this method to generate a 10-digit random number
@@ -383,6 +383,8 @@ class MammotionHTTP:
383
383
  "Authorization": f"Bearer {self.login_info.access_token}",
384
384
  "Content-Type": "application/json",
385
385
  "User-Agent": "okhttp/4.9.3",
386
+ "Client-Id": self.client_id,
387
+ "Client-Type": "1",
386
388
  },
387
389
  ) as resp:
388
390
  data = await resp.json()
@@ -402,6 +404,8 @@ class MammotionHTTP:
402
404
  "Authorization": f"Bearer {self.login_info.access_token}",
403
405
  "Content-Type": "application/json",
404
406
  "User-Agent": "okhttp/4.9.3",
407
+ "Client-Id": self.client_id,
408
+ "Client-Type": "1",
405
409
  },
406
410
  ) as resp:
407
411
  data = await resp.json()
@@ -428,7 +432,7 @@ class MammotionHTTP:
428
432
 
429
433
  @refresh_token_decorator
430
434
  async def get_user_device_list(self) -> Response[list[DeviceInfo]]:
431
- """Fetches device list for a user (owned)."""
435
+ """Fetches device list for a user (owned not shared, shared returns nothing)."""
432
436
  async with ClientSession(MAMMOTION_API_DOMAIN) as session:
433
437
  async with session.get(
434
438
  "/device-server/v1/device/list",
@@ -437,6 +441,8 @@ class MammotionHTTP:
437
441
  "Authorization": f"Bearer {self.login_info.access_token}",
438
442
  "Content-Type": "application/json",
439
443
  "User-Agent": "okhttp/4.9.3",
444
+ "Client-Id": self.client_id,
445
+ "Client-Type": "1",
440
446
  },
441
447
  ) as resp:
442
448
  resp_dict = await resp.json()
@@ -186,8 +186,7 @@ class Mammotion:
186
186
 
187
187
  await mammotion_http.refresh_login()
188
188
 
189
- if len(mammotion_http.device_info) != 0:
190
- await self.connect_iot(exists_aliyun.cloud_client)
189
+ await self.connect_iot(exists_aliyun.cloud_client)
191
190
  if len(mammotion_http.device_records.records) != 0:
192
191
  await mammotion_http.get_mqtt_credentials()
193
192
 
@@ -272,7 +271,7 @@ class Mammotion:
272
271
  if mqtt.is_connected():
273
272
  await loop.run_in_executor(None, mqtt.disconnect)
274
273
 
275
- if len(mammotion_http.device_info) != 0:
274
+ if len(cloud_client.devices_by_account_response.data.data) != 0:
276
275
  mammotion_cloud = MammotionCloud(
277
276
  AliyunMQTT(
278
277
  region_id=cloud_client.region_response.data.regionId,
@@ -416,8 +415,7 @@ class Mammotion:
416
415
  _LOGGER.debug("device_list: %s", device_list)
417
416
  await mammotion_http.get_mqtt_credentials()
418
417
  cloud_client = CloudIOTGateway(mammotion_http)
419
- if len(device_list.data or []) != 0:
420
- await self.connect_iot(cloud_client)
418
+ await self.connect_iot(cloud_client)
421
419
  return cloud_client
422
420
 
423
421
  @staticmethod
@@ -484,12 +482,12 @@ class Mammotion:
484
482
  if device:
485
483
  if device.preference is ConnectionPreference.BLUETOOTH and device.ble:
486
484
  return await device.ble.command(key, **kwargs)
487
- if device.preference is ConnectionPreference.WIFI:
485
+ if device.preference is ConnectionPreference.WIFI and device.cloud:
488
486
  return await device.cloud.command(key, **kwargs)
489
487
  # TODO work with both with EITHER
490
488
  return None
491
489
 
492
- async def start_map_sync(self, name: str):
490
+ async def start_map_sync(self, name: str) -> None:
493
491
  """Start map sync."""
494
492
  device = self.get_device_by_name(name)
495
493
  if device:
@@ -500,6 +498,17 @@ class Mammotion:
500
498
  # TODO work with both with EITHER
501
499
  return None
502
500
 
501
+ async def start_schedule_sync(self, name: str) -> None:
502
+ """Start map sync."""
503
+ device = self.get_device_by_name(name)
504
+ if device:
505
+ if device.preference is ConnectionPreference.BLUETOOTH and device.ble:
506
+ return await device.ble.start_schedule_sync()
507
+ if device.preference is ConnectionPreference.WIFI and device.cloud:
508
+ return await device.cloud.start_schedule_sync()
509
+ # TODO work with both with EITHER
510
+ return None
511
+
503
512
  async def get_stream_subscription(self, name: str, iot_id: str) -> Response[StreamSubscriptionResponse] | Any:
504
513
  """Get stream subscription."""
505
514
  device = self.get_device_by_name(name)
@@ -87,6 +87,13 @@ class MammotionMowerDevice(MammotionBaseDevice, ABC):
87
87
  index = plan.plan_index + 1
88
88
  await self.queue_command("read_plan", sub_cmd=2, plan_index=index)
89
89
 
90
+ async def start_schedule_sync(self) -> None:
91
+ """Start sync of schedule data."""
92
+ if len(self.mower.map.plan) == 0 or list(self.mower.map.plan.values())[0].total_plan_num != len(
93
+ self.mower.map.plan
94
+ ):
95
+ await self.queue_command("read_plan", sub_cmd=2, plan_index=0)
96
+
90
97
  async def start_map_sync(self) -> None:
91
98
  """Start sync of map data."""
92
99
  if location := next((loc for loc in self.mower.report_data.locations if loc.pos_type == 5), None):
@@ -94,17 +101,13 @@ class MammotionMowerDevice(MammotionBaseDevice, ABC):
94
101
 
95
102
  await self.queue_command("send_todev_ble_sync", sync_type=3)
96
103
 
104
+ # TODO correctly check if area names exist for a zone.
97
105
  if self._cloud_device and len(self.mower.map.area_name) == 0 and not DeviceType.is_luba1(self.mower.name):
98
106
  await self.queue_command("get_area_name_list", device_id=self._cloud_device.iot_id)
99
107
 
100
108
  if len(self.mower.map.root_hash_lists) == 0 or len(self.mower.map.missing_hashlist()) > 0:
101
109
  await self.queue_command("get_all_boundary_hash_list", sub_cmd=0)
102
110
 
103
- if len(self.mower.map.plan) == 0 or list(self.mower.map.plan.values())[0].total_plan_num != len(
104
- self.mower.map.plan
105
- ):
106
- await self.queue_command("read_plan", sub_cmd=2, plan_index=0)
107
-
108
111
  for hash_id, frame in list(self.mower.map.area.items()):
109
112
  missing_frames = self.mower.map.find_missing_frames(frame)
110
113
  if len(missing_frames) > 0:
@@ -267,7 +267,7 @@ import betterproto2
267
267
 
268
268
  from .message_pool import default_message_pool
269
269
 
270
- _COMPILER_VERSION = "0.8.0"
270
+ _COMPILER_VERSION = "0.9.0"
271
271
  betterproto2.check_compiler_version(_COMPILER_VERSION)
272
272
 
273
273
 
@@ -1899,7 +1899,7 @@ class LoraCfgRsp(betterproto2.Message):
1899
1899
 
1900
1900
  cfg: "str" = betterproto2.field(3, betterproto2.TYPE_STRING)
1901
1901
 
1902
- fac_cfg: "str" = betterproto2.field(4, betterproto2.TYPE_STRING)
1902
+ fac_cfg: "bytes" = betterproto2.field(4, betterproto2.TYPE_BYTES)
1903
1903
 
1904
1904
 
1905
1905
  default_message_pool.register_message("", "LoraCfgRsp", LoraCfgRsp)