scrcpy代码改进

This commit is contained in:
zhbaor 2024-11-27 23:20:30 +08:00
parent a478ba14f2
commit 0bfc88a3b0
2 changed files with 10 additions and 184 deletions

View file

@ -1,5 +1,4 @@
import functools
import socket
import struct
from time import sleep
from typing import TYPE_CHECKING
@ -48,17 +47,6 @@ class ControlSender:
"""
return struct.pack("!BIII", action, keycode, repeat, 0)
@inject(const.TYPE_INJECT_TEXT)
def text(self, text: str) -> bytes:
"""
Send text to device
Args:
text: text to send
"""
buffer = text.encode("utf-8")
return struct.pack(">i", len(buffer)) + buffer
@inject(const.TYPE_INJECT_TOUCH_EVENT)
def touch(
self, x: int, y: int, action: int = const.ACTION_DOWN, touch_id: int = -1
@ -95,170 +83,6 @@ class ControlSender:
buttons,
)
@inject(const.TYPE_INJECT_SCROLL_EVENT)
def scroll(self, x: int, y: int, h: int, v: int) -> bytes:
"""
Scroll screen
Args:
x: horizontal position
y: vertical position
h: horizontal movement
v: vertical movement
"""
x, y = max(x, 0), max(y, 0)
return struct.pack(
">iiHHii",
int(x),
int(y),
int(self.parent.resolution[0]),
int(self.parent.resolution[1]),
int(h),
int(v),
)
@inject(const.TYPE_BACK_OR_SCREEN_ON)
def back_or_turn_screen_on(self, action: int = const.ACTION_DOWN) -> bytes:
"""
If the screen is off, it is turned on only on ACTION_DOWN
Args:
action: ACTION_DOWN | ACTION_UP
"""
return struct.pack(">B", action)
@inject(const.TYPE_EXPAND_NOTIFICATION_PANEL)
def expand_notification_panel(self) -> bytes:
"""
Expand notification panel
"""
return b""
@inject(const.TYPE_EXPAND_SETTINGS_PANEL)
def expand_settings_panel(self) -> bytes:
"""
Expand settings panel
"""
return b""
@inject(const.TYPE_COLLAPSE_PANELS)
def collapse_panels(self) -> bytes:
"""
Collapse all panels
"""
return b""
def get_clipboard(self, copy_key=const.COPY_KEY_NONE) -> str:
"""
Get clipboard
"""
# Since this function need socket response, we can't auto inject it any more
s: socket.socket = self.parent.control_socket
with self.parent.control_socket_lock:
# Flush socket
s.setblocking(False)
while True:
try:
s.recv(1024)
except BlockingIOError:
break
s.setblocking(True)
# Read package
package = struct.pack(">BB", const.TYPE_GET_CLIPBOARD, copy_key)
s.send(package)
(code,) = struct.unpack(">B", s.recv(1))
assert code == 0
(length,) = struct.unpack(">i", s.recv(4))
return s.recv(length).decode("utf-8")
@inject(const.TYPE_SET_CLIPBOARD)
def set_clipboard(self, text: str, paste: bool = False) -> bytes:
"""
Set clipboard
Args:
text: the string you want to set
paste: paste now
"""
buffer = text.encode("utf-8")
return struct.pack(">?i", paste, len(buffer)) + buffer
@inject(const.TYPE_SET_SCREEN_POWER_MODE)
def set_screen_power_mode(self, mode: int = const.POWER_MODE_NORMAL) -> bytes:
"""
Set screen power mode
Args:
mode: POWER_MODE_OFF | POWER_MODE_NORMAL
"""
return struct.pack(">b", mode)
@inject(const.TYPE_ROTATE_DEVICE)
def rotate_device(self) -> bytes:
"""
Rotate device
"""
return b""
def swipe(
self,
start_x: int,
start_y: int,
end_x: int,
end_y: int,
move_step_length: int = 5,
move_steps_delay: float = 0.005,
) -> None:
"""
Swipe on screen
Args:
start_x: start horizontal position
start_y: start vertical position
end_x: start horizontal position
end_y: end vertical position
move_step_length: length per step
move_steps_delay: sleep seconds after each step
:return:
"""
self.touch(start_x, start_y, const.ACTION_DOWN)
next_x = start_x
next_y = start_y
if end_x > self.parent.resolution[0]:
end_x = self.parent.resolution[0]
if end_y > self.parent.resolution[1]:
end_y = self.parent.resolution[1]
decrease_x = True if start_x > end_x else False
decrease_y = True if start_y > end_y else False
while True:
if decrease_x:
next_x -= move_step_length
if next_x < end_x:
next_x = end_x
else:
next_x += move_step_length
if next_x > end_x:
next_x = end_x
if decrease_y:
next_y -= move_step_length
if next_y < end_y:
next_y = end_y
else:
next_y += move_step_length
if next_y > end_y:
next_y = end_y
self.touch(next_x, next_y, const.ACTION_MOVE)
if next_x == end_x and next_y == end_y:
self.touch(next_x, next_y, const.ACTION_UP)
break
sleep(move_steps_delay)
def tap(self, x, y, hold_time: float = 0.07) -> None:
"""
Tap on screen

View file

@ -8,19 +8,20 @@ from typing import Any, Callable, Optional
import numpy as np
from mower import __rootdir__
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.device.adb_client.const import KeyCode
from mower.utils.device.adb_client.core import Client as ADBClient
from mower.utils.device.adb_client.socket import Socket
from mower.utils.log import logger
from mower.utils.path import get_path
from mower.utils.vector import sm, va
from . import const
from .control import ControlSender
SCR_PATH = "/data/local/tmp/scrcpy-server.jar"
SCR_VER = "2.7"
swipe_update_result = None
@ -93,7 +94,7 @@ class Client:
"""
Start server and get the connection
"""
cmdline = f"CLASSPATH={SCR_PATH} app_process / com.genymobile.scrcpy.Server 2.7 video=false audio=false control=true tunnel_forward=true"
cmdline = f"CLASSPATH={SCR_PATH} app_process / com.genymobile.scrcpy.Server {SCR_VER} video=false audio=false control=true tunnel_forward=true"
if self.displayid is not None:
cmdline += f" display_id={self.displayid}"
self.__server_stream: Socket = self.client.stream_shell(cmdline)
@ -109,16 +110,12 @@ class Client:
"""
Deploy server to android device
"""
server_file_path = __rootdir__ / "vendor" / "scrcpy-server-v2.7"
server_file_path = get_path(f"@install/mower/vendor/scrcpy-server-v{SCR_VER}")
server_buf = server_file_path.read_bytes()
self.client.push(SCR_PATH, server_buf)
self.__start_server()
def __init_server_connection(self) -> None:
"""
Connect to android server, there will be two sockets, video and control socket.
This method will set: video_socket, control_socket, resolution variables
"""
try:
self.control_socket = self.client.stream("localabstract:scrcpy")
except socket.timeout:
@ -176,7 +173,12 @@ class Client:
while try_count < 3:
try:
return f(self, *args, **kwargs)
except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError):
except (
ConnectionResetError,
BrokenPipeError,
ConnectionAbortedError,
) as e:
logger.debug_exception(e)
self.stop()
time.sleep(1)
self.check_adb_alive()