pymammotion 0.2.8__py3-none-any.whl → 0.2.9__py3-none-any.whl

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.

@@ -71,7 +71,7 @@ class CloudIOTGateway:
71
71
 
72
72
  converter = DatatypeConverter()
73
73
 
74
- def __init__(self, connect_response: ConnectResponse | None, login_by_oauth_response: LoginByOAuthResponse | None, aep_response: AepResponse | None, session_by_authcode_response: SessionByAuthCodeResponse | None, region_response: RegionResponse | None, dev_by_account: ListingDevByAccountResponse | None):
74
+ 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):
75
75
  """Initialize the CloudIOTGateway."""
76
76
  self._app_key = APP_KEY
77
77
  self._app_secret = APP_SECRET
@@ -235,7 +235,7 @@ class Mammotion(object):
235
235
  return
236
236
 
237
237
  self.cloud_client = cloud_client
238
- self.mqtt = MammotionMQTT(region_id=cloud_client._region.data.regionId,
238
+ self.mqtt = MammotionMQTT(region_id=cloud_client._region_response.data.regionId,
239
239
  product_key=cloud_client._aep_response.data.productKey,
240
240
  device_name=cloud_client._aep_response.data.deviceName,
241
241
  device_secret=cloud_client._aep_response.data.deviceSecret,
@@ -332,8 +332,9 @@ class MammotionBaseDevice:
332
332
 
333
333
  _mower: MowingDevice
334
334
  _state_manager: StateManager
335
+ _cloud_device: Device | None = None
335
336
 
336
- def __init__(self, device: MowingDevice) -> None:
337
+ def __init__(self, device: MowingDevice, cloud_device: Device | None = None) -> None:
337
338
  """Initialize MammotionBaseDevice."""
338
339
  self.loop = asyncio.get_event_loop()
339
340
  self._raw_data = LubaMsg().to_dict(casing=betterproto.Casing.SNAKE)
@@ -342,12 +343,13 @@ class MammotionBaseDevice:
342
343
  self._state_manager.gethash_ack_callback = self.datahash_response
343
344
  self._state_manager.get_commondata_ack_callback = self.commdata_response
344
345
  self._notify_future: asyncio.Future[bytes] | None = None
346
+ self._cloud_device = cloud_device
345
347
 
346
348
  async def datahash_response(self, hash_ack: NavGetHashListAck):
347
349
  """Handle datahash responses."""
348
350
  result_hash = 0
349
351
  while hash_ack.data_couple[0] != result_hash:
350
- data = await self._send_command_with_args("synchronize_hash_data", hash_num=hash_ack.data_couple[0])
352
+ data = await self.queue_command("synchronize_hash_data", hash_num=hash_ack.data_couple[0])
351
353
  msg = LubaMsg().parse(data)
352
354
  if betterproto.serialized_on_wire(msg.nav.toapp_get_commondata_ack):
353
355
  result_hash = msg.nav.toapp_get_commondata_ack.hash
@@ -365,7 +367,7 @@ class MammotionBaseDevice:
365
367
  return
366
368
  result_hash = 0
367
369
  while data_hash != result_hash:
368
- data = await self._send_command_with_args("synchronize_hash_data", hash_num=data_hash)
370
+ data = await self.queue_command("synchronize_hash_data", hash_num=data_hash)
369
371
  msg = LubaMsg().parse(data)
370
372
  if betterproto.serialized_on_wire(msg.nav.toapp_get_commondata_ack):
371
373
  result_hash = msg.nav.toapp_get_commondata_ack.hash
@@ -377,7 +379,7 @@ class MammotionBaseDevice:
377
379
  region_data.type = common_data.type
378
380
  region_data.total_frame = total_frame
379
381
  region_data.current_frame = current_frame
380
- await self._send_command_with_args("get_regional_data", regional_data=region_data)
382
+ await self.queue_command("get_regional_data", regional_data=region_data)
381
383
 
382
384
  def _update_raw_data(self, data: bytes) -> None:
383
385
  """Update raw and model data from notifications."""
@@ -475,6 +477,10 @@ class MammotionBaseDevice:
475
477
  """Get the LubaMsg of the device."""
476
478
  return self._mower
477
479
 
480
+ @abstractmethod
481
+ async def queue_command(self, key: str, **kwargs: any) -> bytes:
482
+ """Queue commands to mower."""
483
+
478
484
  @abstractmethod
479
485
  async def _send_command(self, key: str, retry: int | None = None) -> bytes | None:
480
486
  """Send command to device and read response."""
@@ -505,9 +511,15 @@ class MammotionBaseDevice:
505
511
 
506
512
  await self._send_command_with_args("get_hash_response", total_frame=1, current_frame=1)
507
513
 
508
- await self._send_command_with_args(
509
- "get_area_name_list", device_id=self._mower.device.net.toapp_wifi_iot_status.devicename
510
- )
514
+ if self._cloud_device:
515
+ await self._send_command_with_args(
516
+ "get_area_name_list", device_id=self._cloud_device.deviceName
517
+ )
518
+ if has_field(self._mower.net.toapp_wifi_iot_status):
519
+ await self._send_command_with_args(
520
+ "get_area_name_list", device_id=self._mower.net.toapp_wifi_iot_status.devicename
521
+ )
522
+
511
523
 
512
524
  # sub_cmd 3 is job hashes??
513
525
  # sub_cmd 4 is dump location (yuka)
@@ -586,6 +598,9 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
586
598
  130, lambda: asyncio.ensure_future(self.run_periodic_sync_task())
587
599
  )
588
600
 
601
+ async def queue_command(self, key: str, **kwargs: any) -> bytes | None:
602
+ return await self._send_command_with_args(key, **kwargs)
603
+
589
604
  async def _send_command_with_args(self, key: str, **kwargs) -> bytes | None:
590
605
  """Send command to device and read response."""
591
606
  if self._operation_lock.locked():
@@ -655,7 +670,7 @@ class MammotionBaseBLEDevice(MammotionBaseDevice):
655
670
  def rssi(self) -> int:
656
671
  """Return RSSI of device."""
657
672
  try:
658
- return self._mower.device.sys.toapp_report_data.connect.ble_rssi
673
+ return self._mower.sys.toapp_report_data.connect.ble_rssi
659
674
  finally:
660
675
  return 0
661
676
 
@@ -938,9 +953,11 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
938
953
  mowing_state: MowingDevice
939
954
  ) -> None:
940
955
  """Initialize MammotionBaseCloudDevice."""
941
- super().__init__(mowing_state)
956
+ super().__init__(mowing_state, cloud_device)
942
957
  self._ble_sync_task = None
943
958
  self.is_ready = False
959
+ self.command_queue = asyncio.Queue()
960
+ self.processing_task = asyncio.create_task(self._process_queue())
944
961
  self._mqtt_client = mqtt_client
945
962
  self.iot_id = cloud_device.iotId
946
963
  self.device = cloud_device
@@ -966,7 +983,7 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
966
983
  async def on_ready(self):
967
984
  """Callback for when MQTT is subscribed to events."""
968
985
  if self.on_ready_callback:
969
- self.on_ready_callback()
986
+ await self.on_ready_callback()
970
987
 
971
988
  await self._ble_sync()
972
989
  await self.run_periodic_sync_task()
@@ -998,6 +1015,32 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
998
1015
  160, lambda: asyncio.ensure_future(self.run_periodic_sync_task())
999
1016
  )
1000
1017
 
1018
+ async def queue_command(self, key: str, **kwargs: any) -> bytes:
1019
+ # Create a future to hold the result
1020
+ _LOGGER.debug("Queueing command: %s", key)
1021
+ future = asyncio.Future()
1022
+ # Put the command in the queue as a tuple (key, command, future)
1023
+ command_bytes = getattr(self._commands, key)(**kwargs)
1024
+ await self.command_queue.put((key, command_bytes, future))
1025
+ # Wait for the future to be resolved
1026
+ return await future
1027
+
1028
+ async def _process_queue(self):
1029
+ while True:
1030
+ # Get the next item from the queue
1031
+ key, command, future = await self.command_queue.get()
1032
+ try:
1033
+ # Process the command using _execute_command_locked
1034
+ result = await self._execute_command_locked(key, command)
1035
+ # Set the result on the future
1036
+ future.set_result(result)
1037
+ except Exception as ex:
1038
+ # Set the exception on the future if something goes wrong
1039
+ future.set_exception(ex)
1040
+ finally:
1041
+ # Mark the task as done
1042
+ self.command_queue.task_done()
1043
+
1001
1044
  async def _on_mqtt_message(self, topic: str, payload: str, iot_id: str) -> None:
1002
1045
  """Handle incoming MQTT messages."""
1003
1046
  _LOGGER.debug("MQTT message received on topic %s: %s, iot_id: %s", topic, payload, iot_id)
@@ -57,7 +57,7 @@ class MammotionMQTT:
57
57
  ).hexdigest()
58
58
 
59
59
  self._client_id = client_id
60
- self.loop = asyncio.get_event_loop()
60
+ self.loop = asyncio.get_running_loop()
61
61
 
62
62
  self._linkkit_client = LinkKit(
63
63
  region_id,
@@ -139,7 +139,8 @@ class MammotionMQTT:
139
139
  payload = json.loads(payload)
140
140
  iot_id = payload.get("params", {}).get("iotId", "")
141
141
  if iot_id != "" and self.on_message:
142
- asyncio.run_coroutine_threadsafe(self.on_message(topic, payload, iot_id), self.loop).result()
142
+ future = asyncio.run_coroutine_threadsafe(self.on_message(topic, payload, iot_id), self.loop)
143
+ asyncio.wrap_future(future, loop=self.loop)
143
144
 
144
145
 
145
146
  def _thing_on_connect(self, session_flag, rc, user_data):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymammotion
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Summary:
5
5
  License: GNU-3.0
6
6
  Author: Michael Arthur
@@ -1,6 +1,6 @@
1
1
  pymammotion/__init__.py,sha256=kmnjdt3AEMejIz5JK7h1tTJj5ZriAgKwZBa3ScA4-Ao,1516
2
2
  pymammotion/aliyun/__init__.py,sha256=T1lkX7TRYiL4nqYanG4l4MImV-SlavSbuooC-W-uUGw,29
3
- pymammotion/aliyun/cloud_gateway.py,sha256=sOqewx_aRxlRGj9FvPYJ0VPmheSTDpH3e1mCAX-HGko,21788
3
+ pymammotion/aliyun/cloud_gateway.py,sha256=IqmxgjDIgRoZvJvQnwYGOSl4XaCV4MoMKTlfhC9-6Ys,21830
4
4
  pymammotion/aliyun/cloud_service.py,sha256=YWcKuKK6iRWy5mTnBYgHxcCusiRGGzQt3spSf7dGDss,2183
5
5
  pymammotion/aliyun/dataclass/aep_response.py,sha256=8f6GIP58ve8gd6AL3HBoXxsy0n2q4ygWvjELGnoOnVc,452
6
6
  pymammotion/aliyun/dataclass/connect_response.py,sha256=Yz-fEbDzgGPTo5Of2oAjmFkSv08T7ze80pQU4k-gKIU,824
@@ -58,10 +58,10 @@ pymammotion/mammotion/commands/messages/video.py,sha256=_8lJsU4sLm2CGnc7RDkueA0A
58
58
  pymammotion/mammotion/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  pymammotion/mammotion/control/joystick.py,sha256=EWV20MMzQuhbLlNlXbsyZKSEpeM7x1CQL7saU4Pn0-g,6165
60
60
  pymammotion/mammotion/devices/__init__.py,sha256=T72jt0ejtMjo1rPmn_FeMF3pmp0LLeRRpc9WcDKEYYY,126
61
- pymammotion/mammotion/devices/mammotion.py,sha256=akUzxCSKPVgg2mG2-UQ6kjDHcZEz9Irs6p1Xh-_C51w,45017
61
+ pymammotion/mammotion/devices/mammotion.py,sha256=IqOPXLVDcq8VQ2mm33qHrauzkS9XAKOVFE0-TOk-q4k,46909
62
62
  pymammotion/mqtt/__init__.py,sha256=Ocs5e-HLJvTuDpVXyECEsWIvwsUaxzj7lZ9mSYutNDY,105
63
63
  pymammotion/mqtt/mammotion_future.py,sha256=WKnHqeHiS2Ut-SaDBNOxqh1jDLeTiyLTsJ7PNUexrjk,687
64
- pymammotion/mqtt/mammotion_mqtt.py,sha256=cBx-T_gsck8bEGaaE-oxdV1ADoPxJi8FKbSntRCSlVQ,8013
64
+ pymammotion/mqtt/mammotion_mqtt.py,sha256=K9TokiQWYJloWu5Hom00g7cfGhWHDSWqbcU9AqW4C9Q,8071
65
65
  pymammotion/proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
66
  pymammotion/proto/basestation.proto,sha256=_x5gAz3FkZXS1jtq4GgZgaDCuRU-UV-7HTFdsfQ3zbo,1034
67
67
  pymammotion/proto/basestation.py,sha256=js64_N2xQYRxWPRdVNEapO0qe7vBlfYnjW5sE8hi7hw,2026
@@ -111,7 +111,7 @@ pymammotion/utility/device_type.py,sha256=KYawu2glZMVlPmxRbA4kVFujXz3miHp3rJiOWR
111
111
  pymammotion/utility/map.py,sha256=aoi-Luzuph02hKynTofMoq3mnPstanx75MDAVv49CuY,2211
112
112
  pymammotion/utility/periodic.py,sha256=9wJMfwXPlx6Mbp3Fws7LLTI34ZDKphH1bva_Ggyk32g,3281
113
113
  pymammotion/utility/rocker_util.py,sha256=syPL0QN4zMzHiTIkUKS7RXBBptjdbkfNlPddwUD5V3A,7171
114
- pymammotion-0.2.8.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
115
- pymammotion-0.2.8.dist-info/METADATA,sha256=oPDS7unJxPTKajrvuT1s7MIK7c6fzKy6t-tKcLT2JP0,3968
116
- pymammotion-0.2.8.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
117
- pymammotion-0.2.8.dist-info/RECORD,,
114
+ pymammotion-0.2.9.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
115
+ pymammotion-0.2.9.dist-info/METADATA,sha256=sUQS-JHi__zyOgzpZzSQDKZpkCJ4yzl4UjNQdGE73M0,3968
116
+ pymammotion-0.2.9.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
117
+ pymammotion-0.2.9.dist-info/RECORD,,