3 Commits

Author SHA1 Message Date
2d12c160b9 v0.2.0.7(2024/08/16)
1. [t_change_ui: clibs.py]:修改了 hmi.log 的日志等级为 WARNING
2. [t_change_ui: openapi.py]:根据第一步的修改,将此模块日志记录等级调整至 warning
3. [current: current.py]
   - README新增了整机自动化测试的前置条件,即滑块需要滑动到最右端
   - current修改了文件校验的逻辑
4. [t_change_ui: aio.py]
   - 修改变量命名,widgit -> widget
   - 根据第 5 点变动,同步修改代码实现
   - 调整 UI 界面代码顺序,使之符合 layout.xlsx 描述
   - 将版本检查的部分单独封装成一个函数,在 detect_network 线程初始化时调用一次,并且程序启动也不会受到阻塞
5. [t_change_ui: layout.xlsx]:修改了组件布局方式
2024-08-16 17:22:52 +08:00
4925d899b4 千分表自动采集程序 2024-08-10 17:23:20 +08:00
3814d163c5 v0.2.0.6(2024/08/09)
1. [t_change_ui: all files]
   - 修改了 logger 的实现
   - 尤其是 clibs.py,使用日志字典,重写了日志记录的功能
2024-08-09 10:47:22 +08:00
20 changed files with 487 additions and 259 deletions

4
.gitignore vendored
View File

@ -11,4 +11,6 @@ aio/assets/templates/c_msg.log*
aio/code/durable_action/__pycache__/ aio/code/durable_action/__pycache__/
aio/assets/templates/durable/ aio/assets/templates/durable/
aio/assets/templates/.__c_msg.lock aio/assets/templates/.__c_msg.lock
aio/code/commons/__pycache__/ aio/code/commons/__pycache__/
aio/assets/templates/debug.log
dial_gauge/results.xlsx

View File

@ -596,3 +596,24 @@ v0.2.0.5(2024/07/31)
- 修改获取初始速度的逻辑只获取configs文件中配置的时间内的速度 - 修改获取初始速度的逻辑只获取configs文件中配置的时间内的速度
- 新增 configs 参数 single_brake可针对特定条件做测试 - 新增 configs 参数 single_brake可针对特定条件做测试
10. [APIs: all]: 添加了 logger.setLevel(INFO),只有添加这个,单个模块内才生效 10. [APIs: all]: 添加了 logger.setLevel(INFO),只有添加这个,单个模块内才生效
v0.2.0.6(2024/08/09)
1. [t_change_ui: all files]
- 修改了 logger 的实现
- 尤其是 clibs.py使用日志字典重写了日志记录的功能
v0.2.0.7(2024/08/16)
1. [t_change_ui: clibs.py]:修改了 hmi.log 的日志等级为 WARNING
2. [t_change_ui: openapi.py]:根据第一步的修改,将此模块日志记录等级调整至 warning
3. [current: current.py]
- README新增了整机自动化测试的前置条件即滑块需要滑动到最右端
- current修改了文件校验的逻辑
4. [t_change_ui: aio.py]
- 修改变量命名widgit -> widget
- 根据第 5 点变动,同步修改代码实现
- 调整 UI 界面代码顺序,使之符合 layout.xlsx 描述
- 将版本检查的部分单独封装成一个函数,在 detect_network 线程初始化时调用一次,并且程序启动也不会受到阻塞
5. [t_change_ui: layout.xlsx]:修改了组件布局方式
> 前两个修改点,修复的是网络提示的颜色不正确问题,因为日志将 textbox 中的内容也作为 debug 信息写入 hmi.log 了

Binary file not shown.

View File

@ -1 +1 @@
1 0

View File

@ -14,16 +14,14 @@ from commons import openapi, clibs
from matplotlib.pyplot import rcParams, figure, subplots_adjust, close from matplotlib.pyplot import rcParams, figure, subplots_adjust, close
from matplotlib import use from matplotlib import use
from pandas import DataFrame, read_excel from pandas import DataFrame, read_excel
from logging import getLogger, INFO
with open(clibs.log_data, 'w') as _: 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): for i in range(1, 11):
try: try:
remove(f'{clibs.log_data}.{i}') remove(f'{clibs.log_data_hmi}.{i}')
except FileNotFoundError: except FileNotFoundError:
pass pass
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
logger.info("日志文件初始化完成...") logger.info("日志文件初始化完成...")
use('Agg') use('Agg')
@ -39,21 +37,21 @@ btns_func = {
'log': {'btn': '', 'row': 3, 'text': '保存日志'}, 'log': {'btn': '', 'row': 3, 'text': '保存日志'},
'end': {'btn': '', 'row': 4, 'text': '结束运行'}, 'end': {'btn': '', 'row': 4, 'text': '结束运行'},
} }
widgits_dp = { widgets_dp = {
'path': {'label': '', 'entry': '', 'row': 1, 'col': 2, 'text': '数据文件夹路径'}, 'path': {'label': '', 'entry': '', 'row': 0, 'col': 1, 'text': '数据文件夹路径'},
'dur': {'label': '', 'entry': '', 'row': 2, 'col': 2, 'text': '周期时间'}, 'dur': {'label': '', 'entry': '', 'row': 1, 'col': 1, 'text': '周期时间'},
'vel': {'label': '', 'optionmenu': '', 'row': 2, 'col': 4, 'text': ''}, 'vel': {'label': '', 'optionmenu': '', 'row': 1, 'col': 1, 'text': ''},
'trq': {'label': '', 'optionmenu': '', 'row': 2, 'col': 6, 'text': ''}, 'trq': {'label': '', 'optionmenu': '', 'row': 1, 'col': 3, 'text': ''},
'trqh': {'label': '', 'optionmenu': '', 'row': 2, 'col': 8, 'text': ''}, 'trqh': {'label': '', 'optionmenu': '', 'row': 1, 'col': 5, 'text': ''},
'estop': {'label': '', 'optionmenu': '', 'row': 2, 'col': 10, 'text': ''}, 'estop': {'label': '', 'optionmenu': '', 'row': 1, 'col': 7, 'text': ''},
} }
widgits_at = { widgets_at = {
'path': {'label': '', 'entry': '', 'row': 2, 'col': 2, 'text': '数据文件夹路径'}, 'path': {'label': '', 'entry': '', 'row': 1, 'col': 1, 'text': '数据文件夹路径'},
'loadsel': {'label': '', 'optionmenu': '', 'row': 2, 'col': 1, 'text': '负载信息'}, 'loadsel': {'label': '', 'optionmenu': '', 'row': 1, 'col': 0, 'text': '负载信息'},
} }
widgits_da = { widgets_da = {
'path': {'label': '', 'entry': '', 'row': 1, 'col': 2, 'text': '数据文件夹路径'}, 'path': {'label': '', 'entry': '', 'row': 0, 'col': 1, 'text': '数据文件夹路径'},
'curvesel': {'label': '', 'optionmenu': '', 'row': 1, 'col': 1, 'text': '指标选择'}, 'curvesel': {'label': '', 'optionmenu': '', 'row': 0, 'col': 0, 'text': '指标选择'},
} }
@ -76,17 +74,20 @@ class App(customtkinter.CTk):
self.geometry("1200x550+30+30") self.geometry("1200x550+30+30")
self.protocol("WM_DELETE_WINDOW", self.func_end_callback) self.protocol("WM_DELETE_WINDOW", self.func_end_callback)
self.config(bg='#E9E9E9') self.config(bg='#E9E9E9')
self.grid_rowconfigure(6, weight=1) self.rowconfigure(0, weight=1)
self.grid_columnconfigure((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), weight=1) self.rowconfigure(1, weight=19)
self.columnconfigure(0, weight=1)
self.columnconfigure(1, weight=19)
self.minsize(1200, 550) self.minsize(1200, 550)
# ===================================================================== # =====================================================================
# create frame sidebar(left) # 1. 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') self.frame_func = customtkinter.CTkFrame(self, width=200, corner_radius=0, fg_color='#E9E9E9')
# create AIO logo 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 = 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) self.label_logo.grid(row=0, column=0, padx=15, pady=15)
# create buttons # 1.2 create buttons
for func in btns_func: 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'] = 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[func]['btn'].grid(row=btns_func[func]['row'], column=0, sticky='new', padx=10, pady=10, ipadx=5, ipady=5)
@ -94,95 +95,104 @@ class App(customtkinter.CTk):
btns_func['check']['btn'].configure(command=lambda: self.thread_it(self.func_check_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['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)) btns_func['end']['btn'].configure(command=lambda: self.thread_it(self.func_end_callback))
# create version info # 1.3 create version info
self.label_version = customtkinter.CTkLabel(self.frame_func, justify='left', text="Vers: 0.2.0.5\nDate: 08/02/2024", font=self.my_font, text_color="#4F4F4F") self.label_version = customtkinter.CTkLabel(self.frame_func, justify='left', text="Vers: 0.2.0.5\nDate: 08/02/2024", font=self.my_font, text_color="#4F4F4F")
self.frame_func.rowconfigure(6, weight=1) self.frame_func.rowconfigure(6, weight=1)
self.label_version.grid(row=6, column=0, padx=20, pady=20, sticky='s') self.label_version.grid(row=6, column=0, padx=20, pady=20, sticky='s')
# ===================================================================== # =====================================================================
# create tabviews # 2. 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 = 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.grid(row=0, column=1, padx=10, pady=5, sticky="nsew")
self.tabview.add("Data Process") self.tabview.add("Data Process")
self.tabview.add("Automatic Test") self.tabview.add("Automatic Test")
self.tabview.add("Durable Action") self.tabview.add("Durable Action")
# create main menu for data process # 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 = 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.grid(row=0, column=0, sticky='we', padx=5, pady=10)
self.menu_main_dp.set("Start Here!") self.menu_main_dp.set("Start Here!")
# create sub menu for data process # 2.2.2 create sub menu
self.menu_sub_dp = customtkinter.CTkOptionMenu(self.tabview.tab('Data Process')) self.menu_sub_dp = customtkinter.CTkOptionMenu(self.tabview.tab('Data Process'))
# create main menu for automatic test # 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 = 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.grid(row=0, column=0, sticky='we', padx=5, pady=5)
self.menu_main_at.set("Start Here!") self.menu_main_at.set("Start Here!")
# For data process tab START ===================================================================== # 2.2.2 create segment buttons
# 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 = 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.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.configure(dynamic_resizing=False, values=["功能切换", "触发急停", "恢复急停", "待定功能", "功能待定", "机器状态", "告警信息"])
self.seg_button.set("功能切换") self.seg_button.set("功能切换")
# create progress bar # 2.2.3 create progress bar
self.progressbar = customtkinter.CTkProgressBar(self.tabview.tab('Automatic Test')) self.progressbar = customtkinter.CTkProgressBar(self.tabview.tab('Automatic Test'))
self.progressbar.grid(row=5, column=1, padx=5, pady=5, sticky="ew") self.progressbar.grid(row=2, column=0, padx=5, pady=5, sticky="ew")
self.progressbar.configure(mode="determinnate", width=10) self.progressbar.configure(mode="determinnate", width=self.w_param)
self.progressbar.start() self.progressbar.start()
# create widgits_at # 2.2.4 create labels, entries and option menus
for widgit in widgits_at: for widget in widgets_at:
if widgit == 'path': if widget == 'path':
widgits_at[widgit]['label'] = customtkinter.CTkLabel(self.tabview.tab('Automatic Test'), text=f'{widgit.upper()}', font=self.my_font) self.tabview.tab('Automatic Test').columnconfigure(12, weight=1)
widgits_at[widgit]['label'].grid(row=widgits_at[widgit]['row'], column=widgits_at[widgit]['col'], sticky='e', padx=(20, 5), pady=5) widgets_at[widget]['label'] = customtkinter.CTkLabel(self.tabview.tab('Automatic Test'), text=f'{widget.upper()}', font=self.my_font)
widgits_at[widgit]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Automatic Test'), width=670, placeholder_text=widgits_at[widgit]['text'], 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)
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') widgets_at[widget]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Automatic Test'), placeholder_text=widgets_at[widget]['text'], font=self.my_font)
widgits_at[widgit]['entry'].configure(state='disabled') 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')
elif widgit in ['loadsel', ]: widgets_at[widget]['entry'].configure(state='disabled')
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) elif widget in ['loadsel', ]:
widgits_at[widgit]['optionmenu'].grid(row=widgits_at[widgit]['row'], column=widgits_at[widgit]['col'], padx=5, pady=5, sticky='we') 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)
widgits_at[widgit]['optionmenu'].set(widgits_at[widgit]['text']) widgets_at[widget]['optionmenu'].grid(row=widgets_at[widget]['row'], column=widgets_at[widget]['col'], padx=5, pady=5, sticky='we')
widgits_at[widgit]['optionmenu'].configure(state='disabled') widgets_at[widget]['optionmenu'].set(widgets_at[widget]['text'])
# For automatic test tab END ===================================================================== widgets_at[widget]['optionmenu'].configure(state='disabled')
# For durable_action tab START ===================================================================== # =====================================================================
# create progress bar # 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 = customtkinter.CTkProgressBar(self.tabview.tab('Durable Action'))
self.progressbar_da.grid(row=2, column=1, padx=5, pady=5, sticky="ew") 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.configure(mode="determinnate", width=self.w_param)
self.progressbar_da.start() self.progressbar_da.start()
for widgit in widgits_da: # 2.3.2 create labels, entries and option menus
if widgit == 'path': for widget in widgets_da:
widgits_da[widgit]['label'] = customtkinter.CTkLabel(self.tabview.tab('Durable Action'), text=f'{widgit.upper()}', font=self.my_font) if widget == 'path':
widgits_da[widgit]['label'].grid(row=widgits_da[widgit]['row'], column=widgits_da[widgit]['col'], sticky='e', padx=(20, 5), pady=10) self.tabview.tab('Durable Action').columnconfigure(12, weight=1)
widgits_da[widgit]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Durable Action'), width=670, placeholder_text=widgits_da[widgit]['text'], font=self.my_font) widgets_da[widget]['label'] = customtkinter.CTkLabel(self.tabview.tab('Durable Action'), text=f'{widget.upper()}', 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') widgets_da[widget]['label'].grid(row=widgets_da[widget]['row'], column=widgets_da[widget]['col'], sticky='e', padx=(20, 5), pady=10)
elif widgit in ['curvesel']: widgets_da[widget]['entry'] = customtkinter.CTkEntry(self.tabview.tab('Durable Action'), placeholder_text=widgets_da[widget]['text'], font=self.my_font)
widgits_da[widgit]['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]['entry'].grid(row=widgets_da[widget]['row'], column=widgets_da[widget]['col']+1, columnspan=11, padx=(5, 10), pady=10, sticky='we')
widgits_da[widgit]['optionmenu'].grid(row=widgits_da[widgit]['row'], column=widgits_da[widgit]['col'], padx=5, pady=10, sticky='we') elif widget in ['curvesel']:
widgits_da[widgit]['optionmenu'].set(widgits_da[widgit]['text']) 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)
# For durable_action tab END ===================================================================== widgets_da[widget]['optionmenu'].grid(row=widgets_da[widget]['row'], column=widgets_da[widget]['col'], padx=5, pady=10, sticky='we')
# create textbox 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 = 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.grid(row=1, column=1, columnspan=13, ipadx=10, ipady=10, padx=10, pady=(5, 10), sticky='nsew')
self.textbox.configure(state='normal') self.textbox.configure(state='normal')
# functions below ↓ ----------------------------------------------------------------------------------------
def version_check(self):
# ===================================================================== # =====================================================================
# version check # version check
cur_vers = self.label_version.cget("text").replace('\n', ' @ ').replace("Vers: ", '').replace("Date: ", '') cur_vers = self.label_version.cget("text").replace('\n', ' @ ').replace("Vers: ", '').replace("Date: ", '')
@ -194,13 +204,12 @@ class App(customtkinter.CTk):
tkinter.messagebox.showwarning(title="版本更新", message=msg) tkinter.messagebox.showwarning(title="版本更新", message=msg)
except: except:
tkinter.messagebox.showwarning(title="版本更新", message="连接服务器失败,无法确认当前是否是最新版本......") tkinter.messagebox.showwarning(title="版本更新", message="连接服务器失败,无法确认当前是否是最新版本......")
# functions below ↓ ----------------------------------------------------------------------------------------
def create_canvas(self, _figure): def create_canvas(self, _figure):
self.canvas = FigureCanvasTkAgg(_figure, self.tabview.tab('Durable Action')) self.canvas = FigureCanvasTkAgg(_figure, self.tabview.tab('Durable Action'))
self.canvas.draw() self.canvas.draw()
self.canvas.get_tk_widget().configure(height=600) self.canvas.get_tk_widget().configure(height=600)
self.canvas.get_tk_widget().grid(row=3, column=1, rowspan=3, columnspan=13, padx=20, pady=10, sticky="nsew") self.canvas.get_tk_widget().grid(row=2, column=0, columnspan=13, padx=10, pady=10, sticky="nsew")
def create_plot(self): def create_plot(self):
rcParams['font.sans-serif'] = ['SimHei'] rcParams['font.sans-serif'] = ['SimHei']
@ -209,7 +218,7 @@ class App(customtkinter.CTk):
rcParams['font.size'] = 14 rcParams['font.size'] = 14
rcParams['lines.marker'] = 'o' rcParams['lines.marker'] = 'o'
curvesel = widgits_da['curvesel']['optionmenu'].get() curvesel = widgets_da['curvesel']['optionmenu'].get()
while True: while True:
if not self.hr.durable_lock: if not self.hr.durable_lock:
self.hr.durable_lock = 1 self.hr.durable_lock = 1
@ -230,7 +239,7 @@ class App(customtkinter.CTk):
if not df.equals(self.df_copy) or self.flg == 0 or curvesel != self.old_curve: if not df.equals(self.df_copy) or self.flg == 0 or curvesel != self.old_curve:
self.flg = 1 self.flg = 1
self.df_copy = df.copy() self.df_copy = df.copy()
self.old_curve = widgits_da['curvesel']['optionmenu'].get() self.old_curve = widgets_da['curvesel']['optionmenu'].get()
close('all') close('all')
_figure = figure(frameon=True, facecolor='#E9E9E9') _figure = figure(frameon=True, facecolor='#E9E9E9')
subplots_adjust(left=0.04, right=0.98, bottom=0.1, top=0.95) subplots_adjust(left=0.04, right=0.98, bottom=0.1, top=0.95)
@ -278,6 +287,7 @@ class App(customtkinter.CTk):
# self.tabview.configure(state='normal') # self.tabview.configure(state='normal')
def detect_network(self): def detect_network(self):
self.version_check()
df = DataFrame(clibs.durable_data_current) df = DataFrame(clibs.durable_data_current)
df.to_excel(clibs.durable_data_current_xlsx, index=False) df.to_excel(clibs.durable_data_current_xlsx, index=False)
df = DataFrame(clibs.durable_data_current_max) df = DataFrame(clibs.durable_data_current_max)
@ -321,130 +331,130 @@ class App(customtkinter.CTk):
tab_name = self.tabview.get() tab_name = self.tabview.get()
self.textbox.delete(index1='1.0', index2='end') self.textbox.delete(index1='1.0', index2='end')
if tab_name == 'Data Process': if tab_name == 'Data Process':
for widgit in widgits_dp: for widget in widgets_dp:
if widgit in ['path', 'dur']: if widget in ['path', 'dur']:
widgits_dp[widgit]['label'].configure(text=f'{widgit.upper()}', text_color='black') widgets_dp[widget]['label'].configure(text=f'{widget.upper()}', text_color='black')
widgits_dp[widgit]['entry'].delete(0, tkinter.END) widgets_dp[widget]['entry'].delete(0, tkinter.END)
widgits_dp[widgit]['entry'].configure(placeholder_text=widgits_dp[widgit]['text'], state='normal') widgets_dp[widget]['entry'].configure(placeholder_text=widgets_dp[widget]['text'], state='normal')
widgits_dp[widgit]['entry'].configure(state='disabled') widgets_dp[widget]['entry'].configure(state='disabled')
elif widgit in ['vel', 'trq', 'trqh', 'estop']: elif widget in ['vel', 'trq', 'trqh', 'estop']:
widgits_dp[widgit]['label'].configure(text=f'{widgit.upper()}', text_color="black") widgets_dp[widget]['label'].configure(text=f'{widget.upper()}', text_color="black")
widgits_dp[widgit]['optionmenu'].configure(state='normal') widgets_dp[widget]['optionmenu'].configure(state='normal')
widgits_dp[widgit]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].set('1')
widgits_dp[widgit]['optionmenu'].configure(state='disabled') widgets_dp[widget]['optionmenu'].configure(state='disabled')
self.menu_sub_dp.grid_forget() self.menu_sub_dp.grid_forget()
elif tab_name == 'Automatic Test': elif tab_name == 'Automatic Test':
for widgit in widgits_at: for widget in widgets_at:
if widgit in ['path', ]: if widget in ['path', ]:
widgits_at[widgit]['label'].configure(text=f'{widgit.upper()}', text_color='black') widgets_at[widget]['label'].configure(text=f'{widget.upper()}', text_color='black')
widgits_at[widgit]['entry'].delete(0, tkinter.END) widgets_at[widget]['entry'].delete(0, tkinter.END)
widgits_at[widgit]['entry'].configure(placeholder_text=widgits_at[widgit]['text'], state='normal') widgets_at[widget]['entry'].configure(placeholder_text=widgets_at[widget]['text'], state='normal')
widgits_at[widgit]['entry'].configure(state='disabled') widgets_at[widget]['entry'].configure(state='disabled')
elif widgit in ['loadsel']: elif widget in ['loadsel']:
widgits_at[widgit]['optionmenu'].configure(state='normal') widgets_at[widget]['optionmenu'].configure(state='normal')
widgits_at[widgit]['optionmenu'].set(widgits_at[widgit]['text']) widgets_at[widget]['optionmenu'].set(widgets_at[widget]['text'])
widgits_at[widgit]['optionmenu'].configure(state='disabled') widgets_at[widget]['optionmenu'].configure(state='disabled')
self.seg_button.set("功能切换") self.seg_button.set("功能切换")
elif tab_name == 'Durable Action': elif tab_name == 'Durable Action':
for widgit in widgits_da: for widget in widgets_da:
if widgit in ['path', ]: if widget in ['path', ]:
widgits_da[widgit]['label'].configure(text=f'{widgit.upper()}', text_color='black') widgets_da[widget]['label'].configure(text=f'{widget.upper()}', text_color='black')
widgits_da[widgit]['entry'].delete(0, tkinter.END) widgets_da[widget]['entry'].delete(0, tkinter.END)
widgits_da[widgit]['entry'].configure(placeholder_text=widgits_at[widgit]['text'], state='normal') widgets_da[widget]['entry'].configure(placeholder_text=widgets_at[widget]['text'], state='normal')
elif widgit in ['curvesel']: elif widget in ['curvesel']:
widgits_da[widgit]['optionmenu'].configure(state='normal') widgets_da[widget]['optionmenu'].configure(state='normal')
widgits_da[widgit]['optionmenu'].set(widgits_da[widgit]['text']) widgets_da[widget]['optionmenu'].set(widgets_da[widget]['text'])
def func_main_callback(self, func_name): def func_main_callback(self, func_name):
self.initialization() self.initialization()
tab_name = self.tabview.get() tab_name = self.tabview.get()
if tab_name == 'Data Process': if tab_name == 'Data Process':
if func_name == 'brake': if func_name == 'brake':
for widgit in widgits_dp: for widget in widgets_dp:
if widgit in ['path']: if widget in ['path']:
widgits_dp[widgit]['label'].configure(text_color='red') widgets_dp[widget]['label'].configure(text_color='red')
widgits_dp[widgit]['entry'].configure(state='normal') widgets_dp[widget]['entry'].configure(state='normal')
elif widgit in ['vel', 'trq', 'estop']: elif widget in ['vel', 'trq', 'estop']:
widgits_dp[widgit]['label'].configure(text_color="red") widgets_dp[widget]['label'].configure(text_color="red")
widgits_dp[widgit]['optionmenu'].configure(state='normal') widgets_dp[widget]['optionmenu'].configure(state='normal')
elif func_name == 'current': 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 = 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.grid(row=1, column=0, sticky='we', padx=5, pady=5)
self.menu_sub_dp.set("--select--") self.menu_sub_dp.set("--select--")
self.menu_sub_dp.configure(text_color='yellow') self.menu_sub_dp.configure(text_color='yellow')
elif func_name == 'iso' or func_name == 'wavelogger': elif func_name == 'iso' or func_name == 'wavelogger':
for widgit in widgits_dp: for widget in widgets_dp:
if widgit in ['path']: if widget in ['path']:
widgits_dp[widgit]['label'].configure(text_color='red') widgets_dp[widget]['label'].configure(text_color='red')
widgits_dp[widgit]['entry'].configure(state='normal') widgets_dp[widget]['entry'].configure(state='normal')
else: else:
self.initialization() self.initialization()
self.menu_main_dp.set("Start Here!") self.menu_main_dp.set("Start Here!")
elif tab_name == 'Automatic Test': elif tab_name == 'Automatic Test':
if func_name == 'brake': if func_name == 'brake':
for widgit in widgits_at: for widget in widgets_at:
if widgit in ['path',]: if widget in ['path',]:
widgits_at[widgit]['label'].configure(text_color='red') widgets_at[widget]['label'].configure(text_color='red')
widgits_at[widgit]['entry'].delete(0, tkinter.END) widgets_at[widget]['entry'].delete(0, tkinter.END)
widgits_at[widgit]['entry'].configure(placeholder_text=widgits_at[widgit]['text'], state='normal') widgets_at[widget]['entry'].configure(placeholder_text=widgets_at[widget]['text'], state='normal')
widgits_at[widgit]['entry'].configure(state='normal') widgets_at[widget]['entry'].configure(state='normal')
elif widgit in ['loadsel', ]: elif widget in ['loadsel', ]:
widgits_at[widgit]['optionmenu'].set(widgits_at[widgit]['text']) widgets_at[widget]['optionmenu'].set(widgets_at[widget]['text'])
widgits_at[widgit]['optionmenu'].configure(state='normal', text_color='red') widgets_at[widget]['optionmenu'].configure(state='normal', text_color='red')
elif func_name == 'current': elif func_name == 'current':
for widgit in widgits_at: for widget in widgets_at:
if widgit in ['path',]: if widget in ['path',]:
widgits_at[widgit]['label'].configure(text_color='red') widgets_at[widget]['label'].configure(text_color='red')
widgits_at[widgit]['entry'].delete(0, tkinter.END) widgets_at[widget]['entry'].delete(0, tkinter.END)
widgits_at[widgit]['entry'].configure(placeholder_text=widgits_at[widgit]['text'], state='normal') widgets_at[widget]['entry'].configure(placeholder_text=widgets_at[widget]['text'], state='normal')
widgits_at[widgit]['entry'].configure(state='normal') widgets_at[widget]['entry'].configure(state='normal')
elif widgit in ['loadsel', ]: elif widget in ['loadsel', ]:
widgits_at[widgit]['optionmenu'].set(widgits_at[widgit]['text']) widgets_at[widget]['optionmenu'].set(widgets_at[widget]['text'])
widgits_at[widgit]['optionmenu'].configure(state='normal', text_color='red') widgets_at[widget]['optionmenu'].configure(state='normal', text_color='red')
else: else:
self.initialization() self.initialization()
self.menu_main_at.set("Start Here!") self.menu_main_at.set("Start Here!")
def func_sub_callback(self, func_name): def func_sub_callback(self, func_name):
if func_name == "max" or func_name == "avg": if func_name == "max" or func_name == "avg":
for widgit in widgits_dp: for widget in widgets_dp:
if widgit in ['path']: if widget in ['path']:
widgits_dp[widgit]['label'].configure(text_color='red') widgets_dp[widget]['label'].configure(text_color='red')
widgits_dp[widgit]['entry'].delete(0, tkinter.END) widgets_dp[widget]['entry'].delete(0, tkinter.END)
widgits_dp[widgit]['entry'].configure(placeholder_text=widgits_dp[widgit]['text'], state='normal') widgets_dp[widget]['entry'].configure(placeholder_text=widgets_dp[widget]['text'], state='normal')
widgits_dp[widgit]['entry'].configure(state='normal') widgets_dp[widget]['entry'].configure(state='normal')
elif widgit in ['dur']: elif widget in ['dur']:
widgits_dp[widgit]['label'].configure(text_color='black') widgets_dp[widget]['label'].configure(text_color='black')
widgits_dp[widgit]['entry'].delete(0, tkinter.END) widgets_dp[widget]['entry'].delete(0, tkinter.END)
widgits_dp[widgit]['entry'].configure(placeholder_text=widgits_dp[widgit]['text'], state='normal') widgets_dp[widget]['entry'].configure(placeholder_text=widgets_dp[widget]['text'], state='normal')
widgits_dp[widgit]['entry'].configure(state='disabled') widgets_dp[widget]['entry'].configure(state='disabled')
elif widgit in ['vel', 'trqh', 'estop']: elif widget in ['vel', 'trqh', 'estop']:
widgits_dp[widgit]['label'].configure(text_color='black') widgets_dp[widget]['label'].configure(text_color='black')
widgits_dp[widgit]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].set('1')
widgits_dp[widgit]['optionmenu'].configure(state='disabled') widgets_dp[widget]['optionmenu'].configure(state='disabled')
elif widgit in ['trq']: elif widget in ['trq']:
widgits_dp[widgit]['label'].configure(text_color='red') widgets_dp[widget]['label'].configure(text_color='red')
widgits_dp[widgit]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].set('1')
widgits_dp[widgit]['optionmenu'].configure(state='normal') widgets_dp[widget]['optionmenu'].configure(state='normal')
elif func_name == 'cycle': elif func_name == 'cycle':
for widgit in widgits_dp: for widget in widgets_dp:
if widgit in ['path', 'dur']: if widget in ['path', 'dur']:
color = 'blue' if widgit == 'dur' else 'red' color = 'blue' if widget == 'dur' else 'red'
widgits_dp[widgit]['label'].configure(text_color=color) widgets_dp[widget]['label'].configure(text_color=color)
widgits_dp[widgit]['entry'].delete(0, tkinter.END) widgets_dp[widget]['entry'].delete(0, tkinter.END)
widgits_dp[widgit]['entry'].configure(placeholder_text=widgits_dp[widgit]['text'], state='normal') widgets_dp[widget]['entry'].configure(placeholder_text=widgets_dp[widget]['text'], state='normal')
widgits_dp[widgit]['entry'].configure(state='normal') widgets_dp[widget]['entry'].configure(state='normal')
elif widgit in ['vel', 'trq', 'trqh']: elif widget in ['vel', 'trq', 'trqh']:
color = 'blue' if widgit == 'trqh' else 'red' color = 'blue' if widget == 'trqh' else 'red'
widgits_dp[widgit]['label'].configure(text_color=color) widgets_dp[widget]['label'].configure(text_color=color)
widgits_dp[widgit]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].set('1')
widgits_dp[widgit]['optionmenu'].configure(state='normal') widgets_dp[widget]['optionmenu'].configure(state='normal')
elif widgit in ['estop']: elif widget in ['estop']:
widgits_dp[widgit]['label'].configure(text_color="black") widgets_dp[widget]['label'].configure(text_color="black")
widgits_dp[widgit]['optionmenu'].set('1') widgets_dp[widget]['optionmenu'].set('1')
widgits_dp[widgit]['optionmenu'].configure(state='disabled') widgets_dp[widget]['optionmenu'].configure(state='disabled')
def write2textbox(self, text, wait=0, exitcode=0, color='blue', tab_name='Data Process'): def write2textbox(self, text, wait=0, exitcode=0, color='blue', tab_name='Data Process'):
self.textbox.tag_add(color, 'insert', 'end') self.textbox.tag_add(color, 'insert', 'end')
@ -499,10 +509,10 @@ class App(customtkinter.CTk):
if tab_name == 'Data Process': if tab_name == 'Data Process':
func_name = self.menu_main_dp.get() func_name = self.menu_main_dp.get()
if func_name == 'brake': if func_name == 'brake':
path = widgits_dp['path']['entry'].get().strip() path = widgets_dp['path']['entry'].get().strip()
vel = widgits_dp['vel']['optionmenu'].get() vel = widgets_dp['vel']['optionmenu'].get()
trq = widgits_dp['trq']['optionmenu'].get() trq = widgets_dp['trq']['optionmenu'].get()
estop = widgits_dp['estop']['optionmenu'].get() estop = widgets_dp['estop']['optionmenu'].get()
c1 = exists(path) c1 = exists(path)
c2 = True if len({vel, trq, estop}) == 3 else False c2 = True if len({vel, trq, estop}) == 3 else False
@ -512,11 +522,11 @@ class App(customtkinter.CTk):
return 0, 0 return 0, 0
# ======================================================= # =======================================================
elif func_name == 'current': elif func_name == 'current':
path = widgits_dp['path']['entry'].get().strip() path = widgets_dp['path']['entry'].get().strip()
dur = widgits_dp['dur']['entry'].get().strip() dur = widgets_dp['dur']['entry'].get().strip()
vel = widgits_dp['vel']['optionmenu'].get() vel = widgets_dp['vel']['optionmenu'].get()
trq = widgits_dp['trq']['optionmenu'].get() trq = widgets_dp['trq']['optionmenu'].get()
trqh = widgits_dp['trqh']['optionmenu'].get() trqh = widgets_dp['trqh']['optionmenu'].get()
sub = self.menu_sub_dp.get() sub = self.menu_sub_dp.get()
c1 = exists(path) c1 = exists(path)
@ -535,14 +545,14 @@ class App(customtkinter.CTk):
return 0, 0 return 0, 0
# ======================================================= # =======================================================
elif func_name == 'iso': elif func_name == 'iso':
path = widgits_dp['path']['entry'].get().strip() path = widgets_dp['path']['entry'].get().strip()
if exists(path): if exists(path):
return 3, path return 3, path
else: else:
return 0, 0 return 0, 0
# ======================================================= # =======================================================
elif func_name == 'wavelogger': elif func_name == 'wavelogger':
path = widgits_dp['path']['entry'].get().strip() path = widgets_dp['path']['entry'].get().strip()
if exists(path): if exists(path):
return 4, path return 4, path
else: else:
@ -553,8 +563,8 @@ class App(customtkinter.CTk):
elif tab_name == 'Automatic Test': elif tab_name == 'Automatic Test':
func_name = self.menu_main_at.get() func_name = self.menu_main_at.get()
if func_name == 'brake': if func_name == 'brake':
path = widgits_at['path']['entry'].get().strip() path = widgets_at['path']['entry'].get().strip()
loadsel = widgits_at['loadsel']['optionmenu'].get() loadsel = widgets_at['loadsel']['optionmenu'].get()
c1 = exists(path) c1 = exists(path)
c2 = loadsel in ['tool100', 'tool66', 'tool33'] c2 = loadsel in ['tool100', 'tool66', 'tool33']
if c1 and c2: if c1 and c2:
@ -562,8 +572,8 @@ class App(customtkinter.CTk):
else: else:
return 0, 0 return 0, 0
elif func_name == 'current': elif func_name == 'current':
path = widgits_at['path']['entry'].get().strip() path = widgets_at['path']['entry'].get().strip()
loadsel = widgits_at['loadsel']['optionmenu'].get() loadsel = widgets_at['loadsel']['optionmenu'].get()
c1 = exists(path) c1 = exists(path)
c2 = loadsel in ['tool100', 'inertia'] c2 = loadsel in ['tool100', 'inertia']
if c1 and c2: if c1 and c2:
@ -573,8 +583,8 @@ class App(customtkinter.CTk):
else: else:
return 0, 0 return 0, 0
elif tab_name == 'Durable Action': elif tab_name == 'Durable Action':
path = widgits_da['path']['entry'].get().strip() path = widgets_da['path']['entry'].get().strip()
curvesel = widgits_da['curvesel']['optionmenu'].get() curvesel = widgets_da['curvesel']['optionmenu'].get()
c1 = exists(path) c1 = exists(path)
c2 = curvesel in ['device_servo_trq_feedback', '[max] device_servo_trq_feedback'] c2 = curvesel in ['device_servo_trq_feedback', '[max] device_servo_trq_feedback']
if c1 and c2: if c1 and c2:

View File

@ -1,11 +1,8 @@
from json import loads
from sys import argv from sys import argv
from logging import getLogger, INFO
from commons import clibs from commons import clibs
tab_name = clibs.tab_names['at'] tab_name = clibs.tab_names['at']
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
def trigger_estop(md, w2t): def trigger_estop(md, w2t):
@ -40,7 +37,7 @@ def get_state(hr, w2t):
def warning_info(hr, w2t): def warning_info(hr, w2t):
for postfix in ['', '.2', '.3', '.4', '.5', '.6', '.7', '.8', '.9', '.10']: for postfix in ['', '.2', '.3', '.4', '.5', '.6', '.7', '.8', '.9', '.10']:
log_name = clibs.log_data + postfix log_name = clibs.log_data_hmi + postfix
try: try:
with open(log_name, 'r', encoding='utf-8') as f_log: with open(log_name, 'r', encoding='utf-8') as f_log:
for line in f_log: for line in f_log:

View File

@ -5,12 +5,10 @@ from paramiko import SSHClient, AutoAddPolicy
from json import loads from json import loads
from openpyxl import load_workbook from openpyxl import load_workbook
from pandas import DataFrame, concat from pandas import DataFrame, concat
from logging import getLogger, INFO
from commons import clibs from commons import clibs
tab_name = clibs.tab_names['at'] tab_name = clibs.tab_names['at']
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
def check_files(path, loadsel, data_dirs, data_files, w2t): def check_files(path, loadsel, data_dirs, data_files, w2t):
@ -107,6 +105,7 @@ def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
write_diagnosis = float(ws.cell(row=3, column=10).value) write_diagnosis = float(ws.cell(row=3, column=10).value)
get_init_speed = float(ws.cell(row=4, column=10).value) get_init_speed = float(ws.cell(row=4, column=10).value)
single_brake = str(ws.cell(row=5, column=10).value) single_brake = str(ws.cell(row=5, column=10).value)
logger.info(f"write_diagnosis = {write_diagnosis}, get_init_speed = {get_init_speed}, single_brake = {single_brake}")
if ws.cell(row=1, column=1).value == 'positive': if ws.cell(row=1, column=1).value == 'positive':
md.write_pon(1) md.write_pon(1)

View File

@ -4,12 +4,9 @@ from sys import argv
from paramiko import SSHClient, AutoAddPolicy from paramiko import SSHClient, AutoAddPolicy
from json import loads from json import loads
from pandas import DataFrame, concat from pandas import DataFrame, concat
from logging import getLogger, INFO
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
tab_name = clibs.tab_names['at'] tab_name = clibs.tab_names['at']
display_pdo_params = [ display_pdo_params = [
{"name": "hw_joint_vel_feedback", "channel": 0}, {"name": "hw_joint_vel_feedback", "channel": 0},

View File

@ -4,10 +4,12 @@ from time import sleep
from os.path import exists from os.path import exists
from paramiko import SSHClient, AutoAddPolicy from paramiko import SSHClient, AutoAddPolicy
from socket import setdefaulttimeout from socket import setdefaulttimeout
from logging import DEBUG, INFO, WARNING, ERROR, CRITICAL, Formatter, StreamHandler, basicConfig from logging import getLogger
from concurrent_log_handler import ConcurrentRotatingFileHandler from logging.config import dictConfig
import concurrent_log_handler
ip_addr = '192.168.0.160' ip_addr = '192.168.0.160' # for product
# ip_addr = '192.168.84.129' # for test
RADIAN = 57.3 # 180 / 3.1415926 RADIAN = 57.3 # 180 / 3.1415926
MAX_FRAME_SIZE = 1024 MAX_FRAME_SIZE = 1024
TIMEOUT = 5 TIMEOUT = 5
@ -15,7 +17,8 @@ setdefaulttimeout(TIMEOUT)
tab_names = {'dp': 'Data Process', 'at': 'Automatic Test', 'da': 'Duration Action', 'op': 'openapi'} tab_names = {'dp': 'Data Process', 'at': 'Automatic Test', 'da': 'Duration Action', 'op': 'openapi'}
# PREFIX = '' # for pyinstaller packaging # PREFIX = '' # for pyinstaller packaging
PREFIX = '../assets/' # for source code debug PREFIX = '../assets/' # for source code debug
log_data = f'{PREFIX}templates/c_msg.log' log_data_hmi = f'{PREFIX}templates/c_msg.log'
log_data_debug = f'{PREFIX}templates/debug.log'
heartbeat = f'{PREFIX}templates/heartbeat' heartbeat = f'{PREFIX}templates/heartbeat'
durable_data_current_xlsx = f'{PREFIX}templates/durable/durable_data_current.xlsx' durable_data_current_xlsx = f'{PREFIX}templates/durable/durable_data_current.xlsx'
durable_data_current_max_xlsx = f'{PREFIX}templates/durable/durable_data_current_max.xlsx' durable_data_current_max_xlsx = f'{PREFIX}templates/durable/durable_data_current_max.xlsx'
@ -38,16 +41,80 @@ durable_data_current_max = {
'axis6': [0 for _ in range(18)], 'axis6': [0 for _ in range(18)],
} }
file_handler = ConcurrentRotatingFileHandler(filename=log_data, backupCount=10, maxBytes=50*1024*1024, encoding='utf-8') # version表示版本该键值为从1开始的整数。该key必选除此之外其它key都是可选。
file_handler.setLevel(INFO) # formatters日志格式化器其value值为一个字典该字典的每个键值对都代表一个Formatter键值对中key代表Formatter ID(自定义ID)value为字典描述如何配置相应的Formatter实例。默认格式为 %(message)s
console_handler = StreamHandler() # filters日志过滤器其value值为一个字典该字典的每个键值对都代表一个Filter键值对中key代表Filter ID(自定义ID)value为字典描述如何配置相应的Filter实例。
console_handler.setLevel(WARNING) # handlers日志处理器其value值为一个字典该字典的每个键值对都代表一个Handler键值对中key代表Handler ID(自定义ID)value为字典描述如何配置相应的Handler实例包含以下配置key
# class (必选):日志处理器类全称
basicConfig( # level=INFO, # level (可选)指定该日志处理器需要处理哪些级别的日志低于该级别的日志将不被该handler处理。level可以为代表日志级别的整数或者表大写字符串字符串日志级别和数字日志级别对应关系如下
datefmt='%Y-%m-%dT%H:%M:%S', # CRITICAL 50
format='%(asctime)s # %(levelname)s-%(filename)s-%(funcName)s # %(message)s', # ERROR 40
handlers=[file_handler, console_handler], # WARNING 30
) # INFO 20
# DEBUG 10
# NOTSET 0
f_complex = '%(asctime)s # %(name)s-%(levelname)s-%(module)s-%(funcName)s-%(lineno)d # %(message)s'
f_simple = '%(levelname)s-%(module)s-%(funcName)s-%(lineno)d: %(message)s'
log_dicts = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'standard': {
'format': f_complex,
'style': '%',
'datefmt': '%Y-%m-%dT%H:%M:%S',
},
'test': {
'format': f_simple,
'style': '%',
'datefmt': '%Y-%m-%dT%H:%M:%S',
},
},
'filters': {},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'test',
},
'hmi.log': {
'level': 'WARNING',
'class': 'concurrent_log_handler.ConcurrentRotatingFileHandler',
'filename': log_data_hmi,
'maxBytes': 1024*1024*50,
'backupCount': 10,
'encoding': 'utf-8',
'formatter': 'standard',
},
'debug.log': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': log_data_debug,
'encoding': 'utf-8',
'formatter': 'standard',
},
},
'loggers': {
'normal': {
'handlers': ['hmi.log', 'debug.log'],
'level': 'DEBUG',
'propagate': False
},
'debug': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': False
},
'': {
'handlers': ['hmi.log', 'debug.log'],
'level': 'DEBUG',
'propagate': False
},
}
}
dictConfig(log_dicts)
log_prod = getLogger('normal')
log_debug = getLogger('debug')
class GetThreadResult(Thread): class GetThreadResult(Thread):

View File

@ -6,11 +6,9 @@ from time import time, sleep
from pymodbus.client.tcp import ModbusTcpClient from pymodbus.client.tcp import ModbusTcpClient
from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder
from pymodbus.constants import Endian from pymodbus.constants import Endian
from logging import getLogger, INFO
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
class ModbusRequest(object): class ModbusRequest(object):
@ -263,7 +261,7 @@ class HmiRequest(object):
def msg_storage(self, response, flag=0): def msg_storage(self, response, flag=0):
# response是解码后的字符串 # response是解码后的字符串
messages = self.c_msg if flag == 0 else self.c_msg_xs messages = self.c_msg if flag == 0 else self.c_msg_xs
logger.info(f"{loads(response)}") logger.warning(f"{loads(response)}")
if 'move.monitor' in response: if 'move.monitor' in response:
pass pass
elif len(messages) < 10000: elif len(messages) < 10000:
@ -504,7 +502,7 @@ class HmiRequest(object):
def get_from_id(self, msg_id, flag=0): def get_from_id(self, msg_id, flag=0):
for i in range(3): for i in range(3):
with open(clibs.log_data, mode='r', encoding='utf-8') as f_log: with open(clibs.log_data_hmi, mode='r', encoding='utf-8') as f_log:
for line in f_log: for line in f_log:
if msg_id in line.strip(): if msg_id in line.strip():
return line return line
@ -512,7 +510,7 @@ class HmiRequest(object):
else: # 尝试在上一次分割的日志中查找,只做一次 else: # 尝试在上一次分割的日志中查找,只做一次
sleep(1) sleep(1)
try: try:
with open(clibs.log_data+'.1', mode='r', encoding='utf-8') as f_log: with open(clibs.log_data_hmi+'.1', mode='r', encoding='utf-8') as f_log:
for line in f_log: for line in f_log:
if msg_id in line.strip(): if msg_id in line.strip():
return line return line
@ -617,7 +615,7 @@ class HmiRequest(object):
self.c.send(self.package(cmd)) self.c.send(self.package(cmd))
sleep(0.5) sleep(0.5)
except Exception as Err: except Exception as Err:
self.w2t(f"{cmd}\n请求发送失败...{Err}", 0, 0, 'red', tab_name=self.tab_name) self.w2t(f"{cmd}: 请求发送失败...{Err}", 0, 0, 'red', tab_name=self.tab_name)
return req['id'] return req['id']

View File

@ -1,15 +1,12 @@
# coding: utf-8
from os.path import isfile from os.path import isfile
from sys import argv from sys import argv
from openpyxl import load_workbook from openpyxl import load_workbook
from time import time, sleep, strftime, localtime from time import time, sleep, strftime, localtime
from threading import Thread from threading import Thread
from pandas import read_csv from pandas import read_csv
from logging import getLogger, INFO
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
def check_files(path, raw_data_dirs, result_files, w2t): def check_files(path, raw_data_dirs, result_files, w2t):

View File

@ -5,11 +5,9 @@ from re import match
from threading import Thread from threading import Thread
from time import sleep from time import sleep
from csv import reader, writer from csv import reader, writer
from logging import getLogger, INFO
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
def w2t_local(msg, wait, w2t): def w2t_local(msg, wait, w2t):

View File

@ -1,13 +1,10 @@
# _*_ encodingutf-8 _*_
import pdfplumber import pdfplumber
from openpyxl import load_workbook from openpyxl import load_workbook
from os import remove from os import remove
from sys import argv from sys import argv
from logging import getLogger, INFO
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
def p_iso(file, p_files, ws, tmpfile): def p_iso(file, p_files, ws, tmpfile):

View File

@ -2,11 +2,9 @@ from pandas import read_csv
from csv import reader from csv import reader
from sys import argv from sys import argv
from openpyxl import Workbook from openpyxl import Workbook
from logging import getLogger, INFO
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
def find_point(bof, step, pos, data_file, flag, df, row, w2t): def find_point(bof, step, pos, data_file, flag, df, row, w2t):

View File

@ -6,12 +6,9 @@ from openpyxl import load_workbook
from math import sqrt from math import sqrt
from numpy import power from numpy import power
from csv import writer from csv import writer
from logging import getLogger, INFO
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
logger.setLevel(INFO)
tab_name = clibs.tab_names['da'] tab_name = clibs.tab_names['da']
count = 0 count = 0
display_pdo_params = [ display_pdo_params = [

2
dial_gauge/README.md Normal file
View File

@ -0,0 +1,2 @@
## 千分表数据自动采集

6
dial_gauge/conf.ini Normal file
View File

@ -0,0 +1,6 @@
[md_rtu]
port = COM10
[md_tcp]
addr = 192.168.0.160
port = 502

99
dial_gauge/gauge.py Normal file
View File

@ -0,0 +1,99 @@
from configparser import ConfigParser
from pymodbus.client import ModbusSerialClient, ModbusTcpClient
from time import sleep, strftime, localtime, time
from openpyxl import load_workbook, Workbook
from os import rename
# import pymodbus
# pymodbus.pymodbus_apply_logging_config("DEBUG")
def initializations():
try:
now = strftime("%Y%m%d%H%M%S", localtime(time()))
rename('results.xlsx', f'results_{now}.xlsx')
except FileNotFoundError:
pass
wb = Workbook()
ws = wb.active
ws.title = 'results'
ws['A1'].value = '时间'
ws['B1'].value = '次数'
ws['C1'].value = '结果'
wb.save('results.xlsx')
wb.close()
def do_connections():
configs = ConfigParser()
configs.read('conf.ini')
# ================ 配置Modbus TCP客户端 ================
tcp_host = configs.get('md_tcp', 'addr')
tcp_port = configs.getint('md_tcp', 'port')
client_tcp = ModbusTcpClient(tcp_host, tcp_port)
if client_tcp.connect():
print(f"Modbus TCP已连接到{tcp_host}:{tcp_port}...")
else:
raise Exception(f"Modbus TCP无法连接到{tcp_host}:{tcp_port}...")
# ================ 配置Modbus RTU客户端 ================
rtu_port = configs.get('md_rtu', 'port')
client_rtu = ModbusSerialClient(
method='rtu',
port=rtu_port, # 根据实际情况调整端口Windows上可能是 'COM3'
baudrate=38400, # 根据协议设定波特率为38400
timeout=1,
parity='N', # 无奇偶校验
stopbits=2, # 2个停止位
bytesize=8 # 8个数据位
)
if client_rtu.connect():
print(f"Modbus RTU已连接到系统{rtu_port}端口...")
else:
raise Exception(f"Modbus RTU无法连接到系统{rtu_port}端口...")
return client_tcp, client_rtu
def get_gauge_data(client_tcp, client_rtu):
count = 2
client_tcp.write_register(41000, 1) # 将 act 信号置为 True
# ================ 功能实现 ================
while True:
while True:
res_tcp = client_tcp.read_holding_registers(41001, 1) # 获取 time_to_go 的值
sleep(0.5)
if not res_tcp.registers[0]:
continue
else:
break
try:
res_rtu = client_rtu.read_holding_registers(0x0000, 2, slave=1)
plus_or_minus = 1 if res_rtu.registers[0] == 0 else -1
result = res_rtu.registers[1] * plus_or_minus / 10000
now = strftime("%Y-%m-%d %H:%M:%S", localtime(time()))
wb = load_workbook('results.xlsx')
ws = wb['results']
ws[f'A{count}'].value = now
ws[f'B{count}'].value = count-1
ws[f'C{count}'].value = float(result)
wb.save('results.xlsx')
wb.close()
count += 1
except:
client_tcp.write_register(41000, 0) # 将 act 信号置为 False
sleep(2) #
def main():
initializations()
client_tcp, client_rtu = do_connections()
get_gauge_data(client_tcp, client_rtu)
if __name__ == '__main__':
main()

43
dial_gauge/gauge.xml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<m>
<l>
<c name="addr" type="2" value="41000"/>
<c name="addr_1st" type="2" value="0"/>
<c name="addr_2nd" type="2" value="0"/>
<c name="bit_bias" type="2" value="0"/>
<c name="byte_bias" type="4" value="0"/>
<c name="description" type="10" value="pc to robot"/>
<c name="dev_name" type="10" value="autotest"/>
<c name="dev_type" type="10" value="MODBUS"/>
<c name="end_addr" type="2" value="41000"/>
<c name="function" type="10" value=""/>
<c name="len" type="2" value="1"/>
<c name="name" type="10" value="act"/>
<c name="retain" type="1" value="false"/>
<c name="rw" type="10" value="rd"/>
<c name="type" type="10" value="bool"/>
<c name="value"/>
<c name="value_single" type="10" value=""/>
<c name="bias" type="2" value="0"/>
</l>
<l>
<c name="addr" type="2" value="41001"/>
<c name="addr_1st" type="2" value="0"/>
<c name="addr_2nd" type="2" value="0"/>
<c name="bit_bias" type="2" value="0"/>
<c name="byte_bias" type="4" value="0"/>
<c name="description" type="10" value="robot to pc"/>
<c name="dev_name" type="10" value="autotest"/>
<c name="dev_type" type="10" value="MODBUS"/>
<c name="end_addr" type="2" value="41001"/>
<c name="function" type="10" value=""/>
<c name="len" type="2" value="1"/>
<c name="name" type="10" value="time_to_go"/>
<c name="retain" type="1" value="false"/>
<c name="rw" type="10" value="rdwr"/>
<c name="type" type="10" value="bool"/>
<c name="value"/>
<c name="value_single" type="10" value=""/>
<c name="bias" type="2" value="0"/>
</l>
</m>

Binary file not shown.