mqttxx 2.0.2__py3-none-any.whl → 2.0.3__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.
mqttxx/client.py CHANGED
@@ -284,6 +284,7 @@ class MQTTClient:
284
284
  else:
285
285
  # 修复 P0-3:RPC 请求无处理器时,立即返回错误响应(防止调用方超时)
286
286
  from .protocol import RPCRequest, RPCResponse
287
+
287
288
  if isinstance(msg, RPCRequest):
288
289
  logger.warning(
289
290
  f"收到 RPC 请求但无处理器 - topic: {topic_str}, method: {msg.method}"
@@ -291,9 +292,11 @@ class MQTTClient:
291
292
  # 立即发送错误响应
292
293
  error_response = RPCResponse(
293
294
  request_id=msg.request_id,
294
- error=f"No RPC handler registered for topic: {topic_str}"
295
+ error=f"No RPC handler registered for topic: {topic_str}",
296
+ )
297
+ await self.publish(
298
+ msg.reply_to, json.dumps(error_response.to_dict()), qos=1
295
299
  )
296
- await self.publish(msg.reply_to, json.dumps(error_response.to_dict()), qos=1)
297
300
  else:
298
301
  logger.debug(f"收到消息(无处理器)- topic: {topic_str}")
299
302
 
@@ -381,10 +384,6 @@ class MQTTClient:
381
384
 
382
385
  async def publish(self, topic: str, payload: str, qos: int = 0):
383
386
  """发布消息
384
-
385
- 修复点:
386
- - ✅ P1-2: 未连接时记录警告
387
-
388
387
  Args:
389
388
  topic: 目标主题
390
389
  payload: 消息载荷(字符串)
@@ -399,7 +398,6 @@ class MQTTClient:
399
398
 
400
399
  try:
401
400
  await self._client.publish(topic, payload, qos=qos)
402
- logger.debug(f"消息已发布 - topic: {topic}, qos: {qos}")
403
401
  except aiomqtt.MqttError as e:
404
402
  logger.error(f"发布失败 - topic: {topic}, error: {e}")
405
403
 
mqttxx/rpc.py CHANGED
@@ -75,7 +75,7 @@ class RPCManager:
75
75
  self,
76
76
  client: MQTTClient,
77
77
  config: Optional[RPCConfig] = None,
78
- auth_callback: Optional[AuthCallback] = None
78
+ auth_callback: Optional[AuthCallback] = None,
79
79
  ):
80
80
  """初始化 RPC 管理器
81
81
 
@@ -106,7 +106,9 @@ class RPCManager:
106
106
  # RPC 状态
107
107
  self._pending_calls: dict[str, asyncio.Future] = {} # request_id → Future
108
108
  self._handlers: dict[str, Callable] = {} # method_name → handler
109
- self._pending_calls_lock = asyncio.Lock() # 修复 P0-1:保护 _pending_calls 并发访问
109
+ self._pending_calls_lock = (
110
+ asyncio.Lock()
111
+ ) # 修复 P0-1:保护 _pending_calls 并发访问
110
112
 
111
113
  logger.info("RPCManager 已初始化")
112
114
 
@@ -129,9 +131,10 @@ class RPCManager:
129
131
  # 同步方法也支持
130
132
  return {"result": "ok"}
131
133
  """
134
+
132
135
  def decorator(func: Callable):
133
136
  self._handlers[method_name] = func
134
- logger.success(f"RPC 方法已注册: {method_name}")
137
+ # logger.debug(f"RPC 方法已注册: {method_name}") 无需输出
135
138
  return func
136
139
 
137
140
  return decorator
@@ -171,12 +174,12 @@ class RPCManager:
171
174
  if isinstance(message, RPCRequest):
172
175
  asyncio.create_task(
173
176
  self._handle_request(topic, message),
174
- name=f"rpc_req_{message.request_id[:8]}"
177
+ name=f"rpc_req_{message.request_id[:8]}",
175
178
  )
176
179
  elif isinstance(message, RPCResponse):
177
180
  asyncio.create_task(
178
181
  self._handle_response(topic, message),
179
- name=f"rpc_resp_{message.request_id[:8]}"
182
+ name=f"rpc_resp_{message.request_id[:8]}",
180
183
  )
181
184
 
182
185
  async def call(
@@ -316,8 +319,7 @@ class RPCManager:
316
319
  f"RPC 权限拒绝 - caller: {message.caller_id}, method: {message.method}"
317
320
  )
318
321
  response = RPCResponse(
319
- request_id=message.request_id,
320
- error="Permission denied"
322
+ request_id=message.request_id, error="Permission denied"
321
323
  )
322
324
  await self._send_response(message.reply_to, response)
323
325
  return
@@ -328,8 +330,7 @@ class RPCManager:
328
330
  if not handler:
329
331
  logger.warning(f"方法未找到 - method: {message.method}")
330
332
  response = RPCResponse(
331
- request_id=message.request_id,
332
- error=f"方法未找到: {message.method}"
333
+ request_id=message.request_id, error=f"方法未找到: {message.method}"
333
334
  )
334
335
  else:
335
336
  # 执行方法
@@ -353,22 +354,20 @@ class RPCManager:
353
354
  try:
354
355
  if asyncio.iscoroutinefunction(self._auth_callback):
355
356
  allowed = await self._auth_callback(
356
- message.caller_id,
357
- message.method,
358
- message
357
+ message.caller_id, message.method, message
359
358
  )
360
359
  else:
361
360
  allowed = self._auth_callback(
362
- message.caller_id,
363
- message.method,
364
- message
361
+ message.caller_id, message.method, message
365
362
  )
366
363
  return bool(allowed)
367
364
  except Exception as e:
368
365
  logger.exception(f"权限检查失败: {e}")
369
366
  return False # 默认拒绝
370
367
 
371
- async def _execute_handler(self, handler: Callable, message: RPCRequest) -> RPCResponse:
368
+ async def _execute_handler(
369
+ self, handler: Callable, message: RPCRequest
370
+ ) -> RPCResponse:
372
371
  """执行 RPC 方法处理器
373
372
 
374
373
  Args:
@@ -390,10 +389,7 @@ class RPCManager:
390
389
  result = handler(message.params)
391
390
 
392
391
  logger.debug(f"RPC 方法执行成功 - method: {message.method}")
393
- return RPCResponse(
394
- request_id=message.request_id,
395
- result=result
396
- )
392
+ return RPCResponse(request_id=message.request_id, result=result)
397
393
 
398
394
  except asyncio.CancelledError:
399
395
  # 任务被取消,向上传播
@@ -401,10 +397,7 @@ class RPCManager:
401
397
 
402
398
  except Exception as e:
403
399
  logger.exception(f"RPC 方法执行失败 - method: {message.method}")
404
- return RPCResponse(
405
- request_id=message.request_id,
406
- error=str(e)
407
- )
400
+ return RPCResponse(request_id=message.request_id, error=str(e))
408
401
 
409
402
  async def _send_response(self, topic: str, response: RPCResponse):
410
403
  """发送 RPC 响应
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mqttxx
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: 基于 aiomqtt 的高级 MQTT 客户端和 RPC 框架
5
5
  Author: MQTTX Team
6
6
  License: MIT
@@ -0,0 +1,12 @@
1
+ mqttxx/__init__.py,sha256=9jhV_niQTYU2D4aD4AfVvWAAfbYf4o2vjwbwSMA_Rv4,1722
2
+ mqttxx/client.py,sha256=0wtw8fXW1buqnGbKOrg5sBJDORdSoHb3ErapiK3pkl4,16358
3
+ mqttxx/config.py,sha256=MlhayABPcyHWAQR1kkWT5SNlVPIcJ5j8tBikvt1kMNE,5101
4
+ mqttxx/conventions.py,sha256=d_OwOvLG4cdptZ2wmrsKe055LRVZXMO0pmt-OAgJhvI,4507
5
+ mqttxx/exceptions.py,sha256=EC9NZmvZbfrK9iEdSyoYt4pUl0dp7yVup8mjOfgBaMw,3704
6
+ mqttxx/protocol.py,sha256=mZfGY3naGGT_mDsv9enFPiAgUFjoqA5WbZhaT5xYCBQ,5313
7
+ mqttxx/rpc.py,sha256=diXZg-H_MB6SiXll4Q9voh2ztC21_UAOgMKeLyBBJ4s,13597
8
+ mqttxx-2.0.3.dist-info/LICENSE,sha256=tfwCF8HPjAvvq_veljjH3_YL90X6ttkjTpRl3BGcXTg,1067
9
+ mqttxx-2.0.3.dist-info/METADATA,sha256=DuDs0jX9uoJD6dg_7r4uspORGjKsc_jN1WHRx27zZB8,11545
10
+ mqttxx-2.0.3.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
11
+ mqttxx-2.0.3.dist-info/top_level.txt,sha256=4SNRXgOpGCT6ThBzAb8zhUmTyZwnIracAIJWAdXXzw0,7
12
+ mqttxx-2.0.3.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- mqttxx/__init__.py,sha256=9jhV_niQTYU2D4aD4AfVvWAAfbYf4o2vjwbwSMA_Rv4,1722
2
- mqttxx/client.py,sha256=mpJS4oTm9V9uqoU4kiRlNK-M8pBVb5mImvxvjyIi57E,16452
3
- mqttxx/config.py,sha256=MlhayABPcyHWAQR1kkWT5SNlVPIcJ5j8tBikvt1kMNE,5101
4
- mqttxx/conventions.py,sha256=d_OwOvLG4cdptZ2wmrsKe055LRVZXMO0pmt-OAgJhvI,4507
5
- mqttxx/exceptions.py,sha256=EC9NZmvZbfrK9iEdSyoYt4pUl0dp7yVup8mjOfgBaMw,3704
6
- mqttxx/protocol.py,sha256=mZfGY3naGGT_mDsv9enFPiAgUFjoqA5WbZhaT5xYCBQ,5313
7
- mqttxx/rpc.py,sha256=9klpfn3Qh2keq8Sk312n0psXa3BSI8ThlFXJZ0O1_wU,13749
8
- mqttxx-2.0.2.dist-info/LICENSE,sha256=tfwCF8HPjAvvq_veljjH3_YL90X6ttkjTpRl3BGcXTg,1067
9
- mqttxx-2.0.2.dist-info/METADATA,sha256=19jtxWnJVWu0vsr5qL5xQl8akMy_H-oktO-x5pPA-Gs,11545
10
- mqttxx-2.0.2.dist-info/WHEEL,sha256=Z4pYXqR_rTB7OWNDYFOm1qRk0RX6GFP2o8LgvP453Hk,91
11
- mqttxx-2.0.2.dist-info/top_level.txt,sha256=4SNRXgOpGCT6ThBzAb8zhUmTyZwnIracAIJWAdXXzw0,7
12
- mqttxx-2.0.2.dist-info/RECORD,,
File without changes