ATX2 入门进阶应用

前言

前面我们已经搭建好了ATX2平台来管理iOS设备,搭建博文参考:ATX2 iOS设备管理平台搭建 接下来分享一下该平台的入门进阶使用(还是基于iOS设备)。

ATX2入门操作

  1. 打开登录地址:http://172.28.xx.xx:4000/login 输入用户名登录ATX平台。
  2. 登录之后进入ATX2界面,在对应的设备点击点击使用则可以远程操作设备。
  3. 如下图所示,点击使用之后可以使用鼠标进行设备远程操作控制。

atx2_iOS_action

注意: iOS的弹窗不能通过屏幕点击来选择,需要在常用功能中点击“选择弹窗按钮”来进行操作

ATX2 API

ATX2提供了API可以进行调用,可以方便我们在自动化测试过程中进行调用。
API文档地址:https://github.com/openatx/atxserver2/blob/master/API.md

准备工作

token获取

ATX2所有的接口采用token认证,token可以在http://172.28.xx.xx:4000/user页面获取到
也可以点击右上角用户名->用户信息获取,如下图所示:

token

获取设备的udid

设备列表界面中的设备编号即为设备的udid,可以使用libimobiledevice命令获取设备的udid,命令如下:

1
2
MacBookPro:~ lemon$ idevice_id -l  # 显示当前所连接的设备[udid],包括 usb、WiFi 连接
c06e788b2d8dc60004a7015ce5dad782

API封装

为了更好的调用API,我们可以进行封装方法,便于后续的调用。首先如下所示,我们定义一个类AtxiOS 这个类进行远程调用设备的初始化操作,如atx地址和token的初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import json,logging
from urllib.parse import urljoin
import requests
from pprint import pprint

logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(filename)s[line:%(lineno)d]%(levelname)s%(message)s')

DEVICES_URL = '/api/v1/devices' #获取全部设备信息
USER_DEVICES_URL = '/api/v1/user/devices' #获取单台设备信息

class AtxiOS(object):
'''
封装ATX2接口用于设备远程操作
'''
def __init__(self, atx_url, token):
'''
初始化操作
:param atx_url: atx的url地址
:param token: 账户的token
'''
self.atx_url = atx_url
self.token = token
self.session = requests.Session()
self.headers = dict(Authorization="Bearer {}".format(self.token))
self.apply_devices = {}

def _get_response(self, url, method="GET", headers=None, data=None):
"""
获取API响应结果
:param url:返回的url地址
:param method:请求方法
:param headers:响应header内容
:param data:响应的data内容
:return: 返回响应信息
"""
if not headers:
headers = self.headers

try:
response = self.session.request(method, url, headers=headers, data=data, timeout=20)
info = response.json()
except Exception as error:
logging.error('网址:{}请求失败。{}'.format(url, error))
info = {'success': False, 'description': 'Bad request url: {}'.format(url)}
return info

获取所有iOS设备信息

在上面的AtxiOS类中定义如下方法用于获取所有iOS设备信息。

1
2
3
4
5
6
7
8
9
def get_all_iOS_devices(self):
"""
获取所有iOS设备
:return:
"""
url = urljoin(self.atx_url, DEVICES_URL)
info = self._get_response(url=url)
pprint(info)
return info

然后调用定义好的方法

1
2
3
4
5
6
ATX_URL ='http://172.28.xx.xx:4000'
Token='xxxxxxxxx'
udid='2cced5ac6ad06c35e067460dad5ff417f264b8ae' #iphone7

atx=AtxiOS(ATX_URL,Token)
atx.get_all_iOS_devices() #获取所有设备信息

调用之后返回结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
{'count': 4,
'devices': [{'colding': False,
'createdAt': '2019-06-11T16:57:17.371000',
'owner': '',
'platform': 'apple',
'present': False,
'properties': {'brand': 'Apple',
'name': '',
'product': 'Unknown'},
'udid': 'ece81864b51f3e0535bf86e9ab24f9209e9727f0',
'updatedAt': '2019-06-11T16:58:33.049000'},
{'colding': False,
'createdAt': '2019-06-11T10:17:43.340000',
'owner': '',
'platform': 'apple',
'present': False,
'properties': {'brand': 'Apple',
'name': '',
'product': 'Unknown'},
'udid': '6dd5e55bf4204cd5ad8042dc4ecb2b703bbdb435',
'updatedAt': '2019-06-11T10:21:28.894000',
'using': False},
{'colding': False,
'createdAt': '2019-06-06T08:54:42.115000',
'idleTimeout': 600,
'lastActivatedAt': '2019-06-10T09:12:46.465000',
'owner': '',
'platform': 'apple',
'present': False,
'properties': {'brand': 'Apple',
'ip': '172.28.212.16',
'name': 'iPhone6',
'product': 'iPhone 6',
'propertyId': '1908090114',
'sdkVersion': '12.2',
'version': '12.1.4'},
'udid': 'fa00fcc158dadb6bd1cc7c618540ebd7c3723520',
'updatedAt': '2019-06-10T10:13:48.662000',
'userId': None,
'using': False,
'usingBeganAt': '2019-06-10T09:02:10.333000',
'usingDuration': 1041.401},
{'colding': False,
'createdAt': '2019-05-30T21:39:47.708000',
'idleTimeout': 600,
'lastActivatedAt': '2019-06-11T16:53:32.250000',
'owner': '',
'platform': 'apple',
'present': True,
'properties': {'brand': 'Apple',
'ip': '172.28.213.231',
'name': 'iPhone 7',
'product': 'iPhone 7',
'propertyId': '1908090112',
'sdkVersion': '12.2',
'version': '12.1.4'},
'udid': '2cced5ac6ad06c35e067460dad5ff417f264b8ae',
'updatedAt': '2019-06-11T16:53:56.737000',
'userId': None,
'using': False,
'usingBeganAt': '2019-06-11T16:53:32.250000',
'usingDuration': 8877.971}],
'success': True}

几个比较重要的字段说明

  • platform目前有两个值androidapple
  • present代表设备是否在线
  • colding代表设备是否正在清理或者自检中, 此时是不能占用设备的
  • using代表设备是否有人正在使用
  • userId代表使用者的ID,这里的ID其实就是Email
  • properties代表设备的一些状态信息,基本都是静态信息

获取单个设备信息

如果我们想查看单个设备的信息,可以封装如下方法来查看。

1
2
3
4
5
6
7
8
9
10
11
def get_iOS_device_by_udid(self, udid):
"""
获取单个设备信息
:param udid:str 设备的 udid 字段
:return:
"""
left_url = "/".join([USER_DEVICES_URL, udid])
url = urljoin(self.atx_url, left_url)
info = self._get_response(url=url)
# pprint(info)
return info

调用方法如下:

1
2
3
4
5
6
7
ATX_URL ='http://172.28.xx.xx:4000'
Token='xxxxxxx'
udid='2cced5ac6ad06c35e067460dad5ff417f264b8ae' #iphone7

atx=AtxiOS(ATX_URL,Token)
device_info=atx.get_iOS_device_by_udid(udid) #获取单个设备信息
pprint(device_info)

返回内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{'device': {'colding': False,
'createdAt': '2019-05-30T21:39:47.708000',
'idleTimeout': 600,
'lastActivatedAt': '2019-06-11T16:53:32.250000',
'owner': '',
'platform': 'apple',
'properties': {'brand': 'Apple',
'ip': '172.28.213.231',
'name': 'iPhone 7',
'product': 'iPhone 7',
'propertyId': '1908090112',
'sdkVersion': '12.2',
'version': '12.1.4'},
'source': {'id': '0681c592-8bf4-11e9-afd1-0242ac120002',
'name': 'pyclient',
'owner': 'nobody@nobody.io',
'priority': 2,
'secret': '',
'url': 'http://172.28.xx.xx:3600',
'wdaUrl': 'http://172.28.xx.xx:20023'},
'sources': {'0681c592-8bf4-11e9-afd1-0242ac120002': {'id': '0681c592-8bf4-11e9-afd1-0242ac120002',
'name': 'pyclient',
'owner': 'nobody@nobody.io',
'priority': 2,
'secret': '',
'url': 'http://172.28.xx.xx:3600',
'wdaUrl': 'http://172.28.xx.xx:20023'}},
'udid': '2cced5ac6ad06c35e067460dad5ff417f264b8ae',
'updatedAt': '2019-06-11T16:53:56.737000',
'userId': None,
'using': False,
'usingBeganAt': '2019-06-11T16:53:32.250000',
'usingDuration': 8877.971},
'success': True}

获取设备远程WDA地址

每台挂载在ATX2平台的iOS设备都有一个唯一的WDA地址,我们可以根据这个地址来远程调用该设备,一般地址格式为:ATX地址IP+端口号

1
2
3
4
5
6
7
8
9
10
11

def get_wda_url(self,udid):
'''
获取iOS设备远程wda链接
:param udid: 设备udid
:return:
'''
device_info =self.get_iOS_device_by_udid(udid)
wda_url = device_info['device']['source']['wdaUrl']
logging.info('wda_url is %s' %wda_url)
return wda_url

调用方法

1
2
3
4
5
6
ATX_URL ='http://172.28.xx.xx:4000'
Token='a0344xxxxx45e92a396b0530'
udid='2cced5ac6ad06c35e067460dad5ff417f264b8ae' #iphone7

atx=AtxiOS(ATX_URL,Token)
atx.get_wda_url(udid) #获取设备的远程url地址

返回结果

1
http://172.28.xx.xx:200000

设备占用

1
2
3
4
5
6
7
8
9
10
11
12
def using_iOS_device(self, udid):
"""
占用一台设备
:param udid: str 设备的 udid 字段
:return:
"""
url = urljoin(self.atx_url, USER_DEVICES_URL)
data = {"udid": udid}
headers = self.headers
headers["Content-Type"] = "application/json"
info = self._get_response(url, "POST", headers, json.dumps(data))
logging.info(info)

调用方法

1
2
3
4
5
6
ATX_URL ='http://172.28.xx.xx:4000'
Token='a0344xxxxx45e92a396b0530'
udid='2cced5ac6ad06c35e067460dad5ff417f264b8ae' #iphone7

atx=AtxiOS(ATX_URL,Token)
atx.using_iOS_device(udid) #占用设备

调用方法之后会有三种情况,设备占用成功或失败,返回内容如下:

1
2
3
{'description': 'Device successfully added', 'success': True} #设备占用成功
{'description': 'Device add failed: device busy', 'success': False} #设备被其他人占用
{'success': False, 'description': 'Device add failed: device not exist'} #udid值错误

设备释放

使用完设备之后我们需要释放设备,定义方法如下:

1
2
3
4
5
6
7
8
9
10
11
def release_iOS_device(self, udid):
"""
释放iOS设备
:param udid:str 设备的 udid 字段
:return:
"""

left_url = "/".join([USER_DEVICES_URL, udid])
url = urljoin(self.atx_url, left_url)
info = self._get_response(url, "DELETE")
logging.info(info)

调用方法如下:

1
2
3
4
5
6
ATX_URL ='http://172.28.xx.xx:4000'
Token='a0344xxxxx45e92a396b0530'
udid='2cced5ac6ad06c35e067460dad5ff417f264b8ae' #iphone7

atx=AtxiOS(ATX_URL,Token)
atx.release_iOS_device(udid) #释放设备

设备释放成功时返回内容如下:

1
{'success': True, 'description': 'Device successfully released'}

注意:释放接口可以释放非当前账户占用的设备,释放时一定要确认udid是否为自己占用的设备,避免影响他人正常使用!

参考资料