571 lines
22 KiB
Python
571 lines
22 KiB
Python
|
||
|
||
import os,time
|
||
import pywinauto
|
||
import pywinauto.controls
|
||
import pywinauto.keyboard
|
||
import pywinauto.mouse
|
||
import win32gui
|
||
import win32con
|
||
import pyautogui as pag
|
||
import uiautomation as uiauto
|
||
import pyperclip
|
||
from WinUIBase import WinUIBase
|
||
import json,datetime
|
||
|
||
pag.PAUSE = 0.5
|
||
|
||
app_config = {
|
||
"name": r"C:\Program Files (x86)\SEAL Analytical\AACE 8.03 Beta\aace.exe",
|
||
"data_dir": r"C:\ProgramData\SEAL Analytical\AACE 8.03 Beta\Data",
|
||
"login_title": "AACE 登录",
|
||
"main_title": " AACE for Windows"
|
||
}
|
||
|
||
class AppService(WinUIBase):
|
||
def __init__(self):
|
||
self.launcher(app_config["name"])
|
||
win_login = self.wait_window_show(app_config["login_title"],3)
|
||
# win_login = self.get_window(app_config["login_title"])
|
||
if win_login != None:
|
||
ctrls = win_login.children()
|
||
btn_oks = [x for x in ctrls if x.element_info.name=="确定"]
|
||
if len(btn_oks)==1:
|
||
btn_ok = btn_oks[0]
|
||
btn_ok.double_click()
|
||
# time.sleep(3.5)
|
||
pass
|
||
pass
|
||
|
||
# 等待outtime 秒内窗口出现,出现则返回对应的窗口,否则返回None
|
||
def wait_window_show(self,title,outtime = 5):
|
||
start_time = time.time()
|
||
win_main = None
|
||
while time.time() - start_time < outtime:
|
||
win_main = self.get_window(title)
|
||
if win_main is not None:
|
||
break
|
||
time.sleep(0.5)
|
||
return win_main
|
||
|
||
# 等待子窗口显示
|
||
def wait_child_window_show(self,win_main,title,outtime):
|
||
start_time = time.time()
|
||
win_edit = None
|
||
while time.time() - start_time < outtime:
|
||
win_edits = self.get_childers(win_main,class_name=title)
|
||
if win_edits is not None:
|
||
if isinstance(win_edits,list):
|
||
if len(win_edits) < 1:
|
||
print('复制运行打开失败')
|
||
return -1
|
||
win_edit = win_edits[0]
|
||
else:
|
||
win_edit = win_edits
|
||
break
|
||
time.sleep(0.5)
|
||
return win_edit
|
||
|
||
def create(self,args):
|
||
data = json.loads(args)
|
||
sample_list = data.get('sampleList',[])
|
||
num_samples = len(sample_list)
|
||
TaskTypes = ['氨氮','氨氮&总磷','总磷']
|
||
tasktype = data.get('taskType')
|
||
if num_samples < 1 or tasktype not in TaskTypes:
|
||
print(f'数据错误-{args}')
|
||
return -1
|
||
print(f'共-{num_samples}条数据')
|
||
result = self.click_create_table(tasktype)
|
||
if result != -1:
|
||
result = self.start(args)
|
||
return result
|
||
|
||
|
||
def start(self,args):
|
||
try:
|
||
data = json.loads(args)
|
||
sample_list = data.get('sampleList',[])
|
||
num_samples = len(sample_list)
|
||
# TaskTypes = ['氨氮','氨氮&总磷','总磷']
|
||
# tasktype = data.get('taskType')
|
||
# if num_samples < 1 or tasktype not in TaskTypes:
|
||
if num_samples < 1:
|
||
print(f'数据错误-{args}')
|
||
return 0
|
||
except Exception as e:
|
||
self.loginformation(f'错误-{str(e)}')
|
||
return 0
|
||
|
||
win_main = self.wait_window_show(app_config["main_title"], 5)
|
||
if win_main == None:
|
||
return
|
||
self.read_task_type_list2()
|
||
self.set_layout_view(win_main)
|
||
|
||
try:
|
||
return self.create_task(win_main,sample_list,"氨氮&总磷")
|
||
except:
|
||
return 0
|
||
pass
|
||
|
||
|
||
def set_layout_view(self,win_main):
|
||
win_main.set_focus()
|
||
pag.press(["Alt",'Y',"U"])
|
||
time.sleep(1)
|
||
pass
|
||
|
||
def create_task(self,win_main,sample_list,task_type="氨氮&总磷"):
|
||
# 数据处理
|
||
# 下面是正式开始解析数据,获取到的sorted_unique_positions就是按位置号排序的全部位置
|
||
unique_positions = set()
|
||
for sample in sample_list:
|
||
position = int(sample["position"])
|
||
unique_positions.add(Convert(position))
|
||
sorted_unique_positions = sorted(unique_positions)
|
||
|
||
# 先执行关闭
|
||
num_samples = len(sorted_unique_positions)
|
||
win_edits = self.get_childers(win_main,class_name="TEditAnlDlg")
|
||
if isinstance(win_edits,list):
|
||
for win_edit in win_edits:
|
||
win_edits.set_focus()
|
||
rect = win_edits.element_info.rectangle
|
||
pag.click(rect.left+140,rect.top+600)
|
||
self.close_popups(win_edits)
|
||
time.sleep(0.5)
|
||
elif win_edits!=None:
|
||
win_edits.set_focus()
|
||
rect = win_edits.element_info.rectangle
|
||
pag.click(rect.left+140,rect.top+600)
|
||
self.close_popups(win_edits)
|
||
time.sleep(0.5)
|
||
dir_path = os.path.join(app_config["data_dir"],task_type)
|
||
file_list = os.listdir(dir_path)
|
||
file_list = [os.path.join(dir_path,str(x)) for x in file_list if str(x).lower().endswith(".run")]
|
||
file_list = [(x,os.stat(x).st_mtime,time.localtime(os.stat(x).st_mtime)) for x in file_list]
|
||
file_list.sort(key=lambda x:x[1],reverse=True)
|
||
last_task = file_list[0]
|
||
last_task_name = os.path.basename(last_task[0])
|
||
|
||
task_type_list = self._show_task_type_view(win_main,"TDirectoryListBox")
|
||
# listboxItem_data = task_type_list.select(task_type)
|
||
# pos = task_type_list.item_rect(listboxItem_data)
|
||
lview = pywinauto.controls.win32_controls.ListBoxWrapper(task_type_list.handle)
|
||
# texts = lview.item_texts()
|
||
for dir in ["Data", task_type]:
|
||
item = lview.select(dir)
|
||
pos = lview.item_rect(dir)
|
||
lview.double_click_input(coords=(pos.left+5,pos.top+5))
|
||
time.sleep(1)
|
||
# 滚动到最下
|
||
task_item_list = self._show_task_type_view(win_main,"TMyListView")
|
||
|
||
last_item = None
|
||
for _ in range(2):
|
||
# 获取列表
|
||
win_setting_type = self.get_window("设置: 分析")
|
||
win_main_item = uiauto.ControlFromHandle(win_setting_type.handle)
|
||
dgv2 = win_main_item.ListControl(ClassName="TMyListView")
|
||
items = dgv2.GetChildren()
|
||
|
||
last_items = [x for x in items if x.Name==last_task_name]
|
||
if len(last_items)==0:
|
||
print("在列表中没有找到最新任务")
|
||
elif len(last_items)==1:
|
||
rect = last_items[0].BoundingRectangle
|
||
if rect.left + rect.top!=0:
|
||
last_item = last_items[0]
|
||
break
|
||
pass
|
||
task_item_list.scroll(direction="down",amount="end")
|
||
time.sleep(1)
|
||
rect = last_item.BoundingRectangle
|
||
last_item_coords=(rect.left+10,rect.top+5)
|
||
pywinauto.mouse.click(coords=last_item_coords)
|
||
time.sleep(2)
|
||
btn_copy_run = self.get_childers(win_setting_type,name="复制运行")
|
||
btn_copy_run.double_click()
|
||
# time.sleep(5)
|
||
# win_edits = self.get_childers(win_main,class_name="TEditAnlDlg")
|
||
# if isinstance(win_edits,list):
|
||
# if len(win_edits) < 1:
|
||
# print('复制运行打开失败')
|
||
# return -1
|
||
# win_edit = win_edits[0]
|
||
# else:
|
||
# win_edit = win_edits
|
||
|
||
win_edit = self.wait_child_window_show(win_main,"TEditAnlDlg",5)
|
||
if win_edit is None:
|
||
print('打开复制运行失败')
|
||
return -1
|
||
time.sleep(3)
|
||
case_name = time.strftime("%Y%m%d%H%M%S",time.localtime())+"_auto"
|
||
pyperclip.copy(f'{case_name}')
|
||
win_edit.type_keys("^a^v")
|
||
time.sleep(0.2)
|
||
|
||
# 获取盘序按钮并点击.下面代码会报错。先用固定位置
|
||
# win_edit_tab2 = self.get_childers(win_edit,name="盘序")
|
||
# win_edit_tab2.click()
|
||
|
||
rect = win_edit.element_info.rectangle
|
||
pag.click(rect.left+70,rect.top+40)
|
||
time.sleep(0.5)
|
||
pag.click(rect.left+280,rect.top+590)
|
||
time.sleep(0.5)
|
||
|
||
file_path = r"C:\Users\Lenovo\Videos\wanhua.xlsx"
|
||
pyperclip.copy(f'{file_path}')
|
||
pag.hotkey('ctrl', 'v')
|
||
time.sleep(1)
|
||
pag.hotkey('enter')
|
||
time.sleep(0.5)
|
||
|
||
win_edits = self.get_childers(win_main,class_name="TEditAnlDlg")
|
||
#点击盘序
|
||
pag.click(rect.left+70,rect.top+40)
|
||
time.sleep(0.5)
|
||
|
||
#点击第5行 O 无效的下一行
|
||
pag.click(rect.left+70,rect.top+165)
|
||
time.sleep(0.5)
|
||
# 点击样品按钮 添加样品
|
||
sample_btn = self.get_childers(win_edits,name="样品")
|
||
sample_btn.click()
|
||
sample_btn.click()
|
||
time.sleep(1)
|
||
win_samplecup = self.get_window('用于样品的杯')
|
||
# 找到数量这个文本框,输入数目,杯位无所谓,在外面修改
|
||
inputs = self.get_childers(win_samplecup,class_name="TSNumberEdit")
|
||
inputs[1].set_edit_text(num_samples)
|
||
|
||
# Alt+确
|
||
win_samplecup.type_keys("%{确}")
|
||
time.sleep(0.5)
|
||
|
||
# 下面是输入内容,先点击5行图标
|
||
pag.click(rect.left+70,rect.top+165)
|
||
time.sleep(0.5)
|
||
pag.press('right')
|
||
pag.press('right')
|
||
|
||
for pos in sorted_unique_positions:
|
||
pag.press('space')
|
||
pag.write(pos)
|
||
pag.press('tab')
|
||
|
||
result = next((x for x in sample_list if (Convert(int(x["position"])) == pos) and int(x["position"]) % 2 != 0), None)
|
||
if result is not None:
|
||
pag.press('space')
|
||
pag.write(result['sampleCode'])
|
||
print(f"{pos}位置的氨氮值为:{result['sampleCode']}")
|
||
|
||
pag.press('tab')
|
||
pag.press('tab')
|
||
|
||
result = next((x for x in sample_list if (Convert(int(x["position"])) == pos) and int(x["position"]) % 2 == 0), None)
|
||
if result is not None:
|
||
pag.press('space')
|
||
pag.write(result['sampleCode'])
|
||
print(f"{pos}位置的总磷值为:{result['sampleCode']}")
|
||
|
||
for _ in range(3):
|
||
pag.press('tab')
|
||
|
||
# for i in range(num_samples):
|
||
# position = sample_list[i].get('position')
|
||
# sampleCode = sample_list[i].get('sampleCode')
|
||
# pag.press('space')
|
||
# pag.write(position)
|
||
# # pyperclip.copy(position)
|
||
# # pag.hotkey('ctrl','v')
|
||
# pag.press('tab')
|
||
# pag.press('space')
|
||
# pag.write(sampleCode)
|
||
|
||
# tabcount = 3
|
||
# match task_type:
|
||
# case '氨氮':
|
||
# tabcount = 3
|
||
# case '氨氮&总磷':
|
||
# tabcount = 5
|
||
# case '总磷':
|
||
# tabcount = 4
|
||
# case _:
|
||
# tabcount = 3
|
||
# for _ in range(tabcount):
|
||
# pag.press('tab')
|
||
|
||
# Alt+确 确定的快捷键
|
||
win_edit.type_keys("%{确}")
|
||
# time.sleep(0.5)
|
||
return 1
|
||
pass
|
||
|
||
def read_task_type_list(self,win_main):
|
||
listbox_panel = self._show_task_type_view(win_main,"TDirectoryListBox")
|
||
listboxItem_data = listbox_panel.select("Data")
|
||
time.sleep(0.1)
|
||
listboxItem_data.double_click_input(coords=(5,5))
|
||
time.sleep(0.5)
|
||
task_type_list = listbox_panel.item_texts()
|
||
data_index = list(task_type_list).index("Data") + 1
|
||
task_type_list = task_type_list[data_index:]
|
||
return task_type_list
|
||
|
||
def read_task_type_list2(self):
|
||
# dir_list = os.listdir(app_config["data_dir"])
|
||
dir_list = []
|
||
for root,dirs,file in os.walk(app_config["data_dir"]):
|
||
dir_list = dirs
|
||
break
|
||
pass
|
||
return dirs
|
||
pass
|
||
|
||
|
||
def _show_task_type_view(self,win_main,class_name):
|
||
win_setting_type = self.get_window("设置: 分析")
|
||
if win_setting_type is None:
|
||
win_main.set_focus()
|
||
common_panels = self.get_childers(win_main,class_name="TPanel")
|
||
rect = common_panels[0].element_info.rectangle
|
||
coords=(rect.left + 5,rect.top+15)
|
||
pag.click(coords[0],coords[1])
|
||
# time.sleep(8)
|
||
# win_setting_type = self.get_window("设置: 分析")
|
||
win_setting_type = self.wait_window_show("设置: 分析",8)
|
||
win_setting_type.set_focus()
|
||
listbox_panel = self.get_childers(win_setting_type,class_name=class_name)
|
||
return listbox_panel
|
||
|
||
|
||
# 点击制图,暂时弃用
|
||
def click_create_table(self, task_type):
|
||
TaskTypes = ['氨氮','氨氮&总磷','总磷']
|
||
if task_type not in TaskTypes:
|
||
print('制图错误')
|
||
return -1
|
||
|
||
# 点击制图按钮
|
||
win_main = self.get_window(app_config["main_title"])
|
||
win_main.set_focus()
|
||
time.sleep(1)
|
||
create_btn = self.get_childers(win_main,name='制图')
|
||
if create_btn is None:
|
||
print('点击制图失败')
|
||
return -1
|
||
create_btn.double_click()
|
||
|
||
# 弹出的界面点击更改,默认是更改直接点enter
|
||
win_msg = self.wait_window_show('AACE信息',5)
|
||
if win_msg is None:
|
||
print("显示AACE信息失败")
|
||
return -1
|
||
|
||
time.sleep(1)
|
||
change_btns = self.get_childers(win_msg,name='更改…')
|
||
change_btn = None
|
||
if isinstance(change_btns,list):
|
||
if len(change_btns) < 1:
|
||
print("未找到更改按钮")
|
||
return -1
|
||
else:
|
||
change_btn = change_btns[0]
|
||
else:
|
||
change_btn = change_btns
|
||
if change_btn is None:
|
||
print("点击更改...失败")
|
||
return -1
|
||
change_btn.double_click()
|
||
|
||
#选择分析界面选择 氨氮、氨氮&总磷、总磷 对应的文件
|
||
win_select_anlysis = self.wait_window_show('选择分析',5)
|
||
if win_select_anlysis is None:
|
||
return -1
|
||
|
||
# 下面代码为选中对应的模式
|
||
dir_path = os.path.join(app_config["data_dir"],task_type)
|
||
file_list = os.listdir(dir_path)
|
||
file_list = [os.path.join(dir_path,str(x)) for x in file_list if str(x).lower().endswith(".anl")]
|
||
file_list = [(x,os.stat(x).st_mtime,time.localtime(os.stat(x).st_mtime)) for x in file_list]
|
||
file_list.sort(key=lambda x:x[1],reverse=True)
|
||
last_task = file_list[0]
|
||
last_task_name = os.path.basename(last_task[0])
|
||
|
||
win_setting_type = self.get_window("选择分析")
|
||
if win_setting_type is None:
|
||
win_main.set_focus()
|
||
common_panels = self.get_childers(win_main,class_name="TPanel")
|
||
rect = common_panels[0].element_info.rectangle
|
||
coords=(rect.left + 5,rect.top+15)
|
||
pag.click(coords[0],coords[1])
|
||
# time.sleep(8)
|
||
# win_setting_type = self.get_window("设置: 分析")
|
||
win_setting_type = self.wait_window_show("选择分析",8)
|
||
win_setting_type.set_focus()
|
||
task_type_list = self.get_childers(win_setting_type,class_name='TDirectoryListBox')
|
||
lview = pywinauto.controls.win32_controls.ListBoxWrapper(task_type_list.handle)
|
||
# texts = lview.item_texts()
|
||
for dir in ["Data", task_type]:
|
||
item = lview.select(dir)
|
||
pos = lview.item_rect(dir)
|
||
lview.double_click_input(coords=(pos.left+5,pos.top+5))
|
||
time.sleep(1)
|
||
|
||
# 点击确认按钮的快捷键
|
||
win_select_anlysis.type_keys("%{确}")
|
||
return 1
|
||
|
||
# 运行此前设置的分析
|
||
def run(self,task_type = "氨氮&总磷"):
|
||
# 点击制图按钮
|
||
win_main = self.get_window(app_config["main_title"])
|
||
win_main.set_focus()
|
||
time.sleep(2)
|
||
run_btn = self.get_childers(win_main,name='运行')
|
||
if run_btn is None:
|
||
return -1
|
||
run_btn.double_click()
|
||
#选择分析界面选择 氨氮、氨氮&总磷、总磷 对应的文件
|
||
win_select_anlysis = self.wait_window_show('运行: 开始',20)
|
||
if win_select_anlysis is None:
|
||
print('运行开始界面显示超时')
|
||
return -1
|
||
|
||
# 下面是选择最新的文件
|
||
dir_path = os.path.join(app_config["data_dir"],task_type)
|
||
file_list = os.listdir(dir_path)
|
||
file_list = [os.path.join(dir_path,str(x)) for x in file_list if str(x).lower().endswith(".run")]
|
||
file_list = [(x,os.stat(x).st_mtime,time.localtime(os.stat(x).st_mtime)) for x in file_list]
|
||
file_list.sort(key=lambda x:x[1],reverse=True)
|
||
last_task = file_list[0]
|
||
last_task_name = os.path.basename(last_task[0])
|
||
|
||
task_type_list = self._show_task_type_view_ex(win_main,'运行: 开始',"TDirectoryListBox")
|
||
# listboxItem_data = task_type_list.select(task_type)
|
||
# pos = task_type_list.item_rect(listboxItem_data)
|
||
lview = pywinauto.controls.win32_controls.ListBoxWrapper(task_type_list.handle)
|
||
# texts = lview.item_texts()
|
||
for dir in ["Data", task_type]:
|
||
item = lview.select(dir)
|
||
pos = lview.item_rect(dir)
|
||
lview.double_click_input(coords=(pos.left+5,pos.top+5))
|
||
time.sleep(1)
|
||
# 滚动到最下
|
||
task_item_list = self._show_task_type_view_ex(win_main,'运行: 开始',"TMyListView")
|
||
|
||
last_item = None
|
||
for _ in range(2):
|
||
# 获取列表
|
||
win_setting_type = self.get_window("运行: 开始")
|
||
win_main_item = uiauto.ControlFromHandle(win_setting_type.handle)
|
||
dgv2 = win_main_item.ListControl(ClassName="TMyListView")
|
||
items = dgv2.GetChildren()
|
||
|
||
last_items = [x for x in items if x.Name==last_task_name]
|
||
if len(last_items)==0:
|
||
print("在列表中没有找到最新任务")
|
||
elif len(last_items)==1:
|
||
rect = last_items[0].BoundingRectangle
|
||
if rect.left + rect.top!=0:
|
||
last_item = last_items[0]
|
||
break
|
||
pass
|
||
task_item_list.scroll(direction="down",amount="end")
|
||
time.sleep(1)
|
||
rect = last_item.BoundingRectangle
|
||
last_item_coords=(rect.left+10,rect.top+5)
|
||
pywinauto.mouse.click(coords=last_item_coords)
|
||
time.sleep(2)
|
||
win_select_anlysis.type_keys("%{确}")
|
||
|
||
win_start = self.wait_window_show('开始运行',5)
|
||
if win_start is None:
|
||
self.loginformation('开始运行界面有误')
|
||
return -1
|
||
alarm_checkbox = self.get_childers(win_start,name='声音警报')
|
||
rect = alarm_checkbox.rectangle()
|
||
alarm_coords=(rect.left+5,rect.top+5)
|
||
pywinauto.mouse.click(coords=alarm_coords)
|
||
time.sleep(1)
|
||
confirm_coords = (rect.left+5,rect.top+75)
|
||
pywinauto.mouse.click(coords=confirm_coords)
|
||
return 1
|
||
|
||
# 显示任务类型窗口
|
||
def _show_task_type_view_ex(self,win_main,title,classname):
|
||
win_setting_type = self.get_window(title)
|
||
if win_setting_type is None:
|
||
win_main.set_focus()
|
||
common_panels = self.get_childers(win_main,class_name="TPanel")
|
||
rect = common_panels[0].element_info.rectangle
|
||
coords=(rect.left + 5,rect.top+15)
|
||
pag.click(coords[0],coords[1])
|
||
# time.sleep(8)
|
||
# win_setting_type = self.get_window("设置: 分析")
|
||
win_setting_type = self.wait_window_show(title,8)
|
||
win_setting_type.set_focus()
|
||
listbox_panel = self.get_childers(win_setting_type,class_name=classname)
|
||
return listbox_panel
|
||
|
||
def loginformation(self,content):
|
||
print(f'{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}:{content}')
|
||
|
||
|
||
def is_finished(self):
|
||
win_main = self.get_window("AACE信息")
|
||
if win_main is None:
|
||
return 0
|
||
|
||
alram_infos = self.get_childers(win_main,name='声音报警')
|
||
alarm_info = None
|
||
result = 0
|
||
if isinstance(alram_infos,list):
|
||
if len(alram_infos) > 0:
|
||
alarm_info = alram_infos[0]
|
||
elif alram_infos is not None:
|
||
alarm_info = alram_infos
|
||
if alarm_info is None:
|
||
result = 0
|
||
else:
|
||
#win_main.get_properties()
|
||
if win_main.is_visible():
|
||
result = 1
|
||
return result
|
||
|
||
def createThenStart(self,args):
|
||
if self.start(args) != 1:
|
||
return 0
|
||
return self.run()
|
||
|
||
def Convert(self,number):
|
||
if number % 2 == 0:
|
||
number = number - 1
|
||
col = number % 6 // 2
|
||
row = number // 6
|
||
return 46 + 15 * col + row * 2
|
||
|
||
def Convert(number):
|
||
if number % 2 == 0:
|
||
number = number - 1
|
||
col = number % 6 // 2
|
||
row = number // 6
|
||
return 46 + 15 * col + row * 2
|
||
|
||
if __name__ == "__main__":
|
||
# # taskType 为: 氨氮、氨氮&总磷、总磷 3,5,4
|
||
#json_data = {"taskType":"氨氮","sampleList":[{"sampleCode":"11","position":"1"},{"sampleCode":"12","position":"3"}]}
|
||
#appService.click_create_table("氨氮")
|
||
#appService.start(paras)
|
||
#appService.run("氨氮")
|
||
# print(appService.is_finished())
|
||
#pass
|
||
appService = AppService()
|
||
json_data = {"sampleList":[{"sampleCode":"111","position":"1"},{"sampleCode":"112","position":"2"},{"sampleCode":"113","position":"7"},{"sampleCode":"114","position":"20"}]}
|
||
paras = json.dumps(json_data)
|
||
appService.createThenStart(paras)
|
||
|