devicesbus read data
This commit is contained in:
@@ -97,6 +97,8 @@ qt_add_executable(softbus_daemon
|
||||
src/device_bus/DeviceBus.cpp
|
||||
src/device_bus/manager/DeviceBusManager.h
|
||||
src/device_bus/manager/DeviceBusManager.cpp
|
||||
src/device_bus/manager/SerialDeviceManager.h
|
||||
src/device_bus/manager/SerialDeviceManager.cpp
|
||||
|
||||
# device bus: registry skeleton
|
||||
src/device_bus/registry/IDeviceRegistry.h
|
||||
@@ -110,6 +112,32 @@ qt_add_executable(softbus_daemon
|
||||
# devices: physical
|
||||
src/devices/physical/SerialDevice.h
|
||||
src/devices/physical/SerialDevice.cpp
|
||||
|
||||
# core memory/plugin
|
||||
src/core/memory/MemoryPool.h
|
||||
src/core/memory/LockFreeQueue.h
|
||||
src/core/plugin_system/IProtocolPlugin.h
|
||||
src/core/plugin_system/PluginManager.h
|
||||
src/core/plugin_system/PluginManager.cpp
|
||||
|
||||
# message bus pipeline
|
||||
src/message_bus/pipeline/PayloadRef.h
|
||||
src/message_bus/pipeline/PipelineContext.h
|
||||
src/message_bus/pipeline/PipelineEngine.h
|
||||
src/message_bus/pipeline/PipelineEngine.cpp
|
||||
src/message_bus/pipeline/stages/1_framers/IFramer.h
|
||||
src/message_bus/pipeline/stages/1_framers/DefaultFramer.cpp
|
||||
src/message_bus/pipeline/stages/2_parsers/IParserStage.h
|
||||
src/message_bus/pipeline/stages/3_filters/IFilterStage.h
|
||||
src/message_bus/pipeline/stages/4_validators/IValidator.h
|
||||
|
||||
# message bus ingress/egress
|
||||
src/message_bus/ingress/IIngressPort.h
|
||||
src/message_bus/ingress/DriverIngressAdapter.h
|
||||
src/message_bus/ingress/DriverIngressAdapter.cpp
|
||||
src/message_bus/egress/IEgressPort.h
|
||||
src/message_bus/egress/EgressRouter.h
|
||||
src/message_bus/egress/EgressRouter.cpp
|
||||
)
|
||||
|
||||
target_include_directories(softbus_daemon
|
||||
|
||||
Binary file not shown.
2
main.cpp
2
main.cpp
@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
app.setApplicationName("soft_bus_daemon");
|
||||
app.setApplicationVersion("1.0.0");
|
||||
app.setApplicationVersion("1.1.0");
|
||||
app.setOrganizationName("soft_bus");
|
||||
|
||||
// ==================================
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Placeholder for can_raw plugin
|
||||
add_library(can_raw SHARED)
|
||||
# Placeholder for can_raw plugin
|
||||
add_library(can_raw SHARED plugin_stub.cpp)
|
||||
set_target_properties(can_raw PROPERTIES OUTPUT_NAME "can_raw")
|
||||
|
||||
1
plugins/protocols/can_raw/plugin_stub.cpp
Normal file
1
plugins/protocols/can_raw/plugin_stub.cpp
Normal file
@@ -0,0 +1 @@
|
||||
extern "C" void softbus_can_raw_plugin_stub() {}
|
||||
@@ -1,3 +1,3 @@
|
||||
# Placeholder for custom_proto plugin
|
||||
add_library(custom_proto SHARED)
|
||||
# Placeholder for custom_proto plugin
|
||||
add_library(custom_proto SHARED plugin_stub.cpp)
|
||||
set_target_properties(custom_proto PROPERTIES OUTPUT_NAME "custom_proto")
|
||||
|
||||
1
plugins/protocols/custom_proto/plugin_stub.cpp
Normal file
1
plugins/protocols/custom_proto/plugin_stub.cpp
Normal file
@@ -0,0 +1 @@
|
||||
extern "C" void softbus_custom_proto_plugin_stub() {}
|
||||
@@ -1,3 +1,3 @@
|
||||
# Placeholder for modbus_rtu plugin
|
||||
add_library(modbus_rtu SHARED)
|
||||
# Placeholder for modbus_rtu plugin
|
||||
add_library(modbus_rtu SHARED plugin_stub.cpp)
|
||||
set_target_properties(modbus_rtu PROPERTIES OUTPUT_NAME "modbus_rtu")
|
||||
|
||||
1
plugins/protocols/modbus_rtu/plugin_stub.cpp
Normal file
1
plugins/protocols/modbus_rtu/plugin_stub.cpp
Normal file
@@ -0,0 +1 @@
|
||||
extern "C" void softbus_modbus_rtu_plugin_stub() {}
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "utils/logs/logging.h"
|
||||
#include "device_bus/DeviceBus.h"
|
||||
#include "message_bus/pipeline/PayloadRef.h"
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
CoreService* CoreService::instance()
|
||||
{
|
||||
@@ -35,6 +37,8 @@ bool CoreService::initialize()
|
||||
}
|
||||
|
||||
LOG_INFO() << "CoreService initializing";
|
||||
qRegisterMetaType<softbus::message_bus::pipeline::PayloadRef>("softbus::message_bus::pipeline::PayloadRef");
|
||||
qRegisterMetaType<softbus::message_bus::pipeline::PipelineContext>("softbus::message_bus::pipeline::PipelineContext");
|
||||
|
||||
// 1. 解析配置路径(放在用户 home 下的相对固定目录:~/softbus/config)
|
||||
const QString configPath =
|
||||
|
||||
@@ -1,7 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
// Placeholder for a lock-free ring queue.
|
||||
class LockFreeQueue {
|
||||
public:
|
||||
LockFreeQueue() = default;
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace softbus::core::memory
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class LockFreeQueue
|
||||
{
|
||||
public:
|
||||
// SPSC ring queue. Producer and consumer must be single-threaded.
|
||||
explicit LockFreeQueue(std::size_t capacity)
|
||||
: m_capacity(capacity + 1), m_data(m_capacity)
|
||||
{
|
||||
}
|
||||
|
||||
bool push(const T& value)
|
||||
{
|
||||
const auto head = m_head.load(std::memory_order_relaxed);
|
||||
const auto next = increment(head);
|
||||
if (next == m_tail.load(std::memory_order_acquire)) {
|
||||
return false; // queue full
|
||||
}
|
||||
m_data[head] = value;
|
||||
m_head.store(next, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool push(T&& value)
|
||||
{
|
||||
const auto head = m_head.load(std::memory_order_relaxed);
|
||||
const auto next = increment(head);
|
||||
if (next == m_tail.load(std::memory_order_acquire)) {
|
||||
return false; // queue full
|
||||
}
|
||||
m_data[head] = std::move(value);
|
||||
m_head.store(next, std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pop(T& out)
|
||||
{
|
||||
const auto tail = m_tail.load(std::memory_order_relaxed);
|
||||
if (tail == m_head.load(std::memory_order_acquire)) {
|
||||
return false; // queue empty
|
||||
}
|
||||
out = std::move(m_data[tail]);
|
||||
m_tail.store(increment(tail), std::memory_order_release);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return m_head.load(std::memory_order_acquire) == m_tail.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
std::size_t capacity() const
|
||||
{
|
||||
return m_capacity - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t increment(std::size_t idx) const
|
||||
{
|
||||
return (idx + 1) % m_capacity;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::size_t m_capacity;
|
||||
std::vector<T> m_data;
|
||||
alignas(64) std::atomic<std::size_t> m_head{0};
|
||||
alignas(64) std::atomic<std::size_t> m_tail{0};
|
||||
};
|
||||
|
||||
} // namespace softbus::core::memory
|
||||
|
||||
@@ -1,7 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
// Placeholder for a preallocated memory pool.
|
||||
class MemoryPool {
|
||||
public:
|
||||
MemoryPool() = default;
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
namespace softbus::core::memory
|
||||
{
|
||||
|
||||
class MemoryPool
|
||||
{
|
||||
public:
|
||||
struct PoolBlock
|
||||
{
|
||||
std::uint8_t* data{nullptr};
|
||||
std::size_t capacity{0};
|
||||
std::size_t size{0};
|
||||
std::size_t slotIndex{0};
|
||||
};
|
||||
|
||||
using BlockPtr = std::shared_ptr<PoolBlock>;
|
||||
|
||||
explicit MemoryPool(std::size_t blockSize = 4096, std::size_t blockCount = 1024)
|
||||
: m_blockSize(blockSize), m_storage(blockSize * blockCount), m_inUse(blockCount, false)
|
||||
{
|
||||
for (std::size_t i = 0; i < blockCount; ++i) {
|
||||
m_freeSlots.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
BlockPtr allocate(std::size_t requiredSize)
|
||||
{
|
||||
if (requiredSize > m_blockSize) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::size_t slot = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_mutex);
|
||||
if (m_freeSlots.empty()) {
|
||||
return {};
|
||||
}
|
||||
slot = m_freeSlots.front();
|
||||
m_freeSlots.pop();
|
||||
m_inUse[slot] = true;
|
||||
}
|
||||
|
||||
auto* raw = new PoolBlock{
|
||||
m_storage.data() + slot * m_blockSize,
|
||||
m_blockSize,
|
||||
requiredSize,
|
||||
slot,
|
||||
};
|
||||
return BlockPtr(raw, [this](PoolBlock* b) {
|
||||
if (!b) return;
|
||||
this->release(*b);
|
||||
delete b;
|
||||
});
|
||||
}
|
||||
|
||||
void release(const PoolBlock& block)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_mutex);
|
||||
if (block.slotIndex >= m_inUse.size()) {
|
||||
return;
|
||||
}
|
||||
if (!m_inUse[block.slotIndex]) {
|
||||
return;
|
||||
}
|
||||
m_inUse[block.slotIndex] = false;
|
||||
m_freeSlots.push(block.slotIndex);
|
||||
}
|
||||
|
||||
std::size_t blockSize() const { return m_blockSize; }
|
||||
std::size_t totalBlocks() const { return m_inUse.size(); }
|
||||
|
||||
std::size_t inUseBlocks() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_mutex);
|
||||
std::size_t used = 0;
|
||||
for (const bool v : m_inUse) {
|
||||
if (v) ++used;
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t m_blockSize;
|
||||
std::vector<std::uint8_t> m_storage;
|
||||
mutable std::mutex m_mutex;
|
||||
std::queue<std::size_t> m_freeSlots;
|
||||
std::vector<bool> m_inUse;
|
||||
};
|
||||
|
||||
} // namespace softbus::core::memory
|
||||
|
||||
@@ -1,7 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
// Placeholder protocol plugin interface.
|
||||
class IProtocolPlugin {
|
||||
public:
|
||||
virtual ~IProtocolPlugin() = default;
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
namespace softbus::core::plugin_system
|
||||
{
|
||||
|
||||
class IProtocolSession
|
||||
{
|
||||
public:
|
||||
virtual ~IProtocolSession() = default;
|
||||
virtual bool feed(softbus::message_bus::pipeline::PipelineContext& ctx) = 0;
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
||||
class IProtocolPlugin
|
||||
{
|
||||
public:
|
||||
virtual ~IProtocolPlugin() = default;
|
||||
|
||||
virtual QString pluginId() const = 0;
|
||||
virtual bool supports(const QString& protocolHint) const = 0;
|
||||
virtual std::unique_ptr<IProtocolSession> createSession() = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::core::plugin_system
|
||||
|
||||
24
src/core/plugin_system/PluginManager.cpp
Normal file
24
src/core/plugin_system/PluginManager.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "core/plugin_system/PluginManager.h"
|
||||
|
||||
namespace softbus::core::plugin_system
|
||||
{
|
||||
|
||||
void PluginManager::registerProtocolPlugin(std::shared_ptr<IProtocolPlugin> plugin)
|
||||
{
|
||||
if (!plugin) {
|
||||
return;
|
||||
}
|
||||
m_protocolPlugins.insert(plugin->pluginId(), std::move(plugin));
|
||||
}
|
||||
|
||||
std::shared_ptr<IProtocolPlugin> PluginManager::selectProtocolPlugin(const QString& protocolHint) const
|
||||
{
|
||||
for (auto it = m_protocolPlugins.constBegin(); it != m_protocolPlugins.constEnd(); ++it) {
|
||||
if (it.value() && it.value()->supports(protocolHint)) {
|
||||
return it.value();
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace softbus::core::plugin_system
|
||||
@@ -1,7 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
// Placeholder for plugin manager.
|
||||
class PluginManager {
|
||||
public:
|
||||
PluginManager() = default;
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
||||
#include "core/plugin_system/IProtocolPlugin.h"
|
||||
|
||||
namespace softbus::core::plugin_system
|
||||
{
|
||||
|
||||
class PluginManager
|
||||
{
|
||||
public:
|
||||
PluginManager() = default;
|
||||
|
||||
void registerProtocolPlugin(std::shared_ptr<IProtocolPlugin> plugin);
|
||||
std::shared_ptr<IProtocolPlugin> selectProtocolPlugin(const QString& protocolHint) const;
|
||||
|
||||
private:
|
||||
QHash<QString, std::shared_ptr<IProtocolPlugin>> m_protocolPlugins;
|
||||
};
|
||||
|
||||
} // namespace softbus::core::plugin_system
|
||||
|
||||
@@ -51,6 +51,7 @@ bool DeviceBus::initialize(const QJsonObject &rootConfig) {
|
||||
}
|
||||
d->manager->setDeviceTreeModel(d->treeModel);
|
||||
d->manager->setRegistry(d->registry.get());
|
||||
d->manager->setDirtyCallback([this]() { this->markDeviceTreeDirty(); });
|
||||
|
||||
// 1) Load persisted config and initialize manager
|
||||
if (!d->manager->initialize(rootConfig)) {
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
#include "device_bus/manager/DeviceBusManager.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QSerialPort>
|
||||
#include <QSet>
|
||||
// #include <algorithm>
|
||||
|
||||
#include "hardware/drivers/serial/SerialQtDriver.h"
|
||||
#include "hardware/drivers/serial/SerialCapabilities.h"
|
||||
#include "message_bus/egress/EgressRouter.h"
|
||||
#include "message_bus/ingress/DriverIngressAdapter.h"
|
||||
#include "message_bus/pipeline/PipelineEngine.h"
|
||||
#include "core/plugin_system/PluginManager.h"
|
||||
#include "device_bus/manager/SerialDeviceManager.h"
|
||||
#include "devices/DeviceTypes.h"
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
using softbus::hardware::drivers::serial::SerialQtDriver;
|
||||
namespace serial_cap = softbus::hardware::drivers::serial::capabilities;
|
||||
DeviceBusManager::~DeviceBusManager()
|
||||
{
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void DeviceBusManager::setDeviceTreeModel(std::shared_ptr<DeviceTreeModel> model)
|
||||
{
|
||||
@@ -25,8 +29,37 @@ void DeviceBusManager::setRegistry(softbus::device_bus::registry::IDeviceRegistr
|
||||
m_registry = registry;
|
||||
}
|
||||
|
||||
void DeviceBusManager::setDirtyCallback(std::function<void()> cb)
|
||||
{
|
||||
m_dirtyCb = std::move(cb);
|
||||
}
|
||||
|
||||
bool DeviceBusManager::initialize(const QJsonObject& rootConfig)
|
||||
{
|
||||
if (!m_memoryPool) {
|
||||
m_memoryPool = std::make_shared<softbus::core::memory::MemoryPool>(4096, 4096);
|
||||
}
|
||||
if (!m_pipelineEngine) {
|
||||
m_pipelineEngine = std::make_unique<softbus::message_bus::pipeline::PipelineEngine>(4096);
|
||||
}
|
||||
if (!m_pluginManager) {
|
||||
m_pluginManager = std::make_shared<softbus::core::plugin_system::PluginManager>();
|
||||
}
|
||||
if (m_pipelineEngine) {
|
||||
m_pipelineEngine->setPluginManager(m_pluginManager);
|
||||
m_pipelineEngine->start();
|
||||
}
|
||||
if (!m_ingressAdapter) {
|
||||
m_ingressAdapter = std::make_unique<softbus::message_bus::ingress::DriverIngressAdapter>(
|
||||
m_memoryPool, m_pipelineEngine.get());
|
||||
}
|
||||
if (!m_egressRouter) {
|
||||
m_egressRouter = std::make_unique<softbus::message_bus::egress::EgressRouter>();
|
||||
}
|
||||
if (!m_egressRunning.exchange(true)) {
|
||||
m_egressThread = std::thread([this]() { this->processEgressLoop(); });
|
||||
}
|
||||
|
||||
if (!m_treeModel) {
|
||||
m_treeModel = std::make_shared<DeviceTreeModel>();
|
||||
}
|
||||
@@ -78,7 +111,7 @@ bool DeviceBusManager::reconcileFromTreeModel()
|
||||
|
||||
if (kind == softbus::devices::DeviceKind::Serial) {
|
||||
desiredSerialEndpoints.insert(n.endpoint);
|
||||
if (!m_serialDevicesByEndpoint.contains(n.endpoint)) {
|
||||
if (!m_serialDevicesByEndpointSharedPtr.contains(n.endpoint)) {
|
||||
initializeSerialDevice(n.endpoint, n.params);
|
||||
}
|
||||
m_deviceEndpointsMap.insert(n.endpoint, kind);
|
||||
@@ -86,7 +119,7 @@ bool DeviceBusManager::reconcileFromTreeModel()
|
||||
}
|
||||
|
||||
// Remove runtime devices that are no longer desired/offline
|
||||
const auto currentKeys = m_serialDevicesByEndpoint.keys();
|
||||
const auto currentKeys = m_serialDevicesByEndpointSharedPtr.keys();
|
||||
for (const auto& endpoint : currentKeys) {
|
||||
if (!desiredSerialEndpoints.contains(endpoint)) {
|
||||
shutdownSerialDevice(endpoint);
|
||||
@@ -99,105 +132,39 @@ bool DeviceBusManager::reconcileFromTreeModel()
|
||||
|
||||
void DeviceBusManager::shutdown()
|
||||
{
|
||||
m_egressRunning.store(false);
|
||||
if (m_egressThread.joinable()) {
|
||||
m_egressThread.join();
|
||||
}
|
||||
|
||||
// 关闭并销毁所有串口设备
|
||||
const auto keys = m_serialDevicesByEndpoint.keys();
|
||||
const auto keys = m_serialDevicesByEndpointSharedPtr.keys();
|
||||
for (const auto& endpoint : keys) {
|
||||
shutdownSerialDevice(endpoint);
|
||||
}
|
||||
if (m_pipelineEngine) {
|
||||
m_pipelineEngine->stop();
|
||||
m_pipelineEngine->drain();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceBusManager::initializeSerialDevice(const QString& endpoint, const QJsonObject& params)
|
||||
{
|
||||
if (m_serialDevicesByEndpoint.contains(endpoint)) {
|
||||
LOG_WARNING() << "DeviceBusManager: serial device 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 = std::make_unique<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);
|
||||
|
||||
softbus::devices::DeviceInfo info;
|
||||
info.id = -1;
|
||||
info.endpoint = endpoint;
|
||||
info.type = QStringLiteral("serial");
|
||||
info.kind = softbus::devices::DeviceKind::Serial;
|
||||
|
||||
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);
|
||||
softbus::device_bus::manager::SerialInitDeps deps;
|
||||
deps.treeModel = m_treeModel.get();
|
||||
deps.dirtyCb = m_dirtyCb;
|
||||
deps.registry = m_registry;
|
||||
deps.ingressAdapter = m_ingressAdapter.get();
|
||||
deps.memoryPool = m_memoryPool;
|
||||
deps.egressRouter = m_egressRouter.get();
|
||||
deps.serialDevicesByEndpoint = &m_serialDevicesByEndpointSharedPtr;
|
||||
(void)softbus::device_bus::manager::initializeSerialDeviceWithDeps(endpoint, params, deps);
|
||||
}
|
||||
|
||||
void DeviceBusManager::shutdownSerialDevice(const QString& endpoint)
|
||||
{
|
||||
auto it = m_serialDevicesByEndpoint.find(endpoint);
|
||||
if (it == m_serialDevicesByEndpoint.end()) {
|
||||
auto it = m_serialDevicesByEndpointSharedPtr.find(endpoint);
|
||||
if (it == m_serialDevicesByEndpointSharedPtr.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -209,6 +176,29 @@ void DeviceBusManager::shutdownSerialDevice(const QString& endpoint)
|
||||
}
|
||||
device->stop();
|
||||
}
|
||||
if (m_egressRouter) {
|
||||
m_egressRouter->unbindSerialDevice(endpoint);
|
||||
}
|
||||
|
||||
m_serialDevicesByEndpoint.erase(it);
|
||||
m_serialDevicesByEndpointSharedPtr.erase(it);
|
||||
}
|
||||
|
||||
void DeviceBusManager::processEgressLoop()
|
||||
{
|
||||
while (m_egressRunning.load()) {
|
||||
if (!m_pipelineEngine || !m_egressRouter) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
continue;
|
||||
}
|
||||
|
||||
softbus::message_bus::pipeline::PipelineContext out;
|
||||
if (!m_pipelineEngine->tryPopEgress(out)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
const bool ok = m_egressRouter->send(out);
|
||||
if (!ok) {
|
||||
// LOG_WARNING() << "DeviceBusManager: egress send failed endpoint=" << out.endpoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,29 @@
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include <QSharedPointer>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <functional>
|
||||
|
||||
#include "core/memory/MemoryPool.h"
|
||||
#include "core/plugin_system/PluginManager.h"
|
||||
#include "device_bus/tree/DeviceTreeModel.h"
|
||||
#include "device_bus/registry/IDeviceRegistry.h"
|
||||
#include "devices/DeviceTypes.h"
|
||||
#include "devices/physical/SerialDevice.h"
|
||||
#include "message_bus/egress/EgressRouter.h"
|
||||
#include "message_bus/ingress/DriverIngressAdapter.h"
|
||||
#include "message_bus/pipeline/PipelineEngine.h"
|
||||
|
||||
class DeviceBusManager
|
||||
{
|
||||
public:
|
||||
~DeviceBusManager();
|
||||
|
||||
void setDeviceTreeModel(std::shared_ptr<DeviceTreeModel> model);
|
||||
void setRegistry(softbus::device_bus::registry::IDeviceRegistry* registry);
|
||||
void setDirtyCallback(std::function<void()> cb);
|
||||
|
||||
bool initialize(const QJsonObject& rootConfig);
|
||||
bool reconcileFromTreeModel();
|
||||
@@ -26,6 +37,7 @@ public:
|
||||
private:
|
||||
void initializeSerialDevice(const QString& endpoint, const QJsonObject& params);
|
||||
void shutdownSerialDevice(const QString& endpoint);
|
||||
void processEgressLoop();
|
||||
// void initializeCanDriver();
|
||||
// void shutdownCanDriver();
|
||||
// void initializeTcpDriver();
|
||||
@@ -40,12 +52,18 @@ private:
|
||||
// 添加map来记住所有设备的endpoint和type的映射
|
||||
QMap<QString, softbus::devices::DeviceKind> m_deviceEndpointsMap;
|
||||
|
||||
QHash<QString, QSharedPointer<softbus::devices::physical::SerialDevice>> m_serialDevicesByEndpoint;
|
||||
QHash<QString, QSharedPointer<softbus::devices::physical::SerialDevice>> m_serialDevicesByEndpointSharedPtr;
|
||||
|
||||
softbus::device_bus::registry::IDeviceRegistry* m_registry = nullptr;
|
||||
std::shared_ptr<softbus::core::memory::MemoryPool> m_memoryPool;
|
||||
std::shared_ptr<softbus::core::plugin_system::PluginManager> m_pluginManager;
|
||||
std::unique_ptr<softbus::message_bus::pipeline::PipelineEngine> m_pipelineEngine;
|
||||
std::unique_ptr<softbus::message_bus::ingress::DriverIngressAdapter> m_ingressAdapter;
|
||||
std::unique_ptr<softbus::message_bus::egress::EgressRouter> m_egressRouter;
|
||||
std::atomic<bool> m_egressRunning{false};
|
||||
std::thread m_egressThread;
|
||||
std::function<void()> m_dirtyCb;
|
||||
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
|
||||
167
src/device_bus/manager/SerialDeviceManager.cpp
Normal file
167
src/device_bus/manager/SerialDeviceManager.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "device_bus/manager/SerialDeviceManager.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QSerialPort>
|
||||
|
||||
#include "device_bus/tree/DeviceTreeModel.h"
|
||||
#include "devices/DeviceTypes.h"
|
||||
#include "hardware/drivers/serial/SerialCapabilities.h"
|
||||
#include "hardware/drivers/serial/SerialQtDriver.h"
|
||||
#include "message_bus/egress/EgressRouter.h"
|
||||
#include "message_bus/ingress/DriverIngressAdapter.h"
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
using softbus::hardware::drivers::serial::SerialQtDriver;
|
||||
namespace serial_cap = softbus::hardware::drivers::serial::capabilities;
|
||||
|
||||
namespace softbus::device_bus::manager
|
||||
{
|
||||
|
||||
static bool setIfChanged(QJsonObject& params, const QString& key, const QJsonValue& value)
|
||||
{
|
||||
const auto it = params.find(key);
|
||||
if (it == params.end() || it.value() != value) {
|
||||
params.insert(key, value);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool persistSerialParams(DeviceTreeModel* treeModel,
|
||||
const QString& endpoint,
|
||||
const QJsonObject& mergedParams,
|
||||
const std::function<void()>& dirtyCb)
|
||||
{
|
||||
if (!treeModel || endpoint.isEmpty() || mergedParams.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int idx = treeModel->findIndexByEndpoint(endpoint);
|
||||
if (idx < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& nodes = treeModel->nodesMutable();
|
||||
if (idx >= nodes.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& node = nodes[idx];
|
||||
auto& p = node.params;
|
||||
|
||||
bool changed = false;
|
||||
changed = setIfChanged(p, QStringLiteral("baudRate"), mergedParams.value(QStringLiteral("baudRate"))) || changed;
|
||||
changed = setIfChanged(p, QStringLiteral("dataBits"), mergedParams.value(QStringLiteral("dataBits"))) || changed;
|
||||
changed = setIfChanged(p, QStringLiteral("parity"), mergedParams.value(QStringLiteral("parity"))) || changed;
|
||||
changed = setIfChanged(p, QStringLiteral("stopBits"), mergedParams.value(QStringLiteral("stopBits"))) || changed;
|
||||
changed =
|
||||
setIfChanged(p, QStringLiteral("flowControl"), mergedParams.value(QStringLiteral("flowControl"))) || changed;
|
||||
|
||||
if (changed && dirtyCb) {
|
||||
dirtyCb();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool initializeSerialDeviceWithDeps(const QString& endpoint, const QJsonObject& params, const SerialInitDeps& deps)
|
||||
{
|
||||
if (!deps.serialDevicesByEndpoint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (deps.serialDevicesByEndpoint->contains(endpoint)) {
|
||||
LOG_WARNING() << "DeviceBusManager: serial device already exists for" << endpoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
persistSerialParams(deps.treeModel, endpoint, merged, deps.dirtyCb);
|
||||
|
||||
auto driver = std::make_unique<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);
|
||||
|
||||
softbus::devices::DeviceInfo info;
|
||||
info.id = -1;
|
||||
info.endpoint = endpoint;
|
||||
info.type = QStringLiteral("serial");
|
||||
info.kind = softbus::devices::DeviceKind::Serial;
|
||||
|
||||
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));
|
||||
// 绑定 ingress 适配器和内存池 数据推送到 ingress 队列
|
||||
device->bindIngress(deps.ingressAdapter, deps.memoryPool);
|
||||
|
||||
if (deps.registry) {
|
||||
deps.registry->registerDevice(info);
|
||||
}
|
||||
|
||||
if (!device->start()) {
|
||||
LOG_ERROR() << "DeviceBusManager: failed to start serial device for" << endpoint;
|
||||
return false;
|
||||
}
|
||||
|
||||
deps.serialDevicesByEndpoint->insert(endpoint, device);
|
||||
// 暂时不绑定 egress 路由器 因为还没有 egress 路由器
|
||||
// egress 路由器 是用来将数据从 ingress 队列中取出并发送给设备的
|
||||
// if (deps.egressRouter) {
|
||||
// deps.egressRouter->bindSerialDevice(endpoint, device);
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace softbus::device_bus::manager
|
||||
41
src/device_bus/manager/SerialDeviceManager.h
Normal file
41
src/device_bus/manager/SerialDeviceManager.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
// 串口参数校验与默认值合并
|
||||
// 参数回写设备树(持久化前置)
|
||||
// 创建设备与驱动
|
||||
// ingress / egress 绑定
|
||||
// registry 注册与设备启动
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <QHash>
|
||||
#include <QJsonObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
|
||||
#include "core/memory/MemoryPool.h"
|
||||
#include "device_bus/registry/IDeviceRegistry.h"
|
||||
#include "devices/physical/SerialDevice.h"
|
||||
|
||||
namespace softbus::message_bus::egress { class EgressRouter; }
|
||||
namespace softbus::message_bus::ingress { class DriverIngressAdapter; }
|
||||
|
||||
class DeviceTreeModel;
|
||||
|
||||
namespace softbus::device_bus::manager
|
||||
{
|
||||
|
||||
struct SerialInitDeps
|
||||
{
|
||||
DeviceTreeModel* treeModel{nullptr};
|
||||
std::function<void()> dirtyCb;
|
||||
softbus::device_bus::registry::IDeviceRegistry* registry{nullptr};
|
||||
softbus::message_bus::ingress::DriverIngressAdapter* ingressAdapter{nullptr};
|
||||
std::shared_ptr<softbus::core::memory::MemoryPool> memoryPool;
|
||||
softbus::message_bus::egress::EgressRouter* egressRouter{nullptr};
|
||||
QHash<QString, QSharedPointer<softbus::devices::physical::SerialDevice>>* serialDevicesByEndpoint{nullptr};
|
||||
};
|
||||
|
||||
bool initializeSerialDeviceWithDeps(const QString& endpoint, const QJsonObject& params, const SerialInitDeps& deps);
|
||||
|
||||
} // namespace softbus::device_bus::manager
|
||||
@@ -148,6 +148,20 @@ int DeviceTreeModel::findIndexByStableKey(const QString& stableKey) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
int DeviceTreeModel::findIndexByEndpoint(const QString& endpoint) const
|
||||
{
|
||||
if (endpoint.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < m_nodes.size(); ++i) {
|
||||
const auto& n = m_nodes.at(i);
|
||||
if (n.endpoint == endpoint) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
QString DeviceTreeModel::upsertNodeByStableKey(const QString& stableKey,
|
||||
const QString& preferredId,
|
||||
const QString& type,
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
|
||||
const DeviceTreeNode* findById(const QString& id) const;
|
||||
int findIndexById(const QString& id) const;
|
||||
int findIndexByEndpoint(const QString& endpoint) const;
|
||||
int findIndexByStableKey(const QString& stableKey) const;
|
||||
|
||||
// Monitor/register path: upsert or mark online/offline
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
#include "devices/physical/SerialDevice.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
#include "core/memory/MemoryPool.h"
|
||||
#include "hardware/drivers/serial/SerialQtDriver.h"
|
||||
#include "message_bus/ingress/IIngressPort.h"
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
using softbus::hardware::drivers::serial::SerialQtDriver;
|
||||
@@ -31,6 +38,9 @@ bool SerialDevice::start()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_driver->SetReadCallback([this](const std::vector<std::uint8_t>& data) { this->onRead(data); });
|
||||
m_driver->SetErrorCallback([this](const std::string& error) { this->onError(error); });
|
||||
|
||||
LOG_INFO() << "SerialDevice: opening endpoint" << m_config.endpoint;
|
||||
return m_driver->Open(m_config.endpoint.toStdString());
|
||||
}
|
||||
@@ -60,5 +70,71 @@ softbus::devices::DeviceKind SerialDevice::kind() const
|
||||
return softbus::devices::DeviceKind::Serial;
|
||||
}
|
||||
|
||||
void SerialDevice::bindIngress(softbus::message_bus::ingress::IIngressPort* ingress,
|
||||
std::shared_ptr<softbus::core::memory::MemoryPool> pool)
|
||||
{
|
||||
m_ingress = ingress;
|
||||
m_pool = std::move(pool);
|
||||
}
|
||||
|
||||
// 串口写入数据回调 不定长数据
|
||||
bool SerialDevice::writePayload(const std::vector<std::uint8_t>& data)
|
||||
{
|
||||
if (!m_driver) {
|
||||
return false;
|
||||
}
|
||||
return m_driver->Write(data);
|
||||
}
|
||||
// 串口写入数据回调 定长数据
|
||||
bool SerialDevice::writePayload(const std::uint8_t* data, std::size_t size)
|
||||
{
|
||||
if (!m_driver) {
|
||||
return false;
|
||||
}
|
||||
return m_driver->Write(data, size);
|
||||
}
|
||||
|
||||
// 串口读取数据回调
|
||||
|
||||
void SerialDevice::onRead(const std::vector<std::uint8_t>& data)
|
||||
{
|
||||
if (!m_ingress || !m_pool || data.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto block = m_pool->allocate(data.size());
|
||||
if (!block || !block->data || block->capacity < data.size()) {
|
||||
m_ingress->reportError(m_config.endpoint, QStringLiteral("memory pool exhausted"));
|
||||
return;
|
||||
}
|
||||
|
||||
std::copy(data.begin(), data.end(), block->data);
|
||||
block->size = data.size();
|
||||
// @test code
|
||||
LOG_INFO() << "SerialDevice: onRead data size" << data.size() << "endpoint" << m_config.endpoint;
|
||||
// 将数据推送到 ingress 队列 包含端口名、协议、数据、时间戳、traceId
|
||||
softbus::message_bus::pipeline::PipelineContext ctx;
|
||||
ctx.endpoint = m_config.endpoint;
|
||||
ctx.protocolHint = m_info.protocol;
|
||||
ctx.payload.block = std::move(block);
|
||||
ctx.payload.length = data.size();
|
||||
ctx.payloadSize = data.size();
|
||||
ctx.traceId = QStringLiteral("serial:%1:%2")
|
||||
.arg(m_config.endpoint)
|
||||
.arg(QDateTime::currentMSecsSinceEpoch());
|
||||
|
||||
if (!m_ingress->push(std::move(ctx))) {
|
||||
m_ingress->reportError(m_config.endpoint, QStringLiteral("ingress queue full"));
|
||||
}
|
||||
}
|
||||
|
||||
void SerialDevice::onError(const std::string& error)
|
||||
{
|
||||
if (!m_ingress) {
|
||||
return;
|
||||
}
|
||||
m_ingress->reportError(m_config.endpoint, QString::fromStdString(error));
|
||||
}
|
||||
|
||||
} // namespace softbus::devices::physical
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "devices/DeviceTypes.h"
|
||||
#include "devices/base/IPhysicalDevice.h"
|
||||
namespace softbus::hardware::drivers::serial { class SerialQtDriver; }
|
||||
namespace softbus::message_bus::ingress { class IIngressPort; }
|
||||
namespace softbus::core::memory { class MemoryPool; }
|
||||
|
||||
namespace softbus::devices::physical
|
||||
{
|
||||
@@ -36,11 +40,21 @@ public:
|
||||
|
||||
QString endpoint() const;
|
||||
softbus::devices::DeviceKind kind() const;
|
||||
void bindIngress(softbus::message_bus::ingress::IIngressPort* ingress,
|
||||
std::shared_ptr<softbus::core::memory::MemoryPool> pool);
|
||||
bool writePayload(const std::vector<std::uint8_t>& data);
|
||||
bool writePayload(const std::uint8_t* data, std::size_t size);
|
||||
|
||||
private:
|
||||
void onRead(const std::vector<std::uint8_t>& data);
|
||||
void onError(const std::string& error);
|
||||
|
||||
private:
|
||||
std::unique_ptr<softbus::hardware::drivers::serial::SerialQtDriver> m_driver;
|
||||
Config m_config;
|
||||
softbus::devices::DeviceInfo m_info;
|
||||
softbus::message_bus::ingress::IIngressPort* m_ingress{nullptr};
|
||||
std::shared_ptr<softbus::core::memory::MemoryPool> m_pool;
|
||||
};
|
||||
|
||||
} // namespace softbus::devices::physical
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace softbus::hardware::drivers::serial::capabilities
|
||||
|
||||
struct SerialDefaults
|
||||
{
|
||||
int baudRate = 115200;
|
||||
int baudRate = 9600;
|
||||
int dataBits = 8;
|
||||
const char* parity = "none";
|
||||
int stopBits = 1;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "hardware/drivers/serial/SerialQtDriver.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QMetaObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
@@ -22,46 +24,51 @@ SerialQtDriver::~SerialQtDriver()
|
||||
|
||||
bool SerialQtDriver::Open(const std::string& endpoint)
|
||||
{
|
||||
if (m_port.isOpen()) {
|
||||
return true;
|
||||
const QString ep = QString::fromStdString(endpoint);
|
||||
if (QThread::currentThread() == this->thread()) {
|
||||
return openOnOwnerThread(ep);
|
||||
}
|
||||
|
||||
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;
|
||||
bool ok = false;
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this, ep, &ok]() { ok = openOnOwnerThread(ep); },
|
||||
Qt::BlockingQueuedConnection);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void SerialQtDriver::Close()
|
||||
{
|
||||
if (m_port.isOpen()) {
|
||||
const QString name = m_port.portName();
|
||||
m_port.close();
|
||||
LOG_DEBUG() << "SerialQtDriver: closed port" << name;
|
||||
if (QThread::currentThread() == this->thread()) {
|
||||
closeOnOwnerThread();
|
||||
return;
|
||||
}
|
||||
QMetaObject::invokeMethod(this, [this]() { closeOnOwnerThread(); }, Qt::BlockingQueuedConnection);
|
||||
}
|
||||
|
||||
bool SerialQtDriver::Write(const std::vector<std::uint8_t>& data)
|
||||
{
|
||||
if (!m_port.isOpen()) {
|
||||
return false;
|
||||
return Write(data.data(), data.size());
|
||||
}
|
||||
|
||||
bool SerialQtDriver::Write(const std::uint8_t* data, std::size_t size)
|
||||
{
|
||||
if (!data || size == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
const QByteArray bytes(reinterpret_cast<const char*>(data), static_cast<int>(size));
|
||||
// QSerialPort 必须在其所属线程内访问;若从外部线程调用,切回 owner 线程执行。
|
||||
if (QThread::currentThread() == this->thread()) {
|
||||
return writeOnOwnerThread(bytes);
|
||||
}
|
||||
return true;
|
||||
|
||||
bool ok = false;
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this, bytes, &ok]() { ok = writeOnOwnerThread(bytes); },
|
||||
Qt::BlockingQueuedConnection);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void SerialQtDriver::SetReadCallback(ReadCallback cb)
|
||||
@@ -134,5 +141,47 @@ void SerialQtDriver::handleError(QSerialPort::SerialPortError error)
|
||||
}
|
||||
}
|
||||
|
||||
bool SerialQtDriver::writeOnOwnerThread(const QByteArray& bytes)
|
||||
{
|
||||
if (!m_port.isOpen()) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
bool SerialQtDriver::openOnOwnerThread(const QString& endpoint)
|
||||
{
|
||||
if (m_port.isOpen()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
m_port.setPortName(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::closeOnOwnerThread()
|
||||
{
|
||||
if (m_port.isOpen()) {
|
||||
const QString name = m_port.portName();
|
||||
m_port.close();
|
||||
LOG_DEBUG() << "SerialQtDriver: closed port" << name;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace softbus::hardware::drivers::serial
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <QObject>
|
||||
#include <QSerialPort>
|
||||
#include <QString>
|
||||
#include <cstddef>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "hardware/interfaces/IStreamDriver.h"
|
||||
|
||||
@@ -60,6 +62,7 @@ public:
|
||||
void Close() override;
|
||||
|
||||
bool Write(const std::vector<std::uint8_t>& data) override;
|
||||
bool Write(const std::uint8_t* data, std::size_t size) override;
|
||||
|
||||
void SetReadCallback(ReadCallback cb) override;
|
||||
void SetErrorCallback(ErrorCallback cb) override;
|
||||
@@ -75,6 +78,11 @@ private slots:
|
||||
void handleReadyRead();
|
||||
void handleError(QSerialPort::SerialPortError error);
|
||||
|
||||
private:
|
||||
bool openOnOwnerThread(const QString& endpoint);
|
||||
void closeOnOwnerThread();
|
||||
bool writeOnOwnerThread(const QByteArray& bytes);
|
||||
|
||||
private:
|
||||
QSerialPort m_port;
|
||||
ReadCallback m_readCallback;
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
virtual void Close() = 0;
|
||||
|
||||
virtual bool Write(const std::vector<std::uint8_t>& data) = 0;
|
||||
virtual bool Write(const std::uint8_t* data, std::size_t size) = 0;
|
||||
|
||||
virtual void SetReadCallback(ReadCallback cb) = 0;
|
||||
virtual void SetErrorCallback(ErrorCallback cb) = 0;
|
||||
|
||||
34
src/message_bus/egress/EgressRouter.cpp
Normal file
34
src/message_bus/egress/EgressRouter.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "message_bus/egress/EgressRouter.h"
|
||||
|
||||
#include "devices/physical/SerialDevice.h"
|
||||
|
||||
namespace softbus::message_bus::egress
|
||||
{
|
||||
|
||||
void EgressRouter::bindSerialDevice(
|
||||
const QString& endpoint,
|
||||
const QSharedPointer<softbus::devices::physical::SerialDevice>& device)
|
||||
{
|
||||
m_serialByEndpoint.insert(endpoint, device);
|
||||
}
|
||||
|
||||
void EgressRouter::unbindSerialDevice(const QString& endpoint)
|
||||
{
|
||||
m_serialByEndpoint.remove(endpoint);
|
||||
}
|
||||
|
||||
bool EgressRouter::send(const softbus::message_bus::pipeline::PipelineContext& ctx)
|
||||
{
|
||||
auto it = m_serialByEndpoint.constFind(ctx.endpoint);
|
||||
if (it == m_serialByEndpoint.constEnd() || !it.value() || !ctx.payload.valid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto* p = ctx.payload.bytes();
|
||||
if (!p) {
|
||||
return false;
|
||||
}
|
||||
return it.value()->writePayload(p, ctx.payload.length);
|
||||
}
|
||||
|
||||
} // namespace softbus::message_bus::egress
|
||||
30
src/message_bus/egress/EgressRouter.h
Normal file
30
src/message_bus/egress/EgressRouter.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QSharedPointer>
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
|
||||
#include "message_bus/egress/IEgressPort.h"
|
||||
|
||||
namespace softbus::devices::physical { class SerialDevice; }
|
||||
|
||||
namespace softbus::message_bus::egress
|
||||
{
|
||||
|
||||
class EgressRouter : public IEgressPort
|
||||
{
|
||||
public:
|
||||
EgressRouter() = default;
|
||||
~EgressRouter() override = default;
|
||||
|
||||
void bindSerialDevice(const QString& endpoint,
|
||||
const QSharedPointer<softbus::devices::physical::SerialDevice>& device);
|
||||
void unbindSerialDevice(const QString& endpoint);
|
||||
bool send(const softbus::message_bus::pipeline::PipelineContext& ctx) override;
|
||||
|
||||
private:
|
||||
QHash<QString, QSharedPointer<softbus::devices::physical::SerialDevice>> m_serialByEndpoint;
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::egress
|
||||
15
src/message_bus/egress/IEgressPort.h
Normal file
15
src/message_bus/egress/IEgressPort.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
namespace softbus::message_bus::egress
|
||||
{
|
||||
|
||||
class IEgressPort
|
||||
{
|
||||
public:
|
||||
virtual ~IEgressPort() = default;
|
||||
virtual bool send(const softbus::message_bus::pipeline::PipelineContext& ctx) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::egress
|
||||
28
src/message_bus/ingress/DriverIngressAdapter.cpp
Normal file
28
src/message_bus/ingress/DriverIngressAdapter.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "message_bus/ingress/DriverIngressAdapter.h"
|
||||
|
||||
#include "message_bus/pipeline/PipelineEngine.h"
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
namespace softbus::message_bus::ingress
|
||||
{
|
||||
|
||||
DriverIngressAdapter::DriverIngressAdapter(std::shared_ptr<softbus::core::memory::MemoryPool> pool,
|
||||
softbus::message_bus::pipeline::PipelineEngine* engine)
|
||||
: m_pool(std::move(pool)), m_engine(engine)
|
||||
{
|
||||
}
|
||||
|
||||
bool DriverIngressAdapter::push(softbus::message_bus::pipeline::PipelineContext ctx)
|
||||
{
|
||||
if (!m_engine) {
|
||||
return false;
|
||||
}
|
||||
return m_engine->enqueueIngress(std::move(ctx));
|
||||
}
|
||||
|
||||
void DriverIngressAdapter::reportError(const QString& endpoint, const QString& error)
|
||||
{
|
||||
LOG_WARNING() << "Ingress error endpoint=" << endpoint << "message=" << error;
|
||||
}
|
||||
|
||||
} // namespace softbus::message_bus::ingress
|
||||
29
src/message_bus/ingress/DriverIngressAdapter.h
Normal file
29
src/message_bus/ingress/DriverIngressAdapter.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "core/memory/MemoryPool.h"
|
||||
#include "message_bus/ingress/IIngressPort.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline { class PipelineEngine; }
|
||||
|
||||
namespace softbus::message_bus::ingress
|
||||
{
|
||||
|
||||
class DriverIngressAdapter : public IIngressPort
|
||||
{
|
||||
public:
|
||||
DriverIngressAdapter(std::shared_ptr<softbus::core::memory::MemoryPool> pool,
|
||||
softbus::message_bus::pipeline::PipelineEngine* engine);
|
||||
|
||||
bool push(softbus::message_bus::pipeline::PipelineContext ctx) override;
|
||||
void reportError(const QString& endpoint, const QString& error) override;
|
||||
|
||||
softbus::core::memory::MemoryPool& pool() const { return *m_pool; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<softbus::core::memory::MemoryPool> m_pool;
|
||||
softbus::message_bus::pipeline::PipelineEngine* m_engine{nullptr};
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::ingress
|
||||
19
src/message_bus/ingress/IIngressPort.h
Normal file
19
src/message_bus/ingress/IIngressPort.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
namespace softbus::message_bus::ingress
|
||||
{
|
||||
|
||||
class IIngressPort
|
||||
{
|
||||
public:
|
||||
virtual ~IIngressPort() = default;
|
||||
|
||||
virtual bool push(softbus::message_bus::pipeline::PipelineContext ctx) = 0;
|
||||
virtual void reportError(const QString& endpoint, const QString& error) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::ingress
|
||||
36
src/message_bus/pipeline/PayloadRef.h
Normal file
36
src/message_bus/pipeline/PayloadRef.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include "core/memory/MemoryPool.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline
|
||||
{
|
||||
|
||||
struct PayloadRef
|
||||
{
|
||||
softbus::core::memory::MemoryPool::BlockPtr block;
|
||||
std::size_t offset{0};
|
||||
std::size_t length{0};
|
||||
|
||||
const std::uint8_t* bytes() const
|
||||
{
|
||||
if (!block || !block->data || offset > block->capacity) {
|
||||
return nullptr;
|
||||
}
|
||||
return block->data + offset;
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
return block && block->data && (offset + length <= block->capacity);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::pipeline
|
||||
|
||||
Q_DECLARE_METATYPE(softbus::message_bus::pipeline::PayloadRef)
|
||||
@@ -1,7 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
// Placeholder for pipeline context.
|
||||
class PipelineContext {
|
||||
public:
|
||||
PipelineContext() = default;
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QMetaType>
|
||||
#include <QString>
|
||||
|
||||
#include "message_bus/pipeline/PayloadRef.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline
|
||||
{
|
||||
|
||||
struct PipelineContext
|
||||
{
|
||||
int deviceId{-1}; // 设备ID
|
||||
QString stableKey;
|
||||
QString endpoint; // 端点
|
||||
QDateTime timestamp{QDateTime::currentDateTimeUtc()}; // 时间戳
|
||||
QString protocolHint; // 协议提示
|
||||
QString traceId; // 跟踪ID
|
||||
|
||||
PayloadRef payload; // 有效载荷
|
||||
std::size_t payloadSize{0}; // 有效载荷大小
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::pipeline
|
||||
|
||||
Q_DECLARE_METATYPE(softbus::message_bus::pipeline::PipelineContext)
|
||||
|
||||
142
src/message_bus/pipeline/PipelineEngine.cpp
Normal file
142
src/message_bus/pipeline/PipelineEngine.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "message_bus/pipeline/PipelineEngine.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline
|
||||
{
|
||||
|
||||
PipelineEngine::PipelineEngine(std::size_t queueCapacity)
|
||||
: m_ingressQ(queueCapacity), m_egressQ(queueCapacity)
|
||||
{
|
||||
}
|
||||
|
||||
PipelineEngine::~PipelineEngine()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void PipelineEngine::start()
|
||||
{
|
||||
if (m_running.exchange(true)) {
|
||||
return;
|
||||
}
|
||||
m_worker = std::thread([this]() { run(); });
|
||||
}
|
||||
|
||||
void PipelineEngine::stop()
|
||||
{
|
||||
if (!m_running.exchange(false)) {
|
||||
return;
|
||||
}
|
||||
if (m_worker.joinable()) {
|
||||
m_worker.join();
|
||||
}
|
||||
}
|
||||
|
||||
void PipelineEngine::drain()
|
||||
{
|
||||
PipelineContext tmp;
|
||||
while (m_ingressQ.pop(tmp)) {
|
||||
}
|
||||
}
|
||||
|
||||
bool PipelineEngine::enqueueIngress(PipelineContext ctx)
|
||||
{
|
||||
if (!m_ingressQ.push(std::move(ctx))) {
|
||||
++m_counters.drop;
|
||||
return false;
|
||||
}
|
||||
++m_counters.in;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PipelineEngine::enqueueEgress(PipelineContext ctx)
|
||||
{
|
||||
return m_egressQ.push(std::move(ctx));
|
||||
}
|
||||
|
||||
bool PipelineEngine::tryPopEgress(PipelineContext& out)
|
||||
{
|
||||
return m_egressQ.pop(out);
|
||||
}
|
||||
|
||||
void PipelineEngine::setPluginManager(std::shared_ptr<softbus::core::plugin_system::PluginManager> pluginManager)
|
||||
{
|
||||
m_pluginManager = std::move(pluginManager);
|
||||
}
|
||||
|
||||
void PipelineEngine::run()
|
||||
{
|
||||
while (m_running.load()) {
|
||||
PipelineContext ctx;
|
||||
if (!m_ingressQ.pop(ctx)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool framed = stage1Framer(ctx);
|
||||
const bool parsed = framed && stage2Parser(ctx);
|
||||
const bool filtered = parsed && stage3Filter(ctx);
|
||||
const bool valid = filtered && stage4Validator(ctx);
|
||||
if (!valid) {
|
||||
++m_counters.error;
|
||||
continue;
|
||||
}
|
||||
if (!m_egressQ.push(std::move(ctx))) {
|
||||
++m_counters.drop;
|
||||
continue;
|
||||
}
|
||||
++m_counters.out;
|
||||
}
|
||||
}
|
||||
|
||||
bool PipelineEngine::stage1Framer(PipelineContext& ctx)
|
||||
{
|
||||
if (!ctx.payload.valid()) {
|
||||
return false;
|
||||
}
|
||||
if (ctx.payloadSize == 0) {
|
||||
ctx.payloadSize = ctx.payload.length;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PipelineEngine::stage4Validator(PipelineContext& ctx)
|
||||
{
|
||||
if (!ctx.payload.valid()) {
|
||||
return false;
|
||||
}
|
||||
if (ctx.endpoint.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (!ctx.timestamp.isValid()) {
|
||||
ctx.timestamp = QDateTime::currentDateTimeUtc();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PipelineEngine::stage2Parser(PipelineContext& ctx)
|
||||
{
|
||||
if (!m_pluginManager) {
|
||||
return true;
|
||||
}
|
||||
auto plugin = m_pluginManager->selectProtocolPlugin(ctx.protocolHint);
|
||||
if (!plugin) {
|
||||
return true;
|
||||
}
|
||||
auto session = plugin->createSession();
|
||||
if (!session) {
|
||||
return false;
|
||||
}
|
||||
return session->feed(ctx);
|
||||
}
|
||||
|
||||
bool PipelineEngine::stage3Filter(PipelineContext& ctx)
|
||||
{
|
||||
(void)ctx;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace softbus::message_bus::pipeline
|
||||
@@ -1,7 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
// Placeholder for pipeline engine.
|
||||
class PipelineEngine {
|
||||
public:
|
||||
PipelineEngine() = default;
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
#include "core/plugin_system/PluginManager.h"
|
||||
#include "core/memory/LockFreeQueue.h"
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline
|
||||
{
|
||||
|
||||
class PipelineEngine
|
||||
{
|
||||
public:
|
||||
struct Counters
|
||||
{
|
||||
std::atomic<std::uint64_t> in{0};
|
||||
std::atomic<std::uint64_t> out{0};
|
||||
std::atomic<std::uint64_t> drop{0};
|
||||
std::atomic<std::uint64_t> error{0};
|
||||
};
|
||||
|
||||
explicit PipelineEngine(std::size_t queueCapacity = 4096);
|
||||
~PipelineEngine();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void drain();
|
||||
|
||||
bool enqueueIngress(PipelineContext ctx);
|
||||
bool enqueueEgress(PipelineContext ctx);
|
||||
|
||||
bool tryPopEgress(PipelineContext& out);
|
||||
void setPluginManager(std::shared_ptr<softbus::core::plugin_system::PluginManager> pluginManager);
|
||||
|
||||
const Counters& counters() const { return m_counters; }
|
||||
|
||||
private:
|
||||
void run();
|
||||
bool stage1Framer(PipelineContext& ctx);
|
||||
bool stage2Parser(PipelineContext& ctx);
|
||||
bool stage3Filter(PipelineContext& ctx);
|
||||
bool stage4Validator(PipelineContext& ctx);
|
||||
|
||||
private:
|
||||
softbus::core::memory::LockFreeQueue<PipelineContext> m_ingressQ;
|
||||
softbus::core::memory::LockFreeQueue<PipelineContext> m_egressQ;
|
||||
std::atomic<bool> m_running{false};
|
||||
std::thread m_worker;
|
||||
Counters m_counters;
|
||||
std::shared_ptr<softbus::core::plugin_system::PluginManager> m_pluginManager;
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::pipeline
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "message_bus/pipeline/stages/1_framers/IFramer.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::stages::framers
|
||||
{
|
||||
|
||||
// Placeholder TU for stage1 concrete framer implementations.
|
||||
|
||||
} // namespace softbus::message_bus::pipeline::stages::framers
|
||||
15
src/message_bus/pipeline/stages/1_framers/IFramer.h
Normal file
15
src/message_bus/pipeline/stages/1_framers/IFramer.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::stages::framers
|
||||
{
|
||||
|
||||
class IFramer
|
||||
{
|
||||
public:
|
||||
virtual ~IFramer() = default;
|
||||
virtual bool frame(softbus::message_bus::pipeline::PipelineContext& ctx) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::pipeline::stages::framers
|
||||
15
src/message_bus/pipeline/stages/2_parsers/IParserStage.h
Normal file
15
src/message_bus/pipeline/stages/2_parsers/IParserStage.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::stages::parsers
|
||||
{
|
||||
|
||||
class IParserStage
|
||||
{
|
||||
public:
|
||||
virtual ~IParserStage() = default;
|
||||
virtual bool parse(softbus::message_bus::pipeline::PipelineContext& ctx) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::pipeline::stages::parsers
|
||||
15
src/message_bus/pipeline/stages/3_filters/IFilterStage.h
Normal file
15
src/message_bus/pipeline/stages/3_filters/IFilterStage.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::stages::filters
|
||||
{
|
||||
|
||||
class IFilterStage
|
||||
{
|
||||
public:
|
||||
virtual ~IFilterStage() = default;
|
||||
virtual bool apply(softbus::message_bus::pipeline::PipelineContext& ctx) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::pipeline::stages::filters
|
||||
15
src/message_bus/pipeline/stages/4_validators/IValidator.h
Normal file
15
src/message_bus/pipeline/stages/4_validators/IValidator.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "message_bus/pipeline/PipelineContext.h"
|
||||
|
||||
namespace softbus::message_bus::pipeline::stages::validators
|
||||
{
|
||||
|
||||
class IValidator
|
||||
{
|
||||
public:
|
||||
virtual ~IValidator() = default;
|
||||
virtual bool validate(softbus::message_bus::pipeline::PipelineContext& ctx) = 0;
|
||||
};
|
||||
|
||||
} // namespace softbus::message_bus::pipeline::stages::validators
|
||||
Reference in New Issue
Block a user