|
@@ -15,6 +15,42 @@ g_level = ['First', 'Second', 'Third', 'Fourth', 'Fifth', 'Sixth',
|
|
|
'Seventh', 'Eighth', 'Ninth', 'Tenth', 'Eleventh', 'Twelfth']
|
|
|
|
|
|
|
|
|
+def takePicture():
|
|
|
+ img = os.path.join(getSATTmpDIR(), "menutree_runpath.png")
|
|
|
+ COptionAction.__ccard.takePicture(img)
|
|
|
+ return img
|
|
|
+
|
|
|
+
|
|
|
+def strSplit(text):
|
|
|
+ ret = []
|
|
|
+ str_int = ''
|
|
|
+ str_ch = ''
|
|
|
+ ch_last = ' '
|
|
|
+ for ch in text:
|
|
|
+ if 47 < ord(ch) < 58:
|
|
|
+ str_int += ch
|
|
|
+ if str_ch.__len__():
|
|
|
+ ret.append(str_ch)
|
|
|
+ str_ch = ''
|
|
|
+ else:
|
|
|
+ if 47 < ord(ch_last) < 58 and ch == '.':
|
|
|
+ str_int += ch
|
|
|
+ if str_ch.__len__():
|
|
|
+ ret.append(str_ch)
|
|
|
+ str_ch = ''
|
|
|
+ else:
|
|
|
+ str_ch += ch
|
|
|
+ if str_int.__len__():
|
|
|
+ ret.append(str_int)
|
|
|
+ str_int = ''
|
|
|
+ ch_last = ch
|
|
|
+ if str_ch.__len__():
|
|
|
+ ret.append(str_ch)
|
|
|
+ if str_int.__len__():
|
|
|
+ ret.append(str_int)
|
|
|
+ return ret
|
|
|
+
|
|
|
+
|
|
|
# 注意:所有不对外暴露的变量和函数需要私有化,以明确哪些接口和参数是对外的。
|
|
|
# 这样便于后期维护时,根据对外的变量和函数来做处理。
|
|
|
class COptionAction(CBaseLog):
|
|
@@ -29,12 +65,13 @@ class COptionAction(CBaseLog):
|
|
|
# 发送鲜活键;
|
|
|
@staticmethod
|
|
|
def __sendAliveKey(aliveKey):
|
|
|
- if aliveKey is not None:
|
|
|
+ if aliveKey is not None and aliveKey.__len__() > 0:
|
|
|
COptionAction.__redRat3.sendKey(aliveKey, 1, 0.1)
|
|
|
|
|
|
def __init__(self, optionName, optionValue, optionConfig, optionExcel):
|
|
|
# 层级位置;
|
|
|
self.__pos = 0
|
|
|
+ # 目标option;
|
|
|
self.__optionName = optionName
|
|
|
# __optionValue可空;
|
|
|
self.__optionValue = optionValue
|
|
@@ -51,55 +88,29 @@ class COptionAction(CBaseLog):
|
|
|
if self.__optionValue != "":
|
|
|
self.__optionValues = self.__optionExcel.getOptionValueInfo(self.__optionName, self.__optionValue)
|
|
|
self.__optionInfo = self.__optionExcel.getOptionInfo(self.__optionName)
|
|
|
- # 当前状态下的变量
|
|
|
+ # 当前状态下的变量,与__pos对应;
|
|
|
self.__curOptionName = ''
|
|
|
self.__curOptionInfo = None
|
|
|
+ # 获取一次当前层级信息;
|
|
|
+ self.getCurOptionInfo()
|
|
|
+
|
|
|
+ @property
|
|
|
+ def pos(self):
|
|
|
+ return self.__pos
|
|
|
+
|
|
|
+ @property
|
|
|
+ def curOptionName(self):
|
|
|
+ return self.__curOptionName
|
|
|
+
|
|
|
+ @property
|
|
|
+ def curOptionInfo(self):
|
|
|
+ return self.__curOptionInfo
|
|
|
|
|
|
'''
|
|
|
- 函数:
|
|
|
+ 函数:调用根节点快捷键(中间节点不需要快捷键;);
|
|
|
参数:
|
|
|
- 注意:
|
|
|
返回:
|
|
|
-
|
|
|
- 测试:。
|
|
|
'''
|
|
|
-
|
|
|
- def strSplit(self, text):
|
|
|
- ret = []
|
|
|
- str_int = ''
|
|
|
- str_ch = ''
|
|
|
- ch_last = ' '
|
|
|
- for ch in text:
|
|
|
- if 47 < ord(ch) < 58:
|
|
|
- str_int += ch
|
|
|
- if str_ch.__len__():
|
|
|
- ret.append(str_ch)
|
|
|
- str_ch = ''
|
|
|
- else:
|
|
|
- if 47 < ord(ch_last) < 58 and ch == '.':
|
|
|
- str_int += ch
|
|
|
- if str_ch.__len__():
|
|
|
- ret.append(str_ch)
|
|
|
- str_ch = ''
|
|
|
- else:
|
|
|
- str_ch += ch
|
|
|
- if str_int.__len__():
|
|
|
- ret.append(str_int)
|
|
|
- str_int = ''
|
|
|
- ch_last = ch
|
|
|
- if str_ch.__len__():
|
|
|
- ret.append(str_ch)
|
|
|
- if str_int.__len__():
|
|
|
- ret.append(str_int)
|
|
|
- return ret
|
|
|
-
|
|
|
- # 截图;
|
|
|
- def takePicture(self):
|
|
|
- pic = os.path.join(getSATTmpDIR(), "menutree_runpath.png")
|
|
|
- COptionAction.__ccard.takePicture(pic)
|
|
|
- return pic
|
|
|
-
|
|
|
- # 调用根节点快捷键(中间节点不需要快捷键;);
|
|
|
def callFirstOptionShortCutKey(self):
|
|
|
if 'shortcut_key' in self.__optionPaths['First']:
|
|
|
COptionAction.__redRat3.sendKey(self.__optionPaths['First']['shortcut_key'])
|
|
@@ -107,7 +118,11 @@ class COptionAction(CBaseLog):
|
|
|
COptionAction.__redRat3.sendKey(self.__optionPaths['First']['parent'])
|
|
|
self.warn(u"表格没有shortcut_key字段,执行默认的parent按键:%s" % self.__optionPaths['First']['parent'])
|
|
|
|
|
|
- # 调用当前结点的toparent_key;
|
|
|
+ '''
|
|
|
+ 函数:调用当前结点的toparent_key
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
def callCurOptionBackKey(self, curOptionName):
|
|
|
curOptionInfo = self.__optionExcel.getOptionInfo(curOptionName)
|
|
|
if 'toparent_key' in self.__optionPaths[curOptionInfo['level']]:
|
|
@@ -140,7 +155,7 @@ class COptionAction(CBaseLog):
|
|
|
'''
|
|
|
|
|
|
def isOnFirstOption(self):
|
|
|
- pic = self.takePicture()
|
|
|
+ pic = takePicture()
|
|
|
return self.__optionFocus.findFocusByIcon(pic, self.__optionPaths['First']['option'])[0]
|
|
|
|
|
|
'''
|
|
@@ -169,6 +184,8 @@ class COptionAction(CBaseLog):
|
|
|
else:
|
|
|
isValueSheet = True if self.__pos >= self.__optionPaths.__len__() else False
|
|
|
|
|
|
+ self.info(u"当前层级在:%s" % ("value表" if isValueSheet else "路径表"))
|
|
|
+
|
|
|
# 获取文本识别的参数;
|
|
|
ocrConfigList = self.__optionConfig.getOptionOCRConfig(curOption)
|
|
|
ocrThreshold = self.__optionConfig.getThresholdDict(firstParent) # 注意,此处使用firstParent;
|
|
@@ -188,20 +205,120 @@ class COptionAction(CBaseLog):
|
|
|
# 注:value表中的option实际并没有兄弟项,取的是所有value项
|
|
|
if isValueSheet and siblingTextList.__len__():
|
|
|
if siblingTextList[0].startswith('range('):
|
|
|
+ self.info(u"识别的内容是value表数字内容(range(0,xx)类型)")
|
|
|
isNumberText = True
|
|
|
|
|
|
# 是否为静态焦点识别(动态则为跑马灯);
|
|
|
if curOthers.__len__() and 'marquee' in curOthers:
|
|
|
- pic = self.takePicture()
|
|
|
- return self.__getDynamicPicText(pic, curOption, optionTextList, siblingTextList, ocrConfigList, ocrThreshold, curOthers['marquee'],
|
|
|
+ return self.__getDynamicPicText(curOption, optionTextList, siblingTextList, ocrConfigList,
|
|
|
+ ocrThreshold, curOthers['marquee'],
|
|
|
isNumberText, isValueSheet)
|
|
|
else:
|
|
|
- return self.__getStaticPicText(curOption, optionTextList, siblingTextList, ocrConfigList, ocrThreshold,
|
|
|
+ return self.__getStaticPicText(takePicture(), curOption, optionTextList, siblingTextList, ocrConfigList,
|
|
|
+ ocrThreshold,
|
|
|
isNumberText, isValueSheet)
|
|
|
# endif
|
|
|
|
|
|
- # 获取静态图片文本内容;
|
|
|
- def __getStaticPicText(self, pic, optionName, optionTextList, siblingTextList, ocrConfigList, ocrThreshold, isNumberText,
|
|
|
+ '''
|
|
|
+ 函数:移动到下一兄弟节点;
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def move2NextSiblingOption(self):
|
|
|
+ # 获取当前option信息;
|
|
|
+ self.getCurOptionInfo()
|
|
|
+ # 析出move key;
|
|
|
+ optionMoveKey = self.__curOptionInfo['option_move_key']
|
|
|
+ if optionMoveKey.__len__() == 0:
|
|
|
+ self.sendKey(self.__curOptionInfo['move_key'][1], 1, 0.1)
|
|
|
+ else:
|
|
|
+ self.sendKey(optionMoveKey[1], 1, 0.1)
|
|
|
+
|
|
|
+ '''
|
|
|
+ 函数:移动到上一兄弟节点
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def move2PrevSiblingOption(self):
|
|
|
+ # 获取当前option信息;
|
|
|
+ self.getCurOptionInfo()
|
|
|
+ # 析出move key;
|
|
|
+ optionMoveKey = self.__curOptionInfo['option_move_key']
|
|
|
+ if optionMoveKey.__len__() == 0:
|
|
|
+ self.sendKey(self.__curOptionInfo['move_key'][0], 1, 0.1)
|
|
|
+ else:
|
|
|
+ self.sendKey(optionMoveKey[0], 1, 0.1)
|
|
|
+
|
|
|
+ '''
|
|
|
+ 函数:返回到父节点
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def back2ParentOption(self):
|
|
|
+ # 获取当前option信息;
|
|
|
+ self.getCurOptionInfo()
|
|
|
+ # 析出move key;
|
|
|
+ backKey = self.__curOptionInfo['back_key']
|
|
|
+ if backKey.__len__() == 0:
|
|
|
+ self.sendKey('back', 1, 0.1)
|
|
|
+ else:
|
|
|
+ self.sendKey(backKey, 1, 0.1)
|
|
|
+
|
|
|
+ '''
|
|
|
+ 函数:进入当前节点;
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def enterOption(self):
|
|
|
+ # 获取当前option信息;
|
|
|
+ self.getCurOptionInfo()
|
|
|
+ # 析出enter key;
|
|
|
+ optionEnterKey = self.__curOptionInfo['option_enter_key']
|
|
|
+ if optionEnterKey.__len__() == 0:
|
|
|
+ self.sendKey(self.__curOptionInfo['enter_key'], 1, 0.)
|
|
|
+ else:
|
|
|
+ self.sendKey(optionEnterKey, 1, 0.1)
|
|
|
+
|
|
|
+ '''
|
|
|
+ 函数:设置当前option的值;
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def setCurOptionValue(self, value):
|
|
|
+ # 获取当前option信息;
|
|
|
+ self.getCurOptionInfo()
|
|
|
+ # 获取当前option的value表信息;
|
|
|
+ curOptionValueInfo = self.__optionExcel.getOptionValueInfo(self.__curOptionName, value)
|
|
|
+
|
|
|
+ '''
|
|
|
+ 函数:
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def getCurOptionInfo(self):
|
|
|
+ if self.__pos >= self.__optionPaths.__len__():
|
|
|
+ self.warn(u"已到达value节点,无法获取路径信息")
|
|
|
+ return False
|
|
|
+
|
|
|
+ # 只有第一次或层级移动了才需要更新;
|
|
|
+ if self.__curOptionInfo is None or self.__pos != self.__curOptionInfo['layers']:
|
|
|
+ self.__curOptionName = self.__optionPaths[g_level[self.__pos]]['option']
|
|
|
+ self.__curOptionInfo = self.__optionExcel.getOptionInfo(self.__curOptionName, self.__optionPaths)
|
|
|
+
|
|
|
+ return True
|
|
|
+
|
|
|
+
|
|
|
+ '''
|
|
|
+ 函数:获取静态图片文本内容
|
|
|
+ 参数:
|
|
|
+ 注意:
|
|
|
+ 返回:
|
|
|
+
|
|
|
+ 测试:。
|
|
|
+ '''
|
|
|
+
|
|
|
+ def __getStaticPicText(self, pic, optionName, optionTextList, siblingTextList, ocrConfigList, ocrThreshold,
|
|
|
+ isNumberText,
|
|
|
isValueSheet, aliveKey=None):
|
|
|
# 获取图片焦点框;
|
|
|
found, focusBox = self.__optionFocus.findFocusByIcon(pic, optionName, isValueSheet)
|
|
@@ -240,7 +357,7 @@ class COptionAction(CBaseLog):
|
|
|
# 特殊情况处理:某些情况下,会将包含数字以外的区域一起识别;
|
|
|
curFocusText = curFocusText.strip('>')
|
|
|
# 将数字分组
|
|
|
- numberTextList = self.strSplit(curFocusText)
|
|
|
+ numberTextList = strSplit(curFocusText)
|
|
|
# 只判断最后一位是否为数字;
|
|
|
if numberTextList.__len__() < 1:
|
|
|
self.error(u"当前识别的文本不是数字文本:%s" % curFocusText)
|
|
@@ -285,9 +402,16 @@ class COptionAction(CBaseLog):
|
|
|
return False, 0 if isNumberText else ""
|
|
|
|
|
|
# 获取动态图片文本内容;
|
|
|
- def __getDynamicPicText(self, optionName, optionTextList, siblingTextList, ocrConfigList, ocrThreshold, marqueeDict, isNumberText, isValueSheet):
|
|
|
+ '''
|
|
|
+ 函数:
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def __getDynamicPicText(self, optionName, optionTextList, siblingTextList, ocrConfigList, ocrThreshold, marqueeDict,
|
|
|
+ isNumberText, isValueSheet):
|
|
|
# 判断图片是否动态:截图两次,判断两次文本内容是否相同;
|
|
|
- firstRetsult, firstText = self.__getStaticPicText(self.takePicture(), optionName, optionTextList, siblingTextList, ocrConfigList,
|
|
|
+ firstRetsult, firstText = self.__getStaticPicText(takePicture(), optionName, optionTextList,
|
|
|
+ siblingTextList, ocrConfigList,
|
|
|
ocrThreshold, isNumberText, isValueSheet)
|
|
|
if firstRetsult is False:
|
|
|
self.error(u"[%s]第一次截图未识别出聚焦框" % optionName)
|
|
@@ -296,7 +420,8 @@ class COptionAction(CBaseLog):
|
|
|
# 发送鲜活键, 保证界面鲜活;
|
|
|
COptionAction.__sendAliveKey(marqueeDict['alive_key'])
|
|
|
# 第二次截图;
|
|
|
- secondRetsult, secondText = self.__getStaticPicText(self.takePicture(), optionName, optionTextList, siblingTextList, ocrConfigList,
|
|
|
+ secondRetsult, secondText = self.__getStaticPicText(takePicture(), optionName, optionTextList,
|
|
|
+ siblingTextList, ocrConfigList,
|
|
|
ocrThreshold, isNumberText, isValueSheet)
|
|
|
if secondRetsult is False:
|
|
|
self.error(u"[%s]第二次截图未识别出聚焦框" % optionName)
|
|
@@ -306,18 +431,20 @@ class COptionAction(CBaseLog):
|
|
|
COptionAction.__sendAliveKey(marqueeDict['alive_key'])
|
|
|
# 比较两文本是否相同;
|
|
|
if firstText.__len__() and firstText == secondText:
|
|
|
- return True, firstText
|
|
|
+ self.info(u"截图两次,文本(%s)识别相同,聚焦的不是跑马灯Option" % firstText)
|
|
|
+ return False, firstText
|
|
|
|
|
|
# 文本不相同,为动态图片;
|
|
|
menuList = marqueeDict['menu']
|
|
|
# 如果只有一项跑马灯,且目标option亦在跑马灯列表中,则直接返回成功结果
|
|
|
if menuList.__len__() == 1 and (optionName in menuList):
|
|
|
+ self.info(u"该层菜单只有一项跑马灯, 找到即成功返回")
|
|
|
return True, firstText
|
|
|
|
|
|
picList = []
|
|
|
# 如果有多项同级option都是跑马灯, 要成功识别文本需要间隔截图5次(大概会成功截图到最全的文本);
|
|
|
for i in range(0, 5):
|
|
|
- picList.append(self.takePicture())
|
|
|
+ picList.append(takePicture())
|
|
|
# 间隔多久截图;
|
|
|
time.sleep(marqueeDict['sleep_time'])
|
|
|
# 发送鲜活键;
|
|
@@ -326,23 +453,138 @@ class COptionAction(CBaseLog):
|
|
|
ocrTextList = []
|
|
|
# 对截图进行文本识别分析;
|
|
|
for pic in picList:
|
|
|
- result, text = self.__getStaticPicText(pic, optionName, optionTextList, siblingTextList, ocrConfigList, ocrThreshold, isNumberText, isValueSheet, marqueeDict['alive_key'])
|
|
|
+ result, text = self.__getStaticPicText(pic, optionName, optionTextList, siblingTextList, ocrConfigList,
|
|
|
+ ocrThreshold, isNumberText, isValueSheet, marqueeDict['alive_key'])
|
|
|
if result is True:
|
|
|
ocrTextList.append(text)
|
|
|
# 发送鲜活键;
|
|
|
COptionAction.__sendAliveKey(marqueeDict['alive_key'])
|
|
|
|
|
|
+ # 过滤重复的字符;
|
|
|
+ ocrTextList = self.__removeDuplicateString(ocrTextList)
|
|
|
+ self.info(u"识别到的跑马灯ocr文字列表:%s" % ocrTextList)
|
|
|
+ # 获取动态文本的option字典;
|
|
|
+ dynamicOptionOcrDict = self.__getOptionInfoDict(menuList)
|
|
|
+ self.info(u"获取到的跑马灯Option对应的ocr字典:%s" % dynamicOptionOcrDict)
|
|
|
+ # 遍历:识别结果与xls结果进行比较;
|
|
|
+ for dynamicOption in dynamicOptionOcrDict:
|
|
|
+ dynamicOptionOcrList = dynamicOptionOcrDict[dynamicOption]
|
|
|
+ for dynamicOptionOcr in dynamicOptionOcrList:
|
|
|
+ # 只要有3张满足,判断找到option;
|
|
|
+ count = 0
|
|
|
+ for ocrText in ocrTextList:
|
|
|
+ if ocrText.lower() in dynamicOptionOcr:
|
|
|
+ count += 1
|
|
|
+
|
|
|
+ if count >= 3 and optionName == dynamicOption:
|
|
|
+ return True, ocrText
|
|
|
+ else:
|
|
|
+ self.info(u"当前聚焦的跑马灯实际为:%s" % dynamicOption)
|
|
|
+ return False, ocrText
|
|
|
+ # endfor
|
|
|
+ # endfor
|
|
|
+
|
|
|
+ self.info("未能识别到当前聚焦的跑马灯Option")
|
|
|
|
|
|
return False, 0 if isNumberText else None
|
|
|
|
|
|
- def move2NextSiblingOption(self, optionName):
|
|
|
- pass
|
|
|
+ '''
|
|
|
+ 函数:
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def __getOptionInfoDict(self, optionNameList):
|
|
|
+ OptionInfoDict = {}
|
|
|
+ for optionName in optionNameList:
|
|
|
+ found, optionDict = self.__optionExcel(optionName)
|
|
|
+ if found:
|
|
|
+ OptionInfoDict[optionName] = optionDict
|
|
|
+ # endif
|
|
|
+ # endfor
|
|
|
+ return OptionInfoDict
|
|
|
|
|
|
- def move2PrevSiblingOption(self, optionName):
|
|
|
- pass
|
|
|
+ # 找到两个字符串左边或者右边相同的部分
|
|
|
+ '''
|
|
|
+ 函数:
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def __findDuplicateString(self, str1, str2, direction="right"):
|
|
|
+ index = 0
|
|
|
+ if direction == "right":
|
|
|
+ while True:
|
|
|
+ index -= 1
|
|
|
+ if abs(index) > str1.__len__() or abs(index) > str2.__len__():
|
|
|
+ break
|
|
|
+ if not str1[index] == str2[index]:
|
|
|
+ break
|
|
|
+ if index == -1:
|
|
|
+ self.info(u"没有找到重复文本")
|
|
|
+ return ""
|
|
|
+ return str1[index + 1:]
|
|
|
+ elif direction == "left":
|
|
|
+ while True:
|
|
|
+ if abs(index) >= str1.__len__() or abs(index) >= str2.__len__():
|
|
|
+ break
|
|
|
+ if not str1[index] == str2[index]:
|
|
|
+ break
|
|
|
+ index += 1
|
|
|
+ return str1[:index]
|
|
|
+
|
|
|
+ # 去掉字符串数组中每个字符串 左边或右边相同的部分
|
|
|
+ '''
|
|
|
+ 函数:
|
|
|
+ 参数:
|
|
|
+ 返回:
|
|
|
+ '''
|
|
|
+ def __removeDuplicateString(self, strList):
|
|
|
+ finishedList = strList
|
|
|
+ directionList = ["left", "right"]
|
|
|
+ for direction in directionList:
|
|
|
+ same_str = self.__findDuplicateString(strList[0], strList[1], direction)
|
|
|
+ if same_str == "":
|
|
|
+ continue
|
|
|
+ else:
|
|
|
+ for i in range(2, strList.__len__()):
|
|
|
+ same_str = self.__findDuplicateString(same_str, strList[i], direction)
|
|
|
+ if same_str == "":
|
|
|
+ break
|
|
|
+ if same_str != "":
|
|
|
+ finishedList = []
|
|
|
+ for text in strList:
|
|
|
+ if direction == "left":
|
|
|
+ text = str[same_str.__len__():]
|
|
|
+ else:
|
|
|
+ text = str[:-same_str.__len__()]
|
|
|
+
|
|
|
+ finishedList.append(text)
|
|
|
+ # endfor
|
|
|
+ # endif
|
|
|
+ # endif
|
|
|
+ # endfor
|
|
|
+ return finishedList
|
|
|
|
|
|
- def back2ParentOption(self):
|
|
|
- pass
|
|
|
+ '''
|
|
|
+ 函数:发送红老鼠按键;
|
|
|
+ 参数:
|
|
|
+ key 1、如果是字符串时,当作单个按键; 2、如果是list时,当作多个按键;
|
|
|
+ count 执行多少次key;
|
|
|
+ wait 1、执行单个key后,等待时长(因为电视机响应遥控需要时间);
|
|
|
+ 2、执行list多个key后,每个key的等待时间;
|
|
|
+ 返回:无
|
|
|
+ '''
|
|
|
+
|
|
|
+ def sendKey(self, key, count, wait):
|
|
|
+ if key is not None and key.__len__() > 0:
|
|
|
+ if type(key) == str:
|
|
|
+ COptionAction.__redRat3.sendKey(key, count, wait)
|
|
|
+ elif type(key) == list:
|
|
|
+ for k in key:
|
|
|
+ COptionAction.__redRat3.sendKey(k, 1, wait)
|
|
|
+ else:
|
|
|
+ self.error(u"error:无效按键内容=%s" % key)
|
|
|
+ else:
|
|
|
+ self.error(u"error:按键内容空")
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|