73 lines
4.9 KiB
C++
73 lines
4.9 KiB
C++
#pragma once
|
||
|
||
#include <QMap>
|
||
#include <QSet>
|
||
#include <QString>
|
||
|
||
// Автоматическое поднятие/восстановление беспроводного (Wi-Fi, ADB over TCP/IP)
|
||
// подключения к Android-устройствам. Без участия оператора: USB остаётся основным
|
||
// транспортом, Wi-Fi — горячий резерв, который подхватывается при отключении кабеля.
|
||
//
|
||
// Сохранённые эндпоинты хранятся в реляционной таблице wifi_connections
|
||
// (WifiConnectionDAO), по строке на android_id: ip/port (= endpoint "ip:port") + mac.
|
||
// MAC нужен, чтобы найти устройство после смены IP по DHCP (поиск в ARP-таблице).
|
||
// WifiAdbManager — единственный владелец записи в этой таблице.
|
||
//
|
||
// Все методы статические и блокирующие (дёргают adb/arp/ping через QProcess) —
|
||
// вызывать из фонового потока (DeviceScreener), не из GUI-потока.
|
||
|
||
// Сохранённый беспроводной эндпоинт устройства.
|
||
struct WifiEndpoint {
|
||
QString endpoint; // "ip:port"
|
||
QString mac; // нормализованный MAC (lower-case, разделитель ':'); может быть пустым
|
||
};
|
||
|
||
class WifiAdbManager {
|
||
public:
|
||
// Параметры одного прохода переподключения сохранённых эндпоинтов.
|
||
struct ReconnectOptions {
|
||
QSet<QString> alreadyOnline; // android_id, уже видимые онлайн — пропускаем
|
||
QSet<QString> staleEndpoints; // "ip:port" в статусе offline — disconnect перед connect
|
||
bool macRediscover = false; // при неудаче искать новый IP устройства по MAC
|
||
bool subnetSweep = false; // разрешить ping-скан подсети для прогрева ARP (медленно/шумно)
|
||
};
|
||
|
||
// Сохранённые эндпоинты: android_id → WifiEndpoint.
|
||
static QMap<QString, WifiEndpoint> loadEndpoints();
|
||
|
||
// Пытается `adb connect` по всем сохранённым эндпоинтам (для устройств, которых
|
||
// ещё нет онлайн). Возвращает число успешно подключённых.
|
||
static int reconnectKnown(const ReconnectOptions &opts);
|
||
|
||
// Принудительно пересоздаёт TCP-соединение Wi-Fi-эндпоинта устройства
|
||
// (disconnect → connect). Нужен, когда соединение «залипло» в полумёртвом
|
||
// состоянии: adb держит эндпоинт как "device", но команды к нему виснут (устройство
|
||
// уходит в debounced-offline, при этом в `adb devices` НЕ появляется статус
|
||
// "offline"). Голый connect в этом случае вернул бы "already connected" и не помог.
|
||
// No-op, если у устройства нет сохранённого Wi-Fi-эндпоинта (например, офлайн по USB).
|
||
// Возвращает true, если после переподключения соединение поднялось.
|
||
static bool kickEndpoint(const QString &androidId);
|
||
|
||
// Bootstrap беспроводного эндпоинта для устройства, подключённого по USB:
|
||
// снять MAC → tcpip <port> → определить wlan0 IP → adb connect → сохранить эндпоинт.
|
||
// ВНИМАНИЕ: tcpip рвёт adbd — вызывать только для простаивающего устройства.
|
||
// Возвращает "ip:port" при успехе, пустую строку при неудаче.
|
||
static QString tryBootstrap(const QString &usbSerial, const QString &androidId, int port);
|
||
|
||
// Удаляет сохранённый эндпоинт и делает adb disconnect (best-effort).
|
||
static void forget(const QString &androidId);
|
||
|
||
private:
|
||
static void saveEndpoint(const QString &androidId, const QString &endpoint, const QString &mac);
|
||
|
||
// Поиск текущего IP устройства по известному MAC (после смены IP по DHCP).
|
||
// subnetHintIp — последний известный IP (для определения /24 при ping-скане).
|
||
static QString findIpByMac(const QString &mac, const QString &subnetHintIp, bool allowSweep);
|
||
static QString arpLookupIp(const QString &normalizedMac);
|
||
static void pingSweepSubnet(const QString &subnetHintIp);
|
||
|
||
static QString normalizeMac(const QString &mac);
|
||
static QString ipOf(const QString &endpoint);
|
||
static QString portOf(const QString &endpoint);
|
||
};
|