|
|
@@ -102,29 +102,132 @@ void SoftBusCore::registerDevice(const DeviceInfo &device) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- m_devices.insert(device.id, device);
|
|
|
+ DeviceInfo normalizedDevice = device;
|
|
|
+ if (normalizedDevice.status.isEmpty()) {
|
|
|
+ normalizedDevice.status = QStringLiteral("online");
|
|
|
+ }
|
|
|
+ normalizedDevice.isActive = true;
|
|
|
+ if (!normalizedDevice.lastSeen.isValid()) {
|
|
|
+ normalizedDevice.lastSeen = QDateTime::currentDateTimeUtc();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果未显式指定名称,则尝试沿用传入数据
|
|
|
+ if (normalizedDevice.name.isEmpty()) {
|
|
|
+ normalizedDevice.name = device.name;
|
|
|
+ }
|
|
|
+
|
|
|
+ int existingDeviceId = -1;
|
|
|
+ DeviceInfo persistedDevice;
|
|
|
+ const bool hasPort =
|
|
|
+ !normalizedDevice.portname.isEmpty();
|
|
|
+ if (hasPort) {
|
|
|
+ if (m_portnameToId.contains(normalizedDevice.portname)) {
|
|
|
+ existingDeviceId = m_portnameToId.value(normalizedDevice.portname);
|
|
|
+ if (m_devices.contains(existingDeviceId)) {
|
|
|
+ persistedDevice = m_devices.value(existingDeviceId);
|
|
|
+ } else {
|
|
|
+ // 内存缺失该设备,移除映射,稍后尝试从数据库查询
|
|
|
+ m_portnameToId.remove(normalizedDevice.portname);
|
|
|
+ existingDeviceId = -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (existingDeviceId <= 0 && m_dbInitialized) {
|
|
|
+ if (fetchPersistedDeviceByPort(normalizedDevice.portname,
|
|
|
+ persistedDevice)) {
|
|
|
+ existingDeviceId = persistedDevice.id;
|
|
|
+ if (existingDeviceId > 0) {
|
|
|
+ m_devices.insert(existingDeviceId, persistedDevice);
|
|
|
+ m_portnameToId[normalizedDevice.portname] = existingDeviceId;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (existingDeviceId > 0) {
|
|
|
+ DeviceInfo mergedDevice = normalizedDevice;
|
|
|
+ mergedDevice.id = existingDeviceId;
|
|
|
+ updateDevice(mergedDevice);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ m_devices.insert(normalizedDevice.id, normalizedDevice);
|
|
|
|
|
|
// 如果设备有端口名,建立映射关系
|
|
|
- if (!device.portname.isEmpty()) {
|
|
|
- m_portnameToId[device.portname] = device.id;
|
|
|
+ if (!normalizedDevice.portname.isEmpty()) {
|
|
|
+ m_portnameToId[normalizedDevice.portname] = normalizedDevice.id;
|
|
|
}
|
|
|
|
|
|
if (m_dbInitialized) {
|
|
|
// 先同步设备信息,再确保端口对应的原始/转化数据表存在
|
|
|
- upsertDeviceRecord(device);
|
|
|
- if (!device.portname.isEmpty()) {
|
|
|
- if (!ensurePerPortRawTable(device.portname)) {
|
|
|
+ upsertDeviceRecord(normalizedDevice, normalizedDevice.lastSeen);
|
|
|
+ if (!normalizedDevice.portname.isEmpty()) {
|
|
|
+ if (!ensurePerPortRawTable(normalizedDevice.portname)) {
|
|
|
qCritical() << "Failed to ensure raw data table for port"
|
|
|
- << device.portname;
|
|
|
+ << normalizedDevice.portname;
|
|
|
}
|
|
|
- if (!ensurePerPortTransformedTable(device.portname)) {
|
|
|
+ if (!ensurePerPortTransformedTable(normalizedDevice.portname)) {
|
|
|
qCritical() << "Failed to ensure transformed data table for port"
|
|
|
- << device.portname;
|
|
|
+ << normalizedDevice.portname;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- emit deviceRegistered(device);
|
|
|
+ emit deviceRegistered(normalizedDevice);
|
|
|
+}
|
|
|
+
|
|
|
+bool SoftBusCore::fetchPersistedDeviceByPort(const QString &portName,
|
|
|
+ DeviceInfo &device) {
|
|
|
+ if (!m_dbInitialized || !m_db.isValid() || !m_db.isOpen() ||
|
|
|
+ portName.isEmpty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ QSqlQuery query(m_db);
|
|
|
+ query.prepare(QStringLiteral(
|
|
|
+ "SELECT device_id, port_name, name, device_type, address, protocol, "
|
|
|
+ "protocol_detail, properties, status, is_active, last_seen "
|
|
|
+ "FROM devices WHERE port_name = :port_name LIMIT 1"));
|
|
|
+ query.bindValue(QStringLiteral(":port_name"), portName);
|
|
|
+ if (!query.exec()) {
|
|
|
+ qCritical() << "Failed to query persisted device for port" << portName
|
|
|
+ << ":" << query.lastError().text();
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!query.next()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ DeviceInfo info;
|
|
|
+ info.id = query.value(0).toInt();
|
|
|
+ info.portname = query.value(1).toString();
|
|
|
+ info.name = query.value(2).toString();
|
|
|
+ info.type = query.value(3).toString();
|
|
|
+ info.address = query.value(4).toInt();
|
|
|
+ info.protocol = query.value(5).toString();
|
|
|
+ info.protocol_detail = query.value(6).toString();
|
|
|
+
|
|
|
+ const QString propertiesString = query.value(7).toString();
|
|
|
+ if (!propertiesString.isEmpty()) {
|
|
|
+ const QJsonDocument doc =
|
|
|
+ QJsonDocument::fromJson(propertiesString.toUtf8());
|
|
|
+ if (doc.isObject()) {
|
|
|
+ info.properties = doc.object();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ info.status = query.value(8).toString();
|
|
|
+ info.isActive = query.value(9).toBool();
|
|
|
+ info.lastSeen = query.value(10).toDateTime();
|
|
|
+
|
|
|
+ if (info.status.isEmpty()) {
|
|
|
+ info.status =
|
|
|
+ info.isActive ? QStringLiteral("online") : QStringLiteral("offline");
|
|
|
+ }
|
|
|
+
|
|
|
+ device = info;
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
// 更新设备
|
|
|
@@ -151,34 +254,134 @@ void SoftBusCore::updateDevice(const DeviceInfo &device) {
|
|
|
|
|
|
// 如果端口名发生变化,更新映射
|
|
|
DeviceInfo oldDevice = m_devices[device.id];
|
|
|
- if (oldDevice.portname != device.portname) {
|
|
|
+ DeviceInfo updatedDevice = device;
|
|
|
+ if (oldDevice.portname != updatedDevice.portname) {
|
|
|
if (!oldDevice.portname.isEmpty()) {
|
|
|
m_portnameToId.remove(oldDevice.portname);
|
|
|
}
|
|
|
- if (!device.portname.isEmpty()) {
|
|
|
- m_portnameToId[device.portname] = device.id;
|
|
|
+ if (!updatedDevice.portname.isEmpty()) {
|
|
|
+ m_portnameToId[updatedDevice.portname] = updatedDevice.id;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- m_devices[device.id] = device;
|
|
|
+ if (updatedDevice.status.isEmpty()) {
|
|
|
+ updatedDevice.status =
|
|
|
+ oldDevice.status.isEmpty() ? QStringLiteral("online") : oldDevice.status;
|
|
|
+ }
|
|
|
+ if (!updatedDevice.lastSeen.isValid() && oldDevice.lastSeen.isValid()) {
|
|
|
+ updatedDevice.lastSeen = oldDevice.lastSeen;
|
|
|
+ }
|
|
|
+ // 如果调用方未显式修改活跃状态,则沿用旧值
|
|
|
+ if (device.isActive == oldDevice.isActive) {
|
|
|
+ updatedDevice.isActive = oldDevice.isActive;
|
|
|
+ }
|
|
|
+
|
|
|
+ m_devices[device.id] = updatedDevice;
|
|
|
|
|
|
if (m_dbInitialized) {
|
|
|
- upsertDeviceRecord(device);
|
|
|
- if (!device.portname.isEmpty()) {
|
|
|
- if (!ensurePerPortRawTable(device.portname)) {
|
|
|
+ upsertDeviceRecord(updatedDevice, updatedDevice.lastSeen);
|
|
|
+ if (!updatedDevice.portname.isEmpty()) {
|
|
|
+ if (!ensurePerPortRawTable(updatedDevice.portname)) {
|
|
|
qCritical() << "Failed to ensure raw data table for port"
|
|
|
- << device.portname;
|
|
|
+ << updatedDevice.portname;
|
|
|
}
|
|
|
- if (!ensurePerPortTransformedTable(device.portname)) {
|
|
|
+ if (!ensurePerPortTransformedTable(updatedDevice.portname)) {
|
|
|
qCritical() << "Failed to ensure transformed data table for port"
|
|
|
- << device.portname;
|
|
|
+ << updatedDevice.portname;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ emit deviceUpdate(updatedDevice);
|
|
|
+}
|
|
|
+
|
|
|
+void SoftBusCore::markDeviceOffline(int deviceId) {
|
|
|
+ if (deviceId <= 0) {
|
|
|
+ qWarning() << "Invalid device id when marking offline";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const bool tracked = m_devices.contains(deviceId);
|
|
|
+ if (!tracked) {
|
|
|
+ qWarning() << "Device" << deviceId
|
|
|
+ << "not tracked in memory when marking offline";
|
|
|
+ if (m_dbInitialized) {
|
|
|
+ markDeviceInactive(deviceId);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ updateDeviceStatus(deviceId, QStringLiteral("offline"), false,
|
|
|
+ QDateTime::currentDateTimeUtc());
|
|
|
+}
|
|
|
+
|
|
|
+void SoftBusCore::markDeviceOfflineByPort(const QString &portname) {
|
|
|
+ if (portname.isEmpty()) {
|
|
|
+ qWarning() << "Empty port name when marking device offline";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!m_portnameToId.contains(portname)) {
|
|
|
+ qWarning() << "No registered device found for port" << portname
|
|
|
+ << "when marking offline";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const int deviceId = m_portnameToId.value(portname);
|
|
|
+ markDeviceOffline(deviceId);
|
|
|
+}
|
|
|
+
|
|
|
+void SoftBusCore::updateDeviceStatus(int deviceId, const QString &status,
|
|
|
+ bool isActive, const QDateTime &lastSeen) {
|
|
|
+ if (deviceId <= 0) {
|
|
|
+ qWarning() << "Invalid device id when updating status";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!m_devices.contains(deviceId)) {
|
|
|
+ qWarning() << "Device" << deviceId
|
|
|
+ << "not tracked in memory when updating status";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ DeviceInfo device = m_devices.value(deviceId);
|
|
|
+ if (!status.isEmpty()) {
|
|
|
+ device.status = status;
|
|
|
+ }
|
|
|
+ device.isActive = isActive;
|
|
|
+ if (lastSeen.isValid()) {
|
|
|
+ device.lastSeen = lastSeen;
|
|
|
+ } else if (!device.lastSeen.isValid()) {
|
|
|
+ device.lastSeen = QDateTime::currentDateTimeUtc();
|
|
|
+ }
|
|
|
+
|
|
|
+ m_devices[deviceId] = device;
|
|
|
+
|
|
|
+ if (m_dbInitialized) {
|
|
|
+ upsertDeviceRecord(device, device.lastSeen);
|
|
|
+ }
|
|
|
+
|
|
|
emit deviceUpdate(device);
|
|
|
}
|
|
|
|
|
|
+void SoftBusCore::updateDeviceStatusByPort(const QString &portname,
|
|
|
+ const QString &status, bool isActive,
|
|
|
+ const QDateTime &lastSeen) {
|
|
|
+ if (portname.isEmpty()) {
|
|
|
+ qWarning() << "Empty port name when updating device status";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!m_portnameToId.contains(portname)) {
|
|
|
+ qWarning() << "No registered device found for port" << portname
|
|
|
+ << "when updating status";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const int deviceId = m_portnameToId.value(portname);
|
|
|
+ updateDeviceStatus(deviceId, status, isActive, lastSeen);
|
|
|
+}
|
|
|
+
|
|
|
// 注销设备
|
|
|
/*
|
|
|
参数:
|
|
|
@@ -1162,10 +1365,18 @@ void SoftBusCore::upsertDeviceRecord(const DeviceInfo &device,
|
|
|
query.bindValue(QStringLiteral(":protocol_detail"), device.protocol_detail);
|
|
|
query.bindValue(QStringLiteral(":properties"),
|
|
|
toJsonVariant(device.properties));
|
|
|
- query.bindValue(QStringLiteral(":status"), QStringLiteral("online"));
|
|
|
- query.bindValue(QStringLiteral(":is_active"), true);
|
|
|
- if (lastSeen.isValid()) {
|
|
|
- query.bindValue(QStringLiteral(":last_seen"), lastSeen);
|
|
|
+ const QString statusValue = device.status.isEmpty()
|
|
|
+ ? QStringLiteral("online")
|
|
|
+ : device.status;
|
|
|
+ query.bindValue(QStringLiteral(":status"), statusValue);
|
|
|
+ query.bindValue(QStringLiteral(":is_active"), device.isActive);
|
|
|
+
|
|
|
+ QDateTime effectiveLastSeen = lastSeen;
|
|
|
+ if (!effectiveLastSeen.isValid() && device.lastSeen.isValid()) {
|
|
|
+ effectiveLastSeen = device.lastSeen;
|
|
|
+ }
|
|
|
+ if (effectiveLastSeen.isValid()) {
|
|
|
+ query.bindValue(QStringLiteral(":last_seen"), effectiveLastSeen);
|
|
|
} else {
|
|
|
query.bindValue(QStringLiteral(":last_seen"), QVariant(QVariant::DateTime));
|
|
|
}
|
|
|
@@ -1284,3 +1495,4 @@ int SoftBusCore::loadEnvOrDefault(const char *envVar, int defaultValue) const {
|
|
|
const int parsed = value.toInt(&ok);
|
|
|
return ok ? parsed : defaultValue;
|
|
|
}
|
|
|
+
|