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

@@ -19,7 +19,7 @@ class PositionMode(Enum):
19
19
  UNKNOWN = 4
20
20
 
21
21
  @staticmethod
22
- def from_value(value: int):
22
+ def from_value(value: int) -> "PositionMode":
23
23
  if value == 0:
24
24
  return PositionMode.FIX
25
25
  elif value == 1:
@@ -52,7 +52,7 @@ class RTKStatus(Enum):
52
52
  UNKNOWN = 6
53
53
 
54
54
  @staticmethod
55
- def from_value(value: int):
55
+ def from_value(value: int) -> "RTKStatus":
56
56
  if value == 0:
57
57
  return RTKStatus.NONE
58
58
  elif value == 1 or value == 2:
@@ -220,7 +220,7 @@ class HashList(DataClassORJSONMixin):
220
220
  self.svg = {hash_id: frames for hash_id, frames in self.svg.items() if hash_id in hashlist}
221
221
 
222
222
  area_hashes = list(self.area.keys())
223
- for hash_id, plan_task in self.plan.items():
223
+ for hash_id, plan_task in self.plan.copy().items():
224
224
  for item in plan_task.zone_hashs:
225
225
  if item not in area_hashes:
226
226
  self.plan.pop(hash_id)
@@ -1,10 +1,10 @@
1
1
  from base64 import b64decode
2
2
  from dataclasses import dataclass
3
- from typing import Any, Literal
3
+ from typing import Annotated, Any, Literal
4
4
 
5
5
  from google.protobuf import json_format
6
6
  from mashumaro.mixins.orjson import DataClassORJSONMixin
7
- from mashumaro.types import SerializableType
7
+ from mashumaro.types import Alias, SerializableType
8
8
 
9
9
  from pymammotion.proto import luba_msg_pb2
10
10
 
@@ -73,34 +73,35 @@ class DeviceBizReqEventValue(DataClassORJSONMixin):
73
73
 
74
74
  @dataclass
75
75
  class GeneralParams(DataClassORJSONMixin):
76
- groupIdList: list[str]
77
- groupId: str
78
- categoryKey: Literal["LawnMower", "Tracker"]
79
- batchId: str
80
- gmtCreate: int
81
- productKey: str
76
+ group_id_list: Annotated[list[str], Alias("groupIdList")]
77
+ group_id: Annotated[str, Alias("groupId")]
78
+ category_key: Annotated[Literal["LawnMower", "Tracker"], Alias("categoryKey")]
79
+ batch_id: Annotated[str, Alias("batchId")]
80
+ gmt_create: Annotated[int, Alias("gmtCreate")]
81
+ product_key: Annotated[str, Alias("productKey")]
82
82
  type: str
83
- deviceName: str
84
- iotId: str
85
- checkLevel: int
83
+ device_name: Annotated[str, Alias("deviceName")]
84
+ iot_id: Annotated[str, Alias("iotId")]
85
+ check_level: Annotated[int, Alias("checkLevel")]
86
86
  namespace: str
87
- tenantId: str
87
+ tenant_id: Annotated[str, Alias("tenantId")]
88
88
  name: str
89
- thingType: Literal["DEVICE"]
89
+ thing_type: Annotated[Literal["DEVICE"], Alias("thingType")]
90
90
  time: int
91
- tenantInstanceId: str
91
+ tenant_instance_id: Annotated[str, Alias("tenantInstanceId")]
92
92
  value: Any
93
93
 
94
+ # Optional fields
94
95
  identifier: str | None = None
95
- checkFailedData: dict | None = None
96
- _tenantId: str | None = None
97
- generateTime: int | None = None
98
- JMSXDeliveryCount: int | None = None
96
+ check_failed_data: Annotated[dict | None, Alias("checkFailedData")] = None
97
+ _tenant_id: Annotated[str | None, Alias("_tenantId")] = None
98
+ generate_time: Annotated[int | None, Alias("generateTime")] = None
99
+ jmsx_delivery_count: Annotated[int | None, Alias("JMSXDeliveryCount")] = None
99
100
  qos: int | None = None
100
- requestId: str | None = None
101
- _categoryKey: str | None = None
102
- deviceType: str | None = None
103
- _traceId: str | None = None
101
+ request_id: Annotated[str | None, Alias("requestId")] = None
102
+ _category_key: Annotated[str | None, Alias("_categoryKey")] = None
103
+ device_type: Annotated[str | None, Alias("deviceType")] = None
104
+ _trace_id: Annotated[str | None, Alias("_traceId")] = None
104
105
 
105
106
 
106
107
  @dataclass
@@ -196,3 +197,27 @@ class ThingEventMessage(DataClassORJSONMixin):
196
197
  raise ValueError(f"Unknown identifier: {identifier} {params_dict}")
197
198
 
198
199
  return cls(method=method, id=event_id, params=params_obj, version=version)
200
+
201
+
202
+ @dataclass
203
+ class MammotionProtoMsgParams(DataClassORJSONMixin, SerializableType):
204
+ value: DeviceProtobufMsgEventValue
205
+ iot_id: str = ""
206
+ product_key: str = ""
207
+ device_name: str = ""
208
+
209
+ @classmethod
210
+ def _deserialize(cls, d: dict[str, Any]) -> "MammotionProtoMsgParams":
211
+ """Override from_dict to allow dict manipulation before conversion."""
212
+ proto: str = d["content"]
213
+
214
+ return cls(value=DeviceProtobufMsgEventValue(content=proto))
215
+
216
+
217
+ @dataclass
218
+ class MammotionEventMessage(DataClassORJSONMixin):
219
+ id: str
220
+ version: str
221
+ sys: dict
222
+ params: MammotionProtoMsgParams
223
+ method: str
@@ -0,0 +1,257 @@
1
+ from dataclasses import dataclass
2
+ from typing import Annotated
3
+
4
+ from mashumaro.config import BaseConfig
5
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
6
+ from mashumaro.types import Alias
7
+
8
+
9
+ @dataclass
10
+ class FirmwareInfo(DataClassORJSONMixin):
11
+ t: str
12
+ c: str
13
+ v: str
14
+
15
+
16
+ @dataclass
17
+ class DeviceVersionInfo(DataClassORJSONMixin):
18
+ dev_ver: Annotated[str, Alias("devVer")]
19
+ whole: int
20
+ fw_info: Annotated[list[FirmwareInfo], Alias("fwInfo")]
21
+
22
+
23
+ @dataclass
24
+ class Coordinate(DataClassORJSONMixin):
25
+ lon: float
26
+ lat: float
27
+
28
+
29
+ @dataclass
30
+ class InternalNavigation(DataClassORJSONMixin):
31
+ nav: Annotated[str, Alias("NAV")]
32
+ pau: Annotated[str, Alias("Pau")]
33
+ r_pau: Annotated[str, Alias("rPau")]
34
+ mcu: Annotated[str, Alias("MCU")]
35
+ app: Annotated[str, Alias("APP")]
36
+ w_slp: Annotated[str, Alias("wSlp")]
37
+ i_slp: Annotated[str, Alias("iSlp")]
38
+
39
+
40
+ @dataclass
41
+ class BandwidthTraffic(DataClassORJSONMixin):
42
+ iot: Annotated[str, Alias("IoT")]
43
+ roi: Annotated[str, Alias("RoI")]
44
+ fpv: Annotated[str, Alias("FPV")]
45
+ inav: InternalNavigation
46
+
47
+
48
+ @dataclass
49
+ class TrafficPeriod(DataClassORJSONMixin):
50
+ r: str
51
+ t: str
52
+ s: str
53
+
54
+
55
+ @dataclass
56
+ class TrafficData(DataClassORJSONMixin):
57
+ upt: str
58
+ hour: Annotated[dict[str, TrafficPeriod], Alias("Hour")]
59
+ day: Annotated[dict[str, TrafficPeriod], Alias("Day")]
60
+ mon: Annotated[dict[str, TrafficPeriod], Alias("Mon")]
61
+
62
+
63
+ @dataclass
64
+ class NetworkInfo(DataClassORJSONMixin):
65
+ ssid: str
66
+ ip: str
67
+ wifi_sta_mac: str
68
+ wifi_rssi: int
69
+ wifi_available: int
70
+ bt_mac: str
71
+ mnet_model: str
72
+ imei: str
73
+ fw_ver: str
74
+ sim: str
75
+ imsi: str
76
+ iccid: str
77
+ sim_source: str
78
+ mnet_rssi: int
79
+ signal: int
80
+ mnet_link: int
81
+ mnet_option: str
82
+ mnet_ip: str
83
+ mnet_reg: str
84
+ mnet_rsrp: str
85
+ mnet_snr: str
86
+ mnet_enable: int
87
+ apn_num: int
88
+ apn_info: str
89
+ apn_cid: int
90
+ used_net: int
91
+ hub_reset: int
92
+ mnet_dis: int
93
+ airplane_times: int
94
+ lsusb_num: int
95
+ b_tra: Annotated[BandwidthTraffic, Alias("bTra")]
96
+ bw_tra: Annotated[BandwidthTraffic, Alias("bwTra")]
97
+ mnet_rx: str
98
+ mnet_tx: str
99
+ m_tra: Annotated[TrafficData, Alias("mTra")]
100
+ mnet_uniot: int
101
+ mnet_un_getiot: int
102
+ ssh_flag: str
103
+ mileage: str
104
+ work_time: str
105
+ wt_sec: int
106
+ bat_cycles: str
107
+
108
+
109
+ @dataclass
110
+ class DeviceOtherInfo(DataClassORJSONMixin):
111
+ soc_up_time: Annotated[int, Alias("socUpTime")]
112
+ mcu_up_time: Annotated[int, Alias("mcuUpTime")]
113
+ soc_loads: Annotated[str, Alias("socLoads")]
114
+ soc_mem_free: Annotated[int, Alias("socMemFree")]
115
+ soc_mem_total: Annotated[int, Alias("socMemTotal")]
116
+ soc_mmc_life_time: Annotated[int, Alias("socMmcLifeTime")]
117
+ usb_dis_cnt: Annotated[int, Alias("usbDisCnt")]
118
+ soc_pstore: Annotated[int, Alias("socPstore")]
119
+ soc_coredump: Annotated[int, Alias("socCoredump")]
120
+ soc_tmp: Annotated[int, Alias("socTmp")]
121
+ mc_mcu: Annotated[str, Alias("mcMcu")]
122
+ tilt_degree: str
123
+ i_msg_free: Annotated[int, Alias("iMsgFree")]
124
+ i_msg_limit: Annotated[int, Alias("iMsgLimit")]
125
+ i_msg_raw: Annotated[int, Alias("iMsgRaw")]
126
+ i_msg_prop: Annotated[int, Alias("iMsgprop")]
127
+ i_msg_serv: Annotated[int, Alias("iMsgServ")]
128
+ i_msg_info: Annotated[int, Alias("iMsgInfo")]
129
+ i_msg_warn: Annotated[int, Alias("iMsgWarn")]
130
+ i_msg_fault: Annotated[int, Alias("iMsgFault")]
131
+ i_msg_ota_stage: Annotated[int, Alias("iMsgOtaStage")]
132
+ i_msg_protobuf: Annotated[int, Alias("iMsgProtobuf")]
133
+ i_msg_notify: Annotated[int, Alias("iMsgNotify")]
134
+ i_msg_log_prog: Annotated[int, Alias("iMsgLogProg")]
135
+ i_msg_biz_req: Annotated[int, Alias("iMsgBizReq")]
136
+ i_msg_cfg_req: Annotated[int, Alias("iMsgCfgReq")]
137
+ i_msg_voice: Annotated[int, Alias("iMsgVoice")]
138
+ i_msg_warn_code: Annotated[int, Alias("iMsgWarnCode")]
139
+ pb_net: Annotated[int, Alias("pbNet")]
140
+ pb_sys: Annotated[int, Alias("pbSys")]
141
+ pb_nav: Annotated[int, Alias("pbNav")]
142
+ pb_local: Annotated[int, Alias("pbLocal")]
143
+ pb_plan: Annotated[int, Alias("pbPlan")]
144
+ pb_e_drv: Annotated[int, Alias("pbEDrv")]
145
+ pb_e_sys: Annotated[int, Alias("pbESys")]
146
+ pb_midware: Annotated[int, Alias("pbMidware")]
147
+ pb_ota: Annotated[int, Alias("pbOta")]
148
+ pb_appl: Annotated[int, Alias("pbAppl")]
149
+ pb_mul: Annotated[int, Alias("pbMul")]
150
+ pb_other: Annotated[int, Alias("pbOther")]
151
+ lora_connect: Annotated[int, Alias("loraConnect")]
152
+ base_status: Annotated[int, Alias("Basestatus")]
153
+ mqtt_rtk_switch: int
154
+ mqtt_rtk_channel: int
155
+ mqtt_rtk_status: int
156
+ mqtt_rtcm_cnt: int
157
+ mqtt_conn_cnt: int
158
+ mqtt_disconn_cnt: int
159
+ mqtt_rtk_hb_flag: int
160
+ mqtt_rtk_hb_count: int
161
+ mqtt_start_cnt: int
162
+ mqtt_close_cnt: int
163
+ mqtt_rtk_ssl_fail: int
164
+ mqtt_rtk_wifi_config: int
165
+ nrtk_svc_prov: int
166
+ nrtk_svc_err: int
167
+ base_stn_id: int
168
+ rtk_status: int
169
+ charge_status: int
170
+ chassis_state: int
171
+ nav: str
172
+ ins_fusion: str
173
+ perception: str
174
+ vision_proxy: str
175
+ vslam_vio: str
176
+ iot_con_timeout: int
177
+ iot_con: int
178
+ iot_con_fail_max: str
179
+ iot_con_fail_min: Annotated[str, Alias("iot_con__fail_min")]
180
+ iot_url_count: int
181
+ iot_url_max: str
182
+ iot_url_min: str
183
+ iot_cn: int
184
+ iot_ap: int
185
+ iot_us: int
186
+ iot_eu: int
187
+ task_area: float
188
+ task_count: int
189
+ task_hash: str
190
+ systemio_boot_time: Annotated[str, Alias("systemioBootTime")]
191
+ dds_no_gdc: int
192
+
193
+
194
+ @dataclass
195
+ class CheckData(DataClassORJSONMixin):
196
+ result: str
197
+ error: Annotated[list[int], Alias("Error")]
198
+ warn: Annotated[list[int], Alias("Warn")]
199
+ ok: Annotated[list[int], Alias("OK")]
200
+
201
+
202
+ @dataclass
203
+ class DeviceProperties(DataClassORJSONMixin):
204
+ device_state: Annotated[int, Alias("deviceState")]
205
+ battery_percentage: Annotated[int, Alias("batteryPercentage")]
206
+ device_version: Annotated[str, Alias("deviceVersion")]
207
+ knife_height: Annotated[int, Alias("knifeHeight")]
208
+ lora_general_config: Annotated[str, Alias("loraGeneralConfig")]
209
+ ext_mod: Annotated[str, Alias("extMod")]
210
+ int_mod: Annotated[str, Alias("intMod")]
211
+ iot_state: Annotated[int, Alias("iotState")]
212
+ iot_msg_total: Annotated[int, Alias("iotMsgTotal")]
213
+ iot_msg_hz: Annotated[int, Alias("iotMsgHz")]
214
+ lt_mr_mod: Annotated[str, Alias("ltMrMod")]
215
+ rt_mr_mod: Annotated[str, Alias("rtMrMod")]
216
+ bms_hardware_version: Annotated[str, Alias("bmsHardwareVersion")]
217
+ stm32_h7_version: Annotated[str, Alias("stm32H7Version")]
218
+ left_motor_version: Annotated[str, Alias("leftMotorVersion")]
219
+ right_motor_version: Annotated[str, Alias("rightMotorVersion")]
220
+ rtk_version: Annotated[str, Alias("rtkVersion")]
221
+ bms_version: Annotated[str, Alias("bmsVersion")]
222
+ mc_boot_version: Annotated[str, Alias("mcBootVersion")]
223
+ left_motor_boot_version: Annotated[str, Alias("leftMotorBootVersion")]
224
+ right_motor_boot_version: Annotated[str, Alias("rightMotorBootVersion")]
225
+
226
+ # Nested JSON objects
227
+ device_version_info: Annotated[DeviceVersionInfo, Alias("deviceVersionInfo")]
228
+ coordinate: Coordinate
229
+ device_other_info: Annotated[DeviceOtherInfo, Alias("deviceOtherInfo")]
230
+ network_info: Annotated[NetworkInfo, Alias("networkInfo")]
231
+ check_data: Annotated[CheckData, Alias("checkData")]
232
+ iot_id: str = ""
233
+
234
+ class Config(BaseConfig):
235
+ # Custom deserializer for nested JSON strings
236
+ serialization_strategy = {
237
+ DeviceVersionInfo: {
238
+ "deserialize": lambda x: DeviceVersionInfo.from_json(x) if isinstance(x, str) else x,
239
+ "serialize": lambda x: x.to_json() if hasattr(x, "to_json") else x,
240
+ },
241
+ Coordinate: {
242
+ "deserialize": lambda x: Coordinate.from_json(x) if isinstance(x, str) else x,
243
+ "serialize": lambda x: x.to_json() if hasattr(x, "to_json") else x,
244
+ },
245
+ DeviceOtherInfo: {
246
+ "deserialize": lambda x: DeviceOtherInfo.from_json(x) if isinstance(x, str) else x,
247
+ "serialize": lambda x: x.to_json() if hasattr(x, "to_json") else x,
248
+ },
249
+ NetworkInfo: {
250
+ "deserialize": lambda x: NetworkInfo.from_json(x) if isinstance(x, str) else x,
251
+ "serialize": lambda x: x.to_json() if hasattr(x, "to_json") else x,
252
+ },
253
+ CheckData: {
254
+ "deserialize": lambda x: CheckData.from_json(x) if isinstance(x, str) else x,
255
+ "serialize": lambda x: x.to_json() if hasattr(x, "to_json") else x,
256
+ },
257
+ }
@@ -1,16 +1,11 @@
1
1
  from dataclasses import dataclass
2
- from typing import Any, Generic, Literal, TypeVar, Union
2
+ from typing import Annotated, Any, Generic, Literal, TypeVar, Union
3
3
 
4
4
  from mashumaro import DataClassDictMixin
5
5
  from mashumaro.mixins.orjson import DataClassORJSONMixin
6
+ from mashumaro.types import Alias
6
7
 
7
- DataT = TypeVar("DataT")
8
-
9
-
10
- @dataclass
11
- class Item(DataClassDictMixin, Generic[DataT]):
12
- time: int
13
- value: DataT
8
+ from pymammotion.data.mqtt.mammotion_properties import DeviceProperties
14
9
 
15
10
 
16
11
  @dataclass
@@ -163,29 +158,29 @@ class Items(DataClassDictMixin):
163
158
 
164
159
  @dataclass
165
160
  class Params(DataClassORJSONMixin):
166
- deviceType: Literal["LawnMower", "Tracker"]
167
- checkFailedData: dict
168
- groupIdList: list[str]
169
- _tenantId: str
170
- groupId: str
171
- categoryKey: Literal["LawnMower", "Tracker"]
172
- batchId: str
173
- gmtCreate: int
174
- productKey: str
175
- generateTime: int
176
- deviceName: str
177
- _traceId: str
178
- iotId: str
179
- JMSXDeliveryCount: int
180
- checkLevel: int
161
+ device_type: Annotated[Literal["LawnMower", "Tracker"], Alias("deviceType")]
162
+ check_failed_data: Annotated[dict[str, Any], Alias("checkFailedData")]
163
+ group_id_list: Annotated[list[str], Alias("groupIdList")]
164
+ _tenant_id: Annotated[str, Alias("_tenantId")]
165
+ group_id: Annotated[str, Alias("groupId")]
166
+ category_key: Annotated[Literal["LawnMower", "Tracker"], Alias("categoryKey")]
167
+ batch_id: Annotated[str, Alias("batchId")]
168
+ gmt_create: Annotated[int, Alias("gmtCreate")]
169
+ product_key: Annotated[str, Alias("productKey")]
170
+ generate_time: Annotated[int, Alias("generateTime")]
171
+ device_name: Annotated[str, Alias("deviceName")]
172
+ _trace_id: Annotated[str, Alias("_traceId")]
173
+ iot_id: Annotated[str, Alias("iotId")]
174
+ jmsx_delivery_count: Annotated[int, Alias("JMSXDeliveryCount")]
175
+ check_level: Annotated[int, Alias("checkLevel")]
181
176
  qos: int
182
- requestId: str
183
- _categoryKey: str
177
+ request_id: Annotated[str, Alias("requestId")]
178
+ _category_key: Annotated[str, Alias("_categoryKey")]
184
179
  namespace: str
185
- tenantId: str
186
- thingType: Literal["DEVICE"]
187
- items: Items
188
- tenantInstanceId: str
180
+ tenant_id: Annotated[str, Alias("tenantId")]
181
+ thing_type: Annotated[Literal["DEVICE"], Alias("thingType")]
182
+ items: Annotated["Items", Alias("items")]
183
+ tenant_instance_id: Annotated[str, Alias("tenantInstanceId")]
189
184
 
190
185
 
191
186
  @dataclass
@@ -194,3 +189,11 @@ class ThingPropertiesMessage(DataClassORJSONMixin):
194
189
  id: str
195
190
  params: Params
196
191
  version: Literal["1.0"]
192
+
193
+
194
+ @dataclass
195
+ class MammotionPropertiesMessage(DataClassORJSONMixin):
196
+ id: str
197
+ version: str
198
+ sys: dict
199
+ params: DeviceProperties
@@ -1,8 +1,9 @@
1
1
  from dataclasses import dataclass
2
2
  from enum import Enum
3
- from typing import Literal
3
+ from typing import Annotated, Literal
4
4
 
5
5
  from mashumaro.mixins.orjson import DataClassORJSONMixin
6
+ from mashumaro.types import Alias
6
7
 
7
8
 
8
9
  @dataclass
@@ -25,23 +26,23 @@ class Status(DataClassORJSONMixin):
25
26
 
26
27
  @dataclass
27
28
  class Params(DataClassORJSONMixin):
28
- groupIdList: list[GroupIdListItem]
29
- netType: Literal["NET_WIFI", "NET_MNET"]
30
- activeTime: int
29
+ group_id_list: Annotated[list[GroupIdListItem], Alias("groupIdList")]
30
+ net_type: Annotated[Literal["NET_WIFI", "NET_MNET"], Alias("netType")]
31
+ active_time: Annotated[int, Alias("activeTime")]
31
32
  ip: str
32
- aliyunCommodityCode: Literal["iothub_senior"]
33
- categoryKey: Literal["LawnMower", "Tracker"]
34
- nodeType: Literal["DEVICE"]
35
- productKey: str
36
- statusLast: int
37
- deviceName: str
38
- iotId: str
33
+ aliyun_commodity_code: Annotated[Literal["iothub_senior"], Alias("aliyunCommodityCode")]
34
+ category_key: Annotated[Literal["LawnMower", "Tracker"], Alias("categoryKey")]
35
+ node_type: Annotated[Literal["DEVICE"], Alias("nodeType")]
36
+ product_key: Annotated[str, Alias("productKey")]
37
+ status_last: Annotated[int, Alias("statusLast")]
38
+ device_name: Annotated[str, Alias("deviceName")]
39
+ iot_id: Annotated[str, Alias("iotId")]
39
40
  namespace: str
40
- tenantId: str
41
- thingType: Literal["DEVICE"]
42
- tenantInstanceId: str
43
- categoryId: int
44
- status: Status
41
+ tenant_id: Annotated[str, Alias("tenantId")]
42
+ thing_type: Annotated[Literal["DEVICE"], Alias("thingType")]
43
+ tenant_instance_id: Annotated[str, Alias("tenantInstanceId")]
44
+ category_id: Annotated[int, Alias("categoryId")]
45
+ status: Annotated[Status, Alias("status")]
45
46
 
46
47
 
47
48
  @dataclass
pymammotion/http/http.py CHANGED
@@ -370,7 +370,13 @@ class MammotionHTTP:
370
370
  async with ClientSession(self.jwt_info.iot) as session:
371
371
  async with session.post(
372
372
  "/v1/mqtt/rpc/thing/service/invoke",
373
- json={"args": {"content": content, "deviceName": device_name, "iotId": iot_id, "productKey": ""}},
373
+ json={
374
+ "args": {"content": content},
375
+ "deviceName": device_name,
376
+ "identifier": "device_protobuf_sync_service",
377
+ "iotId": iot_id,
378
+ "productKey": "",
379
+ },
374
380
  headers={
375
381
  **self._headers,
376
382
  "Authorization": f"Bearer {self.login_info.access_token}",
@@ -289,8 +289,7 @@ class Mammotion:
289
289
  if len(mammotion_http.device_records.records) != 0:
290
290
  mammotion_cloud = MammotionCloud(
291
291
  MammotionMQTT(
292
- product_key=cloud_client.aep_response.data.productKey,
293
- device_name=cloud_client.aep_response.data.deviceName,
292
+ records=mammotion_http.device_records.records,
294
293
  mammotion_http=mammotion_http,
295
294
  mqtt_connection=mammotion_http.mqtt_credentials,
296
295
  ),
@@ -15,8 +15,8 @@ from pymammotion import AliyunMQTT, CloudIOTGateway, MammotionMQTT
15
15
  from pymammotion.aliyun.cloud_gateway import DeviceOfflineException
16
16
  from pymammotion.aliyun.model.dev_by_account_response import Device
17
17
  from pymammotion.data.mower_state_manager import MowerStateManager
18
- from pymammotion.data.mqtt.event import ThingEventMessage
19
- from pymammotion.data.mqtt.properties import ThingPropertiesMessage
18
+ from pymammotion.data.mqtt.event import MammotionEventMessage, ThingEventMessage
19
+ from pymammotion.data.mqtt.properties import MammotionPropertiesMessage, ThingPropertiesMessage
20
20
  from pymammotion.data.mqtt.status import ThingStatusMessage
21
21
  from pymammotion.event.event import DataEvent
22
22
  from pymammotion.mammotion.commands.mammotion_command import MammotionCommand
@@ -112,10 +112,9 @@ class MammotionCloud:
112
112
  # _LOGGER.debug("MQTT message received on topic %s: %s, iot_id: %s", topic, payload, iot_id)
113
113
  json_str = payload.decode("utf-8")
114
114
  dict_payload = json.loads(json_str)
115
- print(dict_payload)
116
- await self._parse_mqtt_response(topic, dict_payload)
115
+ await self._parse_mqtt_response(topic, dict_payload, iot_id)
117
116
 
118
- async def _parse_mqtt_response(self, topic: str, payload: dict) -> None:
117
+ async def _parse_mqtt_response(self, topic: str, payload: dict, iot_id: str) -> None:
119
118
  """Parse and handle MQTT responses based on the topic.
120
119
 
121
120
  This function processes different types of MQTT messages received from various
@@ -150,6 +149,17 @@ class MammotionCloud:
150
149
  property_event = ThingPropertiesMessage.from_dict(payload)
151
150
  await self.mqtt_properties_event.data_event(property_event)
152
151
 
152
+ if topic.endswith("/thing/event/device_protobuf_msg_event/post"):
153
+ _LOGGER.debug("Mammotion Thing event received")
154
+ mammotion_event = MammotionEventMessage.from_dict(payload)
155
+ mammotion_event.params.iot_id = iot_id
156
+ await self.mqtt_message_event.data_event(mammotion_event)
157
+ elif topic.endswith("/thing/event/property/post"):
158
+ _LOGGER.debug("Mammotion Property event received")
159
+ mammotion_property_event = MammotionPropertiesMessage.from_dict(payload)
160
+ mammotion_property_event.params.iot_id = iot_id
161
+ await self.mqtt_properties_event.data_event(mammotion_property_event)
162
+
153
163
  def _disconnect(self) -> None:
154
164
  """Disconnect the MQTT client."""
155
165
  self._mqtt_client.disconnect()
@@ -229,6 +239,7 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
229
239
  self.stopped = True
230
240
 
231
241
  async def start(self) -> None:
242
+ """Start the device connection."""
232
243
  self.stopped = False
233
244
  if not self.mqtt.is_connected():
234
245
  loop = asyncio.get_running_loop()
@@ -277,18 +288,18 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
277
288
  return None
278
289
 
279
290
  async def _parse_message_properties_for_device(self, event: ThingPropertiesMessage) -> None:
280
- if event.params.iotId != self.iot_id:
291
+ if event.params.iot_id != self.iot_id:
281
292
  return
282
293
  await self.state_manager.properties(event)
283
294
 
284
295
  async def _parse_message_status_for_device(self, status: ThingStatusMessage) -> None:
285
- if status.params.iotId != self.iot_id:
296
+ if status.params.iot_id != self.iot_id:
286
297
  return
287
298
  await self.state_manager.status(status)
288
299
 
289
300
  async def _parse_device_event_for_device(self, status: ThingStatusMessage) -> None:
290
301
  """Process device event if it matches the device's IoT ID."""
291
- if status.params.iotId != self.iot_id:
302
+ if status.params.iot_id != self.iot_id:
292
303
  return
293
304
  await self.state_manager.device_event(status)
294
305
 
@@ -307,7 +318,7 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
307
318
  """
308
319
  params = event.params
309
320
  new_msg = LubaMsg()
310
- if event.params.iotId != self.iot_id:
321
+ if event.params.iot_id != self.iot_id:
311
322
  return
312
323
  binary_data = base64.b64decode(params.value.content)
313
324
  try:
@@ -318,9 +329,9 @@ class MammotionBaseCloudDevice(MammotionBaseDevice):
318
329
 
319
330
  if (
320
331
  self._commands.get_device_product_key() == ""
321
- and self._commands.get_device_name() == event.params.deviceName
332
+ and self._commands.get_device_name() == event.params.device_name
322
333
  ):
323
- self._commands.set_device_product_key(event.params.productKey)
334
+ self._commands.set_device_product_key(event.params.product_key)
324
335
 
325
336
  res = betterproto2.which_one_of(new_msg, "LubaSubMsg")
326
337
  if res[0] == "net":
@@ -96,14 +96,14 @@ class MammotionRTKCloudDevice(MammotionRTKDevice):
96
96
 
97
97
  async def _parse_message_properties_for_device(self, event: ThingPropertiesMessage) -> None:
98
98
  """Parse property messages for this RTK device."""
99
- if event.params.iotId != self.iot_id:
99
+ if event.params.iot_id != self.iot_id:
100
100
  return
101
101
  # RTK devices have simpler properties - update as needed
102
102
  _LOGGER.debug("RTK properties update: %s", event)
103
103
 
104
104
  async def _parse_message_status_for_device(self, status: ThingStatusMessage) -> None:
105
105
  """Parse status messages for this RTK device."""
106
- if status.params.iotId != self.iot_id:
106
+ if status.params.iot_id != self.iot_id:
107
107
  return
108
108
  # Update online status
109
109
  self._rtk_device.online = True
@@ -11,27 +11,30 @@ from paho.mqtt.properties import Properties
11
11
  from paho.mqtt.reasoncodes import ReasonCode
12
12
 
13
13
  from pymammotion import MammotionHTTP
14
- from pymammotion.http.model.http import MQTTConnection, Response
14
+ from pymammotion.http.model.http import DeviceRecord, MQTTConnection, Response
15
+ from pymammotion.utility.datatype_converter import DatatypeConverter
15
16
 
16
17
  logger = logging.getLogger(__name__)
17
18
 
18
19
 
19
20
  class MammotionMQTT:
21
+ """Mammotion MQTT Client."""
22
+ converter = DatatypeConverter()
23
+
20
24
  def __init__(
21
- self, mqtt_connection: MQTTConnection, mammotion_http: MammotionHTTP, product_key: str, device_name: str
25
+ self, mqtt_connection: MQTTConnection, mammotion_http: MammotionHTTP, records: list[DeviceRecord]
22
26
  ) -> None:
23
27
  self.on_connected: Callable[[], Awaitable[None]] | None = None
24
28
  self.on_ready: Callable[[], Awaitable[None]] | None = None
25
29
  self.on_error: Callable[[str], Awaitable[None]] | None = None
26
30
  self.on_disconnected: Callable[[], Awaitable[None]] | None = None
27
- self.on_message: Callable[[str, str, str], Awaitable[None]] | None = None
31
+ self.on_message: Callable[[str, bytes, str], Awaitable[None]] | None = None
28
32
  self.loop = asyncio.get_running_loop()
29
33
  self.mammotion_http = mammotion_http
30
34
  self.mqtt_connection = mqtt_connection
31
35
  self.client = self.build(mqtt_connection)
32
36
 
33
- self.device_name = device_name
34
- self.product_key = product_key
37
+ self.records = records
35
38
 
36
39
  # wire callbacks from the service object if present
37
40
  self.client.on_connect = self._on_connect
@@ -42,7 +45,8 @@ class MammotionMQTT:
42
45
 
43
46
  def __del__(self) -> None:
44
47
  if self.client.is_connected():
45
- self.unsubscribe_all(self.product_key, self.device_name)
48
+ for record in self.records:
49
+ self.unsubscribe_all(record.product_key, record.device_name)
46
50
  self.client.disconnect()
47
51
 
48
52
  def connect_async(self) -> None:
@@ -103,14 +107,36 @@ class MammotionMQTT:
103
107
  def _on_message(self, _client: mqtt.Client, _userdata: Any, message: mqtt.MQTTMessage) -> None:
104
108
  """Is called when message is received."""
105
109
  logger.debug("Message on topic %s", message.topic)
106
- json_payload = json.loads(message.payload)
107
-
108
- iot_id = json_payload.get("params", {}).get("iotId", "")
109
- if iot_id != "" and self.on_message is not None:
110
- future = asyncio.run_coroutine_threadsafe(
111
- self.on_message(message.topic, str(message.payload), iot_id), self.loop
112
- )
113
- asyncio.wrap_future(future, loop=self.loop)
110
+ logger.debug(message)
111
+
112
+ if self.on_message is not None:
113
+ iot_id = None
114
+ # Parse the topic path to get product_key and device_name
115
+ topic_parts = message.topic.split("/")
116
+ if len(topic_parts) >= 4:
117
+ product_key = topic_parts[2]
118
+ device_name = topic_parts[3]
119
+
120
+ # Filter records to find matching device
121
+ filtered_records = [
122
+ record
123
+ for record in self.records
124
+ if record.product_key == product_key and record.device_name == device_name
125
+ ]
126
+
127
+ if filtered_records:
128
+ iot_id = filtered_records[0].iot_id
129
+ payload = json.loads(message.payload.decode("utf-8"))
130
+ payload["iot_id"] = iot_id
131
+ payload["product_key"] = product_key
132
+ payload["device_name"] = device_name
133
+ message.payload = json.dumps(payload).encode("utf-8")
134
+
135
+ if iot_id:
136
+ future = asyncio.run_coroutine_threadsafe(
137
+ self.on_message(message.topic, message.payload, iot_id), self.loop
138
+ )
139
+ asyncio.wrap_future(future, loop=self.loop)
114
140
 
115
141
  def _on_connect(
116
142
  self,
@@ -122,11 +148,17 @@ class MammotionMQTT:
122
148
  ) -> None:
123
149
  """Handle connection event and execute callback if set."""
124
150
  self.is_connected = True
151
+ for record in self.records:
152
+ self.subscribe_all(record.product_key, record.device_name)
125
153
  if self.on_connected is not None:
126
- self.subscribe_all(self.product_key, self.device_name)
127
154
  future = asyncio.run_coroutine_threadsafe(self.on_connected(), self.loop)
128
155
  asyncio.wrap_future(future, loop=self.loop)
129
156
 
157
+ if self.on_ready:
158
+ self.is_ready = True
159
+ future = asyncio.run_coroutine_threadsafe(self.on_ready(), self.loop)
160
+ asyncio.wrap_future(future, loop=self.loop)
161
+
130
162
  logger.debug("on_connect, session_flag:%s, rc:%s", session_flag, rc)
131
163
 
132
164
  def _on_disconnect(
@@ -141,7 +173,8 @@ class MammotionMQTT:
141
173
  """Handle disconnection event and execute callback if set."""
142
174
  self.is_connected = False
143
175
  if self.on_disconnected is not None:
144
- self.unsubscribe_all(self.product_key, self.device_name)
176
+ for record in self.records:
177
+ self.unsubscribe_all(record.product_key, record.device_name)
145
178
  future = asyncio.run_coroutine_threadsafe(self.on_disconnected(), self.loop)
146
179
  asyncio.wrap_future(future, loop=self.loop)
147
180
 
@@ -165,6 +198,13 @@ class MammotionMQTT:
165
198
 
166
199
  async def send_cloud_command(self, iot_id: str, command: bytes) -> str:
167
200
  """Send command to cloud."""
168
- res: Response[dict] = await self.mammotion_http.mqtt_invoke(str(command), "", iot_id)
201
+ res: Response[dict] = await self.mammotion_http.mqtt_invoke(
202
+ self.converter.printBase64Binary(command), "", iot_id
203
+ )
204
+
205
+ logger.debug("send_cloud_command: %s", res)
206
+
207
+ if res.code == 500:
208
+ return res.msg
169
209
 
170
210
  return str(res.data["result"])
@@ -2,7 +2,7 @@ import base64
2
2
 
3
3
 
4
4
  class DatatypeConverter:
5
- encode_map = None
5
+ encode_map: list[str | int] | None = None
6
6
 
7
7
  @staticmethod
8
8
  def init_encode_map():
@@ -20,24 +20,25 @@ class DatatypeConverter:
20
20
  """
21
21
 
22
22
  if DatatypeConverter.encode_map is None:
23
- cArr: list[str | int] = [0] * 64
23
+ c_arr: list[str | int] = [0] * 64
24
24
  for num in range(26):
25
- cArr[num] = chr(num + 65)
25
+ c_arr[num] = chr(num + 65)
26
26
  for num_2 in range(26, 52):
27
- cArr[num_2] = chr(num_2 - 26 + 97)
27
+ c_arr[num_2] = chr(num_2 - 26 + 97)
28
28
  for num_3 in range(52, 62):
29
- cArr[num_3] = chr(num_3 - 52 + 48)
30
- cArr[62] = "+"
31
- cArr[63] = "/"
32
- DatatypeConverter.encode_map = cArr
29
+ c_arr[num_3] = chr(num_3 - 52 + 48)
30
+ c_arr[62] = "+"
31
+ c_arr[63] = "/"
32
+ DatatypeConverter.encode_map = c_arr
33
33
  return DatatypeConverter.encode_map
34
34
 
35
35
  @staticmethod
36
- def parseBase64Binary(s):
36
+ def parseBase64Binary(s: str) -> bytes:
37
37
  return base64.b64decode(s)
38
38
 
39
39
  @staticmethod
40
- def printBase64Binary(bArr):
40
+ def printBase64Binary(bArr: bytes) -> str:
41
+ """Print the Base64 str representation of a byte array."""
41
42
  return DatatypeConverter._printBase64Binary(bArr)
42
43
 
43
44
  @staticmethod
@@ -45,7 +46,7 @@ class DatatypeConverter:
45
46
  return DatatypeConverter.encode_map[i & 63]
46
47
 
47
48
  @staticmethod
48
- def _printBase64Binary(bArr: bytes, i: int = 0, i2=None):
49
+ def _printBase64Binary(bArr: bytes, i: int = 0, i2=None) -> str:
49
50
  """Print the Base64 binary representation of a byte array.
50
51
 
51
52
  This function takes a byte array and optional start and end indices to
@@ -68,7 +69,7 @@ class DatatypeConverter:
68
69
  return "".join(cArr)
69
70
 
70
71
  @staticmethod
71
- def _printBase64Binary_core(bArr: bytes, i, i2, cArr, i3):
72
+ def _printBase64Binary_core(bArr: bytes, i, i2, cArr, i3) -> int:
72
73
  """Encode binary data into Base64 format.
73
74
 
74
75
  This function encodes binary data into Base64 format following the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pymammotion
3
- Version: 0.5.42
3
+ Version: 0.5.43
4
4
  Author: jLynx
5
5
  Author-email: Michael Arthur <michael@jumblesoft.co.nz>
6
6
  License-Expression: GPL-3.0
@@ -32,12 +32,12 @@ pymammotion/data/model/device.py,sha256=MeaB0ucFuNU5E4RAQ6qC8sTqdPJMw3lsMXR_YmYv
32
32
  pymammotion/data/model/device_config.py,sha256=cLfvO_xs8GhEQbhTZLOfhYK5OX4T337M9OZkyQ_GNWQ,2652
33
33
  pymammotion/data/model/device_info.py,sha256=vjqHlRbHOyEkkaIoTwAp14CZMY5R5o609SbThfOO-gg,1390
34
34
  pymammotion/data/model/device_limits.py,sha256=m8HdxD-RaAkPm7jHYb9GLxMEH9IfzBPz0ZypmsLnId4,1946
35
- pymammotion/data/model/enums.py,sha256=0a7kCc_V1lzsmmLIQB5oZ83pUKCIrZ4TDDtH09J7jBY,1749
35
+ pymammotion/data/model/enums.py,sha256=LVLP-9ypW0NxwyTeizxPVFNX3INWGfhSR9obM_vl0-M,1782
36
36
  pymammotion/data/model/errors.py,sha256=lBHq2cE8P5fc6Q4JXgrkJXzFKTWgxsoPOyMlTaJWbWk,396
37
37
  pymammotion/data/model/excute_boarder_params.py,sha256=9CpUqrygcle1C_1hDW-riLmm4map4ZbE842NXjcomEI,1394
38
38
  pymammotion/data/model/execute_boarder.py,sha256=9rd_h4fbcsXxgnLOd2rO2hWyD1abnTGc47QTEpp8DD0,1103
39
39
  pymammotion/data/model/generate_route_information.py,sha256=-_c8pk10zwRh-O2vJ0i3DDCOQbv9CRJ7YNWpfsIpajI,807
40
- pymammotion/data/model/hash_list.py,sha256=5hXCSerL7EH6kmnfta8U6eJxpWumsFpzAukwECeJlf8,14810
40
+ pymammotion/data/model/hash_list.py,sha256=jikG45FlsIBXaPzFN84WVN7Mn-c1yi3BmMC46aw2c3k,14817
41
41
  pymammotion/data/model/location.py,sha256=PwmITejfI4pm7PI4rzqSuuHetwle6IJr_CV95435s2M,871
42
42
  pymammotion/data/model/mowing_modes.py,sha256=4rMn1H8w2iU2aBwpmAhPh_sT81yqrocrWWUIaU7DCIc,1171
43
43
  pymammotion/data/model/rapid_state.py,sha256=mIdhAG_LZXpVcybxqTLgLXkNOmVmDTn04B9PGIDA8Ls,1251
@@ -46,9 +46,10 @@ pymammotion/data/model/region_data.py,sha256=OP4hXYX2U1gNxU7VFsHQfQbE1Bze_nvVFQ0
46
46
  pymammotion/data/model/report_info.py,sha256=3nXBFRfdKWnZj4YfBcrPwhBRpq58ICMQlrESfI1tTMg,3808
47
47
  pymammotion/data/model/work.py,sha256=AfKMItFqnRtAlVHzKCfYY-BQy-WFDYZBzdj-9Yc03bo,655
48
48
  pymammotion/data/mqtt/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
49
- pymammotion/data/mqtt/event.py,sha256=pj65y93ACcTzUIJkHZC6s_pRFBYaNMSU1wyYRhiGvw4,5571
50
- pymammotion/data/mqtt/properties.py,sha256=laud9rE-JqBHWKZ44Dov2yMkp3Ld8ghpBwlZ4_3g9uQ,4321
51
- pymammotion/data/mqtt/status.py,sha256=qwZPevIzScePA_25nbRWMN7IhU-MhhtIl7fcZKAJfIc,1102
49
+ pymammotion/data/mqtt/event.py,sha256=JPzu2XCgyLwcdKsN9vqg94WMvHtsGH6vHHSFGstILjo,6911
50
+ pymammotion/data/mqtt/mammotion_properties.py,sha256=oMsHkMJQxLjiUu8wXtWiLV7cmUPM8sJk2GBVsBeIfNU,8528
51
+ pymammotion/data/mqtt/properties.py,sha256=lqd7TCQ04HVZdosCI_J_ovmF7E3VpFFWLz1sFRemIOE,5170
52
+ pymammotion/data/mqtt/status.py,sha256=jZ1Qx8tRhtBOguL7MOtR0jhsA1cRmVKoPJszho5A2Bs,1644
52
53
  pymammotion/event/__init__.py,sha256=mgATR6vPHACNQ-0zH5fi7NdzeTCDV1CZyaWPmtUusi8,115
53
54
  pymammotion/event/event.py,sha256=Z8WYxv_-5khEqKjL1w4c_Et24G1Kdm8QFuIBylD3h3U,3021
54
55
  pymammotion/homeassistant/__init__.py,sha256=j0aQZKWR41pCDR3g1y2p_zfp033pESECcqXiefRg1DQ,107
@@ -57,7 +58,7 @@ pymammotion/homeassistant/rtk_api.py,sha256=YyTF_14cWvvT31H-LYD715W82KsWfkV1nwXs
57
58
  pymammotion/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
59
  pymammotion/http/_init_.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
60
  pymammotion/http/encryption.py,sha256=lzXu3WwBdQlzjXxWnlJuRgkCrKdPbxx5drhMitVKIEk,8287
60
- pymammotion/http/http.py,sha256=bh1bYM9dJmc8Eh4jJ8J-IOVzJVThehHq633pqaaPv_E,20171
61
+ pymammotion/http/http.py,sha256=UvHIVN4nB1Oua9otXvbWGaDfoC6-UjMzXgDxvEx7yog,20336
61
62
  pymammotion/http/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
63
  pymammotion/http/model/camera_stream.py,sha256=ilxQNny_w9Frwt-m8kbHinvyjDv4Bx8C2swfZ2lTEDE,600
63
64
  pymammotion/http/model/http.py,sha256=GyWXIL4fNBssuE7WJR1IR89shWUEMbxRF3T9L24jGMM,6381
@@ -80,22 +81,22 @@ pymammotion/mammotion/control/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
80
81
  pymammotion/mammotion/control/joystick.py,sha256=QfBVxM_gxpWsZAGO90whtgxCI2tIZ3TTad9wHIPsU9s,5640
81
82
  pymammotion/mammotion/devices/__init__.py,sha256=YYphpxf0zr1Xc_dOBKsCzcO5zSwlewuhZNjAbmy6cHI,1012
82
83
  pymammotion/mammotion/devices/base.py,sha256=MLLup0ZQI1GvyEF980BTtIeuayRZJijR1kvk77U1DS0,6518
83
- pymammotion/mammotion/devices/mammotion.py,sha256=wR6QuaC81WHKzrsZfak15qU-v8tP2K2tpbPpZm4N6h0,23850
84
+ pymammotion/mammotion/devices/mammotion.py,sha256=tI_K1P5rh3VUamMepIhWnIuWANHhBME6ViUlf8CRhzo,23767
84
85
  pymammotion/mammotion/devices/mammotion_bluetooth.py,sha256=bwl1wphx2ev3iuDBTFTJbeujtll0L2ZBYDRzTcKBZes,19203
85
- pymammotion/mammotion/devices/mammotion_cloud.py,sha256=TWU1lO268bYKaLatpsMQxvotEjAJyPwySN5YOgXX4zY,14370
86
+ pymammotion/mammotion/devices/mammotion_cloud.py,sha256=8MosSefZtymgHhKxkp7nSHq7b5D6sNPobxoKYVMBy-I,15139
86
87
  pymammotion/mammotion/devices/mammotion_mower_ble.py,sha256=GLc-f9TFhpGp2OYnVestzFqPSyGBMHX2YmrAnnmYu0I,1947
87
88
  pymammotion/mammotion/devices/mammotion_mower_cloud.py,sha256=JwCQICv8S31c1ll23JIWFFJEwzbTss182MvE4ZiQxWs,1877
88
89
  pymammotion/mammotion/devices/mower_device.py,sha256=VUgoJYlMKMOuy9j6MzxDmOIe6y7ziG-O-gUdDQPhkUM,5627
89
90
  pymammotion/mammotion/devices/mower_manager.py,sha256=m2U90ZlNgSmdPAh8BtKtyMVt5ZTBpfxNs5RT_lsUTls,4280
90
91
  pymammotion/mammotion/devices/rtk_ble.py,sha256=egZo4VJYS1_9r7e8f8FA21tD-bVthc-YgJbTtf0cNSI,3601
91
- pymammotion/mammotion/devices/rtk_cloud.py,sha256=_b_AVYTxRx_FhajBtnntesQKrVzW2CO4eRpZ3Sx2qfw,4814
92
+ pymammotion/mammotion/devices/rtk_cloud.py,sha256=gFzcnlSyWnyFLTYR-WOLpjIQD8Y1k844ZTkd-gdyIIk,4816
92
93
  pymammotion/mammotion/devices/rtk_device.py,sha256=8wUCPqS6Xkox7sFj8AaXlVbzh67X9HarqldddBoWqBE,1917
93
94
  pymammotion/mammotion/devices/rtk_manager.py,sha256=m963cKvfx2ThjYJpKb5_KrjqUPpvxK-DLVoF7TNXyP4,4392
94
95
  pymammotion/mammotion/devices/managers/managers.py,sha256=d2z7oo2kMCsZ_YHSOBO9LazMSQxov0NNbr4EzJtxlYs,2495
95
96
  pymammotion/mqtt/__init__.py,sha256=9nhy9GS8EbzOAPOrXHBTd_olePq8mctIkwMruDDSeWw,155
96
97
  pymammotion/mqtt/aliyun_mqtt.py,sha256=CmGsxHfCYkhE5mJFPyV7NXcJs7srvpQo_6PVjDyK3Nk,10144
97
98
  pymammotion/mqtt/mammotion_future.py,sha256=_OWqKOlUGl2yT1xOsXFQYpGd-1zQ63OxqXgy7KRQgYc,710
98
- pymammotion/mqtt/mammotion_mqtt.py,sha256=DFTT-ifbYvX20M6LC75I_94df3c42b1EfXgHfKZQKwA,7176
99
+ pymammotion/mqtt/mammotion_mqtt.py,sha256=Hz2lFvgUPSsz3DkLE_vh4IRnTvTOVhnzEsLm_hjofQg,8663
99
100
  pymammotion/mqtt/mqtt_models.py,sha256=3JXP9Nals-3f27pYUqxD9WrfQHf5tpnal1j4R6vr-CM,1760
100
101
  pymammotion/mqtt/linkkit/__init__.py,sha256=ENgc3ynd2kd9gMQR3-kgmCu6Ed9Y6XCIzU0zFReUlkk,80
101
102
  pymammotion/mqtt/linkkit/h2client.py,sha256=w9Nvi_nY4CLD_fw-pHtYChwQf7e2TiAGeqkY_sF4cf0,19659
@@ -134,7 +135,7 @@ pymammotion/proto/mctrl_sys_pb2.pyi,sha256=N1sJJMx7qWsj1kKYoQJ4JEZanZetLZ5JThs1I
134
135
  pymammotion/proto/message_pool.py,sha256=4-cRhhiM6bmfpUJZ8qxc8LEyqHBHpLCcotjbyZxl7JM,71
135
136
  pymammotion/proto/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
137
  pymammotion/utility/conversions.py,sha256=v3YICy0zZwwBBzrUZgabI7GRfiDBnkiAX2qdtk3NxOY,89
137
- pymammotion/utility/datatype_converter.py,sha256=SPM_HuaaD_XOawlqEnA8qlRRZXGba3WjA8kGOZgeBlQ,4284
138
+ pymammotion/utility/datatype_converter.py,sha256=A9qHBTbnq2PniAyBKxx3Qrk08aF5SIXGK1lDIY1siPU,4424
138
139
  pymammotion/utility/device_config.py,sha256=65Jl73-dQDs4yMXwYXZW_bsgSvnwpFBZDu8OQPEIgx8,27877
139
140
  pymammotion/utility/device_type.py,sha256=RdxBdkqzd03Q0MCCkbfqLj_CKrks8nNV4ji50UvJbH8,17024
140
141
  pymammotion/utility/map.py,sha256=GYscVMg2cX3IPlNpCBNHDW0S55yS1WGRf1iHnNZ7TfQ,2227
@@ -144,7 +145,7 @@ pymammotion/utility/periodic.py,sha256=MbeSb9cfhxzYmdT_RiE0dZe3H9IfbQW_zSqhmSX2R
144
145
  pymammotion/utility/rocker_util.py,sha256=6tX7sS87qoQC_tsxbx3NLL-HgS08wtzXiZkhDiz7uo0,7179
145
146
  pymammotion/utility/constant/__init__.py,sha256=tcY0LDeD-qDDHx2LKt55KOyv9ZI0UfCNM6fknLCmm8s,110
146
147
  pymammotion/utility/constant/device_constant.py,sha256=MJE1DEOg86oWNSXYGx3xxJ542KEuSJNZ0VJLN4eHbUg,8237
147
- pymammotion-0.5.42.dist-info/METADATA,sha256=Qc1EJVsa848is148yLnj19w84HLUYCm7QF15WURBsHU,3575
148
- pymammotion-0.5.42.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
149
- pymammotion-0.5.42.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
150
- pymammotion-0.5.42.dist-info/RECORD,,
148
+ pymammotion-0.5.43.dist-info/METADATA,sha256=71E2QhJPO5sCX_c1ddqj1SHjgi7pxcc6O6Yzy90PzRU,3575
149
+ pymammotion-0.5.43.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
150
+ pymammotion-0.5.43.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
151
+ pymammotion-0.5.43.dist-info/RECORD,,