mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-22 16:40:28 +00:00
Add: aScreenCap support
- Optimize adb command call
This commit is contained in:
parent
1e55c25f49
commit
97b85160cd
BIN
ascreencap/arm64-v8a/ascreencap
Normal file
BIN
ascreencap/arm64-v8a/ascreencap
Normal file
Binary file not shown.
BIN
ascreencap/armeabi-v7a/ascreencap
Normal file
BIN
ascreencap/armeabi-v7a/ascreencap
Normal file
Binary file not shown.
BIN
ascreencap/x86/ascreencap
Normal file
BIN
ascreencap/x86/ascreencap
Normal file
Binary file not shown.
BIN
ascreencap/x86_64/ascreencap
Normal file
BIN
ascreencap/x86_64/ascreencap
Normal file
Binary file not shown.
@ -96,8 +96,8 @@ serial = 127.0.0.1:62001
|
||||
package_name = com.bilibili.azurlane
|
||||
enable_error_log_and_screenshot_save = yes
|
||||
enable_perspective_error_image_save = no
|
||||
use_adb_screenshot = yes
|
||||
use_adb_control = no
|
||||
device_screenshot_method = aScreenCap
|
||||
device_control_method = uiautomator2
|
||||
combat_screenshot_interval = 1.
|
||||
|
||||
[Daily]
|
||||
|
@ -20,6 +20,7 @@ class EmulatorChecker(Device):
|
||||
self._screenshot_uiautomator2()
|
||||
# self._click_adb(1270, 360)
|
||||
# self._click_uiautomator2(1270, 360)
|
||||
# self._screenshot_ascreencap()
|
||||
|
||||
cost = time.time() - t0
|
||||
record.append(cost)
|
||||
@ -27,13 +28,18 @@ class EmulatorChecker(Device):
|
||||
print(count, np.round(np.mean(record), 3), np.round(np.std(record), 3))
|
||||
|
||||
|
||||
class Config:
|
||||
SERIAL = '127.0.0.1:62001'
|
||||
class Config(AzurLaneConfig):
|
||||
SERIAL = '127.0.0.1:5555'
|
||||
# SERIAL = '127.0.0.1:62001'
|
||||
# SERIAL = '127.0.0.1:7555'
|
||||
# SERIAL = 'emulator-5554'
|
||||
# SERIAL = '127.0.0.1:21503'
|
||||
|
||||
USE_ADB_SCREENSHOT = False
|
||||
# Speed: aScreenCap >> uiautomator2 > ADB
|
||||
DEVICE_SCREENSHOT_METHOD = 'aScreenCap' # ADB, uiautomator2, aScreenCap
|
||||
|
||||
# Speed: uiautomator2 >> ADB
|
||||
DEVICE_CONTROL_METHOD = 'uiautomator2' # ADB, uiautomator2
|
||||
|
||||
|
||||
az = EmulatorChecker(AzurLaneConfig('template').merge(Config()))
|
||||
|
@ -280,8 +280,8 @@ def main(ini_name=''):
|
||||
debug.add_argument('--保存透视识别出错的图像', default=default('--保存透视识别出错的图像'), choices=['是', '否'])
|
||||
|
||||
adb = emulator_parser.add_argument_group('ADB设置', '')
|
||||
adb.add_argument('--使用ADB截图', default=default('--使用ADB截图'), choices=['是', '否'], help='建议开启, 能减少CPU占用')
|
||||
adb.add_argument('--使用ADB点击', default=default('--使用ADB点击'), choices=['是', '否'], help='建议关闭, 能加快点击速度')
|
||||
adb.add_argument('--设备截图方案', default=default('--设备截图方案'), choices=['aScreenCap', 'uiautomator2', 'ADB'], help='速度: aScreenCap >> uiautomator2 > ADB')
|
||||
adb.add_argument('--设备控制方案', default=default('--设备控制方案'), choices=['uiautomator2', 'ADB'], help='速度: uiautomator2 >> ADB')
|
||||
adb.add_argument('--战斗中截图间隔', default=default('--战斗中截图间隔'), help='战斗中放慢截图速度, 降低CPU使用')
|
||||
|
||||
# ==========每日任务==========
|
||||
|
@ -278,8 +278,8 @@ def main(ini_name=''):
|
||||
debug.add_argument('--enable_perspective_error_image_save', default=default('--enable_perspective_error_image_save'), choices=['yes', 'no'])
|
||||
|
||||
adb = emulator_parser.add_argument_group('ADB settings', '')
|
||||
adb.add_argument('--use_adb_screenshot', default=default('--use_adb_screenshot'), choices=['yes', 'no'], help='It is recommended to enable it to reduce CPU usage')
|
||||
adb.add_argument('--use_adb_control', default=default('--use_adb_control'), choices=['yes', 'no'], help='Recommended off, can speed up the click speed')
|
||||
adb.add_argument('--device_screenshot_method', default=default('--device_screenshot_method'), choices=['aScreenCap', 'uiautomator2', 'ADB'], help='Speed: aScreenCap >> uiautomator2 > ADB')
|
||||
adb.add_argument('--device_control_method', default=default('--device_control_method'), choices=['uiautomator2', 'ADB'], help='Speed: uiautomator2 >> ADB')
|
||||
adb.add_argument('--combat_screenshot_interval', default=default('--combat_screenshot_interval'), help='Slow down the screenshot speed during battle and reduce CPU')
|
||||
|
||||
# ==========每日任务==========
|
||||
|
@ -273,8 +273,8 @@ def main(ini_name=''):
|
||||
debug.add_argument('--enable_perspective_error_image_save', default=default('--enable_perspective_error_image_save'), choices=['yes', 'no'])
|
||||
|
||||
adb = emulator_parser.add_argument_group('ADB settings', '')
|
||||
adb.add_argument('--use_adb_screenshot', default=default('--use_adb_screenshot'), choices=['yes', 'no'], help='It is recommended to enable it to reduce CPU usage')
|
||||
adb.add_argument('--use_adb_control', default=default('--use_adb_control'), choices=['yes', 'no'], help='Suggest to close, can speed up the click speed')
|
||||
adb.add_argument('--device_screenshot_method', default=default('--device_screenshot_method'), choices=['aScreenCap', 'uiautomator2', 'ADB'], help='Speed: aScreenCap >> uiautomator2 > ADB')
|
||||
adb.add_argument('--device_control_method', default=default('--device_control_method'), choices=['uiautomator2', 'ADB'], help='Speed: uiautomator2 >> ADB')
|
||||
adb.add_argument('--combat_screenshot_interval', default=default('--combat_screenshot_interval'), help='Slow down the screenshot speed during battle and reduce CPU')
|
||||
|
||||
# ==========每日任务==========
|
||||
|
@ -152,8 +152,13 @@ class AzurLaneConfig:
|
||||
SERIAL = ''
|
||||
PACKAGE_NAME = ''
|
||||
COMMAND = ''
|
||||
USE_ADB_SCREENSHOT = True
|
||||
USE_ADB_CONTROL = False
|
||||
ASCREENCAP_FILEPATH = '/data/local/tmp/ascreencap'
|
||||
# Speed: aScreenCap >> uiautomator2 > ADB
|
||||
DEVICE_SCREENSHOT_METHOD = 'aScreenCap' # ADB, uiautomator2, aScreenCap
|
||||
# Speed: uiautomator2 >> ADB
|
||||
DEVICE_CONTROL_METHOD = 'uiautomator2' # ADB, uiautomator2
|
||||
# USE_ADB_SCREENSHOT = True
|
||||
# USE_ADB_CONTROL = False
|
||||
SCREEN_SHOT_SAVE_FOLDER_BASE = './screenshot'
|
||||
SCREEN_SHOT_SAVE_FOLDER = ''
|
||||
SCREEN_SHOT_SAVE_INTERVAL = 5 # Seconds between two save. Saves in the interval will be dropped.
|
||||
@ -405,8 +410,8 @@ class AzurLaneConfig:
|
||||
self.PACKAGE_NAME = option['package_name'].strip()
|
||||
self.ENABLE_ERROR_LOG_AND_SCREENSHOT_SAVE = to_bool(option['enable_error_log_and_screenshot_save'])
|
||||
self.ENABLE_PERSPECTIVE_ERROR_IMAGE_SAVE = to_bool(option['enable_perspective_error_image_save'])
|
||||
self.USE_ADB_SCREENSHOT = to_bool(option['use_adb_screenshot'])
|
||||
self.USE_ADB_CONTROL = to_bool(option['use_adb_control'])
|
||||
self.DEVICE_SCREENSHOT_METHOD = option['device_screenshot_method']
|
||||
self.DEVICE_CONTROL_METHOD = option['device_control_method']
|
||||
self.COMBAT_SCREENSHOT_INTERVAL = float(option['combat_screenshot_interval'])
|
||||
|
||||
option = config['Setting']
|
||||
|
@ -124,8 +124,8 @@ dic_true_eng_to_eng = {
|
||||
'package_name': 'package_name',
|
||||
'enable_error_log_and_screenshot_save': 'enable_error_log_and_screenshot_save',
|
||||
'enable_perspective_error_image_save': 'enable_perspective_error_image_save',
|
||||
'use_adb_screenshot': 'use_adb_screenshot',
|
||||
'use_adb_control': 'use_adb_control',
|
||||
'device_screenshot_method': 'device_screenshot_method',
|
||||
'device_control_method': 'device_control_method',
|
||||
'combat_screenshot_interval': 'combat_screenshot_interval',
|
||||
'enable_daily_mission': 'enable_daily_mission',
|
||||
'enable_hard_campaign': 'enable_hard_campaign',
|
||||
@ -189,6 +189,9 @@ dic_true_eng_to_eng = {
|
||||
'map_100': 'map_100',
|
||||
'map_3_star': 'map_3_star',
|
||||
'map_green': 'map_green',
|
||||
'aScreenCap': 'aScreenCap',
|
||||
'uiautomator2': 'uiautomator2',
|
||||
'ADB': 'ADB',
|
||||
'daily_air': 'daily_air',
|
||||
'daily_gun': 'daily_gun',
|
||||
'daily_torpedo': 'daily_torpedo',
|
||||
@ -311,8 +314,8 @@ dic_chi_to_eng = {
|
||||
'包名': 'package_name',
|
||||
'出错时保存log和截图': 'enable_error_log_and_screenshot_save',
|
||||
'保存透视识别出错的图像': 'enable_perspective_error_image_save',
|
||||
'使用ADB截图': 'use_adb_screenshot',
|
||||
'使用ADB点击': 'use_adb_control',
|
||||
'设备截图方案': 'device_screenshot_method',
|
||||
'设备控制方案': 'device_control_method',
|
||||
'战斗中截图间隔': 'combat_screenshot_interval',
|
||||
'打每日': 'enable_daily_mission',
|
||||
'打困难': 'enable_hard_campaign',
|
||||
@ -375,6 +378,9 @@ dic_chi_to_eng = {
|
||||
'地图通关': 'map_100',
|
||||
'地图三星': 'map_3_star',
|
||||
'地图绿海': 'map_green',
|
||||
'aScreenCap': 'aScreenCap',
|
||||
'uiautomator2': 'uiautomator2',
|
||||
'ADB': 'ADB',
|
||||
'航空': 'daily_air',
|
||||
'炮击': 'daily_gun',
|
||||
'雷击': 'daily_torpedo',
|
||||
|
@ -1,3 +1,4 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import requests
|
||||
@ -18,6 +19,8 @@ class Connection:
|
||||
self.serial = str(self.config.SERIAL)
|
||||
self.device = self.connect(self.serial)
|
||||
self.disable_uiautomator2_auto_quit()
|
||||
if self.config.DEVICE_SCREENSHOT_METHOD == 'aScreenCap':
|
||||
self._ascreencap_init()
|
||||
|
||||
@staticmethod
|
||||
def adb_command(cmd, serial=None):
|
||||
@ -29,13 +32,17 @@ class Connection:
|
||||
# Use shell=True to disable console window when using GUI.
|
||||
# Although, there's still a window when you stop running in GUI, which cause by gooey.
|
||||
# To disable it, edit gooey/gui/util/taskkill.py
|
||||
result = subprocess.check_output(cmd, timeout=4, stderr=subprocess.STDOUT, shell=True)
|
||||
return result
|
||||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
|
||||
return process.communicate(timeout=4)[0]
|
||||
|
||||
def adb_shell(self, cmd, serial=None):
|
||||
cmd.insert(0, 'shell')
|
||||
return self.adb_command(cmd, serial)
|
||||
|
||||
def adb_exec_out(self, cmd, serial=None):
|
||||
cmd.insert(0, 'exec-out')
|
||||
return self.adb_command(cmd, serial)
|
||||
|
||||
def _adb_connect(self, serial):
|
||||
if serial.startswith('127.0.0.1'):
|
||||
msg = self.adb_command(['connect', serial]).decode("utf-8")
|
||||
@ -61,3 +68,22 @@ class Connection:
|
||||
def disable_uiautomator2_auto_quit(self, port=7912, expire=300000):
|
||||
self.adb_command(['forward', 'tcp:%s' % port, 'tcp:%s' % port], serial=self.serial)
|
||||
requests.post('http://127.0.0.1:%s/newCommandTimeout' % port, data=str(expire))
|
||||
|
||||
def _ascreencap_init(self):
|
||||
logger.hr('aScreenCap init')
|
||||
|
||||
arc = self.adb_exec_out(['getprop', 'ro.product.cpu.abi'], serial=self.serial).decode('utf-8').strip()
|
||||
sdk = self.adb_exec_out(['getprop', 'ro.build.version.sdk'], serial=self.serial).decode('utf-8').strip()
|
||||
logger.attr('CPU_Architecture', arc)
|
||||
logger.attr('Android_SDK_version', sdk)
|
||||
|
||||
if int(sdk) not in range(21, 26) or not os.path.exists(f'./ascreencap/{arc}'):
|
||||
logger.warning('No suitable version of aScreenCap lib is available locally')
|
||||
exit(1)
|
||||
|
||||
filepath = f'./ascreencap/{arc}/ascreencap'
|
||||
logger.info(f'Pushing {filepath} to {self.config.ASCREENCAP_FILEPATH}')
|
||||
self.adb_command(['push', filepath, self.config.ASCREENCAP_FILEPATH], serial=self.serial)
|
||||
|
||||
logger.info(f'chmod 0777 {self.config.ASCREENCAP_FILEPATH}')
|
||||
self.adb_shell(['chmod', '0777', self.config.ASCREENCAP_FILEPATH], serial=self.serial)
|
||||
|
@ -57,11 +57,11 @@ class Control(Connection):
|
||||
logger.info(
|
||||
'Click %s @ %s' % (self._point2str(x, y), button)
|
||||
)
|
||||
adb = self.config.USE_ADB_CONTROL
|
||||
if adb:
|
||||
self._click_adb(x, y)
|
||||
else:
|
||||
method = self.config.DEVICE_CONTROL_METHOD
|
||||
if method == 'uiautomator2':
|
||||
self._click_uiautomator2(x, y)
|
||||
else:
|
||||
self._click_adb(x, y)
|
||||
self.sleep(self.config.SLEEP_AFTER_CLICK)
|
||||
|
||||
@retry()
|
||||
|
@ -3,19 +3,23 @@ import time
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
|
||||
import cv2
|
||||
import lz4.block
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from retrying import retry
|
||||
|
||||
from module.base.timer import Timer
|
||||
from module.device.connection import Connection
|
||||
from module.logger import logger
|
||||
from module.base.timer import Timer
|
||||
|
||||
|
||||
class Screenshot(Connection):
|
||||
_screenshot_method = 0
|
||||
_screenshot_method_fixed = False
|
||||
_bytepointer = 0
|
||||
|
||||
_screenshot_interval_timer = Timer(0.1)
|
||||
_adb = False
|
||||
_last_save_time = {}
|
||||
image: Image.Image
|
||||
|
||||
@ -49,6 +53,39 @@ class Screenshot(Connection):
|
||||
screenshot = self.adb_shell(['screencap', '-p'], serial=self.serial)
|
||||
return self._process_screenshot(screenshot)
|
||||
|
||||
def _reposition_byte_pointer(self, byte_array):
|
||||
"""Method to return the sanitized version of ascreencap stdout for devices
|
||||
that suffers from linker warnings. The correct pointer location will be saved
|
||||
for subsequent screen refreshes
|
||||
"""
|
||||
while byte_array[self._bytepointer:self._bytepointer + 4] != b'BMZ1':
|
||||
self._bytepointer += 1
|
||||
if self._bytepointer >= len(byte_array):
|
||||
text = 'Repositioning byte pointer failed, corrupted aScreenCap data received'
|
||||
logger.warning(text)
|
||||
exit(1)
|
||||
return byte_array[self._bytepointer:]
|
||||
|
||||
def _screenshot_ascreencap(self):
|
||||
raw_compressed_data = self._reposition_byte_pointer(
|
||||
self.adb_exec_out([self.config.ASCREENCAP_FILEPATH, '--pack', '2', '--stdout'], serial=self.serial))
|
||||
|
||||
compressed_data_header = np.frombuffer(raw_compressed_data[0:20], dtype=np.uint32)
|
||||
if compressed_data_header[0] != 828001602:
|
||||
compressed_data_header = compressed_data_header.byteswap()
|
||||
if compressed_data_header[0] != 828001602:
|
||||
text = f'aScreenCap header verification failure, corrupted image received. ' \
|
||||
f'HEADER IN HEX = {compressed_data_header.tobytes().hex()}'
|
||||
logger.warning(text)
|
||||
exit(1)
|
||||
|
||||
uncompressed_data_size = compressed_data_header[1].item()
|
||||
data = lz4.block.decompress(raw_compressed_data[20:], uncompressed_size=uncompressed_data_size)
|
||||
image = cv2.imdecode(np.frombuffer(data, dtype=np.uint8), cv2.IMREAD_COLOR)
|
||||
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
|
||||
image = Image.fromarray(image)
|
||||
return image
|
||||
|
||||
@retry()
|
||||
# @timer
|
||||
def screenshot(self):
|
||||
@ -58,13 +95,14 @@ class Screenshot(Connection):
|
||||
"""
|
||||
self._screenshot_interval_timer.wait()
|
||||
self._screenshot_interval_timer.reset()
|
||||
adb = self.config.USE_ADB_SCREENSHOT
|
||||
self._adb = adb
|
||||
method = self.config.DEVICE_SCREENSHOT_METHOD
|
||||
|
||||
if adb:
|
||||
self.image = self._screenshot_adb()
|
||||
else:
|
||||
if method == 'aScreenCap':
|
||||
self.image = self._screenshot_ascreencap()
|
||||
elif method == 'uiautomator2':
|
||||
self.image = self._screenshot_uiautomator2()
|
||||
else:
|
||||
self.image = self._screenshot_adb()
|
||||
|
||||
self.image.load()
|
||||
if self.config.ENABLE_ERROR_LOG_AND_SCREENSHOT_SAVE:
|
||||
@ -83,7 +121,7 @@ class Screenshot(Connection):
|
||||
"""
|
||||
now = time.time()
|
||||
if now - self._last_save_time.get(genre, 0) > self.config.SCREEN_SHOT_SAVE_INTERVAL:
|
||||
fmt = 'png' if self._adb else 'png'
|
||||
fmt = 'png'
|
||||
file = '%s.%s' % (int(now * 1000), fmt)
|
||||
|
||||
folder = os.path.join(self.config.SCREEN_SHOT_SAVE_FOLDER, genre)
|
||||
|
@ -3,6 +3,7 @@ scipy==1.4.1
|
||||
pillow
|
||||
opencv-python
|
||||
scikit-image==0.16.2
|
||||
lz4
|
||||
requests<2.19.0,>=2.18.4
|
||||
uiautomator2
|
||||
retrying
|
||||
|
Loading…
Reference in New Issue
Block a user