log0.3
This commit is contained in:
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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user