import tkinter from os.path import exists from os import getcwd, remove from threading import Thread import tkinter.messagebox import customtkinter from time import time, strftime, localtime, sleep from urllib.request import urlopen from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from data_process import brake, current, iso, wavelogger from automatic_test import do_current, do_brake, btn_functions from durable_action import factory_test from commons import openapi, clibs from matplotlib.pyplot import rcParams, figure, subplots_adjust, close from matplotlib import use from pandas import DataFrame, read_excel with open(clibs.log_data_hmi, 'w') as _hmi, open(clibs.log_data_debug, 'w', encoding='utf-8') as _debug: for i in range(1, 11): try: remove(f'{clibs.log_data_hmi}.{i}') except FileNotFoundError: pass logger = clibs.log_prod logger.info("日志文件初始化完成...") use('Agg') 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 # global vars btns_func = { 'start': {'btn': '', 'row': 1, 'text': '开始运行'}, 'check': {'btn': '', 'row': 2, 'text': '检查参数'}, 'log': {'btn': '', 'row': 3, 'text': '保存日志'}, 'end': {'btn': '', 'row': 4, 'text': '结束运行'}, } widgets_dp = { 'path': {'label': '', 'entry': '', 'row': 0, 'col': 1, 'text': '数据文件夹路径'}, 'dur': {'label': '', 'entry': '', 'row': 1, 'col': 1, 'text': '周期时间'}, 'vel': {'label': '', 'optionmenu': '', 'row': 1, 'col': 1, 'text': ''}, 'trq': {'label': '', 'optionmenu': '', 'row': 1, 'col': 3, 'text': ''}, 'trqh': {'label': '', 'optionmenu': '', 'row': 1, 'col': 5, 'text': ''}, 'estop': {'label': '', 'optionmenu': '', 'row': 1, 'col': 7, 'text': ''}, } widgets_at = { 'path': {'label': '', 'entry': '', 'row': 1, 'col': 1, 'text': '数据文件夹路径'}, 'loadsel': {'label': '', 'optionmenu': '', 'row': 1, 'col': 0, 'text': '负载信息'}, } widgets_da = { 'path': {'label': '', 'entry': '', 'row': 0, 'col': 1, 'text': '数据文件夹路径'}, 'curvesel': {'label': '', 'optionmenu': '', 'row': 0, 'col': 0, '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 self.myThread = 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(0, weight=1) self.grid_rowconfigure(1, weight=19) self.grid_columnconfigure(0, weight=1) self.grid_columnconfigure(1, weight=19) self.minsize(1200, 550) # ===================================================================== # 1. create frame sidebar(left) # ===================================================================== self.frame_func = customtkinter.CTkFrame(self, width=200, corner_radius=0, fg_color='#E9E9E9') self.frame_func.grid(row=0, column=0, rowspan=2, sticky='nsew') # 1.1 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) # 1.2 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)) # 1.3 create version info self.label_version = customtkinter.CTkLabel(self.frame_func, justify='left', text="Vers: 0.2.0.7\nDate: 08/16/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') # ===================================================================== # 2. create tabviews # ===================================================================== self.tabview = customtkinter.CTkTabview(self, anchor='w', fg_color='#E9E9E9', width=1000, height=45, 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") # 2.1 create widgets of tab "Data Process" # 2.1.1 create main menu 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=0, column=0, sticky='we', padx=5, pady=10) self.menu_main_dp.set("Start Here!") # 2.2.2 create sub menu self.menu_sub_dp = customtkinter.CTkOptionMenu(self.tabview.tab('Data Process')) # 2.2.3 create labels, entries and option menus for widget in widgets_dp: if widget == 'path': self.tabview.tab('Data Process').columnconfigure(12, weight=1) widgets_dp[widget]['label'] = customtkinter.CTkLabel(self.tabview.tab('Data Process'), text=f'{widget.upper()}', font=self.my_font) widgets_dp[widget]['label'].grid(row=widgets_dp[widget]['row'], column=widgets_dp[widget]['col'], sticky='e', pady=10) widgets_dp[widget]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Data Process'), placeholder_text=widgets_dp[widget]['text'], font=self.my_font) widgets_dp[widget]['entry'].grid(row=widgets_dp[widget]['row'], column=widgets_dp[widget]['col']+1, columnspan=11, padx=(5, 10), pady=5, sticky='we') widgets_dp[widget]['entry'].configure(state='disabled') elif widget in ['dur']: widgets_dp[widget]['label'] = customtkinter.CTkLabel(self.tabview.tab('Data Process'), text=f"{widget.upper()}", font=self.my_font) widgets_dp[widget]['label'].grid(row=widgets_dp[widget]['row'], column=widgets_dp[widget]['col'], sticky='e', pady=5) widgets_dp[widget]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Data Process'), width=self.w_param, placeholder_text=f"{widgets_dp[widget]['text']}", font=self.my_font) widgets_dp[widget]['entry'].grid(row=widgets_dp[widget]['row'], column=widgets_dp[widget]['col']+1, padx=(5, 10), pady=5, sticky='w') widgets_dp[widget]['entry'].configure(state='disabled') elif widget in ['vel', 'trq', 'trqh', 'estop']: widgets_dp[widget]['label'] = customtkinter.CTkLabel(self.tabview.tab('Data Process'), text=f"{widget.upper()}", font=self.my_font) widgets_dp[widget]['label'].grid(row=widgets_dp[widget]['row'], column=widgets_dp[widget]['col'], sticky='e', pady=5) widgets_dp[widget]['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) widgets_dp[widget]['optionmenu'].grid(row=widgets_dp[widget]['row'], column=widgets_dp[widget]['col']+1, padx=(5, 10), pady=5, sticky='w') widgets_dp[widget]['optionmenu'].configure(state='disabled') # ===================================================================== # 2.2 create widgets of tab "Automatic Test" # 2.2.1 create main menu 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=0, column=0, sticky='we', padx=5, pady=5) self.menu_main_at.set("Start Here!") # 2.2.2 create segment 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=0, column=1, columnspan=12, padx=(65, 10), pady=(10, 10), sticky="ew") self.seg_button.configure(dynamic_resizing=False, values=["功能切换", "触发急停", "恢复急停", "待定功能", "功能待定", "机器状态", "告警信息"]) self.seg_button.set("功能切换") # 2.2.3 create progress bar self.progressbar = customtkinter.CTkProgressBar(self.tabview.tab('Automatic Test')) self.progressbar.grid(row=2, column=0, padx=5, pady=5, sticky="ew") self.progressbar.configure(mode="determinnate", width=self.w_param) self.progressbar.start() # 2.2.4 create labels, entries and option menus for widget in widgets_at: if widget == 'path': self.tabview.tab('Automatic Test').columnconfigure(12, weight=1) widgets_at[widget]['label'] = customtkinter.CTkLabel(self.tabview.tab('Automatic Test'), text=f'{widget.upper()}', font=self.my_font) widgets_at[widget]['label'].grid(row=widgets_at[widget]['row'], column=widgets_at[widget]['col'], sticky='e', padx=(20, 5), pady=5) widgets_at[widget]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Automatic Test'), placeholder_text=widgets_at[widget]['text'], font=self.my_font) widgets_at[widget]['entry'].grid(row=widgets_at[widget]['row'], column=widgets_at[widget]['col']+1, columnspan=11, padx=(5, 10), pady=5, sticky='we') widgets_at[widget]['entry'].configure(state='disabled') elif widget in ['loadsel', ]: widgets_at[widget]['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) widgets_at[widget]['optionmenu'].grid(row=widgets_at[widget]['row'], column=widgets_at[widget]['col'], padx=5, pady=5, sticky='we') widgets_at[widget]['optionmenu'].set(widgets_at[widget]['text']) widgets_at[widget]['optionmenu'].configure(state='disabled') # ===================================================================== # 2.3 create widgets of tab "Durable Action" # 2.3.1 create progress bar self.progressbar_da = customtkinter.CTkProgressBar(self.tabview.tab('Durable Action')) self.progressbar_da.grid(row=1, column=0, padx=5, pady=5, sticky="ew") self.progressbar_da.configure(mode="determinnate", width=self.w_param) self.progressbar_da.start() # 2.3.2 create labels, entries and option menus for widget in widgets_da: if widget == 'path': self.tabview.tab('Durable Action').columnconfigure(12, weight=1) widgets_da[widget]['label'] = customtkinter.CTkLabel(self.tabview.tab('Durable Action'), text=f'{widget.upper()}', font=self.my_font) widgets_da[widget]['label'].grid(row=widgets_da[widget]['row'], column=widgets_da[widget]['col'], sticky='e', padx=(20, 5), pady=10) widgets_da[widget]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Durable Action'), placeholder_text=widgets_da[widget]['text'], font=self.my_font) widgets_da[widget]['entry'].grid(row=widgets_da[widget]['row'], column=widgets_da[widget]['col']+1, columnspan=11, padx=(5, 10), pady=10, sticky='we') elif widget in ['curvesel']: widgets_da[widget]['optionmenu'] = customtkinter.CTkOptionMenu(self.tabview.tab('Durable Action'), dynamic_resizing=False, button_color='#708090', fg_color='#778899', values=['device_servo_trq_feedback', '[max] device_servo_trq_feedback'], font=self.my_font) widgets_da[widget]['optionmenu'].grid(row=widgets_da[widget]['row'], column=widgets_da[widget]['col'], padx=5, pady=10, sticky='we') widgets_da[widget]['optionmenu'].set(widgets_da[widget]['text']) # ===================================================================== # 3. 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=1, column=1, columnspan=13, ipadx=10, ipady=10, padx=10, pady=(5, 10), sticky='nsew') self.textbox.configure(state='normal') # functions below ↓ ---------------------------------------------------------------------------------------- def version_check(self): # ===================================================================== # 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="连接服务器失败,无法确认当前是否是最新版本......") def create_canvas(self, _figure): self.canvas = FigureCanvasTkAgg(_figure, self.tabview.tab('Durable Action')) self.canvas.draw() self.canvas.get_tk_widget().configure(height=600) self.canvas.get_tk_widget().grid(row=2, column=0, columnspan=13, padx=10, pady=10, sticky="nsew") def create_plot(self): rcParams['font.sans-serif'] = ['SimHei'] rcParams['axes.unicode_minus'] = False rcParams['figure.dpi'] = 100 rcParams['font.size'] = 14 rcParams['lines.marker'] = 'o' curvesel = widgets_da['curvesel']['optionmenu'].get() while True: if not self.hr.durable_lock: self.hr.durable_lock = 1 if curvesel == 'device_servo_trq_feedback': df = read_excel(clibs.durable_data_current_xlsx) _title = 'device_servo_trq_feedback' elif curvesel == '[max] device_servo_trq_feedback': _title = '[max] device_servo_trq_feedback' df = read_excel(clibs.durable_data_current_max_xlsx) else: _title = 'device_servo_trq_feedback' df = read_excel(clibs.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 = widgets_da['curvesel']['optionmenu'].get() close('all') _figure = figure(frameon=True, facecolor='#E9E9E9') subplots_adjust(left=0.04, right=0.98, bottom=0.1, top=0.95) _ = df['time'].to_list() _xticks = [str(_i) for _i in _] ax = _figure.add_subplot(1, 1, 1) ax.set_xticks(range(len(_xticks))) ax.set_xticklabels(_xticks) 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', rot=30) 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(clibs.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): self.version_check() df = DataFrame(clibs.durable_data_current) df.to_excel(clibs.durable_data_current_xlsx, index=False) df = DataFrame(clibs.durable_data_current_max) df.to_excel(clibs.durable_data_current_max_xlsx, index=False) with open(clibs.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(clibs.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(4) 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() self.textbox.delete(index1='1.0', index2='end') if tab_name == 'Data Process': for widget in widgets_dp: if widget in ['path', 'dur']: widgets_dp[widget]['label'].configure(text=f'{widget.upper()}', text_color='black') widgets_dp[widget]['entry'].delete(0, tkinter.END) widgets_dp[widget]['entry'].configure(placeholder_text=widgets_dp[widget]['text'], state='normal') widgets_dp[widget]['entry'].configure(state='disabled') elif widget in ['vel', 'trq', 'trqh', 'estop']: widgets_dp[widget]['label'].configure(text=f'{widget.upper()}', text_color="black") widgets_dp[widget]['optionmenu'].configure(state='normal') widgets_dp[widget]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].configure(state='disabled') self.menu_sub_dp.grid_forget() elif tab_name == 'Automatic Test': for widget in widgets_at: if widget in ['path', ]: widgets_at[widget]['label'].configure(text=f'{widget.upper()}', text_color='black') widgets_at[widget]['entry'].delete(0, tkinter.END) widgets_at[widget]['entry'].configure(placeholder_text=widgets_at[widget]['text'], state='normal') widgets_at[widget]['entry'].configure(state='disabled') elif widget in ['loadsel']: widgets_at[widget]['optionmenu'].configure(state='normal') widgets_at[widget]['optionmenu'].set(widgets_at[widget]['text']) widgets_at[widget]['optionmenu'].configure(state='disabled') self.seg_button.set("功能切换") elif tab_name == 'Durable Action': for widget in widgets_da: if widget in ['path', ]: widgets_da[widget]['label'].configure(text=f'{widget.upper()}', text_color='black') widgets_da[widget]['entry'].delete(0, tkinter.END) widgets_da[widget]['entry'].configure(placeholder_text=widgets_at[widget]['text'], state='normal') elif widget in ['curvesel']: widgets_da[widget]['optionmenu'].configure(state='normal') widgets_da[widget]['optionmenu'].set(widgets_da[widget]['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 widget in widgets_dp: if widget in ['path']: widgets_dp[widget]['label'].configure(text_color='red') widgets_dp[widget]['entry'].configure(state='normal') elif widget in ['vel', 'trq', 'estop']: widgets_dp[widget]['label'].configure(text_color="red") widgets_dp[widget]['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=1, column=0, 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 widget in widgets_dp: if widget in ['path']: widgets_dp[widget]['label'].configure(text_color='red') widgets_dp[widget]['entry'].configure(state='normal') else: self.initialization() self.menu_main_dp.set("Start Here!") elif tab_name == 'Automatic Test': if func_name == 'brake': for widget in widgets_at: if widget in ['path',]: widgets_at[widget]['label'].configure(text_color='red') widgets_at[widget]['entry'].delete(0, tkinter.END) widgets_at[widget]['entry'].configure(placeholder_text=widgets_at[widget]['text'], state='normal') widgets_at[widget]['entry'].configure(state='normal') elif widget in ['loadsel', ]: widgets_at[widget]['optionmenu'].set(widgets_at[widget]['text']) widgets_at[widget]['optionmenu'].configure(state='normal', text_color='red') elif func_name == 'current': for widget in widgets_at: if widget in ['path',]: widgets_at[widget]['label'].configure(text_color='red') widgets_at[widget]['entry'].delete(0, tkinter.END) widgets_at[widget]['entry'].configure(placeholder_text=widgets_at[widget]['text'], state='normal') widgets_at[widget]['entry'].configure(state='normal') elif widget in ['loadsel', ]: widgets_at[widget]['optionmenu'].set(widgets_at[widget]['text']) widgets_at[widget]['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 widget in widgets_dp: if widget in ['path']: widgets_dp[widget]['label'].configure(text_color='red') widgets_dp[widget]['entry'].delete(0, tkinter.END) widgets_dp[widget]['entry'].configure(placeholder_text=widgets_dp[widget]['text'], state='normal') widgets_dp[widget]['entry'].configure(state='normal') elif widget in ['dur']: widgets_dp[widget]['label'].configure(text_color='black') widgets_dp[widget]['entry'].delete(0, tkinter.END) widgets_dp[widget]['entry'].configure(placeholder_text=widgets_dp[widget]['text'], state='normal') widgets_dp[widget]['entry'].configure(state='disabled') elif widget in ['vel', 'trqh', 'estop']: widgets_dp[widget]['label'].configure(text_color='black') widgets_dp[widget]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].configure(state='disabled') elif widget in ['trq']: widgets_dp[widget]['label'].configure(text_color='red') widgets_dp[widget]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].configure(state='normal') elif func_name == 'cycle': for widget in widgets_dp: if widget in ['path', 'dur']: color = 'blue' if widget == 'dur' else 'red' widgets_dp[widget]['label'].configure(text_color=color) widgets_dp[widget]['entry'].delete(0, tkinter.END) widgets_dp[widget]['entry'].configure(placeholder_text=widgets_dp[widget]['text'], state='normal') widgets_dp[widget]['entry'].configure(state='normal') elif widget in ['vel', 'trq', 'trqh']: color = 'blue' if widget == 'trqh' else 'red' widgets_dp[widget]['label'].configure(text_color=color) widgets_dp[widget]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].configure(state='normal') elif widget in ['estop']: widgets_dp[widget]['label'].configure(text_color="black") widgets_dp[widget]['optionmenu'].set('1') widgets_dp[widget]['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() logger.info(text) 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 = widgets_dp['path']['entry'].get().strip() vel = widgets_dp['vel']['optionmenu'].get() trq = widgets_dp['trq']['optionmenu'].get() estop = widgets_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 = widgets_dp['path']['entry'].get().strip() dur = widgets_dp['dur']['entry'].get().strip() vel = widgets_dp['vel']['optionmenu'].get() trq = widgets_dp['trq']['optionmenu'].get() trqh = widgets_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 = widgets_dp['path']['entry'].get().strip() if exists(path): return 3, path else: return 0, 0 # ======================================================= elif func_name == 'wavelogger': path = widgets_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 = widgets_at['path']['entry'].get().strip() loadsel = widgets_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 = widgets_at['path']['entry'].get().strip() loadsel = widgets_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 = widgets_da['path']['entry'].get().strip() curvesel = widgets_da['curvesel']['optionmenu'].get() c1 = exists(path) c2 = curvesel in ['device_servo_trq_feedback', '[max] device_servo_trq_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 self.tabview.get() == 'Durable Action': df = DataFrame(clibs.durable_data_current) df.to_excel(clibs.durable_data_current_xlsx, index=False) df = DataFrame(clibs.durable_data_current_max) df.to_excel(clibs.durable_data_current_max_xlsx, index=False) 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()