AACA/Scripts/aacecontrol.py

571 lines
22 KiB
Python
Raw Normal View History

2025-03-07 02:37:50 +00:00
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)