Browse Source

更新工具类

xiao.qiang 7 months ago
parent
commit
f11adb19ec

+ 35 - 0
.gitignore

@@ -126,3 +126,38 @@ crashlytics-build.properties
 /.venv/lib64/
 /poetry.lock
 /.venv/lib64/
+!/build/
+
+!/*.spec
+
+!/dist/
+
+!/poetry.lock
+/.venv/bin/f2py
+/.venv/bin/helpviewer
+/.venv/bin/img2png
+/.venv/bin/img2py
+/.venv/bin/img2xpm
+/.venv/bin/numpy-config
+/.venv/bin/py.test
+/.venv/bin/pycrust
+/.venv/bin/pyi-archive_viewer
+/.venv/bin/pyi-bindepend
+/.venv/bin/pyi-grab_version
+/.venv/bin/pyi-makespec
+/.venv/bin/pyi-set_version
+/.venv/bin/pyinstaller
+/.venv/bin/pyshell
+/.venv/bin/pyslices
+/.venv/bin/pyslicesshell
+/.venv/bin/pytest
+/.venv/bin/pywxrc
+/.venv/bin/uvicorn
+/.venv/bin/wxdemo
+/.venv/bin/wxdocs
+/.venv/bin/wxget
+/.venv/lib64/
+/mobile-tools.spec
+/poetry.lock
+/test02.spec
+/1.xml

+ 19 - 3
README.md

@@ -1,4 +1,4 @@
-# mobel-rpa
+# mobile-rpa
 ## 参考 
 [参考文档](https://developer.android.com/reference/android/support/test/uiautomator/UiSelector)
 
@@ -10,7 +10,15 @@ https://www.genymotion.com/product-desktop/download/
 
 ## 初始化项目
 ```shell
+export HTTP_PROXY=http://127.0.0.1:7899
+export HTTPS_PROXY=http://127.0.0.1:7899
+
+# window  修改编码
+# chcp 65001
 poetry install
+
+#sudo apt-get install python3-tk
+
 ```
 
 运行android定位器
@@ -59,5 +67,13 @@ point 可以 使用weditor获取到的坐标
 
 ## 打包
 ```shell
-pyinstaller  --clean  -i assets/logo/32x32.ico test/deepcoin/test02.py 
-```
+#C:\Users\fzxs\anaconda3\envs\rpa\Lib\site-packages\uiautomator2\assets
+pyinstaller  --clean  --name mobile-tools  -i assets/logo/32x32.ico main.py  --add-data "C:/Users/fzxs/anaconda3/envs/rpa/Lib/site-packages/uiautomator2/assets:uiautomator2/assets" 
+```
+
+```shell
+pyinstaller  --clean --name mobile-tools  -w -i assets/logo/32x32.ico main.py
+```
+
+
+python -m uiautomator2 init

BIN
assets/btn/deepcoin.png


BIN
docs/test-01.jpg


+ 275 - 0
gui/phone_list.py

@@ -0,0 +1,275 @@
+import logging
+import tkinter as tk
+from tkinter import ttk
+
+from plat.base.base_control import BaseControl
+
+
+class LeftPanel(tk.LabelFrame):
+    def __init__(self, master=None):
+        super().__init__(master, text="手机列表")
+        self.master = master
+        self.phone_items_data = []  # 用于存储每个手机项的数据 (包含 CheckVar)
+        self.create_widgets()
+        self._check_scrollable()  # 初始检查是否需要滚动条
+
+    def create_widgets(self):
+
+        title_label = ttk.Frame(self, relief="flat", borderwidth=1)
+        title_label.grid(row=0, column=0, padx=10, pady=10, sticky="ew")
+
+        # 添加分割线
+        separator = ttk.Separator(title_label, orient="horizontal")
+        separator.grid(row=1, column=0, columnspan=4, sticky="ew", padx=5, pady=5)
+
+        name_label = ttk.Label(title_label, text='全选')
+        name_label.grid(row=0, column=1, padx=5, pady=10, sticky="e")
+        # 选择框
+        check_all = tk.BooleanVar()
+        check_button = ttk.Checkbutton(title_label, variable=check_all, command=lambda v=check_all: self.toggle_check(v))
+        check_button.grid(row=0, column=2, padx=5, pady=10, sticky="e")
+
+        # 添加数据按钮
+        add_data_button = ttk.Button(title_label, text="刷新", command=self.add_data)
+        add_data_button.grid(row=0, column=3, padx=5, pady=10, sticky="e")
+
+        # 创建 Canvas 和 Scrollbar
+        self.canvas = tk.Canvas(self)
+        self.scrollbar = ttk.Scrollbar(self, orient="vertical", command=self.canvas.yview)
+        self.canvas.configure(yscrollcommand=self.scrollbar.set)
+
+        self.canvas.grid(row=1, column=0, columnspan=4, sticky="nsew")
+        self.scrollbar.grid(row=1, column=4, sticky="ns")
+
+        # 创建 Frame 放入 Canvas 中
+        self.list_frame = ttk.Frame(self.canvas)
+        self.canvas.create_window((0, 0), window=self.list_frame, anchor="nw")
+        self.list_frame.bind("<Configure>", self._on_frame_configure)
+        self.canvas.bind("<Enter>", self._bind_mousewheel_enter)
+        self.canvas.bind("<Leave>", self._bind_mousewheel_leave)
+
+        # 配置 Grid 的行和列的权重,使 Canvas 可以扩展
+        self.grid_rowconfigure(1, weight=1)
+        self.grid_columnconfigure(0, weight=1)
+        self.grid_columnconfigure(1, weight=0)  # 全选按钮不扩展
+        self.grid_columnconfigure(2, weight=0)  # 添加数据按钮不扩展
+        self.grid_columnconfigure(3, weight=0)  # 取消全选按钮不扩展
+        self.grid_columnconfigure(4, weight=0)  # 滚动条列不扩展
+
+        self._populate_list()
+
+    def _populate_list(self):
+        """根据 self.phone_data 填充列表"""
+        for widget in self.list_frame.winfo_children():
+            widget.destroy()
+        self.phone_items_data = []
+        # for phone in self.phone_data:
+        #     self.create_list_item(phone["name"], phone["status"])
+
+        for pkg, device in BaseControl.connect_dict.items():
+            logging.info(f'==添加手机信息=>{pkg} {device}')
+            self.create_list_item(device)
+
+        self._on_frame_configure(None)  # 更新滚动区域
+
+    def create_list_item(self, device):
+        item_frame = ttk.Frame(self.list_frame, padding=(5, 5))
+        item_frame.pack(fill="x", expand=True)
+
+        name = device['device']
+        status = device['status']
+
+        # 选择框
+        check_var = tk.BooleanVar()
+        check_var.set(True)
+        check_button = ttk.Checkbutton(item_frame, variable=check_var)
+        check_button.pack(side="left")
+
+        # 手机名称
+        name_label = ttk.Label(item_frame, text=f'{device["name"]}:【{device["pkg"]}】', anchor="w", width=20)
+        name_label.pack(side="left", padx=5)
+
+        # 状态指示器
+        status_canvas = tk.Canvas(item_frame, width=10, height=10, highlightthickness=0)
+        status_canvas.pack(side="left", padx=5)
+        if status == "online":
+            status_canvas.create_oval(0, 0, 10, 10, fill="green")
+        else:
+            status_canvas.create_oval(0, 0, 10, 10, fill="red")
+
+        # 状态按钮 (这里我们用一个简单的 Label 模拟)
+        status_button = ttk.Label(item_frame, text="@", width=3, anchor="center", relief="groove")
+        status_button.pack(side="right", padx=5)
+
+        self.phone_items_data.append((check_var, name, status))  # 存储 CheckVar 和数据
+
+    def toggle_check(self, check_var):
+        if check_var.get():
+            print("复选框被选中")
+        else:
+            print("复选框被取消选中")
+        for var, _, _ in self.phone_items_data:
+            var.set(check_var.get())
+        pass
+
+    def add_data(self):
+        """
+        动态添加数据
+        """
+        # logging.info(f"==手机信息=>{BaseControl.connect_dict}")
+        # new_index = len(self.phone_data) + 1
+        # new_phone = {"name": f"Tel - {new_index:02d} [New Device]", "status": "pending"}
+        # self.phone_data.append(new_phone)
+        self._populate_list()  # 重新填充列表以显示新数据
+        self._check_scrollable()  # 添加数据后检查是否需要滚动条
+
+    def _on_frame_configure(self, event):
+        """当列表 Frame 大小改变时,更新 Canvas 的滚动区域并检查是否需要绑定滚轮事件"""
+        self.canvas.configure(scrollregion=self.canvas.bbox("all"))
+        self._check_scrollable()
+
+    def _check_scrollable(self):
+        """检查内容是否需要滚动条,并决定是否需要显示"""
+        if self.canvas.winfo_height() < self.canvas.bbox("all")[3]:
+            self.scrollbar.grid(row=1, column=4, sticky="ns")  # 显示滚动条
+        else:
+            self.scrollbar.grid_remove()  # 隐藏滚动条
+
+    def _bind_mousewheel_enter(self, event):
+        """鼠标进入 Canvas 时绑定滚轮事件"""
+        if self.canvas.winfo_height() < self.canvas.bbox("all")[3]:  # 只有在需要滚动时才绑定
+            self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
+            self.canvas.bind_all("<Button-4>", self._on_mousewheel)  # Linux
+            self.canvas.bind_all("<Button-5>", self._on_mousewheel)  # Linux
+
+    def _bind_mousewheel_leave(self, event):
+        """鼠标离开 Canvas 时解绑滚轮事件"""
+        self.canvas.unbind_all("<MouseWheel>")
+        self.canvas.unbind_all("<Button-4>")
+        self.canvas.unbind_all("<Button-5>")
+
+    def _on_mousewheel(self, event):
+        """鼠标滚轮滚动事件处理"""
+        if event.delta:
+            self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")
+        else:
+            if event.num == 4:
+                self.canvas.yview_scroll(-1, "units")
+            elif event.num == 5:
+                self.canvas.yview_scroll(1, "units")
+
+
+class RightPanel(tk.Frame):
+    def __init__(self, master=None, *args, **kwargs):
+        super().__init__(master)
+        self.master = master
+        self.create_args()
+        self.create_info_ares()
+        self.grid_columnconfigure(0, weight=1)  # 让列可以水平扩展
+        self.grid_rowconfigure(0, weight=0)  # 参数设定区域不需要扩展
+        self.grid_rowconfigure(1, weight=1)  # 让操作区域可以垂直扩展
+
+    def create_args(self):
+        # 右侧区域的组件可以在这里创建
+        # label = ttk.Label(self, text="右侧区域", font=("Arial", 12, "bold"))
+        # label.pack(padx=10, pady=10)
+        #
+        # # 添加更多组件...
+        # button = ttk.Button(self, text="按钮", command=lambda: print("按钮被点击"))
+        # button.pack(padx=10, pady=10)
+
+        fieldset = ttk.LabelFrame(self, text="参数设定")
+        fieldset.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
+        # fieldset.grid_columnconfigure(0, weight=1)
+        # fieldset.grid_rowconfigure(1, weight=1)
+        name_label = ttk.Label(fieldset, text="币种:", width=5)
+        name_label.grid(row=0, column=0, padx=5, pady=5, sticky="nw")
+
+        name_val = tk.Text(fieldset, width=20, height=1.2, wrap='word')
+        name_val.grid(row=0, column=1, padx=5, pady=5, sticky="nw")
+        name_val.insert('1.0', 'HMSTR')  # 插入文本
+        name_val.config(state='disabled')  # 再禁用
+
+        cmd_label = ttk.Label(fieldset, text="数量:", width=5)
+        cmd_label.grid(row=0, column=2, padx=5, pady=5, sticky="nw")
+
+        cmd_text = tk.Text(fieldset, height=1.2, width=10, wrap='word')
+        cmd_text.grid(row=0, column=3, padx=5, pady=5, sticky="nw")
+
+    def create_info_ares(self):
+        # 创建一个 Frame 来模拟 <fieldset>
+        fieldset = ttk.Frame(self)
+        fieldset.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")
+
+        # 设置 fieldset 的网格权重配置
+        fieldset.grid_columnconfigure(0, weight=3)  # 让信息区域占据更多水平空间
+        fieldset.grid_columnconfigure(1, weight=1)  # 操作区域占据较少水平空间
+        fieldset.grid_rowconfigure(0, weight=1)  # 让内容区域可以垂直扩展
+
+        fieldset_action = ttk.LabelFrame(fieldset, text="操作")
+        fieldset_action.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
+        fieldset_action.grid_columnconfigure(0, weight=1)
+        fieldset_action.grid_rowconfigure(1, weight=1)
+
+        fieldset_log = ttk.LabelFrame(fieldset, text="操作日志")
+        fieldset_log.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")
+        fieldset_log.grid_columnconfigure(0, weight=1)  # 文本框列可扩展
+        fieldset_log.grid_rowconfigure(1, weight=1)  # 文本框行可扩展
+
+        #  给fieldset_log 添加一个多行文本区域
+        log_text = tk.Text(fieldset_log, wrap='word')
+        log_text.grid(row=1, column=0, padx=5, pady=5, sticky="nsew")
+        log_text_scroll = ttk.Scrollbar(fieldset_log, command=log_text.yview)
+        log_text_scroll.grid(row=1, column=1, sticky="ns")
+        log_text.config(yscrollcommand=log_text_scroll.set)
+
+        def handle_keypress(event):
+            if event.keysym in ('Return', 'KP_Enter'):
+                log_text.insert('end', '\n')
+                return 'break'
+            return None
+
+        log_text.bind('<KeyPress>', handle_keypress)
+        log_text.focus_set()  # 让文本框获得焦点
+        log_text.focus_set()  # 让文本框获得焦点
+
+        # 给fieldset_action 添加7个按钮,每行2个 共3行
+        green_btn_style = ttk.Style()
+        green_btn_style.configure('Green.TButton', background='#00cc00', foreground='#009900')
+        red_btn_style = ttk.Style()
+        red_btn_style.configure('Red.TButton', background='#ff4444', foreground='#cc0000')
+
+        gray_btn_style = ttk.Style()
+        gray_btn_style.configure('Gray.TButton', background='#888888', foreground='#666666')
+        button1 = ttk.Button(fieldset_action, text="买入/开多", command=lambda: print("买入/开多"), style='Green.TButton')
+        button1.grid(row=0, column=0, padx=5, pady=5, sticky="nw")
+
+        button2 = ttk.Button(fieldset_action, text="买入/平多", command=lambda: print("买入/平多"), style='Green.TButton')
+        button2.grid(row=0, column=1, padx=5, pady=5, sticky="nw")
+        button3 = ttk.Button(fieldset_action, text="卖出/开空", command=lambda: print("卖出/开空"), style='Red.TButton')
+        button3.grid(row=1, column=0, padx=5, pady=5, sticky="nw")
+        button4 = ttk.Button(fieldset_action, text="卖出/平空", command=lambda: print("卖出/平空"), style='Red.TButton')
+        button4.grid(row=1, column=1, padx=5, pady=5, sticky="nw")
+        button5 = ttk.Button(fieldset_action, text="撤销委托", command=lambda: print("撤销委托"))
+        button5.grid(row=2, column=0, padx=5, pady=5, sticky="nw")
+        button6 = ttk.Button(fieldset_action, text="一键撤单", command=lambda: print("一键撤单"))
+        button6.grid(row=2, column=1, padx=5, pady=5, sticky="nw")
+
+
+class PhoneListUI(tk.Frame):
+    """
+    手机列表控制页面
+    """
+
+    def __init__(self, control: BaseControl = None, master=None, cnf=None, **kw):
+        super().__init__(master, cnf if cnf is not None else {}, **kw)
+        self.control = control
+        self.init_ui()
+
+    def init_ui(self):
+        left_panel = LeftPanel(self)
+        left_panel.pack(side="left", fill="y")
+
+        # 为了演示,我们创建一个简单的右侧区域
+        right_panel = RightPanel(self, width=400, height=400)
+        right_panel.pack(side="left", fill="both", expand=True)

+ 333 - 0
gui/settings.py

@@ -0,0 +1,333 @@
+import logging
+import tkinter as tk
+from tkinter import ttk
+from typing import List
+
+from plat.base.base_control import BaseControl, AbsControl
+from utils.config import version
+
+
+class _SettingsConnect(tk.Frame):
+    """
+    连接云手机
+    """
+
+    def __init__(self, master=None, control: AbsControl = None, cnf=None, **kw):
+        super().__init__(master, cnf if cnf is not None else {}, **kw)
+
+        self.control = control
+        self.init_ui()
+        self.pack(padx=10, pady=10)
+
+    def init_ui(self):
+        """
+            初始化连接
+            云手机开启 ABD后无法自动识别,需要通过shell 连接一下。
+            :return:
+
+            """
+        logging.info(f"连接云手机--->")
+        content = ttk.Frame(self)
+        content.pack(fill=tk.BOTH, expand=True)
+
+        fieldset = ttk.LabelFrame(content, text="连接信息")
+        fieldset.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
+        content.grid_columnconfigure(0, weight=1)
+        content.grid_rowconfigure(0, weight=1)
+        fieldset.grid_columnconfigure(0, weight=1)
+        fieldset.grid_rowconfigure(1, weight=1)
+
+        cmd_label = ttk.Label(fieldset, text="ADB连接(一行一个):")
+        cmd_label.grid(row=0, column=0, padx=5, pady=5, sticky="nw")
+
+        cmd_text = tk.Text(fieldset, height=10)
+        cmd_text.grid(row=1, column=0, padx=5, pady=5, sticky="nsew")
+
+        test_btn = ttk.Button(fieldset, text="连接云手机", command=lambda: self.control.init_adb(cmd_text.get('1.0', tk.END).split('\n'), log_text, **{'ui': self}))
+        test_btn.grid(row=2, column=0, padx=5, pady=5, sticky="nw")
+
+        # 日志区域
+        log_label = ttk.Label(content, text="连接信息:")
+        log_label.grid(row=1, column=0, padx=5, pady=5, sticky="nw")
+
+        log_text = tk.Text(content, height=10)
+        log_text.grid(row=2, column=0, padx=10, pady=(0, 10), sticky="nsew")
+        content.grid_rowconfigure(2, weight=1)
+
+    # def _connect_adb(self, cmd_text, log_text):
+    #     # 创建加载指示器
+    #
+    #     def func():
+    #         self.control.init_adb(cmd_text.get('1.0', tk.END).split('\n'), log_text)
+    #
+    #     self.control.loadding(self, func)
+    # loading_window = tk.Toplevel(self)
+    # loading_window.title("连接中")
+    # loading_window.geometry("200x100")
+    # loading_window.transient(self)  # 设置为模态
+    # loading_window.grab_set()  # 设置为模态
+    # loading_window.overrideredirect(True)  # 移除窗口边框和按钮
+    # # 相对于父窗口居中显示
+    # window_width = loading_window.winfo_reqwidth()
+    # window_height = loading_window.winfo_reqheight()
+    # parent_x = self.winfo_rootx()
+    # parent_y = self.winfo_rooty()
+    # parent_width = self.winfo_width()
+    # parent_height = self.winfo_height()
+    # position_right = parent_x + (parent_width - window_width) // 2
+    # position_down = parent_y + (parent_height - window_height) // 2
+    # loading_window.geometry(f"+{position_right}+{position_down}")
+    # loading_label = ttk.Label(loading_window, text="连接中...", padding=20)
+    # loading_label.pack(expand=True)
+    #
+    # def thread_task():
+    #     try:
+    #         self.control.init_adb(cmd_text.get('1.0', tk.END).split('\n'), log_text)
+    #     finally:
+    #         # 在主线程中销毁加载指示器
+    #        self.after(0, lambda: [loading_window.grab_release(), loading_window.destroy()])
+    #
+    # import threading
+    # thread = threading.Thread(target=thread_task)
+    # # thread.daemon = True  # 设置为守护线程,这样主程序退出时线程会自动结束
+    # thread.start()
+
+
+class _SettingsKey(tk.Frame):
+    """
+    设置快捷键
+    """
+    keys_mappings = {
+        '买入/开多': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
+        '买入/平多': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
+        '卖出/开空': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
+        '卖出/平空': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
+        "一键撤单": {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
+        '撤销委托': {'ctrl': False, 'shift': False, 'alt': False, 'key': ''},
+    }
+
+    def __init__(self, master=None, cnf=None, **kw):
+        super().__init__(master, cnf if cnf is not None else {}, **kw)
+
+        self.control = None
+        self.init_ui()
+        self.pack(padx=10, pady=10)
+
+    def init_ui(self):
+        # 快捷键设置
+        fieldset = ttk.LabelFrame(self, text="快捷键设置")
+        fieldset.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
+        fieldset.grid_columnconfigure(0, weight=1)
+        fieldset.grid_rowconfigure(1, weight=1)
+
+        # 配置Checkbutton样式
+        style = ttk.Style()
+        style.configure("TCheckbutton", )
+
+        # 循环 keys_mappings
+        for i, (key, value) in enumerate(self.keys_mappings.items()):
+            # 创建一个 frame 来保存当前行的所有控件
+            row_frame = ttk.Frame(fieldset)
+            row_frame.grid(row=i, column=0, sticky="ew", padx=5, pady=5)
+
+            # 创建说明标签
+            label = ttk.Label(row_frame, text=f"{key:<7}:")
+            label.pack(side=tk.LEFT, padx=(0, 10))
+
+            # 为每个按键组合创建变量并保存在字典中
+            key_state = {
+                'name': key,
+                'ctrl_var': tk.BooleanVar(value=value['ctrl']),
+                'alt_var': tk.BooleanVar(value=value['alt']),
+                'shift_var': tk.BooleanVar(value=value['shift']),
+                'key_var': tk.StringVar(value=value['key'])
+            }
+
+            # 创建复选框
+            ttk.Checkbutton(row_frame, text="Ctrl", variable=key_state['ctrl_var'],
+                            command=lambda state=key_state: self._on_checkbox_click(state)).pack(side=tk.LEFT, padx=5)
+            ttk.Checkbutton(row_frame, text="Alt", variable=key_state['alt_var'],
+                            command=lambda state=key_state: self._on_checkbox_click(state)).pack(side=tk.LEFT, padx=5)
+            ttk.Checkbutton(row_frame, text="Shift", variable=key_state['shift_var'],
+                            command=lambda state=key_state: self._on_checkbox_click(state)).pack(side=tk.LEFT, padx=5)
+
+            # 创建下拉框
+            options = [chr(i) for i in range(65, 91)] + [f"F{i}" for i in range(1, 13)]
+            combo = ttk.Combobox(row_frame, textvariable=key_state['key_var'], values=options,
+                                 width=8, state='readonly', )
+            combo.bind('<<ComboboxSelected>>', lambda event, state=key_state: self._on_checkbox_click(state))
+            # 如果key_state中已有值就使用已有值,否则设置为第一个选项
+            if key_state['key_var'].get():
+                combo.set(key_state['key_var'].get())
+            else:
+                combo.current(i)  # 设置第一个选项为默认值
+            combo.pack(side=tk.LEFT, padx=5)
+
+        # idx = len(self.keys_mappings)
+        # save_btn = ttk.Button(self, text="保存",
+        #                       command=lambda: print('保存快捷键设置'))
+        # save_btn.grid(row=idx + 1, column=0, padx=5, pady=5, sticky="nwe")
+
+        # test_btn = ttk.Button(self, text="恢复默认",
+        #                       command=lambda: print('恢复默认'))
+        # test_btn.grid(row=idx + 2, column=0, padx=5, pady=5, sticky="nwe")
+
+    def _on_checkbox_click(self, key_state: dict):
+        """
+        复选框点击事件处理
+        """
+        # 获取当前状态
+        name = key_state['name']
+        ctrl_state = key_state['ctrl_var'].get()
+        alt_state = key_state['alt_var'].get()
+        shift_state = key_state['shift_var'].get()
+        key = key_state['key_var'].get()
+
+        # 更新映射
+        self.keys_mappings[name].update({
+            'ctrl': ctrl_state,
+            'alt': alt_state,
+            'shift': shift_state,
+            'key': key
+        })
+
+        logging.info(f"快捷键 '{name}' 更新: Ctrl={ctrl_state}, Alt={alt_state}, Shift={shift_state}, Key={key}")
+
+        self._key_binds(name)
+
+    def _key_binds(self, name: str):
+
+        """
+        绑定快捷键
+        :param name:
+        :return:
+        """
+
+        key = self.keys_mappings[name]
+        logging.info(f"<UNK> '{key}' <UNK>")
+        key_combo = []
+        if key['ctrl']:
+            key_combo.append('Control')
+        if key['shift']:
+            key_combo.append('Shift')
+        if key['alt']:
+            key_combo.append('Alt')
+
+        # 组合所有激活的修饰键
+        if key_combo:
+            key_bind = f"<{'-'.join(key_combo)}-{key['key'].lower()}>"
+            self.winfo_toplevel().unbind_all(key_bind)
+            self.winfo_toplevel().bind_all(key_bind, lambda event: self._demo_click(f'-->{name}'))
+            logging.info(f'绑定快捷键: {key_bind} --> {name}')
+        else:
+            # 如果没有修饰键,直接绑定键值
+            self.winfo_toplevel().unbind_all(f"<{key['key'].lower()}>")
+            self.winfo_toplevel().bind_all(f"<{key['key'].lower()}>", lambda event: self._demo_click(f'-->{name}'))
+            logging.info(f"<{key['key']}=> {name}  ")
+
+            pass
+
+    def _demo_click(self, event):
+        logging.info(f"<DEMO> {event} <DEMO>")
+
+    def _keys_binds(self, keys: List[dict]):
+        """
+        返回快捷键映射
+        :param keys: [{'ctrl':True,'shift':True,'alt':True,'key':'a'},...]
+        :return:
+        """
+        # 循环 keys 绑定快捷键, self.control
+        for i, key in enumerate(keys):
+            # 绑定快捷键
+            self.init_ui(keys)
+
+
+class _SettingsOther(tk.Frame):
+    """
+    其他设置
+    """
+
+    def __init__(self, master=None, cnf=None, **kw):
+        super().__init__(master, cnf if cnf is not None else {}, **kw)
+
+        self.tel_connect = None
+        self.control = None
+        self.init_ui()
+
+    def init_ui(self):
+        # 创建并配置notebook
+        notebook = ttk.Notebook(self)
+
+        # 设置notebook的填充
+        notebook.pack(anchor="w", fill=tk.BOTH, expand=True)
+
+
+class _SettingsAbout(tk.Frame):
+    """
+    关于
+    """
+
+    def __init__(self, master=None, cnf=None, **kw):
+        super().__init__(master, cnf if cnf is not None else {}, **kw)
+
+        self.init_ui()
+        self.pack(padx=10, pady=10)
+
+    def init_ui(self):
+        # 创建一个 Frame 来模拟 <fieldset>
+        fieldset = ttk.LabelFrame(self, text="群控助手")
+        fieldset.grid(row=0, column=0, padx=10, pady=10, sticky="nw")
+        self.grid_columnconfigure(0, weight=1)
+        self.grid_rowconfigure(0, weight=0)
+        fieldset.grid_columnconfigure(0, weight=1)
+        fieldset.grid_rowconfigure(1, weight=1)
+
+        cmd_label = ttk.Label(fieldset, text=f"版本:{version}")
+        cmd_label.grid(row=0, column=0, padx=5, pady=5, sticky="nw")
+        cmd_label = ttk.Label(fieldset, text=f"作者:强哥")
+        cmd_label.grid(row=2, column=0, padx=5, pady=5, sticky="nw")
+        cmd_label = ttk.Label(fieldset, text=f"邮箱:fzxs88@yeah.net")
+        cmd_label.grid(row=3, column=0, padx=5, pady=5, sticky="nw")
+
+
+class SettingUI(tk.Frame):
+    """
+    设置页面
+    """
+
+    def __init__(self, master=None, control: BaseControl = None, cnf=None, **kw):
+        super().__init__(master, cnf if cnf is not None else {}, **kw)
+
+        self.about = None
+        self.options = None
+        self.key_mapping = None
+        self.tel_connect = None
+        self.control = control
+        self.init_ui()
+
+    def init_ui(self):
+        # 创建并配置notebook
+        notebook = ttk.Notebook(self)
+        #
+        # 设置notebook的填充
+        notebook.pack(anchor="w", fill=tk.BOTH, expand=True)
+        #
+        # 第一个选项卡的内容
+        self.tel_connect = ttk.Frame(notebook)
+        notebook.add(self.tel_connect, text="连接云手机")
+        _SettingsConnect(master=self.tel_connect, control=self.control)
+        # 第二个选项卡的内容
+        self.key_mapping = ttk.Frame(notebook)
+        notebook.add(self.key_mapping, text="设置快捷键")
+        _SettingsKey(self.key_mapping)
+
+        # 第三个选项卡的内容
+        self.options = ttk.Frame(notebook)
+        notebook.add(self.options, text="其他设置")
+        label3 = ttk.Label(self.options, text="其他设置")
+        label3.pack(padx=10, pady=10)
+
+        # 第四个选项卡的内容
+        self.about = ttk.Frame(notebook)
+        notebook.add(self.about, text="关于")
+        _SettingsAbout(self.about)

+ 22 - 0
main.py

@@ -0,0 +1,22 @@
+import logging
+
+from gui.main_ui import Application
+from plat.deepcoin_control import DeepCoinControl
+from plat.settings_control import SettingsControl
+
+logging.basicConfig(level=logging.INFO, force=True)  # 设置日志级别
+
+if __name__ == "__main__":
+    settings = SettingsControl('设置')
+    app = Application(
+        controls={
+            SettingsControl.__name__: settings,
+            'deepCoin': DeepCoinControl('DeepCoin', settings)
+        }
+        # controls=[
+        #     adb
+        #     ,
+        #     DeepCoinControl('DeepCoin', adb)
+        # ]
+    )
+    app.mainloop()

+ 0 - 158
plat/base/abs_ui.py

@@ -1,158 +0,0 @@
-# 定义抽象类
-import json
-import logging
-from abc import ABC, abstractmethod
-
-import uiautomator2 as u2
-
-
-class AbsUi(ABC):
-
-    def __init__(self, serial: str):
-        """
-        :param serial: 设备序列号。 例如 127.0.0.1:6555
-            可以通过 `adb devices`  获取
-        """
-        # u2.logger.setLevel(logging.DEBUG)
-
-        # 屏幕高度
-        self.height = 0
-        # 屏幕宽度
-        self.width = 0
-        self.d = u2.connect(serial)
-
-        self._points = {}
-
-        self.point_path = 'point.json'
-        self.enable_click_monitor()
-        self._func = []
-
-    def enable_click_monitor(self):
-        """
-        启用点击监控,在屏幕上显示点击位置
-        """
-        # self.d.settings['operation_delay'] = (0.5, 0.5)  # 增加操作延迟以便观察
-        self.d.debug = True
-        self.d.toast.show('点击监控已启用')  # 显示提示
-
-        # 确保有悬浮窗权限
-        self.d.set_fastinput_ime(True)  # 启用ime
-        self.d.show_float_window(True)  # 显示悬浮窗
-
-        # 可选:打开开发者选项中的"指针位置"
-        self.d.shell('settings put system pointer_location 1')
-
-    def to_top_swipe(self):
-        """
-        滑动到屏幕最顶部,通过多次滑动确保到达顶部
-        """
-        width, height = self.get_screen_size()
-        # 循环滑动直到无法继续滑动
-        for _ in range(3):
-            self.d.swipe(width // 2, height * 0.8, width // 2, height)  # 向上滑动
-            # 短暂等待确保滑动完成
-            self.d.sleep(0.1)
-
-    def click_point(self, x: int, y: int):
-        """
-        点击指定坐标
-        :param x: x坐标
-        :param y: y坐标
-        """
-        self.d.click(x, y)
-
-    def click_xpath(self, xpath: str):
-        """
-        点击指定xpath
-        """
-        el = self.d.xpath(xpath).get()
-        if el:
-            el.click()
-        else:
-            logging.warning(f"未找到元素: {xpath}")
-
-    def to_next_swipe(self):
-        """
-        向上滑动一屏
-        """
-        width, height = self.get_screen_size()
-        # 从屏幕下方向上滑动到顶部
-        self.d.swipe(width // 2, height * 0.8, width // 2, height * 0.2, duration=0.1)  # 向上滑动
-
-    def get_screen_size(self):
-        """
-        获取屏幕尺寸,宽度和高度
-        """
-        self.width, self.height = self.d.window_size()
-        logging.info(f"屏幕尺寸: {self.width}x{self.height}")
-        return self.width, self.height
-
-    def drag_slider_ext(self, start_x: int, start_y: int, end_x: int, end_y: int, steps: int = 50):
-        """
-        精确拖动滑块
-        :param start_x: 起始x坐标
-        :param start_y: 起始y坐标
-        :param end_x: 结束x坐标
-        :param end_y: 结束y坐标
-        :param steps: 步数,值越大滑动越平滑
-        """
-        self.d.swipe_ext(start_x, start_y, end_x, end_y, steps)
-
-    def add_point(self, point=None):
-        """
-        添加坐标点
-        point = {
-                "name": "",
-                "x": 0,
-                "y": 0,
-                "desc": "",
-                "xpath": ""
-            }
-        """
-        logging.info("保存坐标点: %s", point)
-        self._points[point['name']] = point
-
-    def add_func(self, func):
-        """
-        添加坐标点采集函数
-        """
-        self._func.append(func)
-
-    def save_point(self):
-        """
-        保存坐标
-        """
-        self.to_top_swipe()
-        self.d.sleep(2)
-
-        for func in self._func:
-            func()
-
-        __tmp__ = {}
-        for k, v in self._points.items():
-            __tmp__[k] = v
-
-        with open(self.point_path, "w", encoding="utf-8") as f:
-            json.dump(__tmp__, f, ensure_ascii=False, indent=4)
-
-    def get_point(self, info: dict):
-        """
-        获取坐标点
-        info 数据结构
-        {
-            "name": "btn_mairu_kaiduo",
-            "desc": "买入/开多",
-            "xpath": '//*[@content-desc="买入/开多"]'
-
-        """
-        el = self.d.xpath(info['xpath']).get()
-        x, y = el.center()
-        self.add_point({
-            "name": info['name'],
-            "x": x,
-            "y": y,
-            "desc": info['desc'],
-            "xpath": info['xpath'],
-        })
-
-        return x, y

+ 450 - 0
plat/base/base_control.py

@@ -0,0 +1,450 @@
+# 定义抽象类
+import json
+import logging
+import tempfile
+from abc import ABC, abstractmethod
+from typing import List
+import tkinter as tk
+from tkinter import ttk
+
+import uiautomator2 as u2
+from uiautomator2.exceptions import LaunchUiAutomationError
+
+
+class BaseControl(ABC):
+    # ctx_dict = {
+    #     'connect': 1,
+    #     'platform': 2,
+    # }
+    connect_dict = {
+
+    }
+
+    app_pkg = {
+        'com.niocpeed.dna': 'DeepCoin',
+    }
+
+    def __init__(self, name: str, ctx: int = 2):
+        # 名称
+        self.name = name
+        self.ctx = ctx
+
+        pass
+
+    def init_adb(self, commands: List[str], *args, **kwargs):
+        """
+        连接设备
+        使用 python shell执行命令
+        """
+        pass
+
+    def print_log(self, msg):
+        logging.info(f'打印信息 {msg}')
+
+    def connect_adb(self, serial: str):
+        """
+        连接设备
+        """
+        logging.info(f'连接设[备{self.name}]:{serial}', )
+        try:
+            d = u2.connect(serial)
+            # self.enable_click_monitor()
+
+            d.shell('settings put system pointer_location 1')
+            # d.debug = True
+            return d
+        except LaunchUiAutomationError as e:
+            print(f"uiautomator2 连接失败: {e}")
+
+    def re_connect(self):
+        """
+        重新建立连接
+        :return:
+        """
+        pass
+
+    # def enable_click_monitor(self):
+    #     """
+    #     启用点击监控,在屏幕上显示点击位置
+    #     """
+    #     # self.d.settings['operation_delay'] = (0.5, 0.5)  # 增加操作延迟以便观察
+    #     # self.d.debug = True
+    #     self.d.toast.show('点击监控已启用')  # 显示提示
+    #
+    #     # 确保有悬浮窗权限
+    #     # self.d.set_fastinput_ime(True)  # 启用ime
+    #     # self.d.show_float_window(True)  # 显示悬浮窗
+    #
+    #     # 可选:打开开发者选项中的"指针位置"
+    #     self.d.shell('settings put system pointer_location 1')
+
+    def loadding(self, top, func):
+        """
+        等待加载完成
+        :return:
+        """
+        # 创建加载指示器
+        loading_window = tk.Toplevel(top)
+        loading_window.title("连接中")
+        loading_window.geometry("200x100")
+        loading_window.transient(top)  # 设置为模态
+        loading_window.grab_set()  # 设置为模态
+        loading_window.overrideredirect(True)  # 移除窗口边框和按钮
+        # 相对于父窗口居中显示
+        window_width = loading_window.winfo_reqwidth()
+        window_height = loading_window.winfo_reqheight()
+        parent_x = top.winfo_rootx()
+        parent_y = top.winfo_rooty()
+        parent_width = top.winfo_width()
+        parent_height = top.winfo_height()
+        position_right = parent_x + (parent_width - window_width) // 2
+        position_down = parent_y + (parent_height - window_height) // 2
+        loading_window.geometry(f"+{position_right}+{position_down}")
+        loading_label = ttk.Label(loading_window, text="连接中...", padding=20)
+        loading_label.pack(expand=True)
+
+        def thread_task():
+            try:
+                func()
+            finally:
+                # 在主线程中销毁加载指示器
+                top.after(0, lambda: [loading_window.grab_release(), loading_window.destroy()])
+
+        import threading
+        thread = threading.Thread(target=thread_task)
+        # thread.daemon = True  # 设置为守护线程,这样主程序退出时线程会自动结束
+        thread.start()
+        pass
+
+
+class AbsControl(BaseControl):
+
+    def __init__(self, name: str, ctx: int = 2, *args, **kwargs):
+        """
+        # :param : 设备序列号。 例如 127.0.0.1:6555
+        #     可以通过 `adb devices`  获取
+        """
+        # u2.logger.setLevel(logging.DEBUG)
+
+        super().__init__(name)
+
+        self.ctx = ctx
+
+        self.info = {}
+        #
+        self._d = None
+
+        # 屏幕高度
+        self.height = 0
+        # 屏幕宽度
+        self.width = 0
+
+        self._points = {}
+
+        self.point_path = 'point.json'
+
+        self._func = []
+
+        self._log_func = None
+
+    def d(self, serial: str = ''):
+        """
+        连接设备
+        """
+        if self._d is not None:
+            return self._d
+
+        if serial in self.connect_dict:
+            self.info = self.connect_dict[serial]
+            self._d = self.info['d']
+        else:
+            self._d = u2.connect(serial)
+
+        return self._d
+
+    def re_connect(self):
+
+        pass
+
+    # @abstractmethod
+    # def get_app_package_name(self):
+    #     return ""
+
+    def prevent_sleep(self):
+        """
+        防止设备休眠
+        """
+        self.d().wake()
+        self.d().screen_on()
+        self.d().unlock()
+
+    def screenshot(self):
+        """
+        截图
+        """
+        # 获取系统/tmp路径
+        tmp = tempfile.gettempdir()
+        return self.d().screenshot(f"{tmp}/{self.name}.png")
+
+    def to_top_swipe(self, sleep=0.1, times=2):
+        """
+        滑动到屏幕最顶部,通过多次滑动确保到达顶部
+        :param sleep: 滑动后等待时间
+        :param times: 滑动次数
+        :return:
+        """
+        width, height = self.get_screen_size()
+        # 循环滑动直到无法继续滑动
+        for _ in range(times):
+            self.d().swipe(width // 2, height * 0.8, width // 2, height)  # 向上滑动
+            # 短暂等待确保滑动完成
+            self.d().sleep(sleep)
+
+    def click_point(self, x: int, y: int):
+        """
+        点击指定坐标
+        :param x: x坐标
+        :param y: y坐标
+        """
+        self.d().click(x, y)
+
+    def click_xpath(self, xpath: str):
+        """
+        点击指定xpath
+        """
+        el = self.d().xpath(xpath).get()
+        if el:
+            el.click()
+        else:
+            logging.warning(f"未找到元素: {xpath}")
+
+    def to_next_swipe(self, sleep=0.1):
+        """
+        向上滑动一屏
+        """
+        width, height = self.get_screen_size()
+        # 从屏幕下方向上滑动到顶部
+        self.d().swipe(width // 2, height * 0.8, width // 2, height * 0.2)  # 向上滑动
+
+        # 短暂等待确保滑动完成
+        self.d().sleep(sleep)
+
+    def get_screen_size(self):
+        """
+        获取屏幕尺寸,宽度和高度
+        """
+        self.width, self.height = self.d().window_size()
+        logging.info(f"屏幕尺寸: {self.width}x{self.height}")
+        return self.width, self.height
+
+    def drag_slider_ext(self, start_x: int, start_y: int, end_x: int, end_y: int, steps: int = 50):
+        """
+        精确拖动滑块
+        :param start_x: 起始x坐标
+        :param start_y: 起始y坐标
+        :param end_x: 结束x坐标
+        :param end_y: 结束y坐标
+        :param steps: 步数,值越大滑动越平滑
+        """
+        self.d().swipe_ext(start_x, start_y, end_x, end_y, steps)
+
+    def add_point(self, point=None):
+        """
+        添加坐标点
+        point = {
+                "name": "",
+                "x": 0,
+                "y": 0,
+                "desc": "",
+                "xpath": ""
+            }
+        """
+        logging.info("保存坐标点: %s", point)
+        self._points[point['name']] = point
+
+    def print_log(self, msg):
+        """
+        打印日志
+        """
+        logging.info(f'>>111>{msg}')
+        print(f'>222>>{msg},{self._log_func}')
+        if self._log_func:
+            self._log_func(msg)
+
+    def add_func(self, func):
+        """
+        添加坐标点采集函数
+        """
+        self._func.append(func)
+
+    def set_log_func(self, func):
+        """
+        添加日志函数
+        """
+        self._log_func = func
+
+    def save_point(self):
+        """
+        保存坐标
+        """
+        self.to_top_swipe()
+        self.d().sleep(2)
+
+        for func in self._func:
+            func()
+
+        __tmp__ = {}
+        for k, v in self._points.items():
+            __tmp__[k] = v
+
+        with open(self.point_path, "w", encoding="utf-8") as f:
+            json.dump(__tmp__, f, ensure_ascii=False, indent=4)
+
+    def get_point(self, info: dict):
+        """
+        获取坐标点
+     :param info:  数据结构
+        {
+            "name": "btn_mairu_kaiduo",
+            "desc": "买入/开多",
+            "xpath": '//*[@content-desc="买入/开多"]'
+        }
+        :return: x, y, el
+        """
+        x, y, el = self.get_point_by_xpath(info['xpath'])
+
+        self.add_point({
+            "name": info['name'],
+            "x": x,
+            "y": y,
+            "desc": info['desc'],
+            "xpath": info['xpath'],
+        })
+        return x, y, el
+
+    def get_point_by_xpath(self, xpath: str):
+        """
+        :param xpath: xpath
+        获取坐标第一个匹配的点
+        info 数据结构
+        :return: x, y, el
+        """
+        el = self.d().xpath(xpath).get()
+        x, y = el.center()
+
+        return x, y, el
+
+    def get_points_by_xpath(self, xpath: str):
+        """
+        获取所有坐标点
+        info 数据结构
+        """
+        els = self.d().xpath(xpath).all()
+
+        items = []
+
+        for el in els:
+            x, y = el.center()
+            items.append((x, y, el))
+
+        return items
+
+    def check_element_exists(self, xpath: str, timeout: float = 0.05) -> bool:
+        """
+        判断指定XPath的元素是否存在
+
+        :param xpath: 元素的XPath
+        :param timeout: 超时时间(秒)
+        :return: 是否存在
+        """
+        self.d().sleep(timeout)
+        return self.d().xpath(xpath).exists
+
+    def input_xpath(self, xpath: str, text: str, clear: bool = True):
+        """
+        给指定xpath的输入框输入文本
+
+        :param xpath: 输入框的xpath
+        :param text: 要输入的文本
+        :param clear: 输入前是否清空原有内容
+        """
+        element = self.d().xpath(xpath).get()
+        if element:
+            if clear:
+                element.text.set_text("")  # 清空原有内容
+            element.set_text(text)  # 输入新内容
+        else:
+            logging.warning(f"未找到输入框: {xpath}")
+
+    def input_by_position(self, x: int, y: int, text: str, clear: bool = True):
+        """
+        通过坐标点击并在输入框中输入文本
+
+        :param x: 输入框x坐标
+        :param y: 输入框y坐标
+        :param text: 要输入的文本
+        :param clear: 是否清空原有内容
+        """
+        self.click_point(x, y)  # 先点击获取焦点
+        if clear:
+            self.d().clear_text()  # 清空原有内容
+        self.d().send_keys(text)  # 输入新文本
+
+    @abstractmethod
+    def event_f1(self):
+        """
+        F1  开仓界面,仓位滑竿百分比(30-60)
+        """
+        pass
+
+    @abstractmethod
+    def event_f2(self):
+        """
+        F2 确认开仓,开多 限价职中间数值
+        检查撤销限价委托单
+        """
+        pass
+
+    @abstractmethod
+    def event_f3(self):
+        """
+        F3 平仓界面 平空,仓位滑竿百分比(90-100)确认开仓,限价职中间数值
+        """
+        pass
+
+    @abstractmethod
+    def event_f4(self):
+        """
+        F4   确认平仓 平多 限价取中间数值 检查撤销限价委托单
+        """
+        pass
+
+    @abstractmethod
+    def event_f5(self):
+        """
+        F5 开仓界面 仓位滑竿百分比(30-60)
+        """
+        pass
+
+    @abstractmethod
+    def event_f6(self):
+        """
+        F6 确认开仓, 开空 限价值中间数值
+        检查撤销限价委托单
+        """
+        pass
+
+    @abstractmethod
+    def event_f7(self):
+        """
+        F7    平仓界面二仓位滑竿百分比(90-100)
+        """
+        pass
+
+    @abstractmethod
+    def event_f8(self):
+        """
+        F8 确认平仓, 平空 限价职中间数值
+        检查撤销限价委托单
+        """
+        pass

+ 0 - 147
plat/deepcoin/point_collection.py

@@ -1,147 +0,0 @@
-# from utils.point_utils import UiFactory
-import logging
-
-from plat.base.abs_ui import AbsUi
-
-
-class PointCollection(AbsUi):
-
-    def __init__(self, serial: str):
-        super().__init__(serial)
-        self.point_path = '../../assets/point/deepcoin_point.json'
-        self.add_func(self.btn_jiao_yi)
-        self.add_func(self.btn_mairu_kaiduo)
-        self.add_func(self.btn_shijia_quanping)
-
-    def btn_jiao_yi(self):
-        return self.get_point({
-            "name": "btn_jiao_yi",
-            "desc": "交易按钮",
-            "xpath": '//*[@content-desc="交易"]'
-        })
-
-    def btn_mairu_kaiduo(self):
-        return self.get_point({
-            "name": "btn_mairu_kaiduo",
-            "desc": "买入/开多",
-            "xpath": '//*[@content-desc="买入/开多"]'
-        })
-
-    def btn_shijia_quanping(self):
-        self.to_next_swipe()
-        return self.get_point({
-            "name": "btn_shijia_quanping",
-            "desc": "买入/开多",
-            "xpath": '//*[@content-desc="市价全平"]'
-        })
-
-    def btn_kaichang(self):
-        return self.get_point({
-            "name": "btn_kaichang",
-            "desc": "开仓",
-            "xpath": '//*[@content-desc="开仓"]'
-        })
-
-    def slider_baozhengjin(self, offset=0, sleep=0.1):
-        """
-        保证金滑块
-           :param sleep 休眠
-           :param offset 价格偏移量 默认取50% x=368 每偏移69 向下多一个 偏移-69向上多一个 取值范围 [-2,2]
-        坐标: 0% 230  25% 299  50% 368  75% 437  100% 506
-
-        """
-        self.to_top_swipe()
-        self.d.sleep(0.1)
-        x, y = self.btn_mairu_kaiduo()
-
-        x1 = x + offset * 69
-        y1 = y - 140
-        logging.info(f"开多坐标: ({x},{y})")
-        logging.info(f"保证金50%坐标: ({x1},{y1})")
-
-        self.click_point(x1, y1)
-        self.d.sleep(sleep)
-
-    def click_kaicang(self):
-        """
-        开仓
-        """
-        self.click_xpath('//*[@content-desc="开仓"]')
-
-    def click_pingchang(self, sleep=0.1):
-        """
-        开仓
-        :param sleep: 等待时间
-        """
-        self.click_xpath('//*[@content-desc="平仓"]')
-        self.d.sleep(sleep)
-
-    def select_weituo_xianjia(self):
-        """
-        选择限价委托
-
-        """
-        x, y = self.btn_kaichang()
-        logging.info(f"开仓按钮坐标: ({x},{y})")
-        x1 = x + 50
-        y1 = y + 55
-        logging.info(f"选择委托框: ({x1},{y1})")
-        self.click_point(x1, y1)
-        x2 = x1
-        y2 = y1 + 100
-        self.d.sleep(0.2)
-        logging.info(f"选择限价委托: ({x2},{y2})")
-        self.click_point(x2, y2)
-
-    def click_price_red(self, offset=0):
-        """
-        点击价格 开多 平空, 点击红色价格
-
-        :param offset 价格偏移量 默认取第5个, 每偏移20 向下多一个 偏移-20 向上多一个 取值范围 [-4,4]
-        """
-        self.select_weituo_xianjia()
-        self.d.sleep(0.1)
-
-        x1 = 50
-        y1 = 330 + offset * 20
-        logging.info(f"选择价格: ({x1},{y1})")
-        self.click_point(x1, y1)
-
-    def click_price_green(self, offset=0):
-        """
-        点击价格 开空 平多, 点击红色价格
-        :param offset 价格偏移量 默认取第5个, 每偏移20 向下多一个,偏移-20 向上多一个
-        """
-
-        self.select_weituo_xianjia()
-
-        self.d.sleep(0.1)
-
-        x1 = 50
-        y1 = 330 + offset
-        logging.info(f"选择价格: ({x1},{y1})")
-        self.click_point(x1, y1)
-
-    def click_mairu_kaiduo(self):
-        """
-        买入开多
-        """
-        self.click_xpath('//*[@content-desc="买入/开多"]')
-
-    def click_mairu_pingkong(self):
-        """
-        买入平空
-        """
-        self.click_xpath('//*[@content-desc="买入/平空"]')
-
-    def click_maichu_kaikong(self):
-        """
-        卖出开空
-        """
-        self.click_xpath('//*[@content-desc="卖出/开空"]')
-
-    def click_maichu_pingduo(self):
-        """
-        卖出平多
-        """
-        self.click_xpath('//*[@content-desc="卖出/平多"]')

+ 340 - 0
plat/deepcoin_control.py

@@ -0,0 +1,340 @@
+# from utils.point_utils import UiFactory
+import logging
+
+from plat.base.base_control import AbsControl
+
+
+class DeepCoinControl(AbsControl):
+
+    def get_app_package_name(self):
+        return 'com.niocpeed.dna'
+
+    def __init__(self, serial: str, *args, **kwargs):
+        super().__init__(serial)
+
+        self.package_name = 'com.niocpeed.dna'
+
+        self.point_path = '../../assets/point/deepcoin_point.json'
+        self.add_func(self.btn_jiao_yi)
+        self.add_func(self.btn_mairu_kaiduo)
+        self.add_func(self.btn_shijia_quanping)
+
+    def btn_jiao_yi(self):
+        return self.get_point({
+            "name": "btn_jiao_yi",
+            "desc": "交易按钮",
+            "xpath": '//*[@content-desc="交易"]'
+        })
+
+    def btn_mairu_kaiduo(self):
+        return self.get_point({
+            "name": "btn_mairu_kaiduo",
+            "desc": "买入/开多",
+            "xpath": '//*[@content-desc="买入/开多"]'
+        })
+
+    def btn_mairu_pingkong(self):
+        return self.get_point({
+            "name": "btn_mairu_pingkong",
+            "desc": "买入/平空",
+            "xpath": '//*[@content-desc="买入/平空"]'
+        })
+
+    def btn_shijia_quanping(self):
+        self.to_next_swipe()
+        return self.get_point({
+            "name": "btn_shijia_quanping",
+            "desc": "买入/开多",
+            "xpath": '//*[@content-desc="市价全平"]'
+        })
+
+    def btn_kaichang(self):
+        return self.get_point({
+            "name": "btn_kaichang",
+            "desc": "开仓",
+            "xpath": '//*[@content-desc="开仓"]'
+        })
+
+    def btn_gengdan(self):
+        """
+        跟单(n) 按钮 坐标
+        """
+        return self.get_point({
+            "name": "btn_gengdan",
+            "desc": "跟单",
+            "xpath": '//*[starts-with(@content-desc, "跟单(")]'
+        })
+
+    def btn_weituo(self):
+        """
+        委托(n) 按钮 坐标
+        FIXME 委托按钮点击2次回出现切换委托界面
+
+        """
+        return self.get_point({
+            "name": "btn_weituo",
+            "desc": "委托",
+            "xpath": '//*[starts-with(@content-desc, "委托(")]'
+        })
+
+    def btn_yijian_chedan(self):
+        """
+        一键撤单按钮
+        """
+        return self.get_point({
+            "name": "btn_yijian_chedan",
+            "desc": "一键撤单",
+            "xpath": '//*[@content-desc="一键撤单"]'
+        })
+
+    def slider_baozhengjin_kaicang(self, offset=0, sleep=0.1):
+        """
+      开仓情况  保证金滑块
+           :param sleep 休眠
+           :param offset 价格偏移量 默认取50% x=368 每偏移69 向下多一个 偏移-69向上多一个 取值范围 [-2,2]
+        坐标: 0% 230  25% 299  50% 368  75% 437  100% 506
+        :return: 买入的按钮实例
+        """
+        # self.to_top_swipe()
+        # self.d.sleep(0.1)
+
+        # 基于买入按钮相对计算坐标
+        x, y, btn = self.btn_mairu_kaiduo()
+
+        x1 = x + offset * 69
+        y1 = y - 155
+        logging.info(f"开多坐标: ({x},{y})")
+        logging.info(f"保证金50%坐标: ({x1},{y1})")
+
+        self.click_point(x1, y1)
+        self.d.sleep(sleep)
+
+        return btn
+
+    def slider_baozhengjin_pingcang(self, offset=0, sleep=0.1):
+        """
+            平仓情况  保证金滑块
+           :param sleep 休眠
+           :param offset 价格偏移量 默认取50% x=368 每偏移69 向下多一个 偏移-69向上多一个 取值范围 [-2,2]
+        坐标: 0% 230  25% 299  50% 368  75% 437  100% 506
+        :return: 买入的按钮实例
+        """
+
+        # 基于买入按钮相对计算坐标
+        x, y, btn = self.btn_mairu_pingkong()
+        x1 = x + offset * 69
+        y1 = y - 70
+        logging.info(f"开多坐标: ({x},{y})")
+        logging.info(f"保证金50%坐标: ({x1},{y1})")
+
+        self.click_point(x1, y1)
+        self.d.sleep(sleep)
+
+        return btn
+
+    def click_kaicang(self):
+        """
+        开仓
+        """
+        self.click_xpath('//*[@content-desc="开仓"]')
+
+    def click_pingchang(self, sleep=0.1):
+        """
+        开仓
+        :param sleep: 等待时间
+        """
+        self.click_xpath('//*[@content-desc="平仓"]')
+        self.d.sleep(sleep)
+
+    def select_kaicang_weituo_xianjia(self):
+        """
+        开仓选择限价委托
+        """
+        x, y, _ = self.btn_kaichang()
+        logging.info(f"开仓按钮坐标: ({x},{y})")
+        x1 = x + 100
+        y1 = y + 70
+        logging.info(f"选择委托框: ({x1},{y1})")
+        self.click_point(x1, y1)
+        x2 = x1
+        y2 = y1 + 150
+        self.d.sleep(0.2)
+        logging.info(f"选择限价委托: ({x2},{y2})")
+        self.click_point(x2, y2)
+
+    def click_price_red(self, offset=0):
+        """
+        点击价格 开多 平空, 点击红色价格
+
+        :param offset 价格偏移量 默认取第5个, 每偏移20 向下多一个 偏移-20 向上多一个 取值范围 [-4,4]
+        """
+
+        x1 = 50
+        y1 = 450 + offset * 20
+        logging.info(f"红色部分选择价格: ({x1},{y1})")
+        self.click_point(x1, y1)
+
+    def click_price_green(self, offset=0):
+        """
+        点击价格 开空 平多, 点击红色价格
+        :param offset 价格偏移量 默认取第5个, 每偏移20 向下多一个,偏移-20 向上多一个
+        """
+
+        # self.select_kaicang_weituo_xianjia()
+        #
+        # self.d.sleep(0.1)
+
+        x1 = 50
+        y1 = 515 + offset
+        logging.info(f"绿色部分选择价格: ({x1},{y1})")
+        self.click_point(x1, y1)
+
+    def click_mairu_kaiduo(self):
+        """
+        买入开多
+        """
+        self.click_xpath('//*[@content-desc="买入/开多"]')
+        self.d.sleep(0.1)
+        # 弹出了确认框
+        if self.check_element_exists('//*[@content-desc="开仓确认"]'):
+            logging.info("弹出了确认框")
+            self.click_xpath('//*[@content-desc="确认"]')
+
+    def click_mairu_pingkong(self):
+        """
+        买入平空
+        """
+        self.click_xpath('//*[@content-desc="买入/平空"]')
+
+    def click_maichu_kaikong(self):
+        """
+        卖出开空
+        """
+        self.click_xpath('//*[@content-desc="卖出/开空"]')
+
+        self.d.sleep(0.1)
+        # 弹出了确认框
+        if self.check_element_exists('//*[@content-desc="开仓确认"]'):
+            logging.info("弹出了确认框")
+            self.click_xpath('//*[@content-desc="确认"]')
+
+    def click_maichu_pingduo(self):
+        """
+        卖出平多
+        """
+        self.click_xpath('//*[@content-desc="卖出/平多"]')
+
+    def click_yijian_chedan(self):
+        """
+        一键撤单
+        如果有滑动 ,回导致第一个坐标不准,点不上。 所以要提前滑动,确保第一个坐标点得上
+        """
+        self.click_xpath('//*[starts-with(@content-desc, "跟单(")]')
+        self.d.sleep(0.1)
+        self.click_xpath('//*[starts-with(@content-desc, "委托(")]')
+        self.d.sleep(0.1)
+
+        b = self.check_element_exists('//*[starts-with(@content-desc, "全部委托(")]')
+        logging.info("是否弹出了选择框: %s", b)
+
+        if b:
+            self.click_xpath('//*[starts-with(@content-desc, "全部委托(")]')
+            self.d.sleep(0.2)
+
+        self.click_xpath('//*[@content-desc="一键撤单"]')
+        self.d.sleep(0.1)
+
+        x, y, _ = self.get_point({
+            "name": "btn_yijian_chedan",
+            "desc": "撤销掉全部委托",
+            "xpath": '//*[@content-desc="撤销掉全部委托"]'
+        })
+        logging.info(f"撤销掉全部委托: ({x},{y})")
+        #  相对坐标 撤销掉全部委托 点击确定。
+        x1 = x + 80
+        y1 = y + 80
+        logging.info(f"撤销掉全 确定按钮: ({x1},{y1})")
+        self.click_point(x1, y1)
+
+    def text_xiadan_shuliang(self, text):
+        """
+        设置 下单数量
+        """
+        x, y, _ = self.get_point({
+            "name": "btn_baozhengjin",
+            "desc": "保证金",
+            "xpath": '//*[@content-desc="保证金"]'
+        })
+        logging.info(f"保证金坐标: ({x},{y})"'')
+        x1 = x - 130
+        y1 = y + 50
+        self.input_by_position(x1, y1, str(text), True)
+
+    def event_f1(self):
+        self.click_kaicang()
+        self.slider_baozhengjin_kaicang()
+        pass
+
+    def event_f2(self):
+        self.to_top_swipe(sleep=0.2)
+        self.click_kaicang()
+        self.select_kaicang_weituo_xianjia()
+        self.d.sleep(0.1)
+
+        self.click_price_red()
+
+        self.text_xiadan_shuliang(3)
+        # self.slider_baozhengjin_kaicang()
+
+        self.click_mairu_kaiduo()
+        pass
+
+    def event_f3(self):
+        self.to_top_swipe(sleep=0.2)
+        self.click_pingchang()
+        self.slider_baozhengjin_pingcang(offset=1)
+        pass
+
+    def event_f4(self):
+        self.to_top_swipe(sleep=0.2)
+        self.click_pingchang()
+        self.select_kaicang_weituo_xianjia()
+        self.click_price_green()
+        # self.text_xiadan_shuliang(3)
+        self.slider_baozhengjin_pingcang(offset=1)
+        self.click_maichu_pingduo()
+        pass
+
+    def event_f5(self):
+        self.to_top_swipe(sleep=0.2)
+        self.click_kaicang()
+        self.slider_baozhengjin_kaicang()
+        pass
+
+    def event_f6(self):
+        self.to_top_swipe(sleep=0.1)
+        self.click_kaicang()
+        self.select_kaicang_weituo_xianjia()
+        self.click_price_red()
+        self.slider_baozhengjin_kaicang()
+        self.click_maichu_kaikong()
+        pass
+
+    def event_f7(self):
+        self.to_top_swipe(sleep=0.1)
+        self.click_pingchang()
+        self.slider_baozhengjin_pingcang(offset=2)
+        pass
+
+    def event_f8(self):
+        self.to_top_swipe(sleep=0.2)
+
+        self.click_pingchang()
+
+        self.click_price_red()
+
+        # self.text_xiadan_shuliang(3)
+        self.slider_baozhengjin_pingcang(offset=2)
+
+        self.click_mairu_pingkong()
+        pass

+ 79 - 0
plat/settings_control.py

@@ -0,0 +1,79 @@
+import logging
+import subprocess
+from typing import List
+
+import tkinter as tk
+from adbutils import adb_path
+
+from plat.base.base_control import BaseControl
+
+
+class SettingsControl(BaseControl):
+
+    def __init__(self, name: str, ctx: int = 1):
+
+        """
+        设置相关的控制器
+        :param name:
+        """
+        super().__init__(name)
+
+        self.ctx = ctx
+
+    def init_adb(self, commands: List[str], *args, **kwargs):
+
+        def func():
+            adb = adb_path()
+            logging.info(f'adb_path:{adb}')
+            log_widget = args[0] if args else None
+            _commons = list(commands)
+            _commons.append(f'adb devices')
+            for command in _commons:
+                command = command.strip()
+                if command == '':
+                    continue
+                logging.info(f'初始化[{self.name}]:{command}')
+                try:
+                    cmd = command.split(' ')
+                    if cmd[1] == 'connect':
+                        self._init_connect(cmd)
+                    cmd[0] = adb
+                    logging.info(f"执行命令:{cmd}")
+                    result = subprocess.run(cmd, capture_output=True, text=True, check=True)
+                    logging.info(f"命令执行结果:\n{result.stdout}")
+                    if log_widget:
+                        log_widget.insert(tk.END, f"命令【{command}】执行成功:\n{result.stdout}")
+
+
+
+                except subprocess.CalledProcessError as cpe:
+                    logging.info(f"命令 '{command}' 执行失败: {cpe}")
+                    if log_widget:
+                        log_widget.insert(tk.END, f"{cpe}\n")
+
+        top = kwargs['ui']
+
+        if top:
+            self.loadding(top, func)
+        else:
+            func()
+
+    def _init_connect(self, cmds: List[str]):
+        """
+        初始化一些连接,将信息保存到 connect_dict
+        :param cmds: 要执行的命令行 ['adb', 'connect', '127.0.0.1:64079']
+        :return:
+        """
+        cmd = list(cmds).pop()
+        d = self.connect_adb(cmd)
+        info = d.info
+        logging.info(f'设备信息{info}')
+        self.connect_dict[cmd] = {
+            'd': d,
+            'info': info,
+            'device': cmd,
+            'status': 'online',
+            'pkg': self.app_pkg[info['currentPackageName']],
+            'name': str(d.shell('settings get global device_name').output).strip(),
+        }
+        pass

+ 6 - 5
pyproject.toml

@@ -4,18 +4,17 @@ version = "0.1.0"
 description = ""
 authors = ["fzxs88 <fzxs88@yeah.net>"]
 readme = "README.md"
+package-mode = false
 
 [tool.poetry.dependencies]
 python = "~3.10"
 fastapi = "^0.115.8"
-uiautomator2 = "^3.2.8"
-weditor = "^0.7.3"
+uiautomator2 = "3.2.9"
 uvicorn = "^0.34.0"
 numpy = "^2.2.4"
-opencv-python = "^4.11.0.86"
-wxpython = "^4.2.2"
 pyinstaller = "^6.12.0"
-
+opencv-python = "^4.11.0.86"
+schedule = "^1.2.2"
 
 [[tool.poetry.source]]
 name = "tsinghua"
@@ -23,9 +22,11 @@ url = "https://pypi.tuna.tsinghua.edu.cn/simple"
 priority = "explicit"
 
 
+
 [tool.poetry.group.dev.dependencies]
 pyinstaller = "^6.12.0"
 pytest = "^8.3.5"
+weditor = "^0.7.3"
 
 [build-system]
 requires = ["poetry-core"]

+ 867 - 0
test/deepcoin/a.XML

@@ -0,0 +1,867 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
+<hierarchy rotation="0">
+    <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.android.systemui" content-desc="" checkable="false" checked="false" clickable="false"
+          enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[0,0][540,36]"
+          drawing-order="0" hint="" display-id="0">
+        <node index="0" text="" resource-id="com.android.systemui:id/status_bar_launch_animation_container"
+              class="android.widget.FrameLayout" package="com.android.systemui" content-desc="" checkable="false" checked="false"
+              clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+              password="false" selected="false" visible-to-user="true" bounds="[0,0][540,36]" drawing-order="1" hint=""
+              display-id="0"/>
+        <node index="1" text="" resource-id="com.android.systemui:id/status_bar_container" class="android.widget.FrameLayout" package="com.android.systemui" content-desc=""
+              checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+              selected="false" visible-to-user="true" bounds="[0,0][540,36]" drawing-order="2" hint="" display-id="0">
+            <node index="0" text="" resource-id="com.android.systemui:id/status_bar" class="android.widget.FrameLayout" package="com.android.systemui" content-desc=""
+                  checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                  selected="false" visible-to-user="true" bounds="[0,0][540,36]" drawing-order="1" hint="" display-id="0">
+                <node index="0" text="" resource-id="com.android.systemui:id/status_bar_contents" class="android.widget.LinearLayout" package="com.android.systemui" content-desc=""
+                      checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                      password="false" selected="false" visible-to-user="true" bounds="[0,0][510,36]" drawing-order="2" hint="" display-id="0">
+                    <node index="0" text="" resource-id="com.android.systemui:id/status_bar_start_side_container" class="android.widget.FrameLayout" package="com.android.systemui"
+                          content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                          long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[12,0][255,36]" drawing-order="1" hint="" display-id="0">
+                        <node index="0" text="" resource-id="com.android.systemui:id/status_bar_start_side_content" class="android.widget.FrameLayout"
+                              package="com.android.systemui" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false"
+                              scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[12,0][135,36]" drawing-order="1" hint=""
+                              display-id="0">
+                            <node index="0" text="" resource-id="com.android.systemui:id/status_bar_start_side_except_heads_up" class="android.widget.LinearLayout"
+                                  package="com.android.systemui" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
+                                  focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[12,0][135,36]"
+                                  drawing-order="2" hint="" display-id="0">
+                                <node index="0" text="03:22" resource-id="com.android.systemui:id/clock"
+                                      class="android.widget.TextView" package="com.android.systemui" content-desc="03:22"
+                                      checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
+                                      focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                                      visible-to-user="true" bounds="[12,0][69,36]" drawing-order="2" hint="" display-id="0"/>
+                                <node index="1" text="" resource-id="com.android.systemui:id/notification_icon_area" class="android.widget.FrameLayout"
+                                      package="com.android.systemui" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
+                                      focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[69,0][135,36]"
+                                      drawing-order="4" hint="" display-id="0">
+                                    <node index="0" text="" resource-id="com.android.systemui:id/notificationIcons" class="android.view.ViewGroup" package="com.android.systemui"
+                                          content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                                          long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[69,0][135,36]" drawing-order="1" hint=""
+                                          display-id="0">
+                                        <node index="0" text="" resource-id="" class="android.widget.ImageView" package="com.android.systemui"
+                                              content-desc="Android 系统通知:AndroidWifi 的连接受限" checkable="false" checked="false" clickable="false"
+                                              enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                                              selected="false" visible-to-user="true" bounds="[69,0][102,36]" drawing-order="1" hint="" display-id="0"/>
+                                        <node index="1" text="" resource-id="" class="android.widget.ImageView" package="com.android.systemui"
+                                              content-desc="Android 系统通知:已安装证书授权服务" checkable="false" checked="false" clickable="false" enabled="true"
+                                              focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                              bounds="[102,0][135,36]" drawing-order="2" hint="" display-id="0"/>
+                                    </node>
+
+                                </node>
+
+                            </node>
+
+                        </node>
+
+                    </node>
+
+                    <node index="1" text="" resource-id="com.android.systemui:id/status_bar_end_side_container" class="android.widget.FrameLayout" package="com.android.systemui"
+                          content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                          long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[255,0][498,36]" drawing-order="3" hint="" display-id="0">
+                        <node index="0" text="" resource-id="com.android.systemui:id/status_bar_end_side_content" class="android.widget.LinearLayout" package="com.android.systemui"
+                              content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                              long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[427,0][498,36]" drawing-order="1" hint="" display-id="0">
+                            <node index="0" text="" resource-id="com.android.systemui:id/system_icons" class="android.widget.LinearLayout" package="com.android.systemui"
+                                  content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                                  long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[427,0][498,36]" drawing-order="2" hint="" display-id="0">
+
+                                <node index="0" text="" resource-id="com.android.systemui:id/statusIcons" class="android.widget.LinearLayout" package="com.android.systemui"
+                                      content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                                      long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[427,0][486,36]" drawing-order="1" hint=""
+                                      display-id="0">
+                                    <node index="0" text="" resource-id="com.android.systemui:id/wifi_combo" class="android.widget.FrameLayout" package="com.android.systemui"
+                                          content-desc="WLAN 信号满格。,未连接到互联网" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
+                                          focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                          bounds="[427,1][454,34]" drawing-order="13" hint="" display-id="0">
+                                        <node index="0" text="" resource-id="com.android.systemui:id/wifi_group" class="android.widget.LinearLayout" package="com.android.systemui"
+                                              content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false"
+                                              scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[431,1][454,34]"
+                                              drawing-order="1" hint="" display-id="0">
+                                            <node index="0" text="" resource-id="com.android.systemui:id/wifi_combo" class="android.widget.FrameLayout"
+                                                  package="com.android.systemui" content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
+                                                  focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                                                  visible-to-user="true" bounds="[431,6][454,29]" drawing-order="2" hint="" display-id="0">
+                                                <node index="0" text=""
+                                                      resource-id="com.android.systemui:id/wifi_signal"
+                                                      class="android.widget.ImageView"
+                                                      package="com.android.systemui"
+                                                      content-desc=""
+                                                      checkable="false"
+                                                      checked="false"
+                                                      clickable="false"
+                                                      enabled="true"
+                                                      focusable="false"
+                                                      focused="false"
+                                                      scrollable="false"
+                                                      long-clickable="false"
+                                                      password="false"
+                                                      selected="false"
+                                                      visible-to-user="true"
+                                                      bounds="[431,6][454,29]"
+                                                      drawing-order="1" hint=""
+                                                      display-id="0"/>
+                                            </node>
+
+                                        </node>
+
+                                    </node>
+
+                                    <node index="1" text="" resource-id="com.android.systemui:id/mobile_combo" class="android.widget.FrameLayout" package="com.android.systemui"
+                                          content-desc="手机信号满格。" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false"
+                                          scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[454,1][477,34]"
+                                          drawing-order="15" hint="" display-id="0">
+                                        <node index="0" text="" resource-id="com.android.systemui:id/mobile_group" class="android.widget.LinearLayout"
+                                              package="com.android.systemui" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
+                                              focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                              bounds="[454,1][477,34]" drawing-order="1" hint="" display-id="0">
+                                            <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.android.systemui" content-desc=""
+                                                  checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                                                  long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[454,6][477,29]" drawing-order="4" hint=""
+                                                  display-id="0">
+                                                <node index="0" text="" resource-id="com.android.systemui:id/mobile_signal" class="android.widget.ImageView"
+                                                      package="com.android.systemui" content-desc="" checkable="false" checked="false" clickable="false"
+                                                      enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                                                      password="false" selected="false" visible-to-user="true" bounds="[454,6][477,29]" drawing-order="1"
+                                                      hint="" display-id="0"/>
+                                            </node>
+
+                                        </node>
+
+                                    </node>
+
+                                </node>
+
+                                <node index="1" text="" resource-id="com.android.systemui:id/battery" class="android.widget.LinearLayout" package="com.android.systemui"
+                                      content-desc="正在充电,已完成百分之 100。" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false"
+                                      scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[486,0][498,36]" drawing-order="2"
+                                      hint="" display-id="0">
+                                    <node index="0" text="" resource-id="" class="android.widget.ImageView" package="com.android.systemui"
+                                          content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false"
+                                          focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                                          visible-to-user="true" bounds="[486,7][498,27]" drawing-order="1" hint="" display-id="0"/>
+                                </node>
+
+                            </node>
+
+                        </node>
+
+                    </node>
+
+                </node>
+
+            </node>
+
+        </node>
+
+    </node>
+
+    <node index="0" text="" resource-id="com.android.systemui:id/navigation_bar_frame" class="android.widget.FrameLayout" package="com.android.systemui" content-desc=""
+          checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+          selected="false" visible-to-user="true" bounds="[0,888][540,960]" drawing-order="0" hint="" display-id="0">
+        <node index="0" text="" resource-id="com.android.systemui:id/navigation_bar_view" class="android.widget.FrameLayout" package="com.android.systemui" content-desc=""
+              checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+              selected="false" visible-to-user="true" bounds="[0,888][540,960]" drawing-order="1" hint="" display-id="0">
+            <node index="0" text="" resource-id="com.android.systemui:id/navigation_inflater" class="android.widget.FrameLayout" package="com.android.systemui" content-desc=""
+                  checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                  selected="false" visible-to-user="true" bounds="[0,888][540,960]" drawing-order="1" hint="" display-id="0">
+                <node index="0" text="" resource-id="com.android.systemui:id/horizontal" class="android.widget.FrameLayout" package="com.android.systemui" content-desc=""
+                      checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                      password="false" selected="false" visible-to-user="true" bounds="[0,888][540,960]" drawing-order="1" hint="" display-id="0">
+                    <node index="0" text="" resource-id="com.android.systemui:id/nav_buttons" class="android.widget.FrameLayout" package="com.android.systemui" content-desc=""
+                          checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                          password="false" selected="false" visible-to-user="true" bounds="[0,888][540,960]" drawing-order="1" hint="" display-id="0">
+                        <node index="0" text="" resource-id="com.android.systemui:id/ends_group" class="android.widget.LinearLayout" package="com.android.systemui" content-desc=""
+                              checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                              password="false" selected="false" visible-to-user="true" bounds="[0,888][540,960]" drawing-order="1" hint="" display-id="0">
+                            <node index="0"
+                                  text=""
+                                  resource-id=""
+                                  class="android.widget.RelativeLayout"
+                                  package="com.android.systemui"
+                                  content-desc=""
+                                  checkable="false"
+                                  checked="false"
+                                  clickable="false"
+                                  enabled="true"
+                                  focusable="false"
+                                  focused="false"
+                                  scrollable="false"
+                                  long-clickable="false"
+                                  password="false"
+                                  selected="false"
+                                  visible-to-user="true"
+                                  bounds="[0,888][67,960]"
+                                  drawing-order="1"
+                                  hint=""
+                                  display-id="0"/>
+
+                            <node index="1" text="" resource-id="" class="android.widget.RelativeLayout" package="com.android.systemui" content-desc="" checkable="false"
+                                  checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                                  selected="false" visible-to-user="true" bounds="[67,888][202,960]" drawing-order="2" hint="" display-id="0">
+                                <node index="0" text=""
+                                      resource-id="com.android.systemui:id/back"
+                                      class="android.widget.ImageView"
+                                      package="com.android.systemui"
+                                      content-desc="返回"
+                                      checkable="false"
+                                      checked="false"
+                                      clickable="true"
+                                      enabled="true"
+                                      focusable="true"
+                                      focused="false"
+                                      scrollable="false"
+                                      long-clickable="false"
+                                      password="false"
+                                      selected="false"
+                                      visible-to-user="true"
+                                      bounds="[74,888][194,960]"
+                                      drawing-order="1" hint=""
+                                      display-id="0"/>
+                            </node>
+
+                            <node index="2" text="" resource-id="" class="android.widget.RelativeLayout" package="com.android.systemui" content-desc="" checkable="false"
+                                  checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                                  selected="false" visible-to-user="true" bounds="[337,888][472,960]" drawing-order="4" hint="" display-id="0">
+                                <node index="0" text=""
+                                      resource-id="com.android.systemui:id/recent_apps"
+                                      class="android.widget.ImageView"
+                                      package="com.android.systemui"
+                                      content-desc="概览"
+                                      checkable="false"
+                                      checked="false"
+                                      clickable="true"
+                                      enabled="true"
+                                      focusable="true"
+                                      focused="false"
+                                      scrollable="false"
+                                      long-clickable="false"
+                                      password="false"
+                                      selected="false"
+                                      visible-to-user="true"
+                                      bounds="[344,888][464,960]"
+                                      drawing-order="1" hint=""
+                                      display-id="0"/>
+                            </node>
+                            <node index="3" text="" resource-id="" class="android.widget.RelativeLayout" package="com.android.systemui" content-desc="" checkable="false"
+                                  checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                                  selected="false" visible-to-user="true" bounds="[472,888][540,960]" drawing-order="5" hint="" display-id="0"/>
+                        </node>
+
+                        <node index="1" text="" resource-id="com.android.systemui:id/center_group" class="android.widget.LinearLayout" package="com.android.systemui"
+                              content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                              long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[210,888][330,960]" drawing-order="2" hint="" display-id="0">
+                            <node index="0" text="" resource-id="com.android.systemui:id/home" class="android.widget.ImageView" package="com.android.systemui"
+                                  content-desc="主屏幕" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
+                                  long-clickable="true" password="false" selected="false" visible-to-user="true" bounds="[210,888][330,960]" drawing-order="1" hint=""
+                                  display-id="0"/>
+                        </node>
+
+                    </node>
+
+                </node>
+
+            </node>
+
+        </node>
+
+    </node>
+
+    <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false" clickable="false"
+          enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+          bounds="[0,0][540,960]" drawing-order="0" hint="" display-id="0">
+        <node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false" clickable="false"
+              enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+              bounds="[0,0][540,960]" drawing-order="1" hint="" display-id="0">
+            <node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                  clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                  visible-to-user="true" bounds="[0,0][540,960]" drawing-order="2" hint="" display-id="0">
+                <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                      clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                      visible-to-user="true" bounds="[0,0][540,960]" drawing-order="1" hint="" display-id="0">
+                    <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                          clickable="false" enabled="true" focusable="true" focused="true" scrollable="false" long-clickable="false" password="false" selected="false"
+                          visible-to-user="true" bounds="[0,0][540,960]" drawing-order="1" hint="" display-id="0">
+                        <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                              clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                              visible-to-user="true" bounds="[0,0][540,960]" drawing-order="0" hint="" display-id="0">
+                            <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                                  clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                                  visible-to-user="true" bounds="[0,0][540,960]" drawing-order="0" hint="" display-id="0">
+                                <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                                      clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                                      visible-to-user="true" bounds="[0,0][540,960]" drawing-order="0" hint="" display-id="0">
+                                    <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                                          clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                                          selected="false" visible-to-user="true" bounds="[0,0][540,960]" drawing-order="0" hint="" display-id="0">
+                                        <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false"
+                                              checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                                              password="false" selected="false" visible-to-user="true" bounds="[0,0][540,821]" drawing-order="0" hint="" display-id="0">
+                                            <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false"
+                                                  checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                                                  password="false" selected="false" visible-to-user="true" bounds="[0,0][540,821]" drawing-order="0" hint="" display-id="0">
+                                                <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false"
+                                                      checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                                                      password="false" selected="false" visible-to-user="true" bounds="[0,0][540,821]" drawing-order="0" hint="" display-id="0">
+                                                    <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false"
+                                                          checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                                                          long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[0,0][540,89]" drawing-order="0"
+                                                          hint="" display-id="0">
+                                                        <node index="0" text="" resource-id="" class="android.widget.ImageView"
+                                                              package="com.niocpeed.dna" content-desc="MOODENGUSDT 永续&#10;-1.46%" checkable="false"
+                                                              checked="false" clickable="true" enabled="true" focusable="true" focused="false"
+                                                              scrollable="false" long-clickable="true" password="false" selected="false"
+                                                              visible-to-user="true" bounds="[24,43][444,82]" drawing-order="0" hint=""
+                                                              display-id="0"/>
+                                                        <node NAF="true" index="1" text="" resource-id=""
+                                                              class="android.widget.ImageView" package="com.niocpeed.dna"
+                                                              content-desc="" checkable="false" checked="false"
+                                                              clickable="true" enabled="true" focusable="true"
+                                                              focused="false" scrollable="false" long-clickable="false"
+                                                              password="false" selected="false" visible-to-user="true"
+                                                              bounds="[468,36][540,89]" drawing-order="0" hint=""
+                                                              display-id="0"/>
+                                                    </node>
+
+                                                    <node index="1" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false"
+                                                          checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false"
+                                                          long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[0,89][540,821]" drawing-order="0"
+                                                          hint="" display-id="0">
+                                                        <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc=""
+                                                              checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false"
+                                                              scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                              bounds="[0,89][540,821]" drawing-order="0" hint="" display-id="0">
+                                                            <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc=""
+                                                                  checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false"
+                                                                  scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                  bounds="[0,89][540,821]" drawing-order="0" hint="" display-id="0">
+                                                                <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc=""
+                                                                      checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false"
+                                                                      scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                      bounds="[0,89][540,774]" drawing-order="0" hint="" display-id="0">
+                                                                    <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc=""
+                                                                          checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false"
+                                                                          scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                          bounds="[0,89][540,774]" drawing-order="0" hint="" display-id="0">
+                                                                        <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc=""
+                                                                              checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false"
+                                                                              scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                              bounds="[0,89][540,774]" drawing-order="0" hint="" display-id="0">
+                                                                            <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                  content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
+                                                                                  focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                                                                                  selected="false" visible-to-user="true" bounds="[0,89][540,774]" drawing-order="0" hint=""
+                                                                                  display-id="0">
+                                                                                <node index="0" text="" resource-id="" class="android.widget.ScrollView" package="com.niocpeed.dna"
+                                                                                      content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
+                                                                                      focusable="false" focused="false" scrollable="true" long-clickable="false" password="false"
+                                                                                      selected="false" visible-to-user="true" bounds="[0,89][540,774]" drawing-order="0" hint=""
+                                                                                      display-id="0">
+                                                                                    <node index="0" text="" resource-id="" class="android.view.View"
+                                                                                          package="com.niocpeed.dna" content-desc="0.03961&#10;85.34K"
+                                                                                          checkable="false" checked="false" clickable="true" enabled="true"
+                                                                                          focusable="true" focused="false" scrollable="false"
+                                                                                          long-clickable="false" password="false" selected="false"
+                                                                                          visible-to-user="true" bounds="[11,89][208,99]" drawing-order="0"
+                                                                                          hint="" display-id="0"/>
+                                                                                    <node index="1" text="" resource-id=""
+                                                                                          class="android.view.View"
+                                                                                          package="com.niocpeed.dna"
+                                                                                          content-desc="0.03960&#10;42.24K"
+                                                                                          checkable="false" checked="false"
+                                                                                          clickable="true" enabled="true"
+                                                                                          focusable="true" focused="false"
+                                                                                          scrollable="false"
+                                                                                          long-clickable="false"
+                                                                                          password="false" selected="false"
+                                                                                          visible-to-user="true"
+                                                                                          bounds="[11,99][208,125]"
+                                                                                          drawing-order="0" hint=""
+                                                                                          display-id="0"/>
+                                                                                    <node index="2"
+                                                                                          text=""
+                                                                                          resource-id=""
+                                                                                          class="android.view.View"
+                                                                                          package="com.niocpeed.dna"
+                                                                                          content-desc="0.03959&#10;28.32K"
+                                                                                          checkable="false"
+                                                                                          checked="false"
+                                                                                          clickable="true"
+                                                                                          enabled="true"
+                                                                                          focusable="true"
+                                                                                          focused="false"
+                                                                                          scrollable="false"
+                                                                                          long-clickable="false"
+                                                                                          password="false"
+                                                                                          selected="false"
+                                                                                          visible-to-user="true"
+                                                                                          bounds="[11,125][208,150]"
+                                                                                          drawing-order="0"
+                                                                                          hint=""
+                                                                                          display-id="0"/>
+                                                                                    <node index="3" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                          content-desc="0.03958&#10;97.22K" checkable="false" checked="false" clickable="true"
+                                                                                          enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                          long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                          bounds="[11,150][208,176]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node
+                                                                                            index="4" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                            content-desc="0.03957&#10;103.37K" checkable="false" checked="false" clickable="true"
+                                                                                            enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                            long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                            bounds="[11,176][208,201]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node index="5"
+                                                                                          text=""
+                                                                                          resource-id=""
+                                                                                          class="android.view.View"
+                                                                                          package="com.niocpeed.dna"
+                                                                                          content-desc="资金费率&#10;-0.045842%"
+                                                                                          checkable="false"
+                                                                                          checked="false"
+                                                                                          clickable="true"
+                                                                                          enabled="true"
+                                                                                          focusable="true"
+                                                                                          focused="false"
+                                                                                          scrollable="false"
+                                                                                          long-clickable="true"
+                                                                                          password="false"
+                                                                                          selected="false"
+                                                                                          visible-to-user="true"
+                                                                                          bounds="[23,213][196,233]"
+                                                                                          drawing-order="0"
+                                                                                          hint=""
+                                                                                          display-id="0"/>
+                                                                                    <node index="6" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                          content-desc="距结算" checkable="false" checked="false" clickable="false"
+                                                                                          enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                          long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                          bounds="[23,233][62,252]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node
+                                                                                            index="7" text="" resource-id="" class="android.widget.ImageView"
+                                                                                            package="com.niocpeed.dna" content-desc="0.00001" checkable="false" checked="false"
+                                                                                            clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                            long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                            bounds="[21,258][105,290]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node index="8"
+                                                                                          text=""
+                                                                                          resource-id=""
+                                                                                          class="android.view.View"
+                                                                                          package="com.niocpeed.dna"
+                                                                                          content-desc="00:37:41"
+                                                                                          checkable="false"
+                                                                                          checked="false"
+                                                                                          clickable="false"
+                                                                                          enabled="true"
+                                                                                          focusable="true"
+                                                                                          focused="false"
+                                                                                          scrollable="false"
+                                                                                          long-clickable="false"
+                                                                                          password="false"
+                                                                                          selected="false"
+                                                                                          visible-to-user="true"
+                                                                                          bounds="[144,233][196,252]"
+                                                                                          drawing-order="0"
+                                                                                          hint=""
+                                                                                          display-id="0"/>
+                                                                                    <node index="9" text="" resource-id="" class="android.widget.ImageView"
+                                                                                          package="com.niocpeed.dna" content-desc="默认" checkable="false" checked="false"
+                                                                                          clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                          long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                          bounds="[113,258][197,290]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node
+                                                                                            index="10" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                            content-desc="可开" checkable="false" checked="false" clickable="true" enabled="true"
+                                                                                            focusable="true" focused="false" scrollable="false" long-clickable="true"
+                                                                                            password="false" selected="false" visible-to-user="true" bounds="[218,89][249,110]"
+                                                                                            drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node index="11" text="" resource-id=""
+                                                                                          class="android.view.View"
+                                                                                          package="com.niocpeed.dna"
+                                                                                          content-desc="814.56 USDT"
+                                                                                          checkable="false" checked="false"
+                                                                                          clickable="false" enabled="true"
+                                                                                          focusable="true" focused="false"
+                                                                                          scrollable="false"
+                                                                                          long-clickable="false"
+                                                                                          password="false" selected="false"
+                                                                                          visible-to-user="true"
+                                                                                          bounds="[425,89][519,110]"
+                                                                                          drawing-order="0" hint=""
+                                                                                          display-id="0"/>
+                                                                                    <node index="12"
+                                                                                          text=""
+                                                                                          resource-id=""
+                                                                                          class="android.view.View"
+                                                                                          package="com.niocpeed.dna"
+                                                                                          content-desc="预估强平价"
+                                                                                          checkable="false"
+                                                                                          checked="false"
+                                                                                          clickable="true"
+                                                                                          enabled="true"
+                                                                                          focusable="true"
+                                                                                          focused="false"
+                                                                                          scrollable="false"
+                                                                                          long-clickable="true"
+                                                                                          password="false"
+                                                                                          selected="false"
+                                                                                          visible-to-user="true"
+                                                                                          bounds="[218,110][296,134]"
+                                                                                          drawing-order="0"
+                                                                                          hint=""
+                                                                                          display-id="0"/>
+                                                                                    <node index="13" text="" resource-id="" class="android.widget.Button"
+                                                                                          package="com.niocpeed.dna" content-desc="买入/开多" checkable="false" checked="false"
+                                                                                          clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                          long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                          bounds="[218,138][519,185]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node
+                                                                                            index="14" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                            content-desc="可开" checkable="false" checked="false" clickable="true" enabled="true"
+                                                                                            focusable="true" focused="false" scrollable="false" long-clickable="true"
+                                                                                            password="false" selected="false" visible-to-user="true" bounds="[218,192][249,216]"
+                                                                                            drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node index="15" text="" resource-id=""
+                                                                                          class="android.view.View"
+                                                                                          package="com.niocpeed.dna"
+                                                                                          content-desc="814.55 USDT"
+                                                                                          checkable="false" checked="false"
+                                                                                          clickable="false" enabled="true"
+                                                                                          focusable="true" focused="false"
+                                                                                          scrollable="false"
+                                                                                          long-clickable="false"
+                                                                                          password="false" selected="false"
+                                                                                          visible-to-user="true"
+                                                                                          bounds="[425,192][519,216]"
+                                                                                          drawing-order="0" hint=""
+                                                                                          display-id="0"/>
+                                                                                    <node index="16"
+                                                                                          text=""
+                                                                                          resource-id=""
+                                                                                          class="android.view.View"
+                                                                                          package="com.niocpeed.dna"
+                                                                                          content-desc="预估强平价"
+                                                                                          checkable="false"
+                                                                                          checked="false"
+                                                                                          clickable="true"
+                                                                                          enabled="true"
+                                                                                          focusable="true"
+                                                                                          focused="false"
+                                                                                          scrollable="false"
+                                                                                          long-clickable="true"
+                                                                                          password="false"
+                                                                                          selected="false"
+                                                                                          visible-to-user="true"
+                                                                                          bounds="[218,216][296,240]"
+                                                                                          drawing-order="0"
+                                                                                          hint=""
+                                                                                          display-id="0"/>
+                                                                                    <node index="17" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                          content-desc="0.03848" checkable="false" checked="false" clickable="false"
+                                                                                          enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                          long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                          bounds="[461,110][519,134]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node
+                                                                                            index="18" text="" resource-id="" class="android.widget.Button"
+                                                                                            package="com.niocpeed.dna" content-desc="卖出/开空" checkable="false" checked="false"
+                                                                                            clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                            long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                            bounds="[218,245][519,291]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node
+                                                                                            index="19" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                            content-desc="0.04080" checkable="false" checked="false" clickable="false"
+                                                                                            enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                            long-clickable="false" password="false" selected="false" visible-to-user="true"
+                                                                                            bounds="[461,216][519,240]" drawing-order="0" hint="" display-id="0"/>
+                                                                                    <node index="20" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                          content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
+                                                                                          focusable="false" focused="false" scrollable="false" long-clickable="false"
+                                                                                          password="false" selected="false" visible-to-user="true" bounds="[0,407][540,774]"
+                                                                                          drawing-order="0" hint="" display-id="0">
+                                                                                        <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                              content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
+                                                                                              focusable="false" focused="false" scrollable="true" long-clickable="false"
+                                                                                              password="false" selected="false" visible-to-user="true" bounds="[0,407][540,774]"
+                                                                                              drawing-order="0" hint="" display-id="0">
+                                                                                            <node index="0" text="" resource-id="" class="android.view.View"
+                                                                                                  package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                                                                                                  clickable="false" enabled="true" focusable="false" focused="false"
+                                                                                                  scrollable="false" long-clickable="false" password="false" selected="false"
+                                                                                                  visible-to-user="true" bounds="[0,407][540,774]" drawing-order="0" hint=""
+                                                                                                  display-id="0">
+                                                                                                <node index="0" text="" resource-id="" class="android.view.View"
+                                                                                                      package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                                                                                                      clickable="false" enabled="true" focusable="false" focused="false"
+                                                                                                      scrollable="false" long-clickable="false" password="false" selected="false"
+                                                                                                      visible-to-user="true" bounds="[0,407][540,774]" drawing-order="0" hint=""
+                                                                                                      display-id="0">
+                                                                                                    <node index="0" text="" resource-id="" class="android.view.View"
+                                                                                                          package="com.niocpeed.dna" content-desc="" checkable="false"
+                                                                                                          checked="false" clickable="false" enabled="true" focusable="false"
+                                                                                                          focused="false" scrollable="false" long-clickable="false" password="false"
+                                                                                                          selected="false" visible-to-user="true" bounds="[0,407][540,774]"
+                                                                                                          drawing-order="0" hint="" display-id="0">
+                                                                                                        <node index="0" text="" resource-id="" class="android.widget.ImageView"
+                                                                                                              package="com.niocpeed.dna" content-desc="数据为空" checkable="false"
+                                                                                                              checked="false" clickable="false" enabled="true" focusable="true"
+                                                                                                              focused="false" scrollable="false" long-clickable="false"
+                                                                                                              password="false" selected="false" visible-to-user="true"
+                                                                                                              bounds="[0,407][540,620]" drawing-order="0" hint="" display-id="0">
+                                                                                                            <node index="0" text="" resource-id="" class="android.view.View"
+                                                                                                                  package="com.niocpeed.dna" content-desc="交易指南"
+                                                                                                                  checkable="false" checked="false" clickable="true"
+                                                                                                                  enabled="true" focusable="true" focused="false"
+                                                                                                                  scrollable="false" long-clickable="true" password="false"
+                                                                                                                  selected="false" visible-to-user="true"
+                                                                                                                  bounds="[165,585][244,620]" drawing-order="0" hint=""
+                                                                                                                  display-id="0"/>
+                                                                                                            <node index="1" text="" resource-id=""
+                                                                                                                  class="android.view.View"
+                                                                                                                  package="com.niocpeed.dna"
+                                                                                                                  content-desc="跟单交易"
+                                                                                                                  checkable="false" checked="false"
+                                                                                                                  clickable="true" enabled="true"
+                                                                                                                  focusable="true" focused="false"
+                                                                                                                  scrollable="false"
+                                                                                                                  long-clickable="true"
+                                                                                                                  password="false" selected="false"
+                                                                                                                  visible-to-user="true"
+                                                                                                                  bounds="[296,585][375,620]"
+                                                                                                                  drawing-order="0" hint=""
+                                                                                                                  display-id="0"/>
+                                                                                                        </node>
+
+                                                                                                    </node>
+
+                                                                                                </node>
+
+                                                                                            </node>
+
+                                                                                        </node>
+
+                                                                                    </node>
+
+                                                                                </node>
+
+                                                                                <node index="1" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                      content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
+                                                                                      focusable="false" focused="false" scrollable="false" long-clickable="false" password="false"
+                                                                                      selected="false" visible-to-user="true" bounds="[21,326][488,359]" drawing-order="0" hint=""
+                                                                                      display-id="0">
+                                                                                    <node index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                                          content-desc="" checkable="false" checked="false" clickable="false" enabled="true"
+                                                                                          focusable="false" focused="false" scrollable="false" long-clickable="false"
+                                                                                          password="false" selected="false" visible-to-user="true" bounds="[21,326][488,359]"
+                                                                                          drawing-order="0" hint="" display-id="0">
+                                                                                        <node index="0" text="" resource-id=""
+                                                                                              class="android.widget.ImageView"
+                                                                                              package="com.niocpeed.dna"
+                                                                                              content-desc="持仓(0)"
+                                                                                              checkable="false" checked="false"
+                                                                                              clickable="true" enabled="true"
+                                                                                              focusable="true" focused="false"
+                                                                                              scrollable="false"
+                                                                                              long-clickable="false" password="false"
+                                                                                              selected="false" visible-to-user="true"
+                                                                                              bounds="[21,326][120,359]"
+                                                                                              drawing-order="0" hint=""
+                                                                                              display-id="0"/>
+                                                                                        <node index="1"
+                                                                                              text=""
+                                                                                              resource-id=""
+                                                                                              class="android.widget.ImageView"
+                                                                                              package="com.niocpeed.dna"
+                                                                                              content-desc="委托(0)"
+                                                                                              checkable="false"
+                                                                                              checked="false"
+                                                                                              clickable="true"
+                                                                                              enabled="true"
+                                                                                              focusable="true"
+                                                                                              focused="false"
+                                                                                              scrollable="false"
+                                                                                              long-clickable="false"
+                                                                                              password="false"
+                                                                                              selected="false"
+                                                                                              visible-to-user="true"
+                                                                                              bounds="[120,326][221,359]"
+                                                                                              drawing-order="0"
+                                                                                              hint=""
+                                                                                              display-id="0"/>
+                                                                                        <node index="2" text="" resource-id="" class="android.view.View"
+                                                                                              package="com.niocpeed.dna" content-desc="跟单(0)" checkable="false"
+                                                                                              checked="false" clickable="true" enabled="true" focusable="true" focused="false"
+                                                                                              scrollable="false" long-clickable="false" password="false" selected="false"
+                                                                                              visible-to-user="true" bounds="[221,326][310,359]" drawing-order="0" hint=""
+                                                                                              display-id="0"/>
+                                                                                        <node index="3" text="" resource-id=""
+                                                                                              class="android.view.View" package="com.niocpeed.dna"
+                                                                                              content-desc="策略(0)" checkable="false" checked="false"
+                                                                                              clickable="true" enabled="true" focusable="true"
+                                                                                              focused="false" scrollable="false"
+                                                                                              long-clickable="false" password="false" selected="false"
+                                                                                              visible-to-user="true" bounds="[310,326][378,359]"
+                                                                                              drawing-order="0" hint="" display-id="0"/>
+                                                                                    </node>
+
+                                                                                </node>
+                                                                                <node index="2" text="" resource-id="" class="android.widget.ImageView"
+                                                                                      package="com.niocpeed.dna" content-desc="币种" checkable="false" checked="false"
+                                                                                      clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                      long-clickable="true" password="false" selected="false" visible-to-user="true"
+                                                                                      bounds="[115,359][162,405]" drawing-order="0" hint="" display-id="0"/>
+                                                                                <node NAF="true"
+                                                                                      index="3"
+                                                                                      text=""
+                                                                                      resource-id=""
+                                                                                      class="android.view.View"
+                                                                                      package="com.niocpeed.dna"
+                                                                                      content-desc=""
+                                                                                      checkable="false"
+                                                                                      checked="false"
+                                                                                      clickable="true"
+                                                                                      enabled="true"
+                                                                                      focusable="true"
+                                                                                      focused="false"
+                                                                                      scrollable="false"
+                                                                                      long-clickable="true"
+                                                                                      password="false"
+                                                                                      selected="false"
+                                                                                      visible-to-user="true"
+                                                                                      bounds="[44,362][110,401]"
+                                                                                      drawing-order="0"
+                                                                                      hint=""
+                                                                                      display-id="0"/>
+                                                                                <node NAF="true" index="4" text="" resource-id="" class="android.widget.ImageView"
+                                                                                      package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                                                                                      clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                      long-clickable="true" password="false" selected="false" visible-to-user="true"
+                                                                                      bounds="[21,373][39,391]" drawing-order="0" hint="" display-id="0"/>
+                                                                                <node index="5"
+                                                                                      text=""
+                                                                                      resource-id=""
+                                                                                      class="android.view.View"
+                                                                                      package="com.niocpeed.dna"
+                                                                                      content-desc="只看当前:"
+                                                                                      checkable="false"
+                                                                                      checked="false"
+                                                                                      clickable="false"
+                                                                                      enabled="true"
+                                                                                      focusable="true"
+                                                                                      focused="false"
+                                                                                      scrollable="false"
+                                                                                      long-clickable="false"
+                                                                                      password="false"
+                                                                                      selected="false"
+                                                                                      visible-to-user="true"
+                                                                                      bounds="[44,374][110,390]"
+                                                                                      drawing-order="0"
+                                                                                      hint=""
+                                                                                      display-id="0"/>
+                                                                                <node NAF="true" index="6" text="" resource-id="" class="android.widget.ImageView"
+                                                                                      package="com.niocpeed.dna" content-desc="" checkable="false" checked="false"
+                                                                                      clickable="true" enabled="true" focusable="true" focused="false" scrollable="false"
+                                                                                      long-clickable="true" password="false" selected="false" visible-to-user="true"
+                                                                                      bounds="[488,316][540,343]" drawing-order="0" hint="" display-id="0"/>
+                                                                                <node index="7"
+                                                                                      text=""
+                                                                                      resource-id=""
+                                                                                      class="android.view.View"
+                                                                                      package="com.niocpeed.dna"
+                                                                                      content-desc="一键撤单"
+                                                                                      checkable="false"
+                                                                                      checked="false"
+                                                                                      clickable="true"
+                                                                                      enabled="true"
+                                                                                      focusable="true"
+                                                                                      focused="false"
+                                                                                      scrollable="false"
+                                                                                      long-clickable="true"
+                                                                                      password="false"
+                                                                                      selected="false"
+                                                                                      visible-to-user="true"
+                                                                                      bounds="[449,365][540,399]"
+                                                                                      drawing-order="0"
+                                                                                      hint=""
+                                                                                      display-id="0"/>
+
+                                                                            </node>
+
+                                                                        </node>
+
+                                                                    </node>
+
+                                                                </node>
+                                                                <node NAF="true" index="1" text="" resource-id="" class="android.widget.ImageView" package="com.niocpeed.dna"
+                                                                      content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true"
+                                                                      focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                                                                      visible-to-user="true" bounds="[410,677][506,749]" drawing-order="0" hint="" display-id="0"/>
+                                                                <node
+                                                                        index="2" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                                        content-desc="MOODENGUSDT 永续 图表" checkable="false" checked="false" clickable="true" enabled="true"
+                                                                        focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false"
+                                                                        visible-to-user="true" bounds="[0,776][482,821]" drawing-order="0" hint="" display-id="0"/>
+                                                                <node
+                                                                        NAF="true" index="3" text="" resource-id="" class="android.widget.ImageView" package="com.niocpeed.dna"
+                                                                        content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true"
+                                                                        focused="false" scrollable="false" long-clickable="false" password="false" selected="false"
+                                                                        visible-to-user="true" bounds="[482,780][530,816]" drawing-order="0" hint="" display-id="0"/>
+                                                            </node>
+
+                                                        </node>
+
+                                                    </node>
+
+                                                </node>
+
+                                            </node>
+
+                                        </node>
+
+                                        <node index="1" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="" checkable="false"
+                                              checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false"
+                                              password="false" selected="false" visible-to-user="true" bounds="[0,821][540,960]" drawing-order="0" hint="" display-id="0">
+                                            <node
+                                                    index="0" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="首页" checkable="false"
+                                                    checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true"
+                                                    password="false" selected="false" visible-to-user="true" bounds="[0,821][108,888]" drawing-order="0" hint="" display-id="0"/>
+                                            <node index="1" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="行情" checkable="false"
+                                                  checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true"
+                                                  password="false" selected="false" visible-to-user="true" bounds="[108,821][216,888]" drawing-order="0" hint="" display-id="0"/>
+                                            <node index="2" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna" content-desc="交易" checkable="false"
+                                                  checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true"
+                                                  password="false" selected="false" visible-to-user="true" bounds="[216,821][324,888]" drawing-order="0" hint=""
+                                                  display-id="0"/>
+                                            <node index="3" text="" resource-id="" class="android.view.View" package="com.niocpeed.dna"
+                                                  content-desc="跟单" checkable="false" checked="false" clickable="true" enabled="true"
+                                                  focusable="true" focused="false" scrollable="false" long-clickable="true" password="false"
+                                                  selected="false" visible-to-user="true" bounds="[324,821][432,888]" drawing-order="0" hint=""
+                                                  display-id="0"/>
+                                            <node index="4" text="" resource-id="" class="android.view.View"
+                                                  package="com.niocpeed.dna" content-desc="资产" checkable="false"
+                                                  checked="false" clickable="true" enabled="true" focusable="true"
+                                                  focused="false" scrollable="false" long-clickable="true" password="false"
+                                                  selected="false" visible-to-user="true" bounds="[432,821][540,888]"
+                                                  drawing-order="0" hint="" display-id="0"/>
+                                        </node>
+
+                                    </node>
+
+                                </node>
+
+                            </node>
+
+                        </node>
+
+                    </node>
+
+                </node>
+
+            </node>
+
+        </node>
+
+    </node>
+
+</hierarchy>

File diff suppressed because it is too large
+ 3 - 0
test/deepcoin/a.json


+ 83 - 83
test/deepcoin/deepcoin_test.py

@@ -1,87 +1,87 @@
-import time
-
-import uiautomator2 as u2
-
-# 连接到设备,默认连接第一个设备,如果有多个设备可以指定序列号
-d = u2.connect('127.0.0.1:6555')
-
-# 获取所有运行的APP
-running_apps = d.app_list_running()
-print("安装列表:", running_apps)
-# 如果app没有启动, 启动APP
-if "com.niocpeed.dna" not in running_apps:
-    print("com niocpeed.dna 重新启动")
-    d.app_start("com.niocpeed.dna")
-    # tab 交易按钮
-btn_jy = d.xpath('//*[@content-desc="交易"]')
-# btn_jy.click()
-# 交易方式选择
-btn_sel = d.xpath('//*[@content-desc="USDT合约"]')
-if btn_sel.exists:
-    btn_sel.click()
-
-# 设置委托
-input_weituo = d.xpath('//*[@content-desc="最优"]')
-# 设置数量
-input_num = d.xpath('//android.widget.ScrollView/android.view.View[18]/android.widget.EditText[1]')
-btn_buy = d(description="买入/开多")
-
-buy_x, buy_y = btn_buy.center()
-
-start1 = time.time()
-input_weituo.click()
-end1 = time.time()
-print("点击:最优委托 操作耗时:", end1 - start1)
-
+# import time
+#
+# import uiautomator2 as u2
+#
+# # 连接到设备,默认连接第一个设备,如果有多个设备可以指定序列号
+# d = u2.connect('127.0.0.1:6555')
+#
+# # 获取所有运行的APP
+# running_apps = d.app_list_running()
+# print("安装列表:", running_apps)
+# # 如果app没有启动, 启动APP
+# if "com.niocpeed.dna" not in running_apps:
+#     print("com niocpeed.dna 重新启动")
+#     d.app_start("com.niocpeed.dna")
+#     # tab 交易按钮
+# btn_jy = d.xpath('//*[@content-desc="交易"]')
+# # btn_jy.click()
+# # 交易方式选择
+# btn_sel = d.xpath('//*[@content-desc="USDT合约"]')
+# if btn_sel.exists:
+#     btn_sel.click()
+#
+# # 设置委托
+# input_weituo = d.xpath('//*[@content-desc="最优"]')
+# # 设置数量
+# input_num = d.xpath('//android.widget.ScrollView/android.view.View[18]/android.widget.EditText[1]')
+# btn_buy = d(description="买入/开多")
+#
+# buy_x, buy_y = btn_buy.center()
+#
 # start1 = time.time()
-# input_weituo.set_text("0.114")
+# input_weituo.click()
 # end1 = time.time()
-# print("设置:操作耗时:", end1 - start1)
-start1 = time.time()
-input_num.click()
-end1 = time.time()
-print("点击数量:操作耗时:", end1 - start1)
+# print("点击:最优委托 操作耗时:", end1 - start1)
+#
+# # start1 = time.time()
+# # input_weituo.set_text("0.114")
+# # end1 = time.time()
+# # print("设置:操作耗时:", end1 - start1)
 # start1 = time.time()
-# input_num.set_text("40")
+# input_num.click()
 # end1 = time.time()
-# print("设置数量:操作耗时:", end1 - start1)
-
-# for i in range(10):
-#     # 初始化点击按钮
-#     start = time.time()
-#     # start1 = time.time()
-#     # input_weituo.click()
-#     # end1 = time.time()
-#     # print("点击:最优委托 操作耗时:", end1 - start1)
-#     #
-#     # # start1 = time.time()
-#     # # input_weituo.set_text("0.114")
-#     # # end1 = time.time()
-#     # # print("设置:操作耗时:", end1 - start1)
-#     # start1 = time.time()
-#     # input_num.click()
-#     # end1 = time.time()
-#     # print("点击:操作耗时:", end1 - start1)
-#     # start1 = time.time()
-#     # input_num.set_text("40")
-#     # end1 = time.time()
-#     # print("设置:操作耗时:", end1 - start1)
-#     start1 = time.time()
-#     #  直接点击   xpath直接点击
-#     # btn_buy.click()
-#     # 比上面的快50毫秒
-#     # d.click(1078, 1094)  # ui点击 指定坐标
-#     # 比上面的快100毫秒  直接调用shell 指定坐标
-#     d.shell(f"input tap {buy_x} {buy_y}")
-#     end1 = time.time()
-#     print("点击下单:操作耗时:", end1 - start1)
-#     end = time.time()
-#     # print("点击整体:操作耗时:", end - start)
-#     time.sleep(5)
-
-# 给开仓确认的弹框 选中 下次不在提醒,能减少时间
-# d(description="确认").click()
-# d.xpath('//*[@content-desc="确认"]').click()
-
-
-# button = d.xpath("//android.widget.Button[@text='Button']")
+# print("点击数量:操作耗时:", end1 - start1)
+# # start1 = time.time()
+# # input_num.set_text("40")
+# # end1 = time.time()
+# # print("设置数量:操作耗时:", end1 - start1)
+#
+# # for i in range(10):
+# #     # 初始化点击按钮
+# #     start = time.time()
+# #     # start1 = time.time()
+# #     # input_weituo.click()
+# #     # end1 = time.time()
+# #     # print("点击:最优委托 操作耗时:", end1 - start1)
+# #     #
+# #     # # start1 = time.time()
+# #     # # input_weituo.set_text("0.114")
+# #     # # end1 = time.time()
+# #     # # print("设置:操作耗时:", end1 - start1)
+# #     # start1 = time.time()
+# #     # input_num.click()
+# #     # end1 = time.time()
+# #     # print("点击:操作耗时:", end1 - start1)
+# #     # start1 = time.time()
+# #     # input_num.set_text("40")
+# #     # end1 = time.time()
+# #     # print("设置:操作耗时:", end1 - start1)
+# #     start1 = time.time()
+# #     #  直接点击   xpath直接点击
+# #     # btn_buy.click()
+# #     # 比上面的快50毫秒
+# #     # d.click(1078, 1094)  # ui点击 指定坐标
+# #     # 比上面的快100毫秒  直接调用shell 指定坐标
+# #     d.shell(f"input tap {buy_x} {buy_y}")
+# #     end1 = time.time()
+# #     print("点击下单:操作耗时:", end1 - start1)
+# #     end = time.time()
+# #     # print("点击整体:操作耗时:", end - start)
+# #     time.sleep(5)
+#
+# # 给开仓确认的弹框 选中 下次不在提醒,能减少时间
+# # d(description="确认").click()
+# # d.xpath('//*[@content-desc="确认"]').click()
+#
+#
+# # button = d.xpath("//android.widget.Button[@text='Button']")

+ 0 - 33
test/deepcoin/test.py

@@ -1,33 +0,0 @@
-#使用python构建一个UI页面 上面有3个按钮
-#点击按钮1,弹出toast提示“点击了按钮1”
-#点击按钮2,弹出toast提示“点击了按钮2”
-#点击按钮3,弹出toast提示“点击了按钮3”
-import tkinter as tk
-from tkinter import messagebox
-
-
-class ToastApp:
-    def __init__(self):
-        self.root = tk.Tk()
-        self.root.title("Button Demo")
-        self.root.geometry("300x200")
-
-        # Create and pack buttons
-        for i in range(3):
-            btn = tk.Button(
-                self.root,
-                text=f"Button {i + 1}",
-                command=lambda x=i + 1: self.show_toast(x)
-            )
-            btn.pack(pady=10)
-
-    def show_toast(self, button_num):
-        messagebox.showinfo("Toast", f"Clicked Button {button_num}")
-
-    def run(self):
-        self.root.mainloop()
-
-
-if __name__ == "__main__":
-    app = ToastApp()
-    app.run()

+ 17 - 6
test/deepcoin/test01.py

@@ -2,6 +2,13 @@
 
 import uiautomator2 as u2
 
+
+import os
+
+command = "ls -l"  # 你想要执行的 shell 命令
+return_code = os.system(command)
+print(f"命令 '{command}' 的返回码是: {return_code}")
+
 # 连接设备
 d = u2.connect()
 # 获取屏幕的尺寸
@@ -39,16 +46,19 @@ print(f"屏幕尺寸: {width}x{height}")
 # 每一步大约需要 5 毫秒
 # 例如:设置 steps=200,整个滑动过程将持续约 1 秒(200 * 5ms = 1000ms)
 # 当设置了 steps 时,会忽略 duration 参数
-# d.swipe(width // 2, height * 0.8, width // 2, height * 0.1)
+d.swipe(width // 2, height * 0.8, width // 2, height * 0.1)
 
 # buttons = d.xpath('//*[starts-with(@content-desc, "持仓")]').all()
 # button = d.xpath('//*[@content-desc="买入/开多"]').get()
-button = d.xpath('//*[@content-desc="市价全平"]').get()
-print(f"第一个 坐标(left, top, right, bottom): {button.bounds}")
-buttons = d.xpath('//*[@content-desc="市价全平"]').all()
+# button = d.xpath('//*[@content-desc="市价全平"]').get()
+# print(f"第一个 坐标(left, top, right, bottom): {button.bounds}")
+# buttons = d.xpath('//*[@content-desc="市价全平"]').all()
+#
+button = d.xpath('//*[@content-desc="手机"]').get()
 
-for idx, button in enumerate(buttons):
-    print(f"按钮 {idx + 1} 坐标(left, top, right, bottom): {button.bounds}")
+button.click()
+# for idx, button in enumerate(buttons):
+#     print(f"按钮 {idx + 1} 坐标(left, top, right, bottom): {button.bounds}")
 
 # if button:
 #     # bounds返回(left, top, right, bottom)坐标
@@ -56,3 +66,4 @@ for idx, button in enumerate(buttons):
 #     top_distance = button.bounds[1]  # top坐标即是距离顶部的距离
 #     print(f"按钮距离顶部: {top_distance}像素")
 # d.swipe(width // 2, height * 0.8, width // 2, height * 0.3, duration=0.5)
+

+ 146 - 0
test/deepcoin/test03.py

@@ -0,0 +1,146 @@
+import wx
+import os
+
+
+class MainFrame(wx.Frame):
+    def __init__(self, parent, title):
+        super().__init__(parent, title=title, size=(800, 600))
+
+        # 创建菜单栏
+        menubar = wx.MenuBar()
+        menu1 = wx.Menu()
+        menu1.Append(wx.ID_EXIT, "退出")
+        menubar.Append(menu1, "菜单1")
+
+        menu2 = wx.Menu()
+        menu2.Append(wx.ID_ANY, "选项1")
+        menu2.Append(wx.ID_ANY, "选项2")
+        menubar.Append(menu2, "菜单2")
+
+        menu3 = wx.Menu()
+        menu3.Append(wx.ID_ANY, "设置")
+        menubar.Append(menu3, "菜单3")
+
+        menu4 = wx.Menu()
+        menu4.Append(wx.ID_ANY, "关于")
+        menubar.Append(menu4, "菜单4")
+
+        self.SetMenuBar(menubar)
+
+        # 创建主面板和布局
+        main_panel = wx.Panel(self)
+        main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        # 创建左侧导航栏
+        left_panel = wx.Panel(main_panel)
+        left_sizer = wx.BoxSizer(wx.VERTICAL)
+
+        self.navigation_list = wx.ListBox(left_panel, choices=["tab1", "tab2", "tab3", "tab4", "..."], style=wx.LB_SINGLE)
+        left_sizer.Add(self.navigation_list, 1, wx.EXPAND | wx.ALL, 5)
+
+        left_panel.SetSizer(left_sizer)
+        main_sizer.Add(left_panel, 0, wx.EXPAND | wx.ALL, 5)
+
+        # 创建右侧内容区域
+        right_panel = wx.Panel(main_panel)
+        right_sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        # 创建 tab 对应的右侧内容面板
+        self.tab_panels = {}
+        for tab_name in ["tab1", "tab2", "tab3", "tab4", "..."]:
+            tab_panel = wx.Panel(right_panel)
+            tab_sizer = wx.BoxSizer(wx.VERTICAL)
+
+            # 将 main_content 创建的内容添加到 tab 面板中
+            content = self.main_content(tab_panel, tab_name)
+            tab_sizer.Add(content, 1, wx.EXPAND | wx.ALL, 5)
+
+            tab_panel.SetSizer(tab_sizer)
+            self.tab_panels[tab_name] = tab_panel
+            right_sizer.Add(tab_panel, 1, wx.EXPAND | wx.ALL, 5)
+            tab_panel.Hide()  # 初始隐藏所有面板
+
+        right_panel.SetSizer(right_sizer)
+        main_sizer.Add(right_panel, 1, wx.EXPAND | wx.ALL, 5)
+
+        main_panel.SetSizer(main_sizer)
+
+        # 绑定 ListBox 的选择事件
+        self.navigation_list.Bind(wx.EVT_LISTBOX, self.on_tab_selected)
+
+        self.Show(True)
+        self.show_tab_content("tab1")  # 初始显示 tab1 的内容
+
+    def main_content(self, parent, tab_name):
+        # 创建右侧内容区域
+        right_panel = wx.Panel(parent)
+        right_sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+        if tab_name == "tab1":
+            # tab1 的内容
+            left_content_panel = wx.Panel(right_panel)
+            left_content_sizer = wx.BoxSizer(wx.VERTICAL)
+
+            form_panel = wx.Panel(left_content_panel)
+            form_sizer = wx.GridBagSizer(5, 5)
+
+            form_sizer.Add(wx.StaticText(form_panel, label="设置1:"), pos=(0, 0), flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
+            form_sizer.Add(wx.TextCtrl(form_panel), pos=(0, 1), flag=wx.EXPAND)
+
+            form_sizer.Add(wx.StaticText(form_panel, label="设置2:"), pos=(1, 0), flag=wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL)
+            form_sizer.Add(wx.TextCtrl(form_panel), pos=(1, 1), flag=wx.EXPAND)
+
+            form_panel.SetSizer(form_sizer)
+            left_content_sizer.Add(form_panel, 0, wx.EXPAND | wx.ALL, 5)
+
+            self.log_text = wx.TextCtrl(left_content_panel, style=wx.TE_MULTILINE | wx.TE_READONLY)
+            left_content_sizer.Add(self.log_text, 1, wx.EXPAND | wx.ALL, 5)
+
+            left_content_panel.SetSizer(left_content_sizer)
+            right_sizer.Add(left_content_panel, 1, wx.EXPAND | wx.ALL, 5)
+
+            image_panel = wx.Panel(right_panel)
+            image_sizer = wx.BoxSizer(wx.HORIZONTAL)
+
+            current_dir = os.path.dirname(os.path.abspath(__file__))
+            image_path = os.path.join(current_dir, "../../assets/img.png")
+            img = wx.Image(image_path, wx.BITMAP_TYPE_PNG).Scale(200, 200)
+            self.image_bitmap = wx.StaticBitmap(image_panel, wx.ID_ANY, wx.Bitmap(img))
+            image_sizer.Add(self.image_bitmap, 1, wx.CENTER)
+
+            image_panel.SetSizer(image_sizer)
+            right_sizer.Add(image_panel, 0, wx.CENTER | wx.ALL, 5)
+        elif tab_name == "tab2":
+            # tab2 的内容
+            text = wx.StaticText(right_panel, label="这是 tab2 的特殊内容")
+            right_sizer.Add(text, 1, wx.CENTER)
+        elif tab_name == "tab3":
+            # tab3 的内容
+            button = wx.Button(right_panel, label="点击我")
+            right_sizer.Add(button, 1, wx.CENTER)
+        else:
+            # 其他 tab 的内容
+            text = wx.StaticText(right_panel, label=f"这是 {tab_name} 的默认内容")
+            right_sizer.Add(text, 1, wx.CENTER)
+
+        right_panel.SetSizer(right_sizer)
+
+        return right_panel
+
+    def on_tab_selected(self, event):
+        selected_tab = self.navigation_list.GetStringSelection()
+        self.show_tab_content(selected_tab)
+
+    def show_tab_content(self, tab_name):
+        for name, panel in self.tab_panels.items():
+            if name == tab_name:
+                panel.Show()
+            else:
+                panel.Hide()
+        self.Layout()  # 重新布局
+
+
+if __name__ == '__main__':
+    app = wx.App()
+    frame = MainFrame(None, "我的GUI布局")
+    app.MainLoop()

+ 99 - 0
test/deepcoin/test04.py

@@ -0,0 +1,99 @@
+import tkinter as tk
+from tkinter import Menu, Text, Label, Entry, Button
+
+from PIL import Image, ImageTk  # 需要安装 Pillow 库
+
+
+class Application(tk.Tk):
+    def __init__(self):
+        super().__init__()
+        self.content_frame = None
+        self.navigation_buttons = None
+        self.navigation_frame = None
+        self.title("Tkinter 复杂 UI 示例")
+        self.geometry("800x600")
+
+        self.create_menu()
+        self.create_navigation()
+        self.create_content_area()
+
+        self.content_cache = {}  # 缓存内容
+
+    def create_menu(self):
+        menubar = Menu(self)
+        self.config(menu=menubar)
+
+        menu1 = Menu(menubar, tearoff=0)
+        menu1.add_command(label="选项 1")
+        menu1.add_command(label="选项 2")
+        menubar.add_cascade(label="菜单 1", menu=menu1)
+        menu1 = Menu(menubar, tearoff=0)
+        menu1.add_command(label="选项 1")
+        menu1.add_command(label="选项 2")
+        menubar.add_cascade(label="菜单 2", menu=menu1)
+        # 添加其他菜单...
+
+    def create_navigation(self):
+        self.navigation_frame = tk.Frame(self, width=150, bg="#f0f0f0")
+        self.navigation_frame.pack(side=tk.LEFT, fill=tk.Y)
+
+        navigation_items = ["导航 1", "导航 2", "导航 3", "导航 4", "导航 5", "导航 6", "导航 7", "导航 8", "导航 9", "导航 10"]
+        # self.navigation_buttons = []
+        for item in navigation_items:
+            button = tk.Button(self.navigation_frame, text=item, command=lambda i=item: self.show_content(i))
+            button.pack(fill=tk.X, pady=5)
+            # self.navigation_buttons.append(button)
+
+    def create_content_area(self):
+        self.content_frame = tk.Frame(self)
+        self.content_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
+
+    def show_content(self, item):
+        print(f"---> {item},{self.content_cache}")
+        for key, value in self.content_cache.items():
+            if key != item:
+                value.pack_forget()
+        if item in self.content_cache:
+            content = self.content_cache[item]
+            content.pack(fill=tk.BOTH, expand=True)
+        else:
+            content = tk.Frame(self.content_frame)
+            content.pack(fill=tk.BOTH, expand=True)
+
+            # 表单区域
+            form_frame = tk.Frame(content)
+            form_frame.pack(side=tk.TOP, fill=tk.X)
+
+            tk.Label(form_frame, text="姓名:").grid(row=0, column=0, sticky="w")
+            name_entry = Entry(form_frame)
+            name_entry.grid(row=0, column=1)
+
+            tk.Label(form_frame, text="年龄:").grid(row=1, column=0, sticky="w")
+            age_entry = Entry(form_frame)
+            age_entry.grid(row=1, column=1)
+
+            Button(form_frame, text="保存").grid(row=2, column=1, sticky="e")
+
+            # 日志区域
+            log_text = Text(content, height=10)
+            log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
+            log_text.insert(tk.END, f"导航 {item} 被点击\n")
+
+            # 图片预览区域
+            image_label = Label(content)
+            image_label.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
+
+            try:
+                image = Image.open("../../assets/img.png")  # 替换为您的图片路径
+                photo = ImageTk.PhotoImage(image)
+                image_label.config(image=photo)
+                image_label.image = photo  # 保持对图片的引用
+            except FileNotFoundError:
+                log_text.insert(tk.END, "图片未找到\n")
+
+            self.content_cache[item] = content  # 缓存内容
+
+
+if __name__ == "__main__":
+    app = Application()
+    app.mainloop()

+ 249 - 0
test/deepcoin/test_deepcoin_control.py

@@ -0,0 +1,249 @@
+import logging
+import unittest
+
+from plat.deepcoin_control import DeepCoinControl
+
+logging.basicConfig(level=logging.INFO, force=True)  # 设置日志级别
+
+
+class MyTestCase(unittest.TestCase):
+    def setUp(self):
+        self.pc = DeepCoinControl('Deepcoin')
+
+        self.pc.connect_adb('127.0.0.1:64079')
+
+    def test_to_top_swipe(self):
+        """
+        滑动到顶部
+        """
+        self.pc.to_top_swipe()
+
+    def test_to_next_swipe(self):
+        """
+        滑动到下一屏
+        """
+        self.pc.to_next_swipe()
+
+    def test_save_point(self):
+        """
+        保存坐标
+        """
+        self.pc.save_point()
+
+    def test_slider_baozhengjin(self):
+        """
+        保证金滑块
+        """
+        self.pc.slider_baozhengjin_kaicang()
+
+    def test_click_kaicang(self):
+        """
+        开仓
+        """
+        self.pc.click_kaicang()
+
+    def test_click_pingchang(self):
+        """
+        平仓
+        """
+        self.pc.click_pingchang()
+
+    def test_select_weituo_xianjia(self):
+        """
+        选择限价委托
+        """
+        self.pc.select_kaicang_weituo_xianjia()
+
+    def test_click_price(self):
+        """
+        点击价格
+        """
+        self.pc.click_price_red()
+
+    def test_f1(self):
+        """
+        f1 开仓界面,仓位滑竿百分比(30-60)
+        """
+        # self.pc.click_kaicang()
+        # self.pc.slider_baozhengjin_kaicang()
+        self.pc.event_f1()
+
+    def test_f2(self):
+        """
+        f2 确认开仓,开多 限价职中间数值
+        检查撤销限价委托单
+        """
+        # self.pc.click_kaicang()
+        #
+        # self.pc.select_kaicang_weituo_xianjia()
+        # self.pc.d.sleep(0.1)
+        #
+        # self.pc.click_price_red()
+        #
+        # # self.pc.text_xiadan_shuliang(3)
+        # self.pc.slider_baozhengjin_kaicang()
+        #
+        # self.pc.click_mairu_kaiduo()
+        self.pc.event_f2()
+
+    def test_f3(self):
+        """
+        F3 平仓界面 平空,仓位滑竿百分比(90-100)确认开仓,限价职中间数值
+        """
+        # self.pc.to_top_swipe(sleep=0.2)
+        # self.pc.click_pingchang()
+        # self.pc.slider_baozhengjin_pingcang(offset=1)
+        self.pc.event_f3()
+
+    def test_f4(self):
+        """
+        F4   确认平仓 平多 限价取中间数值 检查撤销限价委托单
+        """
+        # self.pc.to_top_swipe(sleep=0.2)
+        # self.pc.click_pingchang()
+        # self.pc.select_kaicang_weituo_xianjia()
+        # self.pc.click_price_green()
+        # # self.pc.text_xiadan_shuliang(3)
+        # self.pc.slider_baozhengjin_pingcang(offset=1)
+        # self.pc.click_maichu_pingduo()
+        self.pc.event_f4()
+
+    def test_f5(self):
+        """
+        F5 开仓界面胂仓位滑竿百分比(30-60)
+        """
+        # self.pc.to_top_swipe(sleep=0.2)
+        # self.pc.click_kaicang()
+        # self.pc.slider_baozhengjin_kaicang()
+        self.pc.event_f5()
+
+    def test_f6(self):
+        """
+        F6 确认开仓, 开空 限价值中间数值
+        检查撤销限价委托单
+        """
+        # self.pc.to_top_swipe(sleep=0.1)
+        # self.pc.click_kaicang()
+        # self.pc.select_kaicang_weituo_xianjia()
+        # self.pc.click_price_red()
+        # # self.pc.text_xiadan_shuliang(3)
+        # self.pc.click_maichu_kaikong()
+        self.pc.event_f6()
+
+    def test_f7(self):
+        """
+        F7    平仓界面二仓位滑竿百分比(90-100)
+        """
+        # self.pc.to_top_swipe(sleep=0.2)
+        # self.pc.click_pingchang()
+        # self.pc.slider_baozhengjin_pingcang(offset=2)
+        self.pc.event_f7()
+
+    def test_f8(self):
+        """
+        F8 确认平仓, 平空 限价职中间数值
+        检查撤销限价委托单
+        """
+        # self.pc.to_top_swipe()
+        #
+        # self.pc.d.sleep(0.1)
+        #
+        # self.pc.click_pingchang()
+        #
+        # self.pc.click_price_red()
+        #
+        # # self.pc.text_xiadan_shuliang(3)
+        # self.pc.click_maichu_kaikong()
+        #
+        # self.pc.click_mairu_pingkong()
+        self.pc.event_f8()
+
+    def test_jiao_yi(self):
+        x, y = self.pc.btn_jiao_yi()
+        logging.info(f"交易坐标: ({x},{y})")
+
+    def test_mairu_kaiduo(self):
+        x, y = self.pc.btn_mairu_kaiduo()
+        logging.info(f"买入开多: ({x},{y})")
+
+    def test_chichang(self):
+        self.pc.d.xpath()
+
+    def test_gengdan(self):
+        self.pc.to_next_swipe()
+        x, y = self.pc.btn_gengdan()
+        logging.info(f"跟单坐标: ({x},{y})")
+
+    def test_weituo(self):
+        self.pc.to_next_swipe()
+        x, y = self.pc.btn_weituo()
+        logging.info(f"委托坐标: ({x},{y})")
+
+    def test_gendan_click(self):
+        self.pc.click_xpath('//*[starts-with(@content-desc, "跟单(")]')
+
+    def test_yijianchedan_click(self):
+        """
+        一键撤单
+        """
+        self.pc.to_next_swipe()
+
+        self.pc.click_yijian_chedan()
+
+    def test_jiaoyi_select(self):
+        element = self.pc.d.xpath('//*[@content-desc="交易"]').get()
+
+        # 获取元素位置
+        bounds = element.info['bounds']
+        # 截图
+        screenshot = self.pc.d.screenshot()
+        # 转换为PIL图像
+        from PIL import Image
+        img = Image.fromarray(screenshot)
+        # 获取元素中心点颜色
+        x = (bounds['left'] + bounds['right']) // 2
+        y = (bounds['top'] + bounds['bottom']) // 2
+        return img.getpixel((x, y))
+
+    def test_slider_baozhengjin_pingcang(self):
+        """
+        平仓情况  保证金滑块
+        """
+        self.pc.slider_baozhengjin_pingcang()
+
+    def test_exists(self):
+        # b = self.pc.check_element_exists('//*[starts-with(@content-desc, "全部委托(")]')
+        # logging.info("是否存在: %s", b)
+        b = self.pc.check_element_exists('//*[@content-desc="限价委托"]')
+        logging.info("是否存在: %s", b)
+
+    def test_element(self):
+        element = self.pc.d.xpath('//*[@content-desc="交易"]').get()
+        logging.info("交易按钮: %s", element.info)
+
+    def test_input(self):
+        """
+        给指定xpath的输入框输入文本
+        """
+        self.pc.text_xiadan_shuliang(30)
+
+    def test_kaichang_queren(self):
+        """
+        开仓确认
+        """
+
+        x, y, _ = self.pc.get_point({
+            "name": "btn_kaicang_queren",
+            "desc": "开仓确认",
+            "xpath": '//*[@content-desc="开仓确认"]'
+        })
+        logging.info(f"开仓确认: ({x},{y})")
+
+        if self.pc.check_element_exists('//*[@content-desc="开仓确认"]'):
+            self.pc.click_xpath('//*[@content-desc="确认"]')
+
+    def test_get_appinfo(self):
+        logging.info(f'>>>{self.pc.d.info}',)
+
+if __name__ == '__main__':
+    unittest.main()

+ 0 - 119
test/deepcoin/test_point_collection.py

@@ -1,119 +0,0 @@
-import logging
-import unittest
-
-from plat.deepcoin.point_collection import PointCollection
-
-logging.basicConfig(level=logging.INFO, force=True)  # 设置日志级别
-
-
-class MyTestCase(unittest.TestCase):
-    def setUp(self):
-        self.pc = PointCollection('127.0.0.1:6555')
-
-    def test_to_top_swipe(self):
-        """
-        滑动到顶部
-        """
-        self.pc.to_top_swipe()
-
-    def test_to_next_swipe(self):
-        """
-        滑动到下一屏
-        """
-        self.pc.to_next_swipe()
-
-    def test_save_point(self):
-        """
-        保存坐标
-        """
-        self.pc.save_point()
-
-    def test_slider_baozhengjin(self):
-        """
-        保证金滑块
-        """
-        self.pc.slider_baozhengjin()
-
-    def test_click_kaicang(self):
-        """
-        开仓
-        """
-        self.pc.click_kaicang()
-
-    def test_click_pingchang(self):
-        """
-        平仓
-        """
-        self.pc.click_pingchang()
-
-    def test_select_weituo_xianjia(self):
-        """
-        选择限价委托
-        """
-        self.pc.select_weituo_xianjia()
-
-    def test_click_price(self):
-        """
-        点击价格
-        """
-        self.pc.click_price_red()
-
-    def test_f1(self):
-        """
-        f1 开仓界面,仓位滑竿百分比(30-60)
-        """
-        self.pc.click_kaicang()
-        self.pc.slider_baozhengjin()
-
-    def test_f2(self):
-        """
-        f2 确认开仓,限价职中间数值
-        检查撤销限价委托单
-        """
-
-    def test_f3(self):
-        """
-        F3 开仓界面,仓位滑竿百分比(30-60)确认开仓,限价职中间数值
-        """
-
-    def test_f4(self):
-        """
-        F4   确认开仓限价职中间数值 检查撤销限价委托单
-        """
-
-    def test_f5(self):
-        """
-        F5 开仓界面胂仓位滑竿百分比(30-60)
-        """
-
-    def test_f6(self):
-        """
-        F6 确认开仓,限价职中间数值
-        检查撤销限价委托单
-        """
-
-    def test_f7(self):
-        """
-        F7    平仓界面二仓位滑竿百分比(90-100)
-        """
-
-    def test_f8(self):
-        """
-        F8 确认平仓,限价职中间数值
-        检查撤销限价委托单
-        """
-
-    def test_jiao_yi(self):
-        x, y = self.pc.btn_jiao_yi()
-        logging.info(f"交易坐标: ({x},{y})")
-
-    def test_mairu_kaiduo(self):
-        x, y = self.pc.btn_mairu_kaiduo()
-        logging.info(f"买入开多: ({x},{y})")
-
-    def test_chichang(self):
-        self.pc.d.xpath()
-
-
-if __name__ == '__main__':
-    unittest.main()

+ 158 - 0
test/test-adb.py

@@ -0,0 +1,158 @@
+# import uiautomator2 as u2
+# d = u2.connect('127.0.0.1:52377') # 例如:"127.0.0.1:61468"
+#
+# print('>>>>',d.info)
+import subprocess
+import os
+
+import subprocess
+import os
+
+
+def run_adb_command(command, adb_path=None):
+    """
+    执行 ADB 命令并返回输出,可以通过环境变量指定 ADB 路径。
+
+    Args:
+        command (list): 包含 ADB 命令及其参数的列表。
+        adb_path (str, optional): ADB 可执行文件的完整路径。
+                                   如果为 None,则使用系统环境变量中的 ADB,
+                                   或者在代码中设置的自定义环境变量。
+    Returns:
+        str: 命令的标准输出,如果执行失败则返回 None。
+    """
+    env = os.environ.copy()  # 复制当前的环境变量
+    adb_executable = adb_path + "\\adb.exe"
+    if adb_path:
+        # 在子进程的环境变量中设置 ADB 的路径
+        # adb_executable = adb_path
+        env["PATH"] = os.pathsep.join([os.path.dirname(adb_path), env.get("PATH", "")])
+    # else:
+
+    try:
+        full_command = [adb_executable] + ["shell"] + command
+        result = subprocess.run(
+            full_command,
+            capture_output=True,
+            text=True,
+            check=True,
+            env=env  # 将设置的环境变量传递给子进程
+        )
+        return result.stdout.strip()
+    except subprocess.CalledProcessError as e:
+        print(f"ADB 命令 '{' '.join(command)}' 执行失败:")
+        print(f"错误代码: {e.returncode}")
+        print(f"错误输出:\n{e.stderr}")
+        return None
+    except FileNotFoundError:
+        print(f"错误: ADB 可执行文件 '{adb_executable}' 未找到。请检查路径是否正确。")
+        return None
+
+
+def list_devices(adb_path=None):
+    """
+    列出已连接的 Android 设备。
+
+    Args:
+        adb_path (str, optional): ADB 可执行文件的完整路径。 Defaults to None.
+    """
+    command = ["devices"]
+    output = run_adb_command(command, adb_path)
+    if output:
+        print("已连接的设备:")
+        for line in output.splitlines()[1:]:
+            if line.strip():
+                device_info = line.split('\t')
+                print(f"- {device_info[0]}")
+    else:
+        print("未找到已连接的 Android 设备。")
+
+
+def get_screen_size(device_serial=None, adb_path=None):
+    """
+    获取指定设备的屏幕尺寸。
+
+    Args:
+        device_serial (str, optional): 设备的序列号。 Defaults to None.
+        adb_path (str, optional): ADB 可执行文件的完整路径。 Defaults to None.
+    """
+    command_base = []
+    if device_serial:
+        command_base.extend(["-s", device_serial])
+    command_base.extend(["wm", "size"])
+    output = run_adb_command(command_base, adb_path)
+    if output:
+        if "Physical size" in output:
+            size_str = output.split(":")[1].strip()
+            print(f"屏幕尺寸: {size_str}")
+            return size_str
+        else:
+            print(f"无法获取屏幕尺寸: {output}")
+            return None
+    return None
+
+
+def tap_screen(x, y, device_serial=None, adb_path=None):
+    """
+    模拟点击屏幕指定坐标。
+
+    Args:
+        x (int): 点击的 X 坐标。
+        y (int): 点击的 Y 坐标。
+        device_serial (str, optional): 设备的序列号。 Defaults to None.
+        adb_path (str, optional): ADB 可执行文件的完整路径。 Defaults to None.
+    """
+    command_base = []
+    if device_serial:
+        command_base.extend(["-s", device_serial])
+    command_base.extend(["input", "tap", str(x), str(y)])
+    print(f"模拟点击坐标 ({x}, {y})")
+    run_adb_command(command_base, adb_path)
+
+
+def swipe_screen(start_x, start_y, end_x, end_y, duration_ms=None, adb_path=None):
+    """
+    模拟屏幕滑动操作。
+
+    Args:
+        start_x (int): 滑动起始 X 坐标。
+        start_y (int): 滑动起始 Y 坐标。
+        end_x (int): 滑动结束 X 坐标。
+        end_y (int): 滑动结束 Y 坐标。
+        duration_ms (int, optional): 滑动持续时间 (毫秒). Defaults to None.
+        adb_path (str, optional): ADB 可执行文件的完整路径。 Defaults to None.
+    """
+    command_base = ["input", "swipe", str(start_x), str(start_y), str(end_x), str(end_y)]
+    if duration_ms is not None:
+        command_base.append(str(duration_ms))
+    run_adb_command(command_base, adb_path)
+
+
+if __name__ == "__main__":
+    # 假设你的 ADB 路径是:
+    # adb_custom_path = "/path/to/your/android-sdk/platform-tools/adb"  # 请替换为你的实际路径
+    adb_custom_path = "../bin/windows/platform-tools"  # 请替换为你的实际路径
+    print("--- 列出已连接的设备 (通过设置环境变量) ---")
+    list_devices(adb_path=adb_custom_path)
+
+    # 尝试获取第一个连接设备的屏幕尺寸 (通过设置环境变量)
+    print("\n--- 获取屏幕尺寸 (通过设置环境变量) ---")
+    screen_size_str = get_screen_size(adb_path=adb_custom_path)
+    screen_width = None
+    screen_height = None
+    if screen_size_str:
+        try:
+            width, height = map(int, screen_size_str.split("x"))
+            screen_width = width
+            screen_height = height
+            print(f"屏幕宽度: {screen_width}, 屏幕高度: {screen_height}")
+        except ValueError:
+            print("无法解析屏幕尺寸字符串。")
+
+    # 模拟点击屏幕中间 (如果获取到屏幕尺寸,并设置环境变量)
+    if screen_width and screen_height:
+        center_x = screen_width // 2
+        center_y = screen_height // 2
+        print("\n--- 模拟点击屏幕中间 (通过设置环境变量) ---")
+        tap_screen(center_x, center_y, adb_path=adb_custom_path)
+        swipe_screen(center_x, center_y, center_x, center_y * 1.5, adb_path=adb_custom_path)

+ 66 - 0
test/test-adb1.py

@@ -0,0 +1,66 @@
+import uiautomator2 as u2
+import time
+
+from adbutils import adb
+from uiautomator2 import Direction
+
+d = u2.connect('127.0.0.1:6555')  # 例如:"127.0.0.1:61468"
+# d = u2.connect_usb()
+print('>0>>>', d.info)
+
+res = d.shell('settings get global device_name')
+
+print('>>1>>', str(res.output).strip())
+#
+# el=d.xpath('//*[@content-desc="开仓"]').scroll_to(xpath='//*[@content-desc="市价全平"]', direction=Direction.FORWARD,
+#                                                max_swipes=100)
+#
+# print('>>>>', el)
+#
+# while True:
+#     time.sleep(9999)
+# d.xpath("//*[@text='私人FM']/../android.widget.ImageView")
+
+# d.screen_off();
+# d.sleep(4)
+# d.screen_on();
+# # d.keyevent('24')
+#
+# urls = ['https://www.baidu.com', 'https://www.qq.com']
+# idx = 0
+
+# for d in adb.device_list():
+#     print('--->', d.serial)  # print device serial
+#     print('>>>', d.info)  # print device
+#     # d.open_browser(urls[idx])
+#     idx += 1
+# d.switch_wifi(False)
+# ctx = d.dump_hierarchy()
+# print(f'>>{idx}>>', ctx)
+# pck = d.list_packages()
+# print(pck)
+# # d.switch_wifi(True)
+# # d.app_start("com.android.chrome")
+# img= d.screenshot()
+# img.save(f'screenshot{idx}.png')
+# print(img)
+# time.sleep(10)
+
+# d = adb.device(serial="127.0.0.1:50269")
+# print('>>1>', d.info)  # print device
+#
+# # d.sleep = lambda seconds: d.shell(f'sleep {seconds}')
+# # d.sleep(3)
+# # print('>>2>', d.info)  # print device
+#
+# w, h = d.window_size()
+# print('>>3>', w, h)  # print device
+
+
+# # or
+# d = adb.device(transport_id=24) # transport_id can be found in: adb devices -l
+
+# You do not need to offer serial if only one device connected
+# RuntimeError will be raised if multi device connected
+# d = adb.device()
+# print('>>>',d.info)

+ 16 - 0
test/test-ui-1.py

@@ -0,0 +1,16 @@
+import tkinter as tk
+from tkinter import ttk
+
+from gui.phone_list import LeftPanel, RightPanel
+
+if __name__ == '__main__':
+    root = tk.Tk()
+    root.title("操作页面布局")
+    left_panel = LeftPanel(root)
+    left_panel.pack(side="left", fill="y")
+
+    # 为了演示,我们创建一个简单的右侧区域
+    right_panel = RightPanel(root, width=400, height=400)
+    right_panel.pack(side="left", fill="both", expand=True)
+
+    root.mainloop()

+ 49 - 0
test/test-ui-2.py

@@ -0,0 +1,49 @@
+import tkinter as tk
+
+def show_card(card_number):
+    card1_frame.grid_forget()
+    card2_frame.grid_forget()
+    card3_frame.grid_forget()
+
+    if card_number == 1:
+        card1_frame.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
+    elif card_number == 2:
+        card2_frame.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
+    elif card_number == 3:
+        card3_frame.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
+
+root = tk.Tk()
+root.title("模拟 CardLayout")
+
+# 创建一个容器 Frame
+container = tk.Frame(root)
+container.pack(fill="both", expand=True)
+
+# 创建三个 "卡片" Frame
+card1_frame = tk.Frame(container, bg="lightblue", padx=50, pady=50)
+card2_frame = tk.Frame(container, bg="lightgreen", padx=50, pady=50)
+card3_frame = tk.Frame(container, bg="lightyellow", padx=50, pady=50)
+
+card1_label = tk.Label(card1_frame, text="卡片 1")
+card1_label.pack()
+
+card2_label = tk.Label(card2_frame, text="卡片 2")
+card2_label.pack()
+
+card3_label = tk.Label(card3_frame, text="卡片 3")
+card3_label.pack()
+
+# 初始显示第一个卡片
+show_card(1)
+
+# 创建切换按钮
+button1 = tk.Button(root, text="显示卡片 1", command=lambda: show_card(1))
+button1.pack(pady=5)
+
+button2 = tk.Button(root, text="显示卡片 2", command=lambda: show_card(2))
+button2.pack(pady=5)
+
+button3 = tk.Button(root, text="显示卡片 3", command=lambda: show_card(3))
+button3.pack(pady=5)
+
+root.mainloop()

+ 87 - 0
test/test-ui-3.py

@@ -0,0 +1,87 @@
+import tkinter as tk
+from tkinter import ttk
+
+
+def show_tab(index):
+    notebook.select(index)  # 使用 notebook 的 select 方法切换到指定索引的 tab
+
+
+root = tk.Tk()
+root.title("自定义按钮切换 Notebook 内容")
+
+# 创建一个 Style 实例
+style = ttk.Style()
+
+# 为我们的 Notebook 创建一个新的样式名称
+notebook_style_name = "NoTabs.TNotebook"
+style.configure(notebook_style_name)  # 可以进行其他配置,如果需要
+
+# 移除这个新样式的 Tab 布局
+style.layout(notebook_style_name + ".Tab", [])
+
+notebook = ttk.Notebook(root, style=notebook_style_name)  # 将自定义样式应用到这个 Notebook
+notebook.pack(fill="both", expand=True)
+
+# 创建不同的内容 Frame
+tab1_content = ttk.Frame(notebook)
+label1 = tk.Label(tab1_content, text="这是选项卡 1 的内容", padx=50, pady=50)
+label1.pack(expand=True, fill="both")
+notebook.add(tab1_content, text="标签一")  # 虽然设置了 text,但我们会隐藏标签
+
+tab2_content = ttk.Frame(notebook)
+label2 = tk.Label(tab2_content, text="这是选项卡 2 的内容", padx=50, pady=50)
+label2.pack(expand=True, fill="both")
+notebook.add(tab2_content, text="标签二")  # 同样设置了 text
+
+tab3_content = ttk.Frame(notebook)
+label3 = tk.Label(tab3_content, text="这是选项卡 3 的内容", padx=50, pady=50)
+label3.pack(expand=True, fill="both")
+notebook.add(tab3_content, text="标签三")  # 同样设置了 text
+
+# 创建自定义按钮
+button1 = tk.Button(root, text="显示内容 1", command=lambda: show_tab(0))
+button1.pack(side="left", padx=5)
+
+button2 = tk.Button(root, text="显示内容 2", command=lambda: show_tab(1))
+button2.pack(side="left", padx=5)
+
+button3 = tk.Button(root, text="显示内容 3", command=lambda: show_tab(2))
+button3.pack(side="left", padx=5)
+
+root.mainloop()
+
+# import tkinter as tk
+# from tkinter import ttk
+#
+# def add_new_tab():
+#     global tab_count
+#     tab_count += 1
+#     new_tab = ttk.Frame(notebook)
+#     label = tk.Label(new_tab, text=f"这是动态添加的选项卡 {tab_count}", padx=50, pady=50)
+#     label.pack(expand=True, fill="both")
+#     notebook.add(new_tab, text=f"动态标签 {tab_count}")
+#
+# root = tk.Tk()
+# root.title("动态添加 Notebook 标签")
+#
+# notebook = ttk.Notebook(root)
+# notebook.pack(fill="both", expand=True)
+#
+# # 初始添加一些标签
+# tab1 = ttk.Frame(notebook)
+# label1 = tk.Label(tab1, text="初始选项卡 1", padx=50, pady=50)
+# label1.pack(expand=True, fill="both")
+# notebook.add(tab1, text="标签一")
+#
+# tab2 = ttk.Frame(notebook)
+# label2 = tk.Label(tab2, text="初始选项卡 2", padx=50, pady=50)
+# label2.pack(expand=True, fill="both")
+# notebook.add(tab2, text="标签二")
+#
+# tab_count = 2  # 记录已经添加的标签数量
+#
+# # 添加一个按钮,点击时动态添加新标签
+# add_button = tk.Button(root, text="添加新标签", command=add_new_tab)
+# add_button.pack(pady=10)
+#
+# root.mainloop()

Some files were not shown because too many files changed in this diff