This commit is contained in:
flower_linux
2026-03-12 14:56:53 +08:00
parent 22ee28f33b
commit 9a2224f185
62 changed files with 1597 additions and 505 deletions

View File

@@ -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() 输出
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -2,6 +2,7 @@
#include <QObject>
class CoreService : public QObject {
Q_OBJECT

View 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

View 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

View File

@@ -4,4 +4,4 @@
class LockFreeQueue {
public:
LockFreeQueue() = default;
};
};

View File

@@ -4,4 +4,4 @@
class MemoryPool {
public:
MemoryPool() = default;
};
};

View File

@@ -2,4 +2,4 @@
// Placeholder for data trace model.
struct DataTrace {
};
};

View File

@@ -2,4 +2,4 @@
// Placeholder for metadata model.
struct Metadata {
};
};

View File

@@ -4,4 +4,4 @@
class IProtocolPlugin {
public:
virtual ~IProtocolPlugin() = default;
};
};

View File

@@ -4,4 +4,4 @@
class PluginManager {
public:
PluginManager() = default;
};
};

View 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

View 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

View 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;
}

View 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;
};

View 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);
}
}

View 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;
};

View 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

View 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);
}

View 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;
};

View 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
View File

@@ -0,0 +1,14 @@
#pragma once
#include <QString>
namespace softbus::devices::physical
{
enum class Type
{
Serial,
Can,
Tcp,
Udp,
};
}

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -4,4 +4,4 @@
class PipelineContext {
public:
PipelineContext() = default;
};
};

View File

@@ -4,4 +4,4 @@
class PipelineEngine {
public:
PipelineEngine() = default;
};
};

View File

@@ -4,4 +4,4 @@
class LogStream {
public:
LogStream() = default;
};
};

View File

@@ -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