This commit is contained in:
flower_linux
2026-03-18 16:31:32 +08:00
parent 9a2224f185
commit 91a3361d1f
26 changed files with 478 additions and 119 deletions

View File

@@ -1,12 +1,22 @@
#include "device_bus/DeviceBus.h"
#include <QDir>
#include <QFileInfo>
#include <QJsonDocument>
#include <QSaveFile>
#include "device_bus/manager/DeviceBusManager.h"
#include "device_bus/tree/DeviceTreeModel.h"
#include "utils/logs/logging.h"
namespace softbus::device_bus {
class DeviceBus::Impl {
public:
DeviceBusManager manager;
std::shared_ptr<DeviceTreeModel> treeModel;
QString configPath;
bool deviceTreeDirty{false};
};
DeviceBus &DeviceBus::instance() {
@@ -22,9 +32,65 @@ DeviceBus::~DeviceBus() {
}
bool DeviceBus::initialize(const QJsonObject &rootConfig) {
if (!d->treeModel) {
d->treeModel = std::make_shared<DeviceTreeModel>();
}
d->manager.setDeviceTreeModel(d->treeModel);
return d->manager.initialize(rootConfig);
}
void DeviceBus::shutdown() { d->manager.shutdown(); }
void DeviceBus::shutdown() {
d->manager.shutdown();
if (!d->deviceTreeDirty) {
return;
}
if (d->configPath.isEmpty() || !d->treeModel) {
return;
}
const QFileInfo fi(d->configPath);
const QString dirPath = fi.dir().absolutePath();
if (!QDir().mkpath(dirPath)) {
LOG_ERROR() << "DeviceBus: failed to create config dir" << dirPath;
return;
}
const QJsonObject root = d->treeModel->toDaemonConfigRoot();
const QByteArray bytes = QJsonDocument(root).toJson(QJsonDocument::Indented);
QSaveFile out(d->configPath);
if (!out.open(QIODevice::WriteOnly | QIODevice::Text)) {
LOG_ERROR() << "DeviceBus: failed to open config for write:" << d->configPath;
return;
}
if (out.write(bytes) != bytes.size()) {
LOG_ERROR() << "DeviceBus: failed to write config:" << d->configPath;
out.cancelWriting();
return;
}
if (!out.commit()) {
LOG_ERROR() << "DeviceBus: failed to commit config:" << d->configPath;
return;
}
d->deviceTreeDirty = false;
}
void DeviceBus::setConfigPath(const QString& path) {
d->configPath = path;
}
QString DeviceBus::configPath() const {
return d->configPath;
}
std::shared_ptr<DeviceTreeModel> DeviceBus::deviceTreeModel() const {
return d->treeModel;
}
void DeviceBus::markDeviceTreeDirty() {
d->deviceTreeDirty = true;
}
} // namespace softbus::device_bus

View File

@@ -1,6 +1,10 @@
#pragma once
#include <QJsonObject>
#include <QString>
#include <memory>
#include "device_bus/tree/DeviceTreeModel.h"
namespace softbus::device_bus {
@@ -11,6 +15,15 @@ public:
bool initialize(const QJsonObject &rootConfig);
void shutdown();
void setConfigPath(const QString& path);
QString configPath() const;
// 共享设备树模型(单一真源)
std::shared_ptr<DeviceTreeModel> deviceTreeModel() const;
// 注册/更新设备树后调用,确保 shutdown 会落盘
void markDeviceTreeDirty();
private:
DeviceBus();
~DeviceBus();

View File

@@ -1,35 +1,49 @@
#include "device_bus/manager/DeviceBusManager.h"
#include <memory>
#include <QJsonDocument>
#include <QSerialPort>
#include <algorithm>
#include "hardware/drivers/serial/SerialQtDriver.h"
#include "hardware/drivers/serial/SerialCapabilities.h"
#include "core/device/DeviceTypes.h"
#include "devices/DeviceTypes.h"
#include "utils/logs/logging.h"
using softbus::hardware::drivers::serial::SerialQtDriver;
namespace serial_cap = softbus::hardware::drivers::serial::capabilities;
void DeviceBusManager::setDeviceTreeModel(std::shared_ptr<DeviceTreeModel> model)
{
m_treeModel = std::move(model);
}
bool DeviceBusManager::initialize(const QJsonObject& rootConfig)
{
if (!m_treeModel) {
m_treeModel = std::make_shared<DeviceTreeModel>();
}
// 加载设备树
QString treeError;
if (!m_treeModel.loadFromDaemonConfig(rootConfig, &treeError)) {
if (!m_treeModel->loadFromDaemonConfig(rootConfig, &treeError)) {
LOG_ERROR() << "DeviceBusManager: failed to load device_tree:" << treeError;
return false;
}
const auto nodes = m_treeModel.nodes();
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);
auto kind = softbus::devices::kindFromType(n.type);
if (kind == softbus::devices::DeviceKind::Unknown) {
kind = softbus::devices::inferDeviceKindFromEndpoint(n.endpoint);
}
if (kind == softbus::core::device::DeviceKind::Serial) {
initializeSerialDriver(n.endpoint, n.params);
m_deviceEndpointsMap.insert(n.endpoint, QStringLiteral("serial"));
if (kind == softbus::devices::DeviceKind::Serial) {
initializeSerialDevice(n.endpoint, n.params);
m_deviceEndpointsMap.insert(n.endpoint, kind);
} else {
LOG_WARNING() << "DeviceBusManager: skip unsupported kind for endpoint=" << n.endpoint
<< "type=" << n.type;
@@ -41,17 +55,17 @@ bool DeviceBusManager::initialize(const QJsonObject& rootConfig)
void DeviceBusManager::shutdown()
{
// 关闭并销毁所有串口驱动
const auto keys = m_serialDriversMap.keys();
// 关闭并销毁所有串口设备
const auto keys = m_serialDevicesByEndpoint.keys();
for (const auto& endpoint : keys) {
shutdownSerialDriver(endpoint);
shutdownSerialDevice(endpoint);
}
}
void DeviceBusManager::initializeSerialDriver(const QString& endpoint,const QJsonObject& params)
void DeviceBusManager::initializeSerialDevice(const QString& endpoint, const QJsonObject& params)
{
if (m_serialDriversMap.contains(endpoint)) {
LOG_WARNING() << "DeviceBusManager: serial driver already exists for" << endpoint;
if (m_serialDevicesByEndpoint.contains(endpoint)) {
LOG_WARNING() << "DeviceBusManager: serial device already exists for" << endpoint;
return;
}
@@ -83,7 +97,7 @@ void DeviceBusManager::initializeSerialDriver(const QString& endpoint,const QJso
LOG_INFO() << "DeviceBusManager: init serial endpoint=" << endpoint
<< "params=" << QJsonDocument(merged).toJson(QJsonDocument::Compact);
auto driver = new SerialQtDriver(nullptr);
auto driver = std::make_unique<SerialQtDriver>(nullptr);
driver->SetBaudRate(static_cast<QSerialPort::BaudRate>(baud));
driver->SetDataBits(static_cast<QSerialPort::DataBits>(dataBits));
@@ -106,19 +120,51 @@ void DeviceBusManager::initializeSerialDriver(const QString& endpoint,const QJso
}
driver->SetFlowControl(flow);
// 按你当前策略:初始化时就打开串口
driver->Open(endpoint.toStdString());
softbus::devices::DeviceInfo info;
info.id = -1;
info.endpoint = endpoint;
info.type = QStringLiteral("serial");
info.kind = softbus::devices::DeviceKind::Serial;
m_serialDriversMap.insert(endpoint, driver);
m_serialDriversList.push_back(driver);
softbus::devices::physical::SerialDevice::Config cfg;
cfg.endpoint = endpoint;
cfg.baudRate = baud;
cfg.dataBits = dataBits;
cfg.parity = parityStr;
cfg.stopBits = stopBitsVal;
cfg.flowControl = flowStr;
QSharedPointer<softbus::devices::physical::SerialDevice> device(
new softbus::devices::physical::SerialDevice(std::move(driver), cfg, info));
if (m_registry) {
m_registry->registerDevice(info);
}
// 按当前策略:初始化时就打开串口
if (!device->start()) {
LOG_ERROR() << "DeviceBusManager: failed to start serial device for" << endpoint;
return;
}
m_serialDevicesByEndpoint.insert(endpoint, device);
}
void DeviceBusManager::shutdownSerialDriver(const QString& endpoint)
void DeviceBusManager::shutdownSerialDevice(const QString& endpoint)
{
auto driver = m_serialDriversMap.take(endpoint);
if (driver) {
driver->Close();
delete driver;
m_serialDriversList.removeAll(driver);
auto it = m_serialDevicesByEndpoint.find(endpoint);
if (it == m_serialDevicesByEndpoint.end()) {
return;
}
auto device = it.value();
if (device) {
auto info = device->deviceInfo();
if (m_registry && info.id >= 0) {
m_registry->unregisterDevice(info.id);
}
device->stop();
}
m_serialDevicesByEndpoint.erase(it);
}

View File

@@ -4,20 +4,26 @@
#include <QJsonObject>
#include <QMap>
#include <QList>
#include <functional>
#include <QHash>
#include <QSharedPointer>
#include <memory>
#include "device_bus/tree/DeviceTreeModel.h"
#include "hardware/drivers/serial/SerialQtDriver.h"
#include "device_bus/registry/IDeviceRegistry.h"
#include "devices/DeviceTypes.h"
#include "devices/physical/SerialDevice.h"
class DeviceBusManager
{
public:
void setDeviceTreeModel(std::shared_ptr<DeviceTreeModel> model);
bool initialize(const QJsonObject& rootConfig);
void shutdown();
private:
void initializeSerialDriver(const QString& endpoint, const QJsonObject& params);
void shutdownSerialDriver(const QString& endpoint);
void initializeSerialDevice(const QString& endpoint, const QJsonObject& params);
void shutdownSerialDevice(const QString& endpoint);
// void initializeCanDriver();
// void shutdownCanDriver();
// void initializeTcpDriver();
@@ -28,12 +34,13 @@ private:
private:
DeviceTreeModel m_treeModel;
std::shared_ptr<DeviceTreeModel> m_treeModel;
// 添加map来记住所有设备的endpoint和type的映射
QMap<QString, QString> m_deviceEndpointsMap;
QMap<QString, softbus::devices::DeviceKind> m_deviceEndpointsMap;
QMap<QString, softbus::hardware::drivers::serial::SerialQtDriver*> m_serialDriversMap;
QList<softbus::hardware::drivers::serial::SerialQtDriver*> m_serialDriversList;
QHash<QString, QSharedPointer<softbus::devices::physical::SerialDevice>> m_serialDevicesByEndpoint;
softbus::device_bus::registry::IDeviceRegistry* m_registry = nullptr;
// std::vector<softbus::hardware::drivers::can::CanQtDriver*> m_canDrivers;
// std::vector<softbus::hardware::drivers::tcp::TcpQtDriver*> m_tcpDrivers;

View File

@@ -3,7 +3,7 @@
#include <optional>
#include <vector>
#include "core/device/DeviceTypes.h"
#include "devices/DeviceTypes.h"
namespace softbus::device_bus::registry
{
@@ -13,11 +13,11 @@ class IDeviceRegistry
public:
virtual ~IDeviceRegistry() = default;
virtual void registerDevice(const softbus::core::device::DeviceInfo& info) = 0;
virtual void registerDevice(const softbus::devices::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;
virtual std::optional<softbus::devices::DeviceInfo> findById(int id) const = 0;
virtual std::vector<softbus::devices::DeviceInfo> listDevices() const = 0;
};
} // namespace softbus::device_bus::registry

View File

@@ -1,6 +1,7 @@
#include "device_bus/tree/DeviceTreeModel.h"
#include <QJsonArray>
#include <QJsonObject>
#include "utils/logs/logging.h"
@@ -69,6 +70,52 @@ bool DeviceTreeModel::loadFromDaemonConfig(const QJsonObject& root, QString* err
return true;
}
void DeviceTreeModel::rebuildIndex()
{
m_indexById.clear();
for (int i = 0; i < m_nodes.size(); ++i) {
const auto& n = m_nodes.at(i);
if (!n.id.isEmpty()) {
m_indexById.insert(n.id, i);
}
}
}
QJsonArray DeviceTreeModel::toDeviceTreeJson() const
{
QJsonArray arr;
for (const auto& n : m_nodes) {
QJsonObject obj;
obj.insert(QStringLiteral("id"), n.id);
if (!n.name.isEmpty()) obj.insert(QStringLiteral("name"), n.name);
if (!n.type.isEmpty()) obj.insert(QStringLiteral("type"), n.type);
if (!n.endpoint.isEmpty()) obj.insert(QStringLiteral("endpoint"), n.endpoint);
if (!n.driver.isEmpty()) obj.insert(QStringLiteral("driver"), n.driver);
if (!n.capabilitiesRef.isEmpty()) obj.insert(QStringLiteral("capabilitiesRef"), n.capabilitiesRef);
if (!n.params.isEmpty()) obj.insert(QStringLiteral("params"), n.params);
obj.insert(QStringLiteral("enabled"), n.enabled);
if (!n.childrenIds.isEmpty()) {
QJsonArray children;
for (const auto& c : n.childrenIds) {
children.append(c);
}
obj.insert(QStringLiteral("children"), children);
}
arr.append(obj);
}
return arr;
}
QJsonObject DeviceTreeModel::toDaemonConfigRoot() const
{
QJsonObject root;
root.insert(QStringLiteral("device_tree"), toDeviceTreeJson());
return root;
}
const DeviceTreeNode* DeviceTreeModel::findById(const QString& id) const
{
const auto it = m_indexById.constFind(id);

View File

@@ -1,6 +1,7 @@
#pragma once
#include <QJsonObject>
#include <QJsonArray>
#include <QVector>
#include <QString>
#include <QHash>
@@ -27,9 +28,17 @@ public:
bool loadFromDaemonConfig(const QJsonObject& root, QString* errorMessage = nullptr);
const QVector<DeviceTreeNode>& nodes() const { return m_nodes; }
QVector<DeviceTreeNode>& nodesMutable() { return m_nodes; }
const DeviceTreeNode* findById(const QString& id) const;
// 序列化为 daemon_config.json 所需格式
QJsonArray toDeviceTreeJson() const;
QJsonObject toDaemonConfigRoot() const;
// 当外部直接修改 nodesMutable() 后,需要重建索引
void rebuildIndex();
private:
QVector<DeviceTreeNode> m_nodes;
QHash<QString, int> m_indexById;