105 lines
2.4 KiB
Python
105 lines
2.4 KiB
Python
import subprocess
|
|
import os
|
|
from abc import ABC, abstractmethod
|
|
from enum import IntEnum
|
|
|
|
|
|
class DeviceStatus(IntEnum):
|
|
ONLINE = 0
|
|
"""设备在线"""
|
|
OFFLINE = 1
|
|
"""设备离线"""
|
|
STARTING = 2
|
|
"""设备开启中"""
|
|
CLOSEING = 3
|
|
"""设备关闭中"""
|
|
ERROR = 4
|
|
"""错误"""
|
|
NOT_FOUND = 5
|
|
"""未找到设备"""
|
|
UNKNOWN = 10
|
|
|
|
|
|
class ExeRunner:
|
|
def __init__(self, exe_path, encoding) -> None:
|
|
"""
|
|
指定 exe 路径
|
|
!请传入绝对路径,使用/分隔路径
|
|
"""
|
|
if not os.path.isfile(exe_path):
|
|
raise FileNotFoundError(f"找不到文件: {exe_path}")
|
|
self.exe_path = os.path.abspath(exe_path) # 转为绝对路径
|
|
self.encoding = encoding
|
|
|
|
def run(self, *args) -> subprocess.CompletedProcess[str]:
|
|
"""
|
|
执行命令,返回结果
|
|
"""
|
|
cmd = [self.exe_path] + list(args)
|
|
print(f"执行: {' '.join(cmd)}")
|
|
|
|
result = subprocess.run(
|
|
cmd,
|
|
capture_output=True,
|
|
text=True,
|
|
encoding=self.encoding,
|
|
errors="replace",
|
|
)
|
|
return result
|
|
|
|
|
|
class BaseDevice(ABC):
|
|
@abstractmethod
|
|
async def start(self, idx: str, package_name: str) -> tuple[bool, int, dict]:
|
|
"""
|
|
启动设备
|
|
返回值: (是否成功, 状态码, 启动信息)
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def close(self, idx: str) -> tuple[bool, int]:
|
|
"""
|
|
关闭设备或服务
|
|
返回值: (是否成功, 状态码)
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def get_status(self, idx: str) -> int:
|
|
"""
|
|
获取指定模拟器当前状态
|
|
返回值: 状态码
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def hide_device(self, idx: str) -> tuple[bool, int]:
|
|
"""
|
|
隐藏设备窗口
|
|
返回值: (是否成功, 状态码)
|
|
"""
|
|
...
|
|
|
|
@abstractmethod
|
|
async def show_device(self, idx: str) -> tuple[bool, int]:
|
|
"""
|
|
显示设备窗口
|
|
返回值: (是否成功, 状态码)
|
|
"""
|
|
...
|
|
|
|
async def get_all_info(self) -> dict[str, dict[str, str]]:
|
|
"""
|
|
获取设备信息
|
|
返回值: 设备字典
|
|
结构示例:
|
|
{
|
|
"0":{
|
|
"title": 模拟器名字,
|
|
"status": "1"
|
|
}
|
|
}
|
|
"""
|
|
...
|