pymammotion 0.2.27__tar.gz → 0.2.29__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 (121) hide show
  1. {pymammotion-0.2.27 → pymammotion-0.2.29}/PKG-INFO +1 -1
  2. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/__init__.py +2 -2
  3. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/cloud_gateway.py +32 -16
  4. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/dataclass/dev_by_account_response.py +0 -1
  5. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/dataclass/session_by_authcode_response.py +1 -0
  6. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/bluetooth/ble.py +1 -1
  7. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/account.py +1 -1
  8. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/device.py +10 -5
  9. pymammotion-0.2.29/pymammotion/data/model/device_config.py +80 -0
  10. pymammotion-0.2.29/pymammotion/data/model/generate_route_information.py +27 -0
  11. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/hash_list.py +3 -6
  12. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/location.py +1 -1
  13. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/mowing_modes.py +8 -0
  14. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/mqtt/event.py +7 -2
  15. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/state_manager.py +4 -3
  16. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/http/http.py +10 -0
  17. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/control/joystick.py +1 -0
  18. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/devices/mammotion.py +63 -71
  19. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mqtt/mammotion_future.py +1 -0
  20. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mqtt/mammotion_mqtt.py +6 -9
  21. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/conversions.py +1 -1
  22. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/device_type.py +36 -7
  23. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/movement.py +2 -1
  24. {pymammotion-0.2.27 → pymammotion-0.2.29}/pyproject.toml +3 -3
  25. pymammotion-0.2.27/pymammotion/data/model/device_config.py +0 -9
  26. pymammotion-0.2.27/pymammotion/data/model/generate_route_information.py +0 -133
  27. {pymammotion-0.2.27 → pymammotion-0.2.29}/LICENSE +0 -0
  28. {pymammotion-0.2.27 → pymammotion-0.2.29}/README.md +0 -0
  29. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/__init__.py +0 -0
  30. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/cloud_service.py +0 -0
  31. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/dataclass/aep_response.py +0 -0
  32. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/dataclass/connect_response.py +0 -0
  33. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/dataclass/login_by_oauth_response.py +0 -0
  34. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/dataclass/regions_response.py +0 -0
  35. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/aliyun/tmp_constant.py +0 -0
  36. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/bluetooth/__init__.py +0 -0
  37. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/bluetooth/ble_message.py +0 -0
  38. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/bluetooth/const.py +0 -0
  39. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/bluetooth/data/__init__.py +0 -0
  40. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/bluetooth/data/convert.py +0 -0
  41. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/bluetooth/data/framectrldata.py +0 -0
  42. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/bluetooth/data/notifydata.py +0 -0
  43. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/const.py +0 -0
  44. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/__init__.py +0 -0
  45. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/__init__.py +0 -0
  46. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/enums.py +0 -0
  47. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/excute_boarder_params.py +0 -0
  48. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/execute_boarder.py +0 -0
  49. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/plan.py +0 -0
  50. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/rapid_state.py +0 -0
  51. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/region_data.py +0 -0
  52. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/model/report_info.py +0 -0
  53. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/mqtt/__init__.py +0 -0
  54. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/mqtt/properties.py +0 -0
  55. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/data/mqtt/status.py +0 -0
  56. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/event/__init__.py +0 -0
  57. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/event/event.py +0 -0
  58. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/http/_init_.py +0 -0
  59. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/__init__.py +0 -0
  60. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/__init__.py +0 -0
  61. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/abstract_message.py +0 -0
  62. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/mammotion_command.py +0 -0
  63. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/messages/__init__.py +0 -0
  64. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/messages/driver.py +0 -0
  65. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/messages/media.py +0 -0
  66. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/messages/navigation.py +0 -0
  67. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/messages/network.py +0 -0
  68. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/messages/ota.py +0 -0
  69. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/messages/system.py +0 -0
  70. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/commands/messages/video.py +0 -0
  71. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/control/__init__.py +0 -0
  72. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mammotion/devices/__init__.py +0 -0
  73. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/mqtt/__init__.py +0 -0
  74. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/__init__.py +0 -0
  75. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/basestation.proto +0 -0
  76. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/basestation.py +0 -0
  77. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/basestation_pb2.py +0 -0
  78. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/basestation_pb2.pyi +0 -0
  79. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/common.proto +0 -0
  80. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/common.py +0 -0
  81. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/common_pb2.py +0 -0
  82. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/common_pb2.pyi +0 -0
  83. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/dev_net.proto +0 -0
  84. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/dev_net.py +0 -0
  85. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/dev_net_pb2.py +0 -0
  86. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/dev_net_pb2.pyi +0 -0
  87. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/luba_msg.proto +0 -0
  88. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/luba_msg.py +0 -0
  89. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/luba_msg_pb2.py +0 -0
  90. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/luba_msg_pb2.pyi +0 -0
  91. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/luba_mul.proto +0 -0
  92. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/luba_mul.py +0 -0
  93. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/luba_mul_pb2.py +0 -0
  94. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/luba_mul_pb2.pyi +0 -0
  95. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_driver.proto +0 -0
  96. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_driver.py +0 -0
  97. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_driver_pb2.py +0 -0
  98. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_driver_pb2.pyi +0 -0
  99. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_nav.proto +0 -0
  100. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_nav.py +0 -0
  101. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_nav_pb2.py +0 -0
  102. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_nav_pb2.pyi +0 -0
  103. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_ota.proto +0 -0
  104. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_ota.py +0 -0
  105. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_ota_pb2.py +0 -0
  106. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_ota_pb2.pyi +0 -0
  107. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_pept.proto +0 -0
  108. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_pept.py +0 -0
  109. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_pept_pb2.py +0 -0
  110. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_pept_pb2.pyi +0 -0
  111. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_sys.proto +0 -0
  112. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_sys.py +0 -0
  113. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_sys_pb2.py +0 -0
  114. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/proto/mctrl_sys_pb2.pyi +0 -0
  115. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/py.typed +0 -0
  116. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/constant/__init__.py +0 -0
  117. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/constant/device_constant.py +0 -0
  118. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/datatype_converter.py +0 -0
  119. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/map.py +0 -0
  120. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/periodic.py +0 -0
  121. {pymammotion-0.2.27 → pymammotion-0.2.29}/pymammotion/utility/rocker_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymammotion
3
- Version: 0.2.27
3
+ Version: 0.2.29
4
4
  Summary:
5
5
  License: GNU-3.0
6
6
  Author: Michael Arthur
@@ -9,14 +9,14 @@ import logging
9
9
  import os
10
10
 
11
11
  # works outside HA on its own
12
- from pymammotion.bluetooth.ble import LubaBLE
12
+ from pymammotion.bluetooth.ble import MammotionBLE
13
13
  from pymammotion.http.http import MammotionHTTP, connect_http
14
14
 
15
15
  # TODO make a working device that will work outside HA too.
16
16
  from pymammotion.mammotion.devices import MammotionBaseBLEDevice
17
17
  from pymammotion.mqtt import MammotionMQTT
18
18
 
19
- __all__ = ["LubaBLE", "MammotionHTTP", "connect_http", "MammotionBaseBLEDevice", "MammotionMQTT"]
19
+ __all__ = ["MammotionBLE", "MammotionHTTP", "connect_http", "MammotionBaseBLEDevice", "MammotionMQTT"]
20
20
 
21
21
  logger = logging.getLogger(__name__)
22
22
 
@@ -49,15 +49,19 @@ MOVE_HEADERS = (
49
49
  class SetupException(Exception):
50
50
  pass
51
51
 
52
+
52
53
  class AuthRefreshException(Exception):
53
54
  """Raise exception when library cannot refresh token."""
54
55
 
56
+
55
57
  class DeviceOfflineException(Exception):
56
58
  """Raise exception when device is offline."""
57
59
 
60
+
58
61
  class LoginException(Exception):
59
62
  """Raise exception when library cannot log in."""
60
63
 
64
+
61
65
  class CloudIOTGateway:
62
66
  """Class for interacting with Aliyun Cloud IoT Gateway."""
63
67
 
@@ -72,11 +76,19 @@ class CloudIOTGateway:
72
76
  _devices_by_account_response: ListingDevByAccountResponse | None = None
73
77
  _region_response = None
74
78
 
75
- _iot_token_issued_at : int = None
79
+ _iot_token_issued_at: int = None
76
80
 
77
81
  converter = DatatypeConverter()
78
82
 
79
- def __init__(self, connect_response: ConnectResponse | None = None, login_by_oauth_response: LoginByOAuthResponse | None = None, aep_response: AepResponse | None = None, session_by_authcode_response: SessionByAuthCodeResponse | None = None, region_response: RegionResponse | None = None, dev_by_account: ListingDevByAccountResponse | None = None):
83
+ def __init__(
84
+ self,
85
+ connect_response: ConnectResponse | None = None,
86
+ login_by_oauth_response: LoginByOAuthResponse | None = None,
87
+ aep_response: AepResponse | None = None,
88
+ session_by_authcode_response: SessionByAuthCodeResponse | None = None,
89
+ region_response: RegionResponse | None = None,
90
+ dev_by_account: ListingDevByAccountResponse | None = None,
91
+ ):
80
92
  """Initialize the CloudIOTGateway."""
81
93
  self.mammotion_http: MammotionHTTP | None = None
82
94
  self._app_key = APP_KEY
@@ -376,11 +388,8 @@ class CloudIOTGateway:
376
388
  async with session.post(
377
389
  f"https://{region_url}/api/prd/loginbyoauth.json",
378
390
  headers=headers,
379
- data={
380
- 'loginByOauthRequest': json.dumps(_bodyParam, separators=(",", ":"))
381
- }
391
+ data={"loginByOauthRequest": json.dumps(_bodyParam, separators=(",", ":"))},
382
392
  ) as resp:
383
-
384
393
  data = await resp.json()
385
394
  logger.debug(data)
386
395
  if resp.status == 200:
@@ -441,7 +450,7 @@ class CloudIOTGateway:
441
450
  raise Exception("Error in creating session: " + response_body_str)
442
451
 
443
452
  self._session_by_authcode_response = session_by_auth
444
- self._iot_token_issued_at = int(time.time())
453
+ self._iot_token_issued_at = int(time.time())
445
454
 
446
455
  return response.body
447
456
 
@@ -491,18 +500,23 @@ class CloudIOTGateway:
491
500
  response_body_dict = json.loads(response_body_str)
492
501
 
493
502
  if int(response_body_dict.get("code")) != 200:
494
- raise Exception("Error check or refresh token: " + response_body_dict.get('msg', ''))
503
+ logger.error(response_body_dict)
504
+ raise Exception("Error check or refresh token: " + response_body_dict.__str__())
495
505
 
496
506
  session = SessionByAuthCodeResponse.from_dict(response_body_dict)
497
507
  session_data = session.data
498
508
 
499
- if session_data.identityId is None or session_data.refreshTokenExpire is None or session_data.iotToken is None or session_data.iotTokenExpire is None or session_data.refreshToken is None:
509
+ if (
510
+ session_data.identityId is None
511
+ or session_data.refreshTokenExpire is None
512
+ or session_data.iotToken is None
513
+ or session_data.iotTokenExpire is None
514
+ or session_data.refreshToken is None
515
+ ):
500
516
  raise Exception("Error check or refresh token: Parameters not correct")
501
517
 
502
518
  self._session_by_authcode_response = session
503
- self._iot_token_issued_at = int(time.time())
504
-
505
-
519
+ self._iot_token_issued_at = int(time.time())
506
520
 
507
521
  def list_binding_by_account(self) -> ListingDevByAccountResponse:
508
522
  """List bindings by account."""
@@ -550,14 +564,16 @@ class CloudIOTGateway:
550
564
  """Send a cloud command to the specified IoT device."""
551
565
 
552
566
  """Check if iotToken is expired"""
553
- if self._iot_token_issued_at + self._session_by_authcode_response.data.iotTokenExpire <= (int(time.time()) + (5 * 3600)):
567
+ if self._iot_token_issued_at + self._session_by_authcode_response.data.iotTokenExpire <= (
568
+ int(time.time()) + (5 * 3600)
569
+ ):
554
570
  """Token expired - Try to refresh - Check if refreshToken is not expired"""
555
- if self._iot_token_issued_at + self._session_by_authcode_response.data.refreshTokenExpire > (int(time.time())):
571
+ if self._iot_token_issued_at + self._session_by_authcode_response.data.refreshTokenExpire > (
572
+ int(time.time())
573
+ ):
556
574
  self.check_or_refresh_session()
557
575
  else:
558
576
  raise AuthRefreshException("Refresh token expired. Please re-login")
559
-
560
-
561
577
 
562
578
  config = Config(
563
579
  app_key=self._app_key,
@@ -29,7 +29,6 @@ class Device(DataClassORJSONMixin):
29
29
  categoryImage: Optional[str] = None
30
30
  productModel: Optional[str] = None
31
31
 
32
-
33
32
  class Config(BaseConfig):
34
33
  omit_default = True
35
34
 
@@ -12,6 +12,7 @@ class SessionOauthToken(DataClassORJSONMixin):
12
12
  iotTokenExpire: int
13
13
  refreshToken: str
14
14
 
15
+
15
16
  @dataclass
16
17
  class SessionByAuthCodeResponse(DataClassORJSONMixin):
17
18
  code: int
@@ -11,7 +11,7 @@ from pymammotion.event.event import BleNotificationEvent
11
11
  address = "90:38:0C:6E:EE:9E"
12
12
 
13
13
 
14
- class LubaBLE:
14
+ class MammotionBLE:
15
15
  client: BleakClient
16
16
 
17
17
  def __init__(self, bleEvt: BleNotificationEvent):
@@ -5,4 +5,4 @@ from dataclasses import dataclass
5
5
  class Credentials:
6
6
  email: str = None
7
7
  password: str = None
8
- account_id: str = None
8
+ account_id: str = None
@@ -16,8 +16,13 @@ from pymammotion.proto.mctrl_driver import MctlDriver
16
16
  from pymammotion.proto.mctrl_nav import MctlNav
17
17
  from pymammotion.proto.mctrl_ota import MctlOta
18
18
  from pymammotion.proto.mctrl_pept import MctlPept
19
- from pymammotion.proto.mctrl_sys import MctlSys, MowToAppInfoT, ReportInfoData, SystemUpdateBufMsg, \
20
- SystemRapidStateTunnelMsg
19
+ from pymammotion.proto.mctrl_sys import (
20
+ MctlSys,
21
+ MowToAppInfoT,
22
+ ReportInfoData,
23
+ SystemUpdateBufMsg,
24
+ SystemRapidStateTunnelMsg,
25
+ )
21
26
  from pymammotion.utility.constant import WorkMode
22
27
  from pymammotion.utility.conversions import parse_double
23
28
  from pymammotion.utility.map import CoordinateConverter
@@ -105,9 +110,9 @@ class MowingDevice:
105
110
  parse_double(location.real_pos_y, 4.0), parse_double(location.real_pos_x, 4.0)
106
111
  )
107
112
  if location.zone_hash:
108
- self.location.work_zone = location.zone_hash if self.report_data.dev.sys_status == WorkMode.MODE_WORKING else 0
109
-
110
-
113
+ self.location.work_zone = (
114
+ location.zone_hash if self.report_data.dev.sys_status == WorkMode.MODE_WORKING else 0
115
+ )
111
116
 
112
117
  self.report_data = self.report_data.from_dict(toapp_report_data.to_dict(casing=betterproto.Casing.SNAKE))
113
118
 
@@ -0,0 +1,80 @@
1
+ from dataclasses import dataclass
2
+
3
+ from pymammotion.utility.device_type import DeviceType
4
+
5
+
6
+ @dataclass
7
+ class DeviceLimits:
8
+ blade_height_min: int
9
+ blade_height_max: int
10
+ working_speed_min: float
11
+ working_speed_max: float
12
+
13
+
14
+ @dataclass
15
+ class OperationSettings:
16
+ """Operation settings for a device."""
17
+
18
+ is_mow: bool = True
19
+ is_dump: bool = True
20
+ is_edge: bool = False
21
+ collect_grass_frequency: int = 10
22
+ job_mode: int = 0 # taskMode
23
+ job_version: int = 0
24
+ job_id: int = 0
25
+ speed: float = 0.3
26
+ ultra_wave: int = 2 # touch no touch etc
27
+ channel_mode: int = 0 # line mode is grid single double or single2
28
+ channel_width: int = 25
29
+ rain_tactics: int = 0
30
+ blade_height: int = 0
31
+ path_order: str = ""
32
+ toward: int = 0 # is just angle
33
+ toward_included_angle: int = 0
34
+ toward_mode: int = 0 # angle type relative etc
35
+ border_mode: int = 1 # border laps
36
+ obstacle_laps: int = 1
37
+ start_progress: int = 0
38
+
39
+
40
+ def create_path_order(operation_mode: OperationSettings, device_name: str) -> str:
41
+ i = 8
42
+ bArr = bytearray(8)
43
+ bArr[0] = operation_mode.border_mode
44
+ bArr[1] = operation_mode.obstacle_laps
45
+ bArr[3] = operation_mode.start_progress
46
+ bArr[2] = 0
47
+
48
+ if not DeviceType.is_luba1(device_name):
49
+ bArr[4] = 0
50
+ if DeviceType.is_yuka(device_name):
51
+ i = calculate_yuka_mode(operation_mode)
52
+ elif not DeviceType.is_luba_2(device_name):
53
+ i = 0
54
+ bArr[5] = i
55
+ if operation_mode.is_dump:
56
+ b = operation_mode.collect_grass_frequency
57
+ else:
58
+ b = 10
59
+ bArr[6] = b
60
+ if DeviceType.is_luba1(device_name):
61
+ bArr[4] = operation_mode.toward_mode
62
+ return str(bArr, "UTF-8")
63
+
64
+
65
+ def calculate_yuka_mode(operation_mode: OperationSettings):
66
+ if operation_mode.is_mow and operation_mode.is_dump and operation_mode.is_edge:
67
+ return 14
68
+ if operation_mode.is_mow and operation_mode.is_dump and not operation_mode.is_edge:
69
+ return 12
70
+ if operation_mode.is_mow and not operation_mode.is_dump and operation_mode.is_edge:
71
+ return 10
72
+ if operation_mode.is_mow and not operation_mode.is_dump and not operation_mode.is_edge:
73
+ return 8
74
+ if not operation_mode.is_mow and operation_mode.is_dump and operation_mode.is_edge:
75
+ return 6
76
+ if not operation_mode.is_mow and not operation_mode.is_dump and operation_mode.is_edge:
77
+ return 2
78
+ if not operation_mode.is_mow and operation_mode.is_dump and not operation_mode.is_edge:
79
+ return 4
80
+ return 0
@@ -0,0 +1,27 @@
1
+ import logging
2
+ from dataclasses import dataclass
3
+ from typing import List
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ @dataclass
9
+ class GenerateRouteInformation:
10
+ """Creates a model for generating route information and mowing plan before starting a job."""
11
+
12
+ one_hashs: list[int] = list
13
+ job_mode: int = 0 # taskMode
14
+ job_version: int = 0
15
+ job_id: int = 0
16
+ speed: float = 0.3
17
+ ultra_wave: int = 2 # touch no touch etc
18
+ channel_mode: int = 0 # line mode is grid single double or single2
19
+ channel_width: int = 25
20
+ rain_tactics: int = 0
21
+ blade_height: int = 0
22
+ path_order: str = ""
23
+ toward: int = 0 # is just angle
24
+ toward_included_angle: int = 0
25
+ toward_mode: int = 0 # angle type relative etc
26
+ edge_mode: int = 1 # border laps
27
+ obstacle_laps: int = 1
@@ -6,10 +6,12 @@ from pymammotion.proto.mctrl_nav import NavGetCommDataAck
6
6
 
7
7
  class PathType(IntEnum):
8
8
  """Path types for common data."""
9
+
9
10
  AREA = 0
10
11
  OBSTACLE = 1
11
12
  PATH = 2
12
13
 
14
+
13
15
  @dataclass
14
16
  class FrameList:
15
17
  total_frame: int
@@ -34,7 +36,6 @@ class HashList:
34
36
  self.path = {hash_id: frames for hash_id, frames in self.path.items() if hash_id in hashlist}
35
37
  self.obstacle = {hash_id: frames for hash_id, frames in self.obstacle.items() if hash_id in hashlist}
36
38
 
37
-
38
39
  def missing_frame(self, hash_data: NavGetCommDataAck) -> list[int]:
39
40
  if hash_data.type == PathType.AREA:
40
41
  return self._find_missing_frames(self.area.get(hash_data.hash))
@@ -45,8 +46,6 @@ class HashList:
45
46
  if hash_data.type == PathType.PATH:
46
47
  return self._find_missing_frames(self.path.get(hash_data.hash))
47
48
 
48
-
49
-
50
49
  def update(self, hash_data: NavGetCommDataAck) -> bool:
51
50
  """Update the map data."""
52
51
  if hash_data.type == PathType.AREA:
@@ -58,18 +57,16 @@ class HashList:
58
57
  if hash_data.type == PathType.PATH:
59
58
  return self._add_hash_data(self.path, hash_data)
60
59
 
61
-
62
60
  @staticmethod
63
61
  def _find_missing_frames(frame_list: FrameList) -> list[int]:
64
62
  if frame_list.total_frame == len(frame_list.data):
65
63
  return []
66
- number_list = list(range(1, frame_list.total_frame+1))
64
+ number_list = list(range(1, frame_list.total_frame + 1))
67
65
 
68
66
  current_frames = {frame.current_frame for frame in frame_list.data}
69
67
  missing_numbers = [num for num in number_list if num not in current_frames]
70
68
  return missing_numbers
71
69
 
72
-
73
70
  @staticmethod
74
71
  def _add_hash_data(hash_dict: dict, hash_data: NavGetCommDataAck) -> bool:
75
72
  if hash_dict.get(hash_data.hash) is None:
@@ -30,7 +30,7 @@ class Location:
30
30
  RTK: Point
31
31
  dock: Dock
32
32
  position_type: int = 0
33
- orientation: int = 0 # 360 degree rotation +-
33
+ orientation: int = 0 # 360 degree rotation +-
34
34
  work_zone: int = 0
35
35
 
36
36
  def __init__(self):
@@ -44,3 +44,11 @@ class BypassStrategy(IntEnum):
44
44
  slow_touch = 1
45
45
  less_touch = 2
46
46
  no_touch = 3 # luba 2 yuka only or possibly value of 10
47
+
48
+
49
+ class PathAngleSetting(IntEnum):
50
+ """Path Angle type."""
51
+
52
+ relative_angle = 0
53
+ absolute_angle = 1
54
+ random_angle = 2 # Luba Pro / Luba 2 Yuka only
@@ -45,23 +45,25 @@ class DeviceWarningEventValue(DataClassORJSONMixin):
45
45
  # (see resources/res/values-en-rUS/strings.xml in APK)
46
46
  code: int
47
47
 
48
+
48
49
  @dataclass
49
50
  class DeviceConfigurationRequestValue(DataClassORJSONMixin):
50
51
  code: int
51
52
  bizId: str
52
53
  params: str
53
54
 
55
+
54
56
  @dataclass
55
57
  class DeviceNotificationEventCode(DataClassORJSONMixin):
56
58
  localTime: int
57
59
  code: str
58
60
 
61
+
59
62
  @dataclass
60
63
  class DeviceNotificationEventValue(DataClassORJSONMixin):
61
64
  data: DeviceNotificationEventCode
62
65
 
63
66
 
64
-
65
67
  @dataclass
66
68
  class GeneralParams(DataClassORJSONMixin):
67
69
  groupIdList: list[str]
@@ -100,6 +102,7 @@ class DeviceProtobufMsgEventParams(GeneralParams):
100
102
  type: Literal["info"]
101
103
  value: DeviceProtobufMsgEventValue
102
104
 
105
+
103
106
  @dataclass
104
107
  class DeviceNotificationEventParams(GeneralParams):
105
108
  """Device notification event.
@@ -111,12 +114,14 @@ class DeviceNotificationEventParams(GeneralParams):
111
114
  type: Literal["info"]
112
115
  value: DeviceNotificationEventValue
113
116
 
117
+
114
118
  @dataclass
115
119
  class DeviceWarningEventParams(GeneralParams):
116
120
  identifier: Literal["device_warning_event"]
117
121
  type: Literal["alert"]
118
122
  value: DeviceWarningEventValue
119
123
 
124
+
120
125
  @dataclass
121
126
  class DeviceConfigurationRequestEvent(GeneralParams):
122
127
  type: Literal["info"]
@@ -127,7 +132,7 @@ class DeviceConfigurationRequestEvent(GeneralParams):
127
132
  class ThingEventMessage(DataClassORJSONMixin):
128
133
  method: Literal["thing.events", "thing.properties"]
129
134
  id: str
130
- params: Union[DeviceProtobufMsgEventParams, DeviceWarningEventParams, str]
135
+ params: Union[DeviceProtobufMsgEventParams, DeviceWarningEventParams, dict]
131
136
  version: Literal["1.0"]
132
137
 
133
138
  @classmethod
@@ -1,4 +1,5 @@
1
1
  """Manage state from notifications into MowingDevice."""
2
+
2
3
  from typing import Optional, Callable, Awaitable
3
4
 
4
5
  import betterproto
@@ -15,9 +16,9 @@ class StateManager:
15
16
 
16
17
  def __init__(self, device: MowingDevice):
17
18
  self._device = device
18
- self.gethash_ack_callback: Optional[Callable[[NavGetHashListAck],Awaitable[None]]] = None
19
- self.get_commondata_ack_callback: Optional[Callable[[NavGetCommDataAck],Awaitable[None]]] = None
20
- self.on_notification_callback: Optional[Callable[[],Awaitable[None]]] = None
19
+ self.gethash_ack_callback: Optional[Callable[[NavGetHashListAck], Awaitable[None]]] = None
20
+ self.get_commondata_ack_callback: Optional[Callable[[NavGetCommDataAck], Awaitable[None]]] = None
21
+ self.on_notification_callback: Optional[Callable[[], Awaitable[None]]] = None
21
22
 
22
23
  def get_device(self) -> MowingDevice:
23
24
  """Get device."""
@@ -54,6 +54,16 @@ class MammotionHTTP:
54
54
  self.msg = response.msg
55
55
  self.code = response.code
56
56
 
57
+ async def get_all_error_codes(self):
58
+ async with ClientSession() as session:
59
+ async with session.post(
60
+ "code/record/export-data",
61
+ headers=self._headers,
62
+ ) as resp:
63
+ if resp.status == 200:
64
+ data = await resp.json()
65
+ print(resp)
66
+
57
67
  @classmethod
58
68
  async def login(cls, session: ClientSession, username: str, password: str) -> Response[LoginResponseData]:
59
69
  async with session.post(
@@ -14,6 +14,7 @@ bleNotificationEvt = BleNotificationEvent()
14
14
 
15
15
  nest_asyncio.apply()
16
16
 
17
+
17
18
  class JoystickControl:
18
19
  """Joystick class for controlling Luba with a joystick"""
19
20