AI_UIAutomation/utils/common/network.helper.ts

122 lines
5.0 KiB
TypeScript
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.

/**
* 双协议网络前置:按 PROTO 切手机蓝牙/WiFi用于必测项控制用例的 BLE/WiFi 两种模式。
*
* - ble 模式: 开蓝牙、关 WiFi → app 走 BLE 直连
* - wifi 模式: 关蓝牙、开 WiFi → app 走 WiFi/云
*
* 平台能力(已在三星真机实测):
* - Android WiFi : adb `svc wifi enable/disable` 可行(dumpsys 实测真关/开)
* - Android 蓝牙 : adb `svc bluetooth` 被新系统禁用(exit 137)、`cmd bluetooth_manager` 无实现、
* `settings put bluetooth_on` 不动 radio → 改为 `am start 蓝牙设置` + 点 switch_widget(实测可切 ON↔BLE_ON)
* - iOS : 无公开 API,走系统设置(com.apple.Preferences)UI;locator 需 iOS 真机校准
*/
import { execSync } from 'child_process';
import { DeviceDriver } from '../../drivers/types';
import { APP_CONFIG } from '../../config/app.config';
import { sleep } from './element.helper';
function adbShell(cmd: string): string {
return execSync(`adb shell ${cmd}`, { encoding: 'utf-8', timeout: 20000 });
}
// ---------- Android(纯 adb,已实测) ----------
async function androidSetWifi(on: boolean): Promise<void> {
adbShell(`svc wifi ${on ? 'enable' : 'disable'}`);
await sleep(2000);
}
async function androidSetBluetooth(on: boolean): Promise<void> {
adbShell('am start -a android.settings.BLUETOOTH_SETTINGS');
await sleep(2500);
adbShell('uiautomator dump /sdcard/ui.xml');
const xml = adbShell('cat /sdcard/ui.xml');
// 三星实测节点: resource-id="com.android.settings:id/switch_widget" class=Switch checked=.. bounds=[x1,y1][x2,y2]
const m = xml.match(/switch_widget"[^>]*?checked="(true|false)"[^>]*?bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
if (!m) {
console.warn('[network] 未找到蓝牙开关 switch_widget,跳过(请真机校准 locator)');
return;
}
const isOn = m[1] === 'true';
if (isOn !== on) {
const cx = Math.round((Number(m[2]) + Number(m[4])) / 2);
const cy = Math.round((Number(m[3]) + Number(m[5])) / 2);
adbShell(`input tap ${cx} ${cy}`);
await sleep(3000);
}
}
// ---------- iOS(系统设置 UI,locator 已在 iPhone/iOS26.5 实测) ----------
async function iosSetBluetooth(driver: DeviceDriver, on: boolean): Promise<void> {
await driver.activateApp('com.apple.Preferences');
await sleep(2000);
// 进入蓝牙二级页:设置首页 cell(文案本地化,中文"蓝牙"/英文"Bluetooth")
const entry =
(await driver.findElementRaw('accessibility id', '蓝牙').catch(() => null)) ||
(await driver.findElementRaw('accessibility id', 'Bluetooth').catch(() => null));
if (entry) {
await driver.tapElement(entry);
await sleep(2000);
}
// 蓝牙开关:name="BLUETOOTH"(与语言无关),value "1"=开 / "0"=关
const sw = await driver.findElementRaw('accessibility id', 'BLUETOOTH').catch(() => null);
if (!sw) {
console.warn('[network] iOS 未找到蓝牙开关(accessibility id=BLUETOOTH),跳过');
return;
}
const val = await driver.getElementAttribute(sw, 'value').catch(() => '');
const isOn = val === '1' || val === 'true';
if (isOn !== on) {
await driver.tapElement(sw);
await sleep(2500);
}
}
// iOS WiFi(无 adb,走系统设置;locator 已在 iOS26.5 实测:开关 name="无线局域网" value 1/0)
async function iosSetWifi(driver: DeviceDriver, on: boolean): Promise<void> {
await driver.activateApp('com.apple.Preferences');
await sleep(2000);
// 进入 WiFi 页:cell 文案本地化(中文"无线局域网" / 英文"Wi-Fi"/"WLAN")
const entry =
(await driver.findElementRaw('accessibility id', '无线局域网').catch(() => null)) ||
(await driver.findElementRaw('accessibility id', 'Wi-Fi').catch(() => null)) ||
(await driver.findElementRaw('accessibility id', 'WLAN').catch(() => null));
if (entry) {
await driver.tapElement(entry);
await sleep(2000);
}
// WiFi 开关:name="无线局域网"(本地化), value "1"=开 / "0"=关
const sw =
(await driver.findElementRaw('accessibility id', '无线局域网').catch(() => null)) ||
(await driver.findElementRaw('accessibility id', 'Wi-Fi').catch(() => null));
if (!sw) {
console.warn('[network] iOS 未找到 WiFi 开关,跳过');
return;
}
const val = await driver.getElementAttribute(sw, 'value').catch(() => '');
const isOn = val === '1' || val === 'true';
if (isOn !== on) {
await driver.tapElement(sw);
await sleep(2500);
}
}
/**
* 按协议设置手机网络状态,然后切回 SwitchBot app。
* 无人值守可用(Android 全自动;iOS 走设置 UI)。
*/
export async function applyProtoNetwork(driver: DeviceDriver, proto: 'ble' | 'wifi'): Promise<void> {
const wantBluetooth = proto === 'ble';
const wantWifi = proto === 'wifi';
if (driver.platform === 'android') {
await androidSetWifi(wantWifi);
await androidSetBluetooth(wantBluetooth);
await driver.activateApp(APP_CONFIG.android.appPackage);
} else {
await iosSetWifi(driver, wantWifi);
await iosSetBluetooth(driver, wantBluetooth);
await driver.activateApp(APP_CONFIG.ios.bundleId);
}
await sleep(2000);
}