diff --git a/.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx b/.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx index 8043a60..ff9885c 100644 Binary files a/.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx and b/.cache/clangd/index/DeviceBus.cpp.3FE983A42FE7A6A8.idx differ diff --git a/.cache/clangd/index/DeviceBusManager.cpp.134168DDD210A4ED.idx b/.cache/clangd/index/DeviceBusManager.cpp.134168DDD210A4ED.idx index fe7255a..f41dcb8 100644 Binary files a/.cache/clangd/index/DeviceBusManager.cpp.134168DDD210A4ED.idx and b/.cache/clangd/index/DeviceBusManager.cpp.134168DDD210A4ED.idx differ diff --git a/.cache/clangd/index/DeviceBusManager.h.4DAD625CA48C7EE3.idx b/.cache/clangd/index/DeviceBusManager.h.4DAD625CA48C7EE3.idx index 0598482..5753cf4 100644 Binary files a/.cache/clangd/index/DeviceBusManager.h.4DAD625CA48C7EE3.idx and b/.cache/clangd/index/DeviceBusManager.h.4DAD625CA48C7EE3.idx differ diff --git a/.cache/clangd/index/DeviceMonitorService.cpp.3C0446CEC6FFCFAC.idx b/.cache/clangd/index/DeviceMonitorService.cpp.3C0446CEC6FFCFAC.idx index 8950ce9..c2f9e98 100644 Binary files a/.cache/clangd/index/DeviceMonitorService.cpp.3C0446CEC6FFCFAC.idx and b/.cache/clangd/index/DeviceMonitorService.cpp.3C0446CEC6FFCFAC.idx differ diff --git a/.cache/clangd/index/DeviceMonitorService.h.2C037D82AC481AAB.idx b/.cache/clangd/index/DeviceMonitorService.h.2C037D82AC481AAB.idx index 12e7e8d..4b3b889 100644 Binary files a/.cache/clangd/index/DeviceMonitorService.h.2C037D82AC481AAB.idx and b/.cache/clangd/index/DeviceMonitorService.h.2C037D82AC481AAB.idx differ diff --git a/.cache/clangd/index/DeviceRegistry.cpp.D6392F292F1C203D.idx b/.cache/clangd/index/DeviceRegistry.cpp.D6392F292F1C203D.idx new file mode 100644 index 0000000..e19334f Binary files /dev/null and b/.cache/clangd/index/DeviceRegistry.cpp.D6392F292F1C203D.idx differ diff --git a/.cache/clangd/index/DeviceRegistry.h.97F54B624D840DC0.idx b/.cache/clangd/index/DeviceRegistry.h.97F54B624D840DC0.idx new file mode 100644 index 0000000..8f17e23 Binary files /dev/null and b/.cache/clangd/index/DeviceRegistry.h.97F54B624D840DC0.idx differ diff --git a/.cache/clangd/index/DeviceTreeModel.cpp.D68EA11C8BBF4ADF.idx b/.cache/clangd/index/DeviceTreeModel.cpp.D68EA11C8BBF4ADF.idx index 709efaa..2fa26e1 100644 Binary files a/.cache/clangd/index/DeviceTreeModel.cpp.D68EA11C8BBF4ADF.idx and b/.cache/clangd/index/DeviceTreeModel.cpp.D68EA11C8BBF4ADF.idx differ diff --git a/.cache/clangd/index/DeviceTreeModel.h.A5637DBA59AB7F8A.idx b/.cache/clangd/index/DeviceTreeModel.h.A5637DBA59AB7F8A.idx index d40cdd8..5c84463 100644 Binary files a/.cache/clangd/index/DeviceTreeModel.h.A5637DBA59AB7F8A.idx and b/.cache/clangd/index/DeviceTreeModel.h.A5637DBA59AB7F8A.idx differ diff --git a/.cache/clangd/index/IDeviceRegistry.h.255744FF99F84B26.idx b/.cache/clangd/index/IDeviceRegistry.h.255744FF99F84B26.idx index dc17278..d1711c1 100644 Binary files a/.cache/clangd/index/IDeviceRegistry.h.255744FF99F84B26.idx and b/.cache/clangd/index/IDeviceRegistry.h.255744FF99F84B26.idx differ diff --git a/.cache/clangd/index/NetlinkDeviceMonitor.cpp.852AB1C86537EBFF.idx b/.cache/clangd/index/NetlinkDeviceMonitor.cpp.852AB1C86537EBFF.idx index 1b9e41a..e5f390b 100644 Binary files a/.cache/clangd/index/NetlinkDeviceMonitor.cpp.852AB1C86537EBFF.idx and b/.cache/clangd/index/NetlinkDeviceMonitor.cpp.852AB1C86537EBFF.idx differ diff --git a/.cache/clangd/index/NetlinkDeviceMonitor.h.D31493ABAC6FE7FD.idx b/.cache/clangd/index/NetlinkDeviceMonitor.h.D31493ABAC6FE7FD.idx index 918357f..f5bb5c9 100644 Binary files a/.cache/clangd/index/NetlinkDeviceMonitor.h.D31493ABAC6FE7FD.idx and b/.cache/clangd/index/NetlinkDeviceMonitor.h.D31493ABAC6FE7FD.idx differ diff --git a/.cache/clangd/index/UdevDeviceMonitor.cpp.8FD4DE713A589E66.idx b/.cache/clangd/index/UdevDeviceMonitor.cpp.8FD4DE713A589E66.idx index d8682aa..20edc35 100644 Binary files a/.cache/clangd/index/UdevDeviceMonitor.cpp.8FD4DE713A589E66.idx and b/.cache/clangd/index/UdevDeviceMonitor.cpp.8FD4DE713A589E66.idx differ diff --git a/CMakeLists.txt b/CMakeLists.txt index 9caca72..fcb4781 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -100,6 +100,8 @@ qt_add_executable(softbus_daemon # device bus: registry skeleton src/device_bus/registry/IDeviceRegistry.h + src/device_bus/registry/DeviceRegistry.h + src/device_bus/registry/DeviceRegistry.cpp # devices: base skeleton src/devices/base/IDevice.h diff --git a/bin/softbus_daemon b/bin/softbus_daemon index bfbcc83..37b5ac5 100755 Binary files a/bin/softbus_daemon and b/bin/softbus_daemon differ diff --git a/main.cpp b/main.cpp index 27d4e92..3b0b49b 100644 --- a/main.cpp +++ b/main.cpp @@ -10,6 +10,11 @@ void signalHandler(int signal) { LOG_INFO() << "Received signal:" << signal; + CoreService* coreService = CoreService::instance(); + if (coreService) { + coreService->shutdown(); + } + QCoreApplication::quit(); } @@ -68,7 +73,7 @@ int main(int argc, char *argv[]) LOG_ERROR() << "CoreService initialize failed"; return 1; } - QObject::connect(&app, &QCoreApplication::aboutToQuit, coreService, &CoreService::shutdown); + // QObject::connect(&app, &QCoreApplication::aboutToQuit, coreService, &CoreService::shutdown); // ======================================================================== // 创建并注册 D-Bus 服务(仅在 CoreRouter 角色中启用) diff --git a/src/core/CoreService.cpp b/src/core/CoreService.cpp index c982324..034b3c5 100644 --- a/src/core/CoreService.cpp +++ b/src/core/CoreService.cpp @@ -24,7 +24,7 @@ CoreService::CoreService(QObject* parent) CoreService::~CoreService() { - shutdown(); + } bool CoreService::initialize() diff --git a/src/device_bus/DeviceBus.cpp b/src/device_bus/DeviceBus.cpp index d6cb732..d939c65 100644 --- a/src/device_bus/DeviceBus.cpp +++ b/src/device_bus/DeviceBus.cpp @@ -7,6 +7,7 @@ #include "device_bus/manager/DeviceBusManager.h" #include "device_bus/monitor/DeviceMonitorService.h" +#include "device_bus/registry/DeviceRegistry.h" #include "device_bus/tree/DeviceTreeModel.h" #include "utils/logs/logging.h" @@ -14,11 +15,12 @@ namespace softbus::device_bus { class DeviceBus::Impl { public: - DeviceBusManager manager; + std::unique_ptr manager; std::unique_ptr monitorService; + std::unique_ptr registry; std::shared_ptr treeModel; QString configPath; - bool deviceTreeDirty{false}; + bool deviceTreeDirty{false}; // 设备树是否脏了 }; DeviceBus &DeviceBus::instance() { @@ -34,37 +36,61 @@ DeviceBus::~DeviceBus() { } bool DeviceBus::initialize(const QJsonObject &rootConfig) { - if (!d->monitorService) { - d->monitorService = std::make_unique(nullptr); - if (!d->monitorService->start()) { - LOG_WARNING() << "DeviceBus: device monitor service start failed"; - } + if (!d) { + return false; } if (!d->treeModel) { d->treeModel = std::make_shared(); } - d->manager.setDeviceTreeModel(d->treeModel); - return d->manager.initialize(rootConfig); + if (!d->manager) { + d->manager = std::make_unique(); + } + if (!d->registry) { + d->registry = std::make_unique(d->treeModel); + } + d->manager->setDeviceTreeModel(d->treeModel); + d->manager->setRegistry(d->registry.get()); + + if (!d->monitorService) { + d->monitorService = std::make_unique(nullptr); + d->monitorService->setRegistry(d->registry.get()); + d->monitorService->setDirtyCallback([this]() { this->markDeviceTreeDirty(); }); + if (!d->monitorService->start()) { + LOG_WARNING() << "DeviceBus: device monitor service start failed"; + } + } + return d->manager->initialize(rootConfig); } void DeviceBus::shutdown() { + if (!d) { + return; + } + if (d->monitorService) { + LOG_INFO() << "DeviceBus shutting down monitor service"; d->monitorService->stop(); d->monitorService.reset(); } - d->manager.shutdown(); + if (d->manager) { + LOG_INFO() << "DeviceBus shutting down manager"; + d->manager->shutdown(); + } if (!d->deviceTreeDirty) { + LOG_INFO() << "DeviceBus device tree dirty is false"; return; } + if (d->configPath.isEmpty() || !d->treeModel) { return; } const QFileInfo fi(d->configPath); const QString dirPath = fi.dir().absolutePath(); + LOG_INFO() << "DeviceBus: saving config to" << dirPath; if (!QDir().mkpath(dirPath)) { LOG_ERROR() << "DeviceBus: failed to create config dir" << dirPath; return; @@ -92,18 +118,22 @@ void DeviceBus::shutdown() { } void DeviceBus::setConfigPath(const QString& path) { + if (!d) return; d->configPath = path; } QString DeviceBus::configPath() const { + if (!d) return {}; return d->configPath; } std::shared_ptr DeviceBus::deviceTreeModel() const { + if (!d) return {}; return d->treeModel; } void DeviceBus::markDeviceTreeDirty() { + if (!d) return; d->deviceTreeDirty = true; } diff --git a/src/device_bus/manager/DeviceBusManager.cpp b/src/device_bus/manager/DeviceBusManager.cpp index fb5d19d..678f1eb 100644 --- a/src/device_bus/manager/DeviceBusManager.cpp +++ b/src/device_bus/manager/DeviceBusManager.cpp @@ -4,7 +4,7 @@ #include #include -#include +// #include #include "hardware/drivers/serial/SerialQtDriver.h" #include "hardware/drivers/serial/SerialCapabilities.h" @@ -19,6 +19,11 @@ void DeviceBusManager::setDeviceTreeModel(std::shared_ptr model m_treeModel = std::move(model); } +void DeviceBusManager::setRegistry(softbus::device_bus::registry::IDeviceRegistry* registry) +{ + m_registry = registry; +} + bool DeviceBusManager::initialize(const QJsonObject& rootConfig) { if (!m_treeModel) { @@ -167,4 +172,4 @@ void DeviceBusManager::shutdownSerialDevice(const QString& endpoint) } m_serialDevicesByEndpoint.erase(it); -} \ No newline at end of file +} diff --git a/src/device_bus/manager/DeviceBusManager.h b/src/device_bus/manager/DeviceBusManager.h index 7d54ac1..317a470 100644 --- a/src/device_bus/manager/DeviceBusManager.h +++ b/src/device_bus/manager/DeviceBusManager.h @@ -17,6 +17,7 @@ class DeviceBusManager { public: void setDeviceTreeModel(std::shared_ptr model); + void setRegistry(softbus::device_bus::registry::IDeviceRegistry* registry); bool initialize(const QJsonObject& rootConfig); void shutdown(); diff --git a/src/device_bus/monitor/DeviceMonitorService.cpp b/src/device_bus/monitor/DeviceMonitorService.cpp index 8ed8589..418bf82 100644 --- a/src/device_bus/monitor/DeviceMonitorService.cpp +++ b/src/device_bus/monitor/DeviceMonitorService.cpp @@ -2,6 +2,7 @@ #include +#include "device_bus/registry/IDeviceRegistry.h" #include "utils/logs/logging.h" #if defined(__linux__) @@ -57,6 +58,16 @@ void DeviceMonitorService::stop() m_started = false; } +void DeviceMonitorService::setRegistry(softbus::device_bus::registry::IDeviceRegistry* registry) +{ + m_registry = registry; +} + +void DeviceMonitorService::setDirtyCallback(std::function cb) +{ + m_dirtyCb = std::move(cb); +} + void DeviceMonitorService::onEvent(const DeviceEvent& ev) { // De-dup (short window): suppress identical events bursts @@ -78,6 +89,18 @@ void DeviceMonitorService::onEvent(const DeviceEvent& ev) } m_lastEventMsByKey.insert(key, nowMs); + if (m_registry) { + bool changed = false; + if (ev.action == DeviceEventAction::Add || ev.action == DeviceEventAction::Change) { + changed = m_registry->upsertFromMonitorEvent(ev); + } else if (ev.action == DeviceEventAction::Remove) { + changed = m_registry->markOfflineFromMonitorEvent(ev); + } + if (changed && m_dirtyCb) { + m_dirtyCb(); + } + } + // 第一版:仅日志 LOG_INFO() << "DeviceMonitor event" << "type=" << toString(ev.type) diff --git a/src/device_bus/monitor/DeviceMonitorService.h b/src/device_bus/monitor/DeviceMonitorService.h index bb192ef..8ecb696 100644 --- a/src/device_bus/monitor/DeviceMonitorService.h +++ b/src/device_bus/monitor/DeviceMonitorService.h @@ -5,9 +5,12 @@ #include #include #include +#include #include "device_bus/monitor/IDeviceMonitor.h" +namespace softbus::device_bus::registry { class IDeviceRegistry; } + namespace softbus::device_bus::monitor { @@ -20,6 +23,8 @@ public: bool start(); void stop(); + void setRegistry(softbus::device_bus::registry::IDeviceRegistry* registry); + void setDirtyCallback(std::function cb); private: void onEvent(const DeviceEvent& ev); @@ -27,6 +32,8 @@ private: private: std::vector> m_monitors; bool m_started{false}; + softbus::device_bus::registry::IDeviceRegistry* m_registry{nullptr}; + std::function m_dirtyCb; // Lightweight de-dup: key -> last timestamp (ms) QHash m_lastEventMsByKey; diff --git a/src/device_bus/registry/DeviceRegistry.cpp b/src/device_bus/registry/DeviceRegistry.cpp new file mode 100644 index 0000000..5937434 --- /dev/null +++ b/src/device_bus/registry/DeviceRegistry.cpp @@ -0,0 +1,166 @@ +#include "device_bus/registry/DeviceRegistry.h" + +#include +#include + +#include "utils/logs/logging.h" + +namespace softbus::device_bus::registry +{ + +DeviceRegistry::DeviceRegistry(std::shared_ptr treeModel) + : m_treeModel(std::move(treeModel)) +{ +} + +void DeviceRegistry::registerDevice(const softbus::devices::DeviceInfo& info) +{ + m_devicesById.insert(info.id, info); +} + +void DeviceRegistry::unregisterDevice(int id) +{ + m_devicesById.remove(id); +} + +std::optional DeviceRegistry::findById(int id) const +{ + auto it = m_devicesById.constFind(id); + if (it == m_devicesById.constEnd()) { + return std::nullopt; + } + return it.value(); +} + +std::vector DeviceRegistry::listDevices() const +{ + std::vector out; + out.reserve(m_devicesById.size()); + for (auto it = m_devicesById.cbegin(); it != m_devicesById.cend(); ++it) { + out.push_back(it.value()); + } + return out; +} + +bool DeviceRegistry::upsertFromMonitorEvent(const softbus::device_bus::monitor::DeviceEvent& ev) +{ + if (!m_treeModel) return false; + + const QString stableKey = buildStableKey(ev); + if (stableKey.isEmpty()) { + return false; + } + const QString preferredId = buildPreferredNodeId(ev, stableKey); + const QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODate); + + const QString nodeId = m_treeModel->upsertNodeByStableKey( + stableKey, + preferredId, + inferType(ev), + inferEndpoint(ev), + inferName(ev), + buildParams(ev), + true, + now); + + if (!nodeId.isEmpty()) { + m_stableKeyToNodeId.insert(stableKey, nodeId); + return true; + } + return false; +} + +bool DeviceRegistry::markOfflineFromMonitorEvent(const softbus::device_bus::monitor::DeviceEvent& ev) +{ + if (!m_treeModel) return false; + const QString stableKey = buildStableKey(ev); + if (stableKey.isEmpty()) { + return false; + } + const QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODate); + return m_treeModel->markOfflineByStableKey(stableKey, now); +} + +QString DeviceRegistry::buildStableKey(const softbus::device_bus::monitor::DeviceEvent& ev) +{ + const QString type = inferType(ev); + + if (!ev.serial.isEmpty()) { + return type + QStringLiteral("|serial|") + ev.serial; + } + + if (ev.type == softbus::device_bus::monitor::DeviceEventType::NetInterface) { + if (!ev.ifname.isEmpty()) return type + QStringLiteral("|ifname|") + ev.ifname; + if (ev.ifindex >= 0) return type + QStringLiteral("|ifindex|") + QString::number(ev.ifindex); + } + + const QString path = !ev.props.value(QStringLiteral("SYSPATH")).isEmpty() + ? ev.props.value(QStringLiteral("SYSPATH")) + : (!ev.devicePath.isEmpty() ? ev.devicePath : ev.devnode); + if (!ev.vid.isEmpty() || !ev.pid.isEmpty() || !path.isEmpty()) { + return type + QStringLiteral("|vpidpath|") + ev.vid + QStringLiteral(":") + ev.pid + QStringLiteral("|") + path; + } + + if (!ev.devnode.isEmpty()) { + return type + QStringLiteral("|devnode|") + ev.devnode; + } + return {}; +} + +QString DeviceRegistry::buildPreferredNodeId(const softbus::device_bus::monitor::DeviceEvent& ev, const QString& stableKey) +{ + if (!ev.serial.isEmpty()) { + return QStringLiteral("dev_serial_") + ev.serial; + } + + const QByteArray hash = QCryptographicHash::hash(stableKey.toUtf8(), QCryptographicHash::Sha1).toHex(); + return QStringLiteral("dev_") + QString::fromUtf8(hash.left(12)); +} + +QString DeviceRegistry::inferType(const softbus::device_bus::monitor::DeviceEvent& ev) +{ + using softbus::device_bus::monitor::DeviceEventType; + switch (ev.type) { + case DeviceEventType::Serial: return QStringLiteral("serial"); + case DeviceEventType::NetInterface: return QStringLiteral("network"); + case DeviceEventType::Storage: return QStringLiteral("storage"); + case DeviceEventType::Usb: return QStringLiteral("usb"); + default: return QStringLiteral("unknown"); + } +} + +QString DeviceRegistry::inferEndpoint(const softbus::device_bus::monitor::DeviceEvent& ev) +{ + if (!ev.devnode.isEmpty()) return ev.devnode; + if (!ev.ifname.isEmpty()) return ev.ifname; + if (!ev.devicePath.isEmpty()) return ev.devicePath; + return ev.props.value(QStringLiteral("SYSPATH")); +} + +QString DeviceRegistry::inferName(const softbus::device_bus::monitor::DeviceEvent& ev) +{ + if (!ev.model.isEmpty()) return ev.model; + if (!ev.ifname.isEmpty()) return ev.ifname; + if (!ev.devnode.isEmpty()) return ev.devnode; + return inferType(ev); +} + +QJsonObject DeviceRegistry::buildParams(const softbus::device_bus::monitor::DeviceEvent& ev) +{ + QJsonObject p; + p.insert(QStringLiteral("online"), true); + if (!ev.vid.isEmpty()) p.insert(QStringLiteral("vid"), ev.vid); + if (!ev.pid.isEmpty()) p.insert(QStringLiteral("pid"), ev.pid); + if (!ev.serial.isEmpty()) p.insert(QStringLiteral("serial"), ev.serial); + if (!ev.vendor.isEmpty()) p.insert(QStringLiteral("vendor"), ev.vendor); + if (!ev.model.isEmpty()) p.insert(QStringLiteral("model"), ev.model); + if (!ev.ifname.isEmpty()) p.insert(QStringLiteral("ifname"), ev.ifname); + if (ev.ifindex >= 0) p.insert(QStringLiteral("ifindex"), ev.ifindex); + if (!ev.subsystem.isEmpty()) p.insert(QStringLiteral("subsystem"), ev.subsystem); + if (!ev.devicePath.isEmpty()) p.insert(QStringLiteral("devicePath"), ev.devicePath); + if (!ev.devnode.isEmpty()) p.insert(QStringLiteral("devnode"), ev.devnode); + return p; +} + +} // namespace softbus::device_bus::registry + diff --git a/src/device_bus/registry/DeviceRegistry.h b/src/device_bus/registry/DeviceRegistry.h new file mode 100644 index 0000000..bf9bdb5 --- /dev/null +++ b/src/device_bus/registry/DeviceRegistry.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include + +#include "device_bus/registry/IDeviceRegistry.h" +#include "device_bus/tree/DeviceTreeModel.h" + +namespace softbus::device_bus::registry +{ + +class DeviceRegistry : public IDeviceRegistry +{ +public: + explicit DeviceRegistry(std::shared_ptr treeModel); + ~DeviceRegistry() override = default; + + void registerDevice(const softbus::devices::DeviceInfo& info) override; + void unregisterDevice(int id) override; + + std::optional findById(int id) const override; + std::vector listDevices() const override; + + bool upsertFromMonitorEvent(const softbus::device_bus::monitor::DeviceEvent& ev) override; + bool markOfflineFromMonitorEvent(const softbus::device_bus::monitor::DeviceEvent& ev) override; + +private: + static QString buildStableKey(const softbus::device_bus::monitor::DeviceEvent& ev); + static QString buildPreferredNodeId(const softbus::device_bus::monitor::DeviceEvent& ev, const QString& stableKey); + static QString inferType(const softbus::device_bus::monitor::DeviceEvent& ev); + static QString inferEndpoint(const softbus::device_bus::monitor::DeviceEvent& ev); + static QString inferName(const softbus::device_bus::monitor::DeviceEvent& ev); + static QJsonObject buildParams(const softbus::device_bus::monitor::DeviceEvent& ev); + +private: + std::shared_ptr m_treeModel; + QHash m_devicesById; + QHash m_stableKeyToNodeId; +}; + +} // namespace softbus::device_bus::registry + diff --git a/src/device_bus/registry/IDeviceRegistry.h b/src/device_bus/registry/IDeviceRegistry.h index 636b39d..66f2e32 100644 --- a/src/device_bus/registry/IDeviceRegistry.h +++ b/src/device_bus/registry/IDeviceRegistry.h @@ -4,6 +4,7 @@ #include #include "devices/DeviceTypes.h" +#include "device_bus/monitor/DeviceEvent.h" namespace softbus::device_bus::registry { @@ -18,6 +19,10 @@ public: virtual std::optional findById(int id) const = 0; virtual std::vector listDevices() const = 0; + + // Monitor-driven registry APIs + virtual bool upsertFromMonitorEvent(const softbus::device_bus::monitor::DeviceEvent& ev) = 0; + virtual bool markOfflineFromMonitorEvent(const softbus::device_bus::monitor::DeviceEvent& ev) = 0; }; } // namespace softbus::device_bus::registry diff --git a/src/device_bus/tree/DeviceTreeModel.cpp b/src/device_bus/tree/DeviceTreeModel.cpp index e1e631c..8ede967 100644 --- a/src/device_bus/tree/DeviceTreeModel.cpp +++ b/src/device_bus/tree/DeviceTreeModel.cpp @@ -118,14 +118,96 @@ QJsonObject DeviceTreeModel::toDaemonConfigRoot() const 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(); + const int index = findIndexById(id); if (index < 0 || index >= m_nodes.size()) { return nullptr; } return &m_nodes.at(index); } +int DeviceTreeModel::findIndexById(const QString& id) const +{ + const auto it = m_indexById.constFind(id); + if (it == m_indexById.constEnd()) { + return -1; + } + return it.value(); +} + +int DeviceTreeModel::findIndexByStableKey(const QString& stableKey) const +{ + if (stableKey.isEmpty()) { + return -1; + } + for (int i = 0; i < m_nodes.size(); ++i) { + const auto& n = m_nodes.at(i); + if (n.params.value(QStringLiteral("stableKey")).toString() == stableKey) { + return i; + } + } + return -1; +} + +QString DeviceTreeModel::upsertNodeByStableKey(const QString& stableKey, + const QString& preferredId, + const QString& type, + const QString& endpoint, + const QString& name, + const QJsonObject& extraParams, + bool online, + const QString& lastSeenTs) +{ + int idx = findIndexByStableKey(stableKey); + if (idx < 0 && !preferredId.isEmpty()) { + idx = findIndexById(preferredId); + } + + if (idx < 0) { + DeviceTreeNode node; + node.id = preferredId; + node.type = type; + node.endpoint = endpoint; + node.name = name; + node.enabled = true; + node.params = extraParams; + node.params.insert(QStringLiteral("stableKey"), stableKey); + node.params.insert(QStringLiteral("online"), online); + if (!lastSeenTs.isEmpty()) { + node.params.insert(QStringLiteral("lastSeenTs"), lastSeenTs); + } + m_nodes.push_back(node); + rebuildIndex(); + return node.id; + } + + auto& node = m_nodes[idx]; + if (!type.isEmpty()) node.type = type; + if (!endpoint.isEmpty()) node.endpoint = endpoint; + if (!name.isEmpty()) node.name = name; + node.enabled = true; + + for (auto it = extraParams.begin(); it != extraParams.end(); ++it) { + node.params.insert(it.key(), it.value()); + } + node.params.insert(QStringLiteral("stableKey"), stableKey); + node.params.insert(QStringLiteral("online"), online); + if (!lastSeenTs.isEmpty()) { + node.params.insert(QStringLiteral("lastSeenTs"), lastSeenTs); + } + return node.id; +} + +bool DeviceTreeModel::markOfflineByStableKey(const QString& stableKey, const QString& lastSeenTs) +{ + const int idx = findIndexByStableKey(stableKey); + if (idx < 0) { + return false; + } + auto& node = m_nodes[idx]; + node.params.insert(QStringLiteral("online"), false); + if (!lastSeenTs.isEmpty()) { + node.params.insert(QStringLiteral("lastSeenTs"), lastSeenTs); + } + return true; +} + diff --git a/src/device_bus/tree/DeviceTreeModel.h b/src/device_bus/tree/DeviceTreeModel.h index 7d27148..ab04948 100644 --- a/src/device_bus/tree/DeviceTreeModel.h +++ b/src/device_bus/tree/DeviceTreeModel.h @@ -31,6 +31,19 @@ public: QVector& nodesMutable() { return m_nodes; } const DeviceTreeNode* findById(const QString& id) const; + int findIndexById(const QString& id) const; + int findIndexByStableKey(const QString& stableKey) const; + + // Monitor/register path: upsert or mark online/offline + QString upsertNodeByStableKey(const QString& stableKey, + const QString& preferredId, + const QString& type, + const QString& endpoint, + const QString& name, + const QJsonObject& extraParams, + bool online, + const QString& lastSeenTs); + bool markOfflineByStableKey(const QString& stableKey, const QString& lastSeenTs); // 序列化为 daemon_config.json 所需格式 QJsonArray toDeviceTreeJson() const;