UAT_runner.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. # -*- coding:utf-8 -*-
  2. from UAT_PathManage import UATPathManage
  3. from ssat_sdk.UATree.UAT_tree import UATTree
  4. from ssat_sdk.UATree.UAT_treeConstant import TreeConst
  5. from UAT_runnerCommand import UATRunnerCommand
  6. from ssat_sdk.python_uiautomator import PyUIAutomator, FocusManageAndroid, DirectionManageAndroid
  7. from UAT_log import error, debug, info
  8. import os, sys, time
  9. DEBUG = True
  10. INFO =True
  11. ERROR = True
  12. class UATRunner():
  13. cls = "UATRunner"
  14. def __init__(self):
  15. self.uatPathManage = UATPathManage()
  16. self.pyU = PyUIAutomator()
  17. self.dm = DirectionManageAndroid()
  18. self.fm = FocusManageAndroid(self.pyU, self.dm)
  19. self.runnerCmd = UATRunnerCommand(self.uatPathManage, self.pyU, self.dm, self.fm)
  20. # setOptionValue之后需要一个退回的pathlist来退出菜单
  21. self.executedPath = []
  22. '''
  23. 当电视重启以后,uiautomator连接会断开,需要重新赋予UATRunner一个可用的连接对象
  24. '''
  25. def rebuildUiAutomator(self, pyUIAutomator, directionManageAndroid, focusManageAndroid):
  26. self.pyU = pyUIAutomator
  27. self.dm = directionManageAndroid
  28. self.fm = focusManageAndroid
  29. self.runnerCmd = UATRunnerCommand(self.uatPathManage, self.pyU, self.dm, self.fm)
  30. '''
  31. 返回option的object
  32. '''
  33. def getOptionObject(self, option):
  34. className = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Class]
  35. desc = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Desc]
  36. resId = option[UATTree.TAB_OPTION_VIEW][UATTree.View_ID]
  37. text = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Text]
  38. return self.pyU.getUiObject(className=className, resourceId=resId, description=desc, text=text)
  39. '''
  40. 根据parent的layout和一个option判断在 UATree中的哪个界面,或者还没有进入UATree界面中
  41. :param option:目标option,表示在focusOption的路径上寻找界面定位。则根据excel分表查找
  42. :return parent数据,或者None。None代表未进入UATree界面中
  43. '''
  44. def locateParentUI(self, option=None):
  45. reg = ""
  46. if option is not None:
  47. print "locateParentUI,option:",option[UATTree.TAB_NAME]
  48. oname = option[UATTree.TAB_NAME]
  49. reg = oname.split("_")[0]
  50. print "locateParentUI,reg=",reg
  51. cparent = None
  52. treeDict = self.uatPathManage.uatData.getTreeDict()
  53. # print "locateParentUI: treeDict levels:",treeDict.keys()
  54. parentList = []
  55. levelList = treeDict.keys()
  56. flag = False
  57. for index in range(levelList.__len__()-1, -1, -1):
  58. level = levelList[index]
  59. # print "locateParentUI,level:", index, level
  60. levelDict = treeDict[level]
  61. for parent in levelDict:
  62. if reg.__len__() >0 and not parent.startswith(reg):
  63. continue
  64. parentDict = levelDict[parent]
  65. layout = parentDict["layout"]
  66. # print "locateParentUI: layout:", layout
  67. ret = self.runnerCmd.checkParentChoose(parentDict)
  68. if ret > 0:
  69. cparent = parentDict
  70. flag = True
  71. break
  72. if flag == True:
  73. break
  74. if cparent is None:
  75. info(self.cls, "locateParentUI", "没有选中Parent,电视界面不知道在哪里", INFO)
  76. else:
  77. info(self.cls, "locateParentUI", "选中Parent:" + cparent[UATTree.TAB_NAME], INFO)
  78. # print "ParentParam:", cparent
  79. return cparent
  80. '''
  81. 在该option所在页面下,聚焦到目标option
  82. '''
  83. def moveToOption(self, option):
  84. parent = self.uatPathManage.uatData.getParentByOption(option)
  85. return self.runnerCmd.focusTargetOption(parent, option)
  86. '''
  87. :return -1 执行失败,放弃重新定位执行;0 执行失败,重新定位执行; 1 执行成功
  88. '''
  89. def runForwardPath(self, backPath, forwardPath):
  90. fLen = forwardPath.__len__()
  91. fParent = forwardPath[fLen-1]
  92. # 当backPath和forwardPath的父交点为first层时,不能走shortcut_key,否则会导致执行出现问题(USB界面)
  93. if fParent[UATTree.TAB_LEVEL] == "first" \
  94. and backPath.__len__() < 2:
  95. ret = self.openFirstParent(fParent, forwardPath)
  96. if ret < 1: #注意打开firstparent界面成功,定位错误,会重新定位。场景:usb
  97. return ret
  98. # 逐步进入后面的parent页面
  99. else:
  100. ret = self.goMidPath(fParent, forwardPath[1: fLen- 1])
  101. if ret is False:
  102. return -1
  103. #在目标parent中,选中目标option
  104. return self.moveToOption(forwardPath[0])
  105. else:
  106. ret = self.goMidPath(forwardPath[fLen - 1], forwardPath[1:fLen - 1])
  107. if ret is False:
  108. return -1
  109. # 在目标parent中,选中目标option
  110. return self.moveToOption(forwardPath[0])
  111. '''
  112. 打开第一个页面
  113. :return: -1 代表activity打开失败,0 代表activity打开成功,焦点不在parent layout中;1 表示页面打开成功,焦点在parent layout中
  114. -2 表示处理弹窗的过程中失败了
  115. '''
  116. def openFirstParent(self, fParent, forwardPath):
  117. info(self.cls, "openFirstParent", "GOTO first parent " + fParent[UATTree.TAB_NAME], INFO)
  118. flag = self.runnerCmd.executeShortCutKey(fParent)
  119. if flag is False:
  120. error(self.cls, "openFirstParent", "Open first parent%s fail."%(fParent[UATTree.TAB_NAME]), ERROR)
  121. return -1
  122. ret = self.runnerCmd.executeDialog(fParent)
  123. if ret < 1:
  124. return -2
  125. flag1 = self.runnerCmd.checkParentChoose(fParent)
  126. if flag1 < 1:
  127. error(self.cls, "openFirstParent", "Open first parent activity.But parent %s not foucsed." % (fParent[UATTree.TAB_NAME]), ERROR)
  128. return 0
  129. return 1
  130. def goMidPath(self, curParent, midParentList):
  131. mLen = midParentList.__len__()
  132. for index in range(mLen-1, -1, -1):
  133. parent = midParentList[index]
  134. info(self.cls, "goMidPath", "GOTO parent %s from parent %s "%(parent[UATTree.TAB_NAME], curParent[UATTree.TAB_NAME]), INFO)
  135. ret = self.gotoNextParent(curParent, parent, midParentList)
  136. if ret == 0:
  137. return False
  138. curParent = parent
  139. return True
  140. '''
  141. :return 0:代表失败;1代表enterKey发送成功,进入下一个界面
  142. '''
  143. def gotoNextParent(self, curParent, targetParent, parentList):
  144. targetOptionName = targetParent[UATTree.TAB_NAME]
  145. targetOption = curParent[UATTree.TAB_OPTION][targetOptionName]
  146. flag = self.moveToOption(targetOption)
  147. if flag is False:
  148. return 0
  149. info(self.cls, "gotoNextParent", "moveToOption:%s done! executing enter key!"%targetOption[UATTree.TAB_NAME], INFO)
  150. ret = self.runnerCmd.executeEnterKey(targetOption[UATTree.TAB_ENTER_KEY], nextParent=targetParent)
  151. if ret is False:
  152. error(self.cls, "gotoNextParent",
  153. "Send parent %s enter key fail." % (curParent[UATTree.TAB_NAME]), ERROR)
  154. return 0
  155. else:
  156. ret = self.runnerCmd.executeDialog(targetParent)
  157. return ret
  158. '''
  159. 执行backPath
  160. :return true成功,false失败
  161. '''
  162. def runBackPath(self, backPath):
  163. bLen = backPath.__len__()
  164. if bLen <= 1:
  165. return False
  166. if bLen == 2:
  167. return True
  168. for index in range(1, bLen-1):
  169. curParent = backPath[index]
  170. prevParent = backPath[index+1]
  171. info(self.cls, "runBackPath", "back to parent %s from parent %s."
  172. %(backPath[index][UATTree.TAB_NAME], backPath[index+1][UATTree.TAB_NAME]), INFO)
  173. flag = self.backToPrevParent(curParent, prevParent)
  174. if flag is False:
  175. return False
  176. return True
  177. def backToPrevParent(self, curParent, targetParent):
  178. backKeys = curParent[UATTree.TAB_TOPARENT_KEY]
  179. self.runnerCmd.executeKey(backKeys)
  180. dialog_A = curParent[UATTree.TAB_UI_VIEW][UATTree.UIView_Dialog_B]
  181. if dialog_A.__len__() > 0:
  182. ret = self.runnerCmd.executeDialog(curParent, isForward=False)
  183. if ret == 0:
  184. return False
  185. flag = self.runnerCmd.checkParentChoose(targetParent)
  186. if flag < 1:
  187. error(self.cls, "backToPrevParent",
  188. "back to parent %s from parent %s fail." % (targetParent[UATTree.TAB_NAME], curParent[UATTree.TAB_NAME]), ERROR)
  189. return False
  190. return True
  191. '''
  192. fromFirst:表示是否指定从FirstParent打开开始路径执行。
  193. count:递归控制变量,执行路径的最大尝试次数
  194. '''
  195. def focusOption(self, option, fromFirst, count = 0):
  196. info(self.cls, "focusOption", "fromFirst:"+str(fromFirst), INFO)
  197. if fromFirst is True:
  198. curParent = None
  199. else:
  200. curParent = self.locateParentUI(option)
  201. backPath,forwardPath = self.uatPathManage.genOptionSmartPath(curParent, option)
  202. info(self.cls,"focusOption", "backPath:", INFO)
  203. self.uatPathManage.info(backPath)
  204. info(self.cls,"focusOption", "forwardPath:", INFO)
  205. self.uatPathManage.info(forwardPath)
  206. if forwardPath.__len__() == 0:
  207. return False
  208. if backPath.__len__() == 0 and forwardPath.__len__() >= 2:
  209. info(self.cls, "focusOption", "runBackPath success", INFO)
  210. ret = self.runForwardPath(backPath, forwardPath)
  211. self.executedPath = self.getExecutedPath(forwardPath)
  212. if ret ==0: #重新计算路径执行
  213. if count < 3:
  214. return self.focusOption(option, fromFirst, count+1)
  215. else:
  216. info(self.cls, "focusOption", "runForwardPath fail %s times, focusOption Fail!!!"%count, INFO)
  217. return False
  218. if backPath.__len__() >= 2 and forwardPath.__len__() >=2:
  219. backFlag = self.runBackPath(backPath)
  220. if backFlag is False:
  221. info(self.cls, "focusOption", "runBackPath fail", INFO)
  222. return False
  223. info(self.cls, "focusOption", "runBackPath success", INFO)
  224. goFlag = self.runForwardPath(backPath, forwardPath)
  225. self.executedPath = self.getExecutedPath(forwardPath)
  226. if goFlag < 1:
  227. info(self.cls, "focusOption", "runForwardPath fail", INFO)
  228. return False
  229. info(self.cls, "focusOption", "runForwardPath success", INFO)
  230. return True
  231. '''
  232. for exitMenuByPath
  233. 回退路径,仅仅只是使用forwardPath的话,最后一个元素是option,但是实际上已经进入了这个界面,应该判断的是parent。
  234. 所以要把forwardPath里面的option替换为parent;如果没有配这个option对应的parent,则去掉该option,以便exitMenuByPath函数使用。
  235. '''
  236. def getExecutedPath(self, forwardPath):
  237. option = forwardPath[0]
  238. parentName = option[UATTree.TAB_NAME]
  239. parent = self.uatPathManage.uatData.getParentDict(parentName)
  240. if parent is None:
  241. forwardPath.remove(option)
  242. else:
  243. forwardPath[0] = parent
  244. return forwardPath
  245. '''
  246. 执行该option的EnterKey
  247. '''
  248. def sendOptionEnterKey(self, option):
  249. enterKey = option[UATTree.TAB_ENTER_KEY]
  250. return self.runnerCmd.executeEnterKey(enterKey)
  251. '''
  252. 检查当前页面是否存在目标option
  253. '''
  254. def checkOptionExist(self, option):
  255. parent = self.uatPathManage.uatData.getParentByOption(option)
  256. if not self.runnerCmd.checkParentChoose(parent):
  257. return False
  258. return self.runnerCmd.checkOptionExist(option, parent)
  259. '''
  260. 在focusOption基础上,执行目标option的enter_key
  261. '''
  262. def openOption(self, option, fromFirst, nextParent = None):
  263. info(self.cls, "openOption", "OptionName:"+option[UATTree.TAB_NAME], INFO)
  264. ret = self.focusOption(option, fromFirst)
  265. if ret is False:
  266. return False
  267. ret = self.runnerCmd.executeEnterKey(option[UATTree.TAB_ENTER_KEY], nextParent)
  268. info(self.cls, "openOption", "executeKey,ret:%s" % ret, INFO)
  269. parent = self.uatPathManage.uatData.getParentDict(option[UATTree.TAB_NAME])
  270. if parent is None:
  271. return ret
  272. else:
  273. return self.runnerCmd.executeDialog(parent)
  274. def openParent(self, parent, fromFirst):
  275. if parent[UATTree.TAB_LEVEL] == 'first':
  276. return self.openFirstParent(parent, "")
  277. else:
  278. prevOption = self.uatPathManage.uatData.getOption(parent[UATTree.TAB_NAME])
  279. return self.openOption(prevOption, fromFirst, nextParent=parent)
  280. def setOptionValue(self, option, value, exitMenu=True, fromFirst=True):
  281. ret = self.openOption(option, fromFirst)
  282. if ret is False:
  283. info(self.cls, "setOptionValue", "openOption过程执行失败!!!", INFO)
  284. if exitMenu is True:
  285. self.runnerCmd.exitMenuByPath(self.executedPath)
  286. return False
  287. ret1 = self.runnerCmd.setValue(option, value)
  288. if exitMenu is True:
  289. ret2 = self.runnerCmd.exitMenuByPath(self.executedPath)
  290. else:
  291. ret2 = True
  292. return (ret1 and ret2)
  293. def checkOptionInfoView(self, option, cmpText = "", cmpPic = ""):
  294. infoObj = self.getOptionInfoView(option)
  295. result, picPath, cutPicPath = self.runnerCmd.getUIObjPic(infoObj)
  296. if result is False:
  297. error(self.cls, "checkOptionInfoView", "Warning:option %s 截取infoView所在坐标图片失败!!!" % option["name"], ERROR)
  298. return -1, picPath, cutPicPath
  299. if cmpPic != "":
  300. result = self.runnerCmd.infoViewCmpPic(cmpPic, cutPicPath)
  301. return result, picPath, cutPicPath
  302. elif cmpText != "":
  303. result = self.runnerCmd.infoViewCmpText(cmpText, cutPicPath)
  304. return result, picPath, cutPicPath
  305. else:
  306. info(self.cls, "checkOptionInfoView", "未传入cmpText和cmpPic参数,仅检查infoView是否存在", INFO)
  307. if infoObj is None:
  308. error(self.cls, "checkOptionInfoView", "Warning:option %s 获取infoView失败!!!" % option["name"],
  309. ERROR)
  310. return -1, picPath, cutPicPath
  311. else:
  312. info(self.cls, "checkOptionInfoView", "已识别到option %s的infoView" % option["name"], INFO)
  313. return 1, picPath, cutPicPath
  314. def getOptionInfoView(self, option):
  315. optionView = option[UATTree.TAB_INFO_VIEW]
  316. viewId = optionView[UATTree.View_ID]
  317. viewText = optionView[UATTree.View_Text]
  318. viewDesc = optionView[UATTree.View_Desc]
  319. viewClass = optionView[UATTree.View_Class]
  320. if viewId.__len__() == 0:
  321. return None
  322. infoObj = self.pyU.getUiObject(resourceId=viewId, text=viewText, className=viewClass, description=viewDesc)
  323. return infoObj
  324. if __name__ == "__main__":
  325. uatRunner = UATRunner()
  326. option = uatRunner.uatPathManage.uatData.getOption("usb_video_h264-ac3")
  327. uatRunner.openOption(option, False)
  328. # print uatRunner.locateParentUI()
  329. # parent = uatRunner.uatPathManage.uatData.getParentDict("usb_bmp")
  330. # uatRunner.runnerCmd.checkParentChoose(parent)
  331. # print option
  332. # option = uatRunner.uatPathManage.uatData.getOption("usb_aac_option")
  333. # cmpPic = r"D:/SAT/tmp\1572432282.74_cutPic_[932, 548, 1812, 597].png"
  334. # result, picpath, cutPicPath = uatRunner.checkOptionInfoView(option, cmpPic=cmpPic)
  335. # uatRunner.moveToOption(option)
  336. # parent = uatRunner.locateParentUI()
  337. # print "locateParentUI,parent:", parent
  338. # option = uatRunner.uatPathManage.uatData.getOption("usb_brightness")
  339. # print uatRunner.setOptionValue(option, 50)