1
0
forked from BRT/arc
arc/services/device_screener.cpp
slava 1672216bdc Integrate device data management with database access
Added SQLite database support for managing device information and common data. Implemented DAOs for handling device and common data operations, such as inserting/updating devices and tracking the last scan time. Enhanced `DeviceScreener` to read device info, update database records, and take screenshots.
2025-04-17 22:10:11 +07:00

141 lines
4.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "device_screener.h"
#include <QRegularExpression>
#include <QProcess>
#include <QFile>
#include <QThread>
#include <../../database/dao/device_dao.h>
DeviceScreener::DeviceScreener(QObject *parent) : QObject(parent) {
}
DeviceScreener::~DeviceScreener() = default;
void DeviceScreener::start() {
qDebug() << "Worker started in thread:" << QThread::currentThread();
while (m_running) {
QList<QPair<QString, QString>> devices = readAdbDevices();
for (const auto&[id, status] : devices) {
qDebug() << "Id:" << id << ", Status:" << status;
DeviceInfo device;
device.id = id;
device.status = status;
device.updateTime = QDateTime::currentDateTime();
if (status == "device") {
device = readDeviceInfo(id);
takeScreenshot(id);
}
qDebug() << "Update device: " << DeviceDAO::upsertDevice(device);
}
QThread::sleep(5);
}
emit finished();
}
bool DeviceScreener::takeScreenshot(const QString& deviceId) {
QProcess process;
QStringList arguments;
arguments << "-s" << deviceId << "exec-out" << "screencap" << "-p";
process.start("adb", arguments);
if (!process.waitForFinished(5000)) {
qWarning() << "ADB скриншот не завершился для" << deviceId;
return false;
}
const QByteArray imageData = process.readAllStandardOutput();
if (imageData.isEmpty()) {
qWarning() << "Скриншот пустой для " << deviceId;
return false;
}
// Обновляем изображение в БД
if (!DeviceDAO::updateImage(deviceId, imageData)) {
qWarning() << "Не удалось записать изображение в БД для" << deviceId;
return false;
}
qDebug() << "Screenshot saved, device: " << deviceId;
return true;
}
QList<QPair<QString, QString>> DeviceScreener::readAdbDevices() {
QProcess process;
process.start("adb", QStringList() << "devices");
process.waitForFinished();
const QString output = process.readAllStandardOutput();
// qDebug() << "[adb devices output]:\n" << output;
QList<QPair<QString, QString>> devices;
const QStringList lines = output.split('\n');
for (int i = 1; i < lines.size(); ++i) {
QString line = lines.at(i).trimmed();
if (line.isEmpty()) {
continue;
}
/**
* device — устройство готово к использованию.
* offline — устройство подключено, но не может быть использовано.
* unauthorized — устройство не авторизовано для работы с ADB (нужно подтвердить запрос на подключение на самом устройстве).
* recovery — устройство в режиме восстановления.
*/
// Разделяем строку на id и type по табуляции
if (QStringList parts = line.split('\t'); parts.size() == 2) {
const QString& id = parts.at(0);
const QString& status = parts.at(1);
devices.append(qMakePair(id, status));
}
}
return devices;
}
static const QRegularExpression screenRegex(R"(Physical size: (\d+)x(\d+))");
static const QRegularExpression batteryRegex(R"(level:\s*(\d+))");
DeviceInfo DeviceScreener::readDeviceInfo(const QString& deviceId) {
DeviceInfo info;
info.id = deviceId;
info.screenWidth = 0;
info.screenHeight = 0;
info.battery = 0;
auto runAdbCommand = [&](const QStringList& args) -> QString {
QProcess process;
process.start("adb", QStringList{"-s", deviceId} + args);
process.waitForFinished();
return QString::fromUtf8(process.readAllStandardOutput()).trimmed();
};
info.name = runAdbCommand({"shell", "getprop", "ro.product.model"});
info.android = runAdbCommand({"shell", "getprop", "ro.build.version.release"});
// Размер экрана
const QString screenOutput = runAdbCommand({"shell", "wm", "size"});
QRegularExpressionMatch match = screenRegex.match(screenOutput);
if (match.hasMatch()) {
info.screenWidth = match.captured(1).toInt();
info.screenHeight = match.captured(2).toInt();
}
// Уровень батареи
const QString batteryOutput = runAdbCommand({"shell", "dumpsys", "battery"});
match = batteryRegex.match(batteryOutput);
if (match.hasMatch()) {
info.battery = match.captured(1).toInt();
}
info.updateTime = QDateTime::currentDateTime();
return info;
}
void DeviceScreener::stop() {
m_running = false;
}