This repository has been archived on 2025-02-25. You can view files and clone it, but cannot push or open issues or pull requests.
gitea edafd91567 v0.2.0.8(2024/08/20)
1. [t_change_ui: clibs.py]
   - 从外部拷贝 icon.ico 文件到 templates 目录
   - 在 assets 目录新建 logs 目录,存放日志文件,并增加了相应的逻辑保证正常执行
2. [t_change_ui: aio.py]:增加 App 窗口图标代码
3. [t_change_ui: openapi.py]:将重复输出的网络错误提示,从 textbox 中转移到 debug.log 日志文件中
2024-08-20 11:13:45 +08:00

671 lines
38 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.wm_iconbitmap(clibs.app_icon)
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.8\nDate: 08/20/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()