enable-wirless-connect.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. #!/usr/bin/env node
  2. const { execSync } = require('child_process')
  3. const path = require('path')
  4. // 根目录 = 与根目录 config.js 同目录
  5. const configPath = process.env.STATIC_ROOT
  6. ? path.join(path.dirname(process.env.STATIC_ROOT), 'config.js')
  7. : path.join(__dirname, '..', 'config.js')
  8. const PROJECT_ROOT = path.dirname(path.resolve(configPath))
  9. const TCPIP_PORT = 5555
  10. /** 从配置解析并返回 ADB 可执行文件路径 */
  11. function getAdbPath() {
  12. const fs = require('fs')
  13. if (!fs.existsSync(configPath)) return path.join(PROJECT_ROOT, 'lib', 'scrcpy-adb', process.platform === 'win32' ? 'adb.exe' : 'adb')
  14. const config = require(configPath)
  15. const p = config.adbPath?.path
  16. return p ? (path.isAbsolute(p) ? p : path.resolve(PROJECT_ROOT, p)) : path.join(PROJECT_ROOT, 'lib', 'scrcpy-adb', process.platform === 'win32' ? 'adb.exe' : 'adb')
  17. }
  18. /** 返回当前通过 USB 连接的设备 ID 列表(仅 status 为 device 且非 IP:port,排除无线设备) */
  19. function getConnectedDeviceIds(adbPath) {
  20. const out = execSync(`"${adbPath}" devices`, { encoding: 'utf-8' })
  21. return out
  22. .split('\n')
  23. .filter((line) => line.trim() && !line.startsWith('List') && line.includes('\tdevice'))
  24. .map((line) => line.trim().split('\t')[0])
  25. .filter((id) => id && !id.includes(':'))
  26. }
  27. /** 操作一:在 USB 设备上开启无线调试(settings adb_wifi_enabled 1) */
  28. function enableWirelessSetting(adbPath, deviceId) {
  29. execSync(`"${adbPath}" -s ${deviceId} shell settings put global adb_wifi_enabled 1`, { encoding: 'utf-8' })
  30. }
  31. /** 操作二:在 USB 设备上激活 5555 端口(tcpip),用于无线连接 */
  32. function enableTcpipPort(adbPath, deviceId, port) {
  33. return execSync(`"${adbPath}" -s ${deviceId} tcpip ${port}`, { encoding: 'utf-8' }).trim()
  34. }
  35. /** 从 adb shell 输出中匹配 inet 后的 IPv4(支持 inet 192.168.1.1/24 格式),可排除回环 */
  36. function parseInetFromOutput(out, skipLoopback = false) {
  37. const re = /inet\s+(\d+\.\d+\.\d+\.\d+)/g
  38. const ips = []
  39. let m
  40. while ((m = re.exec(out || '')) !== null) ips.push(m[1])
  41. if (ips.length === 0) return null
  42. if (skipLoopback) {
  43. const nonLoop = ips.find((ip) => ip !== '127.0.0.1')
  44. return nonLoop || null
  45. }
  46. return ips[0]
  47. }
  48. /** 安全拼 adb -s 参数(deviceId 含空格时需引号) */
  49. function adbShellCmd(adbPath, deviceId, shellCmd) {
  50. const id = deviceId.indexOf(' ') >= 0 ? `"${deviceId}"` : deviceId
  51. return `"${adbPath}" -s ${id} shell ${shellCmd}`
  52. }
  53. /** 获取设备当前 WiFi IP:多接口 + 多命令兼容不同机型 */
  54. function getDeviceIp(adbPath, deviceId) {
  55. const run = (shellCmd) => {
  56. try {
  57. return execSync(adbShellCmd(adbPath, deviceId, shellCmd), { encoding: 'utf-8' })
  58. } catch (e) {
  59. return ''
  60. }
  61. }
  62. // 1) wlan0 inet(最常见)
  63. let out = run('ip -4 addr show wlan0')
  64. let ip = parseInetFromOutput(out)
  65. if (ip) return ip
  66. // 2) eth0(部分机型/平板)
  67. out = run('ip -4 addr show eth0')
  68. ip = parseInetFromOutput(out)
  69. if (ip) return ip
  70. // 3) ip route get:src 或 from
  71. out = run('ip route get 1.1.1.1')
  72. let m = out.match(/\bsrc\s+(\d+\.\d+\.\d+\.\d+)\b/)
  73. if (m) return m[1]
  74. m = out.match(/\bfrom\s+(\d+\.\d+\.\d+\.\d+)\b/)
  75. if (m) return m[1]
  76. // 4) getprop
  77. for (const prop of ['dhcp.wlan0.ipaddress', 'net.wlan0.ipaddress', 'dhcp.eth0.ipaddress']) {
  78. out = run('getprop ' + prop)
  79. ip = (out || '').trim()
  80. if (/^\d+\.\d+\.\d+\.\d+$/.test(ip)) return ip
  81. }
  82. // 5) ip -4 addr show 全量,取第一个非回环 IP(避免 lo 的 127.0.0.1)
  83. out = run('ip -4 addr show')
  84. return parseInetFromOutput(out, true)
  85. }
  86. /** 主流程:取 USB 设备,先取 IP(与 getip.js 一致,此时 USB 稳定),再开无线与 tcpip,最后输出 */
  87. function run() {
  88. const adbPath = getAdbPath()
  89. const devices = getConnectedDeviceIds(adbPath)
  90. if (devices.length === 0) {
  91. process.stderr.write('No devices found. Please connect a device via USB.\n')
  92. process.exit(1)
  93. }
  94. const deviceId = devices[0]
  95. // 先取 IP(在 tcpip 之前,USB 稳定时取,与 bat-tool/getip 行为一致)
  96. const ip = getDeviceIp(adbPath, deviceId)
  97. enableWirelessSetting(adbPath, deviceId)
  98. const tcpipOut = enableTcpipPort(adbPath, deviceId, TCPIP_PORT)
  99. process.stdout.write(tcpipOut + '\n')
  100. if (ip) {
  101. process.stdout.write('DEVICE_IP:' + ip + '\n')
  102. }
  103. process.exit(0)
  104. }
  105. run()