adb异常处理优化

This commit is contained in:
Elaina 2024-12-02 23:09:44 +08:00
parent b8b6285ff1
commit db94be4e4c
3 changed files with 53 additions and 60 deletions

View file

@ -4,7 +4,3 @@ class SimulatorError(Exception):
class GameError(Exception): class GameError(Exception):
pass pass
class ADBError(Exception):
pass

View file

@ -10,12 +10,18 @@ from adbutils import AdbClient, AdbDevice
from mower import __system__ from mower import __system__
from mower.utils import config from mower.utils import config
from mower.utils.csleep import MowerExit, csleep from mower.utils.csleep import MowerExit, csleep
from mower.utils.device.exception import SimulatorError
from mower.utils.device.simulator import restart_simulator
from mower.utils.image import bytes2img from mower.utils.image import bytes2img
from mower.utils.log import logger from mower.utils.log import logger
from .utils import subprocess_run from .utils import subprocess_run
class ADBServerError(Exception):
pass
def retry_adb(func): def retry_adb(func):
@wraps(func) @wraps(func)
def retry_wrapper(self, *args, **kwargs): def retry_wrapper(self, *args, **kwargs):
@ -24,9 +30,15 @@ def retry_adb(func):
return func(self, *args, **kwargs) return func(self, *args, **kwargs)
except MowerExit: except MowerExit:
raise raise
except ADBServerError as e:
logger.exception(e)
self.restart_server()
except SimulatorError as e:
logger.exception(e)
restart_simulator()
self._adb_device = None
except Exception as e: except Exception as e:
logger.exception(e) logger.exception(e)
self.adb_reconnect()
return retry_wrapper return retry_wrapper
@ -38,7 +50,6 @@ class ADB:
self._adb_device = None # 用于存储 AdbDevice 实例 self._adb_device = None # 用于存储 AdbDevice 实例
self.check_server_status() self.check_server_status()
@retry_adb
def get_adb_client(self) -> AdbClient: def get_adb_client(self) -> AdbClient:
""" """
Returns an AdbClient instance. Returns an AdbClient instance.
@ -47,9 +58,9 @@ class ADB:
if self._adb_client is None: if self._adb_client is None:
try: try:
self.check_server_status() self.check_server_status()
self._adb_client = AdbClient("127.0.0.1", config.adb_server_port, 5) self._adb_client = AdbClient("127.0.0.1", config.adb_server_port, 10)
except Exception as e: except Exception as e:
raise e raise ADBServerError(e)
return self._adb_client return self._adb_client
@retry_adb @retry_adb
@ -60,9 +71,20 @@ class ADB:
""" """
if self._adb_device is None: if self._adb_device is None:
adb_client = self.get_adb_client() adb_client = self.get_adb_client()
if len(adb_client.list()) == 0: if len(devices := adb_client.list()) == 0:
adb_client.connect(config.conf.adb, 5) try:
adb_client.connect(config.conf.adb, 10)
except Exception as e:
raise SimulatorError(e)
elif devices[0].state == "offline":
try:
adb_client.disconnect(config.conf.adb)
adb_client.connect(config.conf.adb, 10)
except Exception as e:
raise SimulatorError(e)
self._adb_device = AdbDevice(adb_client, config.conf.adb) self._adb_device = AdbDevice(adb_client, config.conf.adb)
self.check_device_status()
return self._adb_device return self._adb_device
@property @property
@ -92,9 +114,13 @@ class ADB:
Returns: Returns:
str: str:
""" """
try:
cmd = list(map(str, cmd)) cmd = list(map(str, cmd))
cmd = [self.adb_bin, "-P", str(config.adb_server_port)] + cmd cmd = [self.adb_bin, "-P", str(config.adb_server_port)] + cmd
return subprocess_run(cmd, timeout=timeout) return subprocess_run(cmd, timeout=timeout)
except Exception as e:
logger.exception(e)
self.check_device_status()
def check_server_status(self) -> str: def check_server_status(self) -> str:
"""Use `adb devices` as `adb start-server`, result is actually useless""" """Use `adb devices` as `adb start-server`, result is actually useless"""
@ -106,21 +132,11 @@ class ADB:
self.adb_command(["kill-server"]) self.adb_command(["kill-server"])
self._adb_client = self._adb_device = None self._adb_client = self._adb_device = None
def restart_server(self) -> None:
self.kill_server()
self.check_server_status()
def adb_disconnect(self): def adb_disconnect(self):
self.adb_client.disconnect(config.conf.adb, raise_error=False) self.adb_client.disconnect(config.conf.adb, raise_error=False)
self._adb_device = None self._adb_device = None
def adb_reconnect(self): @retry_adb
status = self.check_server_status()
if "offline" in status:
self.adb_disconnect()
else:
self.restart_server()
def adb_shell( def adb_shell(
self, cmd, stream=False, timeout=20, encoding: str | None = "utf-8", rstrip=True self, cmd, stream=False, timeout=20, encoding: str | None = "utf-8", rstrip=True
): ):
@ -136,17 +152,28 @@ class ADB:
str if stream=False str if stream=False
socket if stream=True socket if stream=True
""" """
try:
if not isinstance(cmd, str): if not isinstance(cmd, str):
cmd = list(map(str, cmd)) cmd = list(map(str, cmd))
return self.adb.shell( return self.adb.shell(
cmd, stream=stream, timeout=timeout, encoding=encoding, rstrip=rstrip cmd, stream=stream, timeout=timeout, encoding=encoding, rstrip=rstrip
) )
except Exception as e:
logger.debug(cmd)
logger.exception(e)
self.check_device_status()
def adb_push(self, file_path: str, target: str): def adb_push(self, file_path: str, target: str):
"""push file into device with adb_bin""" """push file into device with adb_bin"""
self.adb.push(file_path, target) self.adb.push(file_path, target)
def check_device_status(self):
try:
self.adb.shell("echo test")
except Exception:
raise SimulatorError("设备未连接")
def process( def process(
self, path: str, args: list[str] = [], stderr: int = subprocess.DEVNULL self, path: str, args: list[str] = [], stderr: int = subprocess.DEVNULL
) -> subprocess.Popen: ) -> subprocess.Popen:
@ -259,6 +286,7 @@ class ADB:
class DIY: class DIY:
@retry_adb
def capture_display(): def capture_display():
command = config.conf.custom_screenshot.command command = config.conf.custom_screenshot.command
data = subprocess.check_output( data = subprocess.check_output(

View file

@ -1,6 +1,5 @@
from __future__ import annotations from __future__ import annotations
import functools
import socket import socket
import threading import threading
import time import time
@ -13,7 +12,6 @@ from adbutils import AdbConnection, Network
from mower.utils import config from mower.utils import config
from mower.utils import typealias as tp from mower.utils import typealias as tp
from mower.utils.csleep import MowerExit from mower.utils.csleep import MowerExit
from mower.utils.device.exception import ADBError
from mower.utils.device.method.adb import ADB from mower.utils.device.method.adb import ADB
from mower.utils.device.method.adb.const import KeyCode from mower.utils.device.method.adb.const import KeyCode
from mower.utils.log import logger from mower.utils.log import logger
@ -192,35 +190,6 @@ class Client:
self.control_socket.close() self.control_socket.close()
self.control_socket = None self.control_socket = None
def stable(f):
@functools.wraps(f)
def inner(self: Client, *args, **kwargs):
try_count = 0
while try_count < 3:
try:
return f(self, *args, **kwargs)
except (
ConnectionResetError,
BrokenPipeError,
ConnectionAbortedError,
) as e:
logger.debug_exception(e)
self.stop()
time.sleep(1)
self.start()
try_count += 1
except Exception as e:
logger.exception(e)
self.stop()
time.sleep(1)
self.start()
try_count += 1
else:
raise ADBError("Failed to start scrcpy-server.")
return inner
@retry_scrcpy @retry_scrcpy
def tap(self, x: int, y: int) -> None: def tap(self, x: int, y: int) -> None:
self.control.tap(x, y) self.control.tap(x, y)