1
0
forked from BRT/arc
arc/database/dao/DeviceDAO.cpp
trnsmkot 40cfcff92d - Add buttons for profile and card operations to AccountSettingsWindow with threading integration and UI state management.
- Implement `Dushanbe` automation for `GetProfileInfoScript` and `GetCardInfoScript`.
- Add device validation in `DeviceDAO` and enhance duplicate checks in `NetworkService` during synchronization.
2026-04-06 14:59:00 +07:00

293 lines
9.6 KiB
C++

#include <QSqlQuery>
#include <QSqlError>
#include "DeviceDAO.h"
#include "DatabaseManager.h"
#include "db/DeviceInfo.h"
#include "time/DateUtils.h"
DeviceInfo parseDevice(const QSqlQuery &query) {
DeviceInfo device;
device.id = query.value("id").toString();
device.apiId = query.value("api_id").toString();
device.adbSerial = query.value("adb_serial").toString();
device.status = query.value("status").toString();
device.name = query.value("name").toString();
device.android = query.value("android").toString();
device.screenWidth = query.value("screen_width").toInt();
device.screenHeight = query.value("screen_height").toInt();
device.battery = query.value("battery").toInt();
device.updateTime = DateUtils::fromUtcString(query.value("update_time").toString());
device.image = query.value("image").toByteArray();
return device;
}
QList<DeviceInfo> DeviceDAO::getAllDevices(const bool online) {
QList<DeviceInfo> devices;
QSqlQuery query(DatabaseManager::instance().database());
QString sql = R"(
SELECT id, api_id, adb_serial, status, name, android, screen_width, screen_height, battery, update_time, image
FROM devices
)";
if (online) {
sql += " WHERE status = 'device'";
}
query.prepare(sql);
if (!query.exec()) {
qWarning() << "Ошибка при получении списка устройств:" << query.lastError().text();
return devices;
}
while (query.next()) {
devices.append(parseDevice(query));
}
return devices;
}
QList<QString> DeviceDAO::getOnlineDeviceCodes() {
QList<QString> codes;
QSqlQuery query(DatabaseManager::instance().database());
QString sql = R"(
SELECT id
FROM devices
WHERE image IS NOT NULL AND status = 'device'
)";
query.prepare(sql);
if (!query.exec()) {
qWarning() << "Ошибка при получении списка устройств:" << query.lastError().text();
return {};
}
while (query.next()) {
codes.append(query.value("id").toString());
}
return codes;
}
DeviceInfo DeviceDAO::getDeviceById(const QString &deviceId) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
SELECT id, api_id, adb_serial, status, name, android, screen_width, screen_height, battery, update_time, image
FROM devices
WHERE id = :deviceId
)");
query.bindValue(":deviceId", deviceId);
if (!query.exec()) {
qWarning() << "Ошибка при получении устройства:" << query.lastError().text();
return {};
}
while (query.next()) {
return parseDevice(query);
}
return {};
}
DeviceInfo DeviceDAO::findByAdbSerial(const QString &adbSerial) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
SELECT id, api_id, adb_serial, status, name, android, screen_width, screen_height, battery, update_time, image
FROM devices
WHERE adb_serial = :adb_serial
LIMIT 1
)");
query.bindValue(":adb_serial", adbSerial);
if (!query.exec()) {
qWarning() << "Ошибка при поиске устройства по adb_serial:" << query.lastError().text();
return {};
}
if (query.next()) {
return parseDevice(query);
}
return {};
}
DeviceInfo DeviceDAO::findByName(const QString &name) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
SELECT id, api_id, adb_serial, status, name, android, screen_width, screen_height, battery, update_time, image
FROM devices
WHERE name = :name
LIMIT 1
)");
query.bindValue(":name", name);
if (!query.exec()) {
qWarning() << "Ошибка при поиске устройства по name:" << query.lastError().text();
return {};
}
if (query.next()) {
return parseDevice(query);
}
return {};
}
DeviceInfo DeviceDAO::findUnmatchedDevice() {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare(R"(
SELECT id, api_id, adb_serial, status, name, android, screen_width, screen_height, battery, update_time, image
FROM devices
WHERE api_id IS NOT NULL AND api_id != ''
AND (adb_serial IS NULL OR adb_serial = '')
LIMIT 1
)");
if (!query.exec()) {
qWarning() << "Ошибка при поиске unmatched device:" << query.lastError().text();
return {};
}
if (query.next()) {
return parseDevice(query);
}
return {};
}
bool DeviceDAO::upsertDevice(const DeviceInfo &device) {
if (device.id.isEmpty() || device.name.isEmpty()) {
qWarning() << "[DeviceDAO] upsertDevice skipped: empty id or name";
return false;
}
QSqlQuery query(DatabaseManager::instance().database());
// Проверка: существует ли запись
query.prepare("SELECT COUNT(*) FROM devices WHERE id = :id");
query.bindValue(":id", device.id);
if (!query.exec() || !query.next()) {
qWarning() << "Ошибка при проверке существования записи:" << query.lastError().text();
return false;
}
bool exists = query.value(0).toInt() > 0;
if (exists) {
// Обновление
query.prepare(R"(
UPDATE devices SET
api_id = CASE WHEN :api_id != '' THEN :api_id ELSE api_id END,
adb_serial = CASE WHEN :adb_serial != '' THEN :adb_serial ELSE adb_serial END,
status = :status,
name = :name,
android = :android,
screen_width = :width,
screen_height = :height,
battery = :battery,
update_time = :update_time
WHERE id = :id
)");
} else {
// Вставка
query.prepare(R"(
INSERT INTO devices (
id, api_id, adb_serial, status, name, android, screen_width, screen_height, battery, update_time
) VALUES (
:id, :api_id, :adb_serial, :status, :name, :android, :width, :height, :battery, :update_time
)
)");
}
query.bindValue(":id", device.id);
query.bindValue(":api_id", device.apiId);
query.bindValue(":adb_serial", device.adbSerial);
query.bindValue(":status", device.status);
query.bindValue(":name", device.name);
query.bindValue(":android", device.android);
query.bindValue(":width", device.screenWidth);
query.bindValue(":height", device.screenHeight);
query.bindValue(":battery", device.battery);
query.bindValue(":update_time", DateUtils::toUtcString(device.updateTime));
if (!query.exec()) {
qWarning() << "Ошибка при вставке/обновлении устройства:" << query.lastError().text();
return false;
}
return true;
}
bool DeviceDAO::markDevicesOfflineExcept(const QStringList &onlineDeviceIds) {
QSqlQuery query(DatabaseManager::instance().database());
// Если список ID пуст, помечаем все как offline
if (onlineDeviceIds.isEmpty()) {
if (!query.exec("UPDATE devices SET status = 'offline'")) {
qWarning() << "Ошибка при обновлении устройств на offline:" << query.lastError().text();
return false;
}
return true;
}
// Генерируем плейсхолдеры :id0, :id1, ...
QStringList placeholders;
for (int i = 0; i < onlineDeviceIds.size(); ++i) {
placeholders << QString(":id%1").arg(i);
}
const QString queryString = QString(
"UPDATE devices SET status = 'offline' WHERE id NOT IN (%1)"
).arg(placeholders.join(", "));
query.prepare(queryString);
// Привязываем значения к плейсхолдерам
for (int i = 0; i < onlineDeviceIds.size(); ++i) {
query.bindValue(QString(":id%1").arg(i), onlineDeviceIds[i]);
}
if (!query.exec()) {
qWarning() << "Ошибка при обновлении устройств на offline (исключая online):" << query.lastError().text();
return false;
}
return true;
}
bool DeviceDAO::updateApiId(const QString &deviceId, const QString &apiId) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare("UPDATE devices SET api_id = :api_id WHERE id = :id");
query.bindValue(":api_id", apiId);
query.bindValue(":id", deviceId);
if (!query.exec()) {
qWarning() << "Ошибка при обновлении api_id устройства:" << query.lastError().text();
return false;
}
return true;
}
bool DeviceDAO::deleteDevice(const QString &deviceId) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare("DELETE FROM devices WHERE id = :id");
query.bindValue(":id", deviceId);
if (!query.exec()) {
qWarning() << "Ошибка при удалении устройства:" << query.lastError().text();
return false;
}
return true;
}
bool DeviceDAO::updateImage(const QString &deviceId, const QByteArray &imageData) {
QSqlQuery query(DatabaseManager::instance().database());
query.prepare("UPDATE devices SET image = :image WHERE id = :id");
query.bindValue(":image", imageData);
query.bindValue(":id", deviceId);
if (!query.exec()) {
qWarning() << "Ошибка при обновлении изображения:" << query.lastError().text();
return false;
}
return true;
}