import tkinter from os.path import exists, dirname from os import getcwd from threading import Thread import tkinter.messagebox import customtkinter from time import time, strftime, localtime, sleep from urllib.request import urlopen from socket import setdefaulttimeout from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from data_process import * from automatic_test import * from durable_action import * import openapi import matplotlib.pyplot as plt import matplotlib import pandas as pd matplotlib.use('Agg') heartbeat = f'{dirname(__file__)}/../assets/templates/heartbeat' durable_data_current_xlsx = f'{dirname(__file__)}/../assets/templates/durable/durable_data_current.xlsx' durable_data_velocity_xlsx = f'{dirname(__file__)}/../assets/templates/durable/durable_data_velocity.xlsx' customtkinter.set_appearance_mode("System") # Modes: "System" (standard), "Dark", "Light" customtkinter.set_default_color_theme("blue") # Themes: "blue" (standard), "green", "dark-blue" customtkinter.set_widget_scaling(1.1) # widget dimensions and text size customtkinter.set_window_scaling(1.1) # window geometry dimensions setdefaulttimeout(3) # global vars durable_data_current = { 'time': list(range(1, 26)), 'axis1': [0 for _ in range(25)], 'axis2': [0 for _ in range(25)], 'axis3': [0 for _ in range(25)], 'axis4': [0 for _ in range(25)], 'axis5': [0 for _ in range(25)], 'axis6': [0 for _ in range(25)], } durable_data_velocity = { 'time': list(range(1, 26)), 'axis1': [0 for _ in range(25)], 'axis2': [0 for _ in range(25)], 'axis3': [0 for _ in range(25)], 'axis4': [0 for _ in range(25)], 'axis5': [0 for _ in range(25)], 'axis6': [0 for _ in range(25)], } btns_func = { 'start': {'btn': '', 'row': 1, 'text': '开始运行'}, 'check': {'btn': '', 'row': 2, 'text': '检查参数'}, 'log': {'btn': '', 'row': 3, 'text': '保存日志'}, 'end': {'btn': '', 'row': 4, 'text': '结束运行'}, } widgits_dp = { 'path': {'label': '', 'entry': '', 'row': 1, 'col': 2, 'text': '数据文件夹路径'}, 'dur': {'label': '', 'entry': '', 'row': 2, 'col': 2, 'text': '周期时间'}, 'vel': {'label': '', 'optionmenu': '', 'row': 2, 'col': 4, 'text': ''}, 'trq': {'label': '', 'optionmenu': '', 'row': 2, 'col': 6, 'text': ''}, 'trqh': {'label': '', 'optionmenu': '', 'row': 2, 'col': 8, 'text': ''}, 'estop': {'label': '', 'optionmenu': '', 'row': 2, 'col': 10, 'text': ''}, } widgits_at = { 'path': {'label': '', 'entry': '', 'row': 2, 'col': 2, 'text': '数据文件夹路径'}, 'loadsel': {'label': '', 'optionmenu': '', 'row': 2, 'col': 1, 'text': '负载信息'}, } widgits_da = { 'path': {'label': '', 'entry': '', 'row': 1, 'col': 2, 'text': '数据文件夹路径'}, 'curvesel': {'label': '', 'optionmenu': '', 'row': 1, 'col': 1, 'text': '曲线选择'}, } class App(customtkinter.CTk): def __init__(self): super().__init__() self.my_font = customtkinter.CTkFont(family="Consolas", size=16, weight="bold") self.w_param = 84 self.hr = None self.md = None self.canvas = None self.flg = 0 self.df_copy = None self.old_curve = None # ===================================================================== # configure window self.title("AIO - All in one automatic toolbox") # self.iconbitmap('./icon.ico') self.geometry("1200x550+30+30") self.protocol("WM_DELETE_WINDOW", self.func_end_callback) self.config(bg='#E9E9E9') self.grid_rowconfigure(6, weight=1) self.grid_columnconfigure((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), weight=1) self.minsize(1200, 550) # ===================================================================== # create frame sidebar(left) self.frame_func = customtkinter.CTkFrame(self, width=120, corner_radius=0, fg_color='#E9E9E9') self.frame_func.grid(row=0, column=0, rowspan=7, sticky='nsew') # create AIO logo self.label_logo = customtkinter.CTkLabel(self.frame_func, text="Rokae AIO", height=60, font=customtkinter.CTkFont(family="Segoe Script Bold", size=24, weight="bold"), text_color="#4F4F4F") self.label_logo.grid(row=0, column=0, padx=15, pady=15) # create buttons for func in btns_func: btns_func[func]['btn'] = customtkinter.CTkButton(self.frame_func, corner_radius=10, text=btns_func[func]['text'], fg_color='#4F4F4F', font=self.my_font) btns_func[func]['btn'].grid(row=btns_func[func]['row'], column=0, sticky='new', padx=10, pady=10, ipadx=5, ipady=5) btns_func['start']['btn'].configure(command=lambda: self.thread_it(self.func_start_callback)) btns_func['check']['btn'].configure(command=lambda: self.thread_it(self.func_check_callback)) btns_func['log']['btn'].configure(command=lambda: self.thread_it(self.func_log_callback)) btns_func['end']['btn'].configure(command=lambda: self.thread_it(self.func_end_callback)) # create version info self.label_version = customtkinter.CTkLabel(self.frame_func, justify='left', text="Vers: 0.2.0.0\nDate: 07/17/2024", font=self.my_font, text_color="#4F4F4F") self.frame_func.rowconfigure(6, weight=1) self.label_version.grid(row=6, column=0, padx=20, pady=20, sticky='s') # ===================================================================== # create tabviews self.tabview = customtkinter.CTkTabview(self, width=10000, height=100, anchor='w', fg_color='#E9E9E9', border_width=2, border_color='#CDCDCD', command=self.tabview_click) self.tabview.grid(row=0, column=1, padx=10, pady=5, sticky="nsew") self.tabview.add("Data Process") self.tabview.add("Automatic Test") self.tabview.add("Durable Action") # create main menu for data process self.menu_main_dp = customtkinter.CTkOptionMenu(self.tabview.tab('Data Process'), values=["init", "brake", "current", "iso", "wavelogger"], font=self.my_font, text_color='yellow', button_color='red', fg_color='green', command=self.func_main_callback) self.menu_main_dp.grid(row=1, column=1, sticky='we', padx=5, pady=10) self.menu_main_dp.set("Start Here!") # create sub menu for data process self.menu_sub_dp = customtkinter.CTkOptionMenu(self.tabview.tab('Data Process')) # create main menu for automatic test self.menu_main_at = customtkinter.CTkOptionMenu(self.tabview.tab('Automatic Test'), values=["init", "brake", "current"], font=self.my_font, text_color='yellow', button_color='red', fg_color='green', command=self.func_main_callback) self.menu_main_at.grid(row=1, column=1, sticky='we', padx=5, pady=5) self.menu_main_at.set("Start Here!") # For data process tab START ===================================================================== # create widgits_dp for widgit in widgits_dp: if widgit == 'path': widgits_dp[widgit]['label'] = customtkinter.CTkLabel(self.tabview.tab('Data Process'), text=f'{widgit.upper()}', font=self.my_font) widgits_dp[widgit]['label'].grid(row=widgits_dp[widgit]['row'], column=widgits_dp[widgit]['col'], sticky='e', pady=10) widgits_dp[widgit]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Data Process'), width=670, placeholder_text=widgits_dp[widgit]['text'], font=self.my_font) widgits_dp[widgit]['entry'].grid(row=widgits_dp[widgit]['row'], column=widgits_dp[widgit]['col']+1, columnspan=11, padx=(5, 10), pady=5, sticky='we') widgits_dp[widgit]['entry'].configure(state='disabled') elif widgit in ['dur']: widgits_dp[widgit]['label'] = customtkinter.CTkLabel(self.tabview.tab('Data Process'), text=f"{widgit.upper()}", font=self.my_font) widgits_dp[widgit]['label'].grid(row=widgits_dp[widgit]['row'], column=widgits_dp[widgit]['col'], sticky='e', pady=5) widgits_dp[widgit]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Data Process'), width=self.w_param, placeholder_text=f"{widgits_dp[widgit]['text']}", font=self.my_font) widgits_dp[widgit]['entry'].grid(row=widgits_dp[widgit]['row'], column=widgits_dp[widgit]['col']+1, padx=(5, 10), pady=5, sticky='w') widgits_dp[widgit]['entry'].configure(state='disabled') elif widgit in ['vel', 'trq', 'trqh', 'estop']: widgits_dp[widgit]['label'] = customtkinter.CTkLabel(self.tabview.tab('Data Process'), text=f"{widgit.upper()}", font=self.my_font) widgits_dp[widgit]['label'].grid(row=widgits_dp[widgit]['row'], column=widgits_dp[widgit]['col'], sticky='e', pady=5) widgits_dp[widgit]['optionmenu'] = customtkinter.CTkOptionMenu(self.tabview.tab('Data Process'), button_color='#708090', fg_color='#778899', values=["1", "2", "3", "4", "5", "6", "7"], width=self.w_param, font=self.my_font) widgits_dp[widgit]['optionmenu'].grid(row=widgits_dp[widgit]['row'], column=widgits_dp[widgit]['col']+1, padx=(5, 10), pady=5, sticky='w') widgits_dp[widgit]['optionmenu'].configure(state='disabled') # For data process tab END ===================================================================== # For automatic test tab START ===================================================================== # create buttons self.seg_button = customtkinter.CTkSegmentedButton(self.tabview.tab('Automatic Test'), dynamic_resizing=False, font=customtkinter.CTkFont(size=16, weight='bold'), command=lambda value='机器状态': self.thread_it(self.segmented_button_callback)) self.seg_button.grid(row=1, column=2, columnspan=12, padx=(65, 10), pady=(10, 10), sticky="ew") self.seg_button.configure(dynamic_resizing=False, values=["功能切换", "触发急停", "恢复急停", "待定功能", "功能待定", "机器状态", "告警信息"]) self.seg_button.set("功能切换") # create progress bar self.progressbar = customtkinter.CTkProgressBar(self.tabview.tab('Automatic Test')) self.progressbar.grid(row=5, column=1, padx=5, pady=5, sticky="ew") self.progressbar.configure(mode="determinnate", width=10) self.progressbar.start() # create widgits_at for widgit in widgits_at: if widgit == 'path': widgits_at[widgit]['label'] = customtkinter.CTkLabel(self.tabview.tab('Automatic Test'), text=f'{widgit.upper()}', font=self.my_font) widgits_at[widgit]['label'].grid(row=widgits_at[widgit]['row'], column=widgits_at[widgit]['col'], sticky='e', padx=(20, 5), pady=5) widgits_at[widgit]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Automatic Test'), width=670, placeholder_text=widgits_at[widgit]['text'], font=self.my_font) widgits_at[widgit]['entry'].grid(row=widgits_at[widgit]['row'], column=widgits_at[widgit]['col']+1, columnspan=11, padx=(5, 10), pady=5, sticky='we') widgits_at[widgit]['entry'].configure(state='disabled') elif widgit in ['loadsel', ]: widgits_at[widgit]['optionmenu'] = customtkinter.CTkOptionMenu(self.tabview.tab('Automatic Test'), button_color='#708090', fg_color='#778899', values=["tool33", "tool66", "tool100", "inertia"], width=self.w_param, font=self.my_font) widgits_at[widgit]['optionmenu'].grid(row=widgits_at[widgit]['row'], column=widgits_at[widgit]['col'], padx=5, pady=5, sticky='we') widgits_at[widgit]['optionmenu'].set(widgits_at[widgit]['text']) widgits_at[widgit]['optionmenu'].configure(state='disabled') # For automatic test tab END ===================================================================== # For durable_action tab START ===================================================================== # create progress bar self.progressbar_da = customtkinter.CTkProgressBar(self.tabview.tab('Durable Action')) self.progressbar_da.grid(row=2, column=1, padx=5, pady=5, sticky="ew") self.progressbar_da.configure(mode="determinnate", width=self.w_param) self.progressbar_da.start() for widgit in widgits_da: if widgit == 'path': widgits_da[widgit]['label'] = customtkinter.CTkLabel(self.tabview.tab('Durable Action'), text=f'{widgit.upper()}', font=self.my_font) widgits_da[widgit]['label'].grid(row=widgits_da[widgit]['row'], column=widgits_da[widgit]['col'], sticky='e', padx=(20, 5), pady=10) widgits_da[widgit]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Durable Action'), width=670, placeholder_text=widgits_da[widgit]['text'], font=self.my_font) widgits_da[widgit]['entry'].grid(row=widgits_da[widgit]['row'], column=widgits_da[widgit]['col']+1, columnspan=11, padx=(5, 10), pady=10, sticky='we') elif widgit in ['curvesel']: widgits_da[widgit]['optionmenu'] = customtkinter.CTkOptionMenu(self.tabview.tab('Durable Action'), button_color='#708090', fg_color='#778899', values=["device_servo_trq_feedback", "hw_joint_vel_feedback"], font=self.my_font) widgits_da[widgit]['optionmenu'].grid(row=widgits_da[widgit]['row'], column=widgits_da[widgit]['col'], padx=5, pady=10, sticky='we') widgits_da[widgit]['optionmenu'].set(widgits_da[widgit]['text']) # For durable_action tab END ===================================================================== # create textbox self.textbox = customtkinter.CTkTextbox(self, wrap='none', font=customtkinter.CTkFont(family="consolas", size=14), text_color="blue", fg_color='#E9E9E9', border_width=2, border_color='#CDCDCD', border_spacing=5) self.textbox.grid(row=6, column=1, columnspan=13, ipadx=10, ipady=10, padx=10, pady=(5, 10), sticky='nsew') self.textbox.configure(state='normal') # ===================================================================== # version check cur_vers = self.label_version.cget("text").replace('\n', ' @ ').replace("Vers: ", '').replace("Date: ", '') url_vers = 'http://10.2.23.150:10008/vers' try: new_vers = urlopen(url_vers).read().decode('utf-8') if cur_vers.strip() != new_vers.strip(): msg = f"""当前版本:{cur_vers}\n更新版本:{new_vers}\n\n请及时前往钉盘更新~~~""" tkinter.messagebox.showwarning(title="版本更新", message=msg) except: tkinter.messagebox.showwarning(title="版本更新", message="连接服务器失败,无法确认当前是否是最新版本......") # functions below ↓ ---------------------------------------------------------------------------------------- def create_canvas(self, figure): self.canvas = FigureCanvasTkAgg(figure, self) self.canvas.draw() self.canvas.get_tk_widget().configure(height=640) self.canvas.get_tk_widget().grid(row=3, column=1, rowspan=3, columnspan=13, padx=20, pady=10, sticky="nsew") def create_plot(self): plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False plt.rcParams['figure.dpi'] = 100 plt.rcParams['font.size'] = 14 plt.rcParams['lines.marker'] = 'o' curvesel = widgits_da['curvesel']['optionmenu'].get() while True: if not self.hr.durable_lock: self.hr.durable_lock = 1 if curvesel == 'device_servo_trq_feedback': df = pd.read_excel(durable_data_current_xlsx) _title = 'device_servo_trq_feedback' elif curvesel == 'hw_joint_vel_feedback': _title = 'hw_joint_vel_feedback' df = pd.read_excel(durable_data_velocity_xlsx) else: _title = 'device_servo_trq_feedback' df = pd.read_excel(durable_data_current_xlsx) self.hr.durable_lock = 0 break else: sleep(1) if not df.equals(self.df_copy) or self.flg == 0 or curvesel != self.old_curve: self.flg = 1 self.df_copy = df.copy() self.old_curve = widgits_da['curvesel']['optionmenu'].get() figure = plt.figure(frameon=True, facecolor='#E9E9E9') plt.subplots_adjust(left=0.04, right=0.98, bottom=0.05, top=0.95) ax = figure.add_subplot(1, 1, 1) df.plot(grid=True, x='time', y='axis1', ax=ax) df.plot(grid=True, x='time', y='axis2', ax=ax) df.plot(grid=True, x='time', y='axis3', ax=ax) df.plot(grid=True, x='time', y='axis4', ax=ax) df.plot(grid=True, x='time', y='axis5', ax=ax) df.plot(grid=True, x='time', y='axis6', ax=ax, title=_title, legend='upper left') self.create_canvas(figure) def thread_it(self, func, *args): """ 将函数打包进线程 """ self.myThread = Thread(target=func, args=args) self.myThread.daemon = True # 主线程退出就直接让子线程跟随退出,不论是否运行完成。 self.myThread.start() def segmented_button_callback(self): _btn_funcs = {'trigger_estop': '触发急停', 'reset_estop': '恢复急停', 'get_state': '机器状态', 'warning_info': '告警信息'} value = self.seg_button.get() self.seg_button.configure(state='disabled') # self.tabview.configure(state='disabled') self.textbox.delete(index1='1.0', index2='end') with open(heartbeat, 'r', encoding='utf-8') as f_h: c_state = f_h.read().strip() if c_state == '0' and value != '功能切换': self.write2textbox("无法连接机器人,检查是否已经使用Robot Assist软件连接机器,重试中...", 0, 50, 'red') else: for _func in _btn_funcs: if _btn_funcs[_func] == value: btn_functions.main(self.hr, self.md, _func, self.write2textbox) break self.seg_button.configure(state='normal') # self.tabview.configure(state='normal') def detect_network(self): df = pd.DataFrame(durable_data_current) df.to_excel(durable_data_current_xlsx, index=False) df = pd.DataFrame(durable_data_velocity) df.to_excel(durable_data_velocity_xlsx, index=False) with open(heartbeat, "w", encoding='utf-8') as f_hb: f_hb.write('0') self.hr = openapi.HmiRequest(self.write2textbox) self.md = openapi.ModbusRequest(self.write2textbox) while True: if self.tabview.get() == 'Durable Action': self.create_plot() with open(heartbeat, 'r', encoding='utf-8') as f_hb: c_state = f_hb.read().strip() pb_color = 'green' if c_state == '1' else 'red' self.progressbar.configure(progress_color=pb_color) self.progressbar_da.configure(progress_color=pb_color) if c_state == '0': self.hr.t_bool = False sleep(3) del self.hr self.hr = openapi.HmiRequest(self.write2textbox) sleep(3) def tabview_click(self): self.initialization() tab_name = self.tabview.get() if tab_name == 'Data Process': self.flg = 0 self.menu_main_dp.set("Start Here!") elif tab_name == 'Automatic Test': self.flg = 0 self.menu_main_at.set("Start Here!") self.seg_button.configure(state='normal') elif tab_name == 'Durable Action': pass def initialization(self): tab_name = self.tabview.get() try: self.canvas.get_tk_widget().grid_forget() except: pass self.textbox.delete(index1='1.0', index2='end') if tab_name == 'Data Process': for widgit in widgits_dp: if widgit in ['path', 'dur']: widgits_dp[widgit]['label'].configure(text=f'{widgit.upper()}', text_color='black') widgits_dp[widgit]['entry'].delete(0, tkinter.END) widgits_dp[widgit]['entry'].configure(placeholder_text=widgits_dp[widgit]['text'], state='normal') widgits_dp[widgit]['entry'].configure(state='disabled') elif widgit in ['vel', 'trq', 'trqh', 'estop']: widgits_dp[widgit]['label'].configure(text=f'{widgit.upper()}', text_color="black") widgits_dp[widgit]['optionmenu'].configure(state='normal') widgits_dp[widgit]['optionmenu'].set('1') widgits_dp[widgit]['optionmenu'].configure(state='disabled') self.menu_sub_dp.grid_forget() elif tab_name == 'Automatic Test': for widgit in widgits_at: if widgit in ['path', ]: widgits_at[widgit]['label'].configure(text=f'{widgit.upper()}', text_color='black') widgits_at[widgit]['entry'].delete(0, tkinter.END) widgits_at[widgit]['entry'].configure(placeholder_text=widgits_at[widgit]['text'], state='normal') widgits_at[widgit]['entry'].configure(state='disabled') elif widgit in ['loadsel']: widgits_at[widgit]['optionmenu'].configure(state='normal') widgits_at[widgit]['optionmenu'].set(widgits_at[widgit]['text']) widgits_at[widgit]['optionmenu'].configure(state='disabled') self.seg_button.set("功能切换") elif tab_name == 'Durable Action': for widgit in widgits_da: if widgit in ['path', ]: widgits_da[widgit]['label'].configure(text=f'{widgit.upper()}', text_color='black') widgits_da[widgit]['entry'].delete(0, tkinter.END) widgits_da[widgit]['entry'].configure(placeholder_text=widgits_at[widgit]['text'], state='normal') elif widgit in ['curvesel']: widgits_da[widgit]['optionmenu'].configure(state='normal') widgits_da[widgit]['optionmenu'].set(widgits_da[widgit]['text']) def func_main_callback(self, func_name): self.initialization() tab_name = self.tabview.get() if tab_name == 'Data Process': if func_name == 'brake': for widgit in widgits_dp: if widgit in ['path']: widgits_dp[widgit]['label'].configure(text_color='red') widgits_dp[widgit]['entry'].configure(state='normal') elif widgit in ['vel', 'trq', 'estop']: widgits_dp[widgit]['label'].configure(text_color="red") widgits_dp[widgit]['optionmenu'].configure(state='normal') elif func_name == 'current': self.menu_sub_dp = customtkinter.CTkOptionMenu(self.tabview.tab('Data Process'), values=["max", "avg", "cycle"], font=self.my_font, button_color='red', fg_color='green', command=self.func_sub_callback) self.menu_sub_dp.grid(row=2, column=1, sticky='we', padx=5, pady=5) self.menu_sub_dp.set("--select--") self.menu_sub_dp.configure(text_color='yellow') elif func_name == 'iso' or func_name == 'wavelogger': for widgit in widgits_dp: if widgit in ['path']: widgits_dp[widgit]['label'].configure(text_color='red') widgits_dp[widgit]['entry'].configure(state='normal') else: self.initialization() self.menu_main_dp.set("Start Here!") elif tab_name == 'Automatic Test': if func_name == 'brake': for widgit in widgits_at: if widgit in ['path',]: widgits_at[widgit]['label'].configure(text_color='red') widgits_at[widgit]['entry'].delete(0, tkinter.END) widgits_at[widgit]['entry'].configure(placeholder_text=widgits_at[widgit]['text'], state='normal') widgits_at[widgit]['entry'].configure(state='normal') elif widgit in ['loadsel', ]: widgits_at[widgit]['optionmenu'].set(widgits_at[widgit]['text']) widgits_at[widgit]['optionmenu'].configure(state='normal', text_color='red') elif func_name == 'current': for widgit in widgits_at: if widgit in ['path',]: widgits_at[widgit]['label'].configure(text_color='red') widgits_at[widgit]['entry'].delete(0, tkinter.END) widgits_at[widgit]['entry'].configure(placeholder_text=widgits_at[widgit]['text'], state='normal') widgits_at[widgit]['entry'].configure(state='normal') elif widgit in ['loadsel', ]: widgits_at[widgit]['optionmenu'].set(widgits_at[widgit]['text']) widgits_at[widgit]['optionmenu'].configure(state='normal', text_color='red') else: self.initialization() self.menu_main_at.set("Start Here!") def func_sub_callback(self, func_name): if func_name == "max" or func_name == "avg": for widgit in widgits_dp: if widgit in ['path']: widgits_dp[widgit]['label'].configure(text_color='red') widgits_dp[widgit]['entry'].delete(0, tkinter.END) widgits_dp[widgit]['entry'].configure(placeholder_text=widgits_dp[widgit]['text'], state='normal') widgits_dp[widgit]['entry'].configure(state='normal') elif widgit in ['dur']: widgits_dp[widgit]['label'].configure(text_color='black') widgits_dp[widgit]['entry'].delete(0, tkinter.END) widgits_dp[widgit]['entry'].configure(placeholder_text=widgits_dp[widgit]['text'], state='normal') widgits_dp[widgit]['entry'].configure(state='disabled') elif widgit in ['vel', 'trqh', 'estop']: widgits_dp[widgit]['label'].configure(text_color='black') widgits_dp[widgit]['optionmenu'].set('1') widgits_dp[widgit]['optionmenu'].configure(state='disabled') elif widgit in ['trq']: widgits_dp[widgit]['label'].configure(text_color='red') widgits_dp[widgit]['optionmenu'].set('1') widgits_dp[widgit]['optionmenu'].configure(state='normal') elif func_name == 'cycle': for widgit in widgits_dp: if widgit in ['path', 'dur']: color = 'blue' if widgit == 'dur' else 'red' widgits_dp[widgit]['label'].configure(text_color=color) widgits_dp[widgit]['entry'].delete(0, tkinter.END) widgits_dp[widgit]['entry'].configure(placeholder_text=widgits_dp[widgit]['text'], state='normal') widgits_dp[widgit]['entry'].configure(state='normal') elif widgit in ['vel', 'trq', 'trqh']: color = 'blue' if widgit == 'trqh' else 'red' widgits_dp[widgit]['label'].configure(text_color=color) widgits_dp[widgit]['optionmenu'].set('1') widgits_dp[widgit]['optionmenu'].configure(state='normal') elif widgit in ['estop']: widgits_dp[widgit]['label'].configure(text_color="black") widgits_dp[widgit]['optionmenu'].set('1') widgits_dp[widgit]['optionmenu'].configure(state='disabled') def write2textbox(self, text, wait=0, exitcode=0, color='blue', tab_name='Data Process'): self.textbox.tag_add(color, 'insert', 'end') self.textbox.tag_config(tagName=color, foreground=color) tab_name_cur = self.tabview.get() if tab_name == tab_name_cur: if wait != 0: self.textbox.insert(index='end', text=text, tags=color) self.textbox.update() self.textbox.see('end') elif exitcode != 0: self.textbox.insert(index='end', text=text + '\n', tags=color) self.textbox.update() self.textbox.see('end') raise Exception(f"Error code: {exitcode}") else: self.textbox.insert(index='end', text=text + '\n', tags=color) self.textbox.update() self.textbox.see('end') elif tab_name == 'openapi' and tab_name_cur == 'Automatic Test' or tab_name_cur == 'Durable Action': if wait != 0: self.textbox.insert(index='end', text=text, tags=color) self.textbox.update() self.textbox.see('end') elif exitcode != 0: self.textbox.insert(index='end', text=text + '\n', tags=color) self.textbox.update() self.textbox.see('end') raise Exception(f"Error code: {exitcode}") else: self.textbox.insert(index='end', text=text + '\n', tags=color) self.textbox.update() self.textbox.see('end') def is_float(self, flag, *args): for item in args: try: if flag == 'optional': item = 0 if item == '' else item _ = float(item) elif flag == 'required': _ = float(item) except Exception as Err: tkinter.messagebox.showerror(title="参数错误", message="请检查对应参数是否填写正确!", ) self.write2textbox(f"错误信息:{Err}\n参数数据缺失,或者数据类型错误,更正后重新运行...\n", 0, 3, 'red') return True def check_param(self): tab_name = self.tabview.get() if tab_name == 'Data Process': func_name = self.menu_main_dp.get() if func_name == 'brake': path = widgits_dp['path']['entry'].get().strip() vel = widgits_dp['vel']['optionmenu'].get() trq = widgits_dp['trq']['optionmenu'].get() estop = widgits_dp['estop']['optionmenu'].get() c1 = exists(path) c2 = True if len({vel, trq, estop}) == 3 else False if c1 and c2: return 1, path, int(vel), int(trq), int(estop) else: return 0, 0 # ======================================================= elif func_name == 'current': path = widgits_dp['path']['entry'].get().strip() dur = widgits_dp['dur']['entry'].get().strip() vel = widgits_dp['vel']['optionmenu'].get() trq = widgits_dp['trq']['optionmenu'].get() trqh = widgits_dp['trqh']['optionmenu'].get() sub = self.menu_sub_dp.get() c1 = exists(path) c2 = sub in ['max', 'avg', 'cycle'] c3 = c4 = True if sub == 'cycle': c3 = True if len({vel, trq}) == 2 else False c4 = self.is_float('optional', dur) elif sub == 'max' or sub == 'avg': pass if c1 and c2 and c3 and c4: dur = 0 if dur == '' else dur return 2, path, sub, float(dur), int(vel), int(trq), int(trqh) else: return 0, 0 # ======================================================= elif func_name == 'iso': path = widgits_dp['path']['entry'].get().strip() if exists(path): return 3, path else: return 0, 0 # ======================================================= elif func_name == 'wavelogger': path = widgits_dp['path']['entry'].get().strip() if exists(path): return 4, path else: return 0, 0 # ======================================================= else: return 0, 0 elif tab_name == 'Automatic Test': func_name = self.menu_main_at.get() if func_name == 'brake': path = widgits_at['path']['entry'].get().strip() loadsel = widgits_at['loadsel']['optionmenu'].get() c1 = exists(path) c2 = loadsel in ['tool100', 'tool66', 'tool33'] if c1 and c2: return 5, path, loadsel else: return 0, 0 elif func_name == 'current': path = widgits_at['path']['entry'].get().strip() loadsel = widgits_at['loadsel']['optionmenu'].get() c1 = exists(path) c2 = loadsel in ['tool100', 'inertia'] if c1 and c2: return 6, path, loadsel else: return 0, 0 else: return 0, 0 elif tab_name == 'Durable Action': path = widgits_da['path']['entry'].get().strip() curvesel = widgits_da['curvesel']['optionmenu'].get() c1 = exists(path) c2 = curvesel in ['device_servo_trq_feedback', 'hw_joint_vel_feedback'] if c1 and c2: return 7, path, curvesel else: return 0, 0 def func_start_callback(self): self.textbox.delete(index1='1.0', index2='end') flag, *args = self.check_param() func_dict = { 1: brake.main, 2: current.main, 3: iso.main, 4: wavelogger.main, 5: do_brake.main, 6: do_current.main, 7: factory_test.main } if flag == 1: func_dict[flag](path=args[0], vel=args[1], trq=args[2], estop=args[3], w2t=self.write2textbox) elif flag == 2: func_dict[flag](path=args[0], sub=args[1], dur=args[2], vel=args[3], trq=args[4], trqh=args[5], w2t=self.write2textbox) elif flag == 3: func_dict[flag](path=args[0], w2t=self.write2textbox) elif flag == 4: func_dict[flag](path=args[0], w2t=self.write2textbox) elif flag == 5: self.pre_warning() func_dict[flag](path=args[0], hr=self.hr, md=self.md, loadsel=args[1], w2t=self.write2textbox) elif flag == 6: self.pre_warning() func_dict[flag](path=args[0], hr=self.hr, md=self.md, loadsel=args[1], w2t=self.write2textbox) elif flag == 7: self.pre_warning() func_dict[flag](path=args[0], hr=self.hr, md=self.md, w2t=self.write2textbox) else: tkinter.messagebox.showerror(title="参数错误", message="请检查对应参数是否填写正确!", ) def pre_warning(self): if tkinter.messagebox.askyesno(title="开始运行", message="确认机器已按照测试规范更新固件,并提按照测试机型前修改好工程?"): pass else: self.write2textbox("请按照测试规范更新机器固件,并在实际运行前确认工程已经修改完毕,以防撞机!!!", 0, 123, 'red', 'Automatic Test') def func_check_callback(self): self.textbox.delete(index1='1.0', index2='end') flag, *args = self.check_param() if flag: tkinter.messagebox.showinfo(title="参数正确", message="所有参数形式上填写无误,可以开始运行!") else: tkinter.messagebox.showerror(title="参数错误", message="需要检查对应参数是否填写正确!", ) def func_log_callback(self): content = self.textbox.get(index1='1.0', index2='end') if len(content) > 1: try: now = strftime('%Y%m%d%H%M%S', localtime(time())) log_name = f"{now}_aio.log" with open(f'{log_name}', 'w', encoding='utf-8') as objlog: objlog.write(content) tkinter.messagebox.showinfo(title="保存成功", message=f'{log_name}已被保存存至↓↓↓\n{getcwd()}') except Exception as Err: self.write2textbox(Err) tkinter.messagebox.showerror(title="保存失败", message="未能保存本次日志,或未能完整保存,请准备好相关数据,联系fanmingfu@rokae.com查看详细信息!", ) else: tkinter.messagebox.showwarning(title="未能保存", message="日志数据为空,不可保存!") def func_end_callback(self): if tkinter.messagebox.askyesno(title="关闭程序", message="相关数据可能未保存,正在运行程序时有概率会损坏数据文件,确定要终止程序运行吗?"): self.destroy() if __name__ == "__main__": aio = App() aio.net_detect = Thread(target=aio.detect_network) aio.net_detect.daemon = True aio.net_detect.start() aio.mainloop()