check_device.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import os
  2. import subprocess
  3. import sys
  4. import telnetlib
  5. import threading
  6. import time
  7. import uiautomator2
  8. import uiautomator2 as u2
  9. import yaml
  10. from task.task_dict import script_status
  11. from tools import loggerKit
  12. from tools.common_util import extract_latency, check_network_quality
  13. from tools.device_status import DeviceStatus
  14. # 读取 YAML 文件
  15. with open('config.yaml', 'r') as file:
  16. config = yaml.load(file, Loader=yaml.FullLoader)
  17. wework_package = config['wework']['package']
  18. # net_domain = 'http://api-qa.risingauto.net/'
  19. net_domain = config['bmp-cp']['net_domain']
  20. # extern_domain = 'https://api-qa.risingauto.com/'
  21. extern_domain = config['bmp-cp']['extern_domain']
  22. # 获取连接设备
  23. def get_local_devices():
  24. # 执行 adb 命令并获取输出
  25. result = subprocess.run(['adb', 'devices'], capture_output=True, text=True)
  26. # 解析输出,获取已连接设备列表
  27. output_lines = result.stdout.strip().split('\n')
  28. devices = []
  29. for line in output_lines[1:]:
  30. if '\tdevice' in line:
  31. device_info = line.split('\t')[0]
  32. devices.append(device_info)
  33. # 输出已连接设备列表
  34. if devices:
  35. loggerKit.info("已连接设备:")
  36. for device in devices:
  37. loggerKit.info(device)
  38. else:
  39. loggerKit.info("没有已连接的设备")
  40. return devices
  41. # 检验设备是否连接成功
  42. def check_device_connect(device):
  43. devices = get_local_devices()
  44. if device in devices:
  45. loggerKit.info(device + "已连接")
  46. return True
  47. else:
  48. loggerKit.info(device + "未连接")
  49. return False
  50. # 判断网络代理端口是否是通的
  51. def check_telnet(host, port):
  52. '''
  53. :param host: host
  54. :param port: port
  55. :return:
  56. '''
  57. try:
  58. # 创建Telnet对象
  59. tn = telnetlib.Telnet(host, port, timeout=10)
  60. tn.close()
  61. return True
  62. except ConnectionRefusedError:
  63. return False
  64. except TimeoutError:
  65. return False
  66. except Exception as e:
  67. print("An error occurred:", e)
  68. return False
  69. '''
  70. 通用手机截图
  71. '''
  72. def cap_device(d, device, task_id):
  73. '''
  74. :param d: uiautomator2 对象
  75. :param device: 设备id
  76. :param task_id: 任务id
  77. :return:
  78. '''
  79. try:
  80. app_dir = os.path.dirname(sys.argv[0])
  81. screenshot_path = os.path.join(app_dir, f'screen/{device}/')
  82. tmp_path = screenshot_path.replace(":", "_").replace(".", "_")
  83. # 检查路径是否存在
  84. if not os.path.exists(tmp_path):
  85. # 创建多级目录
  86. os.makedirs(os.path.dirname(tmp_path))
  87. file_path = os.path.join(tmp_path, f'{device}_{task_id}_{time.time()}.png')
  88. d.screenshot().save(file_path)
  89. loggerKit.info(f'设备:{device} 执行任务出现异常,截图保存:{file_path}, tmp_path:{tmp_path}')
  90. except Exception as e:
  91. loggerKit.error(f'设备:{device} 执行任务出现异常后截图保存发生异常:{str(e)}')
  92. '''
  93. check 手机设备状态
  94. '''
  95. def check_single_adb_connect(device, mobile):
  96. target_url = extern_domain.replace("https://", "").replace("http://", "").replace("/", "")
  97. cmd_conn = f"adb connect {device}"
  98. conn_output = subprocess.check_output(cmd_conn, shell=True)
  99. loggerKit.info(f"{conn_output}")
  100. if b'Connection refused' in conn_output:
  101. loggerKit.info('手机待激活{0}->{1},不能领取任务', device, mobile)
  102. return DeviceStatus.Mobile_Phone_To_Be_Activated
  103. elif b'already connected' in conn_output:
  104. # 再次check 设备的 atx agent 服务状态
  105. w = uiautomator2.connect(device)
  106. # check atx agent 服务状态
  107. if w.agent_alive:
  108. loggerKit.info('atx-agent 服务正常, atx 已连接{0}->{1}, 再次成功连接', device, mobile)
  109. else:
  110. # 启动atx-agent服务,防止服务手动误关闭
  111. start_atx_agent = f"adb -s {device} shell /data/local/tmp/atx-agent server -d --nouia "
  112. opts_output = subprocess.check_output(start_atx_agent, shell=True)
  113. loggerKit.info(f"启动设备{device}->{mobile} atx agent 服务, {opts_output}, 再次成功连接")
  114. # check 设备是否在线
  115. cmd_show = f"adb devices -l | grep {device}"
  116. show_output = subprocess.check_output(cmd_show, shell=True)
  117. loggerKit.info(f"设备{device}->{mobile}, {show_output}")
  118. if b"device product" in show_output:
  119. loggerKit.info("设备在线{0}->{1}, 可以领取任务", device, mobile)
  120. d = uiautomator2.connect(device)
  121. loggerKit.info("{0}->{1}=>{2}", d.uiautomator.running(), device, mobile)
  122. if d.uiautomator.running():
  123. # loggerKit.info('atx 连接正常{0}->{1}, uiautomator2 服务正常, 开始判断设备网络质量', device, mobile)
  124. loggerKit.info('atx 连接正常{0}, uiautomator2 服务正常', device)
  125. # 判断手机端网络质量
  126. cmd_ping = f"adb -s " + device + " shell ping -c 6 " + target_url
  127. wifi_output = subprocess.check_output(cmd_ping, shell=True)
  128. byte_array = bytearray(wifi_output)
  129. byte_string = bytes(byte_array)
  130. # Convert byte string to string
  131. wifi_str = byte_string.decode('utf-8')
  132. latencies = extract_latency(wifi_str, device=device, mobile=mobile)
  133. network_quality = check_network_quality(latencies, device=device, mobile=mobile)
  134. match network_quality:
  135. case DeviceStatus.Device_Net_Good:
  136. loggerKit.info('atx 连接正常{0}, uiautomator2 服务正常, 设备网络质量良好, 可以领取任务', device)
  137. return DeviceStatus.Available_For_Task
  138. case DeviceStatus.Device_Net_Common:
  139. loggerKit.info('atx 连接正常{0}, uiautomator2 服务正常, 设备网络质量一般, 可以领取任务', device)
  140. return DeviceStatus.Available_For_Task
  141. case DeviceStatus.Device_Net_Bad:
  142. loggerKit.info('atx 连接正常{0}, uiautomator2 服务正常, 设备网络质量较差, 不能领取任务', device)
  143. return DeviceStatus.Device_Await_Recover
  144. if network_quality == DeviceStatus.Device_Net_Good:
  145. loggerKit.info('atx 连接正常{0}->{1}, uiautomator2 服务正常, 设备网络质量良好, 可以领取任务',
  146. device, mobile)
  147. return DeviceStatus.Available_For_Task
  148. elif network_quality == DeviceStatus.Device_Net_Common:
  149. loggerKit.info('atx 连接正常{0}->{1}, uiautomator2 服务正常, 设备网络质量一般, 可以领取任务',
  150. device, mobile)
  151. return DeviceStatus.Available_For_Task
  152. else:
  153. loggerKit.info('atx 连接正常{0}->{1}, uiautomator2 服务正常, 设备网络质量较差, 不能领取任务',
  154. device, mobile)
  155. return DeviceStatus.Device_Await_Recover
  156. return DeviceStatus.Available_For_Task
  157. else:
  158. loggerKit.info('atx 连接正常 {0}->{1}, uiautomator2 服务待人工启动, 不能领取任务', device, mobile)
  159. time.sleep(1)
  160. return DeviceStatus.To_Be_Manually_Started
  161. elif b"offline product" in show_output:
  162. loggerKit.info("设备不在线{0}->{1}, 不能领取任务", device, mobile)
  163. return DeviceStatus.Device_Offline
  164. else:
  165. loggerKit.info("{0}->{1}=>{2}", device, mobile, show_output)
  166. return DeviceStatus.Device_Offline
  167. elif b'connected to' in conn_output:
  168. u = uiautomator2.connect(device)
  169. # check atx agent 服务状态
  170. if u.agent_alive:
  171. loggerKit.info('atx-agent 服务正常, atx 已连接{0}->{1}, 首次成功连接', device, mobile)
  172. else:
  173. # 启动atx-agent服务,防止服务手动误关闭
  174. cmd_start_atx_agent = f"adb -s {device} shell /data/local/tmp/atx-agent server -d --nouia "
  175. opt_output = subprocess.check_output(cmd_start_atx_agent, shell=True)
  176. loggerKit.info(f"启动设备{device}->{mobile} atx agent 服务, {opt_output}, 首次成功连接")
  177. return DeviceStatus.First_Success_Connect
  178. else:
  179. loggerKit('atx已连接{0}->{1}, 首次成功连接', device, mobile)
  180. return DeviceStatus.First_Success_Connect
  181. def reboot_device(device_serial, exception):
  182. # 连接设备
  183. device = u2.connect(device_serial)
  184. device.healthcheck()
  185. device.screen_on()
  186. device.unlock()
  187. device.debug = False
  188. # 重启企业微信
  189. device.app_stop("com.tencent.wework")
  190. device.app_start("com.tencent.wework")
  191. loggerKit.info("异常, 重启设备 {0}, 异常原因:{1}", device_serial, exception)
  192. # 机器人操作重试机制
  193. def retry(operation, device_serial, content, retries=3, retry_interval=1):
  194. for i in range(retries):
  195. try:
  196. return operation()
  197. except Exception as e:
  198. if i == retries - 1: # 如果已经重试了retries次,那么抛出异常
  199. raise e
  200. time.sleep(retry_interval) # 等待1秒再重试
  201. loggerKit.info("thread[{0}=>{1}], 设备号:{2}, 触发重试机制, 已经重试了{3}次",
  202. threading.current_thread().name, threading.get_ident(),
  203. device_serial, i)
  204. status = script_status(0, 500, content, '')
  205. reboot_device(device_serial, content)
  206. loggerKit.error("thread[{0}=>{1}], 设备号:{2}, {3}", threading.current_thread().name,
  207. threading.get_ident(), device_serial, content)
  208. return status