Просмотр исходного кода

主进程与守护进程分开

flower_linux 3 месяцев назад
Родитель
Сommit
843c878449
56 измененных файлов с 5959 добавлено и 275 удалено
  1. 133 1
      CMakeLists.txt
  2. 84 0
      config/DBUS_SETUP.md
  3. 15 0
      config/com.softbus.Daemon.conf
  4. 12 0
      config/com.softbus.Daemon.system.conf
  5. 53 0
      config/install_dbus_config.sh
  6. 44 0
      config/reload_dbus.sh
  7. 451 0
      docs/串口资源管理方案.md
  8. 737 0
      docs/协议插件架构方案.md
  9. 201 0
      docs/守护进程与主应用关系说明.md
  10. 144 0
      docs/守护进程架构说明.md
  11. 8 4
      main.cpp
  12. 326 3
      mainwindow.cpp
  13. 27 0
      mainwindow.h
  14. 275 17
      src/api/SoftBusAPI.cpp
  15. 34 0
      src/api/SoftBusAPI.h
  16. 29 29
      src/can_manager/can_manager.cpp
  17. 7 8
      src/core/CoreService.cpp
  18. 7 7
      src/core/SoftBusCore.cpp
  19. 5 5
      src/core/dal/mapper/DataMapper.cpp
  20. 3 3
      src/core/pal/serial/SerialProtocolAdapter.cpp
  21. 5 5
      src/core/sbl/dispatcher/MessageDispatcher.cpp
  22. 3 3
      src/core/sbl/pubsub/TopicTree.cpp
  23. 533 0
      src/daemon/daemon_client.cpp
  24. 203 0
      src/daemon/daemon_client.h
  25. 102 0
      src/daemon/daemon_connection_dialog.cpp
  26. 50 0
      src/daemon/daemon_connection_dialog.h
  27. 105 0
      src/daemon/daemon_main.cpp
  28. 229 0
      src/daemon/daemon_message_flow_widget.cpp
  29. 99 0
      src/daemon/daemon_message_flow_widget.h
  30. 389 0
      src/daemon/daemon_service.cpp
  31. 204 0
      src/daemon/daemon_service.h
  32. 230 0
      src/device_config/device_log_dialog.cpp
  33. 68 0
      src/device_config/device_log_dialog.h
  34. 84 6
      src/device_config/device_tree_widget.cpp
  35. 1 0
      src/device_config/device_tree_widget.h
  36. 7 0
      src/device_config/device_tree_widget.ui
  37. 3 3
      src/libmodbus/modbus_config_widget.cpp
  38. 81 0
      src/protocol_plugin/IProtocolParser.h
  39. 210 0
      src/protocol_plugin/ProtocolPluginManager.cpp
  40. 126 0
      src/protocol_plugin/ProtocolPluginManager.h
  41. 10 10
      src/serial_manager/serial_data_buffer.cpp
  42. 36 23
      src/serial_manager/serial_manager.cpp
  43. 5 0
      src/serial_manager/serial_manager.h
  44. 85 10
      src/serial_manager/serial_parser_thread.cpp
  45. 17 9
      src/serial_manager/serial_parser_thread.h
  46. 5 5
      src/serial_manager/serial_storage_thread.cpp
  47. 173 0
      src/settings/settings_dialog.cpp
  48. 90 0
      src/settings/settings_dialog.h
  49. 62 62
      src/soft_bus_core/soft_bus_core.cpp
  50. 21 0
      src/soft_bus_core/soft_bus_core.h
  51. 23 0
      src/utils/logging.h
  52. 46 28
      src/view_can/viewcan.cpp
  53. 5 0
      src/view_can/viewcan.h
  54. 2 1
      src/view_serial/serial_data_widget.cpp
  55. 47 33
      src/view_serial/serialdockpage.cpp
  56. 5 0
      src/view_serial/serialdockpage.h

+ 133 - 1
CMakeLists.txt

@@ -1,13 +1,15 @@
 cmake_minimum_required(VERSION 3.19)
 project(soft_bus LANGUAGES CXX)
 
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
 # 设置C++标准
 set(CMAKE_CXX_STANDARD 20)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_AUTORCC ON)
 set(CMAKE_AUTOMOC ON)
 # 查找Qt6
-find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets SerialPort Charts Sql)
+find_package(Qt6 6.5 REQUIRED COMPONENTS Core Widgets SerialPort Charts Sql DBus)
 
 # 检测编译平台
 if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
@@ -74,6 +76,7 @@ qt_add_executable(soft_bus
     src/view_can/viewcan.h src/view_can/viewcan.cpp src/view_can/viewcan.ui
     src/view_can/can_data_widget.h src/view_can/can_data_widget.cpp src/view_can/can_data_widget.ui
     src/device_config/device_tree_widget.h src/device_config/device_tree_widget.cpp src/device_config/device_tree_widget.ui
+    src/device_config/device_log_dialog.h src/device_config/device_log_dialog.cpp
     src/libmodbus/modbus_config_widget.h src/libmodbus/modbus_config_widget.cpp src/libmodbus/modbus_config_widget.ui
     src/libmodbus/src/modbus.c src/libmodbus/src/modbus-data.c
     src/libmodbus/src/modbus-rtu.c src/libmodbus/src/modbus-tcp.c
@@ -121,6 +124,23 @@ qt_add_executable(soft_bus
     src/api/SoftBusAPI.h
     src/api/SoftBusAPI.cpp
 
+    # 新增:守护进程客户端(用于 GUI 连接守护进程)
+    src/daemon/daemon_client.h
+    src/daemon/daemon_client.cpp
+    src/daemon/daemon_connection_dialog.h
+    src/daemon/daemon_connection_dialog.cpp
+    src/daemon/daemon_message_flow_widget.h
+    src/daemon/daemon_message_flow_widget.cpp
+
+    # 新增:协议插件管理器
+    src/protocol_plugin/ProtocolPluginManager.h
+    src/protocol_plugin/ProtocolPluginManager.cpp
+    src/protocol_plugin/IProtocolParser.h
+
+    # 新增:设置对话框
+    src/settings/settings_dialog.h
+    src/settings/settings_dialog.cpp
+
 )
 
 # 关键修改:链接ADS库(使用目标名称)
@@ -156,6 +176,7 @@ target_link_libraries(soft_bus
         Qt6::SerialPort
         Qt6::Charts
         Qt6::Sql
+        Qt6::DBus
         pthread
 )
 
@@ -224,3 +245,114 @@ qt_generate_deploy_app_script(
     NO_UNSUPPORTED_PLATFORM_ERROR
 )
 install(SCRIPT ${deploy_script})
+
+# ============================================================================
+# 守护进程可执行文件(独立的核心服务进程)
+# ============================================================================
+qt_add_executable(soft_bus_daemon
+    src/daemon/daemon_main.cpp
+    src/daemon/daemon_service.h
+    src/daemon/daemon_service.cpp
+    
+    # 核心服务依赖
+    src/core/CoreService.h
+    src/core/CoreService.cpp
+    src/core/SoftBusCore.h
+    src/core/SoftBusCore.cpp
+    
+    # 软总线核心
+    src/soft_bus_core/soft_bus_core.cpp
+    src/soft_bus_core/soft_bus_core.h
+    
+    # 串口管理器(如果需要)
+    src/serial_manager/serial_manager.cpp
+    src/serial_manager/serial_manager.h
+    src/serial_manager/serial_data_buffer.cpp
+    src/serial_manager/serial_data_buffer.h
+    src/serial_manager/serial_storage_thread.cpp
+    src/serial_manager/serial_storage_thread.h
+    src/serial_manager/serial_parser_thread.cpp
+    src/serial_manager/serial_parser_thread.h
+    
+    # 设备管理
+    src/devices/DeviceWatcherBase.cpp
+    src/devices/DeviceWatcherBase.h
+    src/devices/DeviceManager.cpp
+    src/devices/DeviceManager.h
+    src/devices/serial/SerialPortInfo.h
+    src/devices/serial/SerialPortWatcher.cpp
+    src/devices/serial/SerialPortWatcher.h
+    src/devices/platform/linux/UdevMonitor.h
+    src/devices/platform/linux/UdevMonitor.cpp
+    src/devices/platform/linux/LinuxDeviceUtils.h
+    
+    # CAN 管理器(如果需要)
+    src/can_manager/can_manager.cpp
+    src/can_manager/can_manager.h
+    
+    # 公共域模型
+    src/common/dom/DomBase.h
+    src/common/types.h
+    
+    # 核心层
+    src/core/pal/interfaces/IProtocolAdapter.h
+    src/core/pal/serial/SerialProtocolAdapter.cpp
+    src/core/pal/serial/SerialProtocolAdapter.h
+    src/core/dal/mapper/DataMapper.cpp
+    src/core/dal/mapper/DataMapper.h
+    src/core/dal/processor/DataProcessor.cpp
+    src/core/dal/processor/DataProcessor.h
+    src/core/sbl/dispatcher/MessageDispatcher.cpp
+    src/core/sbl/dispatcher/MessageDispatcher.h
+    src/core/sbl/pubsub/TopicTree.cpp
+    src/core/sbl/pubsub/TopicTree.h
+    
+    # 统一接口层 (API) - 守护进程也需要使用
+    src/api/SoftBusAPI.h
+    src/api/SoftBusAPI.cpp
+    
+    # 协议插件管理器
+    src/protocol_plugin/ProtocolPluginManager.h
+    src/protocol_plugin/ProtocolPluginManager.cpp
+    src/protocol_plugin/IProtocolParser.h
+)
+
+# 守护进程只需要 Qt Core 和 DBus,不需要 Widgets
+target_link_libraries(soft_bus_daemon
+    PRIVATE
+        Qt6::Core
+        Qt6::DBus
+        Qt6::SerialPort
+        Qt6::Sql
+        pthread
+)
+
+# 守护进程的包含路径
+target_include_directories(soft_bus_daemon PRIVATE 
+    ${PROJECT_SOURCE_DIR}/src
+    ${PROJECT_SOURCE_DIR}/src/libmodbus/src
+    ${CAN_API_DIR}/include
+)
+
+# 为守护进程添加编译定义,禁用 DaemonClient 功能
+target_compile_definitions(soft_bus_daemon PRIVATE SOFT_BUS_DAEMON_BUILD)
+
+# Linux 特定的守护进程链接
+if(UNIX AND NOT APPLE)
+    find_library(UDEV_LIB udev REQUIRED)
+    if(UDEV_LIB)
+        target_link_libraries(soft_bus_daemon PRIVATE ${UDEV_LIB})
+    endif()
+    
+    target_link_directories(soft_bus_daemon PRIVATE "${CAN_API_DIR}/lib")
+    target_link_libraries(soft_bus_daemon PRIVATE 
+        "-Wl,--whole-archive"
+        "${CAN_API_LIB}"
+        "-Wl,--no-whole-archive"
+    )
+endif()
+
+# 安装守护进程
+install(TARGETS soft_bus_daemon
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)

+ 84 - 0
config/DBUS_SETUP.md

@@ -0,0 +1,84 @@
+# D-Bus 配置说明
+
+## 问题描述
+
+如果遇到以下错误:
+```
+Failed to register D-Bus service: "Connection \":1.179\" is not allowed to own the service \"com.softbus.Daemon\" due to security policies in the configuration file"
+```
+
+这是因为 D-Bus 安全策略不允许应用程序注册 `com.softbus.Daemon` 服务。
+
+## 解决方案
+
+### 方法 1:使用安装脚本(推荐)
+
+```bash
+cd /path/to/soft_bus/soft_bus
+bash config/install_dbus_config.sh
+```
+
+### 方法 2:手动安装
+
+1. 创建配置目录(如果不存在):
+   ```bash
+   mkdir -p ~/.config/dbus-1/session.d
+   ```
+
+2. 复制配置文件:
+   ```bash
+   cp config/com.softbus.Daemon.conf ~/.config/dbus-1/session.d/
+   ```
+
+### 应用配置
+
+配置文件安装后,需要重启 D-Bus 会话才能生效。有以下几种方法:
+
+#### 方法 A:重新登录(最安全)
+- 注销并重新登录到桌面环境
+
+#### 方法 B:重启 D-Bus 会话守护进程
+```bash
+# 查找会话 D-Bus 守护进程
+ps aux | grep dbus-daemon | grep session
+
+# 重启会话 D-Bus(会自动重启)
+killall -HUP dbus-daemon
+```
+
+#### 方法 C:重启桌面环境
+- 重启桌面环境(如 GNOME、KDE 等)
+
+### 验证配置
+
+安装并重启后,可以验证配置是否生效:
+
+```bash
+# 检查配置文件是否存在
+ls -l ~/.config/dbus-1/session.d/com.softbus.Daemon.conf
+
+# 检查 D-Bus 服务是否可用
+dbus-send --session --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep softbus
+```
+
+## 系统级安装(可选)
+
+如果需要为所有用户安装配置(需要 root 权限):
+
+```bash
+sudo bash config/install_dbus_config.sh --system
+```
+
+## 配置文件说明
+
+配置文件 `com.softbus.Daemon.conf` 包含以下策略:
+
+- **允许所有用户注册服务**:`<allow own="com.softbus.Daemon"/>`
+- **允许发送消息到服务**:`<allow send_destination="com.softbus.Daemon"/>`
+- **允许接收服务消息**:`<allow receive_sender="com.softbus.Daemon"/>`
+
+这些策略确保守护进程可以正常注册和运行。
+
+
+
+

+ 15 - 0
config/com.softbus.Daemon.conf

@@ -0,0 +1,15 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <!-- 允许所有用户注册 com.softbus.Daemon 服务 -->
+  <policy context="default">
+    <allow own="com.softbus.Daemon"/>
+    <allow send_destination="com.softbus.Daemon"/>
+    <allow receive_sender="com.softbus.Daemon"/>
+  </policy>
+</busconfig>
+
+
+
+

+ 12 - 0
config/com.softbus.Daemon.system.conf

@@ -0,0 +1,12 @@
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+  <!-- 允许用户 dt 注册 com.softbus.Daemon 服务(系统总线) -->
+  <policy user="dt">
+    <allow own="com.softbus.Daemon"/>
+    <allow send_destination="com.softbus.Daemon"/>
+    <allow receive_sender="com.softbus.Daemon"/>
+  </policy>
+</busconfig>
+

+ 53 - 0
config/install_dbus_config.sh

@@ -0,0 +1,53 @@
+#!/bin/bash
+# 安装 D-Bus 配置文件脚本
+# 用于允许 soft_bus_daemon 注册 D-Bus 服务
+
+set -e
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+CONFIG_FILE="$SCRIPT_DIR/com.softbus.Daemon.conf"
+SESSION_CONFIG_DIR="$HOME/.config/dbus-1/session.d"
+SYSTEM_CONFIG_DIR="/etc/dbus-1/session.d"
+
+echo "Installing D-Bus configuration for soft_bus_daemon..."
+
+# 创建用户级配置目录(推荐)
+if [ ! -d "$SESSION_CONFIG_DIR" ]; then
+    echo "Creating directory: $SESSION_CONFIG_DIR"
+    mkdir -p "$SESSION_CONFIG_DIR"
+fi
+
+# 复制配置文件到用户目录
+if [ -f "$CONFIG_FILE" ]; then
+    echo "Copying configuration to: $SESSION_CONFIG_DIR/"
+    cp "$CONFIG_FILE" "$SESSION_CONFIG_DIR/"
+    echo "✓ Configuration installed successfully!"
+    echo ""
+    echo "Note: You may need to restart your D-Bus session or log out/in for changes to take effect."
+    echo "Alternatively, restart the dbus-daemon:"
+    echo "  killall dbus-daemon  # This will restart automatically"
+else
+    echo "Error: Configuration file not found: $CONFIG_FILE"
+    exit 1
+fi
+
+# 可选:安装到系统目录(需要 root 权限)
+if [ "$1" == "--system" ]; then
+    if [ "$EUID" -ne 0 ]; then
+        echo "Error: --system option requires root privileges"
+        exit 1
+    fi
+    
+    if [ ! -d "$SYSTEM_CONFIG_DIR" ]; then
+        echo "Creating directory: $SYSTEM_CONFIG_DIR"
+        mkdir -p "$SYSTEM_CONFIG_DIR"
+    fi
+    
+    echo "Copying configuration to: $SYSTEM_CONFIG_DIR/"
+    cp "$CONFIG_FILE" "$SYSTEM_CONFIG_DIR/"
+    echo "✓ System-wide configuration installed successfully!"
+fi
+
+
+
+

+ 44 - 0
config/reload_dbus.sh

@@ -0,0 +1,44 @@
+#!/bin/bash
+# 重新加载 D-Bus 会话配置
+# 注意:这可能会影响当前会话中的其他应用程序
+
+echo "Reloading D-Bus session configuration..."
+echo "Warning: This may affect other applications in your session."
+echo ""
+
+# 查找会话 D-Bus 守护进程
+SESSION_DBUS_PID=$(ps aux | grep -E "dbus-daemon.*session" | grep -v grep | awk '{print $2}' | head -1)
+
+if [ -z "$SESSION_DBUS_PID" ]; then
+    echo "Error: Could not find session D-Bus daemon"
+    exit 1
+fi
+
+echo "Found session D-Bus daemon (PID: $SESSION_DBUS_PID)"
+echo ""
+echo "To apply the new configuration, you have two options:"
+echo ""
+echo "Option 1 (Recommended): Log out and log back in"
+echo "  This is the safest way to reload D-Bus configuration"
+echo ""
+echo "Option 2: Restart D-Bus session daemon"
+echo "  This will restart automatically, but may briefly interrupt D-Bus services"
+echo "  Run: killall -HUP dbus-daemon"
+echo ""
+read -p "Do you want to restart D-Bus now? (y/N): " -n 1 -r
+echo ""
+
+if [[ $REPLY =~ ^[Yy]$ ]]; then
+    echo "Restarting D-Bus session daemon..."
+    killall -HUP dbus-daemon
+    sleep 1
+    echo "✓ D-Bus session daemon restarted"
+    echo ""
+    echo "The configuration should now be active. Try running your daemon again."
+else
+    echo "Skipped. Please log out and log back in to apply the configuration."
+fi
+
+
+
+

+ 451 - 0
docs/串口资源管理方案.md

@@ -0,0 +1,451 @@
+# 串口资源管理方案
+
+## 🔴 问题描述
+
+当前架构中,`soft_bus`(主应用)和 `soft_bus_daemon`(守护进程)是**两个独立的进程**,各自有独立的 `SerialManager` 实例。
+
+**问题**:
+- 如果守护进程占用串口(因为底层硬件持续传输数据)
+- 主应用再尝试打开同一个串口会**失败**(串口是独占资源)
+- 导致主应用无法使用串口功能
+
+## ✅ 解决方案:守护进程统一管理串口
+
+### 架构设计
+
+```
+┌──────────────────────┐                    ┌──────────────────────┐
+│   soft_bus           │                    │  soft_bus_daemon      │
+│   (主应用)            │                    │  (守护进程)            │
+│                      │                    │                      │
+│  ┌────────────────┐  │                    │  ┌────────────────┐  │
+│  │ SoftBusAPI     │  │                    │  │ SoftBusAPI     │  │
+│  │ (不创建串口)    │  │                    │  │ (管理串口)      │  │
+│  └────────────────┘  │                    │  └────────────────┘  │
+│         │            │                    │         │            │
+│         │            │                    │         ▼            │
+│         │            │                    │  ┌────────────────┐  │
+│         │            │                    │  │ SerialManager  │  │
+│         │            │                    │  │ (打开串口)      │  │
+│         │            │                    │  └────────────────┘  │
+│         │            │                    │         │            │
+│         │            │                    │         ▼            │
+│         │            │                    │  ┌────────────────┐  │
+│         │            │                    │  │ /dev/ttyUSB0   │  │
+│         │            │                    │  │ (串口设备)      │  │
+│         │            │                    │  └────────────────┘  │
+│         │            │                    │                      │
+└─────────┼────────────┘                    └─────────┼────────────┘
+          │                                         │
+          │         D-Bus 通信                        │
+          │  ┌─────────────────────────────┐          │
+          └─►│ DaemonService              │◄─────────┘
+             │ (串口操作接口)              │
+             └─────────────────────────────┘
+             
+             数据流向:
+             1. 主应用通过 D-Bus 请求打开/关闭串口
+             2. 守护进程管理串口,接收数据
+             3. 数据通过 D-Bus 信号或数据库传递给主应用
+```
+
+### 实现步骤
+
+#### 1. 扩展 DaemonService 接口
+
+在 `daemon_service.h` 中添加串口管理接口:
+
+```cpp
+// daemon_service.h
+public slots:
+    // ... 现有接口 ...
+    
+    /**
+     * @brief 打开串口
+     * @param portName 串口名称(如 "ttyUSB0")
+     * @param baudRate 波特率
+     * @return 成功返回 true
+     */
+    bool openSerialPort(const QString& portName, int baudRate);
+    
+    /**
+     * @brief 关闭串口
+     * @param portName 串口名称
+     */
+    void closeSerialPort(const QString& portName);
+    
+    /**
+     * @brief 获取已打开的串口列表
+     * @return 串口名称列表(JSON 格式)
+     */
+    QString getOpenedSerialPorts() const;
+    
+    /**
+     * @brief 发送数据到串口
+     * @param portName 串口名称
+     * @param data 数据(Base64 编码)
+     * @return 成功返回 true
+     */
+    bool writeSerialData(const QString& portName, const QString& data);
+
+signals:
+    // ... 现有信号 ...
+    
+    /**
+     * @brief 串口数据接收时发出
+     * @param portName 串口名称
+     * @param data 数据(Base64 编码)
+     */
+    void serialDataReceived(const QString& portName, const QString& data);
+    
+    /**
+     * @brief 串口状态变化时发出
+     * @param portName 串口名称
+     * @param isOpen 是否打开
+     */
+    void serialPortStatusChanged(const QString& portName, bool isOpen);
+```
+
+#### 2. 实现 DaemonService 串口接口
+
+在 `daemon_service.cpp` 中实现:
+
+```cpp
+// daemon_service.cpp
+#include "api/SoftBusAPI.h"
+
+bool DaemonService::openSerialPort(const QString& portName, int baudRate)
+{
+    if (!m_coreService || !m_coreService->isInitialized()) {
+        return false;
+    }
+    
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (!api) {
+        return false;
+    }
+    
+    // 查找串口信息
+    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
+    for (const QSerialPortInfo& info : ports) {
+        if (info.portName() == portName) {
+            // 设置串口配置
+            SerialManager::SerialConfig config;
+            config.baudRate = static_cast<QSerialPort::BaudRate>(baudRate);
+            api->setSerialConfig(config);
+            
+            // 打开串口
+            return api->openSerialPort(info);
+        }
+    }
+    
+    return false;
+}
+
+void DaemonService::closeSerialPort(const QString& portName)
+{
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api) {
+        api->closeSerialPort(portName);
+    }
+}
+
+QString DaemonService::getOpenedSerialPorts() const
+{
+    QJsonArray ports;
+    
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api) {
+        QStringList portList = api->getOpenedSerialPorts();
+        for (const QString& port : portList) {
+            ports.append(port);
+        }
+    }
+    
+    QJsonObject result;
+    result["ports"] = ports;
+    return QJsonDocument(result).toJson(QJsonDocument::Compact);
+}
+
+bool DaemonService::writeSerialData(const QString& portName, const QString& data)
+{
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (!api) {
+        return false;
+    }
+    
+    // Base64 解码
+    QByteArray byteData = QByteArray::fromBase64(data.toUtf8());
+    return api->writeSerialData(portName, byteData);
+}
+```
+
+#### 3. 连接串口数据信号
+
+在 `daemon_service.cpp` 构造函数中连接信号:
+
+```cpp
+DaemonService::DaemonService(CoreService* coreService, QObject* parent)
+    : QObject(parent)
+    , m_coreService(coreService)
+    // ... 其他初始化 ...
+{
+    // ... 现有代码 ...
+    
+    // 连接串口数据信号
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api) {
+        connect(api, &SoftBusAPI::serialDataReceived,
+                this, [this](const QString& portName, const QByteArray& data) {
+                    // Base64 编码后通过 D-Bus 发送
+                    QString base64Data = QString::fromUtf8(data.toBase64());
+                    emit serialDataReceived(portName, base64Data);
+                });
+    }
+}
+```
+
+#### 4. 扩展 DaemonClient 接口
+
+在 `daemon_client.h` 中添加串口操作接口:
+
+```cpp
+// daemon_client.h
+public:
+    // ... 现有接口 ...
+    
+    /**
+     * @brief 打开串口(通过守护进程)
+     * @param portName 串口名称
+     * @param baudRate 波特率
+     * @return 成功返回 true
+     */
+    bool openSerialPort(const QString& portName, int baudRate);
+    
+    /**
+     * @brief 关闭串口(通过守护进程)
+     * @param portName 串口名称
+     */
+    void closeSerialPort(const QString& portName);
+    
+    /**
+     * @brief 获取已打开的串口列表
+     * @return 串口名称列表
+     */
+    QStringList getOpenedSerialPorts() const;
+    
+    /**
+     * @brief 发送数据到串口(通过守护进程)
+     * @param portName 串口名称
+     * @param data 数据
+     * @return 成功返回 true
+     */
+    bool writeSerialData(const QString& portName, const QByteArray& data);
+
+signals:
+    // ... 现有信号 ...
+    
+    /**
+     * @brief 串口数据接收时发出
+     * @param portName 串口名称
+     * @param data 数据
+     */
+    void serialDataReceived(const QString& portName, const QByteArray& data);
+    
+    /**
+     * @brief 串口状态变化时发出
+     * @param portName 串口名称
+     * @param isOpen 是否打开
+     */
+    void serialPortStatusChanged(const QString& portName, bool isOpen);
+```
+
+#### 5. 实现 DaemonClient 串口接口
+
+在 `daemon_client.cpp` 中实现:
+
+```cpp
+// daemon_client.cpp
+bool DaemonClient::openSerialPort(const QString& portName, int baudRate)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return false;
+    }
+    
+    QDBusReply<bool> reply = m_interface->call("openSerialPort", portName, baudRate);
+    return reply.isValid() && reply.value();
+}
+
+void DaemonClient::closeSerialPort(const QString& portName)
+{
+    if (m_interface && m_interface->isValid()) {
+        m_interface->call("closeSerialPort", portName);
+    }
+}
+
+QStringList DaemonClient::getOpenedSerialPorts() const
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return QStringList();
+    }
+    
+    QDBusReply<QString> reply = m_interface->call("getOpenedSerialPorts");
+    if (reply.isValid()) {
+        QJsonDocument doc = QJsonDocument::fromJson(reply.value().toUtf8());
+        QJsonObject obj = doc.object();
+        QJsonArray ports = obj["ports"].toArray();
+        
+        QStringList result;
+        for (const QJsonValue& value : ports) {
+            result.append(value.toString());
+        }
+        return result;
+    }
+    
+    return QStringList();
+}
+
+bool DaemonClient::writeSerialData(const QString& portName, const QByteArray& data)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return false;
+    }
+    
+    // Base64 编码
+    QString base64Data = QString::fromUtf8(data.toBase64());
+    QDBusReply<bool> reply = m_interface->call("writeSerialData", portName, base64Data);
+    return reply.isValid() && reply.value();
+}
+```
+
+#### 6. 连接 D-Bus 信号
+
+在 `daemon_client.cpp` 的 `connectToDaemon()` 中连接信号:
+
+```cpp
+bool DaemonClient::connectToDaemon()
+{
+    // ... 现有代码 ...
+    
+    // 连接串口信号
+    connection.connect(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        "serialDataReceived",
+        this,
+        SLOT(onSerialDataReceived(QString, QString))
+    );
+    
+    connection.connect(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        "serialPortStatusChanged",
+        this,
+        SLOT(onSerialPortStatusChanged(QString, bool))
+    );
+    
+    // ... 其他代码 ...
+}
+
+void DaemonClient::onSerialDataReceived(const QString& portName, const QString& base64Data)
+{
+    QByteArray data = QByteArray::fromBase64(base64Data.toUtf8());
+    emit serialDataReceived(portName, data);
+}
+
+void DaemonClient::onSerialPortStatusChanged(const QString& portName, bool isOpen)
+{
+    emit serialPortStatusChanged(portName, isOpen);
+}
+```
+
+#### 7. 修改主应用的串口使用方式
+
+在主应用中,不再直接使用 `SoftBusAPI` 的串口接口,而是通过 `DaemonClient`:
+
+```cpp
+// 原来的方式(不再使用)
+// SoftBusAPI* api = SoftBusAPI::instance();
+// api->openSerialPort(portInfo);
+
+// 新的方式(通过守护进程)
+DaemonClient* client = DaemonClient::instance();
+if (client->connectToDaemon()) {
+    client->openSerialPort("ttyUSB0", 9600);
+    
+    // 连接数据接收信号
+    connect(client, &DaemonClient::serialDataReceived,
+            this, [this](const QString& portName, const QByteArray& data) {
+                // 处理接收到的数据
+                qDebug() << "Received data from" << portName << ":" << data.toHex();
+            });
+}
+```
+
+#### 8. 守护进程自动启动串口发现
+
+在守护进程启动时,自动开始串口发现:
+
+```cpp
+// daemon_main.cpp
+int main(int argc, char *argv[])
+{
+    // ... 现有代码 ...
+    
+    // 初始化核心服务
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->initialize()) {
+        qCritical() << "Failed to initialize CoreService";
+        return 1;
+    }
+    
+    // 启动设备发现(包括串口)
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api) {
+        api->startDeviceDiscovery(5000);  // 每5秒扫描一次
+    }
+    
+    // ... 其他代码 ...
+}
+```
+
+## 📋 实施建议
+
+### 阶段1:基础实现(推荐先做)
+1. ✅ 扩展 `DaemonService` 添加串口接口
+2. ✅ 扩展 `DaemonClient` 添加串口接口
+3. ✅ 实现基本的打开/关闭/发送功能
+
+### 阶段2:数据传递
+1. ✅ 实现 D-Bus 信号传递串口数据
+2. ✅ 主应用接收并显示数据
+
+### 阶段3:完整功能
+1. ✅ 串口配置(波特率等)通过 D-Bus 传递
+2. ✅ 错误处理和状态反馈
+3. ✅ 自动重连机制
+
+## ⚠️ 注意事项
+
+1. **串口独占性**:确保只有守护进程打开串口,主应用不再直接打开
+2. **数据编码**:D-Bus 传递二进制数据需要使用 Base64 编码
+3. **性能考虑**:高频数据可能影响 D-Bus 性能,考虑批量传输或数据库存储
+4. **错误处理**:守护进程关闭或重启时,主应用需要重新连接
+
+## 🎯 优势
+
+1. ✅ **资源统一管理**:串口由守护进程统一管理,避免冲突
+2. ✅ **进程隔离**:主应用崩溃不影响串口通信
+3. ✅ **数据共享**:数据通过数据库和 D-Bus 共享
+4. ✅ **灵活扩展**:可以轻松添加更多硬件资源管理
+
+## 📝 总结
+
+通过让守护进程统一管理串口资源,主应用通过 D-Bus 操作串口,可以:
+- ✅ 避免串口资源冲突
+- ✅ 确保底层硬件数据持续接收
+- ✅ 主应用可以正常使用串口功能
+- ✅ 提高系统稳定性和可维护性
+

+ 737 - 0
docs/协议插件架构方案.md

@@ -0,0 +1,737 @@
+# 协议插件架构方案
+
+## 🤔 问题
+
+如果以后需要动态添加协议插件,这些插件应该放在哪里?
+- 守护进程中?
+- 主应用中?
+- 还是两者都支持?
+
+## 📊 当前架构分析
+
+### 当前协议解析位置
+
+```
+┌─────────────────────────────────────────┐
+│  守护进程 (soft_bus_daemon)              │
+│                                          │
+│  ┌────────────────────────────────────┐  │
+│  │ SerialManager                     │  │
+│  │  ┌──────────────────────────────┐ │  │
+│  │  │ SerialParserThread           │ │  │
+│  │  │ - parseModbusRTU()           │ │  │
+│  │  │ - parseModbusASCII()         │ │  │
+│  │  │ - parseCustomProtocol()      │ │  │
+│  │  │ (硬编码协议解析)              │ │  │
+│  │  └──────────────────────────────┘ │  │
+│  └────────────────────────────────────┘  │
+│                                          │
+│  硬件设备 → 串口 → 数据接收 → 协议解析    │
+└─────────────────────────────────────────┘
+```
+
+**问题**:
+- 协议解析逻辑硬编码在 `SerialParserThread` 中
+- 添加新协议需要修改守护进程代码并重新编译
+- 无法动态加载协议插件
+
+## ✅ 推荐方案:守护进程支持协议插件机制
+
+### 架构设计
+
+```
+┌─────────────────────────────────────────────────────────┐
+│  守护进程 (soft_bus_daemon)                             │
+│                                                         │
+│  ┌───────────────────────────────────────────────────┐ │
+│  │ SerialManager                                     │ │
+│  │  ┌─────────────────────────────────────────────┐ │ │
+│  │  │ SerialParserThread                         │ │ │
+│  │  │  ┌───────────────────────────────────────┐  │ │ │
+│  │  │  │ ProtocolPluginManager               │  │ │ │
+│  │  │  │ - loadPlugin(pluginPath)             │  │ │ │
+│  │  │  │ - unloadPlugin(pluginId)             │  │ │ │
+│  │  │  │ - getPlugin(protocolName)             │  │ │ │
+│  │  │  └──────────────────────────────────────┘  │ │ │
+│  │  │         │                                   │ │ │
+│  │  │         ▼                                   │ │ │
+│  │  │  ┌──────────────────────────────────────┐  │ │ │
+│  │  │  │ IProtocolParser (接口)               │  │ │ │
+│  │  │  │ - parseFrame(data)                    │  │ │ │
+│  │  │  │ - extractFrame(buffer)                │  │ │ │
+│  │  │  │ - getName()                           │  │ │ │
+│  │  │  └──────────────────────────────────────┘  │ │ │
+│  │  │         ▲                                   │ │ │
+│  │  │         │ 实现                               │ │ │
+│  │  │  ┌──────┴──────┬──────────┬─────────────┐  │ │ │
+│  │  │  │ ModbusRTU   │ Modbus   │ Custom      │  │ │ │
+│  │  │  │ Plugin      │ ASCII    │ Protocol    │  │ │ │
+│  │  │  │ (.so)       │ Plugin   │ Plugin      │  │ │ │
+│  │  │  │             │ (.so)    │ (.so)       │  │ │ │
+│  │  │  └─────────────┴──────────┴─────────────┘  │ │ │
+│  │  └─────────────────────────────────────────────┘ │ │
+│  └───────────────────────────────────────────────────┘ │
+│                                                         │
+│  插件目录: /usr/lib/soft_bus/protocols/                │
+│  - modbus_rtu.so                                        │
+│  - modbus_ascii.so                                      │
+│  - custom_protocol.so                                   │
+│  - ...                                                  │
+└─────────────────────────────────────────────────────────┘
+         ▲
+         │ D-Bus 接口
+         │ (加载/卸载插件)
+         │
+┌────────┴─────────────────────────────────────────────┐
+│  主应用 (soft_bus)                                    │
+│                                                       │
+│  ┌─────────────────────────────────────────────────┐ │
+│  │ DaemonClient                                    │ │
+│  │ - loadProtocolPlugin(pluginPath)                │ │
+│  │ - unloadProtocolPlugin(pluginId)                │ │
+│  │ - listProtocolPlugins()                         │ │
+│  └─────────────────────────────────────────────────┘ │
+│                                                       │
+│  插件管理界面:                                        │
+│  - 显示已加载的协议插件                                │
+│  - 安装/卸载协议插件                                   │
+│  - 配置协议参数                                        │
+└───────────────────────────────────────────────────────┘
+```
+
+## 🎯 核心设计原则
+
+### 1. **协议解析在守护进程中**
+- ✅ **硬件资源在守护进程**:串口、CAN等硬件资源由守护进程管理
+- ✅ **数据流最短**:硬件数据 → 协议解析 → 数据库,路径最短
+- ✅ **性能最优**:避免跨进程传递大量原始数据
+- ✅ **稳定性高**:协议解析崩溃不影响主应用UI
+
+### 2. **支持动态插件加载**
+- ✅ **插件化架构**:协议解析器作为插件(.so文件)动态加载
+- ✅ **热插拔**:可以在运行时加载/卸载协议插件
+- ✅ **无需重启**:添加新协议不需要重启守护进程
+
+### 3. **主应用管理插件**
+- ✅ **UI管理**:主应用提供插件管理界面
+- ✅ **D-Bus通信**:通过D-Bus请求守护进程加载/卸载插件
+- ✅ **配置管理**:主应用管理插件配置,守护进程执行
+
+## 📋 主应用 vs 守护进程职责分工
+
+### ❓ 问题:主应用 soft_bus 是不是只起到界面显示的作用?
+
+**答案:不是!主应用有更重要的职责。**
+
+### 🏗️ 职责分工
+
+#### 守护进程 (soft_bus_daemon) - "执行者"
+```
+职责:硬件资源管理和协议解析执行
+
+✅ 硬件资源管理
+   - 串口设备打开/关闭
+   - CAN设备打开/关闭
+   - 硬件数据接收
+
+✅ 协议解析执行
+   - 加载协议插件
+   - 解析协议数据
+   - 将解析结果写入数据库
+
+✅ 数据采集
+   - 实时数据采集
+   - 数据存储到数据库
+   - 设备状态监控
+
+❌ 不负责
+   - UI显示
+   - 用户配置(只执行配置)
+   - 数据可视化
+```
+
+#### 主应用 (soft_bus) - "管理者 + 展示者"
+```
+职责:配置管理、数据展示、用户交互
+
+✅ 配置管理(通过D-Bus发送给守护进程)
+   - 设备配置(串口参数、CAN参数)
+   - 协议配置(选择协议、协议参数)
+   - 插件管理(安装/卸载协议插件)
+
+✅ 数据展示
+   - 从数据库读取历史数据
+   - 实时数据可视化(图表、表格)
+   - 设备状态显示
+   - 消息统计展示
+
+✅ 用户交互
+   - 设备发现界面
+   - 设备配置界面
+   - 数据查询界面
+   - 插件管理界面
+
+✅ 数据库查询(只读)
+   - 查询设备列表
+   - 查询历史消息
+   - 查询统计数据
+
+❌ 不负责
+   - 直接操作硬件(通过D-Bus请求守护进程)
+   - 协议解析(守护进程执行)
+   - 实时数据采集(守护进程执行)
+```
+
+### 🔄 数据流向
+
+```
+┌─────────────────────────────────────────────────────────┐
+│  硬件设备                                                │
+└──────────────────┬──────────────────────────────────────┘
+                   │
+                   ▼
+┌─────────────────────────────────────────────────────────┐
+│  守护进程 (soft_bus_daemon)                             │
+│  ┌───────────────────────────────────────────────────┐  │
+│  │ SerialManager / CanManager                       │  │
+│  │  - 打开硬件设备                                    │  │
+│  │  - 接收原始数据                                    │  │
+│  └──────────────────┬────────────────────────────────┘  │
+│                    │                                     │
+│                    ▼                                     │
+│  ┌───────────────────────────────────────────────────┐  │
+│  │ ProtocolPluginManager                            │  │
+│  │  - 加载协议插件                                    │  │
+│  │  - 解析协议数据                                    │  │
+│  └──────────────────┬────────────────────────────────┘  │
+│                    │                                     │
+│                    ▼                                     │
+│  ┌───────────────────────────────────────────────────┐  │
+│  │ DeviceBusCore                                    │  │
+│  │  - 存储解析结果到数据库                            │  │
+│  │  - 更新设备状态                                    │  │
+│  └──────────────────┬────────────────────────────────┘  │
+└────────────────────┼─────────────────────────────────────┘
+                     │
+                     ▼
+┌─────────────────────────────────────────────────────────┐
+│  数据库 (soft_bus_db)                                    │
+│  - 设备信息                                              │
+│  - 原始数据                                              │
+│  - 解析后的数据                                          │
+│  - 设备状态                                              │
+└──────────────────┬──────────────────────────────────────┘
+                   │
+                   │ 读取
+                   ▼
+┌─────────────────────────────────────────────────────────┐
+│  主应用 (soft_bus)                                       │
+│  ┌───────────────────────────────────────────────────┐  │
+│  │ DeviceBusCore (只读)                              │  │
+│  │  - 从数据库读取设备列表                             │  │
+│  │  - 从数据库读取历史数据                             │  │
+│  └──────────────────┬────────────────────────────────┘  │
+│                    │                                     │
+│                    ▼                                     │
+│  ┌───────────────────────────────────────────────────┐  │
+│  │ UI组件                                            │  │
+│  │  - 设备树(显示设备列表)                          │  │
+│  │  - 数据表格(显示历史数据)                        │  │
+│  │  - 图表(数据可视化)                              │  │
+│  │  - 配置界面(发送配置到守护进程)                  │  │
+│  └───────────────────────────────────────────────────┘  │
+│                    │                                     │
+│                    │ D-Bus                              │
+│                    ▼                                     │
+│  ┌───────────────────────────────────────────────────┐  │
+│  │ DaemonClient                                     │  │
+│  │  - 请求守护进程打开/关闭设备                       │  │
+│  │  - 请求守护进程加载/卸载插件                       │  │
+│  │  - 查询守护进程状态                               │  │
+│  └───────────────────────────────────────────────────┘  │
+└─────────────────────────────────────────────────────────┘
+```
+
+### 💡 主应用的 CoreService 做什么?
+
+主应用的 `CoreService` 和 `DeviceBusCore` **不是多余的**,它们负责:
+
+1. **数据库访问(只读)**
+   ```cpp
+   // 主应用:从数据库读取设备列表
+   QList<DeviceInfo> devices = m_busCore->getAllDevices();
+   
+   // 主应用:从数据库读取历史消息
+   QList<BusMessage> messages = m_busCore->queryMessages(...);
+   ```
+
+2. **UI状态管理**
+   ```cpp
+   // 主应用:管理UI中的设备列表状态
+   // 主应用:管理数据表格的显示状态
+   // 主应用:管理图表的显示状态
+   ```
+
+3. **配置管理(通过D-Bus发送给守护进程)**
+   ```cpp
+   // 主应用:用户配置设备
+   DeviceInfo device = ...;
+   m_busCore->registerDevice(device);  // 写入数据库
+   
+   // 主应用:通过D-Bus请求守护进程打开设备
+   daemonClient->openDevice(device.portname);
+   ```
+
+### ⚠️ 重要区别
+
+| 操作 | 守护进程 | 主应用 |
+|------|---------|--------|
+| **打开串口** | ✅ 直接打开 | ❌ 通过D-Bus请求 |
+| **接收数据** | ✅ 直接接收 | ❌ 不接收 |
+| **协议解析** | ✅ 直接解析 | ❌ 不解析 |
+| **写入数据库** | ✅ 写入解析结果 | ❌ 不写入 |
+| **读取数据库** | ✅ 读取设备配置 | ✅ 读取历史数据 |
+| **显示UI** | ❌ 无UI | ✅ 显示界面 |
+| **用户配置** | ❌ 只执行 | ✅ 接收并保存 |
+
+### 🎯 总结
+
+**主应用 soft_bus 不是只起到界面显示的作用!**
+
+主应用的职责:
+1. ✅ **配置管理**:用户通过UI配置设备,保存到数据库,通过D-Bus通知守护进程
+2. ✅ **数据展示**:从数据库读取数据,在UI中展示(表格、图表)
+3. ✅ **用户交互**:提供友好的界面,让用户管理设备、查看数据
+4. ✅ **插件管理**:通过D-Bus管理守护进程中的协议插件
+
+守护进程的职责:
+1. ✅ **硬件管理**:直接操作硬件设备(串口、CAN)
+2. ✅ **协议解析**:加载插件,解析协议数据
+3. ✅ **数据采集**:实时采集数据,写入数据库
+
+**简单理解**:
+- 守护进程 = "工人":负责实际干活(硬件操作、数据采集、协议解析)
+- 主应用 = "经理":负责管理和展示(配置管理、数据展示、用户交互)
+
+两者通过**数据库**(共享数据)和**D-Bus**(控制命令)协作!🚀
+
+## 📝 实现方案
+
+### 1. 定义协议解析器接口
+
+```cpp
+// src/core/pal/protocols/IProtocolParser.h
+/**
+ * @file IProtocolParser.h
+ * @brief 协议解析器接口 - 所有协议插件必须实现此接口
+ */
+#pragma once
+
+#include <QByteArray>
+#include <QString>
+#include <QJsonObject>
+
+class IProtocolParser {
+public:
+    virtual ~IProtocolParser() = default;
+    
+    /**
+     * @brief 获取协议名称
+     * @return 协议名称(如 "modbus-rtu", "modbus-ascii")
+     */
+    virtual QString getName() const = 0;
+    
+    /**
+     * @brief 获取协议描述
+     */
+    virtual QString getDescription() const = 0;
+    
+    /**
+     * @brief 获取协议版本
+     */
+    virtual QString getVersion() const = 0;
+    
+    /**
+     * @brief 从缓冲区提取完整帧
+     * @param buffer 数据缓冲区
+     * @param maxLength 最大帧长度
+     * @return 提取的帧数据,如果没有完整帧则返回空
+     */
+    virtual QByteArray extractFrame(const QByteArray& buffer, int maxLength = 256) = 0;
+    
+    /**
+     * @brief 解析协议帧
+     * @param frame 完整的协议帧
+     * @param portName 端口名称(用于设备识别)
+     * @return 解析后的JSON数据,解析失败返回空对象
+     */
+    virtual QJsonObject parseFrame(const QByteArray& frame, const QString& portName) = 0;
+    
+    /**
+     * @brief 验证帧是否有效
+     * @param frame 协议帧
+     * @return 有效返回true
+     */
+    virtual bool validateFrame(const QByteArray& frame) const = 0;
+    
+    /**
+     * @brief 获取协议配置参数(用于UI配置)
+     * @return JSON格式的配置参数定义
+     */
+    virtual QJsonObject getConfigSchema() const = 0;
+    
+    /**
+     * @brief 设置协议配置参数
+     * @param config JSON格式的配置参数
+     */
+    virtual void setConfig(const QJsonObject& config) = 0;
+};
+
+// 插件导出函数(C接口,避免C++名称修饰问题)
+extern "C" {
+    /**
+     * @brief 创建协议解析器实例
+     * @return 协议解析器指针,调用者负责释放
+     */
+    IProtocolParser* createProtocolParser();
+    
+    /**
+     * @brief 获取插件信息
+     * @return JSON格式的插件元数据
+     */
+    const char* getPluginInfo();
+}
+```
+
+### 2. 实现协议插件管理器
+
+```cpp
+// src/core/pal/protocols/ProtocolPluginManager.h
+/**
+ * @file ProtocolPluginManager.h
+ * @brief 协议插件管理器 - 管理协议插件的加载和卸载
+ */
+#pragma once
+
+#include "IProtocolParser.h"
+#include <QMap>
+#include <QString>
+#include <QLibrary>
+#include <QMutex>
+
+class ProtocolPluginManager {
+public:
+    static ProtocolPluginManager* instance();
+    
+    /**
+     * @brief 加载协议插件
+     * @param pluginPath 插件文件路径(.so文件)
+     * @return 插件ID,失败返回空字符串
+     */
+    QString loadPlugin(const QString& pluginPath);
+    
+    /**
+     * @brief 卸载协议插件
+     * @param pluginId 插件ID
+     * @return 成功返回true
+     */
+    bool unloadPlugin(const QString& pluginId);
+    
+    /**
+     * @brief 获取协议解析器
+     * @param protocolName 协议名称(如 "modbus-rtu")
+     * @return 协议解析器指针,不存在返回nullptr
+     */
+    IProtocolParser* getParser(const QString& protocolName);
+    
+    /**
+     * @brief 获取所有已加载的插件信息
+     * @return JSON格式的插件列表
+     */
+    QJsonArray getLoadedPlugins() const;
+    
+    /**
+     * @brief 从目录自动加载插件
+     * @param pluginDir 插件目录路径
+     */
+    void loadPluginsFromDirectory(const QString& pluginDir);
+
+private:
+    ProtocolPluginManager() = default;
+    ~ProtocolPluginManager();
+    
+    struct PluginInfo {
+        QString id;
+        QString path;
+        QString name;
+        QString version;
+        QLibrary* library;
+        IProtocolParser* parser;
+        void (*destroyFunc)(IProtocolParser*);
+    };
+    
+    QMap<QString, PluginInfo> m_plugins;  // pluginId -> PluginInfo
+    QMap<QString, QString> m_protocolMap; // protocolName -> pluginId
+    mutable QMutex m_mutex;
+};
+```
+
+### 3. 修改 SerialParserThread 使用插件
+
+```cpp
+// src/serial_manager/serial_parser_thread.cpp
+#include "core/pal/protocols/ProtocolPluginManager.h"
+
+void SerialParserThread::run()
+{
+    ProtocolPluginManager* pluginManager = ProtocolPluginManager::instance();
+    
+    while (!m_stopped) {
+        // ... 现有代码 ...
+        
+        // 获取设备配置
+        DeviceInfo device = m_busCore->getDeviceInfoByPortname(portName);
+        
+        // 提取帧
+        QByteArray frame = buffer->extractFrame(device.protocol, device.protocol_detail);
+        
+        // 使用插件解析
+        if (!device.protocol.isEmpty()) {
+            IProtocolParser* parser = pluginManager->getParser(device.protocol_detail);
+            if (parser) {
+                QJsonObject parsedData = parser->parseFrame(frame, portName);
+                if (!parsedData.isEmpty()) {
+                    emit modbusDataParsed(parsedData);  // 或统一的数据解析信号
+                    continue;
+                }
+            }
+        }
+        
+        // 如果插件解析失败,尝试其他协议(向后兼容)
+        // ...
+    }
+}
+```
+
+### 4. 扩展 DaemonService 添加插件管理接口
+
+```cpp
+// src/daemon/daemon_service.h
+public slots:
+    // ... 现有接口 ...
+    
+    /**
+     * @brief 加载协议插件
+     * @param pluginPath 插件文件路径
+     * @return 插件ID,失败返回空字符串
+     */
+    QString loadProtocolPlugin(const QString& pluginPath);
+    
+    /**
+     * @brief 卸载协议插件
+     * @param pluginId 插件ID
+     * @return 成功返回true
+     */
+    bool unloadProtocolPlugin(const QString& pluginId);
+    
+    /**
+     * @brief 获取已加载的协议插件列表
+     * @return JSON格式的插件列表
+     */
+    QString getProtocolPlugins() const;
+```
+
+### 5. 实现 DaemonService 插件接口
+
+```cpp
+// src/daemon/daemon_service.cpp
+#include "core/pal/protocols/ProtocolPluginManager.h"
+
+QString DaemonService::loadProtocolPlugin(const QString& pluginPath)
+{
+    ProtocolPluginManager* manager = ProtocolPluginManager::instance();
+    return manager->loadPlugin(pluginPath);
+}
+
+bool DaemonService::unloadProtocolPlugin(const QString& pluginId)
+{
+    ProtocolPluginManager* manager = ProtocolPluginManager::instance();
+    return manager->unloadPlugin(pluginId);
+}
+
+QString DaemonService::getProtocolPlugins() const
+{
+    ProtocolPluginManager* manager = ProtocolPluginManager::instance();
+    QJsonArray plugins = manager->getLoadedPlugins();
+    return QJsonDocument(plugins).toJson(QJsonDocument::Compact);
+}
+```
+
+### 6. 示例:Modbus RTU 插件实现
+
+```cpp
+// plugins/modbus_rtu/modbus_rtu_plugin.cpp
+#include "core/pal/protocols/IProtocolParser.h"
+
+class ModbusRTUParser : public IProtocolParser {
+public:
+    QString getName() const override {
+        return "modbus-rtu";
+    }
+    
+    QString getDescription() const override {
+        return "Modbus RTU Protocol Parser";
+    }
+    
+    QString getVersion() const override {
+        return "1.0.0";
+    }
+    
+    QByteArray extractFrame(const QByteArray& buffer, int maxLength) override {
+        // Modbus RTU 帧提取逻辑
+        // 检查CRC,提取完整帧
+        // ...
+    }
+    
+    QJsonObject parseFrame(const QByteArray& frame, const QString& portName) override {
+        // Modbus RTU 解析逻辑
+        // 解析功能码、数据等
+        // ...
+    }
+    
+    bool validateFrame(const QByteArray& frame) const override {
+        // 验证CRC等
+        // ...
+    }
+    
+    QJsonObject getConfigSchema() const override {
+        // 返回配置参数定义
+        // ...
+    }
+    
+    void setConfig(const QJsonObject& config) override {
+        // 设置配置参数
+        // ...
+    }
+};
+
+extern "C" {
+    IProtocolParser* createProtocolParser() {
+        return new ModbusRTUParser();
+    }
+    
+    const char* getPluginInfo() {
+        return R"({
+            "name": "modbus-rtu",
+            "version": "1.0.0",
+            "description": "Modbus RTU Protocol Parser",
+            "author": "Your Name"
+        })";
+    }
+}
+```
+
+### 7. 插件目录结构
+
+```
+soft_bus/
+├── plugins/
+│   ├── modbus_rtu/
+│   │   ├── CMakeLists.txt
+│   │   ├── modbus_rtu_plugin.cpp
+│   │   └── modbus_rtu_plugin.h
+│   ├── modbus_ascii/
+│   │   └── ...
+│   └── custom_protocol/
+│       └── ...
+└── install/
+    └── lib/
+        └── soft_bus/
+            └── protocols/
+                ├── modbus_rtu.so
+                ├── modbus_ascii.so
+                └── custom_protocol.so
+```
+
+## 🔄 工作流程
+
+### 1. 守护进程启动时自动加载插件
+
+```cpp
+// daemon_main.cpp
+int main(int argc, char *argv[])
+{
+    // ... 初始化 ...
+    
+    // 加载协议插件
+    ProtocolPluginManager* pluginManager = ProtocolPluginManager::instance();
+    pluginManager->loadPluginsFromDirectory("/usr/lib/soft_bus/protocols");
+    
+    // ... 其他初始化 ...
+}
+```
+
+### 2. 主应用通过D-Bus管理插件
+
+```cpp
+// 主应用代码
+DaemonClient* client = DaemonClient::instance();
+client->connectToDaemon();
+
+// 加载新插件
+QString pluginId = client->loadProtocolPlugin("/path/to/new_protocol.so");
+
+// 查看已加载的插件
+QString pluginsJson = client->getProtocolPlugins();
+```
+
+## ✅ 优势
+
+1. **协议解析在守护进程**
+   - ✅ 数据流最短,性能最优
+   - ✅ 硬件资源统一管理
+   - ✅ 协议解析崩溃不影响UI
+
+2. **支持动态插件**
+   - ✅ 无需重新编译守护进程
+   - ✅ 可以热插拔协议插件
+   - ✅ 第三方可以开发协议插件
+
+3. **主应用管理插件**
+   - ✅ 提供友好的UI界面
+   - ✅ 通过D-Bus远程管理
+   - ✅ 配置和插件分离
+
+## 📋 实施建议
+
+### 阶段1:基础架构(推荐先做)
+1. ✅ 定义 `IProtocolParser` 接口
+2. ✅ 实现 `ProtocolPluginManager`
+3. ✅ 修改 `SerialParserThread` 使用插件
+
+### 阶段2:插件化现有协议
+1. ✅ 将 Modbus RTU 改为插件
+2. ✅ 将 Modbus ASCII 改为插件
+3. ✅ 测试插件加载和解析
+
+### 阶段3:D-Bus接口
+1. ✅ 扩展 `DaemonService` 添加插件管理接口
+2. ✅ 扩展 `DaemonClient` 添加插件管理接口
+3. ✅ 主应用添加插件管理UI
+
+### 阶段4:完善功能
+1. ✅ 插件配置管理
+2. ✅ 插件版本管理
+3. ✅ 插件依赖管理
+
+## 🎯 总结
+
+**回答你的问题**:协议插件应该**放在守护进程中**,但通过**插件机制**支持动态加载。
+
+**原因**:
+1. 硬件资源在守护进程,协议解析也应该在守护进程(数据流最短)
+2. 通过插件机制,可以动态加载,不需要重新编译守护进程
+3. 主应用通过D-Bus管理插件,提供友好的UI界面
+
+这样既保证了性能,又支持了灵活扩展!🚀
+

+ 201 - 0
docs/守护进程与主应用关系说明.md

@@ -0,0 +1,201 @@
+# 守护进程与主应用关系说明
+
+## 📋 概述
+
+`soft_bus` (主应用) 和 `soft_bus_daemon` (守护进程) 是两个**独立的进程**,它们通过 **D-Bus** 进行通信,并共享同一个数据库文件。
+
+## 🏗️ 架构图
+
+```
+┌─────────────────────────────────────────────────────────────┐
+│                    系统架构                                  │
+└─────────────────────────────────────────────────────────────┘
+
+┌──────────────────────┐         D-Bus          ┌──────────────────────┐
+│   soft_bus           │ ◄─────────────────────► │  soft_bus_daemon     │
+│   (主应用进程)        │      (进程间通信)       │  (守护进程)           │
+│                      │                         │                      │
+│  ┌────────────────┐  │                         │  ┌────────────────┐  │
+│  │ CoreService    │  │                         │  │ CoreService    │  │
+│  │ (进程内单例)    │  │                         │  │ (进程内单例)    │  │
+│  └────────────────┘  │                         │  └────────────────┘  │
+│         │            │                         │         │            │
+│         ▼            │                         │         ▼            │
+│  ┌────────────────┐  │                         │  ┌────────────────┐  │
+│  │ DeviceBusCore  │  │                         │  │ DeviceBusCore  │  │
+│  │ SoftBusCore    │  │                         │  │ SoftBusCore    │  │
+│  └────────────────┘  │                         │  └────────────────┘  │
+│         │            │                         │         │            │
+└─────────┼────────────┘                         └─────────┼────────────┘
+          │                                              │
+          │              ┌──────────────────┐            │
+          └─────────────►│  soft_bus_db     │◄───────────┘
+                         │  (SQLite数据库)   │
+                         └──────────────────┘
+                         (共享数据库文件)
+```
+
+## 🔍 详细说明
+
+### 1. 进程独立性
+
+#### soft_bus (主应用)
+- **文件**: `main.cpp`
+- **类型**: GUI 应用程序 (QApplication)
+- **功能**: 
+  - 提供用户界面
+  - 管理设备配置
+  - 显示数据可视化
+  - 通过 DaemonClient 查询守护进程状态
+
+#### soft_bus_daemon (守护进程)
+- **文件**: `daemon_main.cpp`
+- **类型**: 后台服务进程 (QCoreApplication)
+- **功能**:
+  - 独立运行的核心服务
+  - 通过 D-Bus 提供状态查询接口
+  - 管理设备总线和消息路由
+  - 即使主应用关闭也能继续运行
+
+### 2. 核心服务实例
+
+每个进程都有**自己独立**的 `CoreService` 实例:
+
+```cpp
+// 主应用进程 (main.cpp)
+CoreService* coreService = CoreService::instance();  // 进程1的实例
+coreService->initialize();  // 初始化进程1的核心
+
+// 守护进程 (daemon_main.cpp)  
+CoreService* coreService = CoreService::instance();  // 进程2的实例
+coreService->initialize();  // 初始化进程2的核心
+```
+
+**重要**: `CoreService::instance()` 是**进程内单例**,不是跨进程单例。两个进程各自有独立的内存空间。
+
+### 3. 数据库共享
+
+两个进程都使用**同一个 SQLite 数据库文件** `soft_bus_db`:
+
+```cpp
+// 两个进程都调用
+m_deviceBusCore->initDB(QStringLiteral("soft_bus_db"));
+```
+
+**效果**:
+- ✅ 数据持久化共享(设备注册、消息存储等)
+- ✅ SQLite 自动处理并发访问
+- ❌ 内存状态不共享(每个进程的设备列表缓存独立)
+
+### 4. D-Bus 通信
+
+主应用通过 `DaemonClient` 与守护进程通信:
+
+```cpp
+// 主应用 (mainwindow.cpp)
+DaemonClient* client = new DaemonClient(this);
+client->connectToDaemon();  // 连接到守护进程
+client->getStatus();        // 查询守护进程状态
+client->getDeviceCount();   // 获取设备数量
+```
+
+守护进程通过 `DaemonService` 提供 D-Bus 接口:
+
+```cpp
+// 守护进程 (daemon_main.cpp)
+DaemonService* service = new DaemonService(coreService, &app);
+connection.registerService("com.softbus.Daemon");  // 注册 D-Bus 服务
+connection.registerObject("/com/softbus/Daemon", service);  // 注册对象
+```
+
+**D-Bus 接口**:
+- `isRunning()` - 检查守护进程是否运行
+- `getStatus()` - 获取状态信息(JSON)
+- `getLoadInfo()` - 获取负载信息(CPU、内存、消息速率)
+- `getDeviceCount()` - 获取设备数量
+- `getMessageStats()` - 获取消息统计
+- `getPid()` - 获取进程ID
+- `shutdown()` - 关闭守护进程
+
+### 5. 实际运行场景
+
+#### 场景1: 只运行主应用
+```
+soft_bus (进程1)
+  └─ CoreService (实例1)
+      └─ DeviceBusCore (实例1)
+          └─ 连接 soft_bus_db
+```
+- 主应用独立运行
+- 有自己的核心服务
+- 可以正常工作
+
+#### 场景2: 主应用 + 守护进程
+```
+soft_bus (进程1)          soft_bus_daemon (进程2)
+  └─ CoreService (实例1)      └─ CoreService (实例2)
+      └─ DeviceBusCore (实例1)     └─ DeviceBusCore (实例2)
+          └─ 连接 soft_bus_db          └─ 连接 soft_bus_db
+                  ▲                              │
+                  └────────── 共享数据库 ─────────┘
+                  
+          D-Bus 通信
+          ◄─────────►
+```
+- 两个进程同时运行
+- 各自有独立的核心服务
+- 共享数据库文件
+- 通过 D-Bus 通信
+
+#### 场景3: 主应用关闭,守护进程继续运行
+```
+soft_bus (已关闭)         soft_bus_daemon (进程2,继续运行)
+                          └─ CoreService (实例2)
+                              └─ DeviceBusCore (实例2)
+                                  └─ 连接 soft_bus_db
+```
+- 守护进程独立运行
+- 核心服务继续工作
+- 数据继续写入数据库
+
+## 🔄 数据同步
+
+### 数据库层面(自动同步)
+- 设备注册信息
+- 消息存储
+- 设备状态(通过数据库查询)
+
+### 内存层面(需要 D-Bus 查询)
+- 实时设备列表(每个进程独立缓存)
+- 运行时状态(需要通过 D-Bus 查询守护进程)
+
+## 💡 设计意图
+
+1. **守护进程**: 提供独立的后台服务,即使没有 GUI 也能运行
+2. **主应用**: 提供用户界面,可以查询守护进程状态
+3. **数据库共享**: 确保数据一致性
+4. **进程隔离**: 提高稳定性,一个进程崩溃不影响另一个
+
+## ⚠️ 注意事项
+
+1. **不是同一个核心**: 两个进程有独立的核心实例
+2. **数据库共享**: 数据通过数据库共享,但内存状态独立
+3. **D-Bus 通信**: 主应用通过 D-Bus 查询守护进程状态
+4. **并发访问**: SQLite 自动处理多进程并发访问
+
+## 📝 总结
+
+| 特性 | 说明 |
+|------|------|
+| **进程关系** | 两个独立的进程 |
+| **核心实例** | 各自有独立的 CoreService 实例 |
+| **数据库** | 共享同一个 SQLite 数据库文件 |
+| **通信方式** | 通过 D-Bus 进行进程间通信 |
+| **内存状态** | 各自独立,不共享 |
+| **数据持久化** | 通过数据库共享 |
+
+**简单理解**: 
+- 它们像两个独立的"办公室",各自有自己的"工作空间"(内存)
+- 但共享同一个"文件柜"(数据库)
+- 通过"电话"(D-Bus)互相联系
+

+ 144 - 0
docs/守护进程架构说明.md

@@ -0,0 +1,144 @@
+# 守护进程架构说明
+
+## 概述
+
+软总线系统采用**守护进程 + GUI 客户端**的架构,核心服务完全独立于 Qt GUI 运行。
+
+## 架构设计
+
+### 1. 守护进程 (soft_bus_daemon)
+
+- **位置**: `src/daemon/daemon_main.cpp`
+- **特点**:
+  - 使用 `QCoreApplication`(不依赖 Qt GUI)
+  - 独立进程运行,不依赖界面
+  - 通过 D-Bus 提供状态查询和负载监控接口
+  - 管理设备总线和消息路由
+
+### 2. GUI 客户端 (soft_bus)
+
+- **位置**: `main.cpp`, `mainwindow.cpp`
+- **特点**:
+  - 使用 `QApplication`(Qt GUI)
+  - 通过 D-Bus 连接守护进程
+  - 显示核心服务状态和负载情况
+  - 可以关闭窗口而不影响核心服务运行
+
+## D-Bus 接口
+
+### 服务名称
+- `com.softbus.Daemon`
+
+### 对象路径
+- `/com/softbus/Daemon`
+
+### 接口方法
+
+#### `isRunning() -> bool`
+检查核心服务是否运行
+
+#### `getStatus() -> QString`
+获取核心服务状态信息(JSON 格式)
+```json
+{
+  "running": true,
+  "status": "running",
+  "initialized": true,
+  "deviceCount": 5,
+  "onlineDeviceCount": 3
+}
+```
+
+#### `getLoadInfo() -> QString`
+获取核心服务负载情况(JSON 格式)
+```json
+{
+  "messageRate": 10.5,
+  "totalMessagesProcessed": 12345,
+  "cpuUsage": 0.0,
+  "memoryUsage": 0.0,
+  "timestamp": "2024-01-01T12:00:00"
+}
+```
+
+#### `getDeviceCount() -> int`
+获取已注册的设备数量
+
+#### `getMessageStats() -> QString`
+获取消息处理统计(JSON 格式)
+
+### 信号
+
+#### `statusChanged(QString status)`
+核心服务状态变化时发出
+
+#### `loadInfoUpdated(QString loadInfo)`
+负载信息更新时发出(每5秒)
+
+## 使用方法
+
+### 1. 编译
+
+```bash
+mkdir build
+cd build
+cmake ..
+make
+```
+
+会生成两个可执行文件:
+- `soft_bus` - GUI 客户端
+- `soft_bus_daemon` - 守护进程
+
+### 2. 启动守护进程
+
+```bash
+# 方式1: 前台运行(用于调试)
+./soft_bus_daemon
+
+# 方式2: 后台运行
+./soft_bus_daemon &
+
+# 方式3: 使用 systemd(推荐生产环境)
+sudo systemctl start soft_bus_daemon
+```
+
+### 3. 启动 GUI 客户端
+
+```bash
+./soft_bus
+```
+
+GUI 会自动连接到守护进程并显示状态。
+
+### 4. 状态显示
+
+在 GUI 的状态栏右侧会显示:
+- **核心服务状态**: 运行中/未运行,以及设备数量
+- **负载信息**: 消息处理速率和总消息数
+
+## 优势
+
+1. **核心服务独立**: 核心服务不依赖 Qt GUI,可以独立运行
+2. **进程隔离**: GUI 崩溃不影响核心服务
+3. **资源优化**: 核心服务只使用 Qt Core,不加载 GUI 库
+4. **易于部署**: 可以将守护进程部署为系统服务
+5. **多客户端**: 可以同时运行多个 GUI 客户端连接同一个守护进程
+
+## 注意事项
+
+1. **D-Bus 权限**: 如果使用系统 D-Bus,可能需要配置权限策略
+2. **消息统计**: 当前消息统计使用占位符,需要从实际的消息处理模块获取
+3. **CPU/内存监控**: 当前使用占位符,可以集成系统监控 API(如 `/proc/self/stat`)
+
+## 未来改进
+
+1. 添加实际的 CPU 和内存使用率监控
+2. 实现消息处理统计的实时更新
+3. 添加守护进程的配置文件支持
+4. 实现守护进程的日志管理
+5. 添加守护进程的健康检查机制
+
+
+
+

+ 8 - 4
main.cpp

@@ -1,7 +1,7 @@
 #include "mainwindow.h"
 #include "core/CoreService.h"
 #include <QApplication>
-#include <QDebug>
+#include "utils/logging.h"
 
 int main(int argc, char *argv[])
 {
@@ -9,10 +9,13 @@ int main(int argc, char *argv[])
     app.setStyle("Fusion");
     app.setWindowIcon(QIcon(":/qrc/icons/ads_icon.svg"));
     
+    // 设置关闭最后一个窗口时不退出应用,让总线核心继续运行
+    app.setQuitOnLastWindowClosed(false);
+    
     // 初始化核心服务(在界面创建之前)
     CoreService* coreService = CoreService::instance();
     if (!coreService->initialize()) {
-        qCritical() << "Failed to initialize CoreService";
+        LOG_CRITICAL() << "Failed to initialize CoreService";
         return -1;
     }
     
@@ -23,8 +26,9 @@ int main(int argc, char *argv[])
     // 运行应用
     int result = app.exec();
     
-    // 应用退出时关闭核心服务
-    qDebug() << "Application exiting, shutting down core service...";
+    // 注意:应用退出时才关闭核心服务
+    // 如果只是关闭窗口,应用不会退出,核心服务会继续运行
+    LOG_DEBUG() << "Application exiting, shutting down core service...";
     coreService->shutdown();
     
     return result;

+ 326 - 3
mainwindow.cpp

@@ -1,9 +1,19 @@
 #include "mainwindow.h"
 #include "database_manager/databasemodule.h"
+#include "daemon/daemon_client.h"
+#include "daemon/daemon_connection_dialog.h"
+#include "daemon/daemon_message_flow_widget.h"
+#include "api/SoftBusAPI.h"
+#include "settings/settings_dialog.h"
 #include "toolbar/toolbar.h"
 #include "view_serial/serialmodule.h"
+#include "utils/logging.h"
 #include <QAction>
+#include <QCloseEvent>
+#include <QDockWidget>
 #include <QHBoxLayout>
+#include <QJsonDocument>
+#include <QJsonObject>
 #include <QLabel>
 #include <QMenu>
 #include <QMenuBar>
@@ -47,7 +57,10 @@ void MainWindow::createUI() {
     centralWidget->setLayout(mainLayout);
     setCentralWidget(centralWidget);
 
-    // 创建工具栏和页面
+    // 先设置守护进程状态(必须在创建模块之前,因为模块可能会初始化 API)
+    setupDaemonStatus();
+
+    // 创建工具栏和页面(在守护进程设置之后)
     createHomeToolbar();
     createSerialToolbar();
     createDatabaseToolbar();
@@ -128,6 +141,9 @@ void MainWindow::createMenuBar() {
         helpMenu->addAction(QIcon(":/qrc/icons/update.png"), "检查更新");
 
     connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout);
+    
+    // 连接退出菜单项,真正退出应用
+    connect(exitAction, &QAction::triggered, qApp, &QApplication::quit);
 }
 
 void MainWindow::createHomeToolbar() {
@@ -189,13 +205,15 @@ void MainWindow::createSettingsToolbar() {
     settingsToolbar->hide();
 
     // 添加按钮
-    settingsToolbar->addAction(QIcon(":/qrc/icons/preferences.png"), "首选项");
+    QAction *preferencesAction = settingsToolbar->addAction(QIcon(":/qrc/icons/preferences.png"), "首选项");
+    connect(preferencesAction, &QAction::triggered, this, &MainWindow::showSettingsDialog);
+    
     settingsToolbar->addAction(QIcon(":/qrc/icons/theme.png"), "主题");
     settingsToolbar->addAction(QIcon(":/qrc/icons/keyboard.png"), "快捷键");
     settingsToolbar->addAction(QIcon(":/qrc/icons/plugins.png"), "插件");
 
     // 创建设置界面页面
-    QLabel *settingsPage = new QLabel("<center><h1>设置界面</h1></center>", this);
+    QLabel *settingsPage = new QLabel("<center><h1>设置界面</h1><p>点击工具栏中的\"首选项\"按钮打开设置对话框</p></center>", this);
     settingsPage->setAlignment(Qt::AlignCenter);
 
     // 添加到堆栈
@@ -288,3 +306,308 @@ void MainWindow::showAbout() {
                        "<p>版本: 1.0.0</p>"
                        "<p>© flower </p>");
 }
+
+void MainWindow::setupDaemonStatus()
+{
+    // 创建守护进程客户端
+    m_daemonClient = new DaemonClient(this);
+    
+    // 连接信号
+    connect(m_daemonClient, &DaemonClient::daemonStatusChanged,
+            this, &MainWindow::onDaemonStatusChanged);
+    connect(m_daemonClient, &DaemonClient::loadInfoUpdated,
+            this, &MainWindow::onLoadInfoUpdated);
+    
+    // 加载设置(在初始化 API 之前)
+    loadSettings();
+    
+    // 如果设置中启用了守护进程模式,先尝试连接守护进程
+    // 注意:默认值应该与 loadSettings() 中的默认值一致
+    // 默认启用守护进程模式,提供更好的资源管理和权限控制
+    QSettings settings;
+    bool useDaemonMode = settings.value("daemon/useDaemonMode", true).toBool();
+    
+    SoftBusAPI* api = SoftBusAPI::instance();
+    bool connected = false;
+    
+    if (useDaemonMode) {
+        // 先尝试启动守护进程(如果未运行)
+        LOG_INFO() << "守护进程模式已启用,正在启动守护进程客户端服务...";
+        bool daemonStarted = m_daemonClient->startDaemon();
+        
+        if (daemonStarted) {
+            LOG_INFO() << "守护进程客户端服务启动成功,正在连接守护进程服务...";
+        } else {
+            LOG_WARNING() << "守护进程启动失败,可能已经运行或无法启动";
+        }
+        
+        // 尝试连接守护进程(connectToDaemon 内部也会尝试启动)
+        connected = m_daemonClient->connectToDaemon();
+        
+        if (!connected) {
+            LOG_WARNING() << "守护进程连接失败,弹出对话框询问用户";
+            // 连接失败,弹出对话框询问是否切换到本地模式
+            DaemonConnectionDialog dialog(this);
+            dialog.setErrorMessage(tr("守护进程服务未运行或无法访问。"));
+            
+            int result = dialog.exec();
+            
+            if (result == QDialog::Accepted) {
+                if (dialog.switchToLocalMode()) {
+                    // 用户选择切换到本地模式
+                    useDaemonMode = false;
+                    settings.setValue("daemon/useDaemonMode", false);
+                    settings.sync();
+                    LOG_INFO() << "用户选择切换到本地模式";
+                } else {
+                    // 用户选择重试,再次尝试启动和连接
+                    LOG_INFO() << "用户选择重试,正在重新启动守护进程...";
+                    daemonStarted = m_daemonClient->startDaemon();
+                    connected = m_daemonClient->connectToDaemon();
+                    if (!connected) {
+                        // 重试仍然失败,自动切换到本地模式
+                        QMessageBox::warning(this, 
+                            tr("连接失败"), 
+                            tr("重试启动和连接守护进程仍然失败,已自动切换到本地模式。"));
+                        useDaemonMode = false;
+                        settings.setValue("daemon/useDaemonMode", false);
+                        settings.sync();
+                        LOG_WARNING() << "重试仍然失败,自动切换到本地模式";
+                    } else {
+                        // 重试成功
+                        useDaemonMode = true;
+                        LOG_INFO() << "重试启动和连接守护进程成功";
+                    }
+                }
+            } else {
+                // 用户取消,默认切换到本地模式
+                useDaemonMode = false;
+                settings.setValue("daemon/useDaemonMode", false);
+                settings.sync();
+                LOG_INFO() << "用户取消对话框,切换到本地模式";
+            }
+        } else {
+            // 连接成功,确保使用守护进程模式
+            useDaemonMode = true;
+            LOG_INFO() << "守护进程启动并连接成功";
+        }
+    } else {
+        LOG_INFO() << "设置中未启用守护进程模式,使用本地模式";
+    }
+    
+    // 根据最终的模式设置初始化 API
+    // 注意:必须先设置模式,再初始化 API,这样 Manager 才能知道使用哪种模式
+    LOG_INFO() << "设置API模式:" << (useDaemonMode ? "守护进程模式" : "本地模式");
+    api->setUseDaemonMode(useDaemonMode);
+    
+    // 初始化 API(会根据模式创建相应的 Manager)
+    LOG_INFO() << "正在初始化 SoftBusAPI...";
+    if (!api->initialize()) {
+        LOG_WARNING() << "Failed to initialize SoftBusAPI";
+        return;
+    }
+    LOG_INFO() << "SoftBusAPI 初始化成功";
+    
+    // 如果使用守护进程模式,设置 DaemonClient 到 SoftBusAPI,让硬件操作通过守护进程
+    if (useDaemonMode) {
+        LOG_INFO() << "设置 DaemonClient 到 SoftBusAPI";
+        api->setDaemonClient(m_daemonClient);
+        // 守护进程连接成功后,启动设备扫描(由守护进程负责扫描)
+        // 注意:在守护进程模式下,设备扫描由守护进程负责,这里只是通知可以开始查询设备列表
+        LOG_INFO() << "启动设备扫描(守护进程模式)";
+        api->startDeviceDiscovery(5000);
+    } else {
+        // 本地模式下,立即启动设备扫描
+        LOG_INFO() << "启动设备扫描(本地模式)";
+        api->startDeviceDiscovery(5000);
+    }
+    
+    // 在状态栏添加状态标签
+    QStatusBar* statusBar = this->statusBar();
+    if (statusBar) {
+        m_statusLabel = new QLabel("核心服务: 未连接", this);
+        m_loadLabel = new QLabel("负载: --", this);
+        
+        statusBar->addPermanentWidget(m_statusLabel);
+        statusBar->addPermanentWidget(m_loadLabel);
+        
+        // 初始更新
+        updateDaemonStatus(false, QString());
+    }
+    
+    // 创建信息流列表停靠窗口(在守护进程客户端创建之后)
+    createMessageFlowDock();
+    
+    // 设置守护进程客户端到信息流组件
+    if (m_daemonClient && m_messageFlowWidget) {
+        m_messageFlowWidget->setDaemonClient(m_daemonClient);
+    }
+}
+
+void MainWindow::onDaemonStatusChanged(bool running, const QString& statusJson)
+{
+    updateDaemonStatus(running, statusJson);
+    
+    // 信息流组件会自动处理状态更新(通过信号连接)
+}
+
+void MainWindow::onLoadInfoUpdated(const QString& loadInfoJson)
+{
+    updateLoadInfo(loadInfoJson);
+    
+    // 信息流组件会自动处理负载信息更新(通过信号连接)
+}
+
+void MainWindow::updateDaemonStatus(bool running, const QString& statusJson)
+{
+    if (!m_statusLabel) return;
+    
+    QString statusText;
+    QString style;
+    
+    if (running) {
+        statusText = "核心服务: 运行中";
+        style = "color: green; font-weight: bold;";
+        
+        // 获取进程ID
+        if (m_daemonClient) {
+            qint64 pid = m_daemonClient->getPid();
+            if (pid > 0) {
+                statusText += QString(" (PID: %1)").arg(pid);
+            }
+        }
+        
+        // 解析状态 JSON 获取详细信息
+        if (!statusJson.isEmpty()) {
+            QJsonDocument doc = QJsonDocument::fromJson(statusJson.toUtf8());
+            if (doc.isObject()) {
+                QJsonObject obj = doc.object();
+                int deviceCount = obj["deviceCount"].toInt(0);
+                int onlineCount = obj["onlineDeviceCount"].toInt(0);
+                statusText += QString(" | 设备: %1/%2").arg(onlineCount).arg(deviceCount);
+            }
+        }
+    } else {
+        statusText = "核心服务: 未运行";
+        style = "color: red; font-weight: bold;";
+    }
+    
+    m_statusLabel->setText(statusText);
+    m_statusLabel->setStyleSheet(style);
+}
+
+void MainWindow::updateLoadInfo(const QString& loadInfoJson)
+{
+    if (!m_loadLabel) return;
+    
+    if (loadInfoJson.isEmpty()) {
+        m_loadLabel->setText("负载: --");
+        return;
+    }
+    
+    QJsonDocument doc = QJsonDocument::fromJson(loadInfoJson.toUtf8());
+    if (!doc.isObject()) {
+        m_loadLabel->setText("负载: --");
+        return;
+    }
+    
+    QJsonObject obj = doc.object();
+    double messageRate = obj["messageRate"].toDouble(0.0);
+    qint64 totalMessages = obj["totalMessages"].toVariant().toLongLong();
+    
+    QString loadText = QString("消息速率: %1 msg/s | 总计: %2")
+                       .arg(messageRate, 0, 'f', 1)
+                       .arg(totalMessages);
+    
+    m_loadLabel->setText(loadText);
+}
+
+void MainWindow::createMessageFlowDock()
+{
+    // 创建信息流列表组件
+    m_messageFlowWidget = new DaemonMessageFlowWidget(this);
+    
+    // 创建停靠窗口
+    QDockWidget* dockWidget = new QDockWidget("守护进程信息流", this);
+    dockWidget->setWidget(m_messageFlowWidget);
+    dockWidget->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
+    dockWidget->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
+    
+    // 添加到主窗口
+    addDockWidget(Qt::BottomDockWidgetArea, dockWidget);
+    
+    // 设置守护进程客户端
+    if (m_daemonClient) {
+        m_messageFlowWidget->setDaemonClient(m_daemonClient);
+    }
+    
+    // 默认隐藏,可以通过视图菜单显示
+    dockWidget->hide();
+    
+    // 添加到视图菜单
+    QMenuBar* menuBar = this->menuBar();
+    if (menuBar) {
+        QMenu* viewMenu = nullptr;
+        QList<QAction*> actions = menuBar->actions();
+        for (QAction* action : actions) {
+            if (action->text() == "视图") {
+                viewMenu = qobject_cast<QMenu*>(action->menu());
+                break;
+            }
+        }
+        
+        if (viewMenu) {
+            QAction* flowAction = viewMenu->addAction("守护进程信息流");
+            flowAction->setCheckable(true);
+            flowAction->setChecked(false);
+            connect(flowAction, &QAction::toggled, dockWidget, &QDockWidget::setVisible);
+        }
+    }
+}
+
+void MainWindow::loadSettings() {
+    QSettings settings;
+    // 默认启用守护进程模式,提供更好的资源管理和权限控制
+    bool useDaemonMode = settings.value("daemon/useDaemonMode", true).toBool();
+    
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api) {
+        api->setUseDaemonMode(useDaemonMode);
+        LOG_DEBUG() << "加载设置 - 守护进程模式:" << (useDaemonMode ? "启用" : "禁用");
+    }
+}
+
+void MainWindow::showSettingsDialog() {
+    if (!m_settingsDialog) {
+        m_settingsDialog = new SettingsDialog(this);
+        // 设置守护进程客户端,让设置对话框能检查守护进程状态
+        m_settingsDialog->setDaemonClient(m_daemonClient);
+    }
+    
+    // 加载当前设置
+    m_settingsDialog->loadSettings();
+    
+    // 显示对话框
+    if (m_settingsDialog->exec() == QDialog::Accepted) {
+        // 用户点击了"确定",应用设置
+        bool useDaemonMode = m_settingsDialog->useDaemonMode();
+        
+        SoftBusAPI* api = SoftBusAPI::instance();
+        if (api) {
+            api->setUseDaemonMode(useDaemonMode);
+            LOG_DEBUG() << "设置已更新 - 守护进程模式:" << (useDaemonMode ? "启用" : "禁用");
+        }
+    }
+}
+
+void MainWindow::closeEvent(QCloseEvent *event) {
+    // 关闭窗口时只是隐藏窗口,不退出应用
+    // 这样总线核心可以继续在后台运行
+    hide();
+    event->ignore();  // 忽略关闭事件,不真正关闭窗口
+    
+    // 更新状态栏提示
+    if (statusBar()) {
+        statusBar()->showMessage("窗口已隐藏,总线核心继续运行中...", 3000);
+    }
+}

+ 27 - 0
mainwindow.h

@@ -8,6 +8,10 @@
 class DatabaseModule;
 class SerialModule;
 class Toolbar;
+class DaemonClient;
+class SettingsDialog;
+class QLabel;
+class DaemonMessageFlowWidget;
 
 class MainWindow : public QMainWindow
 {
@@ -16,6 +20,9 @@ class MainWindow : public QMainWindow
 public:
     MainWindow(QWidget *parent = nullptr);
 
+protected:
+    void closeEvent(QCloseEvent *event) override;
+
 private:
     void createUI();
     // menubar-菜单栏
@@ -33,6 +40,17 @@ private:
     void setupShortcuts();
     void connectSignals();
     void showAbout();
+    // daemon-守护进程
+    void setupDaemonStatus();
+    void updateDaemonStatus(bool running, const QString& statusJson);
+    void updateLoadInfo(const QString& loadInfoJson);
+    void createMessageFlowDock();
+    // settings-设置
+    void loadSettings();
+    void showSettingsDialog();
+private slots:
+    void onDaemonStatusChanged(bool running, const QString& statusJson);
+    void onLoadInfoUpdated(const QString& loadInfoJson);
 private:
     QStackedWidget *m_pageStack;
     QVector<Toolbar*> m_toolbars;
@@ -42,6 +60,15 @@ private:
     DatabaseModule *m_databaseModule = nullptr;
     int m_serialPageIndex = -1;
     int m_databasePageIndex = -1;
+    
+    // 守护进程客户端和状态显示
+    DaemonClient *m_daemonClient = nullptr;
+    QLabel *m_statusLabel = nullptr;
+    QLabel *m_loadLabel = nullptr;
+    DaemonMessageFlowWidget *m_messageFlowWidget = nullptr;
+    
+    // 设置对话框
+    SettingsDialog *m_settingsDialog = nullptr;
 };
 
 #endif // MAINWINDOW_H

+ 275 - 17
src/api/SoftBusAPI.cpp

@@ -6,6 +6,10 @@
 #include "can_manager/can_manager.h"
 #include "serial_manager/serial_manager.h"
 #include "soft_bus_core/soft_bus_core.h"
+#include "utils/logging.h"
+#ifndef SOFT_BUS_DAEMON_BUILD
+#include "daemon/daemon_client.h"
+#endif
 #include <QDebug>
 #include <QSerialPortInfo>
 
@@ -24,7 +28,12 @@ SoftBusAPI::SoftBusAPI(QObject* parent)
     , m_deviceBusCoreOwned(false)  // 默认不拥有所有权
     , m_canManager(nullptr)
     , m_serialManager(nullptr)
+#ifndef SOFT_BUS_DAEMON_BUILD
+    , m_daemonClient(nullptr)
+#endif
     , m_initialized(false)
+    , m_useDaemon(false)  // 默认不使用守护进程
+    , m_pendingDiscoveryInterval(0)  // 默认无待处理的扫描请求
 {
 }
 
@@ -38,7 +47,7 @@ SoftBusAPI::~SoftBusAPI() {
     m_tagQualities.clear();
     m_initialized = false;
     
-    qDebug() << "SoftBusAPI destroyed (core continues running)";
+    LOG_DEBUG() << "SoftBusAPI destroyed (core continues running)";
 }
 
 bool SoftBusAPI::initialize() {
@@ -50,7 +59,7 @@ bool SoftBusAPI::initialize() {
     CoreService* coreService = CoreService::instance();
     if (!coreService->isInitialized()) {
         if (!coreService->initialize()) {
-            qCritical() << "Failed to initialize CoreService";
+            LOG_CRITICAL() << "Failed to initialize CoreService";
             return false;
         }
     }
@@ -58,7 +67,7 @@ bool SoftBusAPI::initialize() {
     // 从 CoreService 获取核心实例
     m_core = coreService->getSoftBusCore();
     if (!m_core) {
-        qCritical() << "Failed to get SoftBusCore from CoreService";
+        LOG_CRITICAL() << "Failed to get SoftBusCore from CoreService";
         return false;
     }
 
@@ -71,10 +80,14 @@ bool SoftBusAPI::initialize() {
     initializeManagers();
 
     m_initialized = true;
-    qDebug() << "SoftBusAPI initialized";
+    LOG_INFO() << "SoftBusAPI initialized";
     return true;
 }
 
+bool SoftBusAPI::isInitialized() const {
+    return m_initialized;
+}
+
 void SoftBusAPI::shutdown() {
     if (!m_initialized) return;
 
@@ -87,7 +100,7 @@ void SoftBusAPI::shutdown() {
     m_tagValues.clear();
     m_tagQualities.clear();
     m_initialized = false;
-    qDebug() << "SoftBusAPI shutdown (core continues running)";
+    LOG_DEBUG() << "SoftBusAPI shutdown (core continues running)";
 }
 
 QVariant SoftBusAPI::getValue(const QString &tagName) {
@@ -99,7 +112,7 @@ QVariant SoftBusAPI::getValue(const QString &tagName) {
 
 bool SoftBusAPI::sendCommand(const QString &tagName, const QVariant &value, bool needAck) {
     if (!m_initialized) {
-        qWarning() << "SoftBusAPI not initialized";
+            LOG_WARNING() << "SoftBusAPI not initialized";
         return false;
     }
 
@@ -114,7 +127,7 @@ bool SoftBusAPI::sendCommand(const QString &tagName, const QVariant &value, bool
     MessageDispatcher* dispatcher = m_core->getDispatcher();
     dispatcher->dispatch(cmd);
 
-    qDebug() << "Sent command:" << tagName << "=" << value;
+    LOG_DEBUG() << "Sent command:" << tagName << "=" << value;
     return true;
 }
 
@@ -184,19 +197,21 @@ void SoftBusAPI::initializeManagers() {
         m_deviceBusCoreOwned = false;  // 不拥有所有权,由 CoreService 管理
     } else {
         // 如果 CoreService 未初始化,则创建一个临时实例(向后兼容)
-        qWarning() << "CoreService not initialized, creating temporary DeviceBusCore";
+        LOG_WARNING() << "CoreService not initialized, creating temporary DeviceBusCore";
         m_deviceBusCore = new DeviceBusCore(this);
         m_deviceBusCoreOwned = true;  // 拥有所有权,需要自己删除
         if (!m_deviceBusCore->initDB(QStringLiteral("soft_bus_db"))) {
-            qWarning() << "Failed to initialize DeviceBusCore database";
+            LOG_WARNING() << "Failed to initialize DeviceBusCore database";
         }
     }
 
     // 创建CAN管理器
+    LOG_INFO() << "创建 CAN 管理器(模式:" << (m_useDaemon ? "守护进程" : "本地") << ")";
     m_canManager = new CanManager(m_deviceBusCore, this);
     m_canManager->setBusCore(m_deviceBusCore);
 
     // 创建串口管理器
+    LOG_INFO() << "创建串口管理器(模式:" << (m_useDaemon ? "守护进程" : "本地") << ")";
     m_serialManager = new SerialManager(m_deviceBusCore, this);
     m_serialManager->setBusCore(m_deviceBusCore);
 
@@ -225,32 +240,68 @@ void SoftBusAPI::initializeManagers() {
 }
 
 void SoftBusAPI::cleanupManagers() {
+    // 断开信号连接并清理管理器
     if (m_canManager) {
+        disconnect(m_canManager, nullptr, this, nullptr);
         m_canManager->stopDiscovery();
         m_canManager->closeAllDevices();
+        // 注意:管理器是子对象(parent 是 this),但我们需要显式删除以便立即重新创建
+        // 先设置 parent 为 nullptr,然后删除
+        m_canManager->setParent(nullptr);
+        delete m_canManager;
+        m_canManager = nullptr;
     }
     if (m_serialManager) {
+        disconnect(m_serialManager, nullptr, this, nullptr);
         m_serialManager->stopDiscovery();
         m_serialManager->closeAllPorts();
+        // 先设置 parent 为 nullptr,然后删除
+        m_serialManager->setParent(nullptr);
+        delete m_serialManager;
+        m_serialManager = nullptr;
     }
-    // 如果拥有设备总线核心的所有权,则关闭它;否则只清除引用
-    if (m_deviceBusCore && m_deviceBusCoreOwned) {
-        m_deviceBusCore->closeDB();
-        delete m_deviceBusCore;
+    // 断开设备总线核心信号连接
+    if (m_deviceBusCore) {
+        disconnect(m_deviceBusCore, nullptr, this, nullptr);
+        // 如果拥有设备总线核心的所有权,则关闭它;否则只清除引用
+        if (m_deviceBusCoreOwned) {
+            m_deviceBusCore->closeDB();
+            delete m_deviceBusCore;
+        }
+        m_deviceBusCore = nullptr;
     }
-    m_deviceBusCore = nullptr;
     m_deviceBusCoreOwned = false;
 }
 
 // ========== 设备管理接口实现 ==========
 void SoftBusAPI::startDeviceDiscovery(int intervalMs) {
     if (!m_initialized) return;
+    
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果使用守护进程模式,检查守护进程是否已连接
+    if (m_useDaemon) {
+        if (!m_daemonClient || !m_daemonClient->isDaemonRunning()) {
+            LOG_WARNING() << "守护进程模式已启用,但守护进程未连接。设备扫描将延迟,直到守护进程连接成功。";
+            // 保存扫描间隔,等待守护进程连接后使用
+            m_pendingDiscoveryInterval = intervalMs;
+            return;
+        }
+        // 守护进程模式下,设备扫描由守护进程负责,这里不需要本地扫描
+        LOG_DEBUG() << "守护进程模式:设备扫描由守护进程负责";
+        // 注意:在守护进程模式下,设备列表应该从守护进程获取
+        // 这里可以触发一次设备列表更新请求
+        return;
+    }
+#endif
+    
+    // 本地模式:启动本地设备扫描
     if (m_serialManager) {
         m_serialManager->startDiscovery(intervalMs);
     }
-    if (m_canManager) {
-        m_canManager->startDiscovery(intervalMs);
-    }
+    // CAN设备暂时不自动启动发现,需要后续手动加载
+    // if (m_canManager) {
+    //     m_canManager->startDiscovery(intervalMs);
+    // }
 }
 
 void SoftBusAPI::stopDeviceDiscovery() {
@@ -263,6 +314,14 @@ void SoftBusAPI::stopDeviceDiscovery() {
 }
 
 QList<DeviceInfo> SoftBusAPI::getAllDevices() const {
+    // 如果使用守护进程模式且守护进程正在运行,从守护进程获取设备列表
+#ifndef SOFT_BUS_DAEMON_BUILD
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        return m_daemonClient->getAllDevices();
+    }
+#endif
+    
+    // 否则从本地设备总线核心获取
     if (m_deviceBusCore) {
         return m_deviceBusCore->getAllDevices();
     }
@@ -292,6 +351,14 @@ QStringList SoftBusAPI::getAvailableSerialPorts() const {
 }
 
 QStringList SoftBusAPI::getOpenedSerialPorts() const {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程查询
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        return m_daemonClient->getOpenedSerialPorts();
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (m_serialManager) {
         return m_serialManager->getOpenedPorts();
     }
@@ -299,23 +366,69 @@ QStringList SoftBusAPI::getOpenedSerialPorts() const {
 }
 
 bool SoftBusAPI::openSerialPort(const QSerialPortInfo &portInfo) {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程操作
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        SerialManager::SerialConfig config = getSerialConfig();
+        return m_daemonClient->openSerialPort(
+            portInfo.portName(),
+            config.baudRate,
+            config.dataBits,
+            config.parity,
+            config.stopBits,
+            config.flowControl
+        );
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (!m_serialManager) return false;
     return m_serialManager->openSerialPort(portInfo);
 }
 
 void SoftBusAPI::closeSerialPort(const QString &portName) {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程操作
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        m_daemonClient->closeSerialPort(portName);
+        return;
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (m_serialManager) {
         m_serialManager->closeSerialPort(portName);
     }
 }
 
 void SoftBusAPI::closeAllSerialPorts() {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程操作
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        QStringList openedPorts = m_daemonClient->getOpenedSerialPorts();
+        for (const QString& portName : openedPorts) {
+            m_daemonClient->closeSerialPort(portName);
+        }
+        return;
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (m_serialManager) {
         m_serialManager->closeAllPorts();
     }
 }
 
 bool SoftBusAPI::isSerialPortOpen(const QString &portName) const {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程查询
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        QStringList openedPorts = m_daemonClient->getOpenedSerialPorts();
+        return openedPorts.contains(portName);
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (m_serialManager) {
         return m_serialManager->isPortOpen(portName);
     }
@@ -323,6 +436,14 @@ bool SoftBusAPI::isSerialPortOpen(const QString &portName) const {
 }
 
 bool SoftBusAPI::sendSerialData(const QString &portName, const QByteArray &data) {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程操作
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        return m_daemonClient->writeSerialData(portName, data);
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (!m_serialManager) return false;
     return m_serialManager->writeData(portName, data);
 }
@@ -349,6 +470,14 @@ QList<int> SoftBusAPI::getAvailableCanDevices() const {
 }
 
 QStringList SoftBusAPI::getOpenedCanDevices() const {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程查询
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        return m_daemonClient->getOpenedCanDevices();
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (m_canManager) {
         return m_canManager->getOpenedDevices();
     }
@@ -356,23 +485,63 @@ QStringList SoftBusAPI::getOpenedCanDevices() const {
 }
 
 bool SoftBusAPI::openCanDevice(int comPort) {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程操作
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        // CAN设备默认波特率,可以根据需要调整
+        int baudRate = 500000;  // 默认500Kbps
+        return m_daemonClient->openCanDevice(comPort, baudRate);
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (!m_canManager) return false;
     return m_canManager->openCanDevice(comPort);
 }
 
 void SoftBusAPI::closeCanDevice(const QString &deviceName) {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程操作
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        m_daemonClient->closeCanDevice(deviceName);
+        return;
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (m_canManager) {
         m_canManager->closeCanDevice(deviceName);
     }
 }
 
 void SoftBusAPI::closeAllCanDevices() {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程操作
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        QStringList openedDevices = m_daemonClient->getOpenedCanDevices();
+        for (const QString& deviceName : openedDevices) {
+            m_daemonClient->closeCanDevice(deviceName);
+        }
+        return;
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (m_canManager) {
         m_canManager->closeAllDevices();
     }
 }
 
 bool SoftBusAPI::isCanDeviceOpen(const QString &deviceName) const {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程查询
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        QStringList openedDevices = m_daemonClient->getOpenedCanDevices();
+        return openedDevices.contains(deviceName);
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (m_canManager) {
         return m_canManager->isDeviceOpen(deviceName);
     }
@@ -381,6 +550,14 @@ bool SoftBusAPI::isCanDeviceOpen(const QString &deviceName) const {
 
 bool SoftBusAPI::sendCanData(const QString &deviceName, int canPort, unsigned int canId,
                              const QByteArray &data, bool isExtendedId) {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 如果设置了守护进程客户端且已连接,则通过守护进程操作
+    if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        return m_daemonClient->sendCanData(deviceName, canPort, canId, data, isExtendedId);
+    }
+#endif
+    
+    // 否则使用本地管理器(向后兼容)
     if (!m_canManager) return false;
     return m_canManager->sendData(deviceName, canPort, canId, data, isExtendedId);
 }
@@ -439,3 +616,84 @@ void SoftBusAPI::onBusMessageStored(const BusMessage &message) {
     emit busMessageStored(message);
 }
 
+#ifndef SOFT_BUS_DAEMON_BUILD
+void SoftBusAPI::setDaemonClient(DaemonClient* daemonClient) {
+    if (m_daemonClient == daemonClient) {
+        return;
+    }
+    
+    // 断开旧的信号连接
+    if (m_daemonClient) {
+        disconnect(m_daemonClient, nullptr, this, nullptr);
+    }
+    
+    m_daemonClient = daemonClient;
+    
+    // 连接新的信号
+    if (m_daemonClient) {
+        // 连接硬件数据接收信号
+        connect(m_daemonClient, &DaemonClient::serialDataReceived,
+                this, &SoftBusAPI::onSerialDataReceived);
+        connect(m_daemonClient, &DaemonClient::canDataReceived,
+                this, &SoftBusAPI::onCanDataReceived);
+        
+        // 注意:不再自动启用守护进程模式,由用户设置决定
+    }
+}
+#endif
+
+void SoftBusAPI::setUseDaemonMode(bool useDaemon) {
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 检查模式是否改变
+    bool modeChanged = (m_useDaemon != useDaemon);
+    
+    LOG_INFO() << "设置守护进程模式:" << useDaemon << (modeChanged ? " (模式改变)" : "");
+    
+    // 如果模式改变且已经初始化,需要重新创建管理器
+    if (modeChanged && m_initialized) {
+        LOG_INFO() << "模式改变且已初始化,重新创建管理器...";
+        // 停止当前管理器
+        cleanupManagers();
+        // 更新模式
+        m_useDaemon = useDaemon;
+        // 重新创建管理器
+        initializeManagers();
+        LOG_INFO() << "管理器已重新创建(模式:" << (m_useDaemon ? "守护进程" : "本地") << ")";
+    } else {
+        // 模式未改变或未初始化,直接更新模式
+        m_useDaemon = useDaemon;
+    }
+    
+    // 如果启用守护进程模式但守护进程未运行,给出警告
+    if (m_useDaemon && m_daemonClient && !m_daemonClient->isDaemonRunning()) {
+        LOG_WARNING() << "警告:守护进程模式已启用,但守护进程服务未运行。硬件操作将失败。";
+    } else if (m_useDaemon && m_daemonClient && m_daemonClient->isDaemonRunning()) {
+        LOG_INFO() << "守护进程模式已启用,守护进程服务正在运行";
+        // 守护进程连接成功,如果有待处理的设备扫描请求,则启动扫描
+        // 注意:在守护进程模式下,设备扫描由守护进程负责,这里只是通知可以开始查询设备列表
+        if (m_pendingDiscoveryInterval > 0) {
+            LOG_INFO() << "守护进程已连接,设备扫描将由守护进程负责";
+            m_pendingDiscoveryInterval = 0;  // 清除待处理标志
+        }
+    } else if (!m_useDaemon) {
+        LOG_INFO() << "使用本地模式进行硬件操作";
+        // 切换到本地模式时,如果有待处理的扫描请求,立即启动本地扫描
+        if (m_pendingDiscoveryInterval > 0) {
+            int interval = m_pendingDiscoveryInterval;
+            m_pendingDiscoveryInterval = 0;
+            startDeviceDiscovery(interval);
+        }
+    } else if (m_useDaemon && !m_daemonClient) {
+        LOG_WARNING() << "守护进程模式已启用,但 DaemonClient 尚未设置";
+    }
+#else
+    // 守护进程版本始终使用本地模式
+    m_useDaemon = false;
+    Q_UNUSED(useDaemon);
+#endif
+}
+
+bool SoftBusAPI::useDaemonMode() const {
+    return m_useDaemon;
+}
+

+ 34 - 0
src/api/SoftBusAPI.h

@@ -21,6 +21,9 @@
 // 前向声明
 class CanManager;
 class SerialManager;
+#ifndef SOFT_BUS_DAEMON_BUILD
+class DaemonClient;
+#endif
 
 // 需要 SerialConfig 结构,所以需要包含头文件
 #include "serial_manager/serial_manager.h"
@@ -43,6 +46,12 @@ public:
      */
     bool initialize();
 
+    /**
+     * @brief 检查API是否已初始化
+     * @return 已初始化返回true
+     */
+    bool isInitialized() const;
+
     /**
      * @brief 关闭API(停止系统)
      */
@@ -173,6 +182,26 @@ public:
      */
     void setSerialConfig(const SerialManager::SerialConfig &config);
 
+#ifndef SOFT_BUS_DAEMON_BUILD
+    /**
+     * @brief 设置守护进程客户端(用于硬件操作)
+     * @param daemonClient 守护进程客户端指针
+     */
+    void setDaemonClient(DaemonClient* daemonClient);
+#endif
+
+    /**
+     * @brief 设置是否使用守护进程模式
+     * @param useDaemon 是否使用守护进程模式
+     */
+    void setUseDaemonMode(bool useDaemon);
+
+    /**
+     * @brief 获取是否使用守护进程模式
+     * @return 使用守护进程模式返回true
+     */
+    bool useDaemonMode() const;
+
     // ========== CAN设备接口 ==========
     /**
      * @brief 获取所有可用CAN设备列表(返回com_port列表)
@@ -372,9 +401,14 @@ private:
     bool m_deviceBusCoreOwned;       // 是否拥有设备总线核心的所有权
     CanManager* m_canManager;        // CAN管理器
     SerialManager* m_serialManager;   // 串口管理器
+#ifndef SOFT_BUS_DAEMON_BUILD
+    DaemonClient* m_daemonClient;    // 守护进程客户端(用于硬件操作)
+#endif
     
     QMap<QString, QVariant> m_tagValues;  // 标签值缓存
     QMap<QString, int> m_tagQualities;     // 标签质量码缓存
     bool m_initialized;
+    bool m_useDaemon;  // 是否使用守护进程进行硬件操作
+    int m_pendingDiscoveryInterval;  // 待处理的设备扫描间隔(守护进程连接前请求的)
 };
 

+ 29 - 29
src/can_manager/can_manager.cpp

@@ -1,5 +1,5 @@
 #include "can_manager.h"
-#include <QDebug>
+#include "utils/logging.h"
 #include <QDateTime>
 #include <QJsonDocument>
 #include <QJsonArray>
@@ -58,7 +58,7 @@ bool CanManager::openCanDevice(int comPort)
     int rtn = EMUCOpenDevice(comPort);
     if (rtn != 0)
     {
-        qWarning() << "Failed to open CAN device on com_port" << comPort;
+        LOG_WARNING() << "Failed to open CAN device on com_port" << comPort;
         return false;
     }
 
@@ -80,7 +80,7 @@ bool CanManager::openCanDevice(int comPort)
     connect(thread, &CanReceiveThread::finished, this, &CanManager::onReceiveThreadFinished);
     thread->start();
 
-    qDebug() << "Opened CAN device:" << deviceName << "on com_port" << comPort;
+    LOG_DEBUG() << "Opened CAN device:" << deviceName << "on com_port" << comPort;
     return true;
 }
 
@@ -111,7 +111,7 @@ void CanManager::closeCanDevice(const QString &deviceName)
         m_portToDeviceName.remove(comPort);
         
         emit deviceRemoved(deviceName);
-        qDebug() << "Closed CAN device:" << deviceName;
+        LOG_DEBUG() << "Closed CAN device:" << deviceName;
     }
 }
 
@@ -131,7 +131,7 @@ void CanManager::closeAllDevices()
         closeCanDevice(deviceName);
     }
     
-    qDebug() << "All CAN devices closed";
+    LOG_DEBUG() << "All CAN devices closed";
 }
 
 void CanManager::setCanConfig(int canPort, const CanConfig &config)
@@ -172,7 +172,7 @@ void CanManager::setCanConfig(int canPort, const CanConfig &config)
         }
     }
     
-    qDebug() << "CAN configuration updated for CAN" << (canPort + 1);
+    LOG_DEBUG() << "CAN configuration updated for CAN" << (canPort + 1);
 }
 
 CanManager::CanConfig CanManager::getCanConfig(int canPort) const
@@ -194,7 +194,7 @@ QList<int> CanManager::getAvailableDevices() const
 {
     QList<int> devices;
     
-    qDebug() << "开始扫描CAN设备,最大端口数:" << MAX_COM_NUM;
+    LOG_DEBUG() << "开始扫描CAN设备,最大端口数:" << MAX_COM_NUM;
     
     // 扫描所有可能的com_port
     for (int i = 0; i < MAX_COM_NUM; i++)
@@ -204,15 +204,15 @@ QList<int> CanManager::getAvailableDevices() const
         {
             EMUCCloseDevice(i);
             devices.append(i);
-            qDebug() << "发现CAN设备,com_port:" << i;
+            LOG_DEBUG() << "发现CAN设备,com_port:" << i;
         }
         else if (i < 10)  // 只输出前10个端口的错误信息,避免日志过多
         {
-            qDebug() << "端口" << i << "打开失败,返回值:" << rtn;
+            LOG_DEBUG() << "端口" << i << "打开失败,返回值:" << rtn;
         }
     }
     
-    qDebug() << "CAN设备扫描完成,共发现" << devices.size() << "个设备";
+    LOG_DEBUG() << "CAN设备扫描完成,共发现" << devices.size() << "个设备";
     return devices;
 }
 
@@ -223,7 +223,7 @@ bool CanManager::sendData(const QString &deviceName, int canPort, unsigned int c
     
     if (!m_deviceNameToPort.contains(deviceName))
     {
-        qWarning() << "Device not found:" << deviceName;
+        LOG_WARNING() << "Device not found:" << deviceName;
         return false;
     }
     
@@ -245,13 +245,13 @@ bool CanManager::sendData(const QString &deviceName, int canPort, unsigned int c
     int rtn = EMUCSend(comPort, &frame);
     if (rtn == 0)
     {
-        qDebug() << "Data sent to" << deviceName << "CAN" << (canPort + 1) 
+        LOG_DEBUG() << "Data sent to" << deviceName << "CAN" << (canPort + 1) 
                  << "ID:" << QString::number(canId, 16) << "Data:" << data.toHex();
         return true;
     }
     else
     {
-        qWarning() << "Failed to send data to" << deviceName;
+        LOG_WARNING() << "Failed to send data to" << deviceName;
         return false;
     }
 }
@@ -259,7 +259,7 @@ bool CanManager::sendData(const QString &deviceName, int canPort, unsigned int c
 void CanManager::setBusCore(DeviceBusCore *busCore)
 {
     m_busCore = busCore;
-    qDebug() << "Bus core set for CanManager";
+    LOG_INFO() << "Bus core set for CanManager";
 }
 
 DeviceBusCore *CanManager::getBusCore() const
@@ -280,7 +280,7 @@ void CanManager::discoverDevices()
 {
     QMutexLocker locker(&m_mutex);
     
-    qDebug() << "开始发现CAN设备...";
+    LOG_DEBUG() << "开始发现CAN设备...";
     
     // 获取当前所有可用设备
     QSet<int> currentDevices;
@@ -297,12 +297,12 @@ void CanManager::discoverDevices()
             {
                 QString deviceName = QString("CAN_%1").arg(i);
                 emit deviceDiscovered(deviceName, i);
-                qDebug() << "新发现CAN设备:" << deviceName << "com_port:" << i;
+                LOG_DEBUG() << "新发现CAN设备:" << deviceName << "com_port:" << i;
             }
         }
     }
     
-    qDebug() << "CAN设备发现完成,当前可用设备数:" << currentDevices.size();
+    LOG_DEBUG() << "CAN设备发现完成,当前可用设备数:" << currentDevices.size();
     
     // 检查是否有设备被移除
     QSet<int> removedDevices = m_lastDiscoveredDevices - currentDevices;
@@ -315,7 +315,7 @@ void CanManager::discoverDevices()
             closeCanDevice(deviceName);
         }
         emit deviceRemoved(deviceName);
-        qDebug() << "CAN device removed:" << deviceName;
+        LOG_DEBUG() << "CAN device removed:" << deviceName;
     }
     
     // 更新上次发现的设备列表
@@ -328,7 +328,7 @@ bool CanManager::initCanDevice(int comPort)
     int rtn = EMUCInitCAN(comPort, EMUC_INACTIVE, EMUC_INACTIVE);
     if (rtn != 0)
     {
-        qWarning() << "Failed to initialize CAN on com_port" << comPort;
+        LOG_WARNING() << "Failed to initialize CAN on com_port" << comPort;
         return false;
     }
     
@@ -345,7 +345,7 @@ bool CanManager::initCanDevice(int comPort)
     rtn = EMUCSetBaudRate(comPort, config1.baudRate, config2.baudRate);
     if (rtn != 0)
     {
-        qWarning() << "Failed to set baud rate on com_port" << comPort;
+        LOG_WARNING() << "Failed to set baud rate on com_port" << comPort;
         return false;
     }
     
@@ -356,7 +356,7 @@ bool CanManager::initCanDevice(int comPort)
     rtn = EMUCSetMode(comPort, config1.mode, config2.mode);
     if (rtn != 0)
     {
-        qWarning() << "Failed to set mode on com_port" << comPort;
+        LOG_WARNING() << "Failed to set mode on com_port" << comPort;
         return false;
     }
     
@@ -385,11 +385,11 @@ bool CanManager::initCanDevice(int comPort)
     rtn = EMUCInitCAN(comPort, EMUC_ACTIVE, EMUC_ACTIVE);
     if (rtn != 0)
     {
-        qWarning() << "Failed to activate CAN on com_port" << comPort;
+        LOG_WARNING() << "Failed to activate CAN on com_port" << comPort;
         return false;
     }
     
-    qDebug() << "CAN device initialized successfully on com_port" << comPort;
+    LOG_DEBUG() << "CAN device initialized successfully on com_port" << comPort;
     return true;
 }
 
@@ -430,7 +430,7 @@ void CanManager::parseData(const QString &deviceName, int canPort, unsigned int
     
     // 发出信号
     emit canDataParsed(payload);
-    qDebug() << "CAN data parsed from" << deviceName << "CAN" << (canPort + 1) << ":" << payload;
+    LOG_DEBUG() << "CAN data parsed from" << deviceName << "CAN" << (canPort + 1) << ":" << payload;
 }
 
 void CanManager::storeRawData(const QString &deviceName, const QByteArray &data)
@@ -442,11 +442,11 @@ void CanManager::storeRawData(const QString &deviceName, const QByteArray &data)
         if (device.id != 0)
         {
             m_busCore->storeRawData(device.id, data);
-            qDebug() << "Raw data stored for device ID" << device.id << "(" << deviceName << "):" << data.toHex();
+            LOG_DEBUG() << "Raw data stored for device ID" << device.id << "(" << deviceName << "):" << data.toHex();
         }
         else
         {
-            qWarning() << "Device not found for device name:" << deviceName;
+            LOG_WARNING() << "Device not found for device name:" << deviceName;
         }
     }
 }
@@ -462,7 +462,7 @@ void CanManager::onReceiveThreadFinished()
     CanReceiveThread *thread = qobject_cast<CanReceiveThread*>(sender());
     if (thread)
     {
-        qDebug() << "CAN receive thread finished for com_port" << thread->getComPort();
+        LOG_DEBUG() << "CAN receive thread finished for com_port" << thread->getComPort();
     }
 }
 
@@ -499,11 +499,11 @@ void CanReceiveThread::run()
             }
             else if (frame.msg_type == EMUC_EEERR_TYPE)
             {
-                qWarning() << "EEPROM Error on com_port" << m_comPort;
+                LOG_WARNING() << "EEPROM Error on com_port" << m_comPort;
             }
             else if (frame.msg_type == EMUC_BUSERR_TYPE)
             {
-                qWarning() << "Bus Error on com_port" << m_comPort;
+                LOG_WARNING() << "Bus Error on com_port" << m_comPort;
             }
         }
         

+ 7 - 8
src/core/CoreService.cpp

@@ -1,6 +1,5 @@
 #include "CoreService.h"
-#include <QDebug>
-#include <QApplication>
+#include "utils/logging.h"
 
 CoreService* CoreService::instance() {
     static CoreService* inst = nullptr;
@@ -24,35 +23,35 @@ CoreService::~CoreService() {
 
 bool CoreService::initialize() {
     if (m_initialized) {
-        qWarning() << "CoreService already initialized";
+        LOG_WARNING() << "CoreService already initialized";
         return true;
     }
 
     // 初始化软总线核心
     m_softBusCore = SoftBusCore::instance();
     if (!m_softBusCore->initialize()) {
-        qCritical() << "Failed to initialize SoftBusCore";
+        LOG_CRITICAL() << "Failed to initialize SoftBusCore";
         return false;
     }
 
     // 创建设备总线核心(不设置父对象,确保独立生命周期)
     m_deviceBusCore = new DeviceBusCore();
     if (!m_deviceBusCore->initDB(QStringLiteral("soft_bus_db"))) {
-        qCritical() << "Failed to initialize DeviceBusCore database";
+        LOG_CRITICAL() << "Failed to initialize DeviceBusCore database";
         delete m_deviceBusCore;
         m_deviceBusCore = nullptr;
         return false;
     }
 
     m_initialized = true;
-    qDebug() << "CoreService initialized - core will continue running after UI closes";
+    LOG_DEBUG() << "CoreService initialized - core will continue running after UI closes";
     return true;
 }
 
 void CoreService::shutdown() {
     if (!m_initialized) return;
 
-    qDebug() << "CoreService shutting down...";
+    LOG_DEBUG() << "CoreService shutting down...";
 
     // 关闭设备总线核心
     if (m_deviceBusCore) {
@@ -69,6 +68,6 @@ void CoreService::shutdown() {
     }
 
     m_initialized = false;
-    qDebug() << "CoreService shutdown complete";
+    LOG_DEBUG() << "CoreService shutdown complete";
 }
 

+ 7 - 7
src/core/SoftBusCore.cpp

@@ -1,5 +1,5 @@
 #include "SoftBusCore.h"
-#include <QDebug>
+#include "utils/logging.h"
 
 SoftBusCore* SoftBusCore::instance() {
     static SoftBusCore* inst = nullptr;
@@ -28,7 +28,7 @@ SoftBusCore::~SoftBusCore() {
 
 bool SoftBusCore::initialize() {
     if (m_initialized) {
-        qWarning() << "SoftBusCore already initialized";
+        LOG_WARNING() << "SoftBusCore already initialized";
         return true;
     }
 
@@ -37,7 +37,7 @@ bool SoftBusCore::initialize() {
 
     m_initialized = true;
     emit systemStarted();
-    qDebug() << "SoftBusCore initialized";
+    LOG_DEBUG() << "SoftBusCore initialized";
     return true;
 }
 
@@ -57,14 +57,14 @@ void SoftBusCore::shutdown() {
 
     m_initialized = false;
     emit systemStopped();
-    qDebug() << "SoftBusCore shutdown";
+    LOG_DEBUG() << "SoftBusCore shutdown";
 }
 
 void SoftBusCore::registerProtocolAdapter(IProtocolAdapter* adapter) {
     if (!adapter) return;
 
     if (m_adapters.contains(adapter)) {
-        qWarning() << "Protocol adapter already registered:" << adapter->getName();
+        LOG_WARNING() << "Protocol adapter already registered:" << adapter->getName();
         return;
     }
 
@@ -74,14 +74,14 @@ void SoftBusCore::registerProtocolAdapter(IProtocolAdapter* adapter) {
     });
 
     m_adapters.append(adapter);
-    qDebug() << "Registered protocol adapter:" << adapter->getName();
+    LOG_DEBUG() << "Registered protocol adapter:" << adapter->getName();
 }
 
 void SoftBusCore::unregisterProtocolAdapter(IProtocolAdapter* adapter) {
     if (!adapter) return;
 
     m_adapters.removeAll(adapter);
-    qDebug() << "Unregistered protocol adapter:" << adapter->getName();
+    LOG_DEBUG() << "Unregistered protocol adapter:" << adapter->getName();
 }
 
 void SoftBusCore::onProtocolDataReceived(DomBasePtr data) {

+ 5 - 5
src/core/dal/mapper/DataMapper.cpp

@@ -2,7 +2,7 @@
 #include <QJsonDocument>
 #include <QJsonArray>
 #include <QFile>
-#include <QDebug>
+#include "utils/logging.h"
 #include <cmath>
 
 DataMapper::DataMapper() {
@@ -14,7 +14,7 @@ DataMapper::~DataMapper() {
 bool DataMapper::loadProfile(const QString &filePath) {
     QFile file(filePath);
     if (!file.open(QIODevice::ReadOnly)) {
-        qWarning() << "Failed to open mapping profile:" << filePath;
+        LOG_WARNING() << "Failed to open mapping profile:" << filePath;
         return false;
     }
 
@@ -24,7 +24,7 @@ bool DataMapper::loadProfile(const QString &filePath) {
     QJsonParseError error;
     QJsonDocument doc = QJsonDocument::fromJson(data, &error);
     if (error.error != QJsonParseError::NoError) {
-        qWarning() << "Failed to parse JSON:" << error.errorString();
+        LOG_WARNING() << "Failed to parse JSON:" << error.errorString();
         return false;
     }
 
@@ -33,7 +33,7 @@ bool DataMapper::loadProfile(const QString &filePath) {
 
 bool DataMapper::loadFromJson(const QJsonObject &json) {
     if (!json.contains("tags") || !json["tags"].isArray()) {
-        qWarning() << "Invalid mapping profile: missing 'tags' array";
+        LOG_WARNING() << "Invalid mapping profile: missing 'tags' array";
         return false;
     }
 
@@ -74,7 +74,7 @@ bool DataMapper::loadFromJson(const QJsonObject &json) {
         m_mappingTable[config.sourceId] = config;
     }
 
-    qDebug() << "Loaded" << m_mappingTable.size() << "tag mappings";
+    LOG_DEBUG() << "Loaded" << m_mappingTable.size() << "tag mappings";
     return true;
 }
 

+ 3 - 3
src/core/pal/serial/SerialProtocolAdapter.cpp

@@ -2,7 +2,7 @@
 #include "serial_manager/serial_manager.h"
 #include "common/dom/DomBase.h"
 #include <QSerialPortInfo>
-#include <QDebug>
+#include "utils/logging.h"
 #include <QJsonDocument>
 
 SerialProtocolAdapter::SerialProtocolAdapter(QObject* parent)
@@ -18,7 +18,7 @@ SerialProtocolAdapter::~SerialProtocolAdapter() {
 
 bool SerialProtocolAdapter::open() {
     if (!m_serialManager) {
-        qWarning() << "SerialManager not set";
+        LOG_WARNING() << "SerialManager not set";
         return false;
     }
 
@@ -42,7 +42,7 @@ bool SerialProtocolAdapter::isOpen() const {
 
 bool SerialProtocolAdapter::sendRaw(const QByteArray &data) {
     if (!m_serialManager || m_currentPortName.isEmpty()) {
-        qWarning() << "SerialManager not available or no port selected";
+        LOG_WARNING() << "SerialManager not available or no port selected";
         return false;
     }
 

+ 5 - 5
src/core/sbl/dispatcher/MessageDispatcher.cpp

@@ -1,6 +1,6 @@
 #include "MessageDispatcher.h"
 #include "common/dom/DomBase.h"
-#include <QDebug>
+#include "utils/logging.h"
 #include <QRegularExpression>
 #include <QVariant>
 #include <QMetaObject>
@@ -33,7 +33,7 @@ void MessageDispatcher::start() {
 
     m_running = true;
     m_processTimer->start();
-    qDebug() << "MessageDispatcher started";
+    LOG_DEBUG() << "MessageDispatcher started";
 }
 
 void MessageDispatcher::stop() {
@@ -48,7 +48,7 @@ void MessageDispatcher::stop() {
     m_monitorQueue.clear();
     m_lowPriorityQueue.clear();
 
-    qDebug() << "MessageDispatcher stopped";
+    LOG_DEBUG() << "MessageDispatcher stopped";
 }
 
 void MessageDispatcher::dispatch(DomBasePtr data) {
@@ -110,7 +110,7 @@ void MessageDispatcher::subscribe(const QString &topicPattern, QObject* receiver
     // 但接收者的槽可能签名不同,我们需要动态调用
     // 这里先存储订阅信息,实际分发时使用QMetaObject::invokeMethod
 
-    qDebug() << "Subscribed:" << topicPattern << "->" << slotName;
+    LOG_DEBUG() << "Subscribed:" << topicPattern << "->" << slotName;
 }
 
 void MessageDispatcher::unsubscribe(QObject* receiver) {
@@ -134,7 +134,7 @@ void MessageDispatcher::unsubscribe(QObject* receiver) {
     }
 
     disconnect(receiver);
-    qDebug() << "Unsubscribed receiver";
+    LOG_DEBUG() << "Unsubscribed receiver";
 }
 
 void MessageDispatcher::processQueues() {

+ 3 - 3
src/core/sbl/pubsub/TopicTree.cpp

@@ -1,5 +1,5 @@
 #include "TopicTree.h"
-#include <QDebug>
+#include "utils/logging.h"
 
 TopicTree::TopicTree() {
     m_root = new TopicNode("");
@@ -25,7 +25,7 @@ void TopicTree::subscribe(const QString &topic, QObject* subscriber) {
 
     if (!current->subscribers.contains(subscriber)) {
         current->subscribers.append(subscriber);
-        qDebug() << "Subscribed" << subscriber << "to topic:" << topic;
+        LOG_DEBUG() << "Subscribed" << subscriber << "to topic:" << topic;
     }
 }
 
@@ -43,7 +43,7 @@ void TopicTree::unsubscribe(const QString &topic, QObject* subscriber) {
     }
 
     current->subscribers.removeAll(subscriber);
-    qDebug() << "Unsubscribed" << subscriber << "from topic:" << topic;
+    LOG_DEBUG() << "Unsubscribed" << subscriber << "from topic:" << topic;
 }
 
 QList<QObject*> TopicTree::getSubscribers(const QString &topic) const {

+ 533 - 0
src/daemon/daemon_client.cpp

@@ -0,0 +1,533 @@
+/**
+ * @file daemon_client.cpp
+ * @brief D-Bus 客户端实现
+ */
+
+#include "daemon_client.h"
+#include "soft_bus_core/soft_bus_core.h"
+#include <QDBusConnection>
+#include <QDBusInterface>
+#include <QDBusReply>
+#include "utils/logging.h"
+#include <QTimer>
+#include <QProcess>
+#include <QCoreApplication>
+#include <QDir>
+#include <QStandardPaths>
+#include <QFileInfo>
+#include <QThread>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QDateTime>
+
+DaemonClient::DaemonClient(QObject* parent)
+    : QObject(parent)
+    , m_interface(nullptr)
+    , m_updateTimer(nullptr)
+    , m_daemonProcess(nullptr)
+    , m_connected(false)
+{
+    setupTimer();
+}
+
+DaemonClient::~DaemonClient()
+{
+    if (m_updateTimer) {
+        m_updateTimer->stop();
+    }
+    delete m_interface;
+    // 注意:不在这里停止守护进程,让它继续运行
+    // delete m_daemonProcess; // 守护进程应该独立运行
+}
+
+bool DaemonClient::connectToDaemon()
+{
+    if (m_connected && m_interface) {
+        return true;
+    }
+
+    // 使用系统 D-Bus(系统级服务)
+    QDBusConnection connection = QDBusConnection::systemBus();
+    if (!connection.isConnected()) {
+        LOG_WARNING() << "Cannot connect to system D-Bus";
+        m_connected = false;
+        return false;
+    }
+
+    // 创建 D-Bus 接口
+    delete m_interface;
+    m_interface = new QDBusInterface(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        connection,
+        this
+    );
+
+    // 如果接口无效,尝试启动守护进程
+    if (!m_interface->isValid()) {
+        LOG_INFO() << "Daemon service not found, attempting to start...";
+        if (!startDaemon()) {
+            LOG_WARNING() << "Failed to start daemon:" << connection.lastError().message();
+            m_connected = false;
+            return false;
+        }
+        
+        // 等待守护进程启动(最多等待3秒)
+        for (int i = 0; i < 30; ++i) {
+            QThread::msleep(100);
+            QCoreApplication::processEvents();
+            
+            // 重新创建接口
+            delete m_interface;
+            m_interface = new QDBusInterface(
+                "com.softbus.Daemon",
+                "/com/softbus/Daemon",
+                "com.softbus.Daemon",
+                connection,
+                this
+            );
+            
+            if (m_interface->isValid()) {
+                LOG_INFO() << "Daemon started successfully";
+                break;
+            }
+        }
+        
+        if (!m_interface->isValid()) {
+            LOG_WARNING() << "Daemon started but D-Bus interface is still not valid:" << connection.lastError().message();
+            m_connected = false;
+            return false;
+        }
+    }
+
+    // 连接信号
+    connection.connect(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        "statusChanged",
+        this,
+        SLOT(onDaemonStatusChanged(QString))
+    );
+
+    connection.connect(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        "loadInfoUpdated",
+        this,
+        SLOT(onLoadInfoUpdated(QString))
+    );
+
+    // 连接硬件资源信号
+    connection.connect(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        "serialDataReceived",
+        this,
+        SLOT(onSerialDataReceived(QString, QString))
+    );
+    
+    connection.connect(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        "serialPortStatusChanged",
+        this,
+        SLOT(onSerialPortStatusChanged(QString, bool))
+    );
+    
+    connection.connect(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        "canDataReceived",
+        this,
+        SLOT(onCanDataReceived(QString, int, uint, QString, bool))
+    );
+    
+    connection.connect(
+        "com.softbus.Daemon",
+        "/com/softbus/Daemon",
+        "com.softbus.Daemon",
+        "canDeviceStatusChanged",
+        this,
+        SLOT(onCanDeviceStatusChanged(QString, bool))
+    );
+
+    m_connected = true;
+    updateStatus(); // 立即更新一次状态
+    return true;
+}
+
+bool DaemonClient::isDaemonRunning() const
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return false;
+    }
+
+    QDBusReply<bool> reply = m_interface->call("isRunning");
+    if (reply.isValid()) {
+        return reply.value();
+    }
+    return false;
+}
+
+QString DaemonClient::getStatus() const
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return QString();
+    }
+
+    QDBusReply<QString> reply = m_interface->call("getStatus");
+    if (reply.isValid()) {
+        return reply.value();
+    }
+    return QString();
+}
+
+QString DaemonClient::getLoadInfo() const
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return QString();
+    }
+
+    QDBusReply<QString> reply = m_interface->call("getLoadInfo");
+    if (reply.isValid()) {
+        return reply.value();
+    }
+    return QString();
+}
+
+int DaemonClient::getDeviceCount() const
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return 0;
+    }
+
+    QDBusReply<int> reply = m_interface->call("getDeviceCount");
+    if (reply.isValid()) {
+        return reply.value();
+    }
+    return 0;
+}
+
+QList<DeviceInfo> DaemonClient::getAllDevices() const
+{
+    QList<DeviceInfo> devices;
+    
+    if (!m_interface || !m_interface->isValid()) {
+        return devices;
+    }
+
+    QDBusReply<QString> reply = m_interface->call("getAllDevices");
+    if (!reply.isValid()) {
+        return devices;
+    }
+    
+    QJsonDocument doc = QJsonDocument::fromJson(reply.value().toUtf8());
+    if (!doc.isObject()) {
+        return devices;
+    }
+    
+    QJsonObject obj = doc.object();
+    QJsonArray devicesArray = obj["devices"].toArray();
+    
+    for (const QJsonValue& value : devicesArray) {
+        QJsonObject deviceObj = value.toObject();
+        DeviceInfo device;
+        device.id = deviceObj["id"].toInt();
+        device.portname = deviceObj["portname"].toString();
+        device.name = deviceObj["name"].toString();
+        device.type = deviceObj["type"].toString();
+        device.address = deviceObj["address"].toInt();
+        device.protocol = deviceObj["protocol"].toString();
+        device.protocol_detail = deviceObj["protocol_detail"].toString();
+        device.status = deviceObj["status"].toString();
+        device.isActive = deviceObj["isActive"].toBool();
+        
+        QString lastSeenStr = deviceObj["lastSeen"].toString();
+        if (!lastSeenStr.isEmpty()) {
+            device.lastSeen = QDateTime::fromString(lastSeenStr, Qt::ISODate);
+        }
+        
+        device.properties = deviceObj["properties"].toObject();
+        devices.append(device);
+    }
+    
+    return devices;
+}
+
+qint64 DaemonClient::getPid() const
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return 0;
+    }
+
+    QDBusReply<qint64> reply = m_interface->call("getPid");
+    if (reply.isValid()) {
+        return reply.value();
+    }
+    return 0;
+}
+
+void DaemonClient::updateStatus()
+{
+    if (!m_connected) {
+        if (!connectToDaemon()) {
+            emit daemonStatusChanged(false, "disconnected");
+            return;
+        }
+    }
+
+    bool running = isDaemonRunning();
+    QString statusJson = getStatus();
+    emit daemonStatusChanged(running, statusJson);
+    
+    QString loadInfo = getLoadInfo();
+    if (!loadInfo.isEmpty()) {
+        emit loadInfoUpdated(loadInfo);
+    }
+}
+
+void DaemonClient::onDaemonStatusChanged(const QString& status)
+{
+    bool running = isDaemonRunning();
+    emit daemonStatusChanged(running, status);
+}
+
+void DaemonClient::onLoadInfoUpdated(const QString& loadInfo)
+{
+    emit loadInfoUpdated(loadInfo);
+}
+
+// ========== 硬件资源操作接口实现 ==========
+bool DaemonClient::openSerialPort(const QString& portName, int baudRate, int dataBits,
+                                  int parity, int stopBits, int flowControl)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return false;
+    }
+    
+    QDBusReply<bool> reply = m_interface->call("openSerialPort", portName, baudRate,
+                                                dataBits, parity, stopBits, flowControl);
+    return reply.isValid() && reply.value();
+}
+
+void DaemonClient::closeSerialPort(const QString& portName)
+{
+    if (m_interface && m_interface->isValid()) {
+        m_interface->call("closeSerialPort", portName);
+    }
+}
+
+QStringList DaemonClient::getOpenedSerialPorts() const
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return QStringList();
+    }
+    
+    QDBusReply<QString> reply = m_interface->call("getOpenedSerialPorts");
+    if (reply.isValid()) {
+        QJsonDocument doc = QJsonDocument::fromJson(reply.value().toUtf8());
+        QJsonObject obj = doc.object();
+        QJsonArray ports = obj["ports"].toArray();
+        
+        QStringList result;
+        for (const QJsonValue& value : ports) {
+            result.append(value.toString());
+        }
+        return result;
+    }
+    
+    return QStringList();
+}
+
+bool DaemonClient::writeSerialData(const QString& portName, const QByteArray& data)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return false;
+    }
+    
+    // Base64 编码
+    QString base64Data = QString::fromUtf8(data.toBase64());
+    QDBusReply<bool> reply = m_interface->call("writeSerialData", portName, base64Data);
+    return reply.isValid() && reply.value();
+}
+
+bool DaemonClient::openCanDevice(int comPort, int baudRate)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return false;
+    }
+    
+    QDBusReply<bool> reply = m_interface->call("openCanDevice", comPort, baudRate);
+    return reply.isValid() && reply.value();
+}
+
+void DaemonClient::closeCanDevice(const QString& deviceName)
+{
+    if (m_interface && m_interface->isValid()) {
+        m_interface->call("closeCanDevice", deviceName);
+    }
+}
+
+QStringList DaemonClient::getOpenedCanDevices() const
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return QStringList();
+    }
+    
+    QDBusReply<QString> reply = m_interface->call("getOpenedCanDevices");
+    if (reply.isValid()) {
+        QJsonDocument doc = QJsonDocument::fromJson(reply.value().toUtf8());
+        QJsonObject obj = doc.object();
+        QJsonArray devices = obj["devices"].toArray();
+        
+        QStringList result;
+        for (const QJsonValue& value : devices) {
+            result.append(value.toString());
+        }
+        return result;
+    }
+    
+    return QStringList();
+}
+
+bool DaemonClient::sendCanData(const QString& deviceName, int canPort, unsigned int canId,
+                               const QByteArray& data, bool isExtendedId)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        return false;
+    }
+    
+    // Base64 编码
+    QString base64Data = QString::fromUtf8(data.toBase64());
+    QDBusReply<bool> reply = m_interface->call("sendCanData", deviceName, canPort,
+                                                canId, base64Data, isExtendedId);
+    return reply.isValid() && reply.value();
+}
+
+void DaemonClient::onSerialDataReceived(const QString& portName, const QString& base64Data)
+{
+    QByteArray data = QByteArray::fromBase64(base64Data.toUtf8());
+    emit serialDataReceived(portName, data);
+}
+
+void DaemonClient::onSerialPortStatusChanged(const QString& portName, bool isOpen)
+{
+    emit serialPortStatusChanged(portName, isOpen);
+}
+
+void DaemonClient::onCanDataReceived(const QString& deviceName, int canPort, unsigned int canId,
+                                      const QString& base64Data, bool isExtendedId)
+{
+    QByteArray data = QByteArray::fromBase64(base64Data.toUtf8());
+    emit canDataReceived(deviceName, canPort, canId, data, isExtendedId);
+}
+
+void DaemonClient::onCanDeviceStatusChanged(const QString& deviceName, bool isOpen)
+{
+    emit canDeviceStatusChanged(deviceName, isOpen);
+}
+
+void DaemonClient::setupTimer()
+{
+    m_updateTimer = new QTimer(this);
+    connect(m_updateTimer, &QTimer::timeout, this, &DaemonClient::updateStatus);
+    m_updateTimer->start(2000); // 每2秒更新一次状态
+}
+
+bool DaemonClient::startDaemon()
+{
+    // 如果守护进程已经在运行,不重复启动
+    if (m_daemonProcess && m_daemonProcess->state() == QProcess::Running) {
+        LOG_INFO() << "Daemon process is already running";
+        return true;
+    }
+
+    QString daemonPath = findDaemonExecutable();
+    if (daemonPath.isEmpty()) {
+        LOG_WARNING() << "Cannot find daemon executable";
+        return false;
+    }
+
+    LOG_INFO() << "Starting daemon:" << daemonPath;
+
+    // 创建进程对象(不设置父对象,让守护进程独立运行)
+    if (!m_daemonProcess) {
+        m_daemonProcess = new QProcess(this);
+        // 设置进程分离,让守护进程独立运行
+        m_daemonProcess->setProcessChannelMode(QProcess::ForwardedChannels);
+    }
+
+    // 启动守护进程
+    m_daemonProcess->start(daemonPath, QStringList());
+    
+    if (!m_daemonProcess->waitForStarted(3000)) {
+        LOG_WARNING() << "Failed to start daemon:" << m_daemonProcess->errorString();
+        return false;
+    }
+
+    LOG_INFO() << "Daemon process started, PID:" << m_daemonProcess->processId();
+    return true;
+}
+
+QString DaemonClient::findDaemonExecutable() const
+{
+    // 方法1: 检查与主程序同一目录
+    QString appDir = QCoreApplication::applicationDirPath();
+    QString daemonPath = appDir + "/soft_bus_daemon";
+    if (QFileInfo::exists(daemonPath)) {
+        return QDir(daemonPath).absolutePath();
+    }
+
+    // 方法2: 检查构建目录(开发环境)- 尝试多个可能的构建目录
+    QStringList buildDirs;
+    buildDirs << appDir + "/../build/Desktop_Qt_6_9_2-Debug/soft_bus_daemon"
+              << appDir + "/../build/soft_bus_daemon"
+              << QDir::currentPath() + "/build/Desktop_Qt_6_9_2-Debug/soft_bus_daemon"
+              << QDir::currentPath() + "/build/soft_bus_daemon";
+    
+    for (const QString &buildPath : buildDirs) {
+        QString absPath = QDir(buildPath).absolutePath();
+        if (QFileInfo::exists(absPath)) {
+            return absPath;
+        }
+    }
+
+    // 方法3: 使用 which 命令(Linux)
+    QProcess whichProcess;
+    whichProcess.start("which", QStringList() << "soft_bus_daemon");
+    if (whichProcess.waitForFinished(1000)) {
+        QString result = QString::fromUtf8(whichProcess.readAllStandardOutput()).trimmed();
+        if (!result.isEmpty() && QFileInfo::exists(result)) {
+            return result;
+        }
+    }
+
+    // 方法4: 使用系统路径查找
+    QStringList searchPaths;
+    searchPaths << "/usr/bin"
+                << "/usr/local/bin";
+    
+    // 添加标准应用程序路径
+    QStringList appPaths = QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation);
+    for (const QString &appPath : appPaths) {
+        searchPaths << appPath;
+    }
+    
+    for (const QString &path : searchPaths) {
+        QString fullPath = path + "/soft_bus_daemon";
+        if (QFileInfo::exists(fullPath)) {
+            return fullPath;
+        }
+    }
+
+    LOG_WARNING() << "Daemon executable not found. Searched in:" << appDir << "and build directories";
+    return QString();
+}
+

+ 203 - 0
src/daemon/daemon_client.h

@@ -0,0 +1,203 @@
+/**
+ * @file daemon_client.h
+ * @brief D-Bus 客户端 - Qt GUI 用于连接守护进程
+ */
+
+#ifndef DAEMON_CLIENT_H
+#define DAEMON_CLIENT_H
+
+#include <QObject>
+#include <QString>
+#include <QList>
+#include "soft_bus_core/soft_bus_core.h"
+
+class QDBusInterface;
+class QTimer;
+class QProcess;
+
+/**
+ * @brief D-Bus 客户端 - 用于 Qt GUI 连接守护进程
+ */
+class DaemonClient : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit DaemonClient(QObject* parent = nullptr);
+    ~DaemonClient();
+
+    /**
+     * @brief 连接到守护进程,如果未运行则自动启动
+     * @return true 如果连接成功
+     */
+    bool connectToDaemon();
+
+    /**
+     * @brief 启动守护进程
+     * @return true 如果启动成功
+     */
+    bool startDaemon();
+
+    /**
+     * @brief 检查守护进程是否运行
+     */
+    bool isDaemonRunning() const;
+
+    /**
+     * @brief 获取守护进程状态
+     */
+    QString getStatus() const;
+
+    /**
+     * @brief 获取负载信息
+     */
+    QString getLoadInfo() const;
+
+    /**
+     * @brief 获取设备数量
+     */
+    int getDeviceCount() const;
+
+    /**
+     * @brief 获取所有设备列表
+     * @return 设备信息列表
+     */
+    QList<DeviceInfo> getAllDevices() const;
+
+    /**
+     * @brief 获取守护进程的进程ID
+     * @return 进程ID,如果无法获取则返回0
+     */
+    qint64 getPid() const;
+
+    // ========== 硬件资源操作接口 ==========
+    /**
+     * @brief 打开串口(通过守护进程)
+     * @param portName 串口名称
+     * @param baudRate 波特率
+     * @param dataBits 数据位(默认8)
+     * @param parity 校验位(默认0=NoParity)
+     * @param stopBits 停止位(默认1)
+     * @param flowControl 流控制(默认0=NoFlowControl)
+     * @return 成功返回 true
+     */
+    bool openSerialPort(const QString& portName, int baudRate, int dataBits = 8,
+                        int parity = 0, int stopBits = 1, int flowControl = 0);
+    
+    /**
+     * @brief 关闭串口(通过守护进程)
+     * @param portName 串口名称
+     */
+    void closeSerialPort(const QString& portName);
+    
+    /**
+     * @brief 获取已打开的串口列表
+     * @return 串口名称列表
+     */
+    QStringList getOpenedSerialPorts() const;
+    
+    /**
+     * @brief 发送数据到串口(通过守护进程)
+     * @param portName 串口名称
+     * @param data 数据
+     * @return 成功返回 true
+     */
+    bool writeSerialData(const QString& portName, const QByteArray& data);
+
+    /**
+     * @brief 打开CAN设备(通过守护进程)
+     * @param comPort CAN端口号
+     * @param baudRate 波特率
+     * @return 成功返回 true
+     */
+    bool openCanDevice(int comPort, int baudRate);
+    
+    /**
+     * @brief 关闭CAN设备(通过守护进程)
+     * @param deviceName 设备名称(如 "CAN_0")
+     */
+    void closeCanDevice(const QString& deviceName);
+    
+    /**
+     * @brief 获取已打开的CAN设备列表
+     * @return 设备名称列表
+     */
+    QStringList getOpenedCanDevices() const;
+    
+    /**
+     * @brief 发送CAN数据(通过守护进程)
+     * @param deviceName 设备名称
+     * @param canPort CAN端口(1或2)
+     * @param canId CAN ID
+     * @param data 数据(最多8字节)
+     * @param isExtendedId 是否为扩展ID
+     * @return 成功返回 true
+     */
+    bool sendCanData(const QString& deviceName, int canPort, unsigned int canId,
+                     const QByteArray& data, bool isExtendedId = true);
+
+signals:
+    /**
+     * @brief 守护进程状态变化时发出
+     */
+    void daemonStatusChanged(bool running, const QString& status);
+
+    /**
+     * @brief 负载信息更新时发出
+     */
+    void loadInfoUpdated(const QString& loadInfo);
+
+    /**
+     * @brief 串口数据接收时发出
+     * @param portName 串口名称
+     * @param data 数据
+     */
+    void serialDataReceived(const QString& portName, const QByteArray& data);
+    
+    /**
+     * @brief 串口状态变化时发出
+     * @param portName 串口名称
+     * @param isOpen 是否打开
+     */
+    void serialPortStatusChanged(const QString& portName, bool isOpen);
+
+    /**
+     * @brief CAN数据接收时发出
+     * @param deviceName 设备名称
+     * @param canPort CAN端口(1或2)
+     * @param canId CAN ID
+     * @param data 接收的数据
+     * @param isExtendedId 是否为扩展ID
+     */
+    void canDataReceived(const QString& deviceName, int canPort, unsigned int canId,
+                        const QByteArray& data, bool isExtendedId);
+    
+    /**
+     * @brief CAN设备状态变化时发出
+     * @param deviceName 设备名称
+     * @param isOpen 是否打开
+     */
+    void canDeviceStatusChanged(const QString& deviceName, bool isOpen);
+
+private slots:
+    void updateStatus();
+    void onDaemonStatusChanged(const QString& status);
+    void onLoadInfoUpdated(const QString& loadInfo);
+    void onSerialDataReceived(const QString& portName, const QString& base64Data);
+    void onSerialPortStatusChanged(const QString& portName, bool isOpen);
+    void onCanDataReceived(const QString& deviceName, int canPort, unsigned int canId,
+                           const QString& base64Data, bool isExtendedId);
+    void onCanDeviceStatusChanged(const QString& deviceName, bool isOpen);
+
+private:
+    QDBusInterface* m_interface;
+    QTimer* m_updateTimer;
+    QProcess* m_daemonProcess;
+    bool m_connected;
+    
+    void setupTimer();
+    QString findDaemonExecutable() const;
+};
+
+#endif // DAEMON_CLIENT_H
+

+ 102 - 0
src/daemon/daemon_connection_dialog.cpp

@@ -0,0 +1,102 @@
+/**
+ * @file daemon_connection_dialog.cpp
+ * @brief 守护进程连接失败对话框实现
+ */
+
+#include "daemon_connection_dialog.h"
+#include <QLabel>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QMessageBox>
+#include <QIcon>
+
+DaemonConnectionDialog::DaemonConnectionDialog(QWidget* parent)
+    : QDialog(parent)
+    , m_messageLabel(nullptr)
+    , m_detailLabel(nullptr)
+    , m_switchButton(nullptr)
+    , m_retryButton(nullptr)
+    , m_cancelButton(nullptr)
+    , m_switchToLocal(false)
+{
+    setWindowTitle(tr("无法连接到守护进程"));
+    setWindowIcon(QIcon(":/qrc/icons/ads_icon.svg"));
+    setModal(true);
+    resize(450, 200);
+
+    // 创建主布局
+    QVBoxLayout* mainLayout = new QVBoxLayout(this);
+
+    // 消息标签
+    m_messageLabel = new QLabel(this);
+    m_messageLabel->setWordWrap(true);
+    m_messageLabel->setText(tr("无法连接到守护进程服务。"));
+    QFont font = m_messageLabel->font();
+    font.setPointSize(10);
+    m_messageLabel->setFont(font);
+    mainLayout->addWidget(m_messageLabel);
+
+    // 详细信息标签
+    m_detailLabel = new QLabel(this);
+    m_detailLabel->setWordWrap(true);
+    m_detailLabel->setText(tr("守护进程可能未运行或无法访问。\n"
+                              "您可以选择切换到本地模式,或重试连接。"));
+    m_detailLabel->setStyleSheet("color: #666;");
+    mainLayout->addWidget(m_detailLabel);
+
+    mainLayout->addStretch();
+
+    // 按钮布局
+    QHBoxLayout* buttonLayout = new QHBoxLayout();
+    buttonLayout->addStretch();
+
+    // 切换到本地模式按钮
+    m_switchButton = new QPushButton(tr("切换到本地模式"), this);
+    m_switchButton->setDefault(true);
+    connect(m_switchButton, &QPushButton::clicked, this, &DaemonConnectionDialog::onSwitchToLocal);
+    buttonLayout->addWidget(m_switchButton);
+
+    // 重试按钮
+    m_retryButton = new QPushButton(tr("重试"), this);
+    connect(m_retryButton, &QPushButton::clicked, this, &DaemonConnectionDialog::onRetry);
+    buttonLayout->addWidget(m_retryButton);
+
+    // 取消按钮
+    m_cancelButton = new QPushButton(tr("取消"), this);
+    connect(m_cancelButton, &QPushButton::clicked, this, &QDialog::reject);
+    buttonLayout->addWidget(m_cancelButton);
+
+    mainLayout->addLayout(buttonLayout);
+
+    setLayout(mainLayout);
+}
+
+DaemonConnectionDialog::~DaemonConnectionDialog()
+{
+}
+
+void DaemonConnectionDialog::setErrorMessage(const QString& message)
+{
+    if (m_messageLabel) {
+        m_messageLabel->setText(tr("无法连接到守护进程服务。\n%1").arg(message));
+    }
+}
+
+bool DaemonConnectionDialog::switchToLocalMode() const
+{
+    return m_switchToLocal;
+}
+
+void DaemonConnectionDialog::onSwitchToLocal()
+{
+    m_switchToLocal = true;
+    accept();
+}
+
+void DaemonConnectionDialog::onRetry()
+{
+    m_switchToLocal = false;
+    accept();
+}
+

+ 50 - 0
src/daemon/daemon_connection_dialog.h

@@ -0,0 +1,50 @@
+/**
+ * @file daemon_connection_dialog.h
+ * @brief 守护进程连接失败对话框
+ */
+
+#ifndef DAEMON_CONNECTION_DIALOG_H
+#define DAEMON_CONNECTION_DIALOG_H
+
+#include <QDialog>
+#include <QString>
+
+class QLabel;
+class QPushButton;
+
+/**
+ * @brief 守护进程连接失败时询问是否切换到本地模式的对话框
+ */
+class DaemonConnectionDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit DaemonConnectionDialog(QWidget* parent = nullptr);
+    ~DaemonConnectionDialog();
+
+    /**
+     * @brief 设置错误消息
+     */
+    void setErrorMessage(const QString& message);
+
+    /**
+     * @brief 用户是否选择切换到本地模式
+     */
+    bool switchToLocalMode() const;
+
+private slots:
+    void onSwitchToLocal();
+    void onRetry();
+
+private:
+    QLabel* m_messageLabel;
+    QLabel* m_detailLabel;
+    QPushButton* m_switchButton;
+    QPushButton* m_retryButton;
+    QPushButton* m_cancelButton;
+    bool m_switchToLocal;
+};
+
+#endif // DAEMON_CONNECTION_DIALOG_H
+

+ 105 - 0
src/daemon/daemon_main.cpp

@@ -0,0 +1,105 @@
+/**
+ * @file daemon_main.cpp
+ * @brief 软总线核心守护进程主程序
+ * 
+ * 功能:
+ * - 独立运行的核心服务进程(不依赖 Qt GUI)
+ * - 通过 D-Bus 提供状态查询和负载监控接口
+ * - 管理设备总线和消息路由
+ */
+
+#include "daemon_service.h"
+#include "core/CoreService.h"
+#include "api/SoftBusAPI.h"
+#include <QCoreApplication>
+#include <QDBusConnection>
+#include <QDBusError>
+#include <QDebug>
+#include <QLoggingCategory>
+#include <QDateTime>
+#include <signal.h>
+#include <unistd.h>
+
+Q_LOGGING_CATEGORY(daemon, "soft_bus.daemon")
+
+// 全局服务实例,用于信号处理
+DaemonService* g_daemonService = nullptr;
+
+// 信号处理函数
+void signalHandler(int signal) {
+    qCInfo(daemon) << "Received signal" << signal;
+    if (g_daemonService) {
+        g_daemonService->shutdown();
+    }
+    QCoreApplication::quit();
+}
+
+int main(int argc, char *argv[])
+{
+    QCoreApplication app(argc, argv);
+    app.setApplicationName("soft_bus_daemon");
+    app.setApplicationVersion("1.0.0");
+    app.setOrganizationName("soft_bus");
+
+    qCInfo(daemon) << "Starting Soft Bus Daemon...";
+
+    // 注册信号处理
+    signal(SIGINT, signalHandler);
+    signal(SIGTERM, signalHandler);
+
+    // 初始化核心服务
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->initialize()) {
+        qCCritical(daemon) << "Failed to initialize CoreService";
+        return 1;
+    }
+    
+    // 初始化 SoftBusAPI(用于硬件资源管理)
+    // 注意:守护进程应该使用本地模式(因为它本身就是硬件操作者)
+    SoftBusAPI* api = SoftBusAPI::instance();
+    api->setUseDaemonMode(false);  // 守护进程使用本地模式
+    if (!api->initialize()) {
+        qCCritical(daemon) << "Failed to initialize SoftBusAPI";
+        return 1;
+    }
+    
+    // 启动设备发现(包括串口和CAN)
+    api->startDeviceDiscovery(5000);  // 每5秒扫描一次
+
+    // 创建 D-Bus 服务
+    g_daemonService = new DaemonService(coreService, &app);
+    
+    // 使用系统 D-Bus(系统级服务)
+    QDBusConnection connection = QDBusConnection::systemBus();
+    if (!connection.isConnected()) {
+        qCCritical(daemon) << "Cannot connect to system D-Bus";
+        return 1;
+    }
+
+    // 注册 D-Bus 服务
+    if (!connection.registerService("com.softbus.Daemon")) {
+        qCCritical(daemon) << "Failed to register D-Bus service:" << connection.lastError().message();
+        return 1;
+    }
+
+    // 注册 D-Bus 对象
+    if (!connection.registerObject("/com/softbus/Daemon", g_daemonService,
+                                    QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
+        qCCritical(daemon) << "Failed to register D-Bus object:" << connection.lastError().message();
+        return 1;
+    }
+
+    qCInfo(daemon) << "Soft Bus Daemon started successfully";
+    qCInfo(daemon) << "D-Bus service: com.softbus.Daemon";
+    qCInfo(daemon) << "D-Bus object: /com/softbus/Daemon";
+
+    // 运行事件循环
+    int ret = app.exec();
+
+    // 清理
+    qCInfo(daemon) << "Shutting down Soft Bus Daemon...";
+    coreService->shutdown();
+
+    return ret;
+}
+

+ 229 - 0
src/daemon/daemon_message_flow_widget.cpp

@@ -0,0 +1,229 @@
+/**
+ * @file daemon_message_flow_widget.cpp
+ * @brief 守护进程信息流列表显示组件实现
+ */
+
+#include "daemon_message_flow_widget.h"
+#include "daemon_client.h"
+#include <QVBoxLayout>
+#include <QHeaderView>
+#include <QTableWidgetItem>
+#include <QBrush>
+#include <QColor>
+#include <QJsonDocument>
+#include <QJsonObject>
+
+DaemonMessageFlowWidget::DaemonMessageFlowWidget(QWidget *parent)
+    : QWidget(parent)
+    , m_tableWidget(nullptr)
+    , m_daemonClient(nullptr)
+    , m_clientIdCounter(1)
+    , m_taskIdCounter(1)
+    , m_connectionTaskId(0)
+    , m_deviceListTaskId(0)
+    , m_loadInfoTaskId(0)
+{
+    setupUI();
+}
+
+DaemonMessageFlowWidget::~DaemonMessageFlowWidget()
+{
+}
+
+void DaemonMessageFlowWidget::setupUI()
+{
+    QVBoxLayout* layout = new QVBoxLayout(this);
+    layout->setContentsMargins(0, 0, 0, 0);
+    
+    // 创建表格
+    m_tableWidget = new QTableWidget(this);
+    m_tableWidget->setColumnCount(4);
+    m_tableWidget->setHorizontalHeaderLabels(QStringList() << "操作" << "目标" << "时间" << "状态");
+    m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
+    m_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
+    m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    m_tableWidget->setAlternatingRowColors(true);
+    m_tableWidget->setShowGrid(true);
+    
+    // 设置列宽
+    m_tableWidget->horizontalHeader()->setStretchLastSection(true);
+    m_tableWidget->setColumnWidth(0, 150);  // 操作
+    m_tableWidget->setColumnWidth(1, 100);   // 目标
+    m_tableWidget->setColumnWidth(2, 150);   // 时间
+    
+    layout->addWidget(m_tableWidget);
+}
+
+void DaemonMessageFlowWidget::setDaemonClient(DaemonClient* client)
+{
+    if (m_daemonClient == client) {
+        return;
+    }
+    
+    // 断开旧的连接
+    if (m_daemonClient) {
+        disconnect(m_daemonClient, nullptr, this, nullptr);
+    }
+    
+    m_daemonClient = client;
+    
+    // 连接新的信号
+    if (m_daemonClient) {
+        connect(m_daemonClient, &DaemonClient::daemonStatusChanged,
+                this, &DaemonMessageFlowWidget::onDaemonStatusChanged);
+        connect(m_daemonClient, &DaemonClient::loadInfoUpdated,
+                this, &DaemonMessageFlowWidget::onLoadInfoUpdated);
+        
+        // 添加初始连接信息
+        m_connectionTaskId = addFlowItem("连接守护进程", QString("主界面%1").arg(m_clientIdCounter), "连接中");
+    }
+}
+
+int DaemonMessageFlowWidget::addFlowItem(const QString& operation, const QString& target, const QString& status)
+{
+    int taskId = m_taskIdCounter++;
+    MessageFlowItem item(taskId, operation, target, status);
+    m_flowItems.append(item);
+    
+    // 添加到表格
+    int row = m_tableWidget->rowCount();
+    m_tableWidget->insertRow(row);
+    
+    // 保存ID到行的映射
+    m_idToRowMap[taskId] = row;
+    
+    // 操作列
+    QTableWidgetItem* opItem = new QTableWidgetItem(operation);
+    opItem->setData(Qt::UserRole, taskId);  // 存储任务ID
+    m_tableWidget->setItem(row, 0, opItem);
+    
+    // 目标列
+    QTableWidgetItem* targetItem = new QTableWidgetItem(target);
+    m_tableWidget->setItem(row, 1, targetItem);
+    
+    // 时间列(固定显示,不刷新)
+    QTableWidgetItem* timeItem = new QTableWidgetItem(formatTime(item.timestamp));
+    m_tableWidget->setItem(row, 2, timeItem);
+    
+    // 状态列
+    QTableWidgetItem* statusItem = new QTableWidgetItem(status);
+    if (status == "进行中" || status == "连接中") {
+        statusItem->setForeground(QBrush(QColor(0, 150, 0)));  // 绿色表示进行中
+    } else if (status == "完成" || status == "已连接") {
+        statusItem->setForeground(QBrush(QColor(0, 0, 255)));   // 蓝色表示完成
+    } else if (status.contains("失败") || status.contains("错误") || status == "未连接") {
+        statusItem->setForeground(QBrush(QColor(255, 0, 0)));  // 红色表示失败
+    }
+    m_tableWidget->setItem(row, 3, statusItem);
+    
+    // 滚动到底部
+    m_tableWidget->scrollToBottom();
+    
+    return taskId;
+}
+
+void DaemonMessageFlowWidget::updateFlowItemStatus(int taskId, const QString& status)
+{
+    // 通过ID查找对应的行
+    if (!m_idToRowMap.contains(taskId)) {
+        return;
+    }
+    
+    int row = m_idToRowMap[taskId];
+    if (row < 0 || row >= m_flowItems.size() || row >= m_tableWidget->rowCount()) {
+        return;
+    }
+    
+    // 更新条目状态
+    if (m_flowItems[row].id == taskId) {
+        m_flowItems[row].status = status;
+        
+        // 更新表格中的状态
+        QTableWidgetItem* statusItem = m_tableWidget->item(row, 3);
+        if (statusItem) {
+            statusItem->setText(status);
+            if (status == "进行中" || status == "连接中") {
+                statusItem->setForeground(QBrush(QColor(0, 150, 0)));
+            } else if (status == "完成" || status == "已连接") {
+                statusItem->setForeground(QBrush(QColor(0, 0, 255)));
+            } else if (status.contains("失败") || status.contains("错误") || status == "未连接") {
+                statusItem->setForeground(QBrush(QColor(255, 0, 0)));
+            }
+        }
+    }
+}
+
+void DaemonMessageFlowWidget::clearFlowItems()
+{
+    m_flowItems.clear();
+    m_idToRowMap.clear();
+    m_tableWidget->setRowCount(0);
+}
+
+
+QString DaemonMessageFlowWidget::formatTime(const QDateTime& timestamp) const
+{
+    // 固定显示时间,不刷新
+    return timestamp.toString("hh:mm:ss");
+}
+
+void DaemonMessageFlowWidget::onDaemonStatusChanged(bool running, const QString& statusJson)
+{
+    QString target = QString("主界面%1").arg(m_clientIdCounter);
+    
+    if (running) {
+        updateFlowItemStatus(m_connectionTaskId, "已连接");
+        
+        // 解析状态JSON,添加设备信息更新
+        if (!statusJson.isEmpty()) {
+            QJsonDocument doc = QJsonDocument::fromJson(statusJson.toUtf8());
+            if (doc.isObject()) {
+                QJsonObject obj = doc.object();
+                int deviceCount = obj["deviceCount"].toInt(0);
+                int onlineCount = obj["onlineDeviceCount"].toInt(0);
+                
+                QString status = QString("设备: %1/%2").arg(onlineCount).arg(deviceCount);
+                if (m_deviceListTaskId == 0) {
+                    m_deviceListTaskId = addFlowItem("更新设备列表", target, status);
+                } else {
+                    updateFlowItemStatus(m_deviceListTaskId, status);
+                }
+            }
+        }
+    } else {
+        updateFlowItemStatus(m_connectionTaskId, "未连接");
+    }
+}
+
+void DaemonMessageFlowWidget::onLoadInfoUpdated(const QString& loadInfoJson)
+{
+    if (loadInfoJson.isEmpty()) {
+        return;
+    }
+    
+    QJsonDocument doc = QJsonDocument::fromJson(loadInfoJson.toUtf8());
+    if (!doc.isObject()) {
+        return;
+    }
+    
+    QJsonObject obj = doc.object();
+    double messageRate = obj["messageRate"].toDouble(0.0);
+    qint64 totalMessages = obj["totalMessagesProcessed"].toVariant().toLongLong();
+    if (totalMessages == 0) {
+        // 尝试使用不同的键名
+        totalMessages = obj["totalMessages"].toVariant().toLongLong();
+    }
+    
+    QString target = QString("主界面%1").arg(m_clientIdCounter);
+    QString status = QString("消息速率: %1 msg/s | 总计: %2")
+                    .arg(messageRate, 0, 'f', 1)
+                    .arg(totalMessages);
+    
+    // 更新负载信息(如果存在)
+    if (m_loadInfoTaskId == 0) {
+        m_loadInfoTaskId = addFlowItem("更新负载信息", target, status);
+    } else {
+        updateFlowItemStatus(m_loadInfoTaskId, status);
+    }
+}
+

+ 99 - 0
src/daemon/daemon_message_flow_widget.h

@@ -0,0 +1,99 @@
+/**
+ * @file daemon_message_flow_widget.h
+ * @brief 守护进程信息流列表显示组件
+ * 
+ * 显示守护进程与主进程之间的通信记录,包括:
+ * - 操作类型(如"更新设备列表")
+ * - 目标(如"主界面1")
+ * - 时间
+ * - 状态(持续刷新)
+ */
+
+#ifndef DAEMON_MESSAGE_FLOW_WIDGET_H
+#define DAEMON_MESSAGE_FLOW_WIDGET_H
+
+#include <QWidget>
+#include <QTableWidget>
+#include <QDateTime>
+#include <QMap>
+
+class DaemonClient;
+
+/**
+ * @brief 信息流条目结构
+ */
+struct MessageFlowItem {
+    int id;                  // 任务ID(唯一标识)
+    QString operation;      // 操作类型(如"更新设备列表")
+    QString target;          // 目标(如"主界面1")
+    QDateTime timestamp;     // 时间戳
+    QString status;          // 状态(如"进行中"、"完成"、"失败")
+    
+    MessageFlowItem()
+        : id(-1) {}
+    
+    MessageFlowItem(int taskId, const QString& op, const QString& tgt, const QString& st = "进行中")
+        : id(taskId)
+        , operation(op)
+        , target(tgt)
+        , timestamp(QDateTime::currentDateTime())
+        , status(st)
+    {}
+};
+
+/**
+ * @brief 守护进程信息流列表显示组件
+ */
+class DaemonMessageFlowWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit DaemonMessageFlowWidget(QWidget *parent = nullptr);
+    ~DaemonMessageFlowWidget();
+
+    /**
+     * @brief 设置守护进程客户端
+     */
+    void setDaemonClient(DaemonClient* client);
+
+    /**
+     * @brief 添加信息流条目
+     * @return 返回任务ID,用于后续更新
+     */
+    int addFlowItem(const QString& operation, const QString& target, const QString& status = "进行中");
+
+    /**
+     * @brief 更新信息流条目的状态(通过ID)
+     */
+    void updateFlowItemStatus(int taskId, const QString& status);
+
+    /**
+     * @brief 清除所有信息流条目
+     */
+    void clearFlowItems();
+
+private slots:
+    void onDaemonStatusChanged(bool running, const QString& statusJson);
+    void onLoadInfoUpdated(const QString& loadInfoJson);
+
+private:
+    void setupUI();
+    QString formatTime(const QDateTime& timestamp) const;
+
+private:
+    QTableWidget* m_tableWidget;
+    DaemonClient* m_daemonClient;
+    QList<MessageFlowItem> m_flowItems;
+    QMap<int, int> m_idToRowMap;  // 任务ID到表格行的映射
+    int m_clientIdCounter;  // 客户端ID计数器(用于区分多个主界面实例)
+    int m_taskIdCounter;   // 任务ID计数器
+    
+    // 特定任务的ID
+    int m_connectionTaskId;  // 连接任务ID
+    int m_deviceListTaskId;  // 设备列表任务ID
+    int m_loadInfoTaskId;    // 负载信息任务ID
+};
+
+#endif // DAEMON_MESSAGE_FLOW_WIDGET_H
+

+ 389 - 0
src/daemon/daemon_service.cpp

@@ -0,0 +1,389 @@
+/**
+ * @file daemon_service.cpp
+ * @brief D-Bus 服务实现
+ */
+
+#include "daemon_service.h"
+#include "core/CoreService.h"
+#include "soft_bus_core/soft_bus_core.h"
+#include "api/SoftBusAPI.h"
+#include "serial_manager/serial_manager.h"
+#include "can_manager/can_manager.h"
+#include <QCoreApplication>
+#include <QDBusConnection>
+#include <QDateTime>
+#include "utils/logging.h"
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QTimer>
+#include <QSerialPortInfo>
+#include <QSerialPort>
+#include <QByteArray>
+#include <unistd.h>
+
+DaemonService::DaemonService(CoreService* coreService, QObject* parent)
+    : QObject(parent)
+    , m_coreService(coreService)
+    , m_loadInfoTimer(nullptr)
+    , m_totalMessagesProcessed(0)
+    , m_lastMessageCount(0)
+{
+    initializeLoadInfo();
+    
+    // 定时更新负载信息(每5秒)
+    m_loadInfoTimer = new QTimer(this);
+    connect(m_loadInfoTimer, &QTimer::timeout, this, &DaemonService::updateLoadInfo);
+    m_loadInfoTimer->start(5000);
+    
+    updateLoadInfo(); // 立即更新一次
+    
+    // 延迟连接硬件资源信号(确保 SoftBusAPI 已初始化)
+    QTimer::singleShot(100, this, [this]() {
+        SoftBusAPI* api = SoftBusAPI::instance();
+        if (api && api->isInitialized()) {
+            // 连接串口信号
+            connect(api, &SoftBusAPI::serialDataReceived,
+                    this, [this](const QString& portName, const QByteArray& data) {
+                        QString base64Data = QString::fromUtf8(data.toBase64());
+                        emit serialDataReceived(portName, base64Data);
+                    });
+            
+            // 连接CAN信号
+            connect(api, &SoftBusAPI::canDataReceived,
+                    this, [this](const QString& deviceName, int canPort, unsigned int canId,
+                                 const QByteArray& data, bool isExtendedId) {
+                        QString base64Data = QString::fromUtf8(data.toBase64());
+                        emit canDataReceived(deviceName, canPort, canId, base64Data, isExtendedId);
+                    });
+        }
+    });
+}
+
+DaemonService::~DaemonService()
+{
+    if (m_loadInfoTimer) {
+        m_loadInfoTimer->stop();
+    }
+}
+
+bool DaemonService::isRunning() const
+{
+    return m_coreService && m_coreService->isInitialized();
+}
+
+QString DaemonService::getStatus() const
+{
+    QJsonObject status;
+    
+    if (!m_coreService || !m_coreService->isInitialized()) {
+        status["running"] = false;
+        status["status"] = "stopped";
+        return QJsonDocument(status).toJson(QJsonDocument::Compact);
+    }
+    
+    status["running"] = true;
+    status["status"] = "running";
+    status["initialized"] = m_coreService->isInitialized();
+    
+    DeviceBusCore* busCore = m_coreService->getDeviceBusCore();
+    if (busCore) {
+        QList<DeviceInfo> devices = busCore->getAllDevices();
+        status["deviceCount"] = devices.size();
+        
+        int onlineCount = 0;
+        for (const auto& device : devices) {
+            if (device.status == "online" && device.isActive) {
+                onlineCount++;
+            }
+        }
+        status["onlineDeviceCount"] = onlineCount;
+    }
+    
+    return QJsonDocument(status).toJson(QJsonDocument::Compact);
+}
+
+QString DaemonService::getLoadInfo() const
+{
+    QJsonObject loadInfo;
+    
+    if (!m_coreService || !m_coreService->isInitialized()) {
+        loadInfo["cpuUsage"] = 0.0;
+        loadInfo["memoryUsage"] = 0.0;
+        loadInfo["messageRate"] = 0.0;
+        return QJsonDocument(loadInfo).toJson(QJsonDocument::Compact);
+    }
+    
+    // 计算消息处理速率(每秒处理的消息数)
+    qint64 elapsed = m_lastUpdateTime.msecsTo(QDateTime::currentDateTime());
+    double messageRate = 0.0;
+    if (elapsed > 0) {
+        qint64 messageDelta = m_totalMessagesProcessed - m_lastMessageCount;
+        messageRate = (messageDelta * 1000.0) / elapsed;
+    }
+    
+    loadInfo["messageRate"] = messageRate;
+    loadInfo["totalMessagesProcessed"] = m_totalMessagesProcessed;
+    loadInfo["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
+    
+    // TODO: 添加实际的 CPU 和内存使用率监控
+    // 可以使用 QProcess 调用系统命令或使用系统 API
+    loadInfo["cpuUsage"] = 0.0;  // 占位符
+    loadInfo["memoryUsage"] = 0.0;  // 占位符
+    
+    return QJsonDocument(loadInfo).toJson(QJsonDocument::Compact);
+}
+
+int DaemonService::getDeviceCount() const
+{
+    if (!m_coreService || !m_coreService->isInitialized()) {
+        return 0;
+    }
+    
+    DeviceBusCore* busCore = m_coreService->getDeviceBusCore();
+    if (!busCore) {
+        return 0;
+    }
+    
+    return busCore->getAllDevices().size();
+}
+
+QString DaemonService::getAllDevices() const
+{
+    QJsonArray devicesArray;
+    
+    if (!m_coreService || !m_coreService->isInitialized()) {
+        QJsonObject result;
+        result["devices"] = devicesArray;
+        return QJsonDocument(result).toJson(QJsonDocument::Compact);
+    }
+    
+    DeviceBusCore* busCore = m_coreService->getDeviceBusCore();
+    if (!busCore) {
+        QJsonObject result;
+        result["devices"] = devicesArray;
+        return QJsonDocument(result).toJson(QJsonDocument::Compact);
+    }
+    
+    QList<DeviceInfo> devices = busCore->getAllDevices();
+    for (const DeviceInfo& device : devices) {
+        QJsonObject deviceObj;
+        deviceObj["id"] = device.id;
+        deviceObj["portname"] = device.portname;
+        deviceObj["name"] = device.name;
+        deviceObj["type"] = device.type;
+        deviceObj["address"] = device.address;
+        deviceObj["protocol"] = device.protocol;
+        deviceObj["protocol_detail"] = device.protocol_detail;
+        deviceObj["status"] = device.status;
+        deviceObj["isActive"] = device.isActive;
+        if (device.lastSeen.isValid()) {
+            deviceObj["lastSeen"] = device.lastSeen.toString(Qt::ISODate);
+        }
+        deviceObj["properties"] = device.properties;
+        devicesArray.append(deviceObj);
+    }
+    
+    QJsonObject result;
+    result["devices"] = devicesArray;
+    return QJsonDocument(result).toJson(QJsonDocument::Compact);
+}
+
+QString DaemonService::getMessageStats() const
+{
+    QJsonObject stats;
+    
+    if (!m_coreService || !m_coreService->isInitialized()) {
+        stats["totalMessages"] = 0;
+        stats["messageRate"] = 0.0;
+        return QJsonDocument(stats).toJson(QJsonDocument::Compact);
+    }
+    
+    qint64 elapsed = m_lastUpdateTime.msecsTo(QDateTime::currentDateTime());
+    double messageRate = 0.0;
+    if (elapsed > 0) {
+        qint64 messageDelta = m_totalMessagesProcessed - m_lastMessageCount;
+        messageRate = (messageDelta * 1000.0) / elapsed;
+    }
+    
+    stats["totalMessages"] = m_totalMessagesProcessed;
+    stats["messageRate"] = messageRate;
+    stats["lastUpdateTime"] = m_lastUpdateTime.toString(Qt::ISODate);
+    
+    return QJsonDocument(stats).toJson(QJsonDocument::Compact);
+}
+
+qint64 DaemonService::getPid() const
+{
+    return static_cast<qint64>(getpid());
+}
+
+void DaemonService::shutdown()
+{
+    LOG_DEBUG() << "DaemonService shutdown requested";
+    emit statusChanged("shutting_down");
+    
+    if (m_loadInfoTimer) {
+        m_loadInfoTimer->stop();
+    }
+    
+    QCoreApplication::quit();
+}
+
+void DaemonService::updateLoadInfo()
+{
+    // 更新消息计数(这里需要从实际的消息处理中获取)
+    // 目前使用占位符,实际应该从 DeviceBusCore 或消息处理模块获取
+    
+    // 发出负载信息更新信号
+    emit loadInfoUpdated(getLoadInfo());
+    
+    // 更新统计时间
+    m_lastMessageCount = m_totalMessagesProcessed;
+    m_lastUpdateTime = QDateTime::currentDateTime();
+}
+
+void DaemonService::initializeLoadInfo()
+{
+    m_totalMessagesProcessed = 0;
+    m_lastMessageCount = 0;
+    m_lastUpdateTime = QDateTime::currentDateTime();
+}
+
+// ========== 硬件资源管理接口实现 ==========
+bool DaemonService::openSerialPort(const QString& portName, int baudRate, int dataBits,
+                                    int parity, int stopBits, int flowControl)
+{
+    if (!m_coreService || !m_coreService->isInitialized()) {
+        return false;
+    }
+    
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+    
+    // 查找串口信息
+    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
+    for (const QSerialPortInfo& info : ports) {
+        if (info.portName() == portName) {
+            // 设置串口配置
+            SerialManager::SerialConfig config;
+            config.baudRate = static_cast<QSerialPort::BaudRate>(baudRate);
+            config.dataBits = static_cast<QSerialPort::DataBits>(dataBits);
+            config.parity = static_cast<QSerialPort::Parity>(parity);
+            config.stopBits = static_cast<QSerialPort::StopBits>(stopBits);
+            config.flowControl = static_cast<QSerialPort::FlowControl>(flowControl);
+            api->setSerialConfig(config);
+            
+            // 打开串口
+            bool success = api->openSerialPort(info);
+            if (success) {
+                emit serialPortStatusChanged(portName, true);
+            }
+            return success;
+        }
+    }
+    
+    LOG_WARNING() << "Serial port not found:" << portName;
+    return false;
+}
+
+void DaemonService::closeSerialPort(const QString& portName)
+{
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api && api->isInitialized()) {
+        api->closeSerialPort(portName);
+        emit serialPortStatusChanged(portName, false);
+    }
+}
+
+QString DaemonService::getOpenedSerialPorts() const
+{
+    QJsonArray ports;
+    
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api && api->isInitialized()) {
+        QStringList portList = api->getOpenedSerialPorts();
+        for (const QString& port : portList) {
+            ports.append(port);
+        }
+    }
+    
+    QJsonObject result;
+    result["ports"] = ports;
+    return QJsonDocument(result).toJson(QJsonDocument::Compact);
+}
+
+bool DaemonService::writeSerialData(const QString& portName, const QString& data)
+{
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        return false;
+    }
+    
+    // Base64 解码
+    QByteArray byteData = QByteArray::fromBase64(data.toUtf8());
+    return api->sendSerialData(portName, byteData);
+}
+
+bool DaemonService::openCanDevice(int comPort, int baudRate)
+{
+    if (!m_coreService || !m_coreService->isInitialized()) {
+        return false;
+    }
+    
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+    
+    bool success = api->openCanDevice(comPort);
+    if (success) {
+        QString deviceName = QString("CAN_%1").arg(comPort);
+        emit canDeviceStatusChanged(deviceName, true);
+    }
+    return success;
+}
+
+void DaemonService::closeCanDevice(const QString& deviceName)
+{
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api && api->isInitialized()) {
+        api->closeCanDevice(deviceName);
+        emit canDeviceStatusChanged(deviceName, false);
+    }
+}
+
+QString DaemonService::getOpenedCanDevices() const
+{
+    QJsonArray devices;
+    
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (api && api->isInitialized()) {
+        QStringList deviceList = api->getOpenedCanDevices();
+        for (const QString& device : deviceList) {
+            devices.append(device);
+        }
+    }
+    
+    QJsonObject result;
+    result["devices"] = devices;
+    return QJsonDocument(result).toJson(QJsonDocument::Compact);
+}
+
+bool DaemonService::sendCanData(const QString& deviceName, int canPort, unsigned int canId,
+                                 const QString& data, bool isExtendedId)
+{
+    SoftBusAPI* api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        return false;
+    }
+    
+    // Base64 解码
+    QByteArray byteData = QByteArray::fromBase64(data.toUtf8());
+    return api->sendCanData(deviceName, canPort, canId, byteData, isExtendedId);
+}
+

+ 204 - 0
src/daemon/daemon_service.h

@@ -0,0 +1,204 @@
+/**
+ * @file daemon_service.h
+ * @brief D-Bus 服务接口 - 提供核心服务状态和负载查询
+ */
+
+#ifndef DAEMON_SERVICE_H
+#define DAEMON_SERVICE_H
+
+#include <QObject>
+#include <QString>
+#include <QDateTime>
+
+class CoreService;
+class DeviceBusCore;
+class QTimer;
+
+/**
+ * @brief D-Bus 服务适配器 - 暴露核心服务接口
+ */
+class DaemonService : public QObject
+{
+    Q_OBJECT
+    Q_CLASSINFO("D-Bus Interface", "com.softbus.Daemon")
+
+public:
+    explicit DaemonService(CoreService* coreService, QObject* parent = nullptr);
+    ~DaemonService();
+
+public slots:
+    /**
+     * @brief 检查核心服务是否运行
+     * @return true 如果核心服务正在运行
+     */
+    bool isRunning() const;
+
+    /**
+     * @brief 获取核心服务状态信息
+     * @return JSON 格式的状态信息
+     */
+    QString getStatus() const;
+
+    /**
+     * @brief 获取核心服务负载情况
+     * @return JSON 格式的负载信息(CPU、内存、消息处理速率等)
+     */
+    QString getLoadInfo() const;
+
+    /**
+     * @brief 获取设备数量
+     * @return 已注册的设备数量
+     */
+    int getDeviceCount() const;
+
+    /**
+     * @brief 获取所有设备列表
+     * @return JSON 格式的设备列表
+     */
+    QString getAllDevices() const;
+
+    /**
+     * @brief 获取消息处理统计
+     * @return JSON 格式的统计信息
+     */
+    QString getMessageStats() const;
+
+    /**
+     * @brief 获取守护进程的进程ID
+     * @return 进程ID,如果无法获取则返回0
+     */
+    qint64 getPid() const;
+
+    /**
+     * @brief 关闭守护进程
+     */
+    void shutdown();
+
+    // ========== 硬件资源管理接口 ==========
+    /**
+     * @brief 打开串口
+     * @param portName 串口名称(如 "ttyUSB0")
+     * @param baudRate 波特率
+     * @param dataBits 数据位
+     * @param parity 校验位
+     * @param stopBits 停止位
+     * @param flowControl 流控制
+     * @return 成功返回 true
+     */
+    bool openSerialPort(const QString& portName, int baudRate, int dataBits = 8, 
+                        int parity = 0, int stopBits = 1, int flowControl = 0);
+    
+    /**
+     * @brief 关闭串口
+     * @param portName 串口名称
+     */
+    void closeSerialPort(const QString& portName);
+    
+    /**
+     * @brief 获取已打开的串口列表
+     * @return 串口名称列表(JSON 格式)
+     */
+    QString getOpenedSerialPorts() const;
+    
+    /**
+     * @brief 发送数据到串口
+     * @param portName 串口名称
+     * @param data 数据(Base64 编码)
+     * @return 成功返回 true
+     */
+    bool writeSerialData(const QString& portName, const QString& data);
+
+    /**
+     * @brief 打开CAN设备
+     * @param comPort CAN端口号
+     * @param baudRate 波特率
+     * @return 成功返回 true
+     */
+    bool openCanDevice(int comPort, int baudRate);
+    
+    /**
+     * @brief 关闭CAN设备
+     * @param deviceName 设备名称(如 "CAN_0")
+     */
+    void closeCanDevice(const QString& deviceName);
+    
+    /**
+     * @brief 获取已打开的CAN设备列表
+     * @return 设备名称列表(JSON 格式)
+     */
+    QString getOpenedCanDevices() const;
+    
+    /**
+     * @brief 发送CAN数据
+     * @param deviceName 设备名称
+     * @param canPort CAN端口(1或2)
+     * @param canId CAN ID
+     * @param data 数据(Base64 编码,最多8字节)
+     * @param isExtendedId 是否为扩展ID
+     * @return 成功返回 true
+     */
+    bool sendCanData(const QString& deviceName, int canPort, unsigned int canId,
+                     const QString& data, bool isExtendedId);
+
+signals:
+    /**
+     * @brief 核心服务状态变化时发出
+     * @param status 状态字符串
+     */
+    void statusChanged(const QString& status);
+
+    /**
+     * @brief 负载信息更新时发出
+     * @param loadInfo JSON 格式的负载信息
+     */
+    void loadInfoUpdated(const QString& loadInfo);
+
+    /**
+     * @brief 串口数据接收时发出
+     * @param portName 串口名称
+     * @param data 数据(Base64 编码)
+     */
+    void serialDataReceived(const QString& portName, const QString& data);
+    
+    /**
+     * @brief 串口状态变化时发出
+     * @param portName 串口名称
+     * @param isOpen 是否打开
+     */
+    void serialPortStatusChanged(const QString& portName, bool isOpen);
+
+    /**
+     * @brief CAN数据接收时发出
+     * @param deviceName 设备名称
+     * @param canPort CAN端口(1或2)
+     * @param canId CAN ID
+     * @param data 数据(Base64 编码)
+     * @param isExtendedId 是否为扩展ID
+     */
+    void canDataReceived(const QString& deviceName, int canPort, unsigned int canId,
+                        const QString& data, bool isExtendedId);
+    
+    /**
+     * @brief CAN设备状态变化时发出
+     * @param deviceName 设备名称
+     * @param isOpen 是否打开
+     */
+    void canDeviceStatusChanged(const QString& deviceName, bool isOpen);
+
+private slots:
+    void updateLoadInfo();
+
+private:
+    CoreService* m_coreService;
+    QTimer* m_loadInfoTimer;
+    
+    // 负载统计
+    qint64 m_totalMessagesProcessed;
+    qint64 m_lastMessageCount;
+    QDateTime m_lastUpdateTime;
+    
+    void initializeLoadInfo();
+};
+
+#endif // DAEMON_SERVICE_H
+

+ 230 - 0
src/device_config/device_log_dialog.cpp

@@ -0,0 +1,230 @@
+/**
+ * @file device_log_dialog.cpp
+ * @brief 设备日志对话框实现
+ */
+
+#include "device_log_dialog.h"
+#include <QLabel>
+#include <QTextEdit>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QDateTime>
+#include <QIcon>
+#include <QScrollBar>
+
+DeviceLogDialog::DeviceLogDialog(QWidget* parent)
+    : QDialog(parent)
+    , m_busCore(nullptr)
+    , m_deviceNameLabel(nullptr)
+    , m_deviceInfoLabel(nullptr)
+    , m_logTextEdit(nullptr)
+    , m_refreshButton(nullptr)
+    , m_closeButton(nullptr)
+    , m_mainLayout(nullptr)
+    , m_buttonLayout(nullptr)
+{
+    setWindowTitle(tr("设备日志"));
+    setWindowIcon(QIcon(":/qrc/icons/ads_icon.svg"));
+    setModal(false);  // 非模态对话框,可以同时打开多个
+    resize(600, 500);
+    setMinimumSize(500, 400);
+
+    // 创建主布局
+    m_mainLayout = new QVBoxLayout(this);
+
+    // 设备名称标签
+    m_deviceNameLabel = new QLabel(this);
+    QFont nameFont = m_deviceNameLabel->font();
+    nameFont.setPointSize(12);
+    nameFont.setBold(true);
+    m_deviceNameLabel->setFont(nameFont);
+    m_mainLayout->addWidget(m_deviceNameLabel);
+
+    // 设备信息标签
+    m_deviceInfoLabel = new QLabel(this);
+    m_deviceInfoLabel->setWordWrap(true);
+    m_deviceInfoLabel->setStyleSheet("color: #666; margin-bottom: 10px;");
+    m_mainLayout->addWidget(m_deviceInfoLabel);
+
+    // 日志文本编辑框
+    m_logTextEdit = new QTextEdit(this);
+    m_logTextEdit->setReadOnly(true);
+    m_logTextEdit->setFont(QFont("Consolas", 9));
+    m_logTextEdit->setStyleSheet(
+        "QTextEdit {"
+        "background-color: #f5f5f5;"
+        "color: #333333;"
+        "border: 1px solid #ddd;"
+        "border-radius: 4px;"
+        "padding: 5px;"
+        "}"
+    );
+    m_mainLayout->addWidget(m_logTextEdit, 1);  // 设置拉伸因子为1
+
+    // 按钮布局
+    m_buttonLayout = new QHBoxLayout();
+    m_buttonLayout->addStretch();
+
+    // 刷新按钮
+    m_refreshButton = new QPushButton(tr("刷新"), this);
+    connect(m_refreshButton, &QPushButton::clicked, this, &DeviceLogDialog::onRefresh);
+    m_buttonLayout->addWidget(m_refreshButton);
+
+    // 关闭按钮
+    m_closeButton = new QPushButton(tr("关闭"), this);
+    m_closeButton->setDefault(true);
+    connect(m_closeButton, &QPushButton::clicked, this, &DeviceLogDialog::onClose);
+    m_buttonLayout->addWidget(m_closeButton);
+
+    m_mainLayout->addLayout(m_buttonLayout);
+
+    setLayout(m_mainLayout);
+}
+
+DeviceLogDialog::~DeviceLogDialog()
+{
+}
+
+void DeviceLogDialog::setDeviceInfo(const DeviceInfo& deviceInfo, DeviceBusCore* busCore)
+{
+    m_deviceInfo = deviceInfo;
+    m_busCore = busCore;
+    
+    updateLog();
+}
+
+void DeviceLogDialog::updateLog()
+{
+    // 更新设备名称
+    QString deviceName = m_deviceInfo.name.isEmpty() 
+        ? (m_deviceInfo.portname.isEmpty() ? QString("设备 %1").arg(m_deviceInfo.id) : m_deviceInfo.portname)
+        : m_deviceInfo.name;
+    m_deviceNameLabel->setText(deviceName);
+
+    // 更新设备信息
+    QString infoText = QString(tr("设备ID: %1 | 端口: %2 | 类型: %3 | 协议: %4"))
+        .arg(m_deviceInfo.id)
+        .arg(m_deviceInfo.portname.isEmpty() ? tr("未知") : m_deviceInfo.portname)
+        .arg(m_deviceInfo.type.isEmpty() ? tr("未知") : m_deviceInfo.type)
+        .arg(m_deviceInfo.protocol.isEmpty() ? tr("未知") : m_deviceInfo.protocol);
+    
+    if (m_deviceInfo.address > 0) {
+        infoText += QString(tr(" | 地址: %1")).arg(m_deviceInfo.address);
+    }
+    
+    m_deviceInfoLabel->setText(infoText);
+
+    // 更新日志内容
+    QString logText = getDeviceHistoryText();
+    m_logTextEdit->setPlainText(logText);
+    
+    // 滚动到底部
+    QScrollBar* scrollBar = m_logTextEdit->verticalScrollBar();
+    if (scrollBar) {
+        scrollBar->setValue(scrollBar->maximum());
+    }
+}
+
+QString DeviceLogDialog::getDeviceHistoryText() const
+{
+    QString logText;
+    
+    // 添加标题
+    logText += tr("========== 设备加载历史 ==========\n\n");
+    
+    // 设备基本信息
+    logText += tr("【设备基本信息】\n");
+    logText += tr("设备ID: %1\n").arg(m_deviceInfo.id);
+    logText += tr("设备名称: %1\n").arg(m_deviceInfo.name.isEmpty() ? tr("未设置") : m_deviceInfo.name);
+    logText += tr("端口名称: %1\n").arg(m_deviceInfo.portname.isEmpty() ? tr("未知") : m_deviceInfo.portname);
+    logText += tr("设备类型: %1\n").arg(m_deviceInfo.type.isEmpty() ? tr("未知") : m_deviceInfo.type);
+    logText += tr("设备地址: %1\n").arg(m_deviceInfo.address > 0 ? QString::number(m_deviceInfo.address) : tr("未设置"));
+    logText += tr("协议类型: %1\n").arg(m_deviceInfo.protocol.isEmpty() ? tr("未知") : m_deviceInfo.protocol);
+    if (!m_deviceInfo.protocol_detail.isEmpty()) {
+        logText += tr("协议详情: %1\n").arg(m_deviceInfo.protocol_detail);
+    }
+    logText += "\n";
+    
+    // 设备状态信息
+    logText += tr("【设备状态信息】\n");
+    QString statusText = m_deviceInfo.status.isEmpty() 
+        ? (m_deviceInfo.isActive ? tr("在线") : tr("离线"))
+        : (m_deviceInfo.status == "online" ? tr("在线") : 
+           m_deviceInfo.status == "offline" ? tr("离线") : m_deviceInfo.status);
+    logText += tr("当前状态: %1\n").arg(statusText);
+    logText += tr("是否活跃: %1\n").arg(m_deviceInfo.isActive ? tr("是") : tr("否"));
+    
+    if (m_deviceInfo.lastSeen.isValid()) {
+        logText += tr("最后活跃时间: %1\n")
+            .arg(m_deviceInfo.lastSeen.toString("yyyy-MM-dd hh:mm:ss"));
+    } else {
+        logText += tr("最后活跃时间: %1\n").arg(tr("未知"));
+    }
+    logText += "\n";
+    
+    // 设备加载历史(模拟,实际应该从数据库查询)
+    logText += tr("【设备加载历史】\n");
+    
+    // 如果有最后活跃时间,可以推断一些历史信息
+    if (m_deviceInfo.lastSeen.isValid()) {
+        QDateTime now = QDateTime::currentDateTime();
+        qint64 secondsSinceLastSeen = m_deviceInfo.lastSeen.secsTo(now);
+        
+        if (m_deviceInfo.isActive) {
+            logText += tr("[%1] 设备上线\n")
+                .arg(m_deviceInfo.lastSeen.toString("yyyy-MM-dd hh:mm:ss"));
+            
+            if (secondsSinceLastSeen < 60) {
+                logText += tr("[%1] 设备活跃(%2秒前)\n")
+                    .arg(now.toString("yyyy-MM-dd hh:mm:ss"))
+                    .arg(secondsSinceLastSeen);
+            }
+        } else {
+            logText += tr("[%1] 设备离线\n")
+                .arg(m_deviceInfo.lastSeen.toString("yyyy-MM-dd hh:mm:ss"));
+            
+            logText += tr("[%1] 设备已离线(%2秒前)\n")
+                .arg(now.toString("yyyy-MM-dd hh:mm:ss"))
+                .arg(secondsSinceLastSeen);
+        }
+    } else {
+        logText += tr("[%1] 设备信息已加载\n")
+            .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
+    }
+    
+    // 如果有BusCore,可以查询更多历史信息
+    if (m_busCore && m_deviceInfo.id > 0) {
+        // 可以在这里查询设备的原始数据记录数量等
+        // 例如:查询最近的数据记录时间
+        logText += "\n";
+        logText += tr("【数据统计】\n");
+        logText += tr("(数据统计功能待实现)\n");
+    }
+    
+    logText += "\n";
+    logText += tr("========== 日志结束 ==========\n");
+    logText += tr("更新时间: %1\n")
+        .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
+    
+    return logText;
+}
+
+void DeviceLogDialog::onRefresh()
+{
+    // 如果BusCore可用,重新获取设备信息
+    if (m_busCore && m_deviceInfo.id > 0) {
+        DeviceInfo updatedDevice = m_busCore->getDeviceInfo(m_deviceInfo.id);
+        if (updatedDevice.id > 0) {
+            m_deviceInfo = updatedDevice;
+        }
+    }
+    
+    updateLog();
+}
+
+void DeviceLogDialog::onClose()
+{
+    close();
+}
+

+ 68 - 0
src/device_config/device_log_dialog.h

@@ -0,0 +1,68 @@
+/**
+ * @file device_log_dialog.h
+ * @brief 设备日志对话框 - 显示设备加载历史和状态信息
+ */
+
+#ifndef DEVICE_LOG_DIALOG_H
+#define DEVICE_LOG_DIALOG_H
+
+#include <QDialog>
+#include <QString>
+#include "soft_bus_core/soft_bus_core.h"
+
+class QLabel;
+class QTextEdit;
+class QPushButton;
+class QVBoxLayout;
+class QHBoxLayout;
+class DeviceBusCore;
+
+/**
+ * @brief 设备日志对话框 - 显示设备加载历史和状态信息
+ */
+class DeviceLogDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit DeviceLogDialog(QWidget* parent = nullptr);
+    ~DeviceLogDialog();
+
+    /**
+     * @brief 设置设备信息并显示日志
+     * @param deviceInfo 设备信息
+     * @param busCore 设备总线核心(用于查询历史数据)
+     */
+    void setDeviceInfo(const DeviceInfo& deviceInfo, DeviceBusCore* busCore = nullptr);
+
+private slots:
+    void onRefresh();
+    void onClose();
+
+private:
+    /**
+     * @brief 更新日志内容
+     */
+    void updateLog();
+
+    /**
+     * @brief 获取设备加载历史文本
+     */
+    QString getDeviceHistoryText() const;
+
+private:
+    DeviceInfo m_deviceInfo;
+    DeviceBusCore* m_busCore;
+    
+    QLabel* m_deviceNameLabel;
+    QLabel* m_deviceInfoLabel;
+    QTextEdit* m_logTextEdit;
+    QPushButton* m_refreshButton;
+    QPushButton* m_closeButton;
+    
+    QVBoxLayout* m_mainLayout;
+    QHBoxLayout* m_buttonLayout;
+};
+
+#endif // DEVICE_LOG_DIALOG_H
+

+ 84 - 6
src/device_config/device_tree_widget.cpp

@@ -1,9 +1,12 @@
 #include "device_tree_widget.h"
 #include "ui_device_tree_widget.h"
 #include "api/SoftBusAPI.h"
-#include <QDebug>
+#include "utils/logging.h"
+#include "soft_bus_core/soft_bus_core.h"
 #include <QStandardItem>
 #include <QItemSelectionModel>
+#include <QBrush>
+#include <QColor>
 
 DeviceTreeWidget::DeviceTreeWidget(QWidget *parent)
     : QWidget(parent)
@@ -27,6 +30,9 @@ DeviceTreeWidget::DeviceTreeWidget(QWidget *parent)
     connect(ui->treeV_device->selectionModel(), &QItemSelectionModel::currentChanged,
             this, &DeviceTreeWidget::onDeviceSelected);
     
+    // 连接刷新按钮
+    connect(ui->btn_refresh, &QPushButton::clicked, this, &DeviceTreeWidget::onRefreshClicked);
+    
     // 初始化接口类型节点
     m_serialNode = new QStandardItem("串口设备");
     m_serialNode->setSelectable(false);
@@ -83,6 +89,10 @@ void DeviceTreeWidget::setAPI(SoftBusAPI *api)
                     this, &DeviceTreeWidget::updateDeviceList);
         }
         
+        // 连接设备状态更新信号(如果API有的话,通过CoreService获取BusCore)
+        // 注意:这里需要通过CoreService获取DeviceBusCore来连接状态更新信号
+        // 暂时通过deviceRegistered信号来更新,后续可以添加专门的设备状态更新信号
+        
         // 立即更新设备列表
         updateDeviceList();
     }
@@ -112,13 +122,40 @@ void DeviceTreeWidget::updateSerialDevices()
 
     // 从API获取所有可用的串口设备
     QStringList availablePorts = m_api->getAvailableSerialPorts();
-    qDebug() << "更新设备列表,找到" << availablePorts.size() << "个串口设备";
+    LOG_DEBUG() << "更新设备列表,找到" << availablePorts.size() << "个串口设备";
+    
+    // 获取所有已注册的设备信息,用于判断在线状态
+    QList<DeviceInfo> allDevices = m_api->getAllDevices();
+    QMap<QString, DeviceInfo> deviceMap;
+    for (const DeviceInfo &device : allDevices) {
+        if (!device.portname.isEmpty()) {
+            deviceMap[device.portname] = device;
+        }
+    }
     
     foreach (const QString &portName, availablePorts)
     {
         QStandardItem *item = createDeviceItem("serial", portName, portName);
+        
+        // 根据设备状态设置颜色
+        if (deviceMap.contains(portName)) {
+            const DeviceInfo &device = deviceMap[portName];
+            bool isOnline = device.status == "online" || (device.status.isEmpty() && device.isActive);
+            
+            if (isOnline) {
+                // 在线设备:绿色
+                item->setForeground(QBrush(QColor(0, 150, 0)));
+            } else {
+                // 离线设备:灰色
+                item->setForeground(QBrush(QColor(128, 128, 128)));
+            }
+        } else {
+            // 未注册的设备:默认颜色(黑色)
+            item->setForeground(QBrush(QColor(0, 0, 0)));
+        }
+        
         m_serialNode->appendRow(item);
-        qDebug() << "添加串口设备到列表:" << portName;
+        LOG_DEBUG() << "添加串口设备到列表:" << portName;
     }
 }
 
@@ -130,15 +167,42 @@ void DeviceTreeWidget::updateCanDevices()
 
     // 从API获取所有可用的CAN设备
     QList<int> availableDevices = m_api->getAvailableCanDevices();
-    qDebug() << "更新设备列表,找到" << availableDevices.size() << "个CAN设备";
+    LOG_DEBUG() << "更新设备列表,找到" << availableDevices.size() << "个CAN设备";
+    
+    // 获取所有已注册的设备信息,用于判断在线状态
+    QList<DeviceInfo> allDevices = m_api->getAllDevices();
+    QMap<QString, DeviceInfo> deviceMap;
+    for (const DeviceInfo &device : allDevices) {
+        if (!device.portname.isEmpty()) {
+            deviceMap[device.portname] = device;
+        }
+    }
     
     foreach (int comPort, availableDevices)
     {
         QString deviceName = QString("CAN_%1").arg(comPort);
         QString displayName = QString("CAN_%1 (端口%2)").arg(comPort).arg(comPort);
         QStandardItem *item = createDeviceItem("can", deviceName, displayName);
+        
+        // 根据设备状态设置颜色
+        if (deviceMap.contains(deviceName)) {
+            const DeviceInfo &device = deviceMap[deviceName];
+            bool isOnline = device.status == "online" || (device.status.isEmpty() && device.isActive);
+            
+            if (isOnline) {
+                // 在线设备:绿色
+                item->setForeground(QBrush(QColor(0, 150, 0)));
+            } else {
+                // 离线设备:灰色
+                item->setForeground(QBrush(QColor(128, 128, 128)));
+            }
+        } else {
+            // 未注册的设备:默认颜色(黑色)
+            item->setForeground(QBrush(QColor(0, 0, 0)));
+        }
+        
         m_canNode->appendRow(item);
-        qDebug() << "添加CAN设备到列表:" << deviceName << "com_port:" << comPort;
+        LOG_DEBUG() << "添加CAN设备到列表:" << deviceName << "com_port:" << comPort;
     }
 }
 
@@ -187,7 +251,7 @@ void DeviceTreeWidget::onDeviceSelected(const QModelIndex &index)
             if (!deviceType.isEmpty() && !deviceId.isEmpty())
             {
                 emit deviceSelected(deviceType, deviceId);
-                qDebug() << "设备被选择:" << deviceType << deviceId;
+                LOG_DEBUG() << "设备被选择:" << deviceType << deviceId;
             }
         }
     }
@@ -218,3 +282,17 @@ void DeviceTreeWidget::onCanDeviceRemoved(const QString &deviceName)
     updateDeviceList();
 }
 
+void DeviceTreeWidget::onRefreshClicked()
+{
+    LOG_INFO() << " 刷新设备列表";
+    
+    // 如果API可用,触发一次设备发现(如果支持立即扫描)
+    if (m_api) {
+        // 注意:startDeviceDiscovery 会启动定时扫描,但也会立即执行一次扫描
+        // 这里我们直接更新设备列表,因为 getAvailableSerialPorts() 会实时获取
+        updateDeviceList();
+    } else {
+        LOG_WARNING() << "API未设置,无法刷新设备列表";
+    }
+}
+

+ 1 - 0
src/device_config/device_tree_widget.h

@@ -47,6 +47,7 @@ private slots:
     void onPortRemoved(const QString &portName);
     void onCanDeviceDiscovered(const QString &deviceName, int comPort);
     void onCanDeviceRemoved(const QString &deviceName);
+    void onRefreshClicked();
 
 private:
     // 创建树节点

+ 7 - 0
src/device_config/device_tree_widget.ui

@@ -14,6 +14,13 @@
    <string>设备树</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QPushButton" name="btn_refresh">
+     <property name="text">
+      <string>刷新</string>
+     </property>
+    </widget>
+   </item>
    <item>
     <widget class="QTreeView" name="treeV_device">
      <property name="selectionMode">

+ 3 - 3
src/libmodbus/modbus_config_widget.cpp

@@ -3,7 +3,7 @@
 #include "soft_bus_core/soft_bus_core.h"
 #include "api/SoftBusAPI.h"
 #include <QSerialPortInfo>
-#include <QDebug>
+#include "utils/logging.h"
 #include <QMessageBox>
 #include <QRegularExpression>
 
@@ -114,7 +114,7 @@ void ModbusConfigWidget::onApplyConfig()
 
     // 这里可以保存配置到设备或配置文件
     QMessageBox::information(this, "提示", "配置已应用");
-    qDebug() << "Modbus配置已应用";
+    LOG_DEBUG() << "Modbus配置已应用";
 }
 
 void ModbusConfigWidget::onResetToDefaults()
@@ -238,7 +238,7 @@ void ModbusConfigWidget::onGenerateCommand()
 
     if (!command.isEmpty()) {
         emit modbusCommandGenerated(command);
-        qDebug() << "Modbus命令已生成:" << command.toHex(' ');
+        LOG_DEBUG() << "Modbus命令已生成:" << command.toHex(' ');
     } else {
         QMessageBox::warning(this, "错误", "命令生成失败,请检查配置参数");
     }

+ 81 - 0
src/protocol_plugin/IProtocolParser.h

@@ -0,0 +1,81 @@
+/**
+ * @file IProtocolParser.h
+ * @brief 协议解析器接口 - 所有协议插件必须实现此接口
+ */
+
+#ifndef IPROTOCOL_PARSER_H
+#define IPROTOCOL_PARSER_H
+
+#include <QObject>
+#include <QByteArray>
+#include <QJsonObject>
+#include <QString>
+
+/**
+ * @brief 协议解析器接口
+ * 
+ * 所有协议插件必须实现此接口,提供协议解析功能。
+ * 插件通过动态库(.so)形式加载。
+ */
+class IProtocolParser : public QObject
+{
+    Q_OBJECT
+
+public:
+    virtual ~IProtocolParser() = default;
+
+    /**
+     * @brief 获取协议名称
+     * @return 协议名称(如 "modbus-rtu", "modbus-ascii")
+     */
+    virtual QString getName() const = 0;
+
+    /**
+     * @brief 获取协议版本
+     * @return 协议版本字符串
+     */
+    virtual QString getVersion() const = 0;
+
+    /**
+     * @brief 从数据缓冲区中提取一个完整的协议帧
+     * @param buffer 数据缓冲区
+     * @param frame 输出:提取的完整帧(如果找到)
+     * @return 是否成功提取到完整帧
+     */
+    virtual bool extractFrame(const QByteArray& buffer, QByteArray& frame) = 0;
+
+    /**
+     * @brief 解析协议帧
+     * @param frame 完整的协议帧
+     * @param result 输出:解析结果(JSON格式)
+     * @return 是否成功解析
+     */
+    virtual bool parseFrame(const QByteArray& frame, QJsonObject& result) = 0;
+
+    /**
+     * @brief 验证帧的完整性
+     * @param frame 协议帧
+     * @return 是否完整
+     */
+    virtual bool validateFrame(const QByteArray& frame) const = 0;
+
+    /**
+     * @brief 获取协议配置参数说明
+     * @return 配置参数说明(JSON格式)
+     */
+    virtual QJsonObject getConfigSchema() const = 0;
+
+    /**
+     * @brief 设置协议配置参数
+     * @param config 配置参数(JSON格式)
+     */
+    virtual void setConfig(const QJsonObject& config) = 0;
+};
+
+// 导出符号宏
+#define IProtocolParser_iid "com.softbus.IProtocolParser/1.0"
+
+Q_DECLARE_INTERFACE(IProtocolParser, IProtocolParser_iid)
+
+#endif // IPROTOCOL_PARSER_H
+

+ 210 - 0
src/protocol_plugin/ProtocolPluginManager.cpp

@@ -0,0 +1,210 @@
+/**
+ * @file ProtocolPluginManager.cpp
+ * @brief 协议插件管理器实现
+ */
+
+#include "ProtocolPluginManager.h"
+#include <QDir>
+#include <QFileInfo>
+#include "utils/logging.h"
+#include <QCoreApplication>
+
+ProtocolPluginManager::ProtocolPluginManager(QObject* parent)
+    : QObject(parent)
+{
+    // 默认插件目录
+    m_pluginDir = QCoreApplication::applicationDirPath() + "/protocols";
+}
+
+ProtocolPluginManager::~ProtocolPluginManager()
+{
+    // 卸载所有插件
+    QStringList loadedPlugins = m_loaders.keys();
+    for (const QString& pluginId : loadedPlugins) {
+        unloadPlugin(pluginId);
+    }
+}
+
+void ProtocolPluginManager::setPluginDir(const QString& pluginDir)
+{
+    m_pluginDir = pluginDir;
+}
+
+int ProtocolPluginManager::scanPlugins()
+{
+    QDir dir(m_pluginDir);
+    if (!dir.exists()) {
+        LOG_WARNING() << "Plugin directory does not exist:" << m_pluginDir;
+        return 0;
+    }
+
+    // 查找所有 .so 文件(Linux)或 .dylib 文件(macOS)或 .dll 文件(Windows)
+    QStringList filters;
+#ifdef Q_OS_LINUX
+    filters << "*.so";
+#elif defined(Q_OS_MACOS)
+    filters << "*.dylib";
+#elif defined(Q_OS_WIN)
+    filters << "*.dll";
+#endif
+
+    QStringList files = dir.entryList(filters, QDir::Files);
+    int count = 0;
+
+    for (const QString& fileName : files) {
+        QString filePath = dir.absoluteFilePath(fileName);
+        ProtocolPluginInfo info = loadPluginFromFile(filePath);
+        if (!info.id.isEmpty()) {
+            m_plugins[info.id] = info;
+            count++;
+            LOG_DEBUG() << "Found plugin:" << info.name << "version" << info.version;
+        }
+    }
+
+    return count;
+}
+
+bool ProtocolPluginManager::loadPlugin(const QString& pluginId)
+{
+    if (m_loaders.contains(pluginId)) {
+        LOG_WARNING() << "Plugin already loaded:" << pluginId;
+        return true;
+    }
+
+    if (!m_plugins.contains(pluginId)) {
+        LOG_WARNING() << "Plugin not found:" << pluginId;
+        return false;
+    }
+
+    ProtocolPluginInfo& info = m_plugins[pluginId];
+    if (info.loaded) {
+        return true;
+    }
+
+    // 创建插件加载器
+    QPluginLoader* loader = new QPluginLoader(info.filePath, this);
+    if (!loader->load()) {
+        LOG_WARNING() << "Failed to load plugin:" << pluginId << loader->errorString();
+        delete loader;
+        return false;
+    }
+
+    // 获取插件实例
+    QObject* plugin = loader->instance();
+    if (!plugin) {
+        LOG_WARNING() << "Failed to get plugin instance:" << pluginId;
+        loader->unload();
+        delete loader;
+        return false;
+    }
+
+    // 转换为协议解析器接口
+    IProtocolParser* parser = qobject_cast<IProtocolParser*>(plugin);
+    if (!parser) {
+        LOG_WARNING() << "Plugin does not implement IProtocolParser:" << pluginId;
+        loader->unload();
+        delete loader;
+        return false;
+    }
+
+    // 保存加载器 and 解析器
+    m_loaders[pluginId] = loader;
+    m_parsers[info.name] = parser;
+    info.loaded = true;
+    info.parser = parser;
+
+    LOG_DEBUG() << "Plugin loaded:" << info.name << "version" << info.version;
+    emit pluginLoaded(pluginId);
+
+    return true;
+}
+
+void ProtocolPluginManager::unloadPlugin(const QString& pluginId)
+{
+    if (!m_loaders.contains(pluginId)) {
+        return;
+    }
+
+    ProtocolPluginInfo& info = m_plugins[pluginId];
+    QPluginLoader* loader = m_loaders[pluginId];
+
+    // 移除解析器映射
+    if (m_parsers.contains(info.name)) {
+        m_parsers.remove(info.name);
+    }
+
+    // 卸载插件
+    loader->unload();
+    delete loader;
+    m_loaders.remove(pluginId);
+
+    info.loaded = false;
+    info.parser = nullptr;
+
+    LOG_DEBUG() << "Plugin unloaded:" << info.name;
+    emit pluginUnloaded(pluginId);
+}
+
+IProtocolParser* ProtocolPluginManager::getParser(const QString& protocolName)
+{
+    return m_parsers.value(protocolName, nullptr);
+}
+
+QList<ProtocolPluginInfo> ProtocolPluginManager::getLoadedPlugins() const
+{
+    QList<ProtocolPluginInfo> result;
+    for (const ProtocolPluginInfo& info : m_plugins.values()) {
+        if (info.loaded) {
+            result.append(info);
+        }
+    }
+    return result;
+}
+
+QList<ProtocolPluginInfo> ProtocolPluginManager::getAllPlugins() const
+{
+    return m_plugins.values();
+}
+
+bool ProtocolPluginManager::isPluginLoaded(const QString& pluginId) const
+{
+    return m_loaders.contains(pluginId);
+}
+
+ProtocolPluginInfo ProtocolPluginManager::loadPluginFromFile(const QString& filePath)
+{
+    ProtocolPluginInfo info;
+    info.filePath = filePath;
+
+    // 尝试加载插件以获取信息
+    QPluginLoader loader(filePath);
+    if (!loader.load()) {
+        LOG_WARNING() << "Failed to load plugin for scanning:" << filePath << loader.errorString();
+        return info;
+    }
+
+    QObject* plugin = loader.instance();
+    if (!plugin) {
+        loader.unload();
+        return info;
+    }
+
+    IProtocolParser* parser = qobject_cast<IProtocolParser*>(plugin);
+    if (!parser) {
+        loader.unload();
+        return info;
+    }
+
+    // 获取插件信息
+    info.id = QFileInfo(filePath).baseName();
+    info.name = parser->getName();
+    info.version = parser->getVersion();
+    info.loaded = false;
+    info.parser = nullptr;
+
+    // 卸载(只是扫描,不保留加载状态)
+    loader.unload();
+
+    return info;
+}
+

+ 126 - 0
src/protocol_plugin/ProtocolPluginManager.h

@@ -0,0 +1,126 @@
+/**
+ * @file ProtocolPluginManager.h
+ * @brief 协议插件管理器 - 管理协议插件的加载、卸载和使用
+ */
+
+#ifndef PROTOCOL_PLUGIN_MANAGER_H
+#define PROTOCOL_PLUGIN_MANAGER_H
+
+#include <QObject>
+#include <QString>
+#include <QStringList>
+#include <QMap>
+#include <QPluginLoader>
+#include <QJsonObject>
+#include "IProtocolParser.h"
+
+/**
+ * @brief 协议插件信息
+ */
+struct ProtocolPluginInfo
+{
+    QString id;              // 插件ID
+    QString name;            // 协议名称
+    QString version;         // 版本
+    QString filePath;        // 插件文件路径
+    bool loaded;             // 是否已加载
+    IProtocolParser* parser; // 解析器实例
+};
+
+/**
+ * @brief 协议插件管理器
+ * 
+ * 负责:
+ * - 扫描插件目录
+ * - 加载/卸载协议插件
+ * - 根据协议名称获取解析器
+ * - 管理插件生命周期
+ */
+class ProtocolPluginManager : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit ProtocolPluginManager(QObject* parent = nullptr);
+    ~ProtocolPluginManager();
+
+    /**
+     * @brief 设置插件目录
+     * @param pluginDir 插件目录路径
+     */
+    void setPluginDir(const QString& pluginDir);
+
+    /**
+     * @brief 扫描插件目录,发现可用插件
+     * @return 发现的插件数量
+     */
+    int scanPlugins();
+
+    /**
+     * @brief 加载指定插件
+     * @param pluginId 插件ID
+     * @return 成功返回 true
+     */
+    bool loadPlugin(const QString& pluginId);
+
+    /**
+     * @brief 卸载指定插件
+     * @param pluginId 插件ID
+     */
+    void unloadPlugin(const QString& pluginId);
+
+    /**
+     * @brief 根据协议名称获取解析器
+     * @param protocolName 协议名称(如 "modbus-rtu")
+     * @return 解析器指针,如果不存在返回 nullptr
+     */
+    IProtocolParser* getParser(const QString& protocolName);
+
+    /**
+     * @brief 获取所有已加载的插件信息
+     * @return 插件信息列表
+     */
+    QList<ProtocolPluginInfo> getLoadedPlugins() const;
+
+    /**
+     * @brief 获取所有可用插件信息(包括未加载的)
+     * @return 插件信息列表
+     */
+    QList<ProtocolPluginInfo> getAllPlugins() const;
+
+    /**
+     * @brief 检查插件是否已加载
+     * @param pluginId 插件ID
+     * @return 已加载返回 true
+     */
+    bool isPluginLoaded(const QString& pluginId) const;
+
+signals:
+    /**
+     * @brief 插件加载时发出
+     * @param pluginId 插件ID
+     */
+    void pluginLoaded(const QString& pluginId);
+
+    /**
+     * @brief 插件卸载时发出
+     * @param pluginId 插件ID
+     */
+    void pluginUnloaded(const QString& pluginId);
+
+private:
+    QString m_pluginDir;
+    QMap<QString, ProtocolPluginInfo> m_plugins;      // 所有插件(已加载和未加载)
+    QMap<QString, QPluginLoader*> m_loaders;          // 插件加载器
+    QMap<QString, IProtocolParser*> m_parsers;        // 协议名称 -> 解析器映射
+
+    /**
+     * @brief 从插件文件加载插件
+     * @param filePath 插件文件路径
+     * @return 成功返回插件信息
+     */
+    ProtocolPluginInfo loadPluginFromFile(const QString& filePath);
+};
+
+#endif // PROTOCOL_PLUGIN_MANAGER_H
+

+ 10 - 10
src/serial_manager/serial_data_buffer.cpp

@@ -1,5 +1,5 @@
 #include "serial_data_buffer.h"
-#include <QDebug>
+#include "utils/logging.h"
 #include <QThread>
 #include <QMutexLocker>
 #include <QList>
@@ -28,7 +28,7 @@ void SerialDataBuffer::appendData(const QByteArray &data)
     {
         m_buffer.append(data);
         m_lastDataTime = QDateTime::currentDateTime();
-        qDebug() << "Buffer for" << m_portName << "appended" << data.size() << "bytes, total:" << m_buffer.size();
+        LOG_DEBUG() << "Buffer for" << m_portName << "appended" << data.size() << "bytes, total:" << m_buffer.size();
     }
 }
 
@@ -48,7 +48,7 @@ QByteArray SerialDataBuffer::extractFrame(const QString &protocol, const QString
         // 检查超时(使用无锁版本,因为已经持有锁)
         if (isTimeoutUnlocked())
         {
-            qDebug() << "Buffer timeout for" << m_portName << ", clearing buffer";
+            LOG_DEBUG() << "Buffer timeout for" << m_portName << ", clearing buffer";
             m_buffer.clear();
             return QByteArray();
         }
@@ -91,13 +91,13 @@ QByteArray SerialDataBuffer::extractFrame(const QString &protocol, const QString
         if (m_buffer.size() >= frame.size() && m_buffer.startsWith(frame))
         {
             m_buffer.remove(0, frame.size());
-            qDebug() << "Removed extracted frame from buffer for" << m_portName;
+            LOG_DEBUG() << "Removed extracted frame from buffer for" << m_portName;
         }
         else if (m_buffer.size() >= frame.size())
         {
             // 如果帧不匹配,可能是数据已被处理,尝试移除相同长度
             m_buffer.remove(0, frame.size());
-            qDebug() << "Removed frame-sized data from buffer for" << m_portName;
+            LOG_DEBUG() << "Removed frame-sized data from buffer for" << m_portName;
         }
     }
     else
@@ -108,7 +108,7 @@ QByteArray SerialDataBuffer::extractFrame(const QString &protocol, const QString
         // 如果缓冲区太大,可能是数据损坏,清空无效数据
         if (m_buffer.size() > MODBUS_RTU_MAX_LENGTH * 2)
         {
-            qWarning() << "Buffer too large for" << m_portName << ", clearing";
+            LOG_WARNING() << "Buffer too large for" << m_portName << ", clearing";
             m_buffer.clear();
         }
         // 如果搜索了多个位置都没找到,可能是数据损坏,移除第一个字节
@@ -116,7 +116,7 @@ QByteArray SerialDataBuffer::extractFrame(const QString &protocol, const QString
         {
             // 移除第一个字节,可能是无效数据
             m_buffer.remove(0, 1);
-            qDebug() << "Removed invalid byte from buffer for" << m_portName;
+            LOG_DEBUG() << "Removed invalid byte from buffer for" << m_portName;
         }
     }
 
@@ -178,7 +178,7 @@ QByteArray SerialDataBuffer::extractModbusRTUFrameFromBuffer(const QByteArray &b
             // 验证CRC(在锁外进行,不会阻塞其他线程)
             if (validateModbusRTUCRC(candidate))
             {
-                qDebug() << "Extracted Modbus RTU frame from" << m_portName << ":" << candidate.toHex() << "length:" << len;
+                LOG_DEBUG() << "Extracted Modbus RTU frame from" << m_portName << ":" << candidate.toHex() << "length:" << len;
                 return candidate;
             }
         }
@@ -206,7 +206,7 @@ QByteArray SerialDataBuffer::extractModbusRTUFrameFromBuffer(const QByteArray &b
             // 验证CRC(在锁外进行,不会阻塞其他线程)
             if (validateModbusRTUCRC(candidate))
             {
-                qDebug() << "Extracted Modbus RTU frame from" << m_portName << ":" << candidate.toHex() << "length:" << len;
+                LOG_DEBUG() << "Extracted Modbus RTU frame from" << m_portName << ":" << candidate.toHex() << "length:" << len;
                 return candidate;
             }
         }
@@ -238,7 +238,7 @@ QByteArray SerialDataBuffer::extractModbusASCIIFrameFromBuffer(const QByteArray
     int frameLength = endIdx - startIdx + 2;
     QByteArray frame = buffer.mid(startIdx, frameLength);
     
-    qDebug() << "Extracted Modbus ASCII frame from" << m_portName << ":" << frame;
+    LOG_DEBUG() << "Extracted Modbus ASCII frame from" << m_portName << ":" << frame;
     return frame;
 }
 

+ 36 - 23
src/serial_manager/serial_manager.cpp

@@ -2,7 +2,8 @@
 #include "serial_data_buffer.h"
 #include "serial_storage_thread.h"
 #include "serial_parser_thread.h"
-#include <QDebug>
+#include "protocol_plugin/ProtocolPluginManager.h"
+#include "utils/logging.h"
 #include <QDateTime>
 #include <QJsonDocument>
 #include <QJsonArray>
@@ -15,7 +16,8 @@ SerialManager::SerialManager(DeviceBusCore *busCore, QObject *parent)
       m_discoveryTimer(new QTimer(this)),
       m_serialConfig(),
       m_storageThread(nullptr),
-      m_parserThread(nullptr)
+      m_parserThread(nullptr),
+      m_pluginManager(nullptr)
 {
     // 连接定时器信号
     connect(m_discoveryTimer, &QTimer::timeout, this, &SerialManager::discoverSerialPorts);
@@ -90,13 +92,13 @@ bool SerialManager::openSerialPort(const QSerialPortInfo &portInfo)
         connect(serialPort, &QSerialPort::readyRead, this, [this, portInfo]()
                 { onReadyRead(portInfo.portName()); });
 
-        qDebug() << "Opened serial port:" << portInfo.portName();
+        LOG_DEBUG() << "Opened serial port:" << portInfo.portName();
         return true;
     }
     else
     {
         // 打开失败,清理资源
-        qWarning() << "Failed to open port" << portInfo.portName() << ":" << serialPort->errorString();
+        LOG_WARNING() << "Failed to open port" << portInfo.portName() << ":" << serialPort->errorString();
         delete serialPort;
         return false;
     }
@@ -119,7 +121,7 @@ void SerialManager::closeSerialPort(const QString &portName)
         }
         
         emit portRemoved(portName);
-        qDebug() << "Closed serial port:" << portName;
+        LOG_DEBUG() << "Closed serial port:" << portName;
     }
 }
 bool SerialManager::isPortOpen(const QString &portName)
@@ -141,7 +143,7 @@ void SerialManager::closeAllPorts()
     qDeleteAll(m_dataBuffers);
     m_dataBuffers.clear();
     
-    qDebug() << "All serial ports closed";
+    LOG_DEBUG() << "All serial ports closed";
 }
 
 void SerialManager::setSerialConfig(const SerialConfig &config)
@@ -158,7 +160,7 @@ void SerialManager::setSerialConfig(const SerialConfig &config)
         port->setFlowControl(config.flowControl);
     }
 
-    qDebug() << "Serial configuration updated";
+    LOG_DEBUG() << "Serial configuration updated";
 }
 
 SerialManager::SerialConfig SerialManager::getSerialConfig() const
@@ -256,12 +258,12 @@ bool SerialManager::writeData(const QString &portName, const QByteArray &data)
         qint64 bytesWritten = m_serialPorts[portName]->write(data);
         if (bytesWritten == data.size())
         {
-            qDebug() << "Data written to" << portName << ":" << data.toHex();
+            LOG_DEBUG() << "Data written to" << portName << ":" << data.toHex();
             return true;
         }
         else
         {
-            qWarning() << "Failed to write all data to" << portName
+            LOG_WARNING() << "Failed to write all data to" << portName
                        << ". Written:" << bytesWritten << "of" << data.size();
         }
     }
@@ -271,7 +273,7 @@ bool SerialManager::writeData(const QString &portName, const QByteArray &data)
 void SerialManager::setBusCore(DeviceBusCore *busCore)
 {
     m_busCore = busCore;
-    qDebug() << "Bus core set for SerialManager";
+    LOG_INFO() << "Bus core set for SerialManager";
     
     // 更新线程的busCore
     if (m_storageThread)
@@ -308,7 +310,7 @@ void SerialManager::discoverSerialPorts()
         {
             registerDiscoveredPort(info);
             emit portDiscovered(portName, info.description());
-            qDebug() << "New port discovered:" << portName << "-" << info.description();
+            LOG_DEBUG() << "New port discovered:" << portName << "-" << info.description();
         }
     }
 
@@ -326,7 +328,7 @@ void SerialManager::discoverSerialPorts()
             m_busCore->markDeviceOfflineByPort(portName);
         }
         emit portRemoved(portName);
-        qDebug() << "Port removed:" << portName;
+        LOG_DEBUG() << "Port removed:" << portName;
     }
 
     // 更新上次发现的端口列表
@@ -343,7 +345,7 @@ void SerialManager::onReadyRead(const QString &portName)
         if (!data.isEmpty())
         {
             // 发出数据接收信号(用于UI显示)
-            qDebug() << "Received data from" << portName << ":" << data.toHex();
+            LOG_DEBUG() << "Received data from" << portName << ":" << data.toHex();
             emit dataReceived(portName, data);
 
             // 将数据添加到缓冲区(用于帧拼凑)
@@ -374,13 +376,13 @@ void SerialManager::initThreads()
     {
         m_storageThread = new SerialStorageThread(m_busCore, this);
         m_storageThread->start();
-        qDebug() << "SerialStorageThread created and started";
+        LOG_DEBUG() << "SerialStorageThread created and started";
     }
 
     // 创建解析线程
     if (!m_parserThread)
     {
-        m_parserThread = new SerialParserThread(m_busCore, this);
+        m_parserThread = new SerialParserThread(m_busCore, m_pluginManager, this);
         
         // 连接解析线程的信号
         connect(m_parserThread, &SerialParserThread::modbusDataParsed,
@@ -389,7 +391,7 @@ void SerialManager::initThreads()
                 this, &SerialManager::customDataParsed);
         
         m_parserThread->start();
-        qDebug() << "SerialParserThread created and started";
+        LOG_DEBUG() << "SerialParserThread created and started";
         
         // 注册已有的缓冲区
         for (auto it = m_dataBuffers.begin(); it != m_dataBuffers.end(); ++it)
@@ -399,17 +401,28 @@ void SerialManager::initThreads()
     }
 }
 
+void SerialManager::setPluginManager(ProtocolPluginManager *pluginManager)
+{
+    m_pluginManager = pluginManager;
+    
+    // 更新解析线程的插件管理器
+    if (m_parserThread)
+    {
+        m_parserThread->setPluginManager(pluginManager);
+    }
+}
+
 void SerialManager::registerDiscoveredPort(const QSerialPortInfo &info)
 {
     if (!m_busCore)
     {
-        qDebug() << "Bus core is not set; skip registering port" << info.portName();
+            LOG_DEBUG() << "Bus core is not set; skip registering port" << info.portName();
         return;
     }
 
     if (!isRealSerialPort(info))
     {
-        qDebug() << "Skip registering non-real serial port" << info.portName();
+            LOG_DEBUG() << "Skip registering non-real serial port" << info.portName();
         return;
     }
 
@@ -463,7 +476,7 @@ void SerialManager::registerDiscoveredPort(const QSerialPortInfo &info)
             existingDevice.isActive = true;
             existingDevice.lastSeen = QDateTime::currentDateTimeUtc();
             m_busCore->updateDevice(existingDevice);
-            qDebug() << "Updated existing serial device registration for port" << portName;
+            LOG_DEBUG() << "Updated existing serial device registration for port" << portName;
         }
 
         if (!needFullUpdate)
@@ -478,7 +491,7 @@ void SerialManager::registerDiscoveredPort(const QSerialPortInfo &info)
     device.id = generateNextDeviceId();
     if (device.id <= 0)
     {
-        qWarning() << "Failed to allocate device ID for port" << portName;
+        LOG_WARNING() << "Failed to allocate device ID for port" << portName;
         return;
     }
 
@@ -535,7 +548,7 @@ void SerialManager::registerDiscoveredPort(const QSerialPortInfo &info)
     m_busCore->registerDevice(device);
     m_busCore->updateDeviceStatus(device.id, QStringLiteral("online"), true,
                                   device.lastSeen);
-    qDebug() << "Registered serial device in bus core for port" << portName << "with id" << device.id;
+    LOG_DEBUG() << "Registered serial device in bus core for port" << portName << "with id" << device.id;
 }
 
 int SerialManager::generateNextDeviceId() const
@@ -563,7 +576,7 @@ void SerialManager::cleanupThreads()
         m_storageThread->wait();
         delete m_storageThread;
         m_storageThread = nullptr;
-        qDebug() << "SerialStorageThread stopped and deleted";
+        LOG_DEBUG() << "SerialStorageThread stopped and deleted";
     }
 
     // 停止并清理解析线程
@@ -573,6 +586,6 @@ void SerialManager::cleanupThreads()
         m_parserThread->wait();
         delete m_parserThread;
         m_parserThread = nullptr;
-        qDebug() << "SerialParserThread stopped and deleted";
+        LOG_DEBUG() << "SerialParserThread stopped and deleted";
     }
 }

+ 5 - 0
src/serial_manager/serial_manager.h

@@ -92,6 +92,9 @@ public:
     // 获取软总线核心
     DeviceBusCore *getBusCore() const;
 
+    // 设置协议插件管理器
+    void setPluginManager(class ProtocolPluginManager *pluginManager);
+
 signals:
     // 发现新串口时发出的信号,包含串口名称和描述
     void portDiscovered(const QString &portName, const QString &description);
@@ -143,6 +146,8 @@ private:
     SerialStorageThread *m_storageThread;
     // 解析线程
     SerialParserThread *m_parserThread;
+    // 协议插件管理器
+    class ProtocolPluginManager *m_pluginManager;
 };
 
 #endif // SERIAL_MANAGER_H

+ 85 - 10
src/serial_manager/serial_parser_thread.cpp

@@ -1,19 +1,28 @@
 #include "serial_parser_thread.h"
 #include "serial_data_buffer.h"
 #include "soft_bus_core/soft_bus_core.h"
-#include <QDebug>
+#include "protocol_plugin/ProtocolPluginManager.h"
+#include "protocol_plugin/IProtocolParser.h"
+#include "utils/logging.h"
 #include <QDateTime>
 #include <QJsonObject>
 #include <QJsonArray>
 #include <QMutexLocker>
 
-SerialParserThread::SerialParserThread(DeviceBusCore *busCore, QObject *parent)
+SerialParserThread::SerialParserThread(DeviceBusCore *busCore, ProtocolPluginManager *pluginManager, QObject *parent)
     : QThread(parent),
       m_busCore(busCore),
+      m_pluginManager(pluginManager),
       m_stopped(false)
 {
 }
 
+void SerialParserThread::setPluginManager(ProtocolPluginManager *pluginManager)
+{
+    QMutexLocker locker(&m_mutex);
+    m_pluginManager = pluginManager;
+}
+
 SerialParserThread::~SerialParserThread()
 {
     stop();
@@ -47,7 +56,7 @@ void SerialParserThread::stop()
 
 void SerialParserThread::run()
 {
-    qDebug() << "SerialParserThread started";
+    LOG_DEBUG() << "SerialParserThread started";
     
     while (!m_stopped)
     {
@@ -121,7 +130,7 @@ void SerialParserThread::run()
 
                 if (!parsed)
                 {
-                    qWarning() << "Failed to parse frame from" << portName << ":" << frame.toHex();
+                    LOG_WARNING() << "Failed to parse frame from" << portName << ":" << frame.toHex();
                 }
 
                 // 尝试提取下一个帧
@@ -130,17 +139,30 @@ void SerialParserThread::run()
             
             if (frameCount >= maxFrames)
             {
-                qWarning() << "Reached max frame extraction limit for" << portName;
+                LOG_WARNING() << "Reached max frame extraction limit for" << portName;
             }
         }
     }
     
-    qDebug() << "SerialParserThread stopped";
+    LOG_DEBUG() << "SerialParserThread stopped";
 }
 
 bool SerialParserThread::tryParseWithProtocol(const QByteArray &frame, const QString &portName,
                                               const QString &protocol, const QString &protocolDetail)
 {
+    // 优先使用协议插件
+    if (m_pluginManager) {
+        QString pluginName = protocol;
+        if (!protocolDetail.isEmpty()) {
+            pluginName = protocolDetail;  // 使用详细协议名称(如 "modbus-rtu")
+        }
+        
+        if (parseWithPlugin(frame, portName, pluginName, protocolDetail)) {
+            return true;
+        }
+    }
+
+    // 如果没有插件或插件解析失败,使用内置解析(向后兼容)
     if (protocol == "modbus")
     {
         if (protocolDetail == "modbus-rtu")
@@ -169,6 +191,59 @@ bool SerialParserThread::tryParseWithProtocol(const QByteArray &frame, const QSt
     return false;
 }
 
+bool SerialParserThread::parseWithPlugin(const QByteArray &frame, const QString &portName,
+                                         const QString &protocol, const QString &protocolDetail)
+{
+    if (!m_pluginManager) {
+        return false;
+    }
+
+    // 获取协议解析器
+    IProtocolParser* parser = m_pluginManager->getParser(protocol);
+    if (!parser) {
+        return false;
+    }
+
+    // 验证帧
+    if (!parser->validateFrame(frame)) {
+        return false;
+    }
+
+    // 解析帧
+    QJsonObject result;
+    if (!parser->parseFrame(frame, result)) {
+        return false;
+    }
+
+    // 创建总线消息
+    BusMessage message;
+    message.id = QString("%1_%2_%3").arg(portName).arg(protocol)
+                  .arg(QDateTime::currentMSecsSinceEpoch());
+    message.source = portName;
+    message.destination = "data_processor";
+    message.timestamp = QDateTime::currentMSecsSinceEpoch();
+
+    // 设置payload
+    QJsonObject payload = result;
+    payload["protocol"] = protocol;
+    if (!protocolDetail.isEmpty()) {
+        payload["protocol_detail"] = protocolDetail;
+    }
+    payload["raw_hex"] = QString(frame.toHex());
+    message.payload = payload;
+
+    // 存储总线消息
+    if (m_busCore) {
+        m_busCore->storeBusMessage(message);
+    }
+
+    // 发出信号
+    emit modbusDataParsed(payload);  // 复用现有信号
+    LOG_DEBUG() << "Protocol plugin parsed data from" << portName << "protocol" << protocol << ":" << payload;
+
+    return true;
+}
+
 bool SerialParserThread::tryParseWithOtherProtocols(const QByteArray &frame, const QString &portName)
 {
     // 尝试Modbus RTU
@@ -199,7 +274,7 @@ void SerialParserThread::parseModbusRTU(const QByteArray &frame, const QString &
 {
     if (frame.size() < 4)
     {
-        qWarning() << "Modbus RTU frame too short:" << frame.size();
+        LOG_WARNING() << "Modbus RTU frame too short:" << frame.size();
         return;
     }
 
@@ -240,7 +315,7 @@ void SerialParserThread::parseModbusRTU(const QByteArray &frame, const QString &
 
     // 发出信号
     emit modbusDataParsed(payload);
-    qDebug() << "Modbus RTU data parsed from" << portName << ":" << payload;
+    LOG_DEBUG() << "Modbus RTU data parsed from" << portName << ":" << payload;
 }
 
 void SerialParserThread::parseModbusASCII(const QByteArray &frame, const QString &portName)
@@ -272,7 +347,7 @@ void SerialParserThread::parseModbusASCII(const QByteArray &frame, const QString
 
     // 发出信号
     emit modbusDataParsed(payload);
-    qDebug() << "Modbus ASCII data parsed from" << portName << ":" << payload;
+    LOG_DEBUG() << "Modbus ASCII data parsed from" << portName << ":" << payload;
 }
 
 void SerialParserThread::parseCustomProtocol(const QByteArray &frame, const QString &portName, const QString &protocolDetail)
@@ -304,6 +379,6 @@ void SerialParserThread::parseCustomProtocol(const QByteArray &frame, const QStr
 
     // 发出信号
     emit customDataParsed(payload);
-    qDebug() << "Custom protocol data parsed from" << portName << ":" << payload;
+    LOG_DEBUG() << "Custom protocol data parsed from" << portName << ":" << payload;
 }
 

+ 17 - 9
src/serial_manager/serial_parser_thread.h

@@ -18,8 +18,11 @@
 #include <QByteArray>
 #include <QString>
 #include <QMap>
+#include <QJsonObject>
 
 class DeviceBusCore;
+class ProtocolPluginManager;
+class IProtocolParser;
 #include "serial_data_buffer.h"
 
 /**
@@ -30,7 +33,7 @@ class SerialParserThread : public QThread
     Q_OBJECT
 
 public:
-    explicit SerialParserThread(DeviceBusCore *busCore, QObject *parent = nullptr);
+    explicit SerialParserThread(DeviceBusCore *busCore, ProtocolPluginManager *pluginManager = nullptr, QObject *parent = nullptr);
     ~SerialParserThread();
 
     // 注册端口缓冲区
@@ -40,8 +43,12 @@ public:
     void notifyNewData(const QString &portName);
 
     // 停止线程
+    
     void stop();
 
+    // 设置协议插件管理器
+    void setPluginManager(ProtocolPluginManager *pluginManager);
+
 signals:
     // 解析完成信号
     void modbusDataParsed(const QJsonObject &data);
@@ -51,14 +58,9 @@ protected:
     void run() override;
 
 private:
-    // 解析Modbus RTU帧
-    void parseModbusRTU(const QByteArray &frame, const QString &portName);
-    
-    // 解析Modbus ASCII帧
-    void parseModbusASCII(const QByteArray &frame, const QString &portName);
-    
-    // 解析自定义协议
-    void parseCustomProtocol(const QByteArray &frame, const QString &portName, const QString &protocolDetail);
+    // 使用协议插件解析
+    bool parseWithPlugin(const QByteArray &frame, const QString &portName, 
+                         const QString &protocol, const QString &protocolDetail);
 
     // 尝试使用配置的协议解析
     bool tryParseWithProtocol(const QByteArray &frame, const QString &portName, 
@@ -67,7 +69,13 @@ private:
     // 尝试其他协议解析(当配置协议解析失败时)
     bool tryParseWithOtherProtocols(const QByteArray &frame, const QString &portName);
 
+    // 协议解析方法
+    void parseModbusRTU(const QByteArray &frame, const QString &portName);
+    void parseModbusASCII(const QByteArray &frame, const QString &portName);
+    void parseCustomProtocol(const QByteArray &frame, const QString &portName, const QString &protocolDetail);
+
     DeviceBusCore *m_busCore;
+    ProtocolPluginManager *m_pluginManager;
     QMap<QString, SerialDataBuffer*> m_buffers;
     QQueue<QString> m_pendingPorts;
     QMutex m_mutex;

+ 5 - 5
src/serial_manager/serial_storage_thread.cpp

@@ -1,6 +1,6 @@
 #include "serial_storage_thread.h"
 #include "soft_bus_core/soft_bus_core.h"
-#include <QDebug>
+#include "utils/logging.h"
 #include <QDateTime>
 #include <QMutexLocker>
 
@@ -44,7 +44,7 @@ void SerialStorageThread::stop()
 
 void SerialStorageThread::run()
 {
-    qDebug() << "SerialStorageThread started";
+    LOG_DEBUG() << "SerialStorageThread started";
     
     while (!m_stopped)
     {
@@ -83,17 +83,17 @@ void SerialStorageThread::run()
                 if (device.id != 0)
                 {
                     m_busCore->storeRawData(device.id, task.data);
-                    qDebug() << "Raw data stored for device ID" << device.id 
+                    LOG_DEBUG() << "Raw data stored for device ID" << device.id 
                              << "(" << task.portName << "):" << task.data.toHex();
                 }
                 else
                 {
-                    qWarning() << "Device not found for portname:" << task.portName;
+                    LOG_WARNING() << "Device not found for portname:" << task.portName;
                 }
             }
         }
     }
     
-    qDebug() << "SerialStorageThread stopped";
+    LOG_DEBUG() << "SerialStorageThread stopped";
 }
 

+ 173 - 0
src/settings/settings_dialog.cpp

@@ -0,0 +1,173 @@
+#include "settings_dialog.h"
+#include "daemon/daemon_client.h"
+#include <QCheckBox>
+#include <QLabel>
+#include <QPushButton>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QGroupBox>
+#include <QSettings>
+#include <QMessageBox>
+#include <QTimer>
+
+SettingsDialog::SettingsDialog(QWidget *parent)
+    : QDialog(parent)
+    , m_useDaemonMode(true)  // 默认启用守护进程模式
+    , m_daemonClient(nullptr)
+{
+    setWindowTitle("设置");
+    setModal(true);
+    resize(500, 300);
+    
+    createUI();
+    loadSettings();
+    
+    // 定时更新守护进程状态
+    QTimer *statusTimer = new QTimer(this);
+    connect(statusTimer, &QTimer::timeout, this, &SettingsDialog::updateDaemonStatus);
+    statusTimer->start(1000); // 每秒更新一次
+    updateDaemonStatus(); // 立即更新一次
+}
+
+SettingsDialog::~SettingsDialog()
+{
+}
+
+void SettingsDialog::createUI()
+{
+    m_mainLayout = new QVBoxLayout(this);
+    
+    // 守护进程设置组
+    m_daemonGroupBox = new QGroupBox("守护进程设置", this);
+    QVBoxLayout *daemonLayout = new QVBoxLayout(m_daemonGroupBox);
+    
+    m_useDaemonCheckBox = new QCheckBox("使用守护进程模式进行硬件操作", m_daemonGroupBox);
+    m_useDaemonCheckBox->setToolTip("启用后,所有硬件操作(串口、CAN)将通过守护进程执行,\n"
+                                     "需要守护进程服务正在运行。\n"
+                                     "禁用后将使用本地模式直接操作硬件。");
+    connect(m_useDaemonCheckBox, &QCheckBox::toggled, 
+            this, &SettingsDialog::onDaemonModeChanged);
+    
+    m_daemonStatusLabel = new QLabel("状态:未知", m_daemonGroupBox);
+    m_daemonInfoLabel = new QLabel("提示:守护进程模式可以提供更好的资源管理和权限控制。", m_daemonGroupBox);
+    m_daemonInfoLabel->setWordWrap(true);
+    m_daemonInfoLabel->setStyleSheet("color: #666; font-size: 10pt;");
+    
+    daemonLayout->addWidget(m_useDaemonCheckBox);
+    daemonLayout->addWidget(m_daemonStatusLabel);
+    daemonLayout->addSpacing(10);
+    daemonLayout->addWidget(m_daemonInfoLabel);
+    daemonLayout->addStretch();
+    
+    m_mainLayout->addWidget(m_daemonGroupBox);
+    m_mainLayout->addStretch();
+    
+    // 按钮布局
+    m_buttonLayout = new QHBoxLayout();
+    m_buttonLayout->addStretch();
+    
+    m_applyButton = new QPushButton("应用", this);
+    m_okButton = new QPushButton("确定", this);
+    m_cancelButton = new QPushButton("取消", this);
+    
+    connect(m_applyButton, &QPushButton::clicked, this, &SettingsDialog::onApply);
+    connect(m_okButton, &QPushButton::clicked, this, &SettingsDialog::onOk);
+    connect(m_cancelButton, &QPushButton::clicked, this, &SettingsDialog::onCancel);
+    
+    m_buttonLayout->addWidget(m_applyButton);
+    m_buttonLayout->addWidget(m_okButton);
+    m_buttonLayout->addWidget(m_cancelButton);
+    
+    m_mainLayout->addLayout(m_buttonLayout);
+    
+    setLayout(m_mainLayout);
+}
+
+bool SettingsDialog::useDaemonMode() const
+{
+    return m_useDaemonMode;
+}
+
+void SettingsDialog::setUseDaemonMode(bool use)
+{
+    m_useDaemonMode = use;
+    if (m_useDaemonCheckBox) {
+        m_useDaemonCheckBox->setChecked(use);
+    }
+}
+
+void SettingsDialog::setDaemonClient(DaemonClient* daemonClient)
+{
+    m_daemonClient = daemonClient;
+    updateDaemonStatus();
+}
+
+void SettingsDialog::loadSettings()
+{
+    QSettings settings;
+    // 默认启用守护进程模式,提供更好的资源管理和权限控制
+    m_useDaemonMode = settings.value("daemon/useDaemonMode", true).toBool();
+    m_useDaemonCheckBox->setChecked(m_useDaemonMode);
+    updateDaemonStatus();
+}
+
+void SettingsDialog::saveSettings()
+{
+    QSettings settings;
+    settings.setValue("daemon/useDaemonMode", m_useDaemonMode);
+    settings.sync();
+}
+
+void SettingsDialog::onApply()
+{
+    m_useDaemonMode = m_useDaemonCheckBox->isChecked();
+    saveSettings();
+    updateDaemonStatus();
+    
+    QMessageBox::information(this, "提示", "设置已应用。\n"
+                             "注意:某些设置可能需要重启应用程序才能生效。");
+}
+
+void SettingsDialog::onOk()
+{
+    m_useDaemonMode = m_useDaemonCheckBox->isChecked();
+    saveSettings();
+    accept();
+}
+
+void SettingsDialog::onCancel()
+{
+    // 恢复原始设置
+    loadSettings();
+    reject();
+}
+
+void SettingsDialog::onDaemonModeChanged(bool enabled)
+{
+    updateDaemonStatus();
+}
+
+void SettingsDialog::updateDaemonStatus()
+{
+    bool useDaemon = m_useDaemonCheckBox->isChecked();
+    
+    if (useDaemon) {
+        // 检查守护进程是否真的在运行
+        bool daemonRunning = false;
+        if (m_daemonClient) {
+            daemonRunning = m_daemonClient->isDaemonRunning();
+        }
+        
+        if (daemonRunning) {
+            m_daemonStatusLabel->setText("状态:已启用 ✓ 守护进程服务正在运行");
+            m_daemonStatusLabel->setStyleSheet("color: green; font-weight: bold;");
+        } else {
+            m_daemonStatusLabel->setText("状态:已启用 ✗ 守护进程服务未运行(硬件操作将失败)");
+            m_daemonStatusLabel->setStyleSheet("color: red; font-weight: bold;");
+        }
+    } else {
+        m_daemonStatusLabel->setText("状态:已禁用(使用本地模式)");
+        m_daemonStatusLabel->setStyleSheet("color: #666;");
+    }
+}
+

+ 90 - 0
src/settings/settings_dialog.h

@@ -0,0 +1,90 @@
+/**
+ * @file settings_dialog.h
+ * @brief 设置对话框 - 应用程序设置界面
+ * 
+ * 功能:
+ * - 守护进程模式设置
+ * - 其他应用程序设置
+ */
+
+#ifndef SETTINGS_DIALOG_H
+#define SETTINGS_DIALOG_H
+
+#include <QDialog>
+
+class QCheckBox;
+class QLabel;
+class QPushButton;
+class QVBoxLayout;
+class QHBoxLayout;
+class QGroupBox;
+class DaemonClient;
+
+/**
+ * @brief 设置对话框
+ */
+class SettingsDialog : public QDialog
+{
+    Q_OBJECT
+
+public:
+    explicit SettingsDialog(QWidget *parent = nullptr);
+    ~SettingsDialog();
+
+    /**
+     * @brief 获取是否使用守护进程模式
+     */
+    bool useDaemonMode() const;
+
+    /**
+     * @brief 设置是否使用守护进程模式
+     */
+    void setUseDaemonMode(bool use);
+
+    /**
+     * @brief 设置守护进程客户端(用于检查守护进程状态)
+     */
+    void setDaemonClient(DaemonClient* daemonClient);
+
+    /**
+     * @brief 加载设置
+     */
+    void loadSettings();
+
+    /**
+     * @brief 保存设置
+     */
+    void saveSettings();
+
+private slots:
+    void onApply();
+    void onOk();
+    void onCancel();
+    void onDaemonModeChanged(bool enabled);
+
+private:
+    void createUI();
+    void updateDaemonStatus();
+
+    // UI 组件
+    QGroupBox *m_daemonGroupBox;
+    QCheckBox *m_useDaemonCheckBox;
+    QLabel *m_daemonStatusLabel;
+    QLabel *m_daemonInfoLabel;
+    
+    QPushButton *m_applyButton;
+    QPushButton *m_okButton;
+    QPushButton *m_cancelButton;
+    
+    QVBoxLayout *m_mainLayout;
+    QHBoxLayout *m_buttonLayout;
+    
+    // 设置值
+    bool m_useDaemonMode;
+    
+    // 守护进程客户端(用于检查状态)
+    DaemonClient* m_daemonClient;
+};
+
+#endif // SETTINGS_DIALOG_H
+

+ 62 - 62
src/soft_bus_core/soft_bus_core.cpp

@@ -1,7 +1,7 @@
 #include "soft_bus_core.h"
 #include <QByteArray>
 #include <QDateTime>
-#include <QDebug>
+#include "utils/logging.h"
 #include <QHashFunctions>
 #include <QJsonDocument>
 #include <QSqlError>
@@ -98,7 +98,7 @@ void DeviceBusCore::closeDB() {
 */
 void DeviceBusCore::registerDevice(const DeviceInfo &device) {
     if (m_devices.contains(device.id)) {
-        qWarning() << "Device" << device.id << "is already registered";
+        LOG_WARNING() << "Device" << device.id << "is already registered";
         return;
     }
 
@@ -163,11 +163,11 @@ void DeviceBusCore::registerDevice(const DeviceInfo &device) {
         upsertDeviceRecord(normalizedDevice, normalizedDevice.lastSeen);
         if (!normalizedDevice.portname.isEmpty()) {
             if (!ensurePerPortRawTable(normalizedDevice.portname)) {
-                qCritical() << "Failed to ensure raw data table for port"
+                LOG_CRITICAL() << "Failed to ensure raw data table for port"
                             << normalizedDevice.portname;
             }
             if (!ensurePerPortTransformedTable(normalizedDevice.portname)) {
-                qCritical() << "Failed to ensure transformed data table for port"
+                LOG_CRITICAL() << "Failed to ensure transformed data table for port"
                             << normalizedDevice.portname;
             }
         }
@@ -190,7 +190,7 @@ bool DeviceBusCore::fetchPersistedDeviceByPort(const QString &portName,
         "FROM devices WHERE port_name = :port_name LIMIT 1"));
     query.bindValue(QStringLiteral(":port_name"), portName);
     if (!query.exec()) {
-        qCritical() << "Failed to query persisted device for port" << portName
+        LOG_CRITICAL() << "Failed to query persisted device for port" << portName
                     << ":" << query.lastError().text();
         return false;
     }
@@ -248,7 +248,7 @@ bool DeviceBusCore::fetchPersistedDeviceByPort(const QString &portName,
 */
 void DeviceBusCore::updateDevice(const DeviceInfo &device) {
     if (!m_devices.contains(device.id)) {
-        qWarning() << "Device" << device.id << "is not registered";
+        LOG_WARNING() << "Device" << device.id << "is not registered";
         return;
     }
 
@@ -282,11 +282,11 @@ void DeviceBusCore::updateDevice(const DeviceInfo &device) {
         upsertDeviceRecord(updatedDevice, updatedDevice.lastSeen);
         if (!updatedDevice.portname.isEmpty()) {
             if (!ensurePerPortRawTable(updatedDevice.portname)) {
-                qCritical() << "Failed to ensure raw data table for port"
+                LOG_CRITICAL() << "Failed to ensure raw data table for port"
                             << updatedDevice.portname;
             }
             if (!ensurePerPortTransformedTable(updatedDevice.portname)) {
-                qCritical() << "Failed to ensure transformed data table for port"
+                LOG_CRITICAL() << "Failed to ensure transformed data table for port"
                             << updatedDevice.portname;
             }
         }
@@ -297,13 +297,13 @@ void DeviceBusCore::updateDevice(const DeviceInfo &device) {
 
 void DeviceBusCore::markDeviceOffline(int deviceId) {
     if (deviceId <= 0) {
-        qWarning() << "Invalid device id when marking offline";
+        LOG_WARNING() << "Invalid device id when marking offline";
         return;
     }
 
     const bool tracked = m_devices.contains(deviceId);
     if (!tracked) {
-        qWarning() << "Device" << deviceId
+        LOG_WARNING() << "Device" << deviceId
                    << "not tracked in memory when marking offline";
         if (m_dbInitialized) {
             markDeviceInactive(deviceId);
@@ -317,12 +317,12 @@ void DeviceBusCore::markDeviceOffline(int deviceId) {
 
 void DeviceBusCore::markDeviceOfflineByPort(const QString &portname) {
     if (portname.isEmpty()) {
-        qWarning() << "Empty port name when marking device offline";
+        LOG_WARNING() << "Empty port name when marking device offline";
         return;
     }
 
     if (!m_portnameToId.contains(portname)) {
-        qWarning() << "No registered device found for port" << portname
+        LOG_WARNING() << "No registered device found for port" << portname
                    << "when marking offline";
         return;
     }
@@ -334,12 +334,12 @@ void DeviceBusCore::markDeviceOfflineByPort(const QString &portname) {
 void DeviceBusCore::updateDeviceStatus(int deviceId, const QString &status,
                                      bool isActive, const QDateTime &lastSeen) {
     if (deviceId <= 0) {
-        qWarning() << "Invalid device id when updating status";
+        LOG_WARNING() << "Invalid device id when updating status";
         return;
     }
 
     if (!m_devices.contains(deviceId)) {
-        qWarning() << "Device" << deviceId
+        LOG_WARNING() << "Device" << deviceId
                    << "not tracked in memory when updating status";
         return;
     }
@@ -368,12 +368,12 @@ void DeviceBusCore::updateDeviceStatusByPort(const QString &portname,
                                            const QString &status, bool isActive,
                                            const QDateTime &lastSeen) {
     if (portname.isEmpty()) {
-        qWarning() << "Empty port name when updating device status";
+        LOG_WARNING() << "Empty port name when updating device status";
         return;
     }
 
     if (!m_portnameToId.contains(portname)) {
-        qWarning() << "No registered device found for port" << portname
+        LOG_WARNING() << "No registered device found for port" << portname
                    << "when updating status";
         return;
     }
@@ -398,7 +398,7 @@ void DeviceBusCore::updateDeviceStatusByPort(const QString &portname,
 */
 void DeviceBusCore::unregisterDevice(int deviceId) {
     if (!m_devices.contains(deviceId)) {
-        qWarning() << "Device" << deviceId << "is not registered";
+        LOG_WARNING() << "Device" << deviceId << "is not registered";
         return;
     }
 
@@ -495,7 +495,7 @@ void DeviceBusCore::routeMessage(const BusMessage &message) {
 */
 void DeviceBusCore::storeRawData(int deviceId, const QByteArray &data) {
     if (!m_dbInitialized || !m_db.isValid() || !m_db.isOpen()) {
-        qWarning() << "Database not initialized for storing raw data";
+        LOG_WARNING() << "Database not initialized for storing raw data";
         return;
     }
 
@@ -509,7 +509,7 @@ void DeviceBusCore::storeRawData(int deviceId, const QByteArray &data) {
 
     // 确认端口对应的原始数据表已创建
     if (!ensurePerPortRawTable(portName)) {
-        qCritical() << "Failed to ensure port-specific raw data table for"
+        LOG_CRITICAL() << "Failed to ensure port-specific raw data table for"
                     << portName;
         return;
     }
@@ -551,7 +551,7 @@ void DeviceBusCore::storeRawData(int deviceId, const QByteArray &data) {
 
     if (!query.exec()) {
         const QString errorText = query.lastError().text();
-        qCritical() << "Failed to store raw data:" << errorText;
+        LOG_CRITICAL() << "Failed to store raw data:" << errorText;
         emit databaseError(errorText);
         return;
     }
@@ -578,7 +578,7 @@ void DeviceBusCore::storeRawData(int deviceId, const QByteArray &data) {
 */
 void DeviceBusCore::storeBusMessage(const BusMessage &message) {
     if (!m_dbInitialized || !m_db.isValid() || !m_db.isOpen()) {
-        qWarning() << "Database not initialized for storing bus message";
+        LOG_WARNING() << "Database not initialized for storing bus message";
         return;
     }
 
@@ -608,7 +608,7 @@ void DeviceBusCore::storeBusMessage(const BusMessage &message) {
 
     if (!query.exec()) {
         const QString errorText = query.lastError().text();
-        qCritical() << "Failed to store bus message:" << errorText;
+        LOG_CRITICAL() << "Failed to store bus message:" << errorText;
         emit databaseError(errorText);
         return;
     }
@@ -617,7 +617,7 @@ void DeviceBusCore::storeBusMessage(const BusMessage &message) {
     if (!resolvedPort.isEmpty()) {
         // 若识别出端口,则额外写入该端口对应的转化数据表
         if (!ensurePerPortTransformedTable(resolvedPort)) {
-            qCritical() << "Failed to ensure transformed data table for port"
+            LOG_CRITICAL() << "Failed to ensure transformed data table for port"
                         << resolvedPort;
         } else {
             const QString tableIdentifier =
@@ -684,7 +684,7 @@ void DeviceBusCore::storeBusMessage(const BusMessage &message) {
 
             if (!transformedQuery.exec()) {
                 const QString errorText = transformedQuery.lastError().text();
-                qCritical() << "Failed to store transformed bus data:" << errorText;
+                LOG_CRITICAL() << "Failed to store transformed bus data:" << errorText;
                 emit databaseError(errorText);
             } else if (knownDevice) {
                 upsertDeviceRecord(deviceInfo, messageTime);
@@ -700,7 +700,7 @@ QList<QByteArray> DeviceBusCore::queryRawData(int deviceId, qint64 startTime,
     QList<QByteArray> results;
 
     if (!m_dbInitialized || !m_db.isValid() || !m_db.isOpen()) {
-        qWarning() << "Database not initialized for querying raw data";
+        LOG_WARNING() << "Database not initialized for querying raw data";
         return results;
     }
 
@@ -718,7 +718,7 @@ QList<QByteArray> DeviceBusCore::queryRawData(int deviceId, qint64 startTime,
 
     // 查询前确保端口数据表存在
     if (!ensurePerPortRawTable(portName)) {
-        qCritical() << "Failed to ensure raw data table when querying port"
+        LOG_CRITICAL() << "Failed to ensure raw data table when querying port"
                     << portName;
         return results;
     }
@@ -747,7 +747,7 @@ QList<QByteArray> DeviceBusCore::queryRawData(int deviceId, qint64 startTime,
 
     if (!query.exec()) {
         const QString errorText = query.lastError().text();
-        qCritical() << "Failed to query raw data:" << errorText;
+        LOG_CRITICAL() << "Failed to query raw data:" << errorText;
         emit databaseError(errorText);
         return results;
     }
@@ -766,7 +766,7 @@ QList<BusMessage> DeviceBusCore::queryBusMessages(const QString &source,
     QList<BusMessage> results;
 
     if (!m_dbInitialized || !m_db.isValid() || !m_db.isOpen()) {
-        qWarning() << "Database not initialized for querying bus messages";
+        LOG_WARNING() << "Database not initialized for querying bus messages";
         return results;
     }
 
@@ -800,7 +800,7 @@ QList<BusMessage> DeviceBusCore::queryBusMessages(const QString &source,
 
     if (!query.exec()) {
         const QString errorText = query.lastError().text();
-        qCritical() << "Failed to query bus messages:" << errorText;
+        LOG_CRITICAL() << "Failed to query bus messages:" << errorText;
         emit databaseError(errorText);
         return results;
     }
@@ -818,7 +818,7 @@ QList<BusMessage> DeviceBusCore::queryBusMessages(const QString &source,
             if (doc.isObject()) {
                 message.payload = doc.object();
             } else {
-                qWarning() << "Invalid payload JSON for message" << message.id;
+                LOG_WARNING() << "Invalid payload JSON for message" << message.id;
             }
         }
 
@@ -853,7 +853,7 @@ bool DeviceBusCore::ensureRawTable() {
                        ")");
 
     if (!query.exec(createTemplateSql)) {
-        qCritical() << "Failed to create raw_data_template table:"
+        LOG_CRITICAL() << "Failed to create raw_data_template table:"
                     << query.lastError().text();
         return false;
     }
@@ -868,7 +868,7 @@ bool DeviceBusCore::ensureRawTable() {
                        ")");
 
     if (!query.exec(createRegistrySql)) {
-        qCritical() << "Failed to create raw_data_registry table:"
+        LOG_CRITICAL() << "Failed to create raw_data_registry table:"
                     << query.lastError().text();
         return false;
     }
@@ -876,7 +876,7 @@ bool DeviceBusCore::ensureRawTable() {
     if (!query.exec(QStringLiteral(
             "CREATE INDEX IF NOT EXISTS idx_raw_data_registry_table "
             "ON raw_data_registry (table_name)"))) {
-        qCritical() << "Failed to create raw_data_registry index:"
+        LOG_CRITICAL() << "Failed to create raw_data_registry index:"
                     << query.lastError().text();
         return false;
     }
@@ -903,7 +903,7 @@ bool DeviceBusCore::ensureBusTable() {
                        ")");
 
     if (!query.exec(createTableSql)) {
-        qCritical() << "Failed to create bus_messages table:"
+        LOG_CRITICAL() << "Failed to create bus_messages table:"
                     << query.lastError().text();
         return false;
     }
@@ -911,7 +911,7 @@ bool DeviceBusCore::ensureBusTable() {
     // 兼容已有实例:确保扩展列存在
     if (!query.exec(QStringLiteral("ALTER TABLE bus_messages ADD COLUMN IF NOT "
                                    "EXISTS metadata JSONB"))) {
-        qCritical() << "Failed to ensure bus_messages metadata column:"
+        LOG_CRITICAL() << "Failed to ensure bus_messages metadata column:"
                     << query.lastError().text();
         return false;
     }
@@ -919,7 +919,7 @@ bool DeviceBusCore::ensureBusTable() {
     if (!query.exec(
             QStringLiteral("ALTER TABLE bus_messages ADD COLUMN IF NOT EXISTS "
                            "created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()"))) {
-        qCritical() << "Failed to ensure bus_messages created_at column:"
+        LOG_CRITICAL() << "Failed to ensure bus_messages created_at column:"
                     << query.lastError().text();
         return false;
     }
@@ -927,7 +927,7 @@ bool DeviceBusCore::ensureBusTable() {
     if (!query.exec(QStringLiteral(
             "CREATE INDEX IF NOT EXISTS idx_bus_messages_source_dest_ts "
             "ON bus_messages (source, destination, ts)"))) {
-        qCritical() << "Failed to create bus_messages index:"
+        LOG_CRITICAL() << "Failed to create bus_messages index:"
                     << query.lastError().text();
         return false;
     }
@@ -935,7 +935,7 @@ bool DeviceBusCore::ensureBusTable() {
     if (!query.exec(
             QStringLiteral("CREATE INDEX IF NOT EXISTS idx_bus_messages_ts "
                            "ON bus_messages (ts)"))) {
-        qCritical() << "Failed to create bus_messages timestamp index:"
+        LOG_CRITICAL() << "Failed to create bus_messages timestamp index:"
                     << query.lastError().text();
         return false;
     }
@@ -959,7 +959,7 @@ bool DeviceBusCore::ensureBusTable() {
                        ")");
 
     if (!query.exec(transformedTemplateSql)) {
-        qCritical() << "Failed to create transformed_data_template table:"
+        LOG_CRITICAL() << "Failed to create transformed_data_template table:"
                     << query.lastError().text();
         return false;
     }
@@ -974,7 +974,7 @@ bool DeviceBusCore::ensureBusTable() {
                        ")");
 
     if (!query.exec(transformedRegistrySql)) {
-        qCritical() << "Failed to create transformed_data_registry table:"
+        LOG_CRITICAL() << "Failed to create transformed_data_registry table:"
                     << query.lastError().text();
         return false;
     }
@@ -982,7 +982,7 @@ bool DeviceBusCore::ensureBusTable() {
     if (!query.exec(QStringLiteral(
             "CREATE INDEX IF NOT EXISTS idx_transformed_data_registry_table "
             "ON transformed_data_registry (table_name)"))) {
-        qCritical() << "Failed to create transformed_data_registry index:"
+        LOG_CRITICAL() << "Failed to create transformed_data_registry index:"
                     << query.lastError().text();
         return false;
     }
@@ -1006,7 +1006,7 @@ bool DeviceBusCore::ensureBusTable() {
                        ")");
 
     if (!query.exec(devicesSql)) {
-        qCritical() << "Failed to create devices table:"
+        LOG_CRITICAL() << "Failed to create devices table:"
                     << query.lastError().text();
         return false;
     }
@@ -1016,7 +1016,7 @@ bool DeviceBusCore::ensureBusTable() {
                        "devices (port_name)");
 
     if (!query.exec(devicePortIndexSql)) {
-        qCritical() << "Failed to create devices port index:"
+        LOG_CRITICAL() << "Failed to create devices port index:"
                     << query.lastError().text();
         return false;
     }
@@ -1037,7 +1037,7 @@ bool DeviceBusCore::ensureBusTable() {
         ")");
 
     if (!query.exec(deviceParametersSql)) {
-        qCritical() << "Failed to create device_parameters table:"
+        LOG_CRITICAL() << "Failed to create device_parameters table:"
                     << query.lastError().text();
         return false;
     }
@@ -1045,7 +1045,7 @@ bool DeviceBusCore::ensureBusTable() {
     if (!query.exec(QStringLiteral(
             "CREATE INDEX IF NOT EXISTS idx_device_parameters_device "
             "ON device_parameters (device_id)"))) {
-        qCritical() << "Failed to create device_parameters index:"
+        LOG_CRITICAL() << "Failed to create device_parameters index:"
                     << query.lastError().text();
         return false;
     }
@@ -1063,7 +1063,7 @@ bool DeviceBusCore::ensureBusTable() {
                        ")");
 
     if (!query.exec(systemLogsSql)) {
-        qCritical() << "Failed to create system_logs table:"
+        LOG_CRITICAL() << "Failed to create system_logs table:"
                     << query.lastError().text();
         return false;
     }
@@ -1071,7 +1071,7 @@ bool DeviceBusCore::ensureBusTable() {
     if (!query.exec(
             QStringLiteral("CREATE INDEX IF NOT EXISTS idx_system_logs_category "
                            "ON system_logs (category)"))) {
-        qCritical() << "Failed to create system_logs category index:"
+        LOG_CRITICAL() << "Failed to create system_logs category index:"
                     << query.lastError().text();
         return false;
     }
@@ -1079,7 +1079,7 @@ bool DeviceBusCore::ensureBusTable() {
     if (!query.exec(QStringLiteral(
             "CREATE INDEX IF NOT EXISTS idx_system_logs_created_at "
             "ON system_logs (created_at)"))) {
-        qCritical() << "Failed to create system_logs timestamp index:"
+        LOG_CRITICAL() << "Failed to create system_logs timestamp index:"
                     << query.lastError().text();
         return false;
     }
@@ -1164,7 +1164,7 @@ bool DeviceBusCore::initializeDatabase(QSqlDatabase &db,
                     const QSqlError createError = maintenanceQuery.lastError();
                     if (createError.nativeErrorCode() !=
                         QLatin1String("42P04")) { // duplicate_database
-                        qCritical() << "Failed to create database" << databaseName << ":"
+                        LOG_CRITICAL() << "Failed to create database" << databaseName << ":"
                                     << createError.text();
                         maintenanceDb.close();
                         maintenanceDb = QSqlDatabase();
@@ -1174,7 +1174,7 @@ bool DeviceBusCore::initializeDatabase(QSqlDatabase &db,
                 }
                 maintenanceDb.close();
             } else {
-                qCritical() << "Failed to open maintenance database"
+                LOG_CRITICAL() << "Failed to open maintenance database"
                             << maintenanceDbName << ":"
                             << maintenanceDb.lastError().text();
                 maintenanceDb = QSqlDatabase();
@@ -1186,12 +1186,12 @@ bool DeviceBusCore::initializeDatabase(QSqlDatabase &db,
             QSqlDatabase::removeDatabase(maintenanceConnection);
 
             if (!db.open()) {
-                qCritical() << "Failed to reopen PostgreSQL database" << databaseName
+                LOG_CRITICAL() << "Failed to reopen PostgreSQL database" << databaseName
                             << ":" << db.lastError().text();
                 return false;
             }
         } else {
-            qCritical() << "Failed to open PostgreSQL database" << databaseName << ":"
+            LOG_CRITICAL() << "Failed to open PostgreSQL database" << databaseName << ":"
                         << initialError.text();
             return false;
         }
@@ -1214,7 +1214,7 @@ bool DeviceBusCore::ensurePerPortRawTable(const QString &portName) {
     if (!query.exec(QStringLiteral("CREATE TABLE IF NOT EXISTS %1 (LIKE "
                                    "raw_data_template INCLUDING ALL)")
                         .arg(quotedTable))) {
-        qCritical() << "Failed to create raw data table" << tableName << ":"
+        LOG_CRITICAL() << "Failed to create raw data table" << tableName << ":"
                     << query.lastError().text();
         return false;
     }
@@ -1231,7 +1231,7 @@ bool DeviceBusCore::ensurePerPortRawTable(const QString &portName) {
             QStringLiteral(
                 "CREATE INDEX IF NOT EXISTS %1 ON %2 (device_id, created_at)")
                 .arg(deviceCreatedIndex, quotedTable))) {
-        qCritical() << "Failed to create device_created index for" << tableName
+        LOG_CRITICAL() << "Failed to create device_created index for" << tableName
                     << ":" << query.lastError().text();
         return false;
     }
@@ -1241,7 +1241,7 @@ bool DeviceBusCore::ensurePerPortRawTable(const QString &portName) {
     if (!query.exec(
             QStringLiteral("CREATE INDEX IF NOT EXISTS %1 ON %2 (created_at)")
                 .arg(createdIndex, quotedTable))) {
-        qCritical() << "Failed to create created_at index for" << tableName << ":"
+        LOG_CRITICAL() << "Failed to create created_at index for" << tableName << ":"
                     << query.lastError().text();
         return false;
     }
@@ -1257,7 +1257,7 @@ bool DeviceBusCore::ensurePerPortRawTable(const QString &portName) {
     registryQuery.bindValue(QStringLiteral(":table_name"), tableName);
 
     if (!registryQuery.exec()) {
-        qCritical() << "Failed to upsert raw_data_registry for" << portName << ":"
+        LOG_CRITICAL() << "Failed to upsert raw_data_registry for" << portName << ":"
                     << registryQuery.lastError().text();
         return false;
     }
@@ -1279,7 +1279,7 @@ bool DeviceBusCore::ensurePerPortTransformedTable(const QString &portName) {
     if (!query.exec(QStringLiteral("CREATE TABLE IF NOT EXISTS %1 (LIKE "
                                    "transformed_data_template INCLUDING ALL)")
                         .arg(quotedTable))) {
-        qCritical() << "Failed to create transformed data table" << tableName << ":"
+        LOG_CRITICAL() << "Failed to create transformed data table" << tableName << ":"
                     << query.lastError().text();
         return false;
     }
@@ -1295,7 +1295,7 @@ bool DeviceBusCore::ensurePerPortTransformedTable(const QString &portName) {
             QStringLiteral(
                 "CREATE INDEX IF NOT EXISTS %1 ON %2 (device_id, created_at)")
                 .arg(deviceCreatedIndex, quotedTable))) {
-        qCritical() << "Failed to create transformed device index for" << tableName
+        LOG_CRITICAL() << "Failed to create transformed device index for" << tableName
                     << ":" << query.lastError().text();
         return false;
     }
@@ -1305,7 +1305,7 @@ bool DeviceBusCore::ensurePerPortTransformedTable(const QString &portName) {
     if (!query.exec(
             QStringLiteral("CREATE INDEX IF NOT EXISTS %1 ON %2 (created_at)")
                 .arg(createdIndex, quotedTable))) {
-        qCritical() << "Failed to create transformed created_at index for"
+        LOG_CRITICAL() << "Failed to create transformed created_at index for"
                     << tableName << ":" << query.lastError().text();
         return false;
     }
@@ -1321,7 +1321,7 @@ bool DeviceBusCore::ensurePerPortTransformedTable(const QString &portName) {
     registryQuery.bindValue(QStringLiteral(":table_name"), tableName);
 
     if (!registryQuery.exec()) {
-        qCritical() << "Failed to upsert transformed_data_registry for" << portName
+        LOG_CRITICAL() << "Failed to upsert transformed_data_registry for" << portName
                     << ":" << registryQuery.lastError().text();
         return false;
     }
@@ -1383,7 +1383,7 @@ void DeviceBusCore::upsertDeviceRecord(const DeviceInfo &device,
 
     if (!query.exec()) {
         const QString errorText = query.lastError().text();
-        qCritical() << "Failed to upsert device record:" << errorText;
+        LOG_CRITICAL() << "Failed to upsert device record:" << errorText;
         emit databaseError(errorText);
     }
 }
@@ -1402,7 +1402,7 @@ void DeviceBusCore::markDeviceInactive(int deviceId) {
 
     if (!query.exec()) {
         const QString errorText = query.lastError().text();
-        qCritical() << "Failed to mark device inactive:" << errorText;
+        LOG_CRITICAL() << "Failed to mark device inactive:" << errorText;
         emit databaseError(errorText);
     }
 }

+ 21 - 0
src/soft_bus_core/soft_bus_core.h

@@ -12,6 +12,7 @@
 #define SOFT_BUS_CORE_H
 
 #include <QDateTime>
+#include <QJsonDocument>
 #include <QJsonObject>
 #include <QList>
 #include <QMap>
@@ -48,6 +49,26 @@ struct DeviceInfo {
         protocol(protocol), protocol_detail(protocol_detail),
         properties(properties), status(status), isActive(isActive),
         lastSeen(lastSeen) {}
+
+  // 转换为 JSON 字符串
+  QString toJson() const {
+    QJsonObject obj;
+    obj[QStringLiteral("id")] = id;
+    obj[QStringLiteral("portname")] = portname;
+    obj[QStringLiteral("name")] = name;
+    obj[QStringLiteral("type")] = type;
+    obj[QStringLiteral("address")] = address;
+    obj[QStringLiteral("protocol")] = protocol;
+    obj[QStringLiteral("protocol_detail")] = protocol_detail;
+    obj[QStringLiteral("properties")] = properties;
+    obj[QStringLiteral("status")] = status;
+    obj[QStringLiteral("isActive")] = isActive;
+    if (lastSeen.isValid()) {
+      obj[QStringLiteral("lastSeen")] = lastSeen.toString(Qt::ISODate);
+    }
+    QJsonDocument doc(obj);
+    return QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
+  }
 };
 
 // 软总线消息结构

+ 23 - 0
src/utils/logging.h

@@ -0,0 +1,23 @@
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#include <QDebug>
+#include <QLoggingCategory>
+#include <cstring>
+
+/**
+ * @file logging.h
+ * @brief 日志宏定义,提供带文件名和函数名的日志输出
+ */
+
+// 获取文件名(不含路径)
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+// 日志宏,格式:[文件名.函数名] 消息
+#define LOG_DEBUG() qDebug() << "[" << __FILENAME__ << "." << __FUNCTION__ << "]"
+#define LOG_INFO() qInfo() << "[" << __FILENAME__ << "." << __FUNCTION__ << "]"
+#define LOG_WARNING() qWarning() << "[" << __FILENAME__ << "." << __FUNCTION__ << "]"
+#define LOG_CRITICAL() qCritical() << "[" << __FILENAME__ << "." << __FUNCTION__ << "]"
+
+#endif // LOGGING_H
+

+ 46 - 28
src/view_can/viewcan.cpp

@@ -1,12 +1,13 @@
 #include "viewcan.h"
 #include "ui_viewcan.h"
 #include "device_config/device_tree_widget.h"
+#include "device_config/device_log_dialog.h"
 #include "can_data_widget.h"
 #include "message_viewer/raw_data_table_widget.h"
 #include "message_viewer/bus_data_table_widget.h"
 #include "api/SoftBusAPI.h"
 #include "core/CoreService.h"
-#include <QDebug>
+#include "utils/logging.h"
 #include <QTimer>
 
 ViewCan::ViewCan(QWidget *parent)
@@ -25,7 +26,7 @@ ViewCan::ViewCan(QWidget *parent)
     if (coreService->isInitialized()) {
         m_busCore = coreService->getDeviceBusCore();
     } else {
-        qWarning() << "CoreService not initialized in ViewCan";
+        LOG_WARNING() << "CoreService not initialized in ViewCan";
     }
     
     // 先初始化系统
@@ -37,12 +38,11 @@ ViewCan::ViewCan(QWidget *parent)
     // 创建连接
     createConnections();
     
-    // 启动设备发现(立即执行一次,然后每5秒扫描一次)
-    SoftBusAPI *api = SoftBusAPI::instance();
-    api->startDeviceDiscovery(5000);
+    // 注意:设备扫描由 MainWindow 统一管理,在守护进程连接成功或本地模式时启动
+    // 这里不再立即启动设备扫描,避免在守护进程未连接时就开始扫描
     
-    // 延迟一小段时间后更新设备列表,确保设备发现完成
-    QTimer::singleShot(100, this, [this]() {
+    // 延迟一小段时间后更新设备列表(等待设备扫描启动)
+    QTimer::singleShot(500, this, [this]() {
         if (m_deviceTreeWidget) {
             m_deviceTreeWidget->updateDeviceList();
         }
@@ -55,6 +55,14 @@ ViewCan::~ViewCan()
     SoftBusAPI *api = SoftBusAPI::instance();
     api->stopDeviceDiscovery();
     
+    // 清理设备日志对话框
+    for (auto it = m_deviceLogDialogs.begin(); it != m_deviceLogDialogs.end(); ++it) {
+        if (it.value()) {
+            it.value()->deleteLater();
+        }
+    }
+    m_deviceLogDialogs.clear();
+    
     delete ui;
 }
 
@@ -64,38 +72,27 @@ void ViewCan::initializeSystem()
     CoreService* coreService = CoreService::instance();
     if (!coreService->isInitialized()) {
         if (!coreService->initialize()) {
-            qCritical() << "Failed to initialize CoreService";
+            LOG_CRITICAL() << "Failed to initialize CoreService";
             return;
         }
         m_busCore = coreService->getDeviceBusCore();
     }
     
     if (!m_busCore) {
-        qCritical() << "DeviceBusCore is null";
+        LOG_CRITICAL() << "DeviceBusCore is null";
         return;
     }
     
     // 初始化API(API内部会创建Manager)
     SoftBusAPI *api = SoftBusAPI::instance();
     if (!api->initialize()) {
-        qWarning() << "Failed to initialize SoftBusAPI";
+        LOG_WARNING() << "Failed to initialize SoftBusAPI";
         return;
     }
     
-    // 注册一些示例设备(使用API获取设备列表)
-    QList<int> availableDevices = api->getAvailableCanDevices();
-    static int deviceIdCounter = 1000; // CAN设备ID从1000开始,避免与串口设备冲突
-    for (int comPort : availableDevices)
-    {
-        DeviceInfo device;
-        device.id = deviceIdCounter++;
-        device.portname = QString("CAN_%1").arg(comPort);
-        device.name = "CAN设备: " + device.portname;
-        device.type = "can";
-        device.protocol = "can";
-        device.protocol_detail = "can-2.0";
-        m_busCore->registerDevice(device);
-    }
+    // 注意:设备注册应该由守护进程或设备扫描负责,而不是在这里立即注册
+    // 在守护进程模式下,设备由守护进程注册;在本地模式下,设备由设备扫描注册
+    // 这里不再立即注册设备,避免在守护进程未连接时就在本地模式注册设备
 }
 
 void ViewCan::createUI()
@@ -110,7 +107,7 @@ void ViewCan::createUI()
     // 使用 SoftBusAPI 统一接口
     SoftBusAPI *api = SoftBusAPI::instance();
     if (!api->initialize()) {
-        qWarning() << "Failed to initialize SoftBusAPI";
+        LOG_WARNING() << "Failed to initialize SoftBusAPI";
     }
     
     m_deviceTreeWidget->setAPI(api);
@@ -150,19 +147,19 @@ void ViewCan::onDeviceSelected(const QString &deviceType, const QString &deviceI
     if (deviceType == "can") {
         device = m_busCore->getDeviceInfoByPortname(deviceId);
     } else {
-        qWarning() << "暂不支持设备类型:" << deviceType;
+        LOG_WARNING() << "暂不支持设备类型:" << deviceType;
         return;
     }
     
     if (device.id == 0) {
-        qWarning() << "设备未找到,类型:" << deviceType << ", ID:" << deviceId;
+        LOG_WARNING() << "设备未找到,类型:" << deviceType << ", ID:" << deviceId;
         return;
     }
     
     m_currentDeviceId = device.id;
     m_currentDeviceName = deviceId; // 对于CAN,deviceId就是设备名称
     
-    qDebug() << "设备被选择: 类型=" << deviceType << ", ID=" << device.id << ", 设备名=" << deviceId;
+    LOG_DEBUG() << "设备被选择: 类型=" << deviceType << ", ID=" << device.id << ", 设备名=" << deviceId;
     
     // 如果是CAN设备,打开设备
     if (deviceType == "can") {
@@ -183,6 +180,27 @@ void ViewCan::onDeviceSelected(const QString &deviceType, const QString &deviceI
     m_canDataWidget->setCurrentDeviceId(deviceId);
     m_rawDataTableWidget->showRawData(device.id);
     m_busDataTableWidget->showBusMessages(device.id);
+    
+    // 打开设备日志对话框
+    DeviceLogDialog* logDialog = nullptr;
+    if (m_deviceLogDialogs.contains(device.id)) {
+        logDialog = m_deviceLogDialogs[device.id];
+        // 如果对话框已关闭,重新创建
+        if (!logDialog || !logDialog->isVisible()) {
+            logDialog = new DeviceLogDialog(this);
+            m_deviceLogDialogs[device.id] = logDialog;
+        }
+    } else {
+        logDialog = new DeviceLogDialog(this);
+        m_deviceLogDialogs[device.id] = logDialog;
+    }
+    
+    if (logDialog) {
+        logDialog->setDeviceInfo(device, m_busCore);
+        logDialog->show();
+        logDialog->raise();
+        logDialog->activateWindow();
+    }
 }
 
 void ViewCan::onBusMessageStored(const BusMessage &message)

+ 5 - 0
src/view_can/viewcan.h

@@ -13,11 +13,13 @@
 #define VIEWCAN_H
 
 #include <QWidget>
+#include <QMap>
 #include "my_dock_manager/mdockmanager.h"
 #include "soft_bus_core/soft_bus_core.h"
 
 // 前向声明各个模块化组件
 class DeviceTreeWidget;
+class DeviceLogDialog;
 class CanDataWidget;
 class RawDataTableWidget;
 class BusDataTableWidget;
@@ -61,6 +63,9 @@ private:
     
     int m_currentDeviceId;     // 当前选择的设备ID(数字)
     QString m_currentDeviceName;  // 当前选择的设备名称(界面显示用)
+    
+    // 设备日志对话框映射(每个设备一个对话框)
+    QMap<int, DeviceLogDialog*> m_deviceLogDialogs;
 };
 
 #endif // VIEWCAN_H

+ 2 - 1
src/view_serial/serial_data_widget.cpp

@@ -1,6 +1,7 @@
 #include "serial_data_widget.h"
 #include "ui_serial_data_widget.h"
 #include "api/SoftBusAPI.h"
+#include "utils/logging.h"
 #include <QMessageBox>
 #include <QDateTime>
 #include <QSerialPortInfo>
@@ -182,7 +183,7 @@ void SerialDataWidget::on_btn_serial_detect_clicked()
 
         // 转换为字节数组(使用Latin1编码,确保单字节字符,避免UTF-8多字节编码导致的乱码)
         QByteArray dataToWrite = detectMessage.toLatin1();
-        qDebug() << "serial_detect: " << dataToWrite.toHex() << "(" << dataToWrite << ")";
+        LOG_DEBUG() << "serial_detect: " << dataToWrite.toHex() << "(" << dataToWrite << ")";
         
         // 发送检测信息
         if (m_api->sendSerialData(portName, dataToWrite))

+ 47 - 33
src/view_serial/serialdockpage.cpp

@@ -1,6 +1,7 @@
 #include "serialdockpage.h"
 
 #include "device_config/device_tree_widget.h"
+#include "device_config/device_log_dialog.h"
 #include "libmodbus/modbus_config_widget.h"
 #include "message_viewer/bus_data_table_widget.h"
 #include "message_viewer/raw_data_table_widget.h"
@@ -9,9 +10,9 @@
 #include "soft_bus_core/soft_bus_core.h"
 #include "api/SoftBusAPI.h"
 #include "core/CoreService.h"
-
-#include <QDebug>
+#include "utils/logging.h"
 #include <QSerialPortInfo>
+#include <QMap>
 
 SerialDockPage::SerialDockPage(QWidget *parent)
     : MDockManager(parent)
@@ -31,7 +32,7 @@ SerialDockPage::SerialDockPage(QWidget *parent)
     if (coreService->isInitialized()) {
         m_busCore = coreService->getDeviceBusCore();
     } else {
-        qWarning() << "CoreService not initialized in SerialDockPage";
+        LOG_WARNING() << "CoreService not initialized in SerialDockPage";
     }
     
     initializeSystem();
@@ -39,15 +40,22 @@ SerialDockPage::SerialDockPage(QWidget *parent)
     createConnections();
     captureDefaultLayout();
     
-    // 启动设备发现
-    SoftBusAPI *api = SoftBusAPI::instance();
-    api->startDeviceDiscovery(5000);
+    // 注意:设备扫描由 MainWindow 统一管理,在守护进程连接成功或本地模式时启动
+    // 这里不再立即启动设备扫描,避免在守护进程未连接时就开始扫描
 }
 
 SerialDockPage::~SerialDockPage()
 {
     SoftBusAPI *api = SoftBusAPI::instance();
     api->stopDeviceDiscovery();
+    
+    // 清理设备日志对话框
+    for (auto it = m_deviceLogDialogs.begin(); it != m_deviceLogDialogs.end(); ++it) {
+        if (it.value()) {
+            it.value()->deleteLater();
+        }
+    }
+    m_deviceLogDialogs.clear();
 }
 
 void SerialDockPage::resetLayout()
@@ -79,39 +87,22 @@ void SerialDockPage::initializeSystem()
     CoreService* coreService = CoreService::instance();
     if (!coreService->isInitialized()) {
         if (!coreService->initialize()) {
-            qCritical() << "Failed to initialize CoreService";
+            LOG_CRITICAL() << "Failed to initialize CoreService";
             return;
         }
         m_busCore = coreService->getDeviceBusCore();
     }
     
     if (!m_busCore) {
-        qCritical() << "DeviceBusCore is null";
+        LOG_CRITICAL() << "DeviceBusCore is null";
         return;
     }
     
     // 数据库已由 CoreService 初始化,无需再次初始化
 
-    // 初始化API(API内部会创建Manager)
-    SoftBusAPI *api = SoftBusAPI::instance();
-    if (!api->initialize()) {
-        qWarning() << "Failed to initialize SoftBusAPI";
-        return;
-    }
-
-    // 注册一些示例设备(使用API获取设备列表)
-    const QStringList availablePorts = api->getAvailableSerialPorts();
-    static int deviceIdCounter = 1;
-    for (const QString &portName : availablePorts) {
-        DeviceInfo device;
-        device.id = deviceIdCounter++;
-        device.portname = portName;
-        device.name = QStringLiteral("串口设备: %1").arg(portName);
-        device.type = QStringLiteral("serial");
-        device.protocol = QStringLiteral("modbus");
-        device.protocol_detail = QStringLiteral("modbus-rtu");
-        m_busCore->registerDevice(device);
-    }
+    // 注意:API 初始化应该由 MainWindow::setupDaemonStatus() 统一管理
+    // 这里不再初始化 API,避免在模式设置之前就创建管理器
+    // 如果 API 未初始化,组件会在需要时检查并提示
 }
 
 void SerialDockPage::createUI()
@@ -124,9 +115,11 @@ void SerialDockPage::createUI()
     m_busDataTableWidget = new BusDataTableWidget(this);
 
     // 使用 SoftBusAPI 统一接口
+    // 注意:API 应该已经由 MainWindow::setupDaemonStatus() 初始化
+    // 这里不再重复初始化,避免重复创建管理器
     SoftBusAPI *api = SoftBusAPI::instance();
-    if (!api->initialize()) {
-        qWarning() << "Failed to initialize SoftBusAPI";
+    if (!api->isInitialized()) {
+        LOG_WARNING() << "SoftBusAPI not initialized yet, components may not work properly";
     }
     
     m_deviceTreeWidget->setAPI(api);
@@ -164,12 +157,12 @@ void SerialDockPage::onDeviceSelected(const QString &deviceType, const QString &
     if (deviceType == QStringLiteral("serial")) {
         device = m_busCore->getDeviceInfoByPortname(deviceId);
     } else {
-        qWarning() << "Unsupported device type:" << deviceType;
+        LOG_WARNING() << "Unsupported device type:" << deviceType;
         return;
     }
 
     if (device.id == 0) {
-        qWarning() << "Device not found. type:" << deviceType << "id:" << deviceId;
+        LOG_WARNING() << "Device not found. type:" << deviceType << "id:" << deviceId << "device:" << device.toJson();
         return;
     }
 
@@ -195,12 +188,33 @@ void SerialDockPage::onDeviceSelected(const QString &deviceType, const QString &
     m_modbusConfigWidget->setCurrentDeviceId(deviceType, deviceId);
     m_rawDataTableWidget->showRawData(device.id);
     m_busDataTableWidget->showBusMessages(device.id);
+    
+    // 打开设备日志对话框
+    DeviceLogDialog* logDialog = nullptr;
+    if (m_deviceLogDialogs.contains(device.id)) {
+        logDialog = m_deviceLogDialogs[device.id];
+        // 如果对话框已关闭,重新创建
+        if (!logDialog || !logDialog->isVisible()) {
+            logDialog = new DeviceLogDialog(this);
+            m_deviceLogDialogs[device.id] = logDialog;
+        }
+    } else {
+        logDialog = new DeviceLogDialog(this);
+        m_deviceLogDialogs[device.id] = logDialog;
+    }
+    
+    if (logDialog) {
+        logDialog->setDeviceInfo(device, m_busCore);
+        logDialog->show();
+        logDialog->raise();
+        logDialog->activateWindow();
+    }
 }
 
 void SerialDockPage::onModbusCommandGenerated(const QByteArray &command)
 {
     m_serialDataWidget->setSendData(command);
-    qDebug() << "Modbus command generated:" << command.toHex(' ');
+    LOG_DEBUG() << "Modbus command generated:" << command.toHex(' ');
 }
 
 void SerialDockPage::onBusMessageStored(const BusMessage &message)

+ 5 - 0
src/view_serial/serialdockpage.h

@@ -19,8 +19,10 @@
 #include <QObject>
 #include <QByteArray>
 #include <QString>
+#include <QMap>
 
 class DeviceTreeWidget;
+class DeviceLogDialog;
 class SerialSettingsWidget;
 class ModbusConfigWidget;
 class SerialDataWidget;
@@ -56,6 +58,9 @@ private:
     BusDataTableWidget *m_busDataTableWidget;
     int m_currentDeviceId;
     QString m_currentPortName;
+    
+    // 设备日志对话框映射(每个设备一个对话框)
+    QMap<int, DeviceLogDialog*> m_deviceLogDialogs;
 };
 
 #endif // SERIALDOCKPAGE_H