pymammotion 0.5.2__py3-none-any.whl → 0.5.4__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.

@@ -5,6 +5,7 @@ import hashlib
5
5
  import hmac
6
6
  import itertools
7
7
  import json
8
+ from json.decoder import JSONDecodeError
8
9
  from logging import getLogger
9
10
  import random
10
11
  import string
@@ -15,7 +16,6 @@ from aiohttp import ClientSession, ConnectionTimeoutError
15
16
  from alibabacloud_iot_api_gateway.models import CommonParams, Config, IoTApiRequest
16
17
  from alibabacloud_tea_util.client import Client as UtilClient
17
18
  from alibabacloud_tea_util.models import RuntimeOptions
18
- from orjson.orjson import JSONDecodeError
19
19
  from Tea.exceptions import UnretryableException
20
20
 
21
21
  from pymammotion.aliyun.client import Client
@@ -153,7 +153,7 @@ class CloudIOTGateway:
153
153
  return json.loads(response_body_str) if response_body_str is not None else {}
154
154
  except JSONDecodeError:
155
155
  logger.error("Couldn't decode message %s", response_body_str)
156
- return {'code': 22000}
156
+ return {"code": 22000}
157
157
 
158
158
  def sign(self, data):
159
159
  """Generate signature for the given data."""
@@ -691,21 +691,21 @@ class CloudIOTGateway:
691
691
  return self._devices_by_account_response
692
692
 
693
693
  async def send_cloud_command(self, iot_id: str, command: bytes) -> str:
694
-
695
694
  """Sends a cloud command to a specified IoT device.
696
-
695
+
697
696
  This function checks if the IoT token is expired and attempts to refresh it if
698
697
  possible. It then constructs a request using the provided command and sends it
699
698
  to the IoT device via an asynchronous HTTP POST request. The function handles
700
699
  various error codes and exceptions based on the response from the cloud
701
700
  service.
702
-
701
+
703
702
  Args:
704
703
  iot_id (str): The unique identifier of the IoT device.
705
704
  command (bytes): The command to be sent to the IoT device in binary format.
706
-
705
+
707
706
  Returns:
708
707
  str: A unique message ID for the sent command.
708
+
709
709
  """
710
710
  if command is None:
711
711
  raise Exception("Command is missing / None")
@@ -273,7 +273,7 @@ class Mammotion:
273
273
  def get_or_create_device_by_name(self, device: Device, mqtt_client: MammotionCloud) -> MammotionMixedDeviceManager:
274
274
  if mow_device := self.device_manager.get_device(device.deviceName):
275
275
  return mow_device
276
- return MammotionMixedDeviceManager(
276
+ mow_device = MammotionMixedDeviceManager(
277
277
  name=device.deviceName,
278
278
  iot_id=device.iotId,
279
279
  cloud_client=mqtt_client.cloud_client,
@@ -281,6 +281,8 @@ class Mammotion:
281
281
  cloud_device=device,
282
282
  ble_device=None,
283
283
  )
284
+ self.device_manager.add_device(mow_device)
285
+ return mow_device
284
286
 
285
287
  async def send_command(self, name: str, key: str):
286
288
  """Send a command to the device."""
@@ -61,7 +61,9 @@ class MammotionCloud:
61
61
  return self._mqtt_client.is_connected
62
62
 
63
63
  def disconnect(self) -> None:
64
- self._mqtt_client.disconnect()
64
+ """Disconnect the MQTT client."""
65
+ if self.is_connected:
66
+ self._mqtt_client.disconnect()
65
67
 
66
68
  def connect_async(self) -> None:
67
69
  self._mqtt_client.connect_async()
@@ -713,7 +713,7 @@ UxeCp6
713
713
  self.__on_ota_message_arrived = None
714
714
 
715
715
  if self.__just_for_pycharm_autocomplete:
716
- self.__mqtt_client = mqtt.Client(CallbackAPIVersion.VERSION1)
716
+ self.__mqtt_client = mqtt.Client(CallbackAPIVersion.VERSION2)
717
717
 
718
718
  # device interface info
719
719
  self.__device_info_topic = "/sys/%s/%s/thing/deviceinfo/update" % (self.__product_key, self.__device_name)
@@ -1311,7 +1311,10 @@ UxeCp6
1311
1311
  elif self.__mqtt_protocol == "MQTTv31":
1312
1312
  mqtt_protocol_version = mqtt.MQTTv31
1313
1313
  self.__mqtt_client = mqtt.Client(
1314
- client_id=client_id, clean_session=self.__mqtt_clean_session, protocol=mqtt_protocol_version
1314
+ callback_api_version=CallbackAPIVersion.VERSION2,
1315
+ client_id=client_id,
1316
+ clean_session=self.__mqtt_clean_session,
1317
+ protocol=mqtt_protocol_version,
1315
1318
  )
1316
1319
 
1317
1320
  if self.__link_log.is_enabled():
@@ -1352,6 +1355,9 @@ UxeCp6
1352
1355
 
1353
1356
  def connect_async(self):
1354
1357
  self.__link_log.debug("connect_async")
1358
+ if self.__linkkit_state == LinkKit.LinkKitState.CONNECTED:
1359
+ self.__link_log.info("already connected, returning")
1360
+ return
1355
1361
  if self.__linkkit_state not in (LinkKit.LinkKitState.INITIALIZED, LinkKit.LinkKitState.DISCONNECTED):
1356
1362
  raise LinkKit.StateError("not in INITIALIZED or DISCONNECTED state")
1357
1363
  self.__connect_async_req = True
@@ -1564,13 +1570,13 @@ UxeCp6
1564
1570
  else:
1565
1571
  return 1, None
1566
1572
 
1567
- def __on_internal_connect_safe(self, client, user_data, session_flag, rc) -> None:
1568
- if rc == 0:
1573
+ def __on_internal_connect_safe(self, client, userdata, flags, reason_code, properties) -> None:
1574
+ if reason_code == 0:
1569
1575
  self.__reset_reconnect_wait()
1570
1576
  self.__force_reconnect = False
1571
- session_flag_internal = {"session present": session_flag}
1577
+ session_flag_internal = {"session present": flags}
1572
1578
  self.__handler_task.post_message(
1573
- self.__handler_task_cmd_on_connect, (client, user_data, session_flag_internal, rc)
1579
+ self.__handler_task_cmd_on_connect, (client, userdata, session_flag_internal, reason_code, properties)
1574
1580
  )
1575
1581
 
1576
1582
  def __loop_forever_internal(self):
@@ -1603,7 +1609,7 @@ UxeCp6
1603
1609
  except ssl.SSLError as e:
1604
1610
  self.__link_log.error("config mqtt raise exception:" + str(e))
1605
1611
  self.__linkkit_state = LinkKit.LinkKitState.INITIALIZED
1606
- self.__on_internal_connect_safe(None, None, 0, 6)
1612
+ self.__on_internal_connect_safe(None, None, 0, 6, {})
1607
1613
  return
1608
1614
 
1609
1615
  try:
@@ -1613,7 +1619,7 @@ UxeCp6
1613
1619
  except Exception as e:
1614
1620
  self.__link_log.error("__loop_forever_internal connect raise exception:" + str(e))
1615
1621
  self.__linkkit_state = LinkKit.LinkKitState.INITIALIZED
1616
- self.__on_internal_connect_safe(None, None, 0, 7)
1622
+ self.__on_internal_connect_safe(None, None, 0, 7, {})
1617
1623
  return
1618
1624
  while True:
1619
1625
  if self.__worker_loop_exit_req:
@@ -1636,7 +1642,7 @@ UxeCp6
1636
1642
  # return
1637
1643
  if self.__linkkit_state == LinkKit.LinkKitState.CONNECTING:
1638
1644
  self.__linkkit_state = LinkKit.LinkKitState.DISCONNECTED
1639
- self.__on_internal_connect_safe(None, None, 0, 9)
1645
+ self.__on_internal_connect_safe(None, None, 0, 9, {})
1640
1646
  if self.__linkkit_state == LinkKit.LinkKitState.DESTRUCTING:
1641
1647
  self.__handler_task.stop()
1642
1648
  self.__linkkit_state = LinkKit.LinkKitState.DESTRUCTED
@@ -1658,7 +1664,7 @@ UxeCp6
1658
1664
  break
1659
1665
 
1660
1666
  if self.__linkkit_state == LinkKit.LinkKitState.CONNECTED:
1661
- self.__on_internal_disconnect(None, None, 1)
1667
+ self.__on_internal_disconnect(None, None, 1, {})
1662
1668
  self.__link_log.info("loop return:%r" % rc)
1663
1669
 
1664
1670
  if self.__worker_loop_exit_req:
@@ -2533,23 +2539,25 @@ UxeCp6
2533
2539
  client, user_data, message = value
2534
2540
  self.__on_internal_async_message(message)
2535
2541
 
2536
- def __on_internal_connect(self, client, user_data, session_flag, rc) -> None:
2542
+ def __on_internal_connect(self, client, userdata, flags, reason_code, properties) -> None:
2537
2543
  self.__link_log.info("__on_internal_connect")
2538
- if rc == 0:
2544
+ if reason_code == 0:
2539
2545
  self.__reset_reconnect_wait()
2540
2546
  # self.__upload_device_interface_info()
2541
- self.__handler_task.post_message(self.__handler_task_cmd_on_connect, (client, user_data, session_flag, rc))
2547
+ self.__handler_task.post_message(
2548
+ self.__handler_task_cmd_on_connect, (client, userdata, flags, reason_code, properties)
2549
+ )
2542
2550
 
2543
2551
  def __handler_task_on_connect_callback(self, value) -> None:
2544
- client, user_data, session_flag, rc = value
2552
+ client, userdata, flags, reason_code = value
2545
2553
  self.__link_log.info("__on_internal_connect enter")
2546
- self.__link_log.debug("session:%d, return code:%d" % (session_flag["session present"], rc))
2554
+ self.__link_log.debug("session:%d, return code:%d" % (flags["session present"], reason_code))
2547
2555
  if rc == 0:
2548
2556
  self.__linkkit_state = LinkKit.LinkKitState.CONNECTED
2549
2557
  # self.__worker_thread.start()
2550
2558
  if self.__on_connect is not None:
2551
2559
  try:
2552
- self.__on_connect(session_flag["session present"], rc, self.__user_data)
2560
+ self.__on_connect(flags["session present"], reason_code, self.__user_data)
2553
2561
  except Exception as e:
2554
2562
  self.__link_log.error("on_connect process raise exception:%r" % e)
2555
2563
  if self.__thing_setup_state:
@@ -2557,7 +2565,7 @@ UxeCp6
2557
2565
  if self.__on_thing_enable:
2558
2566
  self.__on_thing_enable(self.__user_data)
2559
2567
 
2560
- def __on_internal_disconnect(self, client, user_data, rc) -> None:
2568
+ def __on_internal_disconnect(self, client, userdata, flags, reason_code, properties) -> None:
2561
2569
  self.__link_log.info("__on_internal_disconnect enter")
2562
2570
  if self.__linkkit_state == LinkKit.LinkKitState.DESTRUCTING:
2563
2571
  self.__linkkit_state = LinkKit.LinkKitState.DESTRUCTED
@@ -2590,13 +2598,15 @@ UxeCp6
2590
2598
  self.__device_info_mid.clear()
2591
2599
  self.__thing_update_device_info_up_mid.clear()
2592
2600
  self.__thing_delete_device_info_up_mid.clear()
2593
- self.__handler_task.post_message(self.__handler_task_cmd_on_disconnect, (client, user_data, rc))
2601
+ self.__handler_task.post_message(
2602
+ self.__handler_task_cmd_on_disconnect, (client, userdata, reason_code, properties)
2603
+ )
2594
2604
  if self.__linkkit_state == LinkKit.LinkKitState.DESTRUCTED:
2595
2605
  self.__handler_task.stop()
2596
2606
 
2597
2607
  def __handler_task_on_disconnect_callback(self, value) -> None:
2598
2608
  self.__link_log.info("__handler_task_on_disconnect_callback enter")
2599
- client, user_data, rc = value
2609
+ client, userdata, reason_code = value
2600
2610
  if self.__thing_setup_state:
2601
2611
  if self.__thing_enable_state:
2602
2612
  self.__thing_enable_state = False
@@ -2607,7 +2617,7 @@ UxeCp6
2607
2617
  self.__link_log.error("on_thing_disable process raise exception:%r" % e)
2608
2618
  if self.__on_disconnect is not None:
2609
2619
  try:
2610
- self.__on_disconnect(rc, self.__user_data)
2620
+ self.__on_disconnect(reason_code, self.__user_data)
2611
2621
  except Exception as e:
2612
2622
  self.__link_log.error("on_disconnect process raise exception:%r" % e)
2613
2623
 
@@ -175,18 +175,18 @@ class MammotionMQTT:
175
175
  )
176
176
  payload = json.loads(payload)
177
177
  iot_id = payload.get("params", {}).get("iotId", "")
178
- if iot_id != "" and self.on_message:
178
+ if iot_id != "" and self.on_message is not None:
179
179
  future = asyncio.run_coroutine_threadsafe(self.on_message(topic, payload, iot_id), self.loop)
180
180
  asyncio.wrap_future(future, loop=self.loop)
181
181
 
182
- def _thing_on_connect(self, session_flag, rc, user_data) -> None:
182
+ def _thing_on_connect(self, userdata, flags, reason_code, properties) -> None:
183
183
  """Is called on thing connect."""
184
184
  self.is_connected = True
185
185
  if self.on_connected is not None:
186
186
  future = asyncio.run_coroutine_threadsafe(self.on_connected(), self.loop)
187
187
  asyncio.wrap_future(future, loop=self.loop)
188
188
 
189
- logger.debug("on_connect, session_flag:%d, rc:%d", session_flag, rc)
189
+ logger.debug("on_connect, session_flag:%d, rc:%d", flags, reason_code)
190
190
 
191
191
  # self._linkkit_client.subscribe_topic(f"/sys/{self._product_key}/{self._device_name}/#")
192
192
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pymammotion
3
- Version: 0.5.2
3
+ Version: 0.5.4
4
4
  Summary:
5
5
  License: GPL-3.0
6
6
  Author: Michael Arthur
@@ -1,7 +1,7 @@
1
1
  pymammotion/__init__.py,sha256=H-U94bNLp0LPC6hkRopVEUlUsZSR97n7WfKGPjK1GMg,1638
2
2
  pymammotion/aliyun/__init__.py,sha256=T1lkX7TRYiL4nqYanG4l4MImV-SlavSbuooC-W-uUGw,29
3
3
  pymammotion/aliyun/client.py,sha256=GCpAnLOVWW_W0c8UvdRpWVzZH5oLto8JZnb82stJi-8,9662
4
- pymammotion/aliyun/cloud_gateway.py,sha256=dRsxFOm_ou1X0VjU-i5B5hee3ay3q6HK1bqEP0oK0EE,29717
4
+ pymammotion/aliyun/cloud_gateway.py,sha256=tOnw4oh8CtAzVOgZc8yhnIIbM2Cv0rET5EyHD7JR4Po,29692
5
5
  pymammotion/aliyun/model/aep_response.py,sha256=EY4uMTJ4F9rvbcXnAOc5YKi7q__9kIVgfDwfyr65Gk0,421
6
6
  pymammotion/aliyun/model/connect_response.py,sha256=Yz-fEbDzgGPTo5Of2oAjmFkSv08T7ze80pQU4k-gKIU,824
7
7
  pymammotion/aliyun/model/dev_by_account_response.py,sha256=P9yYy4Z2tLkJSqXA_5XGaCUliSSVa5ILl7VoMtL_tCA,977
@@ -72,15 +72,15 @@ pymammotion/mammotion/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
72
72
  pymammotion/mammotion/control/joystick.py,sha256=QfBVxM_gxpWsZAGO90whtgxCI2tIZ3TTad9wHIPsU9s,5640
73
73
  pymammotion/mammotion/devices/__init__.py,sha256=f2qQFPgLGmV85W2hSlMUh5BYuht9o_Ar_JEAAMD4fsE,102
74
74
  pymammotion/mammotion/devices/base.py,sha256=qDh7P7fnakDKgxTqjNLcQg8eE-6gHJaXAV0ONjhy_IU,12038
75
- pymammotion/mammotion/devices/mammotion.py,sha256=iXXV_jqv8w35ugaMRev3lEp_oKJTob54LZ6ZF659h-Y,15087
75
+ pymammotion/mammotion/devices/mammotion.py,sha256=dvFNLJvYS_Fu3JFkrJE3ljhECzewNJYMIPGuTAeFYHY,15170
76
76
  pymammotion/mammotion/devices/mammotion_bluetooth.py,sha256=dSDw8xLUfAU2c9vKX65w87Rm2E78284WjJ72CKniPt4,19349
77
- pymammotion/mammotion/devices/mammotion_cloud.py,sha256=sj13Z08mhuinsAExSlZ1f_u8FWh8OH43Lt2hzzfvNdI,14828
77
+ pymammotion/mammotion/devices/mammotion_cloud.py,sha256=Pd4aOIhcjVZznJfa0ANYTdG3QWO47maM2eB_qE8SR4U,14904
78
78
  pymammotion/mqtt/__init__.py,sha256=Ocs5e-HLJvTuDpVXyECEsWIvwsUaxzj7lZ9mSYutNDY,105
79
79
  pymammotion/mqtt/linkkit/__init__.py,sha256=ENgc3ynd2kd9gMQR3-kgmCu6Ed9Y6XCIzU0zFReUlkk,80
80
80
  pymammotion/mqtt/linkkit/h2client.py,sha256=w9Nvi_nY4CLD_fw-pHtYChwQf7e2TiAGeqkY_sF4cf0,19659
81
- pymammotion/mqtt/linkkit/linkkit.py,sha256=NzFpdtfxNHQ6xNu-POyp45fTK7AWUAWV7RavFevX4m4,132772
81
+ pymammotion/mqtt/linkkit/linkkit.py,sha256=joaubTgYYRILEkDMfCPiauOLuiKqY0eCpS8L5Ni8GkY,133217
82
82
  pymammotion/mqtt/mammotion_future.py,sha256=_OWqKOlUGl2yT1xOsXFQYpGd-1zQ63OxqXgy7KRQgYc,710
83
- pymammotion/mqtt/mammotion_mqtt.py,sha256=NTuGoAKI4gYB5IV6aU2E19p__uTUmlz5KVslqy9Agbk,10171
83
+ pymammotion/mqtt/mammotion_mqtt.py,sha256=4jNNV5tx6CCryjLSmAQA6u19bhRSuVkZem32JCpOakE,10198
84
84
  pymammotion/proto/__init__.py,sha256=vUF-eieR8e4VfduqaQ3KfeCRhsMD56NTX2Kk6sS38IE,73466
85
85
  pymammotion/proto/basestation.proto,sha256=YiSsDmT0DY_ep6DHay13SbhxGMhentYt0BmJrVQrwLQ,1198
86
86
  pymammotion/proto/basestation_pb2.py,sha256=suenbpMz9JZCXdGJGdiPaapppRz9Cf4IDzAXUfdIG3w,3083
@@ -124,7 +124,7 @@ pymammotion/utility/movement.py,sha256=N75oAoAgFydqoaOedYIxGUHmuTCtPzAOtb-d_29tp
124
124
  pymammotion/utility/mur_mur_hash.py,sha256=xEfOZVbqRawJj66eLgtnZ85OauDR47oIPr29OHelzPI,4468
125
125
  pymammotion/utility/periodic.py,sha256=MbeSb9cfhxzYmdT_RiE0dZe3H9IfbQW_zSqhmSX2RUc,3321
126
126
  pymammotion/utility/rocker_util.py,sha256=6tX7sS87qoQC_tsxbx3NLL-HgS08wtzXiZkhDiz7uo0,7179
127
- pymammotion-0.5.2.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
128
- pymammotion-0.5.2.dist-info/METADATA,sha256=-Qj7lhgHAoIQzfB2NlfbFXOUpQkkVYqI6Q2D00dZleg,3870
129
- pymammotion-0.5.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
130
- pymammotion-0.5.2.dist-info/RECORD,,
127
+ pymammotion-0.5.4.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
128
+ pymammotion-0.5.4.dist-info/METADATA,sha256=8ATEs2lmbEZbpK5GZO31VxAYMdSEuAiaV-d4lSjSIzk,3870
129
+ pymammotion-0.5.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
130
+ pymammotion-0.5.4.dist-info/RECORD,,