设备监控-回写
This commit is contained in:
@@ -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<DeviceBusManager> manager;
|
||||
std::unique_ptr<monitor::DeviceMonitorService> monitorService;
|
||||
std::unique_ptr<registry::DeviceRegistry> registry;
|
||||
std::shared_ptr<DeviceTreeModel> 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<monitor::DeviceMonitorService>(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<DeviceTreeModel>();
|
||||
}
|
||||
d->manager.setDeviceTreeModel(d->treeModel);
|
||||
return d->manager.initialize(rootConfig);
|
||||
if (!d->manager) {
|
||||
d->manager = std::make_unique<DeviceBusManager>();
|
||||
}
|
||||
if (!d->registry) {
|
||||
d->registry = std::make_unique<registry::DeviceRegistry>(d->treeModel);
|
||||
}
|
||||
d->manager->setDeviceTreeModel(d->treeModel);
|
||||
d->manager->setRegistry(d->registry.get());
|
||||
|
||||
if (!d->monitorService) {
|
||||
d->monitorService = std::make_unique<monitor::DeviceMonitorService>(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<DeviceTreeModel> DeviceBus::deviceTreeModel() const {
|
||||
if (!d) return {};
|
||||
return d->treeModel;
|
||||
}
|
||||
|
||||
void DeviceBus::markDeviceTreeDirty() {
|
||||
if (!d) return;
|
||||
d->deviceTreeDirty = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QSerialPort>
|
||||
#include <algorithm>
|
||||
// #include <algorithm>
|
||||
|
||||
#include "hardware/drivers/serial/SerialQtDriver.h"
|
||||
#include "hardware/drivers/serial/SerialCapabilities.h"
|
||||
@@ -19,6 +19,11 @@ void DeviceBusManager::setDeviceTreeModel(std::shared_ptr<DeviceTreeModel> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ class DeviceBusManager
|
||||
{
|
||||
public:
|
||||
void setDeviceTreeModel(std::shared_ptr<DeviceTreeModel> model);
|
||||
void setRegistry(softbus::device_bus::registry::IDeviceRegistry* registry);
|
||||
|
||||
bool initialize(const QJsonObject& rootConfig);
|
||||
void shutdown();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <QJsonDocument>
|
||||
|
||||
#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<void()> 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)
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
#include <vector>
|
||||
#include <QHash>
|
||||
#include <QDateTime>
|
||||
#include <functional>
|
||||
|
||||
#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<void()> cb);
|
||||
|
||||
private:
|
||||
void onEvent(const DeviceEvent& ev);
|
||||
@@ -27,6 +32,8 @@ private:
|
||||
private:
|
||||
std::vector<std::unique_ptr<IDeviceMonitor>> m_monitors;
|
||||
bool m_started{false};
|
||||
softbus::device_bus::registry::IDeviceRegistry* m_registry{nullptr};
|
||||
std::function<void()> m_dirtyCb;
|
||||
|
||||
// Lightweight de-dup: key -> last timestamp (ms)
|
||||
QHash<QString, qint64> m_lastEventMsByKey;
|
||||
|
||||
166
src/device_bus/registry/DeviceRegistry.cpp
Normal file
166
src/device_bus/registry/DeviceRegistry.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#include "device_bus/registry/DeviceRegistry.h"
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "utils/logs/logging.h"
|
||||
|
||||
namespace softbus::device_bus::registry
|
||||
{
|
||||
|
||||
DeviceRegistry::DeviceRegistry(std::shared_ptr<DeviceTreeModel> 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<softbus::devices::DeviceInfo> DeviceRegistry::findById(int id) const
|
||||
{
|
||||
auto it = m_devicesById.constFind(id);
|
||||
if (it == m_devicesById.constEnd()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return it.value();
|
||||
}
|
||||
|
||||
std::vector<softbus::devices::DeviceInfo> DeviceRegistry::listDevices() const
|
||||
{
|
||||
std::vector<softbus::devices::DeviceInfo> 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
|
||||
|
||||
44
src/device_bus/registry/DeviceRegistry.h
Normal file
44
src/device_bus/registry/DeviceRegistry.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#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<DeviceTreeModel> treeModel);
|
||||
~DeviceRegistry() override = default;
|
||||
|
||||
void registerDevice(const softbus::devices::DeviceInfo& info) override;
|
||||
void unregisterDevice(int id) override;
|
||||
|
||||
std::optional<softbus::devices::DeviceInfo> findById(int id) const override;
|
||||
std::vector<softbus::devices::DeviceInfo> 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<DeviceTreeModel> m_treeModel;
|
||||
QHash<int, softbus::devices::DeviceInfo> m_devicesById;
|
||||
QHash<QString, QString> m_stableKeyToNodeId;
|
||||
};
|
||||
|
||||
} // namespace softbus::device_bus::registry
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "devices/DeviceTypes.h"
|
||||
#include "device_bus/monitor/DeviceEvent.h"
|
||||
|
||||
namespace softbus::device_bus::registry
|
||||
{
|
||||
@@ -18,6 +19,10 @@ public:
|
||||
|
||||
virtual std::optional<softbus::devices::DeviceInfo> findById(int id) const = 0;
|
||||
virtual std::vector<softbus::devices::DeviceInfo> 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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,19 @@ public:
|
||||
QVector<DeviceTreeNode>& 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;
|
||||
|
||||
Reference in New Issue
Block a user