#!/usr/bin/env node const { execSync } = require('child_process') const path = require('path') const fs = require('fs') // 根目录 = config 文件所在目录的上级(config 在 <根>/configs/config.js) const configPath = process.env.STATIC_ROOT ? path.join(path.dirname(process.env.STATIC_ROOT), 'configs', 'config.js') : path.join(__dirname, '..', '..', 'configs', 'config.js') const PROJECT_ROOT = path.dirname(path.dirname(path.resolve(configPath))) function getAdbPath() { if (!fs.existsSync(configPath)) return path.join(PROJECT_ROOT, 'lib', 'scrcpy-adb', process.platform === 'win32' ? 'adb.exe' : 'adb') const config = require(configPath) const p = config.adbPath?.path return p ? (path.isAbsolute(p) ? p : path.resolve(PROJECT_ROOT, p)) : path.join(PROJECT_ROOT, 'lib', 'scrcpy-adb', process.platform === 'win32' ? 'adb.exe' : 'adb') } function getConnectedDeviceIds(adbPath) { const out = execSync(`"${adbPath}" devices`, { encoding: 'utf-8' }) return out .split('\n') .filter((line) => line.trim() && !line.startsWith('List') && line.includes('\tdevice')) .map((line) => line.trim().split('\t')[0]) .filter((id) => id && !id.includes(':')) } function parseInetFromOutput(out, skipLoopback = false) { const re = /inet\s+(\d+\.\d+\.\d+\.\d+)/g const ips = [] let m while ((m = re.exec(out || '')) !== null) ips.push(m[1]) if (ips.length === 0) return null if (skipLoopback) { const nonLoop = ips.find((ip) => ip !== '127.0.0.1') return nonLoop || null } return ips[0] } function adbShellCmd(adbPath, deviceId, shellCmd) { const id = deviceId.indexOf(' ') >= 0 ? `"${deviceId}"` : deviceId return `"${adbPath}" -s ${id} shell ${shellCmd}` } function getDeviceIp(adbPath, deviceId) { const run = (shellCmd) => { try { return execSync(adbShellCmd(adbPath, deviceId, shellCmd), { encoding: 'utf-8' }) } catch (e) { return '' } } let out = run('ip -4 addr show wlan0') let ip = parseInetFromOutput(out) if (ip) return ip out = run('ip -4 addr show eth0') ip = parseInetFromOutput(out) if (ip) return ip out = run('ip route get 1.1.1.1') let m = out.match(/\bsrc\s+(\d+\.\d+\.\d+\.\d+)\b/) if (m) return m[1] m = out.match(/\bfrom\s+(\d+\.\d+\.\d+\.\d+)\b/) if (m) return m[1] for (const prop of ['dhcp.wlan0.ipaddress', 'net.wlan0.ipaddress', 'dhcp.eth0.ipaddress']) { out = run('getprop ' + prop) ip = (out || '').trim() if (/^\d+\.\d+\.\d+\.\d+$/.test(ip)) return ip } out = run('ip -4 addr show') return parseInetFromOutput(out, true) } function run() { const adbPath = getAdbPath() const devices = getConnectedDeviceIds(adbPath) if (devices.length === 0) { process.stderr.write('No devices found. Please connect a device via USB.\n') process.exit(1) } const deviceId = devices[0] const ip = getDeviceIp(adbPath, deviceId) if (ip) { process.stdout.write(ip + '\n') process.exit(0) } process.stderr.write('Could not get device IP. Check WiFi on device.\n') process.exit(1) } run()