log0.3
This commit is contained in:
BIN
.cache/clangd/index/CoreService.cpp.4E2160035C5FBDAD.idx
Normal file
BIN
.cache/clangd/index/CoreService.cpp.4E2160035C5FBDAD.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/CoreService.h.545B9643BE6343CF.idx
Normal file
BIN
.cache/clangd/index/CoreService.h.545B9643BE6343CF.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx
Normal file
BIN
.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/DeviceBus.h.170EB5C1B9D8C650.idx
Normal file
BIN
.cache/clangd/index/DeviceBus.h.170EB5C1B9D8C650.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/DeviceBusManager.cpp.134168DDD210A4ED.idx
Normal file
BIN
.cache/clangd/index/DeviceBusManager.cpp.134168DDD210A4ED.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/DeviceBusManager.h.4DAD625CA48C7EE3.idx
Normal file
BIN
.cache/clangd/index/DeviceBusManager.h.4DAD625CA48C7EE3.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/DeviceTreeModel.cpp.D68EA11C8BBF4ADF.idx
Normal file
BIN
.cache/clangd/index/DeviceTreeModel.cpp.D68EA11C8BBF4ADF.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/DeviceTreeModel.h.A5637DBA59AB7F8A.idx
Normal file
BIN
.cache/clangd/index/DeviceTreeModel.h.A5637DBA59AB7F8A.idx
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.cache/clangd/index/IStreamDriver.h.7F77A7878AD58FDD.idx
Normal file
BIN
.cache/clangd/index/IStreamDriver.h.7F77A7878AD58FDD.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/IpcDBus.cpp.F75762A8BF6179E0.idx
Normal file
BIN
.cache/clangd/index/IpcDBus.cpp.F75762A8BF6179E0.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/IpcDBus.h.DD48681835A8EA94.idx
Normal file
BIN
.cache/clangd/index/IpcDBus.h.DD48681835A8EA94.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/SerialCapabilities.h.50ACDAA3497BB1F6.idx
Normal file
BIN
.cache/clangd/index/SerialCapabilities.h.50ACDAA3497BB1F6.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/SerialQtDriver.cpp.E8F1085153E8E1E0.idx
Normal file
BIN
.cache/clangd/index/SerialQtDriver.cpp.E8F1085153E8E1E0.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/SerialQtDriver.h.0D1EBDDF4831E0E3.idx
Normal file
BIN
.cache/clangd/index/SerialQtDriver.h.0D1EBDDF4831E0E3.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/logging.h.C8CBC4848C286E20.idx
Normal file
BIN
.cache/clangd/index/logging.h.C8CBC4848C286E20.idx
Normal file
Binary file not shown.
BIN
.cache/clangd/index/main.cpp.76A75E580B25A05E.idx
Normal file
BIN
.cache/clangd/index/main.cpp.76A75E580B25A05E.idx
Normal file
Binary file not shown.
164
.gitignore
vendored
164
.gitignore
vendored
@@ -1,82 +1,82 @@
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
*.qbs.user*
|
||||
CMakeLists.txt.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
# Directories with generated files
|
||||
.moc/
|
||||
.obj/
|
||||
.pch/
|
||||
.rcc/
|
||||
.uic/
|
||||
/build*/
|
||||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
*.qbs.user*
|
||||
CMakeLists.txt.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
# Directories with generated files
|
||||
.moc/
|
||||
.obj/
|
||||
.pch/
|
||||
.rcc/
|
||||
.uic/
|
||||
/build*/
|
||||
|
||||
201
CMakeLists.txt
201
CMakeLists.txt
@@ -1,85 +1,116 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(soft_bus_daemon
|
||||
LANGUAGES CXX
|
||||
VERSION 1.0.0
|
||||
)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
|
||||
|
||||
# Output layout
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/plugins)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/plugins)
|
||||
|
||||
# 启用AddressSanitizer(仅在非Windows平台上)
|
||||
if(NOT WIN32)
|
||||
set(SANITIZE_FLAGS "-fsanitize=address")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
|
||||
else()
|
||||
message(STATUS "AddressSanitizer disabled on Windows because the runtime is unavailable in the MinGW kit.")
|
||||
endif()
|
||||
|
||||
# 设置C++标准
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
# 查找Qt6(守护进程只需要 Core/DBus/Network/SerialPort/Sql)
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Core SerialPort Network Sql DBus)
|
||||
|
||||
# 检测编译平台
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(PlatformDir "x86")
|
||||
else()
|
||||
set(PlatformDir "x64")
|
||||
endif()
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
# 添加软总线模板库
|
||||
# 1. 日志库
|
||||
qt_add_library(softbus_template
|
||||
src/utils/logs/logging.h
|
||||
src/utils/logs/LogStream.h
|
||||
)
|
||||
|
||||
qt_add_executable(softbus_daemon
|
||||
main.cpp
|
||||
src/core/CoreService.cpp
|
||||
|
||||
# api 接口
|
||||
|
||||
src/api/ipc_dbus/IpcDBus.h
|
||||
src/api/ipc_dbus/IpcDBus.cpp
|
||||
|
||||
|
||||
)
|
||||
|
||||
target_include_directories(softbus_daemon
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
|
||||
|
||||
|
||||
target_link_libraries(softbus_daemon
|
||||
PRIVATE
|
||||
Qt::Core
|
||||
Qt6::DBus
|
||||
Qt6::SerialPort
|
||||
Qt6::Network
|
||||
)
|
||||
|
||||
add_subdirectory(plugins)
|
||||
|
||||
|
||||
install(TARGETS softbus_daemon
|
||||
BUNDLE DESTINATION .
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(soft_bus_daemon
|
||||
LANGUAGES CXX
|
||||
VERSION 1.0.0
|
||||
)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
|
||||
|
||||
# Output layout
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/plugins)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/plugins)
|
||||
|
||||
# 启用AddressSanitizer(仅在非Windows平台上)
|
||||
if(NOT WIN32)
|
||||
set(SANITIZE_FLAGS "-fsanitize=address")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SANITIZE_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZE_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZE_FLAGS}")
|
||||
else()
|
||||
message(STATUS "AddressSanitizer disabled on Windows because the runtime is unavailable in the MinGW kit.")
|
||||
endif()
|
||||
|
||||
# 设置C++标准
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
# 查找Qt6(守护进程只需要 Core/DBus/Network/SerialPort/Sql)
|
||||
find_package(Qt6 6.5 REQUIRED COMPONENTS Core SerialPort Network Sql DBus)
|
||||
|
||||
# 检测编译平台
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(PlatformDir "x86")
|
||||
else()
|
||||
set(PlatformDir "x64")
|
||||
endif()
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
# 添加软总线模板库
|
||||
# 1. 日志库
|
||||
qt_add_library(softbus_template
|
||||
src/utils/logs/logging.h
|
||||
src/utils/logs/LogStream.h
|
||||
)
|
||||
|
||||
qt_add_executable(softbus_daemon
|
||||
main.cpp
|
||||
src/core/CoreService.cpp
|
||||
# core device types
|
||||
src/core/device/DeviceTypes.h
|
||||
src/core/device/DeviceTypes.cpp
|
||||
|
||||
|
||||
# api 接口
|
||||
|
||||
src/api/ipc_dbus/IpcDBus.h
|
||||
src/api/ipc_dbus/IpcDBus.cpp
|
||||
|
||||
# hardware interfaces (Level 2)
|
||||
src/hardware/interfaces/IStreamDriver.h
|
||||
src/hardware/interfaces/IFrameDriver.h
|
||||
src/hardware/interfaces/IDeviceWatcher.h
|
||||
|
||||
# hardware drivers (Level 2)
|
||||
src/hardware/drivers/serial/SerialQtDriver.h
|
||||
src/hardware/drivers/serial/SerialQtDriver.cpp
|
||||
src/hardware/drivers/serial/SerialCapabilities.h
|
||||
|
||||
# device bus: tree & capabilities
|
||||
src/device_bus/tree/DeviceTreeModel.h
|
||||
src/device_bus/tree/DeviceTreeModel.cpp
|
||||
src/device_bus/capabilities/DriverCapabilityProvider.h
|
||||
src/device_bus/capabilities/DriverCapabilityProvider.cpp
|
||||
|
||||
# device bus: facade & manager
|
||||
src/device_bus/DeviceBus.h
|
||||
src/device_bus/DeviceBus.cpp
|
||||
src/device_bus/manager/DeviceBusManager.h
|
||||
src/device_bus/manager/DeviceBusManager.cpp
|
||||
|
||||
# device bus: registry skeleton
|
||||
src/device_bus/registry/IDeviceRegistry.h
|
||||
|
||||
# devices: base skeleton
|
||||
src/devices/base/IDevice.h
|
||||
)
|
||||
|
||||
target_include_directories(softbus_daemon
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
)
|
||||
|
||||
|
||||
|
||||
target_link_libraries(softbus_daemon
|
||||
PRIVATE
|
||||
Qt::Core
|
||||
Qt6::DBus
|
||||
Qt6::SerialPort
|
||||
Qt6::Network
|
||||
)
|
||||
|
||||
add_subdirectory(plugins)
|
||||
|
||||
|
||||
install(TARGETS softbus_daemon
|
||||
BUNDLE DESTINATION .
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
Binary file not shown.
@@ -1,5 +1,23 @@
|
||||
{
|
||||
"plugin_dir": "bin/plugins",
|
||||
"device_tree": [],
|
||||
"routes": []
|
||||
}
|
||||
{
|
||||
"plugin_dir": "bin/plugins",
|
||||
"device_tree": [
|
||||
{
|
||||
"id": "serial_1",
|
||||
"name": "Serial Device 1",
|
||||
"type": "serial",
|
||||
"endpoint": "/dev/ttyS1",
|
||||
"driver": "hardware/drivers/serial/SerialQtDriver",
|
||||
"capabilitiesRef": "src/hardware/drivers/serial/parameters.json",
|
||||
"params": {
|
||||
"baudRate": 115200,
|
||||
"dataBits": 8,
|
||||
"parity": "none",
|
||||
"stopBits": 1,
|
||||
"flowControl": "none"
|
||||
},
|
||||
"children": [],
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"routes": []
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
"modbus_rtu": {
|
||||
"register_map": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
272
main.cpp
272
main.cpp
@@ -1,136 +1,136 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusError>
|
||||
#include <signal.h>
|
||||
#include "src/utils/logs/logging.h"
|
||||
#include "src/core/CoreService.h"
|
||||
#include "src/api/ipc_dbus/IpcDBus.h"
|
||||
|
||||
void signalHandler(int signal)
|
||||
{
|
||||
LOG_INFO() << "Received signal:" << signal;
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// ==================================
|
||||
// 创建并配置 Qt 应用程序对象
|
||||
// ==================================
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
app.setApplicationName("soft_bus_daemon");
|
||||
app.setApplicationVersion("1.0.0");
|
||||
app.setOrganizationName("soft_bus");
|
||||
|
||||
// ==================================
|
||||
// 设置 Qt 应用程序信息
|
||||
// ==================================
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QStringLiteral("Soft Bus Daemon"));
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
QCommandLineOption roleOption(QStringLiteral("role"),
|
||||
QStringLiteral("Daemon role (CoreRouter, CollectorSerial, CollectorCan, Collector, SqlServer)"),
|
||||
QStringLiteral("role"),
|
||||
QStringLiteral("CoreRouter"));
|
||||
parser.addOption(roleOption);
|
||||
QCommandLineOption dbusBusOption(QStringLiteral("dbus-bus"),
|
||||
QStringLiteral("DBus bus to use: system|session|auto (default: auto)"),
|
||||
QStringLiteral("bus"),
|
||||
QStringLiteral("auto"));
|
||||
parser.addOption(dbusBusOption);
|
||||
parser.process(app);
|
||||
|
||||
|
||||
const QString roleString = parser.value(roleOption).trimmed();
|
||||
const QString dbusBus = parser.value(dbusBusOption).trimmed();
|
||||
CoreService::Role role = CoreService::Role::CoreRouter; // 默认角色
|
||||
if (roleString == QStringLiteral("CoreRouter")) {
|
||||
role = CoreService::Role::CoreRouter;
|
||||
} else if (roleString == QStringLiteral("CollectorSerial")) {
|
||||
role = CoreService::Role::CollectorSerial;
|
||||
} else if (roleString == QStringLiteral("CollectorCan")) {
|
||||
role = CoreService::Role::CollectorCan;
|
||||
} else if (roleString == QStringLiteral("Collector")) {
|
||||
role = CoreService::Role::Collector;
|
||||
} else if (roleString == QStringLiteral("SqlServer")) {
|
||||
role = CoreService::Role::SqlServer;
|
||||
} else {
|
||||
LOG_ERROR() << "Invalid role:" << roleString
|
||||
<< "valid roles are: CoreRouter, CollectorSerial, CollectorCan, Collector, SqlServer";
|
||||
return 1;
|
||||
}
|
||||
|
||||
CoreService* coreService = CoreService::instance();
|
||||
if (!coreService->initialize()) {
|
||||
LOG_ERROR() << "CoreService initialize failed";
|
||||
return 1;
|
||||
}
|
||||
QObject::connect(&app, &QCoreApplication::aboutToQuit, coreService, &CoreService::shutdown);
|
||||
|
||||
// ========================================================================
|
||||
// 创建并注册 D-Bus 服务(仅在 CoreRouter 角色中启用)
|
||||
// ========================================================================
|
||||
if (role == CoreService::Role::CoreRouter) {
|
||||
const QString serviceName = QStringLiteral("com.softbus.Daemon");
|
||||
const QString objectPath = QStringLiteral("/com/softbus/Daemon");
|
||||
|
||||
IpcDBus* ipc = new IpcDBus(coreService, roleString, &app);
|
||||
|
||||
auto pickConnection = [&]() -> QDBusConnection {
|
||||
if (dbusBus == QStringLiteral("system")) {
|
||||
return QDBusConnection::systemBus();
|
||||
}
|
||||
if (dbusBus == QStringLiteral("session")) {
|
||||
return QDBusConnection::sessionBus();
|
||||
}
|
||||
// auto: 优先 system(更符合 daemon),失败则退回 session(方便本地开发)
|
||||
QDBusConnection conn = QDBusConnection::systemBus();
|
||||
if (conn.isConnected()) {
|
||||
return conn;
|
||||
}
|
||||
return QDBusConnection::sessionBus();
|
||||
};
|
||||
|
||||
QDBusConnection connection = pickConnection();
|
||||
if (!connection.isConnected()) {
|
||||
LOG_ERROR() << "Cannot connect to D-Bus. system error="
|
||||
<< QDBusConnection::systemBus().lastError().message()
|
||||
<< " session error=" << QDBusConnection::sessionBus().lastError().message();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!connection.registerService(serviceName)) {
|
||||
LOG_ERROR() << "Failed to register D-Bus service:" << serviceName
|
||||
<< "error=" << connection.lastError().message();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!connection.registerObject(objectPath,
|
||||
ipc,
|
||||
QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
|
||||
LOG_ERROR() << "Failed to register D-Bus object:" << objectPath
|
||||
<< "error=" << connection.lastError().message();
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_INFO() << "D-Bus ready. bus="
|
||||
<< (connection.name() == QDBusConnection::systemBus().name() ? "system" : "session")
|
||||
<< " service=" << serviceName
|
||||
<< " object=" << objectPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==================================
|
||||
// 处理系统信号,确保在接收到 SIGINT 或 SIGTERM 时能够优雅地退出
|
||||
// ==================================
|
||||
|
||||
signal(SIGINT, signalHandler);
|
||||
signal(SIGTERM, signalHandler);
|
||||
|
||||
int ret = app.exec();
|
||||
return ret;
|
||||
}
|
||||
#include <QCoreApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusError>
|
||||
#include <signal.h>
|
||||
#include "src/utils/logs/logging.h"
|
||||
#include "src/core/CoreService.h"
|
||||
#include "src/api/ipc_dbus/IpcDBus.h"
|
||||
|
||||
void signalHandler(int signal)
|
||||
{
|
||||
LOG_INFO() << "Received signal:" << signal;
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// ==================================
|
||||
// 创建并配置 Qt 应用程序对象
|
||||
// ==================================
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
app.setApplicationName("soft_bus_daemon");
|
||||
app.setApplicationVersion("1.0.0");
|
||||
app.setOrganizationName("soft_bus");
|
||||
|
||||
// ==================================
|
||||
// 设置 Qt 应用程序信息
|
||||
// ==================================
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QStringLiteral("Soft Bus Daemon"));
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
QCommandLineOption roleOption(QStringLiteral("role"),
|
||||
QStringLiteral("Daemon role (CoreRouter, CollectorSerial, CollectorCan, Collector, SqlServer)"),
|
||||
QStringLiteral("role"),
|
||||
QStringLiteral("CoreRouter"));
|
||||
parser.addOption(roleOption);
|
||||
QCommandLineOption dbusBusOption(QStringLiteral("dbus-bus"),
|
||||
QStringLiteral("DBus bus to use: system|session|auto (default: auto)"),
|
||||
QStringLiteral("bus"),
|
||||
QStringLiteral("auto"));
|
||||
parser.addOption(dbusBusOption);
|
||||
parser.process(app);
|
||||
|
||||
|
||||
const QString roleString = parser.value(roleOption).trimmed();
|
||||
const QString dbusBus = parser.value(dbusBusOption).trimmed();
|
||||
CoreService::Role role = CoreService::Role::CoreRouter; // 默认角色
|
||||
if (roleString == QStringLiteral("CoreRouter")) {
|
||||
role = CoreService::Role::CoreRouter;
|
||||
} else if (roleString == QStringLiteral("CollectorSerial")) {
|
||||
role = CoreService::Role::CollectorSerial;
|
||||
} else if (roleString == QStringLiteral("CollectorCan")) {
|
||||
role = CoreService::Role::CollectorCan;
|
||||
} else if (roleString == QStringLiteral("Collector")) {
|
||||
role = CoreService::Role::Collector;
|
||||
} else if (roleString == QStringLiteral("SqlServer")) {
|
||||
role = CoreService::Role::SqlServer;
|
||||
} else {
|
||||
LOG_ERROR() << "Invalid role:" << roleString
|
||||
<< "valid roles are: CoreRouter, CollectorSerial, CollectorCan, Collector, SqlServer";
|
||||
return 1;
|
||||
}
|
||||
|
||||
CoreService* coreService = CoreService::instance();
|
||||
if (!coreService->initialize()) {
|
||||
LOG_ERROR() << "CoreService initialize failed";
|
||||
return 1;
|
||||
}
|
||||
QObject::connect(&app, &QCoreApplication::aboutToQuit, coreService, &CoreService::shutdown);
|
||||
|
||||
// ========================================================================
|
||||
// 创建并注册 D-Bus 服务(仅在 CoreRouter 角色中启用)
|
||||
// ========================================================================
|
||||
if (role == CoreService::Role::CoreRouter) {
|
||||
const QString serviceName = QStringLiteral("com.softbus.Daemon");
|
||||
const QString objectPath = QStringLiteral("/com/softbus/Daemon");
|
||||
|
||||
IpcDBus* ipc = new IpcDBus(coreService, roleString, &app);
|
||||
|
||||
auto pickConnection = [&]() -> QDBusConnection {
|
||||
if (dbusBus == QStringLiteral("system")) {
|
||||
return QDBusConnection::systemBus();
|
||||
}
|
||||
if (dbusBus == QStringLiteral("session")) {
|
||||
return QDBusConnection::sessionBus();
|
||||
}
|
||||
// auto: 优先 system(更符合 daemon),失败则退回 session(方便本地开发)
|
||||
QDBusConnection conn = QDBusConnection::systemBus();
|
||||
if (conn.isConnected()) {
|
||||
return conn;
|
||||
}
|
||||
return QDBusConnection::sessionBus();
|
||||
};
|
||||
|
||||
QDBusConnection connection = pickConnection();
|
||||
if (!connection.isConnected()) {
|
||||
LOG_ERROR() << "Cannot connect to D-Bus. system error="
|
||||
<< QDBusConnection::systemBus().lastError().message()
|
||||
<< " session error=" << QDBusConnection::sessionBus().lastError().message();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!connection.registerService(serviceName)) {
|
||||
LOG_ERROR() << "Failed to register D-Bus service:" << serviceName
|
||||
<< "error=" << connection.lastError().message();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!connection.registerObject(objectPath,
|
||||
ipc,
|
||||
QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) {
|
||||
LOG_ERROR() << "Failed to register D-Bus object:" << objectPath
|
||||
<< "error=" << connection.lastError().message();
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_INFO() << "D-Bus ready. bus="
|
||||
<< (connection.name() == QDBusConnection::systemBus().name() ? "system" : "session")
|
||||
<< " service=" << serviceName
|
||||
<< " object=" << objectPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==================================
|
||||
// 处理系统信号,确保在接收到 SIGINT 或 SIGTERM 时能够优雅地退出
|
||||
// ==================================
|
||||
|
||||
signal(SIGINT, signalHandler);
|
||||
signal(SIGTERM, signalHandler);
|
||||
|
||||
int ret = app.exec();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.19)
|
||||
add_subdirectory(protocols/modbus_rtu)
|
||||
add_subdirectory(protocols/can_raw)
|
||||
add_subdirectory(protocols/custom_proto)
|
||||
add_subdirectory(filters)
|
||||
add_subdirectory(filters)
|
||||
|
||||
@@ -1 +1 @@
|
||||
# Placeholder for filter plugins
|
||||
# Placeholder for filter plugins
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Placeholder for can_raw plugin
|
||||
add_library(can_raw SHARED)
|
||||
set_target_properties(can_raw PROPERTIES OUTPUT_NAME "can_raw")
|
||||
set_target_properties(can_raw PROPERTIES OUTPUT_NAME "can_raw")
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Placeholder for custom_proto plugin
|
||||
add_library(custom_proto SHARED)
|
||||
set_target_properties(custom_proto PROPERTIES OUTPUT_NAME "custom_proto")
|
||||
set_target_properties(custom_proto PROPERTIES OUTPUT_NAME "custom_proto")
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Placeholder for modbus_rtu plugin
|
||||
add_library(modbus_rtu SHARED)
|
||||
set_target_properties(modbus_rtu PROPERTIES OUTPUT_NAME "modbus_rtu")
|
||||
set_target_properties(modbus_rtu PROPERTIES OUTPUT_NAME "modbus_rtu")
|
||||
|
||||
@@ -1,75 +1,75 @@
|
||||
#include "IpcDBus.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "src/core/CoreService.h"
|
||||
|
||||
IpcDBus::IpcDBus(CoreService* coreService, const QString& role, QObject* parent)
|
||||
: QObject(parent),
|
||||
m_coreService(coreService),
|
||||
m_role(role)
|
||||
{
|
||||
}
|
||||
|
||||
IpcDBus::~IpcDBus() = default;
|
||||
|
||||
bool IpcDBus::isRunning() const
|
||||
{
|
||||
if (!m_coreService) {
|
||||
return false;
|
||||
}
|
||||
return m_coreService->isInitialized();
|
||||
}
|
||||
|
||||
QString IpcDBus::ping() const
|
||||
{
|
||||
return QStringLiteral("pong");
|
||||
}
|
||||
|
||||
QString IpcDBus::getVersion() const
|
||||
{
|
||||
return QCoreApplication::applicationVersion();
|
||||
}
|
||||
|
||||
QString IpcDBus::getStatus() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj.insert(QStringLiteral("service"), QStringLiteral("com.softbus.Daemon"));
|
||||
obj.insert(QStringLiteral("objectPath"), QStringLiteral("/com/softbus/Daemon"));
|
||||
obj.insert(QStringLiteral("interface"), QStringLiteral("com.softbus.Daemon"));
|
||||
obj.insert(QStringLiteral("pid"), static_cast<qint64>(QCoreApplication::applicationPid()));
|
||||
obj.insert(QStringLiteral("role"), m_role);
|
||||
obj.insert(QStringLiteral("running"), isRunning());
|
||||
obj.insert(QStringLiteral("timestampMs"), static_cast<qint64>(QDateTime::currentMSecsSinceEpoch()));
|
||||
|
||||
const QJsonDocument doc(obj);
|
||||
return QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
qint64 IpcDBus::getPid() const
|
||||
{
|
||||
return static_cast<qint64>(QCoreApplication::applicationPid());
|
||||
}
|
||||
|
||||
void IpcDBus::shutdown()
|
||||
{
|
||||
if (m_coreService) {
|
||||
m_coreService->shutdown();
|
||||
}
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
bool IpcDBus::reloadConfig()
|
||||
{
|
||||
// 占位:后续移植配置系统时在这里触发 reload
|
||||
return false;
|
||||
}
|
||||
|
||||
void IpcDBus::updateLoadInfo()
|
||||
{
|
||||
// 预留:后续可在此周期性采样 CPU/内存/队列长度等指标,并通过 getStatus() 输出
|
||||
}
|
||||
|
||||
#include "IpcDBus.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "src/core/CoreService.h"
|
||||
|
||||
IpcDBus::IpcDBus(CoreService* coreService, const QString& role, QObject* parent)
|
||||
: QObject(parent),
|
||||
m_coreService(coreService),
|
||||
m_role(role)
|
||||
{
|
||||
}
|
||||
|
||||
IpcDBus::~IpcDBus() = default;
|
||||
|
||||
bool IpcDBus::isRunning() const
|
||||
{
|
||||
if (!m_coreService) {
|
||||
return false;
|
||||
}
|
||||
return m_coreService->isInitialized();
|
||||
}
|
||||
|
||||
QString IpcDBus::ping() const
|
||||
{
|
||||
return QStringLiteral("pong");
|
||||
}
|
||||
|
||||
QString IpcDBus::getVersion() const
|
||||
{
|
||||
return QCoreApplication::applicationVersion();
|
||||
}
|
||||
|
||||
QString IpcDBus::getStatus() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj.insert(QStringLiteral("service"), QStringLiteral("com.softbus.Daemon"));
|
||||
obj.insert(QStringLiteral("objectPath"), QStringLiteral("/com/softbus/Daemon"));
|
||||
obj.insert(QStringLiteral("interface"), QStringLiteral("com.softbus.Daemon"));
|
||||
obj.insert(QStringLiteral("pid"), static_cast<qint64>(QCoreApplication::applicationPid()));
|
||||
obj.insert(QStringLiteral("role"), m_role);
|
||||
obj.insert(QStringLiteral("running"), isRunning());
|
||||
obj.insert(QStringLiteral("timestampMs"), static_cast<qint64>(QDateTime::currentMSecsSinceEpoch()));
|
||||
|
||||
const QJsonDocument doc(obj);
|
||||
return QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
qint64 IpcDBus::getPid() const
|
||||
{
|
||||
return static_cast<qint64>(QCoreApplication::applicationPid());
|
||||
}
|
||||
|
||||
void IpcDBus::shutdown()
|
||||
{
|
||||
if (m_coreService) {
|
||||
m_coreService->shutdown();
|
||||
}
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
bool IpcDBus::reloadConfig()
|
||||
{
|
||||
// 占位:后续移植配置系统时在这里触发 reload
|
||||
return false;
|
||||
}
|
||||
|
||||
void IpcDBus::updateLoadInfo()
|
||||
{
|
||||
// 预留:后续可在此周期性采样 CPU/内存/队列长度等指标,并通过 getStatus() 输出
|
||||
}
|
||||
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
/**
|
||||
* @file Ipc_dbus.h
|
||||
* @brief D-Bus 服务接口 - 提供核心服务状态和负载查询
|
||||
*/
|
||||
|
||||
#ifndef IPC_DBUS_H
|
||||
#define IPC_DBUS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QString>
|
||||
// 前向声明
|
||||
class CoreService;
|
||||
/**
|
||||
* @brief D-Bus 服务适配器 - 暴露核心服务接口
|
||||
*/
|
||||
class IpcDBus : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "com.softbus.Daemon")
|
||||
|
||||
public:
|
||||
explicit IpcDBus(CoreService* coreService, const QString& role, QObject* parent = nullptr);
|
||||
~IpcDBus();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 检查核心服务是否运行
|
||||
* @return true 如果核心服务正在运行
|
||||
*/
|
||||
bool isRunning() const;
|
||||
|
||||
QString ping() const;
|
||||
|
||||
QString getVersion() const;
|
||||
|
||||
/**
|
||||
* @brief 获取核心服务状态信息
|
||||
* @return JSON 格式的状态信息
|
||||
*/
|
||||
QString getStatus() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取守护进程的进程ID
|
||||
* @return 进程ID,如果无法获取则返回0
|
||||
*/
|
||||
qint64 getPid() const;
|
||||
|
||||
/**
|
||||
* @brief 关闭守护进程
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
bool reloadConfig();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private slots:
|
||||
void updateLoadInfo();
|
||||
|
||||
private:
|
||||
CoreService* m_coreService{nullptr}; // non-owning
|
||||
QString m_role;
|
||||
};
|
||||
|
||||
#endif // IPC_DBUS_H
|
||||
|
||||
/**
|
||||
* @file Ipc_dbus.h
|
||||
* @brief D-Bus 服务接口 - 提供核心服务状态和负载查询
|
||||
*/
|
||||
|
||||
#ifndef IPC_DBUS_H
|
||||
#define IPC_DBUS_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <QString>
|
||||
// 前向声明
|
||||
class CoreService;
|
||||
/**
|
||||
* @brief D-Bus 服务适配器 - 暴露核心服务接口
|
||||
*/
|
||||
class IpcDBus : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "com.softbus.Daemon")
|
||||
|
||||
public:
|
||||
explicit IpcDBus(CoreService* coreService, const QString& role, QObject* parent = nullptr);
|
||||
~IpcDBus();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief 检查核心服务是否运行
|
||||
* @return true 如果核心服务正在运行
|
||||
*/
|
||||
bool isRunning() const;
|
||||
|
||||
QString ping() const;
|
||||
|
||||
QString getVersion() const;
|
||||
|
||||
/**
|
||||
* @brief 获取核心服务状态信息
|
||||
* @return JSON 格式的状态信息
|
||||
*/
|
||||
QString getStatus() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取守护进程的进程ID
|
||||
* @return 进程ID,如果无法获取则返回0
|
||||
*/
|
||||
qint64 getPid() const;
|
||||
|
||||
/**
|
||||
* @brief 关闭守护进程
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
bool reloadConfig();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private slots:
|
||||
void updateLoadInfo();
|
||||
|
||||
private:
|
||||
CoreService* m_coreService{nullptr}; // non-owning
|
||||
QString m_role;
|
||||
};
|
||||
|
||||
#endif // IPC_DBUS_H
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
#include "CoreService.h"
|
||||
#include "../utils/logs/logging.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "utils/logs/logging.h"
|
||||
#include "device_bus/DeviceBus.h"
|
||||
|
||||
CoreService* CoreService::instance()
|
||||
{
|
||||
@@ -26,6 +35,34 @@ bool CoreService::initialize()
|
||||
}
|
||||
|
||||
LOG_INFO() << "CoreService initializing";
|
||||
|
||||
// 1. 解析配置路径(放在用户 home 下的相对固定目录:~/softbus/config)
|
||||
const QString configPath =
|
||||
QDir::homePath() + QStringLiteral("/softbus/config/daemon_config.json");
|
||||
|
||||
QFile f(configPath);
|
||||
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
LOG_ERROR() << "CoreService: failed to open" << configPath;
|
||||
return false;
|
||||
}
|
||||
|
||||
const QByteArray data = f.readAll();
|
||||
f.close();
|
||||
|
||||
QJsonParseError pe;
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(data, &pe);
|
||||
if (pe.error != QJsonParseError::NoError || !doc.isObject()) {
|
||||
LOG_ERROR() << "CoreService: invalid JSON in" << configPath << ":" << pe.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
const QJsonObject root = doc.object();
|
||||
|
||||
// 2. 初始化 device_bus(交给 DeviceBus facade 处理具体设备)
|
||||
if (!softbus::device_bus::DeviceBus::instance().initialize(root)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
return true;
|
||||
}
|
||||
@@ -38,6 +75,7 @@ void CoreService::shutdown()
|
||||
}
|
||||
|
||||
LOG_INFO() << "CoreService shutting down";
|
||||
softbus::device_bus::DeviceBus::instance().shutdown();
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <QObject>
|
||||
|
||||
|
||||
class CoreService : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
39
src/core/device/DeviceTypes.cpp
Normal file
39
src/core/device/DeviceTypes.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "core/device/DeviceTypes.h"
|
||||
|
||||
namespace softbus::core::device
|
||||
{
|
||||
|
||||
DeviceKind kindFromType(const QString& typeStr)
|
||||
{
|
||||
const QString t = typeStr.trimmed().toLower();
|
||||
if (t == QStringLiteral("serial")) return DeviceKind::Serial;
|
||||
if (t == QStringLiteral("can")) return DeviceKind::Can;
|
||||
if (t == QStringLiteral("ethernet") || t == QStringLiteral("network")) return DeviceKind::Network;
|
||||
if (t == QStringLiteral("virtual")) return DeviceKind::Virtual;
|
||||
if (t == QStringLiteral("distributed")) return DeviceKind::Distributed;
|
||||
return DeviceKind::Unknown;
|
||||
}
|
||||
|
||||
DeviceKind inferDeviceKindFromEndpoint(const QString& endpoint)
|
||||
{
|
||||
const QString ep = endpoint.trimmed();
|
||||
if (ep.startsWith(QStringLiteral("/dev/tty"))) return DeviceKind::Serial;
|
||||
if (ep.startsWith(QStringLiteral("can"))) return DeviceKind::Can;
|
||||
if (ep.startsWith(QStringLiteral("tcp://")) || ep.startsWith(QStringLiteral("udp://"))) return DeviceKind::Network;
|
||||
return DeviceKind::Unknown;
|
||||
}
|
||||
|
||||
QString driverKeyFor(DeviceKind kind)
|
||||
{
|
||||
switch (kind) {
|
||||
case DeviceKind::Serial: return QStringLiteral("serial_qt");
|
||||
case DeviceKind::Can: return QStringLiteral("can_socketcan");
|
||||
case DeviceKind::Network: return QStringLiteral("tcp_qt");
|
||||
case DeviceKind::Virtual: return QStringLiteral("virtual_device");
|
||||
case DeviceKind::Distributed: return QStringLiteral("distributed_node");
|
||||
default: return QStringLiteral("unknown");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace softbus::core::device
|
||||
|
||||
69
src/core/device/DeviceTypes.h
Normal file
69
src/core/device/DeviceTypes.h
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
|
||||
namespace softbus::core::device
|
||||
{
|
||||
|
||||
enum class DeviceKind {
|
||||
Serial,
|
||||
Can,
|
||||
Network,
|
||||
Virtual,
|
||||
Distributed,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
struct DeviceInfo
|
||||
{
|
||||
int id{0};
|
||||
QString endpoint;
|
||||
QString name;
|
||||
QString type; // "serial" / "can" / "network" / ...
|
||||
int address{0};
|
||||
QString protocol;
|
||||
QString protocolDetail;
|
||||
QJsonObject properties;
|
||||
QString status{QStringLiteral("online")};
|
||||
bool isActive{true};
|
||||
QDateTime lastSeen;
|
||||
|
||||
QString toJson() const
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj[QStringLiteral("id")] = id;
|
||||
obj[QStringLiteral("endpoint")] = endpoint;
|
||||
obj[QStringLiteral("name")] = name;
|
||||
obj[QStringLiteral("type")] = type;
|
||||
obj[QStringLiteral("address")] = address;
|
||||
obj[QStringLiteral("protocol")] = protocol;
|
||||
obj[QStringLiteral("protocol_detail")] = protocolDetail;
|
||||
obj[QStringLiteral("properties")] = properties;
|
||||
obj[QStringLiteral("status")] = status;
|
||||
obj[QStringLiteral("isActive")] = isActive;
|
||||
if (lastSeen.isValid()) {
|
||||
obj[QStringLiteral("lastSeen")] = lastSeen.toString(Qt::ISODate);
|
||||
}
|
||||
const QJsonDocument doc(obj);
|
||||
return QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
|
||||
}
|
||||
};
|
||||
|
||||
struct BusMessage
|
||||
{
|
||||
QString id;
|
||||
QString source;
|
||||
QString destination;
|
||||
QJsonObject payload;
|
||||
qint64 timestamp{0};
|
||||
};
|
||||
|
||||
DeviceKind kindFromType(const QString& typeStr);
|
||||
DeviceKind inferDeviceKindFromEndpoint(const QString& endpoint);
|
||||
QString driverKeyFor(DeviceKind kind);
|
||||
|
||||
} // namespace softbus::core::device
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
class LockFreeQueue {
|
||||
public:
|
||||
LockFreeQueue() = default;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
class MemoryPool {
|
||||
public:
|
||||
MemoryPool() = default;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
// Placeholder for data trace model.
|
||||
struct DataTrace {
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
// Placeholder for metadata model.
|
||||
struct Metadata {
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
class IProtocolPlugin {
|
||||
public:
|
||||
virtual ~IProtocolPlugin() = default;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
class PluginManager {
|
||||
public:
|
||||
PluginManager() = default;
|
||||
};
|
||||
};
|
||||
|
||||
30
src/device_bus/DeviceBus.cpp
Normal file
30
src/device_bus/DeviceBus.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "device_bus/DeviceBus.h"
|
||||
|
||||
#include "device_bus/manager/DeviceBusManager.h"
|
||||
|
||||
namespace softbus::device_bus {
|
||||
|
||||
class DeviceBus::Impl {
|
||||
public:
|
||||
DeviceBusManager manager;
|
||||
};
|
||||
|
||||
DeviceBus &DeviceBus::instance() {
|
||||
static DeviceBus inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
DeviceBus::DeviceBus() : d(new Impl()) {}
|
||||
|
||||
DeviceBus::~DeviceBus() {
|
||||
delete d;
|
||||
d = nullptr;
|
||||
}
|
||||
|
||||
bool DeviceBus::initialize(const QJsonObject &rootConfig) {
|
||||
return d->manager.initialize(rootConfig);
|
||||
}
|
||||
|
||||
void DeviceBus::shutdown() { d->manager.shutdown(); }
|
||||
|
||||
} // namespace softbus::device_bus
|
||||
24
src/device_bus/DeviceBus.h
Normal file
24
src/device_bus/DeviceBus.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace softbus::device_bus {
|
||||
|
||||
class DeviceBus {
|
||||
public:
|
||||
static DeviceBus &instance();
|
||||
|
||||
bool initialize(const QJsonObject &rootConfig);
|
||||
void shutdown();
|
||||
|
||||
private:
|
||||
DeviceBus();
|
||||
~DeviceBus();
|
||||
DeviceBus(const DeviceBus &) = delete;
|
||||
DeviceBus &operator=(const DeviceBus &) = delete;
|
||||
|
||||
class Impl;
|
||||
Impl *d;
|
||||
};
|
||||
|
||||
} // namespace softbus::device_bus
|
||||
77
src/device_bus/capabilities/DriverCapabilityProvider.cpp
Normal file
77
src/device_bus/capabilities/DriverCapabilityProvider.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "device_bus/capabilities/DriverCapabilityProvider.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
bool DriverCapabilityProvider::loadFromFile(const QString& jsonPath, QString* errorMessage)
|
||||
{
|
||||
m_defaults = QJsonObject();
|
||||
m_enums = QJsonObject();
|
||||
|
||||
QFile f(jsonPath);
|
||||
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
if (errorMessage) {
|
||||
*errorMessage = QStringLiteral("Failed to open capability file: %1").arg(jsonPath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const QByteArray data = f.readAll();
|
||||
f.close();
|
||||
|
||||
QJsonParseError pe;
|
||||
const QJsonDocument doc = QJsonDocument::fromJson(data, &pe);
|
||||
if (pe.error != QJsonParseError::NoError || !doc.isObject()) {
|
||||
if (errorMessage) {
|
||||
*errorMessage = QStringLiteral("Invalid JSON in capability file %1: %2")
|
||||
.arg(jsonPath, pe.errorString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const QJsonObject root = doc.object();
|
||||
m_defaults = root.value(QStringLiteral("defaults")).toObject();
|
||||
m_enums = root.value(QStringLiteral("enums")).toObject();
|
||||
|
||||
LOG_INFO() << "DriverCapabilityProvider loaded from" << jsonPath;
|
||||
return true;
|
||||
}
|
||||
|
||||
QJsonObject DriverCapabilityProvider::mergeAndValidateParams(const QJsonObject& nodeParams) const
|
||||
{
|
||||
// 1. 从 defaults 拷贝一份出来
|
||||
QJsonObject result = m_defaults;
|
||||
|
||||
// 2. 覆盖节点里的显式参数
|
||||
for (auto it = nodeParams.constBegin(); it != nodeParams.constEnd(); ++it) {
|
||||
const QString key = it.key();
|
||||
const QJsonValue value = it.value();
|
||||
|
||||
// 如果存在枚举限制,则先校验
|
||||
const QJsonValue enumVal = m_enums.value(key);
|
||||
if (enumVal.isArray()) {
|
||||
const QJsonArray arr = enumVal.toArray();
|
||||
bool ok = false;
|
||||
for (const QJsonValue& candidate : arr) {
|
||||
if (candidate == value) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
LOG_WARNING() << "DriverCapabilityProvider: param" << key
|
||||
<< "value" << value.toVariant()
|
||||
<< "not in allowed enum, keep default";
|
||||
continue; // 不覆盖默认值
|
||||
}
|
||||
}
|
||||
|
||||
result.insert(key, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
21
src/device_bus/capabilities/DriverCapabilityProvider.h
Normal file
21
src/device_bus/capabilities/DriverCapabilityProvider.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
|
||||
// 负责加载 drivers 下的 parameters.json,并对节点 params 做默认值合并与简单枚举校验
|
||||
|
||||
class DriverCapabilityProvider
|
||||
{
|
||||
public:
|
||||
// 从给定路径加载能力描述(如 "src/hardware/drivers/serial/parameters.json")
|
||||
bool loadFromFile(const QString& jsonPath, QString* errorMessage = nullptr);
|
||||
|
||||
// 将节点 params 与 defaults 合并,并按 enums 做简单校验
|
||||
QJsonObject mergeAndValidateParams(const QJsonObject& nodeParams) const;
|
||||
|
||||
private:
|
||||
QJsonObject m_defaults;
|
||||
QJsonObject m_enums;
|
||||
};
|
||||
|
||||
124
src/device_bus/manager/DeviceBusManager.cpp
Normal file
124
src/device_bus/manager/DeviceBusManager.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "device_bus/manager/DeviceBusManager.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <algorithm>
|
||||
|
||||
#include "hardware/drivers/serial/SerialCapabilities.h"
|
||||
#include "core/device/DeviceTypes.h"
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
using softbus::hardware::drivers::serial::SerialQtDriver;
|
||||
namespace serial_cap = softbus::hardware::drivers::serial::capabilities;
|
||||
|
||||
bool DeviceBusManager::initialize(const QJsonObject& rootConfig)
|
||||
{
|
||||
// 加载设备树
|
||||
QString treeError;
|
||||
if (!m_treeModel.loadFromDaemonConfig(rootConfig, &treeError)) {
|
||||
LOG_ERROR() << "DeviceBusManager: failed to load device_tree:" << treeError;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto nodes = m_treeModel.nodes();
|
||||
for (const auto& n : nodes) {
|
||||
if (!n.enabled) continue;
|
||||
auto kind = softbus::core::device::kindFromType(n.type);
|
||||
if (kind == softbus::core::device::DeviceKind::Unknown) {
|
||||
kind = softbus::core::device::inferDeviceKindFromEndpoint(n.endpoint);
|
||||
}
|
||||
|
||||
if (kind == softbus::core::device::DeviceKind::Serial) {
|
||||
initializeSerialDriver(n.endpoint, n.params);
|
||||
m_deviceEndpointsMap.insert(n.endpoint, QStringLiteral("serial"));
|
||||
} else {
|
||||
LOG_WARNING() << "DeviceBusManager: skip unsupported kind for endpoint=" << n.endpoint
|
||||
<< "type=" << n.type;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeviceBusManager::shutdown()
|
||||
{
|
||||
// 关闭并销毁所有串口驱动
|
||||
const auto keys = m_serialDriversMap.keys();
|
||||
for (const auto& endpoint : keys) {
|
||||
shutdownSerialDriver(endpoint);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceBusManager::initializeSerialDriver(const QString& endpoint,const QJsonObject& params)
|
||||
{
|
||||
if (m_serialDriversMap.contains(endpoint)) {
|
||||
LOG_WARNING() << "DeviceBusManager: serial driver already exists for" << endpoint;
|
||||
return;
|
||||
}
|
||||
|
||||
// 合并参数(defaults + enum 校验)
|
||||
serial_cap::SerialDefaults def = serial_cap::kDefaults;
|
||||
|
||||
int baud = params.value(QStringLiteral("baudRate")).toInt(def.baudRate);
|
||||
if (!serial_cap::isValidBaud(baud)) baud = def.baudRate;
|
||||
|
||||
int dataBits = params.value(QStringLiteral("dataBits")).toInt(def.dataBits);
|
||||
if (!serial_cap::isValidDataBits(dataBits)) dataBits = def.dataBits;
|
||||
|
||||
QString parityStr = params.value(QStringLiteral("parity")).toString(QLatin1String(def.parity));
|
||||
if (!serial_cap::isValidParity(parityStr)) parityStr = QLatin1String(def.parity);
|
||||
|
||||
int stopBitsVal = params.value(QStringLiteral("stopBits")).toInt(def.stopBits);
|
||||
if (!serial_cap::isValidStopBits(stopBitsVal)) stopBitsVal = def.stopBits;
|
||||
|
||||
QString flowStr = params.value(QStringLiteral("flowControl")).toString(QLatin1String(def.flowControl));
|
||||
if (!serial_cap::isValidFlowControl(flowStr)) flowStr = QLatin1String(def.flowControl);
|
||||
|
||||
QJsonObject merged;
|
||||
merged.insert(QStringLiteral("baudRate"), baud);
|
||||
merged.insert(QStringLiteral("dataBits"), dataBits);
|
||||
merged.insert(QStringLiteral("parity"), parityStr);
|
||||
merged.insert(QStringLiteral("stopBits"), stopBitsVal);
|
||||
merged.insert(QStringLiteral("flowControl"), flowStr);
|
||||
|
||||
LOG_INFO() << "DeviceBusManager: init serial endpoint=" << endpoint
|
||||
<< "params=" << QJsonDocument(merged).toJson(QJsonDocument::Compact);
|
||||
|
||||
auto driver = new SerialQtDriver(nullptr);
|
||||
driver->SetBaudRate(static_cast<QSerialPort::BaudRate>(baud));
|
||||
driver->SetDataBits(static_cast<QSerialPort::DataBits>(dataBits));
|
||||
|
||||
QSerialPort::Parity parity = QSerialPort::NoParity;
|
||||
if (parityStr == QStringLiteral("even")) {
|
||||
parity = QSerialPort::EvenParity;
|
||||
} else if (parityStr == QStringLiteral("odd")) {
|
||||
parity = QSerialPort::OddParity;
|
||||
}
|
||||
driver->SetParity(parity);
|
||||
|
||||
QSerialPort::StopBits stopBits = (stopBitsVal == 2) ? QSerialPort::TwoStop : QSerialPort::OneStop;
|
||||
driver->SetStopBits(stopBits);
|
||||
|
||||
QSerialPort::FlowControl flow = QSerialPort::NoFlowControl;
|
||||
if (flowStr == QStringLiteral("hardware")) {
|
||||
flow = QSerialPort::HardwareControl;
|
||||
} else if (flowStr == QStringLiteral("software")) {
|
||||
flow = QSerialPort::SoftwareControl;
|
||||
}
|
||||
driver->SetFlowControl(flow);
|
||||
|
||||
// 按你当前策略:初始化时就打开串口
|
||||
driver->Open(endpoint.toStdString());
|
||||
|
||||
m_serialDriversMap.insert(endpoint, driver);
|
||||
m_serialDriversList.push_back(driver);
|
||||
}
|
||||
|
||||
void DeviceBusManager::shutdownSerialDriver(const QString& endpoint)
|
||||
{
|
||||
auto driver = m_serialDriversMap.take(endpoint);
|
||||
if (driver) {
|
||||
driver->Close();
|
||||
delete driver;
|
||||
m_serialDriversList.removeAll(driver);
|
||||
}
|
||||
}
|
||||
42
src/device_bus/manager/DeviceBusManager.h
Normal file
42
src/device_bus/manager/DeviceBusManager.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QJsonObject>
|
||||
#include <QMap>
|
||||
#include <QList>
|
||||
#include <functional>
|
||||
|
||||
#include "device_bus/tree/DeviceTreeModel.h"
|
||||
#include "hardware/drivers/serial/SerialQtDriver.h"
|
||||
|
||||
class DeviceBusManager
|
||||
{
|
||||
public:
|
||||
bool initialize(const QJsonObject& rootConfig);
|
||||
void shutdown();
|
||||
|
||||
private:
|
||||
void initializeSerialDriver(const QString& endpoint, const QJsonObject& params);
|
||||
void shutdownSerialDriver(const QString& endpoint);
|
||||
// void initializeCanDriver();
|
||||
// void shutdownCanDriver();
|
||||
// void initializeTcpDriver();
|
||||
// void shutdownTcpDriver();
|
||||
// void initializeUdpDriver();
|
||||
// void shutdownUdpDriver();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
DeviceTreeModel m_treeModel;
|
||||
// 添加map来记住所有设备的endpoint和type的映射
|
||||
QMap<QString, QString> m_deviceEndpointsMap;
|
||||
|
||||
QMap<QString, softbus::hardware::drivers::serial::SerialQtDriver*> m_serialDriversMap;
|
||||
QList<softbus::hardware::drivers::serial::SerialQtDriver*> m_serialDriversList;
|
||||
|
||||
// std::vector<softbus::hardware::drivers::can::CanQtDriver*> m_canDrivers;
|
||||
// std::vector<softbus::hardware::drivers::tcp::TcpQtDriver*> m_tcpDrivers;
|
||||
// std::vector<softbus::hardware::drivers::udp::UdpQtDriver*> m_udpDrivers;
|
||||
};
|
||||
|
||||
24
src/device_bus/registry/IDeviceRegistry.h
Normal file
24
src/device_bus/registry/IDeviceRegistry.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "core/device/DeviceTypes.h"
|
||||
|
||||
namespace softbus::device_bus::registry
|
||||
{
|
||||
|
||||
class IDeviceRegistry
|
||||
{
|
||||
public:
|
||||
virtual ~IDeviceRegistry() = default;
|
||||
|
||||
virtual void registerDevice(const softbus::core::device::DeviceInfo& info) = 0;
|
||||
virtual void unregisterDevice(int id) = 0;
|
||||
|
||||
virtual std::optional<softbus::core::device::DeviceInfo> findById(int id) const = 0;
|
||||
virtual std::vector<softbus::core::device::DeviceInfo> listDevices() const = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::device_bus::registry
|
||||
|
||||
84
src/device_bus/tree/DeviceTreeModel.cpp
Normal file
84
src/device_bus/tree/DeviceTreeModel.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
#include "device_bus/tree/DeviceTreeModel.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
bool DeviceTreeModel::loadFromDaemonConfig(const QJsonObject& root, QString* errorMessage)
|
||||
{
|
||||
m_nodes.clear();
|
||||
m_indexById.clear();
|
||||
|
||||
if (!root.contains(QStringLiteral("device_tree"))) {
|
||||
if (errorMessage) {
|
||||
*errorMessage = QStringLiteral("daemon_config.json missing 'device_tree' field");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const QJsonValue treeVal = root.value(QStringLiteral("device_tree"));
|
||||
if (!treeVal.isArray()) {
|
||||
if (errorMessage) {
|
||||
*errorMessage = QStringLiteral("'device_tree' must be an array");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const QJsonArray arr = treeVal.toArray();
|
||||
m_nodes.reserve(arr.size());
|
||||
|
||||
for (const QJsonValue& v : arr) {
|
||||
if (!v.isObject()) {
|
||||
LOG_WARNING() << "DeviceTreeModel: skip non-object node in device_tree";
|
||||
continue;
|
||||
}
|
||||
const QJsonObject obj = v.toObject();
|
||||
|
||||
DeviceTreeNode node;
|
||||
node.id = obj.value(QStringLiteral("id")).toString();
|
||||
node.name = obj.value(QStringLiteral("name")).toString();
|
||||
node.type = obj.value(QStringLiteral("type")).toString();
|
||||
node.endpoint = obj.value(QStringLiteral("endpoint")).toString();
|
||||
node.driver = obj.value(QStringLiteral("driver")).toString();
|
||||
node.capabilitiesRef = obj.value(QStringLiteral("capabilitiesRef")).toString();
|
||||
node.params = obj.value(QStringLiteral("params")).toObject();
|
||||
node.enabled = obj.value(QStringLiteral("enabled")).toBool(true);
|
||||
|
||||
// children: array of ids
|
||||
const QJsonValue childrenVal = obj.value(QStringLiteral("children"));
|
||||
if (childrenVal.isArray()) {
|
||||
const QJsonArray childrenArr = childrenVal.toArray();
|
||||
for (const QJsonValue& c : childrenArr) {
|
||||
if (c.isString()) {
|
||||
node.childrenIds.push_back(c.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.id.isEmpty()) {
|
||||
LOG_WARNING() << "DeviceTreeModel: node without id, skipping";
|
||||
continue;
|
||||
}
|
||||
|
||||
const int index = m_nodes.size();
|
||||
m_nodes.push_back(node);
|
||||
m_indexById.insert(node.id, index);
|
||||
}
|
||||
|
||||
LOG_INFO() << "DeviceTreeModel loaded" << m_nodes.size() << "nodes from daemon_config";
|
||||
return true;
|
||||
}
|
||||
|
||||
const DeviceTreeNode* DeviceTreeModel::findById(const QString& id) const
|
||||
{
|
||||
const auto it = m_indexById.constFind(id);
|
||||
if (it == m_indexById.constEnd()) {
|
||||
return nullptr;
|
||||
}
|
||||
const int index = it.value();
|
||||
if (index < 0 || index >= m_nodes.size()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &m_nodes.at(index);
|
||||
}
|
||||
|
||||
37
src/device_bus/tree/DeviceTreeModel.h
Normal file
37
src/device_bus/tree/DeviceTreeModel.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QVector>
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
|
||||
// 轻量级设备树模型:从 daemon_config.json 的 device_tree 字段加载
|
||||
|
||||
struct DeviceTreeNode
|
||||
{
|
||||
QString id;
|
||||
QString name;
|
||||
QString type;
|
||||
QString endpoint;
|
||||
QString driver;
|
||||
QString capabilitiesRef;
|
||||
QJsonObject params;
|
||||
QVector<QString> childrenIds;
|
||||
bool enabled{true};
|
||||
};
|
||||
|
||||
class DeviceTreeModel
|
||||
{
|
||||
public:
|
||||
// 从给定的 JSON 根对象(包含 device_tree 字段)加载
|
||||
bool loadFromDaemonConfig(const QJsonObject& root, QString* errorMessage = nullptr);
|
||||
|
||||
const QVector<DeviceTreeNode>& nodes() const { return m_nodes; }
|
||||
|
||||
const DeviceTreeNode* findById(const QString& id) const;
|
||||
|
||||
private:
|
||||
QVector<DeviceTreeNode> m_nodes;
|
||||
QHash<QString, int> m_indexById;
|
||||
};
|
||||
|
||||
17
src/devices/base/IDevice.h
Normal file
17
src/devices/base/IDevice.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "core/device/DeviceTypes.h"
|
||||
|
||||
namespace softbus::devices
|
||||
{
|
||||
|
||||
class IDevice
|
||||
{
|
||||
public:
|
||||
virtual ~IDevice() = default;
|
||||
|
||||
virtual softbus::core::device::DeviceInfo deviceInfo() const = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::devices
|
||||
|
||||
14
src/devices/devicesType.h
Normal file
14
src/devices/devicesType.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace softbus::devices::physical
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
Serial,
|
||||
Can,
|
||||
Tcp,
|
||||
Udp,
|
||||
};
|
||||
}
|
||||
67
src/hardware/drivers/serial/SerialCapabilities.h
Normal file
67
src/hardware/drivers/serial/SerialCapabilities.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <QString>
|
||||
|
||||
namespace softbus::hardware::drivers::serial::capabilities
|
||||
{
|
||||
|
||||
struct SerialDefaults
|
||||
{
|
||||
int baudRate = 115200;
|
||||
int dataBits = 8;
|
||||
const char* parity = "none";
|
||||
int stopBits = 1;
|
||||
const char* flowControl = "none";
|
||||
};
|
||||
|
||||
inline constexpr SerialDefaults kDefaults{};
|
||||
|
||||
inline constexpr std::array<int, 5> kBaudRates{9600, 19200, 38400, 57600, 115200};
|
||||
inline constexpr std::array<int, 4> kDataBits{5, 6, 7, 8};
|
||||
inline constexpr std::array<const char*, 3> kParity{"none", "even", "odd"};
|
||||
inline constexpr std::array<int, 2> kStopBits{1, 2};
|
||||
inline constexpr std::array<const char*, 3> kFlowControl{"none", "hardware", "software"};
|
||||
|
||||
inline bool isValidBaud(int v)
|
||||
{
|
||||
for (int b : kBaudRates) {
|
||||
if (b == v) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isValidDataBits(int v)
|
||||
{
|
||||
for (int b : kDataBits) {
|
||||
if (b == v) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isValidParity(const QString& s)
|
||||
{
|
||||
for (const char* p : kParity) {
|
||||
if (s == QLatin1String(p)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isValidStopBits(int v)
|
||||
{
|
||||
for (int b : kStopBits) {
|
||||
if (b == v) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isValidFlowControl(const QString& s)
|
||||
{
|
||||
for (const char* f : kFlowControl) {
|
||||
if (s == QLatin1String(f)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace softbus::hardware::drivers::serial::capabilities
|
||||
|
||||
138
src/hardware/drivers/serial/SerialQtDriver.cpp
Normal file
138
src/hardware/drivers/serial/SerialQtDriver.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "hardware/drivers/serial/SerialQtDriver.h"
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
namespace softbus::hardware::drivers::serial
|
||||
{
|
||||
|
||||
SerialQtDriver::SerialQtDriver(QObject* parent)
|
||||
: QObject(parent),
|
||||
m_port(this)
|
||||
{
|
||||
connect(&m_port, &QSerialPort::readyRead, this, &SerialQtDriver::handleReadyRead);
|
||||
connect(&m_port, &QSerialPort::errorOccurred, this, &SerialQtDriver::handleError);
|
||||
}
|
||||
|
||||
SerialQtDriver::~SerialQtDriver()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool SerialQtDriver::Open(const std::string& endpoint)
|
||||
{
|
||||
if (m_port.isOpen()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
m_port.setPortName(QString::fromStdString(endpoint));
|
||||
if (!m_port.open(QIODevice::ReadWrite)) {
|
||||
if (m_errorCallback) {
|
||||
m_errorCallback(m_port.errorString().toStdString());
|
||||
}
|
||||
LOG_WARNING() << "SerialQtDriver: failed to open port" << m_port.portName() << ":" << m_port.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG() << "SerialQtDriver: opened port" << m_port.portName();
|
||||
return true;
|
||||
}
|
||||
|
||||
void SerialQtDriver::Close()
|
||||
{
|
||||
if (m_port.isOpen()) {
|
||||
const QString name = m_port.portName();
|
||||
m_port.close();
|
||||
LOG_DEBUG() << "SerialQtDriver: closed port" << name;
|
||||
}
|
||||
}
|
||||
|
||||
bool SerialQtDriver::Write(const std::vector<std::uint8_t>& data)
|
||||
{
|
||||
if (!m_port.isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const QByteArray bytes(reinterpret_cast<const char*>(data.data()), static_cast<int>(data.size()));
|
||||
const qint64 written = m_port.write(bytes);
|
||||
if (written != bytes.size()) {
|
||||
LOG_WARNING() << "SerialQtDriver: partial write on" << m_port.portName() << "written" << written << "of"
|
||||
<< bytes.size();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SerialQtDriver::SetReadCallback(ReadCallback cb)
|
||||
{
|
||||
m_readCallback = std::move(cb);
|
||||
}
|
||||
|
||||
void SerialQtDriver::SetErrorCallback(ErrorCallback cb)
|
||||
{
|
||||
m_errorCallback = std::move(cb);
|
||||
}
|
||||
|
||||
void SerialQtDriver::SetBaudRate(QSerialPort::BaudRate baud)
|
||||
{
|
||||
m_port.setBaudRate(baud);
|
||||
}
|
||||
|
||||
void SerialQtDriver::SetDataBits(QSerialPort::DataBits bits)
|
||||
{
|
||||
m_port.setDataBits(bits);
|
||||
}
|
||||
|
||||
void SerialQtDriver::SetParity(QSerialPort::Parity parity)
|
||||
{
|
||||
m_port.setParity(parity);
|
||||
}
|
||||
|
||||
void SerialQtDriver::SetStopBits(QSerialPort::StopBits stopBits)
|
||||
{
|
||||
m_port.setStopBits(stopBits);
|
||||
}
|
||||
|
||||
void SerialQtDriver::SetFlowControl(QSerialPort::FlowControl flow)
|
||||
{
|
||||
m_port.setFlowControl(flow);
|
||||
}
|
||||
|
||||
void SerialQtDriver::handleReadyRead()
|
||||
{
|
||||
if (!m_readCallback) {
|
||||
const QByteArray data = m_port.readAll();
|
||||
LOG_DEBUG() << "SerialQtDriver: dropped" << data.size() << "bytes on" << m_port.portName()
|
||||
<< "because no read callback is set";
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray data = m_port.readAll();
|
||||
if (data.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::uint8_t> buffer(reinterpret_cast<const std::uint8_t*>(data.constData()),
|
||||
reinterpret_cast<const std::uint8_t*>(data.constData()) + data.size());
|
||||
m_readCallback(buffer);
|
||||
}
|
||||
|
||||
void SerialQtDriver::handleError(QSerialPort::SerialPortError error)
|
||||
{
|
||||
if (error == QSerialPort::NoError) {
|
||||
return;
|
||||
}
|
||||
|
||||
const QString msg =
|
||||
QStringLiteral("SerialQtDriver error on %1: %2").arg(m_port.portName(), m_port.errorString());
|
||||
|
||||
LOG_WARNING() << msg;
|
||||
|
||||
if (m_errorCallback) {
|
||||
m_errorCallback(msg.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace softbus::hardware::drivers::serial
|
||||
|
||||
85
src/hardware/drivers/serial/SerialQtDriver.h
Normal file
85
src/hardware/drivers/serial/SerialQtDriver.h
Normal file
@@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QSerialPort>
|
||||
#include <QString>
|
||||
|
||||
#include "hardware/interfaces/IStreamDriver.h"
|
||||
|
||||
// 这里的串口的唯一标识是串口的端口名,如 /dev/ttyUSB0, can0, tcp://...
|
||||
// 串口的endpoint是串口的端口名,如 /dev/ttyUSB0, can0, tcp://...
|
||||
// 使用说明:
|
||||
// 1. 创建一个SerialQtDriver对象
|
||||
// 2. 调用Open方法打开串口
|
||||
// 3. 调用Write方法写数据
|
||||
// 4. 调用SetReadCallback方法设置读回调
|
||||
// 5. 调用SetErrorCallback方法设置错误回调
|
||||
// 6. 调用Close方法关闭串口
|
||||
// 7. 调用SetBaudRate方法设置波特率
|
||||
// 8. 调用SetDataBits方法设置数据位
|
||||
// 9. 调用SetParity方法设置校验位
|
||||
// 10. 调用SetStopBits方法设置停止位
|
||||
// 11. 调用SetFlowControl方法设置流控制
|
||||
// eg:
|
||||
// SerialQtDriver driver;
|
||||
// driver.Open("/dev/ttyUSB0");
|
||||
// driver.Write({0x01, 0x02, 0x03});
|
||||
// driver.SetReadCallback([](const std::vector<std::uint8_t>& data) {
|
||||
// std::cout << "read data: " << data << std::endl;
|
||||
// });
|
||||
// driver.SetErrorCallback([](const std::string& error) {
|
||||
// std::cout << "error: " << error << std::endl;
|
||||
// });
|
||||
// driver.Close();
|
||||
// 12. 调用SetBaudRate方法设置波特率
|
||||
// 13. 调用SetDataBits方法设置数据位
|
||||
// 14. 调用SetParity方法设置校验位
|
||||
// 15. 调用SetStopBits方法设置停止位
|
||||
// 16. 调用SetFlowControl方法设置流控制
|
||||
// eg:
|
||||
// driver.SetBaudRate(QSerialPort::Baud115200);
|
||||
// driver.SetDataBits(QSerialPort::Data8);
|
||||
// driver.SetParity(QSerialPort::NoParity);
|
||||
// driver.SetStopBits(QSerialPort::OneStop);
|
||||
// driver.SetFlowControl(QSerialPort::NoFlowControl);
|
||||
// driver.Close();
|
||||
|
||||
namespace softbus::hardware::drivers::serial
|
||||
{
|
||||
|
||||
// 基于 Qt 的串口驱动实现:只负责串口 open/read/write,不包含设备注册、数据库或协议逻辑
|
||||
class SerialQtDriver : public QObject, public softbus::hardware::interfaces::IStreamDriver
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SerialQtDriver(QObject* parent = nullptr);
|
||||
~SerialQtDriver() override;
|
||||
|
||||
bool Open(const std::string& endpoint) override;
|
||||
void Close() override;
|
||||
|
||||
bool Write(const std::vector<std::uint8_t>& data) override;
|
||||
|
||||
void SetReadCallback(ReadCallback cb) override;
|
||||
void SetErrorCallback(ErrorCallback cb) override;
|
||||
|
||||
// 允许上层配置串口参数(最小集合)
|
||||
void SetBaudRate(QSerialPort::BaudRate baud);
|
||||
void SetDataBits(QSerialPort::DataBits bits);
|
||||
void SetParity(QSerialPort::Parity parity);
|
||||
void SetStopBits(QSerialPort::StopBits stopBits);
|
||||
void SetFlowControl(QSerialPort::FlowControl flow);
|
||||
|
||||
private slots:
|
||||
void handleReadyRead();
|
||||
void handleError(QSerialPort::SerialPortError error);
|
||||
|
||||
private:
|
||||
QSerialPort m_port;
|
||||
ReadCallback m_readCallback;
|
||||
ErrorCallback m_errorCallback;
|
||||
};
|
||||
|
||||
} // namespace softbus::hardware::drivers::serial
|
||||
|
||||
37
src/hardware/interfaces/IDeviceWatcher.h
Normal file
37
src/hardware/interfaces/IDeviceWatcher.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace softbus::hardware::interfaces
|
||||
{
|
||||
|
||||
struct DiscoveredDevice
|
||||
{
|
||||
std::string id; // 稳定 ID(如序列号、路径)
|
||||
std::string endpoint; // 打开所需的 endpoint(如 /dev/ttyUSB0, can0, tcp://...)
|
||||
std::string type; // 设备类型:serial / can / ethernet / usb 等
|
||||
};
|
||||
|
||||
// 设备发现 / 监控接口:负责发现插拔事件,不负责创建设备或驱动实例
|
||||
class IDeviceWatcher
|
||||
{
|
||||
public:
|
||||
using DeviceAttachedCallback = std::function<void(const DiscoveredDevice&)>;
|
||||
using DeviceDetachedCallback = std::function<void(const DiscoveredDevice&)>;
|
||||
|
||||
virtual ~IDeviceWatcher() = default;
|
||||
|
||||
virtual bool Start() = 0;
|
||||
virtual void Stop() = 0;
|
||||
|
||||
virtual void SetDeviceAttachedCallback(DeviceAttachedCallback cb) = 0;
|
||||
virtual void SetDeviceDetachedCallback(DeviceDetachedCallback cb) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::hardware::interfaces
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
41
src/hardware/interfaces/IFrameDriver.h
Normal file
41
src/hardware/interfaces/IFrameDriver.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace softbus::hardware::interfaces
|
||||
{
|
||||
|
||||
struct Frame
|
||||
{
|
||||
std::vector<std::uint8_t> payload;
|
||||
std::uint32_t id{0}; // 如 CAN ID
|
||||
std::uint64_t timestamp{0};
|
||||
};
|
||||
|
||||
// 面向帧设备(如 CAN 总线)的统一驱动接口
|
||||
class IFrameDriver
|
||||
{
|
||||
public:
|
||||
using FrameCallback = std::function<void(const Frame&)>;
|
||||
using ErrorCallback = std::function<void(const std::string& message)>;
|
||||
|
||||
virtual ~IFrameDriver() = default;
|
||||
|
||||
virtual bool Open(const std::string& endpoint) = 0;
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual bool WriteFrame(const Frame& frame) = 0;
|
||||
|
||||
virtual void SetFrameCallback(FrameCallback cb) = 0;
|
||||
virtual void SetErrorCallback(ErrorCallback cb) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::hardware::interfaces
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
34
src/hardware/interfaces/IStreamDriver.h
Normal file
34
src/hardware/interfaces/IStreamDriver.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace softbus::hardware::interfaces
|
||||
{
|
||||
|
||||
// 面向字节流设备的统一驱动接口:串口 / TCP / UDP 等
|
||||
class IStreamDriver
|
||||
{
|
||||
public:
|
||||
using ReadCallback = std::function<void(const std::vector<std::uint8_t>&)>;
|
||||
using ErrorCallback = std::function<void(const std::string& message)>;
|
||||
|
||||
virtual ~IStreamDriver() = default;
|
||||
|
||||
virtual bool Open(const std::string& endpoint) = 0;
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual bool Write(const std::vector<std::uint8_t>& data) = 0;
|
||||
|
||||
virtual void SetReadCallback(ReadCallback cb) = 0;
|
||||
virtual void SetErrorCallback(ErrorCallback cb) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::hardware::interfaces
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
class PipelineContext {
|
||||
public:
|
||||
PipelineContext() = default;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
class PipelineEngine {
|
||||
public:
|
||||
PipelineEngine() = default;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
class LogStream {
|
||||
public:
|
||||
LogStream() = default;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
#ifndef LOGGING_H
|
||||
#define LOGGING_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLoggingCategory>
|
||||
#include <QString>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
/**
|
||||
* @file logging.h
|
||||
* @brief 日志宏定义,提供带文件名和函数名的日志输出,并异步存储到数据库
|
||||
*/
|
||||
|
||||
// 获取文件名(不含路径)
|
||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
// 构建来源字符串的辅助宏
|
||||
// #define __LOG_SOURCE__ (QString(__FILENAME__) + "." + QString(__FUNCTION__))
|
||||
|
||||
// 日志宏,格式:[文件名.函数名] 消息
|
||||
|
||||
#define LOG_DEBUG() \
|
||||
qDebug() << "[" << __FILENAME__ << "/" << __FUNCTION__ << "]"
|
||||
|
||||
#define LOG_ERROR() \
|
||||
qCritical() << "[" << __FILENAME__ << "/" << __FUNCTION__ << "]"
|
||||
|
||||
#define LOG_INFO() \
|
||||
qInfo() << "[" << __FILENAME__ << "/" << __FUNCTION__ << "]"
|
||||
|
||||
#define LOG_WARNING() \
|
||||
qWarning() << "[" << __FILENAME__ << "/" << __FUNCTION__ << "]"
|
||||
|
||||
#endif // LOGGING_H
|
||||
|
||||
#ifndef LOGGING_H
|
||||
#define LOGGING_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QLoggingCategory>
|
||||
#include <QString>
|
||||
#include <cstring>
|
||||
|
||||
|
||||
/**
|
||||
* @file logging.h
|
||||
* @brief 日志宏定义,提供带文件名和函数名的日志输出,并异步存储到数据库
|
||||
*/
|
||||
|
||||
// 获取文件名(不含路径)
|
||||
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
|
||||
// 构建来源字符串的辅助宏
|
||||
// #define __LOG_SOURCE__ (QString(__FILENAME__) + "." + QString(__FUNCTION__))
|
||||
|
||||
// 日志宏,格式:[文件名.函数名] 消息
|
||||
|
||||
#define LOG_DEBUG() \
|
||||
qDebug() << "[" << __FILENAME__ << "/" << __FUNCTION__ << "]"
|
||||
|
||||
#define LOG_ERROR() \
|
||||
qCritical() << "[" << __FILENAME__ << "/" << __FUNCTION__ << "]"
|
||||
|
||||
#define LOG_INFO() \
|
||||
qInfo() << "[" << __FILENAME__ << "/" << __FUNCTION__ << "]"
|
||||
|
||||
#define LOG_WARNING() \
|
||||
qWarning() << "[" << __FILENAME__ << "/" << __FUNCTION__ << "]"
|
||||
|
||||
#endif // LOGGING_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user