fix: MqttClient 重构为 QObject — publish 通过 Qt 信号排队避免 C 层崩溃
问题: paho-mqtt publish() C 扩展在 Windows 上从 GUI 线程调用时静默崩溃。 修复: - MqttClient 改为 QObject 子类 - publish() 通过 Qt Signal(Qt.QueuedConnection) 排队,_do_publish() 始终在主线程事件循环中执行 paho 调用 - 状态/消息通知改用 Qt Signal 跨线程传递 - 新增 subscribe()/unsubscribe() 公开 API,消除 main.py 直接 访问 _client 的脆弱代码 - 移除 MainWindow 中已不再需要的中间信号 _mqtt_status/_mqtt_msg
This commit is contained in:
+5
-11
@@ -39,8 +39,6 @@ from dbn_mqtt_tool.protocol import (
|
||||
)
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
_mqtt_status = Signal(bool, str)
|
||||
_mqtt_msg = Signal(str, str, object)
|
||||
_devices_changed = Signal()
|
||||
|
||||
def __init__(self):
|
||||
@@ -52,12 +50,10 @@ class MainWindow(QMainWindow):
|
||||
self._mqtt = MqttClient()
|
||||
self._devmgr = DeviceManager()
|
||||
|
||||
self._mqtt.on_status_change(lambda c, m: self._mqtt_status.emit(c, m))
|
||||
self._mqtt.on_message(lambda t, s, p: self._mqtt_msg.emit(t, s, p))
|
||||
self._mqtt._status_notify.connect(self._on_status)
|
||||
self._mqtt._msg_notify.connect(self._on_message)
|
||||
self._devmgr.on_change(lambda: self._devices_changed.emit())
|
||||
|
||||
self._mqtt_status.connect(self._on_status)
|
||||
self._mqtt_msg.connect(self._on_message)
|
||||
self._devices_changed.connect(self._refresh_devices)
|
||||
|
||||
self._build_ui()
|
||||
@@ -695,7 +691,7 @@ class MainWindow(QMainWindow):
|
||||
self._log(f"[自定义] 发布失败: {e}")
|
||||
|
||||
def _custom_subscribe(self):
|
||||
if not self._mqtt.connected or not self._mqtt._client:
|
||||
if not self._mqtt.connected:
|
||||
QMessageBox.warning(self, "提示", "请先连接 Broker")
|
||||
return
|
||||
topic = self._custom_sub_topic.text()
|
||||
@@ -703,7 +699,7 @@ class MainWindow(QMainWindow):
|
||||
return
|
||||
try:
|
||||
qos = int(self._custom_sub_qos.currentText())
|
||||
self._mqtt._client.subscribe(topic, qos=qos)
|
||||
self._mqtt.subscribe(topic, qos=qos)
|
||||
self._custom_subs[topic] = qos
|
||||
# 更新列表
|
||||
found = False
|
||||
@@ -724,13 +720,11 @@ class MainWindow(QMainWindow):
|
||||
items = self._custom_sub_list.selectedItems()
|
||||
if not items:
|
||||
return
|
||||
if not self._mqtt._client:
|
||||
return
|
||||
for item in items:
|
||||
topic = item.text(0)
|
||||
try:
|
||||
if topic in self._custom_subs:
|
||||
self._mqtt._client.unsubscribe(topic)
|
||||
self._mqtt.unsubscribe(topic)
|
||||
del self._custom_subs[topic]
|
||||
idx = self._custom_sub_list.indexOfTopLevelItem(item)
|
||||
self._custom_sub_list.takeTopLevelItem(idx)
|
||||
|
||||
Reference in New Issue
Block a user