pymammotion 0.2.41__tar.gz → 0.2.42__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 (124) hide show
  1. {pymammotion-0.2.41 → pymammotion-0.2.42}/PKG-INFO +1 -1
  2. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/aliyun/cloud_gateway.py +90 -7
  3. {pymammotion-0.2.41/pymammotion/aliyun/dataclass → pymammotion-0.2.42/pymammotion/aliyun/model}/dev_by_account_response.py +1 -1
  4. pymammotion-0.2.42/pymammotion/aliyun/model/stream_subscription_response.py +19 -0
  5. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/bluetooth/ble_message.py +9 -7
  6. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/device.py +10 -0
  7. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/device_config.py +1 -1
  8. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/state_manager.py +7 -1
  9. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/http/http.py +17 -0
  10. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/http/model/http.py +4 -0
  11. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/messages/network.py +15 -15
  12. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/messages/system.py +50 -19
  13. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/devices/base.py +5 -1
  14. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/devices/mammotion.py +31 -25
  15. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/devices/mammotion_bluetooth.py +5 -0
  16. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/devices/mammotion_cloud.py +37 -8
  17. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mqtt/mammotion_mqtt.py +12 -0
  18. {pymammotion-0.2.41 → pymammotion-0.2.42}/pyproject.toml +3 -3
  19. {pymammotion-0.2.41 → pymammotion-0.2.42}/LICENSE +0 -0
  20. {pymammotion-0.2.41 → pymammotion-0.2.42}/README.md +0 -0
  21. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/__init__.py +0 -0
  22. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/aliyun/__init__.py +0 -0
  23. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/aliyun/cloud_service.py +0 -0
  24. {pymammotion-0.2.41/pymammotion/aliyun/dataclass → pymammotion-0.2.42/pymammotion/aliyun/model}/aep_response.py +0 -0
  25. {pymammotion-0.2.41/pymammotion/aliyun/dataclass → pymammotion-0.2.42/pymammotion/aliyun/model}/connect_response.py +0 -0
  26. {pymammotion-0.2.41/pymammotion/aliyun/dataclass → pymammotion-0.2.42/pymammotion/aliyun/model}/login_by_oauth_response.py +0 -0
  27. {pymammotion-0.2.41/pymammotion/aliyun/dataclass → pymammotion-0.2.42/pymammotion/aliyun/model}/regions_response.py +0 -0
  28. {pymammotion-0.2.41/pymammotion/aliyun/dataclass → pymammotion-0.2.42/pymammotion/aliyun/model}/session_by_authcode_response.py +0 -0
  29. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/aliyun/tmp_constant.py +0 -0
  30. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/bluetooth/__init__.py +0 -0
  31. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/bluetooth/ble.py +0 -0
  32. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/bluetooth/const.py +0 -0
  33. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/bluetooth/data/__init__.py +0 -0
  34. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/bluetooth/data/convert.py +0 -0
  35. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/bluetooth/data/framectrldata.py +0 -0
  36. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/bluetooth/data/notifydata.py +0 -0
  37. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/const.py +0 -0
  38. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/__init__.py +0 -0
  39. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/__init__.py +0 -0
  40. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/account.py +0 -0
  41. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/enums.py +0 -0
  42. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/excute_boarder_params.py +0 -0
  43. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/execute_boarder.py +0 -0
  44. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/generate_route_information.py +0 -0
  45. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/hash_list.py +0 -0
  46. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/location.py +0 -0
  47. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/mowing_modes.py +0 -0
  48. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/plan.py +0 -0
  49. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/rapid_state.py +0 -0
  50. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/region_data.py +0 -0
  51. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/model/report_info.py +0 -0
  52. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/mqtt/__init__.py +0 -0
  53. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/mqtt/event.py +0 -0
  54. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/mqtt/properties.py +0 -0
  55. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/data/mqtt/status.py +0 -0
  56. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/event/__init__.py +0 -0
  57. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/event/event.py +0 -0
  58. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/http/_init_.py +0 -0
  59. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/__init__.py +0 -0
  60. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/__init__.py +0 -0
  61. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/abstract_message.py +0 -0
  62. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/mammotion_command.py +0 -0
  63. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/messages/__init__.py +0 -0
  64. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/messages/driver.py +0 -0
  65. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/messages/media.py +0 -0
  66. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/messages/navigation.py +0 -0
  67. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/messages/ota.py +0 -0
  68. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/commands/messages/video.py +0 -0
  69. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/control/__init__.py +0 -0
  70. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/control/joystick.py +0 -0
  71. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mammotion/devices/__init__.py +0 -0
  72. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mqtt/__init__.py +0 -0
  73. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/mqtt/mammotion_future.py +0 -0
  74. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/__init__.py +0 -0
  75. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/basestation.proto +0 -0
  76. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/basestation.py +0 -0
  77. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/basestation_pb2.py +0 -0
  78. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/basestation_pb2.pyi +0 -0
  79. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/common.proto +0 -0
  80. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/common.py +0 -0
  81. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/common_pb2.py +0 -0
  82. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/common_pb2.pyi +0 -0
  83. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/dev_net.proto +0 -0
  84. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/dev_net.py +0 -0
  85. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/dev_net_pb2.py +0 -0
  86. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/dev_net_pb2.pyi +0 -0
  87. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/luba_msg.proto +0 -0
  88. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/luba_msg.py +0 -0
  89. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/luba_msg_pb2.py +0 -0
  90. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/luba_msg_pb2.pyi +0 -0
  91. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/luba_mul.proto +0 -0
  92. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/luba_mul.py +0 -0
  93. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/luba_mul_pb2.py +0 -0
  94. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/luba_mul_pb2.pyi +0 -0
  95. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_driver.proto +0 -0
  96. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_driver.py +0 -0
  97. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_driver_pb2.py +0 -0
  98. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_driver_pb2.pyi +0 -0
  99. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_nav.proto +0 -0
  100. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_nav.py +0 -0
  101. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_nav_pb2.py +0 -0
  102. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_nav_pb2.pyi +0 -0
  103. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_ota.proto +0 -0
  104. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_ota.py +0 -0
  105. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_ota_pb2.py +0 -0
  106. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_ota_pb2.pyi +0 -0
  107. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_pept.proto +0 -0
  108. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_pept.py +0 -0
  109. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_pept_pb2.py +0 -0
  110. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_pept_pb2.pyi +0 -0
  111. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_sys.proto +0 -0
  112. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_sys.py +0 -0
  113. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_sys_pb2.py +0 -0
  114. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/proto/mctrl_sys_pb2.pyi +0 -0
  115. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/py.typed +0 -0
  116. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/utility/constant/__init__.py +0 -0
  117. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/utility/constant/device_constant.py +0 -0
  118. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/utility/conversions.py +0 -0
  119. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/utility/datatype_converter.py +0 -0
  120. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/utility/device_type.py +0 -0
  121. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/utility/map.py +0 -0
  122. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/utility/movement.py +0 -0
  123. {pymammotion-0.2.41 → pymammotion-0.2.42}/pymammotion/utility/periodic.py +0 -0
  124. {pymammotion-0.2.41 → pymammotion-0.2.42}/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.41
3
+ Version: 0.2.42
4
4
  Summary:
5
5
  License: GNU-3.0
6
6
  Author: Michael Arthur
@@ -17,14 +17,14 @@ from alibabacloud_iot_api_gateway.models import CommonParams, Config, IoTApiRequ
17
17
  from alibabacloud_tea_util.client import Client as UtilClient
18
18
  from alibabacloud_tea_util.models import RuntimeOptions
19
19
 
20
- from pymammotion.aliyun.dataclass.aep_response import AepResponse
21
- from pymammotion.aliyun.dataclass.connect_response import ConnectResponse
22
- from pymammotion.aliyun.dataclass.dev_by_account_response import (
20
+ from pymammotion.aliyun.model.aep_response import AepResponse
21
+ from pymammotion.aliyun.model.connect_response import ConnectResponse
22
+ from pymammotion.aliyun.model.dev_by_account_response import (
23
23
  ListingDevByAccountResponse,
24
24
  )
25
- from pymammotion.aliyun.dataclass.login_by_oauth_response import LoginByOAuthResponse
26
- from pymammotion.aliyun.dataclass.regions_response import RegionResponse
27
- from pymammotion.aliyun.dataclass.session_by_authcode_response import (
25
+ from pymammotion.aliyun.model.login_by_oauth_response import LoginByOAuthResponse
26
+ from pymammotion.aliyun.model.regions_response import RegionResponse
27
+ from pymammotion.aliyun.model.session_by_authcode_response import (
28
28
  SessionByAuthCodeResponse,
29
29
  )
30
30
  from pymammotion.const import ALIYUN_DOMAIN, APP_KEY, APP_SECRET, APP_VERSION
@@ -436,6 +436,49 @@ class CloudIOTGateway:
436
436
 
437
437
  return response.body
438
438
 
439
+ def sign_out(self) -> None:
440
+ config = Config(
441
+ app_key=self._app_key,
442
+ app_secret=self._app_secret,
443
+ domain=self._region_response.data.apiGatewayEndpoint,
444
+ )
445
+ client = Client(config)
446
+
447
+ # build request
448
+ request = CommonParams(api_ver="1.0.4", language="en-US")
449
+ body = IoTApiRequest(
450
+ id=str(uuid.uuid4()),
451
+ params={
452
+ "request": {
453
+ "refreshToken": self._session_by_authcode_response.data.refreshToken,
454
+ "identityId": self._session_by_authcode_response.data.identityId,
455
+ }
456
+ },
457
+ request=request,
458
+ version="1.0",
459
+ )
460
+
461
+ # send request
462
+ # possibly need to do this ourselves
463
+ response = client.do_request(
464
+ "/iotx/account/invalidSession",
465
+ "https",
466
+ "POST",
467
+ None,
468
+ body,
469
+ RuntimeOptions(),
470
+ )
471
+ logger.debug(response.status_message)
472
+ logger.debug(response.headers)
473
+ logger.debug(response.status_code)
474
+ logger.debug(response.body)
475
+
476
+ # Decode the response body
477
+ response_body_str = response.body.decode("utf-8")
478
+
479
+ # Load the JSON string into a dictionary
480
+ response_body_dict = json.loads(response_body_str)
481
+
439
482
  def check_or_refresh_session(self):
440
483
  """Check or refresh the session."""
441
484
  logger.debug("Try to refresh token")
@@ -542,6 +585,47 @@ class CloudIOTGateway:
542
585
  self._devices_by_account_response = ListingDevByAccountResponse.from_dict(response_body_dict)
543
586
  return self._devices_by_account_response
544
587
 
588
+ def list_binding_by_dev(self, iot_id: str):
589
+ config = Config(
590
+ app_key=self._app_key,
591
+ app_secret=self._app_secret,
592
+ domain=self._region_response.data.apiGatewayEndpoint,
593
+ )
594
+
595
+ client = Client(config)
596
+
597
+ # build request
598
+ request = CommonParams(
599
+ api_ver="1.0.8",
600
+ language="en-US",
601
+ iot_token=self._session_by_authcode_response.data.iotToken,
602
+ )
603
+ body = IoTApiRequest(
604
+ id=str(uuid.uuid4()),
605
+ params={"pageSize": 100, "pageNo": 1, "iotId": iot_id},
606
+ request=request,
607
+ version="1.0",
608
+ )
609
+
610
+ # send request
611
+ response = client.do_request("/uc/listBindingByDev", "https", "POST", None, body, RuntimeOptions())
612
+ logger.debug(response.status_message)
613
+ logger.debug(response.headers)
614
+ logger.debug(response.status_code)
615
+ logger.debug(response.body)
616
+
617
+ # Decode the response body
618
+ response_body_str = response.body.decode("utf-8")
619
+
620
+ # Load the JSON string into a dictionary
621
+ response_body_dict = json.loads(response_body_str)
622
+
623
+ if int(response_body_dict.get("code")) != 200:
624
+ raise Exception("Error in creating session: " + response_body_dict["msg"])
625
+
626
+ self._devices_by_account_response = ListingDevByAccountResponse.from_dict(response_body_dict)
627
+ return self._devices_by_account_response
628
+
545
629
  def send_cloud_command(self, iot_id: str, command: bytes) -> str:
546
630
  """Send a cloud command to the specified IoT device."""
547
631
 
@@ -587,7 +671,6 @@ class CloudIOTGateway:
587
671
  version="1.0",
588
672
  )
589
673
  logger.debug(self.converter.printBase64Binary(command))
590
-
591
674
  # send request
592
675
  response = client.do_request("/thing/service/invoke", "https", "POST", None, body, RuntimeOptions())
593
676
  logger.debug(response.status_message)
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import List, Optional
2
+ from typing import Optional
3
3
 
4
4
  from mashumaro.config import BaseConfig
5
5
  from mashumaro.mixins.orjson import DataClassORJSONMixin
@@ -0,0 +1,19 @@
1
+ from dataclasses import dataclass
2
+ from typing import List
3
+
4
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
5
+
6
+
7
+ @dataclass
8
+ class Camera(DataClassORJSONMixin):
9
+ cameraId: int
10
+ token: str
11
+
12
+
13
+ @dataclass
14
+ class StreamSubscriptionResponse(DataClassORJSONMixin):
15
+ appid: str
16
+ cameras: List[Camera]
17
+ channelName: str
18
+ token: str
19
+ uid: int
@@ -16,7 +16,6 @@ from pymammotion.bluetooth.data.convert import parse_custom_data
16
16
  from pymammotion.bluetooth.data.framectrldata import FrameCtrlData
17
17
  from pymammotion.bluetooth.data.notifydata import BlufiNotifyData
18
18
  from pymammotion.data.model.execute_boarder import ExecuteBorder
19
- from pymammotion.mammotion.commands.messages.navigation import MessageNavigation
20
19
  from pymammotion.proto import (
21
20
  dev_net_pb2,
22
21
  luba_msg_pb2,
@@ -49,7 +48,6 @@ class BleMessage:
49
48
  mReadSequence: iter
50
49
  mAck: queue
51
50
  notification: BlufiNotifyData
52
- messageNavigation: MessageNavigation = MessageNavigation()
53
51
 
54
52
  def __init__(self, client: BleakClient) -> None:
55
53
  self.client = client
@@ -123,9 +121,9 @@ class BleMessage:
123
121
 
124
122
  async def requestDeviceStatus(self) -> None:
125
123
  request = False
126
- type = self.messageNavigation.getTypeValue(0, 5)
124
+ type = self.getTypeValue(0, 5)
127
125
  try:
128
- request = await self.messageNavigation.post(BleMessage.mEncrypted, BleMessage.mChecksum, False, type, None)
126
+ request = await self.post(BleMessage.mEncrypted, BleMessage.mChecksum, False, type, None)
129
127
  # _LOGGER.debug(request)
130
128
  except Exception as err:
131
129
  # Log.w(TAG, "post requestDeviceStatus interrupted")
@@ -137,9 +135,9 @@ class BleMessage:
137
135
 
138
136
  async def requestDeviceVersion(self) -> None:
139
137
  request = False
140
- type = self.messageNavigation.getTypeValue(0, 7)
138
+ type = self.getTypeValue(0, 7)
141
139
  try:
142
- request = await self.messageNavigation.post(BleMessage.mEncrypted, BleMessage.mChecksum, False, type, None)
140
+ request = await self.post(BleMessage.mEncrypted, BleMessage.mChecksum, False, type, None)
143
141
  # _LOGGER.debug(request)
144
142
  except Exception as err:
145
143
  # Log.w(TAG, "post requestDeviceStatus interrupted")
@@ -147,7 +145,7 @@ class BleMessage:
147
145
  _LOGGER.error(err)
148
146
 
149
147
  async def sendBorderPackage(self, executeBorder: ExecuteBorder) -> None:
150
- await self.messageNavigation.post_custom_data(serialize(executeBorder))
148
+ await self.post_custom_data(serialize(executeBorder))
151
149
 
152
150
  async def gatt_write(self, data: bytes) -> None:
153
151
  await self.client.write_gatt_char(UUID_WRITE_CHARACTERISTIC, data, True)
@@ -340,6 +338,10 @@ class BleMessage:
340
338
  # onPostCustomDataResult(status, data)
341
339
  except Exception as err:
342
340
  _LOGGER.debug(err)
341
+ # we might be constantly connected and in a bad state
342
+ self.mSendSequence = itertools.count()
343
+ self.mReadSequence = itertools.count()
344
+ await self.client.disconnect()
343
345
 
344
346
  async def post(
345
347
  self,
@@ -112,7 +112,17 @@ class MowingDevice(DataClassORJSONMixin):
112
112
  self.report_data = self.report_data.from_dict(toapp_report_data.to_dict(casing=betterproto.Casing.SNAKE))
113
113
 
114
114
  def run_state_update(self, rapid_state: SystemRapidStateTunnelMsg) -> None:
115
+ coordinate_converter = CoordinateConverter(self.location.RTK.latitude, self.location.RTK.longitude)
115
116
  self.mowing_state = RapidState().from_raw(rapid_state.rapid_state_data)
117
+ self.location.position_type = self.mowing_state.pos_type
118
+ self.location.orientation = self.mowing_state.toward / 10000
119
+ self.location.device = coordinate_converter.enu_to_lla(
120
+ parse_double(self.mowing_state.pos_y, 4.0), parse_double(self.mowing_state.pos_x, 4.0)
121
+ )
122
+ if self.mowing_state.zone_hash:
123
+ self.location.work_zone = (
124
+ self.mowing_state.zone_hash if self.report_data.dev.sys_status == WorkMode.MODE_WORKING else 0
125
+ )
116
126
 
117
127
  def mow_info(self, toapp_mow_info: MowToAppInfoT) -> None:
118
128
  pass
@@ -8,7 +8,7 @@ from pymammotion.utility.device_type import DeviceType
8
8
  @dataclass
9
9
  class DeviceLimits(DataClassORJSONMixin):
10
10
  blade_height_min: int = 30
11
- blade_height_max: int = 70
11
+ blade_height_max: int = 100
12
12
  working_speed_min: float = 0.2
13
13
  working_speed_max: float = 1.2
14
14
  working_path_min: int = 15
@@ -1,5 +1,6 @@
1
1
  """Manage state from notifications into MowingDevice."""
2
2
 
3
+ from datetime import datetime
3
4
  from typing import Any, Awaitable, Callable, Optional
4
5
 
5
6
  import betterproto
@@ -8,12 +9,14 @@ from pymammotion.data.model.device import MowingDevice
8
9
  from pymammotion.data.model.hash_list import AreaHashNameList
9
10
  from pymammotion.proto.luba_msg import LubaMsg
10
11
  from pymammotion.proto.mctrl_nav import AppGetAllAreaHashName, NavGetCommDataAck, NavGetHashListAck
12
+ from pymammotion.utility.constant import WorkMode
11
13
 
12
14
 
13
15
  class StateManager:
14
16
  """Manage state."""
15
17
 
16
18
  _device: MowingDevice
19
+ last_updated_at: datetime = datetime.now()
17
20
 
18
21
  def __init__(self, device: MowingDevice) -> None:
19
22
  self._device = device
@@ -21,6 +24,7 @@ class StateManager:
21
24
  self.get_commondata_ack_callback: Optional[Callable[[NavGetCommDataAck], Awaitable[None]]] = None
22
25
  self.on_notification_callback: Optional[Callable[[], Awaitable[None]]] = None
23
26
  self.queue_command_callback: Optional[Callable[[str, dict[str, Any]], Awaitable[bytes]]] = None
27
+ self.last_updated_at = datetime.now()
24
28
 
25
29
  def get_device(self) -> MowingDevice:
26
30
  """Get device."""
@@ -33,6 +37,7 @@ class StateManager:
33
37
  async def notification(self, message: LubaMsg) -> None:
34
38
  """Handle protobuf notifications."""
35
39
  res = betterproto.which_one_of(message, "LubaSubMsg")
40
+ self.last_updated_at = datetime.now()
36
41
 
37
42
  match res[0]:
38
43
  case "nav":
@@ -78,7 +83,8 @@ class StateManager:
78
83
  case "toapp_report_data":
79
84
  self._device.update_report_data(sys_msg[1])
80
85
  if self.queue_command_callback:
81
- await self.queue_command_callback("get_report_cfg", stop=True)
86
+ if self._device.sys.toapp_report_data.dev.sys_status != WorkMode.MODE_WORKING:
87
+ await self.queue_command_callback("get_report_cfg_stop")
82
88
  case "mow_to_app_info":
83
89
  self._device.mow_info(sys_msg[1])
84
90
  case "system_tard_state_tunnel":
@@ -3,6 +3,7 @@ from typing import cast
3
3
 
4
4
  from aiohttp import ClientSession
5
5
 
6
+ from pymammotion.aliyun.model.stream_subscription_response import StreamSubscriptionResponse
6
7
  from pymammotion.const import (
7
8
  MAMMOTION_API_DOMAIN,
8
9
  MAMMOTION_CLIENT_ID,
@@ -43,6 +44,22 @@ class MammotionHTTP:
43
44
  data = await resp.json()
44
45
  response = Response.from_dict(data)
45
46
 
47
+ async def get_stream_subscription(self, iot_id: str) -> Response[StreamSubscriptionResponse]:
48
+ """Get agora.io data for view camera stream"""
49
+ async with ClientSession(MAMMOTION_API_DOMAIN) as session:
50
+ async with session.post(
51
+ "/device-server/v1/stream/subscription",
52
+ json={"deviceId": iot_id},
53
+ headers={
54
+ "Authorization": f"{self._headers.get('Authorization', "")}",
55
+ "Content-Type": "application/json",
56
+ },
57
+ ) as resp:
58
+ data = await resp.json()
59
+ # TODO catch errors from mismatch like token expire etc
60
+ # Assuming the data format matches the expected structure
61
+ return Response[StreamSubscriptionResponse].from_dict(data)
62
+
46
63
  @classmethod
47
64
  async def login(cls, session: ClientSession, username: str, password: str) -> Response[LoginResponseData]:
48
65
  async with session.post(
@@ -2,6 +2,7 @@ from dataclasses import dataclass
2
2
  from typing import Generic, Literal, Optional, TypeVar
3
3
 
4
4
  from mashumaro import DataClassDictMixin
5
+ from mashumaro.config import BaseConfig
5
6
  from mashumaro.mixins.orjson import DataClassORJSONMixin
6
7
 
7
8
  DataT = TypeVar("DataT")
@@ -51,6 +52,9 @@ class Response(DataClassDictMixin, Generic[DataT]):
51
52
  msg: str
52
53
  data: DataT | None = None
53
54
 
55
+ class Config(BaseConfig):
56
+ omit_default = True
57
+
54
58
 
55
59
  @dataclass
56
60
  class LoginResponseUserInformation(DataClassORJSONMixin):
@@ -1,5 +1,5 @@
1
1
  # === sendOrderMsg_Net ===
2
-
2
+ from pymammotion import logger
3
3
  from pymammotion.mammotion.commands.messages.navigation import MessageNavigation
4
4
  from pymammotion.proto import dev_net_pb2, luba_msg_pb2
5
5
 
@@ -34,12 +34,12 @@ class MessageNetwork:
34
34
 
35
35
  def get_4g_module_info(self) -> bytes:
36
36
  build = dev_net_pb2.DevNet(todev_get_mnet_cfg_req=dev_net_pb2.DevNet().todev_get_mnet_cfg_req)
37
- print("Send command -- Get device 4G network module information")
37
+ logger.debug("Send command -- Get device 4G network module information")
38
38
  return self.send_order_msg_net(build)
39
39
 
40
40
  def get_4g_info(self) -> bytes:
41
41
  build = dev_net_pb2.DevNet(todev_mnet_info_req=dev_net_pb2.DevNet().todev_mnet_info_req)
42
- print("Send command -- Get device 4G network information")
42
+ logger.debug("Send command -- Get device 4G network information")
43
43
  return self.send_order_msg_net(build)
44
44
 
45
45
  def set_zmq_enable(self) -> bytes:
@@ -50,12 +50,12 @@ class MessageNetwork:
50
50
  tx_zmq_url="tcp://0.0.0.0:5555",
51
51
  )
52
52
  )
53
- print("Send command -- Set vision ZMQ to enable")
53
+ logger.debug("Send command -- Set vision ZMQ to enable")
54
54
  return self.send_order_msg_net(build)
55
55
 
56
56
  def set_iot_setting(self, iot_control_type: dev_net_pb2.iot_conctrl_type) -> bytes:
57
57
  build = dev_net_pb2.DevNet(todev_set_iot_offline_req=iot_control_type)
58
- print("Send command -- Device re-online")
58
+ logger.debug("Send command -- Device re-online")
59
59
  return self.send_order_msg_net(build)
60
60
 
61
61
  def set_device_log_upload(
@@ -75,7 +75,7 @@ class MessageNetwork:
75
75
  num=number,
76
76
  type=type,
77
77
  )
78
- print(
78
+ logger.debug(
79
79
  f"Send log====Feedback====Command======requestID:{request_id} operation:{operation} serverIp:{server_ip} type:{type}"
80
80
  )
81
81
  return self.send_order_msg_net(dev_net_pb2.DevNet(todev_ble_sync=1, todev_uploadfile_req=build))
@@ -98,7 +98,7 @@ class MessageNetwork:
98
98
  num=number,
99
99
  type=type,
100
100
  )
101
- print(
101
+ logger.debug(
102
102
  f"Send log====Feedback====Command======requestID:{request_id} operation:{operation} serverIp:{server_ip} type:{type}"
103
103
  )
104
104
  return self.send_order_msg_net(dev_net_pb2.DevNet(todev_ble_sync=1, todev_uploadfile_req=build))
@@ -126,7 +126,7 @@ class MessageNetwork:
126
126
 
127
127
  def get_device_network_info(self) -> bytes:
128
128
  build = dev_net_pb2.DevNet(todev_networkinfo_req=dev_net_pb2.GetNetworkInfoReq(req_ids=1))
129
- print("Send command - get device network information")
129
+ logger.debug("Send command - get device network information")
130
130
  return self.send_order_msg_net(build)
131
131
 
132
132
  def set_device_4g_enable_status(self, new_4g_status: bool) -> bytes:
@@ -141,7 +141,7 @@ class MessageNetwork:
141
141
  ),
142
142
  )
143
143
 
144
- print(f"Send command - set 4G (on/off status). newWifiStatus={new_4g_status}")
144
+ logger.debug(f"Send command - set 4G (on/off status). newWifiStatus={new_4g_status}")
145
145
  return self.send_order_msg_net(build)
146
146
 
147
147
  def set_device_wifi_enable_status(self, new_wifi_status: bool) -> bytes:
@@ -149,11 +149,11 @@ class MessageNetwork:
149
149
  todev_ble_sync=1,
150
150
  todev_Wifi_Configuration=dev_net_pb2.DrvWifiSet(configParam=4, wifi_enable=new_wifi_status),
151
151
  )
152
- print(f"szNetwork: Send command - set network (on/off status). newWifiStatus={new_wifi_status}")
152
+ logger.debug(f"szNetwork: Send command - set network (on/off status). newWifiStatus={new_wifi_status}")
153
153
  return self.send_order_msg_net(build)
154
154
 
155
155
  def wifi_connectinfo_update(self, device_name: str, is_binary: bool) -> bytes:
156
- print(
156
+ logger.debug(
157
157
  f"Send command - get Wifi connection information.wifiConnectinfoUpdate().deviceName={device_name}.isBinary={is_binary}"
158
158
  )
159
159
  if is_binary:
@@ -161,7 +161,7 @@ class MessageNetwork:
161
161
  todev_ble_sync=1,
162
162
  todev_WifiMsgUpload=dev_net_pb2.DrvWifiUpload(wifi_msg_upload=1),
163
163
  )
164
- print("Send command - get Wifi connection information")
164
+ logger.debug("Send command - get Wifi connection information")
165
165
  return self.send_order_msg_net(build)
166
166
  self.wifi_connectinfo_update2()
167
167
 
@@ -171,10 +171,10 @@ class MessageNetwork:
171
171
  # 68, hash_map)) # ToDo: Fix this
172
172
 
173
173
  def get_record_wifi_list(self, is_binary: bool) -> bytes:
174
- print(f"getRecordWifiList().isBinary={is_binary}")
174
+ logger.debug(f"getRecordWifiList().isBinary={is_binary}")
175
175
  if is_binary:
176
176
  build = dev_net_pb2.DevNet(todev_ble_sync=1, todev_WifiListUpload=dev_net_pb2.DrvWifiList())
177
- print("Send command - get memorized WiFi list upload command")
177
+ logger.debug("Send command - get memorized WiFi list upload command")
178
178
  return self.send_order_msg_net(build)
179
179
  self.get_record_wifi_list2()
180
180
 
@@ -189,7 +189,7 @@ class MessageNetwork:
189
189
  todev_ble_sync=1,
190
190
  todev_Wifi_Configuration=dev_net_pb2.DrvWifiSet(configParam=status, Confssid=ssid),
191
191
  )
192
- print(
192
+ logger.debug(
193
193
  f"Send command - set network (disconnect, direct connect, forget, no operation reconnect) operation command (downlink ssid={ssid}, status={status})"
194
194
  )
195
195
  return self.send_order_msg_net(build)
@@ -2,6 +2,7 @@
2
2
  import datetime
3
3
  from abc import ABC
4
4
 
5
+ from pymammotion import logger
5
6
  from pymammotion.mammotion.commands.abstract_message import AbstractMessage
6
7
  from pymammotion.mammotion.commands.messages.navigation import MessageNavigation
7
8
  from pymammotion.proto.luba_msg import LubaMsg, MsgAttr, MsgCmdType, MsgDevice
@@ -36,7 +37,7 @@ class MessageSystem(AbstractMessage, ABC):
36
37
 
37
38
  def reset_system(self):
38
39
  build = MctlSys(todev_reset_system=1)
39
- print("Send command - send factory reset")
40
+ logger.debug("Send command - send factory reset")
40
41
  return self.send_order_msg_sys(build)
41
42
 
42
43
  def set_blade_control(self, on_off: int):
@@ -72,24 +73,24 @@ class MessageSystem(AbstractMessage, ABC):
72
73
  end_hour=0,
73
74
  end_min=0,
74
75
  )
75
- print(f"Send read and write sidelight command is_sidelight:{
76
+ logger.debug(f"Send read and write sidelight command is_sidelight:{
76
77
  is_sidelight}, operate:{operate}")
77
78
  build2 = MctlSys(todev_time_ctrl_light=build)
78
- print(f"Send command - send read and write sidelight command is_sidelight:{
79
+ logger.debug(f"Send command - send read and write sidelight command is_sidelight:{
79
80
  is_sidelight}, operate:{operate}, timeCtrlLight:{build}")
80
81
  return self.send_order_msg_sys(build2)
81
82
 
82
83
  def test_tool_order_to_sys(self, sub_cmd: int, param_id: int, param_value: list[int]):
83
84
  build = MCtrlSimulationCmdData(sub_cmd=sub_cmd, param_id=param_id, param_value=param_value)
84
- print(f"Send tool test command: subCmd={sub_cmd}, param_id:{
85
+ logger.debug(f"Send tool test command: subCmd={sub_cmd}, param_id:{
85
86
  param_id}, param_value={param_value}")
86
87
  build2 = MctlSys(simulation_cmd=build)
87
- print(f"Send tool test command: subCmd={sub_cmd}, param_id:{
88
+ logger.debug(f"Send tool test command: subCmd={sub_cmd}, param_id:{
88
89
  param_id}, param_value={param_value}")
89
90
  return self.send_order_msg_sys(build2)
90
91
 
91
- def read_and_set_rtk_paring_code(self, op: int, cgf: str):
92
- print(f"Send read and write base station configuration quality op:{
92
+ def read_and_set_rtk_paring_code(self, op: int, cgf: str | None = None):
93
+ logger.debug(f"Send read and write base station configuration quality op:{
93
94
  op}, cgf:{cgf}")
94
95
  return self.send_order_msg_sys(MctlSys(todev_lora_cfg_req=LoraCfgReq(op=op, cfg=cgf)))
95
96
 
@@ -98,7 +99,7 @@ class MessageSystem(AbstractMessage, ABC):
98
99
  self.messageNavigation.allpowerfull_rw_adapter_x3(id, context, rw)
99
100
  return
100
101
  build = MctlSys(bidire_comm_cmd=SysCommCmd(id=id, context=context, rw=rw))
101
- print(f"Send command - 9 general read and write command id={id}, context={context}, rw={rw}")
102
+ logger.debug(f"Send command - 9 general read and write command id={id}, context={context}, rw={rw}")
102
103
  if id == 5:
103
104
  # This logic doesnt make snese, but its what they had so..
104
105
  return self.send_order_msg_sys(build)
@@ -107,7 +108,7 @@ class MessageSystem(AbstractMessage, ABC):
107
108
  # Commented out as not needed and too many refs to try fix up
108
109
  # def factory_test_order(self, test_id: int, test_duration: int, expect: str):
109
110
  # new_builder = mow_to_app_qctools_info_t.Builder()
110
- # print(f"Factory tool print, expect={expect}")
111
+ # logger.debug(f"Factory tool logger.debug, expect={expect}")
111
112
  # if not expect:
112
113
  # build = new_builder.set_type_value(
113
114
  # test_id).set_time_of_duration(test_duration).build()
@@ -157,11 +158,11 @@ class MessageSystem(AbstractMessage, ABC):
157
158
  # else:
158
159
  # build = new_builder.set_type_value(
159
160
  # test_id).set_time_of_duration(test_duration).build()
160
- # print(f"Factory tool print, mow_to_app_qctools_info_t={
161
+ # logger.debug(f"Factory tool logger.debug, mow_to_app_qctools_info_t={
161
162
  # build.except_count}, mow_to_app_qctools_info_t22={build.except_list}")
162
163
  # build2 = MctlSys(mow_to_app_qctools_info=build)
163
- # print(f"Send command - factory tool test command testId={
164
- # test_id}, testDuration={test_duration}", "Factory tool print222", True)
164
+ # logger.debug(f"Send command - factory tool test command testId={
165
+ # test_id}, testDuration={test_duration}", "Factory tool logger.debug222", True)
165
166
  # return self.send_order_msg_sys(build2)
166
167
 
167
168
  def send_sys_set_date_time(self):
@@ -175,7 +176,7 @@ class MessageSystem(AbstractMessage, ABC):
175
176
  i7 = calendar.second
176
177
  i8 = calendar.utcoffset().total_seconds() // 60 if calendar.utcoffset() else 0
177
178
  i9 = 1 if calendar.dst() else 0
178
- print(f"Print time zone, time zone={
179
+ logger.debug(f"Print time zone, time zone={
179
180
  i8}, daylight saving time={i9} week={i4}")
180
181
  build = MctlSys(
181
182
  todev_data_time=SysSetDateTime(
@@ -190,7 +191,7 @@ class MessageSystem(AbstractMessage, ABC):
190
191
  daylight=i9,
191
192
  )
192
193
  )
193
- print(
194
+ logger.debug(
194
195
  f"Send command - synchronize time zone={i8}, daylight saving time={i9} week={i4}, day:{
195
196
  i3}, month:{i2}, hours:{i5}, minutes:{i6}, seconds:{i7}, year={i}",
196
197
  "Time synchronization",
@@ -222,16 +223,46 @@ class MessageSystem(AbstractMessage, ABC):
222
223
  count=count,
223
224
  )
224
225
  )
225
- print(f"Send command==== IOT slim data Act {
226
+ logger.debug(f"Send command==== IOT slim data Act {
226
227
  build.todev_report_cfg.act} {build}")
227
228
  return self.send_order_msg_sys(build)
228
229
 
229
- def get_report_cfg(
230
- self, timeout: int = 10000, period: int = 1000, no_change_period: int = 2000, stop: bool = False
231
- ):
230
+ def get_report_cfg_stop(self, timeout: int = 10000, period: int = 1000, no_change_period: int = 1000):
232
231
  mctlsys = MctlSys(
233
232
  todev_report_cfg=ReportInfoCfg(
234
- act=RptAct.RPT_STOP if stop else RptAct.RPT_START,
233
+ act=RptAct.RPT_STOP,
234
+ timeout=timeout,
235
+ period=period,
236
+ no_change_period=no_change_period,
237
+ count=1,
238
+ )
239
+ )
240
+
241
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_CONNECT)
242
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_RTK)
243
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_DEV_LOCAL)
244
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_WORK)
245
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_DEV_STA)
246
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_MAINTAIN)
247
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_VISION_POINT)
248
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_VIO)
249
+ mctlsys.todev_report_cfg.sub.append(RptInfoType.RIT_VISION_STATISTIC)
250
+
251
+ lubaMsg = LubaMsg()
252
+ lubaMsg.msgtype = MsgCmdType.MSG_CMD_TYPE_EMBED_SYS
253
+ lubaMsg.sender = MsgDevice.DEV_MOBILEAPP
254
+ lubaMsg.rcver = MsgDevice.DEV_MAINCTL
255
+ lubaMsg.msgattr = MsgAttr.MSG_ATTR_REQ
256
+ lubaMsg.seqs = 1
257
+ lubaMsg.version = 1
258
+ lubaMsg.subtype = 1
259
+ lubaMsg.sys = mctlsys
260
+ return lubaMsg.SerializeToString()
261
+
262
+ def get_report_cfg(self, timeout: int = 10000, period: int = 1000, no_change_period: int = 2000):
263
+ mctlsys = MctlSys(
264
+ todev_report_cfg=ReportInfoCfg(
265
+ act=RptAct.RPT_START,
235
266
  timeout=timeout,
236
267
  period=period,
237
268
  no_change_period=no_change_period,
@@ -5,7 +5,7 @@ from typing import Any, Awaitable, Callable
5
5
 
6
6
  import betterproto
7
7
 
8
- from pymammotion.aliyun.dataclass.dev_by_account_response import Device
8
+ from pymammotion.aliyun.model.dev_by_account_response import Device
9
9
  from pymammotion.data.model import RegionData
10
10
  from pymammotion.data.model.device import MowingDevice
11
11
  from pymammotion.data.state_manager import StateManager
@@ -190,6 +190,10 @@ class MammotionBaseDevice:
190
190
  async def _ble_sync(self):
191
191
  """Send ble sync command every 3 seconds or sooner."""
192
192
 
193
+ @abstractmethod
194
+ def stop(self):
195
+ """Stop everything ready for destroying."""
196
+
193
197
  async def start_sync(self, retry: int) -> None:
194
198
  """Start synchronization with the device."""
195
199
  await self.queue_command("get_device_base_info")