# -*- coding:utf-8 -*- from UAT_PathManage import UATPathManage from ssat_sdk.UATree.UAT_tree import UATTree from ssat_sdk.UATree.UAT_treeConstant import TreeConst from UAT_runnerCommand import UATRunnerCommand from ssat_sdk.python_uiautomator import PyUIAutomator, FocusManageAndroid, DirectionManageAndroid from UAT_log import error, debug, info import os, sys, time DEBUG = True INFO =True ERROR = True class UATRunner(): cls = "UATRunner" def __init__(self): self.uatPathManage = UATPathManage() self.pyU = PyUIAutomator() self.dm = DirectionManageAndroid() self.fm = FocusManageAndroid(self.pyU, self.dm) self.runnerCmd = UATRunnerCommand(self.uatPathManage, self.pyU, self.dm, self.fm) # setOptionValue之后需要一个退回的pathlist来退出菜单 self.executedPath = [] ''' 当电视重启以后,uiautomator连接会断开,需要重新赋予UATRunner一个可用的连接对象 ''' def rebuildUiAutomator(self, pyUIAutomator, directionManageAndroid, focusManageAndroid): self.pyU = pyUIAutomator self.dm = directionManageAndroid self.fm = focusManageAndroid self.runnerCmd = UATRunnerCommand(self.uatPathManage, self.pyU, self.dm, self.fm) ''' 返回option的object ''' def getOptionObject(self, option): className = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Class] desc = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Desc] resId = option[UATTree.TAB_OPTION_VIEW][UATTree.View_ID] text = option[UATTree.TAB_OPTION_VIEW][UATTree.View_Text] return self.pyU.getUiObject(className=className, resourceId=resId, description=desc, text=text) ''' 根据parent的layout和一个option判断在 UATree中的哪个界面,或者还没有进入UATree界面中 :param option:目标option,表示在focusOption的路径上寻找界面定位。则根据excel分表查找 :return parent数据,或者None。None代表未进入UATree界面中 ''' def locateParentUI(self, option=None): reg = "" if option is not None: print "locateParentUI,option:",option[UATTree.TAB_NAME] oname = option[UATTree.TAB_NAME] reg = oname.split("_")[0] print "locateParentUI,reg=",reg cparent = None treeDict = self.uatPathManage.uatData.getTreeDict() # print "locateParentUI: treeDict levels:",treeDict.keys() parentList = [] levelList = treeDict.keys() flag = False for index in range(levelList.__len__()-1, -1, -1): level = levelList[index] # print "locateParentUI,level:", index, level levelDict = treeDict[level] for parent in levelDict: if reg.__len__() >0 and not parent.startswith(reg): continue parentDict = levelDict[parent] layout = parentDict["layout"] # print "locateParentUI: layout:", layout ret = self.runnerCmd.checkParentChoose(parentDict) if ret > 0: cparent = parentDict flag = True break if flag == True: break if cparent is None: info(self.cls, "locateParentUI", "没有选中Parent,电视界面不知道在哪里", INFO) else: info(self.cls, "locateParentUI", "选中Parent:" + cparent[UATTree.TAB_NAME], INFO) # print "ParentParam:", cparent return cparent ''' 在该option所在页面下,聚焦到目标option ''' def moveToOption(self, option): parent = self.uatPathManage.uatData.getParentByOption(option) return self.runnerCmd.focusTargetOption(parent, option) ''' :return -1 执行失败,放弃重新定位执行;0 执行失败,重新定位执行; 1 执行成功 ''' def runForwardPath(self, backPath, forwardPath): fLen = forwardPath.__len__() fParent = forwardPath[fLen-1] # 当backPath和forwardPath的父交点为first层时,不能走shortcut_key,否则会导致执行出现问题(USB界面) if fParent[UATTree.TAB_LEVEL] == "first" \ and backPath.__len__() < 2: ret = self.openFirstParent(fParent, forwardPath) if ret < 1: #注意打开firstparent界面成功,定位错误,会重新定位。场景:usb return ret # 逐步进入后面的parent页面 else: ret = self.goMidPath(fParent, forwardPath[1: fLen- 1]) if ret is False: return -1 #在目标parent中,选中目标option return self.moveToOption(forwardPath[0]) else: ret = self.goMidPath(forwardPath[fLen - 1], forwardPath[1:fLen - 1]) if ret is False: return -1 # 在目标parent中,选中目标option return self.moveToOption(forwardPath[0]) ''' 打开第一个页面 :return: -1 代表activity打开失败,0 代表activity打开成功,焦点不在parent layout中;1 表示页面打开成功,焦点在parent layout中 -2 表示处理弹窗的过程中失败了 ''' def openFirstParent(self, fParent, forwardPath): info(self.cls, "openFirstParent", "GOTO first parent " + fParent[UATTree.TAB_NAME], INFO) flag = self.runnerCmd.executeShortCutKey(fParent) if flag is False: error(self.cls, "openFirstParent", "Open first parent%s fail."%(fParent[UATTree.TAB_NAME]), ERROR) return -1 ret = self.runnerCmd.executeDialog(fParent) if ret < 1: return -2 flag1 = self.runnerCmd.checkParentChoose(fParent) if flag1 < 1: error(self.cls, "openFirstParent", "Open first parent activity.But parent %s not foucsed." % (fParent[UATTree.TAB_NAME]), ERROR) return 0 return 1 def goMidPath(self, curParent, midParentList): mLen = midParentList.__len__() for index in range(mLen-1, -1, -1): parent = midParentList[index] info(self.cls, "goMidPath", "GOTO parent %s from parent %s "%(parent[UATTree.TAB_NAME], curParent[UATTree.TAB_NAME]), INFO) ret = self.gotoNextParent(curParent, parent, midParentList) if ret == 0: return False curParent = parent return True ''' :return 0:代表失败;1代表enterKey发送成功,进入下一个界面 ''' def gotoNextParent(self, curParent, targetParent, parentList): targetOptionName = targetParent[UATTree.TAB_NAME] targetOption = curParent[UATTree.TAB_OPTION][targetOptionName] flag = self.moveToOption(targetOption) if flag is False: return 0 info(self.cls, "gotoNextParent", "moveToOption:%s done! executing enter key!"%targetOption[UATTree.TAB_NAME], INFO) ret = self.runnerCmd.executeEnterKey(targetOption[UATTree.TAB_ENTER_KEY], nextParent=targetParent) if ret is False: error(self.cls, "gotoNextParent", "Send parent %s enter key fail." % (curParent[UATTree.TAB_NAME]), ERROR) return 0 else: ret = self.runnerCmd.executeDialog(targetParent) return ret ''' 执行backPath :return true成功,false失败 ''' def runBackPath(self, backPath): bLen = backPath.__len__() if bLen <= 1: return False if bLen == 2: return True for index in range(1, bLen-1): curParent = backPath[index] prevParent = backPath[index+1] info(self.cls, "runBackPath", "back to parent %s from parent %s." %(backPath[index][UATTree.TAB_NAME], backPath[index+1][UATTree.TAB_NAME]), INFO) flag = self.backToPrevParent(curParent, prevParent) if flag is False: return False return True def backToPrevParent(self, curParent, targetParent): backKeys = curParent[UATTree.TAB_TOPARENT_KEY] self.runnerCmd.executeKey(backKeys) dialog_A = curParent[UATTree.TAB_UI_VIEW][UATTree.UIView_Dialog_B] if dialog_A.__len__() > 0: ret = self.runnerCmd.executeDialog(curParent, isForward=False) if ret == 0: return False flag = self.runnerCmd.checkParentChoose(targetParent) if flag < 1: error(self.cls, "backToPrevParent", "back to parent %s from parent %s fail." % (targetParent[UATTree.TAB_NAME], curParent[UATTree.TAB_NAME]), ERROR) return False return True ''' fromFirst:表示是否指定从FirstParent打开开始路径执行。 count:递归控制变量,执行路径的最大尝试次数 ''' def focusOption(self, option, fromFirst, count = 0): info(self.cls, "focusOption", "fromFirst:"+str(fromFirst), INFO) if fromFirst is True: curParent = None else: curParent = self.locateParentUI(option) backPath,forwardPath = self.uatPathManage.genOptionSmartPath(curParent, option) info(self.cls,"focusOption", "backPath:", INFO) self.uatPathManage.info(backPath) info(self.cls,"focusOption", "forwardPath:", INFO) self.uatPathManage.info(forwardPath) if forwardPath.__len__() == 0: return False if backPath.__len__() == 0 and forwardPath.__len__() >= 2: info(self.cls, "focusOption", "runBackPath success", INFO) ret = self.runForwardPath(backPath, forwardPath) self.executedPath = self.getExecutedPath(forwardPath) if ret ==0: #重新计算路径执行 if count < 3: return self.focusOption(option, fromFirst, count+1) else: info(self.cls, "focusOption", "runForwardPath fail %s times, focusOption Fail!!!"%count, INFO) return False if backPath.__len__() >= 2 and forwardPath.__len__() >=2: backFlag = self.runBackPath(backPath) if backFlag is False: info(self.cls, "focusOption", "runBackPath fail", INFO) return False info(self.cls, "focusOption", "runBackPath success", INFO) goFlag = self.runForwardPath(backPath, forwardPath) self.executedPath = self.getExecutedPath(forwardPath) if goFlag < 1: info(self.cls, "focusOption", "runForwardPath fail", INFO) return False info(self.cls, "focusOption", "runForwardPath success", INFO) return True ''' for exitMenuByPath 回退路径,仅仅只是使用forwardPath的话,最后一个元素是option,但是实际上已经进入了这个界面,应该判断的是parent。 所以要把forwardPath里面的option替换为parent;如果没有配这个option对应的parent,则去掉该option,以便exitMenuByPath函数使用。 ''' def getExecutedPath(self, forwardPath): option = forwardPath[0] parentName = option[UATTree.TAB_NAME] parent = self.uatPathManage.uatData.getParentDict(parentName) if parent is None: forwardPath.remove(option) else: forwardPath[0] = parent return forwardPath ''' 执行该option的EnterKey ''' def sendOptionEnterKey(self, option): enterKey = option[UATTree.TAB_ENTER_KEY] return self.runnerCmd.executeEnterKey(enterKey) ''' 检查当前页面是否存在目标option ''' def checkOptionExist(self, option): parent = self.uatPathManage.uatData.getParentByOption(option) if not self.runnerCmd.checkParentChoose(parent): return False return self.runnerCmd.checkOptionExist(option, parent) ''' 在focusOption基础上,执行目标option的enter_key ''' def openOption(self, option, fromFirst, nextParent = None): info(self.cls, "openOption", "OptionName:"+option[UATTree.TAB_NAME], INFO) ret = self.focusOption(option, fromFirst) if ret is False: return False ret = self.runnerCmd.executeEnterKey(option[UATTree.TAB_ENTER_KEY], nextParent) info(self.cls, "openOption", "executeKey,ret:%s" % ret, INFO) parent = self.uatPathManage.uatData.getParentDict(option[UATTree.TAB_NAME]) if parent is None: return ret else: return self.runnerCmd.executeDialog(parent) def openParent(self, parent, fromFirst): if parent[UATTree.TAB_LEVEL] == 'first': return self.openFirstParent(parent, "") else: prevOption = self.uatPathManage.uatData.getOption(parent[UATTree.TAB_NAME]) return self.openOption(prevOption, fromFirst, nextParent=parent) def setOptionValue(self, option, value, exitMenu=True, fromFirst=True): ret = self.openOption(option, fromFirst) if ret is False: info(self.cls, "setOptionValue", "openOption过程执行失败!!!", INFO) if exitMenu is True: self.runnerCmd.exitMenuByPath(self.executedPath) return False ret1 = self.runnerCmd.setValue(option, value) if exitMenu is True: ret2 = self.runnerCmd.exitMenuByPath(self.executedPath) else: ret2 = True return (ret1 and ret2) def checkOptionInfoView(self, option, cmpText = "", cmpPic = ""): infoObj = self.getOptionInfoView(option) result, picPath, cutPicPath = self.runnerCmd.getUIObjPic(infoObj) if result is False: error(self.cls, "checkOptionInfoView", "Warning:option %s 截取infoView所在坐标图片失败!!!" % option["name"], ERROR) return -1, picPath, cutPicPath if cmpPic != "": result = self.runnerCmd.infoViewCmpPic(cmpPic, cutPicPath) return result, picPath, cutPicPath elif cmpText != "": result = self.runnerCmd.infoViewCmpText(cmpText, cutPicPath) return result, picPath, cutPicPath else: info(self.cls, "checkOptionInfoView", "未传入cmpText和cmpPic参数,仅检查infoView是否存在", INFO) if infoObj is None: error(self.cls, "checkOptionInfoView", "Warning:option %s 获取infoView失败!!!" % option["name"], ERROR) return -1, picPath, cutPicPath else: info(self.cls, "checkOptionInfoView", "已识别到option %s的infoView" % option["name"], INFO) return 1, picPath, cutPicPath def getOptionInfoView(self, option): optionView = option[UATTree.TAB_INFO_VIEW] viewId = optionView[UATTree.View_ID] viewText = optionView[UATTree.View_Text] viewDesc = optionView[UATTree.View_Desc] viewClass = optionView[UATTree.View_Class] if viewId.__len__() == 0: return None infoObj = self.pyU.getUiObject(resourceId=viewId, text=viewText, className=viewClass, description=viewDesc) return infoObj if __name__ == "__main__": uatRunner = UATRunner() option = uatRunner.uatPathManage.uatData.getOption("usb_video_h264-ac3") uatRunner.openOption(option, False) # print uatRunner.locateParentUI() # parent = uatRunner.uatPathManage.uatData.getParentDict("usb_bmp") # uatRunner.runnerCmd.checkParentChoose(parent) # print option # option = uatRunner.uatPathManage.uatData.getOption("usb_aac_option") # cmpPic = r"D:/SAT/tmp\1572432282.74_cutPic_[932, 548, 1812, 597].png" # result, picpath, cutPicPath = uatRunner.checkOptionInfoView(option, cmpPic=cmpPic) # uatRunner.moveToOption(option) # parent = uatRunner.locateParentUI() # print "locateParentUI,parent:", parent # option = uatRunner.uatPathManage.uatData.getOption("usb_brightness") # print uatRunner.setOptionValue(option, 50)