在网上转了一圈关于苹果免越狱自动化的方案,无非都是调用wda实现的,需要签名等等一大堆复杂的流程。终于找到一家是通过硬件实现的,他们硬件提供的DLL方式接口。而IOSAutoTouch基于他们硬件接口又做了二次封装支持http和websocket调用并加入屏幕传输的功能让用户更简单的进行自动化操作苹果手机。前两天买的硬件到货了,激动的立马动手写了一个简单的例子。这个例子就是自动打开低电量模式
他们是通过这玩意控制手机的
首先导入IOSAutoTouch封装的python调用库,和安装aircv库(这个是OpenCV库的一个封装)
aircv 安装方法 pip install aircv
IOSAutoTouch库需要从他们官网下载
初始化IAT库
# 初始化IAT库,填写内核服务的ip,本机填写127.0.0.1采用http协议进行交互
iatapi = ios_at_api.HttpApi('192.168.0.113')
调用IAT库发送快捷按钮返回主屏幕
# 发送返回主屏幕热键,deviceid参数是设备id
# 如果不知道设备id可以用这条命令打印出所有的设备id print(iatapi.get_device_list())
iatapi.send_key(deviceid=devid, key='', fn_key='WIN+h')
通过aircv库查找设置按钮的位置,并调用IAT库的点击指定坐标的接口
imobj = imread('./img/设置按钮.bmp')
acret = ac.find_template(screenshot(devid), imobj, 0.8)
if acret is None:
print("没有找到子图")
exit()
print(acret)
print("查找设置按钮子图成功{}".format(acret['result']))
x = int(acret['result'][0])
y = int(acret['result'][1])
iatapi.click(deviceid=devid, x=x, y=y) # 点击找到的坐标
滑动找到设置里的电池图标并点击
for i in range(3): # 往下滑动3次,保证到设置界面的最开始
iatapi.swipe(deviceid=devid, direction='down', length=0.8, afor=6)
time.sleep(1) # 延时1秒钟
for i in range(3): # 往上滑动3次
iatapi.swipe(deviceid=devid, direction='up', length=0.7, afor=10)
time.sleep(0.2) # 延时一下,避免滑动太快滑过了
time.sleep(1) # 延时1秒钟
imobj = imread('./img/电池图标.bmp')
acret = ac.find_template(screenshot(devid), imobj, 0.8)
if acret is None:
print("没有找到子图")
exit()
print(acret)
print("查找电池图标子图成功{}".format(acret['result']))
x = int(acret['result'][0])
y = int(acret['result'][1])
iatapi.click(deviceid=devid, x=x, y=y) # 点击找到的坐标
点击打开低电量图标
imobj = imread('./img/打开低电量模式.bmp')
acret = ac.find_template(screenshot(devid), imobj, 0.8)
if acret is None:
print("没有找到子图")
exit()
print(acret)
print("查找打开低电量模式子图成功{}".format(acret['result']))
x = int(acret['result'][0])
y = int(acret['result'][1])
iatapi.click(deviceid=devid, x=x, y=y) # 点击找到的坐标
到此就全部完毕了,非常简单
下面是完整的代码:
import base64
import gzip
import io
import time
import ios_at_api # 导入ios_at_api模块
import aircv as ac
import cv2
import numpy as np
iatapi = ios_at_api.HttpApi('192.168.0.113') # 初始化IAT库,采用http协议进行交互
# 将base64字符串转换成cv2图片对象
def base64_to_bmp(data: dict):
image_base64 = data['data']['img']
is_gzip = data['data']['gzip']
imgdata = base64.b64decode(image_base64)
if is_gzip:
with gzip.GzipFile(fileobj=io.BytesIO(imgdata)) as f:
imgdata = f.read()
image = np.asarray(bytearray(imgdata), dtype="uint8")
im = cv2.imdecode(image, cv2.IMREAD_ANYCOLOR)
if im is None:
raise RuntimeError("读取图片流错误")
return im
# 将本地图片转换成cv2图片对象
def imread(filename):
im = cv2.imread(filename)
if im is None:
raise RuntimeError("file: '%s' not exists" % filename)
return im
def screenshot(deviceid):
image_data = iatapi.get_device_screenshot(deviceid=devid, gzip=False)
if image_data['status'] > 0:
print('截屏调用失败,原因:{}'.format(image_data['message']))
return None
else:
print('截屏调用成功')
return base64_to_bmp(image_data)
if __name__ == "__main__": # 主程序入口
# 如果不知道设备id可以用这条命令打印出所有的设备id print(iatapi.get_device_list())
devid = '5C:1D:D9:ED:D9:DE' # 要操作的设备id
for i in range(3): # 连续发送3次保证到达主屏幕
iatapi.send_key(deviceid=devid, key='', fn_key='WIN+h') # 发送返回主屏幕热键
time.sleep(0.5) # 延时一下,不然会变成APP切换器
imobj = imread('./img/设置按钮.bmp')
acret = ac.find_template(screenshot(devid), imobj, 0.8)
if acret is None:
print("没有找到子图")
exit()
print(acret)
print("查找设置按钮子图成功{}".format(acret['result']))
x = int(acret['result'][0])
y = int(acret['result'][1])
iatapi.click(deviceid=devid, x=x, y=y) # 点击找到的坐标
time.sleep(1) # 延时1秒钟
for i in range(3): # 往下滑动3次,保证到设置界面的最开始
iatapi.swipe(deviceid=devid, direction='down', length=0.8, afor=6)
time.sleep(1) # 延时1秒钟
for i in range(3): # 往上滑动3次
iatapi.swipe(deviceid=devid, direction='up', length=0.7, afor=10)
time.sleep(0.2) # 延时一下,避免滑动太快滑过了
time.sleep(1) # 延时1秒钟
imobj = imread('./img/电池图标.bmp')
acret = ac.find_template(screenshot(devid), imobj, 0.8)
if acret is None:
print("没有找到子图")
exit()
print(acret)
print("查找电池图标子图成功{}".format(acret['result']))
x = int(acret['result'][0])
y = int(acret['result'][1])
iatapi.click(deviceid=devid, x=x, y=y) # 点击找到的坐标
time.sleep(1) # 延时1秒钟
imobj = imread('./img/关闭低电量模式.bmp')
acret = ac.find_template(screenshot(devid), imobj, 0.8)
if not acret is None:
print("已经是低电量模式,无需打开")
exit()
imobj = imread('./img/打开低电量模式.bmp')
acret = ac.find_template(screenshot(devid), imobj, 0.8)
if acret is None:
print("没有找到子图")
exit()
print(acret)
print("查找打开低电量模式子图成功{}".format(acret['result']))
x = int(acret['result'][0])
y = int(acret['result'][1])
iatapi.click(deviceid=devid, x=x, y=y) # 点击找到的坐标