在数字娱乐领域,自动化技术正悄然改变着玩家的体验方式。当传统软件方案遭遇限制时,硬件与软件的巧妙结合往往能开辟新路径。本文将深入探讨一种经济高效的自动化方案,通过CH9329模块与Python的协同工作,实现特定场景下的自动化操作。
CH9329是一款USB HID设备控制器芯片,能够模拟键盘和鼠标输入。与纯软件方案相比,这种硬件模拟方式具有显著优势:
硬件准备清单如下:
| 组件 | 规格 | 预估成本 |
|---|---|---|
| CH9329模块 | 支持USB HID模拟 | 15-20元 |
| CH340 USB转TTL模块 | 用于串口通信 | 5-7元 |
| 杜邦线 | 母对母 | 通常随模块赠送 |
连接步骤简单明了:
提示:首次使用时可能需要安装CH340驱动程序,各大操作系统平台均有官方支持。
实现自动化需要搭建适当的Python环境。推荐使用Python 3.7或更高版本,并安装以下关键库:
python复制# 基础自动化控制
pip install pyautogui
# 图像处理支持
pip install opencv-python Pillow
# 串口通信
pip install pyserial
这些库各司其职:
pyautogui:提供屏幕识别和窗口管理功能opencv-python和Pillow:支持图像识别和处理pyserial:实现与CH9329模块的串口通信图像识别是自动化的重要环节。通过pyautogui.locateOnScreen()函数,可以实时检测屏幕上特定元素的位置:
python复制import pyautogui as pg
from PIL import Image
# 加载目标图像模板
target_image = Image.open('button_template.png')
# 在屏幕上查找匹配区域
position = pg.locateOnScreen(target_image, confidence=0.9)
if position:
center = pg.center(position)
print(f"找到目标,中心坐标:{center}")
CH9329通过串口接收特定格式的指令来控制鼠标和键盘。以下是一个完整的通信协议实现示例:
python复制import serial
import time
class CH9329Controller:
def __init__(self, port='COM3', baudrate=115200):
self.serial = serial.Serial(port, baudrate, timeout=1)
def mouse_move(self, x, y):
"""鼠标绝对移动命令"""
# 将屏幕坐标转换为设备坐标(0-4095)
nx = int(x * 4096 / 1920) # 假设屏幕宽度1920
ny = int(y * 4096 / 1080) # 假设屏幕高度1080
cmd = [
0x57, 0xAB, 0x00, 0x04, # 帧头
0x07, 0x02, # 鼠标绝对移动命令
0x00, # 按钮状态
nx & 0xFF, (nx >> 8) & 0xFF, # X坐标低/高字节
ny & 0xFF, (ny >> 8) & 0xFF, # Y坐标低/高字节
0x00 # 滚轮状态
]
cmd.append(sum(cmd) & 0xFF) # 校验和
self.serial.write(bytes(cmd))
self.serial.flushInput()
def mouse_click(self, button='left'):
"""模拟鼠标点击"""
button_code = 0x01 if button == 'left' else 0x02
# 按下命令
press_cmd = [
0x57, 0xAB, 0x00, 0x04,
0x07, 0x02,
button_code, 0x00, 0x00, 0x00, 0x00, 0x00
]
press_cmd.append(sum(press_cmd) & 0xFF)
# 释放命令
release_cmd = press_cmd.copy()
release_cmd[6] = 0x00 # 按钮状态归零
release_cmd[-1] = sum(release_cmd[:-1]) & 0xFF
self.serial.write(bytes(press_cmd))
time.sleep(0.05)
self.serial.write(bytes(release_cmd))
time.sleep(0.05)
self.serial.flushInput()
注意:实际应用中需要根据屏幕分辨率调整坐标转换公式,并处理可能的串口通信异常。
一个健壮的自动化系统需要精心设计工作流程。以下是典型的状态机设计:
python复制class AutomationSystem:
def __init__(self):
self.state = 'IDLE'
self.controller = CH9329Controller()
def run(self):
while True:
if self.state == 'IDLE':
self._find_match()
elif self.state == 'IN_QUEUE':
self._accept_match()
elif self.state == 'IN_GAME':
self._play_game()
elif self.state == 'FINISHED':
self._next_round()
time.sleep(1)
def _find_match(self):
"""寻找比赛"""
start_btn = pg.locateOnScreen('find_match.png')
if start_btn:
center = pg.center(start_btn)
self.controller.mouse_move(center.x, center.y)
self.controller.mouse_click()
self.state = 'IN_QUEUE'
def _accept_match(self):
"""接受比赛"""
accept_btn = pg.locateOnScreen('accept.png')
if accept_btn:
center = pg.center(accept_btn)
self.controller.mouse_move(center.x, center.y)
self.controller.mouse_click()
self.state = 'IN_GAME'
def _play_game(self):
"""游戏内操作"""
# 检测特定游戏阶段
if pg.locateOnScreen('stage_3_2.png'):
self._surrender()
self.state = 'FINISHED'
else:
# 执行随机操作避免被检测
self._random_actions()
def _surrender(self):
"""投降操作"""
# 打开设置菜单
self.controller.mouse_move(1890, 870)
self.controller.mouse_click()
time.sleep(1)
# 点击投降按钮
self.controller.mouse_move(800, 850)
self.controller.mouse_click()
time.sleep(0.5)
# 确认投降
self.controller.mouse_move(850, 500)
self.controller.mouse_click()
def _next_round(self):
"""开始下一轮"""
next_btn = pg.locateOnScreen('play_again.png')
if next_btn:
center = pg.center(next_btn)
self.controller.mouse_move(center.x, center.y)
self.controller.mouse_click()
self.state = 'IDLE'
def _random_actions(self):
"""随机操作增加真实性"""
import random
x = random.randint(400, 1500)
y = random.randint(100, 700)
self.controller.mouse_move(x, y)
if random.random() < 0.3:
self.controller.mouse_click()
这种模块化设计便于维护和扩展,每个状态对应明确的行为模式,通过图像识别实现状态转换。
在长期使用中,我们总结出以下优化经验:
分辨率适配方案
不同设备的分辨率差异会影响图像识别和坐标定位。解决方法包括:
性能优化技巧
错误处理机制
完善的错误处理能显著提高系统稳定性:
python复制def safe_locate(image, max_attempts=3):
"""带重试机制的图像识别"""
attempts = 0
while attempts < max_attempts:
try:
position = pg.locateOnScreen(image, confidence=0.85)
if position:
return position
except Exception as e:
print(f"识别出错: {e}")
attempts += 1
time.sleep(1)
return None
日志记录系统
添加详细的日志记录有助于问题排查:
python复制import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='automation.log'
)
logger = logging.getLogger(__name__)
# 在关键节点添加日志
logger.info("开始寻找比赛...")
position = safe_locate('find_match.png')
if position:
logger.info(f"找到比赛按钮,位置: {position}")
CH9329模块的应用远不止于游戏自动化。其核心价值在于提供了一种低成本硬件交互方案,可广泛应用于:
一个简单的宏按键实现示例:
python复制class MacroController:
def __init__(self):
self.serial = serial.Serial('COM3', 115200)
def send_key_combination(self, keys):
"""发送组合键"""
key_codes = {
'ctrl': 0x01,
'shift': 0x02,
'alt': 0x04,
'win': 0x08,
'a': 0x04,
'c': 0x06,
'v': 0x19,
'enter': 0x28
}
modifiers = 0
key_list = []
for key in keys.split('+'):
if key in ['ctrl', 'shift', 'alt', 'win']:
modifiers |= key_codes[key]
else:
key_list.append(key_codes.get(key.lower(), 0))
# 构建HID报告
report = [
0x57, 0xAB, 0x00, 0x02, # 帧头
0x08, # 键盘报告长度
modifiers, # 修饰键
0x00, # 保留
*key_list[:6], # 普通键(最多6个)
(0,) * (6 - len(key_list[:6])), # 补零
sum([0x57, 0xAB, 0x00, 0x02, 0x08, modifiers, 0x00] + key_list[:6]) & 0xFF # 校验和
]
# 发送按下命令
self.serial.write(bytes(report))
time.sleep(0.1)
# 发送释放命令
report[6] = 0x00 # 清除所有按键
report[-1] = sum(report[:-1]) & 0xFF
self.serial.write(bytes(report))
这种硬件方案为Python自动化开辟了新可能,突破了纯软件方案的限制,同时保持了开发的灵活性和低成本优势。