pymammotion 0.4.0a6__py3-none-any.whl → 0.4.0a7__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.
@@ -57,9 +57,11 @@ class AuthRefreshException(Exception):
57
57
  class DeviceOfflineException(Exception):
58
58
  """Raise exception when device is offline."""
59
59
 
60
+
60
61
  class GatewayTimeoutException(Exception):
61
62
  """Raise exception when the gateway times out."""
62
63
 
64
+
63
65
  class LoginException(Exception):
64
66
  """Raise exception when library cannot log in."""
65
67
 
@@ -10,6 +10,7 @@ from pymammotion.data.model.device_info import DeviceFirmwares, MowerInfo
10
10
  from pymammotion.data.model.location import Location
11
11
  from pymammotion.data.model.report_info import ReportData
12
12
  from pymammotion.data.mqtt.properties import ThingPropertiesMessage
13
+ from pymammotion.data.mqtt.status import ThingStatusMessage
13
14
  from pymammotion.http.model.http import ErrorInfo
14
15
  from pymammotion.proto.mctrl_sys import (
15
16
  DeviceFwInfo,
@@ -27,8 +28,10 @@ from pymammotion.utility.map import CoordinateConverter
27
28
  class MowingDevice(DataClassORJSONMixin):
28
29
  """Wraps the betterproto dataclasses, so we can bypass the groups for keeping all data."""
29
30
 
31
+ online: bool = True
30
32
  mower_state: MowerInfo = field(default_factory=MowerInfo)
31
33
  mqtt_properties: ThingPropertiesMessage | None = None
34
+ status_properties: ThingStatusMessage | None = None
32
35
  map: HashList = field(default_factory=HashList)
33
36
  location: Location = field(default_factory=Location)
34
37
  mowing_state: RapidState = field(default_factory=RapidState)
@@ -1,6 +1,6 @@
1
1
  from base64 import b64decode
2
2
  from dataclasses import dataclass
3
- from typing import Any, Literal, Optional, Union
3
+ from typing import Any, Literal
4
4
 
5
5
  from google.protobuf import json_format
6
6
  from mashumaro.mixins.orjson import DataClassORJSONMixin
@@ -91,16 +91,16 @@ class GeneralParams(DataClassORJSONMixin):
91
91
  tenantInstanceId: str
92
92
  value: Any
93
93
 
94
- identifier: Optional[str] = None
95
- checkFailedData: Optional[dict] = None
96
- _tenantId: Optional[str] = None
97
- generateTime: Optional[int] = None
98
- JMSXDeliveryCount: Optional[int] = None
99
- qos: Optional[int] = None
100
- requestId: Optional[str] = None
101
- _categoryKey: Optional[str] = None
102
- deviceType: Optional[str] = None
103
- _traceId: Optional[str] = None
94
+ identifier: str | None = None
95
+ checkFailedData: dict | None = None
96
+ _tenantId: str | None = None
97
+ generateTime: int | None = None
98
+ JMSXDeliveryCount: int | None = None
99
+ qos: int | None = None
100
+ requestId: str | None = None
101
+ _categoryKey: str | None = None
102
+ deviceType: str | None = None
103
+ _traceId: str | None = None
104
104
 
105
105
 
106
106
  @dataclass
@@ -117,7 +117,7 @@ class DeviceNotificationEventParams(GeneralParams):
117
117
  {'data': '{"localTime":1725159492000,"code":"1002"}'},
118
118
  """
119
119
 
120
- identifier: Literal["device_notification_event", "device_warning_code_event"]
120
+ identifier: Literal["device_notification_event", "device_information_event", "device_warning_code_event"]
121
121
  type: Literal["info"]
122
122
  value: DeviceNotificationEventValue
123
123
 
@@ -146,7 +146,7 @@ class DeviceConfigurationRequestEvent(GeneralParams):
146
146
  class ThingEventMessage(DataClassORJSONMixin):
147
147
  method: Literal["thing.events", "thing.properties"]
148
148
  id: str
149
- params: Union[DeviceProtobufMsgEventParams, DeviceWarningEventParams, dict]
149
+ params: DeviceProtobufMsgEventParams | DeviceWarningEventParams | dict
150
150
  version: Literal["1.0"]
151
151
 
152
152
  @classmethod
@@ -170,7 +170,11 @@ class ThingEventMessage(DataClassORJSONMixin):
170
170
  params_obj = DeviceBizReqEventParams.from_dict(params_dict)
171
171
  elif identifier == "device_config_req_event":
172
172
  params_obj = payload.get("params", {})
173
- elif identifier == "device_notification_event" or identifier == "device_warning_code_event":
173
+ elif (
174
+ identifier == "device_notification_event"
175
+ or identifier == "device_warning_code_event"
176
+ or identifier == "device_information_event"
177
+ ):
174
178
  params_obj = DeviceNotificationEventParams.from_dict(params_dict)
175
179
  else:
176
180
  raise ValueError(f"Unknown identifier: {identifier} {params_dict}")
@@ -26,7 +26,7 @@ class Status(DataClassORJSONMixin):
26
26
  @dataclass
27
27
  class Params(DataClassORJSONMixin):
28
28
  groupIdList: list[GroupIdListItem]
29
- netType: Literal["NET_WIFI"]
29
+ netType: Literal["NET_WIFI", "NET_MNET"]
30
30
  activeTime: int
31
31
  ip: str
32
32
  aliyunCommodityCode: Literal["iothub_senior"]
@@ -11,6 +11,7 @@ from pymammotion.data.model.device import MowingDevice
11
11
  from pymammotion.data.model.device_info import SideLight
12
12
  from pymammotion.data.model.hash_list import AreaHashNameList
13
13
  from pymammotion.data.mqtt.properties import ThingPropertiesMessage
14
+ from pymammotion.data.mqtt.status import ThingStatusMessage
14
15
  from pymammotion.proto.dev_net import DrvDevInfoResp, WifiIotStatusReport
15
16
  from pymammotion.proto.luba_msg import LubaMsg
16
17
  from pymammotion.proto.mctrl_nav import AppGetAllAreaHashName, NavGetCommDataAck, NavGetHashListAck, SvgMessageAckT
@@ -42,8 +43,20 @@ class StateManager:
42
43
  self._device = device
43
44
 
44
45
  async def properties(self, properties: ThingPropertiesMessage) -> None:
45
- params = properties.params
46
- self._device.mqtt_properties = params
46
+ self._device.mqtt_properties = properties
47
+
48
+ async def status(self, status: ThingStatusMessage) -> None:
49
+ if not self._device.online:
50
+ self._device.online = True
51
+ self._device.status_properties = status
52
+
53
+ @property
54
+ def online(self) -> bool:
55
+ return self._device.online
56
+
57
+ @online.setter
58
+ def online(self, value: bool) -> None:
59
+ self._device.online = value
47
60
 
48
61
  async def notification(self, message: LubaMsg) -> None:
49
62
  """Handle protobuf notifications."""
@@ -4,7 +4,8 @@ import json
4
4
  import logging
5
5
  from asyncio import TimerHandle
6
6
  from collections import deque
7
- from typing import Any, Awaitable, Callable, Optional, cast
7
+ from collections.abc import Awaitable, Callable
8
+ from typing import Any, cast
8
9
 
9
10
  import betterproto
10
11
 
@@ -13,6 +14,7 @@ from pymammotion.aliyun.cloud_gateway import DeviceOfflineException
13
14
  from pymammotion.aliyun.model.dev_by_account_response import Device
14
15
  from pymammotion.data.mqtt.event import ThingEventMessage
15
16
  from pymammotion.data.mqtt.properties import ThingPropertiesMessage
17
+ from pymammotion.data.mqtt.status import ThingStatusMessage
16
18
  from pymammotion.data.state_manager import StateManager
17
19
  from pymammotion.event.event import DataEvent
18
20
  from pymammotion.mammotion.commands.mammotion_command import MammotionCommand
@@ -35,6 +37,7 @@ class MammotionCloud:
35
37
  self._waiting_queue = deque()
36
38
  self.mqtt_message_event = DataEvent()
37
39
  self.mqtt_properties_event = DataEvent()
40
+ self.mqtt_status_event = DataEvent()
38
41
  self.on_ready_event = DataEvent()
39
42
  self.on_disconnected_event = DataEvent()
40
43
  self.on_connected_event = DataEvent()
@@ -116,7 +119,7 @@ class MammotionCloud:
116
119
  json_str = json.dumps(payload)
117
120
  payload = json.loads(json_str)
118
121
 
119
- await self._handle_mqtt_message(topic, payload)
122
+ await self._parse_mqtt_response(topic, payload)
120
123
 
121
124
  async def _parse_mqtt_response(self, topic: str, payload: dict) -> None:
122
125
  """Parse the MQTT response."""
@@ -134,10 +137,9 @@ class MammotionCloud:
134
137
  if event.method == "thing.properties":
135
138
  await self.mqtt_properties_event.data_event(event)
136
139
  _LOGGER.debug(event)
137
-
138
- async def _handle_mqtt_message(self, topic: str, payload: dict) -> None:
139
- """Async handler for incoming MQTT messages."""
140
- await self._parse_mqtt_response(topic=topic, payload=payload)
140
+ elif topic.endswith("/app/down/thing/status"):
141
+ status = ThingStatusMessage.from_dict(payload)
142
+ await self.mqtt_status_event.data_event(status)
141
143
 
142
144
  def _disconnect(self) -> None:
143
145
  """Disconnect the MQTT client."""
@@ -156,7 +158,7 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
156
158
  super().__init__(state_manager, cloud_device)
157
159
  self._ble_sync_task: TimerHandle | None = None
158
160
  self.stopped = False
159
- self.on_ready_callback: Optional[Callable[[], Awaitable[None]]] = None
161
+ self.on_ready_callback: Callable[[], Awaitable[None]] | None = None
160
162
  self.loop = asyncio.get_event_loop()
161
163
  self._mqtt = mqtt
162
164
  self.iot_id = cloud_device.iotId
@@ -166,6 +168,7 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
166
168
  self.currentID = ""
167
169
  self._mqtt.mqtt_message_event.add_subscribers(self._parse_message_for_device)
168
170
  self._mqtt.mqtt_properties_event.add_subscribers(self._parse_message_properties_for_device)
171
+ self._mqtt.mqtt_status_event.add_subscribers(self._parse_message_status_for_device)
169
172
  self._mqtt.on_ready_event.add_subscribers(self.on_ready)
170
173
  self._mqtt.on_disconnected_event.add_subscribers(self.on_disconnect)
171
174
  self._mqtt.on_connected_event.add_subscribers(self.on_connect)
@@ -278,6 +281,11 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
278
281
  return
279
282
  self.state_manager.properties(event)
280
283
 
284
+ async def _parse_message_status_for_device(self, status: ThingStatusMessage) -> None:
285
+ if status.params.iotId != self.iot_id:
286
+ return
287
+ self.state_manager.status(status)
288
+
281
289
  async def _parse_message_for_device(self, event: ThingEventMessage) -> None:
282
290
  _LOGGER.debug("_parse_message_for_device")
283
291
  params = event.params
@@ -193,6 +193,10 @@ class MammotionMQTT:
193
193
  else:
194
194
  logger.info("Unhandled event: %s", params.identifier)
195
195
  elif message.topic.endswith("/app/down/thing/status"):
196
+ # the tell if a device has come back online
197
+ # lastStatus
198
+ # 1 online?
199
+ # 3 offline?
196
200
  status = ThingStatusMessage(**payload)
197
201
  logger.debug(status.params.status.value)
198
202
  elif message.topic.endswith("/app/down/thing/properties"):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pymammotion
3
- Version: 0.4.0a6
3
+ Version: 0.4.0a7
4
4
  Summary:
5
5
  License: GPL-3.0
6
6
  Author: Michael Arthur
@@ -1,6 +1,6 @@
1
1
  pymammotion/__init__.py,sha256=u1OHuD8Uj0qCOH4I7Lt5d7T-TPt1R0pY-bv8S6UfVxM,1587
2
2
  pymammotion/aliyun/__init__.py,sha256=T1lkX7TRYiL4nqYanG4l4MImV-SlavSbuooC-W-uUGw,29
3
- pymammotion/aliyun/cloud_gateway.py,sha256=uUes76XWvclWVy-b9tIKPhjHDh9ZIRMarU0UcefMTh0,26115
3
+ pymammotion/aliyun/cloud_gateway.py,sha256=XLe1crlSmntZtt3MekGBZzqQ0zHh_c4sVAb_x-hDRe0,26117
4
4
  pymammotion/aliyun/cloud_service.py,sha256=px7dUKow5Z7VyebjYzuKkzkm77XbUXYiFiYO_2e-UQ0,2207
5
5
  pymammotion/aliyun/model/aep_response.py,sha256=8f6GIP58ve8gd6AL3HBoXxsy0n2q4ygWvjELGnoOnVc,452
6
6
  pymammotion/aliyun/model/connect_response.py,sha256=Yz-fEbDzgGPTo5Of2oAjmFkSv08T7ze80pQU4k-gKIU,824
@@ -24,7 +24,7 @@ pymammotion/const.py,sha256=lWRxvTVdXnNHuxqvRkjO5ziK0Ic-fZMM6J2dbe5M6Nc,385
24
24
  pymammotion/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  pymammotion/data/model/__init__.py,sha256=aSyroxYQQS-WMRi6WmWm2js4wLa9nmsi160gx9tts4o,323
26
26
  pymammotion/data/model/account.py,sha256=vJM-KTf2q6eBfVC-UlNHBSmJvqHiCawZ40vnuhXhaz8,140
27
- pymammotion/data/model/device.py,sha256=lKQl3wuCTlqM0D5F-kpxSRemqv5lbffnkSGnD9yw6lI,6743
27
+ pymammotion/data/model/device.py,sha256=lZEuWfEr4My0BUjY3OdIpUui91t9KbONhBc2t9oS2ro,6883
28
28
  pymammotion/data/model/device_config.py,sha256=wjayKnzoPDmBhqWZKTPDSueNEPCIWCB20tFEDSGIUsM,2602
29
29
  pymammotion/data/model/device_info.py,sha256=8FxHok09_uy99qBmgPiZw-MYbyqxXolF9eEw-8cQxSw,899
30
30
  pymammotion/data/model/device_limits.py,sha256=saW3iUvGq8WEn6CASn5hS5tVJpSeak4FDy_gnHtYqTQ,1955
@@ -41,10 +41,10 @@ pymammotion/data/model/raw_data.py,sha256=NO7FMzg_nE3WxT_K2ny-pEqbMf25LnvoYMB86s
41
41
  pymammotion/data/model/region_data.py,sha256=OTV15vRyn9JORXsQPjWMNF1ZujuNhsOKl25KeqwMObA,3007
42
42
  pymammotion/data/model/report_info.py,sha256=9sPPfhBv8f0K-xuHRkKrbez-7nZ_oCND2vZYLuKvkBA,3436
43
43
  pymammotion/data/mqtt/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
44
- pymammotion/data/mqtt/event.py,sha256=pEOQcjnv5XKosSPD8UmVAgCAaI8vLuIhGECZcU4xKjk,5055
44
+ pymammotion/data/mqtt/event.py,sha256=r14gzZVxmlGVAwFdZQ1CUsMZFHHwRKnbt2VHnjugP28,5123
45
45
  pymammotion/data/mqtt/properties.py,sha256=kvphcjrDuJHuX8Az98-wKeFv_rSmu2Fz9YKLGodGSj0,3759
46
- pymammotion/data/mqtt/status.py,sha256=zqnlo-MzejEQZszl0i0Wucoc3E76x6UtI9JLxoBnu54,1067
47
- pymammotion/data/state_manager.py,sha256=ZLPczA-tQMDKA8-O_DNDxYVqaRiDBan1lzCCHqMaV_Q,5744
46
+ pymammotion/data/mqtt/status.py,sha256=DuNC3JdewLPKNqNHx76_FPXRvheYSiM-CdiVTCCYY8s,1079
47
+ pymammotion/data/state_manager.py,sha256=t8RtRPUZuqp6dyMgy5bTV9W1Te-Ppq8-Qatj80o-85g,6140
48
48
  pymammotion/event/__init__.py,sha256=mgATR6vPHACNQ-0zH5fi7NdzeTCDV1CZyaWPmtUusi8,115
49
49
  pymammotion/event/event.py,sha256=bj2RirSIRyBs0QvkcrOtwZWUX_8F3m1sySuHVyKmZLs,2143
50
50
  pymammotion/http/_init_.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -69,13 +69,13 @@ pymammotion/mammotion/devices/__init__.py,sha256=f2qQFPgLGmV85W2hSlMUh5BYuht9o_A
69
69
  pymammotion/mammotion/devices/base.py,sha256=2IKm7CYGmvRLpJaAKp25tL23UhOoSEHJ6On5D0N5TSk,10763
70
70
  pymammotion/mammotion/devices/mammotion.py,sha256=_4w8dGoA1dcylZWtfMJyr7z-bjp9WcIEnWJ3mPHqOKA,12632
71
71
  pymammotion/mammotion/devices/mammotion_bluetooth.py,sha256=HUOKnjYUWTGjksyQDCPKF_u3dWo2ddgrWCBXnJ2VkwA,18963
72
- pymammotion/mammotion/devices/mammotion_cloud.py,sha256=a9fB0ZCYElRxrjnwCM81RXCbxo5kJKhGa-BGck9U3-A,12949
72
+ pymammotion/mammotion/devices/mammotion_cloud.py,sha256=IzJeWeLL8maLGHRi1-FO_cnTTbfB0gp1o8l0lCn0vbc,13329
73
73
  pymammotion/mqtt/__init__.py,sha256=Ocs5e-HLJvTuDpVXyECEsWIvwsUaxzj7lZ9mSYutNDY,105
74
74
  pymammotion/mqtt/linkkit/__init__.py,sha256=ENgc3ynd2kd9gMQR3-kgmCu6Ed9Y6XCIzU0zFReUlkk,80
75
75
  pymammotion/mqtt/linkkit/h2client.py,sha256=cca526y3NiZjMPodXWHGupgELpIBTc9MxM5fN4Ku0z0,19683
76
76
  pymammotion/mqtt/linkkit/linkkit.py,sha256=1kmQP3G-S2hOVZjL2HRu3anaaJR5YThljIXlnlfzzAg,132781
77
77
  pymammotion/mqtt/mammotion_future.py,sha256=_OWqKOlUGl2yT1xOsXFQYpGd-1zQ63OxqXgy7KRQgYc,710
78
- pymammotion/mqtt/mammotion_mqtt.py,sha256=5Jt-zG9A-E1MyVdyhvEIF0Ssbh_Y8grvadK2fcQjBuQ,8746
78
+ pymammotion/mqtt/mammotion_mqtt.py,sha256=Zpub35HFkixviTojnthKrYo0L_chodagHh4e3PWch4o,8876
79
79
  pymammotion/proto/__init__.py,sha256=v3_P1LOsYRBN9qCAhaWrWMX7GWHrox9XD3hdZQxcPZM,190
80
80
  pymammotion/proto/basestation.proto,sha256=_x5gAz3FkZXS1jtq4GgZgaDCuRU-UV-7HTFdsfQ3zbo,1034
81
81
  pymammotion/proto/basestation.py,sha256=js64_N2xQYRxWPRdVNEapO0qe7vBlfYnjW5sE8hi7hw,2026
@@ -128,7 +128,7 @@ pymammotion/utility/map.py,sha256=GYscVMg2cX3IPlNpCBNHDW0S55yS1WGRf1iHnNZ7TfQ,22
128
128
  pymammotion/utility/movement.py,sha256=N75oAoAgFydqoaOedYIxGUHmuTCtPzAOtb-d_29tpfI,615
129
129
  pymammotion/utility/periodic.py,sha256=MbeSb9cfhxzYmdT_RiE0dZe3H9IfbQW_zSqhmSX2RUc,3321
130
130
  pymammotion/utility/rocker_util.py,sha256=6tX7sS87qoQC_tsxbx3NLL-HgS08wtzXiZkhDiz7uo0,7179
131
- pymammotion-0.4.0a6.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
132
- pymammotion-0.4.0a6.dist-info/METADATA,sha256=Dp_naMRuux98fhLby-gjSQeeX6f5teipKUdesc4m7oo,3990
133
- pymammotion-0.4.0a6.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
134
- pymammotion-0.4.0a6.dist-info/RECORD,,
131
+ pymammotion-0.4.0a7.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
132
+ pymammotion-0.4.0a7.dist-info/METADATA,sha256=7mR-M17cLowY7vYMjieQ4a7fSvoXbUChwW28DIpLOQs,3990
133
+ pymammotion-0.4.0a7.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
134
+ pymammotion-0.4.0a7.dist-info/RECORD,,