5 Commits

Author SHA1 Message Date
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
03b15751c2 add exception handle for openapi-selector 2024-08-17 09:28:33 +08:00
29bd4185c4 version change 2024-08-16 17:48:08 +08:00
97071d231f Merge branch 't_change_ui' 2024-08-16 17:23:25 +08:00
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
10 changed files with 290 additions and 245 deletions

4
.gitignore vendored
View File

@ -7,10 +7,8 @@ aio/venv
aio/__pycache__/ aio/__pycache__/
aio/code/automatic_test/__pycache__/ aio/code/automatic_test/__pycache__/
aio/code/data_process/__pycache__/ aio/code/data_process/__pycache__/
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/code/commons/__pycache__/ aio/code/commons/__pycache__/
aio/assets/templates/debug.log aio/assets/templates/logs/
dial_gauge/results.xlsx dial_gauge/results.xlsx

View File

@ -34,7 +34,7 @@
打包时,只需要修改 clibs.py 中的 PREFIX 即可,调试时再修改回来 打包时,只需要修改 clibs.py 中的 PREFIX 即可,调试时再修改回来
``` ```
pyinstaller --noconfirm --onedir --windowed --optimize 2 --contents-directory . --upx-dir "D:/Syncthing/common/A_Program/upx-4.2.4-win64/" --add-data "C:/Users/Administrator/AppData/Local/Programs/Python/Python312/Lib/site-packages/customtkinter;customtkinter/" --add-data "D:/Syncthing/company/D-测试工作/X-自动化测试/01-AIO/rokae/aio/assets/templates:templates" --version-file ../assets/file_version_info.txt -i ../assets/icon.ico ../code/aio.py -p ../code/data_process/brake.py -p ../code/data_process/iso.py -p ../code/data_process/current.py -p ../code/data_process/wavelogger.py -p ../code/commons/openapi.py -p ../code/commons/clibs.py -p ../code/automatic_test/btn_functions.py -p ../code/automatic_test/do_current.py -p ../code/automatic_test/do_brake.py -p ../code/durable_action/factory_test.py pyinstaller --noconfirm --onedir --windowed --optimize 2 --contents-directory . --upx-dir "D:/Syncthing/common/A_Program/upx-4.2.4-win64/" --add-data "C:/Users/Administrator/AppData/Local/Programs/Python/Python312/Lib/site-packages/customtkinter;customtkinter/" --add-data "D:/Syncthing/company/D-测试工作/X-自动化测试/01-AIO/rokae/aio/assets/templates:templates" --version-file ../assets/file_version_info.txt -i ../assets/templates/icon.ico ../code/aio.py -p ../code/data_process/brake.py -p ../code/data_process/iso.py -p ../code/data_process/current.py -p ../code/data_process/wavelogger.py -p ../code/commons/openapi.py -p ../code/commons/clibs.py -p ../code/automatic_test/btn_functions.py -p ../code/automatic_test/do_current.py -p ../code/automatic_test/do_brake.py -p ../code/durable_action/factory_test.py
``` ```
--- ---
@ -275,7 +275,7 @@ v0.1.5.1(2024/06/12)
5. [requirements.txt] 新增必要库配置文件 5. [requirements.txt] 新增必要库配置文件
v0.1.5.2(2024/06/13) v0.1.5.2(2024/06/13)
1. [brake.py/aio.py]: 将sto修改为estop 1. [brake.py/aio.py] 将sto修改为estop
2. [brake.py] 修改了速度计算逻辑新版本的vel列数据遵循如下规则av = vel * 180 / pi根据av再计算speed 2. [brake.py] 修改了速度计算逻辑新版本的vel列数据遵循如下规则av = vel * 180 / pi根据av再计算speed
3. [brake.py] 将threshold修改为常量50 3. [brake.py] 将threshold修改为常量50
4. [brake.py] 提高了输出提示语的明确性,删除了不必要的省略号 4. [brake.py] 提高了输出提示语的明确性,删除了不必要的省略号
@ -449,18 +449,18 @@ v0.1.7.6(2024/07/04)
3. [APIs: openapi.py] 3. [APIs: openapi.py]
- 增加了modbus读取浮点数的功能 - 增加了modbus读取浮点数的功能
- 优化了get_from_id的逻辑 - 优化了get_from_id的逻辑
4. [autotest.xml]: 新增了scenario_time只写寄存器 4. [autotest.xml] 新增了scenario_time只写寄存器
v0.1.8.0(2024/07/04) v0.1.8.0(2024/07/04)
1. [APIs: do_current.py]: 完成了堵转电流和惯量负载电机电流的采集和处理,至此,电机电流的自动化工作基本完成 1. [APIs: do_current.py] 完成了堵转电流和惯量负载电机电流的采集和处理,至此,电机电流的自动化工作基本完成
v0.1.8.1(2024/07/05) v0.1.8.1(2024/07/05)
1. [APIs: do_brake.py]: 完成了制动性能测试框架的搭建,可以顺利执行完整的测试程序,但是未实现急停和数据处理 1. [APIs: do_brake.py] 完成了制动性能测试框架的搭建,可以顺利执行完整的测试程序,但是未实现急停和数据处理
2. [APIs: aio.py]: 修改了do_brake主函数的参数 2. [APIs: aio.py] 修改了do_brake主函数的参数
3. 增加工程文件target.zip 3. 增加工程文件target.zip
v0.1.8.2(2024/07/08) v0.1.8.2(2024/07/08)
1. [APIs: do_brake.py]: 完成了制动性能测试逻辑只不过制动信号传递生效延迟不可控暂时pending 1. [APIs: do_brake.py] 完成了制动性能测试逻辑只不过制动信号传递生效延迟不可控暂时pending
2. [APIs: do_current.py]: 修改曲线数据时序主要是value data取反即可解决了波形锯齿明细的问题 2. [APIs: do_current.py]: 修改曲线数据时序主要是value data取反即可解决了波形锯齿明细的问题
3. [APIs: openapi.py]: modbus新增了触发急停信号的寄存器 stop0_signal并重写了解除急停socket新增了register.set_value协议 3. [APIs: openapi.py]: modbus新增了触发急停信号的寄存器 stop0_signal并重写了解除急停socket新增了register.set_value协议
@ -591,8 +591,8 @@ v0.2.0.5(2024/07/31)
- 保持电流,只取最后 15s - 保持电流,只取最后 15s
- 优化 ssh 输入密码的部分 - 优化 ssh 输入密码的部分
6. [t_change_ui: all the part]: 引入 commons 包,并定制了 logging 输出,后续持续优化 6. [t_change_ui: all the part]: 引入 commons 包,并定制了 logging 输出,后续持续优化
7. [APIs: btn_functions.py]: 重写了告警输出函数,从日志中拿数据 7. [APIs: btn_functions.py] 重写了告警输出函数,从日志中拿数据
8. [APIs: aio.py]: 将日志框输出的内容,也保存至日志文件 8. [APIs: aio.py] 将日志框输出的内容,也保存至日志文件
9. [APIs: do_brake.py] 9. [APIs: do_brake.py]
- 修改获取初始速度的逻辑只获取configs文件中配置的时间内的速度 - 修改获取初始速度的逻辑只获取configs文件中配置的时间内的速度
- 新增 configs 参数 single_brake可针对特定条件做测试 - 新增 configs 参数 single_brake可针对特定条件做测试
@ -601,4 +601,27 @@ v0.2.0.5(2024/07/31)
v0.2.0.6(2024/08/09) v0.2.0.6(2024/08/09)
1. [t_change_ui: all files] 1. [t_change_ui: all files]
- 修改了 logger 的实现 - 修改了 logger 的实现
- 尤其是 clibs.py使用日志字典重写了日志记录的功能 - 尤其是 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 了
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 日志文件中

View File

@ -6,8 +6,8 @@ VSVersionInfo(
ffi=FixedFileInfo( ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4) # filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0. # Set not needed items to zero 0.
filevers=(0, 2, 0, 5), filevers=(0, 2, 0, 8),
prodvers=(0, 2, 0, 5), prodvers=(0, 2, 0, 8),
# Contains a bitmask that specifies the valid bits 'flags'r # Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f, mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file. # Contains a bitmask that specifies the Boolean attributes of the file.
@ -31,12 +31,12 @@ VSVersionInfo(
'040904b0', '040904b0',
[StringStruct('CompanyName', 'Rokae - https://www.rokae.com/'), [StringStruct('CompanyName', 'Rokae - https://www.rokae.com/'),
StringStruct('FileDescription', 'All in one automatic toolbox'), StringStruct('FileDescription', 'All in one automatic toolbox'),
StringStruct('FileVersion', '0.2.0.5 (2024-08-02)'), StringStruct('FileVersion', '0.2.0.8 (2024-08-20)'),
StringStruct('InternalName', 'AIO.exe'), StringStruct('InternalName', 'AIO.exe'),
StringStruct('LegalCopyright', '© 2024-2024 Manford Fan'), StringStruct('LegalCopyright', '© 2024-2024 Manford Fan'),
StringStruct('OriginalFilename', 'AIO.exe'), StringStruct('OriginalFilename', 'AIO.exe'),
StringStruct('ProductName', 'AIO'), StringStruct('ProductName', 'AIO'),
StringStruct('ProductVersion', '0.2.0.5 (2024-08-02)')]) StringStruct('ProductVersion', '0.2.0.8 (2024-08-20)')])
]), ]),
VarFileInfo([VarStruct('Translation', [1033, 1200])]) VarFileInfo([VarStruct('Translation', [1033, 1200])])
] ]

Binary file not shown.

View File

@ -1 +1 @@
1 0

View File

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 162 KiB

View File

@ -1 +1 @@
0.2.0.5 @ 08/02/2024 0.2.0.8 @ 08/20/2024

View File

@ -37,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': '指标选择'},
} }
@ -70,21 +70,24 @@ class App(customtkinter.CTk):
# ===================================================================== # =====================================================================
# configure window # configure window
self.title("AIO - All in one automatic toolbox") self.title("AIO - All in one automatic toolbox")
# self.iconbitmap('./icon.ico') self.wm_iconbitmap(clibs.app_icon)
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.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13), weight=1) self.grid_rowconfigure(1, weight=19)
self.grid_columnconfigure(0, weight=1)
self.grid_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)
@ -92,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.8\nDate: 08/20/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: ", '')
@ -192,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']
@ -207,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
@ -228,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)
@ -276,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)
@ -319,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')
@ -497,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
@ -510,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)
@ -533,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:
@ -551,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:
@ -560,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:
@ -571,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,4 +1,4 @@
from os import scandir from os import scandir, mkdir
from threading import Thread from threading import Thread
from time import sleep from time import sleep
from os.path import exists from os.path import exists
@ -17,8 +17,10 @@ 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_hmi = f'{PREFIX}templates/c_msg.log' app_icon = f'{PREFIX}templates/icon.ico'
log_data_debug = f'{PREFIX}templates/debug.log' log_path = f'{PREFIX}templates/logs/'
log_data_hmi = f'{PREFIX}templates/logs/c_msg.log'
log_data_debug = f'{PREFIX}templates/logs/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'
@ -41,6 +43,9 @@ durable_data_current_max = {
'axis6': [0 for _ in range(18)], 'axis6': [0 for _ in range(18)],
} }
if not exists(log_path):
mkdir(log_path)
# version表示版本该键值为从1开始的整数。该key必选除此之外其它key都是可选。 # version表示版本该键值为从1开始的整数。该key必选除此之外其它key都是可选。
# formatters日志格式化器其value值为一个字典该字典的每个键值对都代表一个Formatter键值对中key代表Formatter ID(自定义ID)value为字典描述如何配置相应的Formatter实例。默认格式为 %(message)s # formatters日志格式化器其value值为一个字典该字典的每个键值对都代表一个Formatter键值对中key代表Formatter ID(自定义ID)value为字典描述如何配置相应的Formatter实例。默认格式为 %(message)s
# filters日志过滤器其value值为一个字典该字典的每个键值对都代表一个Filter键值对中key代表Filter ID(自定义ID)value为字典描述如何配置相应的Filter实例。 # filters日志过滤器其value值为一个字典该字典的每个键值对都代表一个Filter键值对中key代表Filter ID(自定义ID)value为字典描述如何配置相应的Filter实例。
@ -78,7 +83,7 @@ log_dicts = {
'formatter': 'test', 'formatter': 'test',
}, },
'hmi.log': { 'hmi.log': {
'level': 'DEBUG', 'level': 'WARNING',
'class': 'concurrent_log_handler.ConcurrentRotatingFileHandler', 'class': 'concurrent_log_handler.ConcurrentRotatingFileHandler',
'filename': log_data_hmi, 'filename': log_data_hmi,
'maxBytes': 1024*1024*50, 'maxBytes': 1024*1024*50,

View File

@ -203,7 +203,7 @@ class HmiRequest(object):
self.c_xs.connect((clibs.ip_addr, 6666)) self.c_xs.connect((clibs.ip_addr, 6666))
self.c_xs.setblocking(False) self.c_xs.setblocking(False)
self.w2t("Connection success", 0, 0, 'green', tab_name=self.tab_name) logger.info("Connection success...")
with open(clibs.heartbeat, "w", encoding='utf-8') as f_hb: with open(clibs.heartbeat, "w", encoding='utf-8') as f_hb:
f_hb.write('1') f_hb.write('1')
md = ModbusRequest(self.w2t) md = ModbusRequest(self.w2t)
@ -213,7 +213,7 @@ class HmiRequest(object):
md.write_probe(False) md.write_probe(False)
md.write_axis(1) md.write_axis(1)
except Exception as Err: except Exception as Err:
self.w2t("Connection failed...", 0, 0, 'red', tab_name=self.tab_name) logger.info("Connection failed...")
with open(clibs.heartbeat, "w", encoding='utf-8') as f_hb: with open(clibs.heartbeat, "w", encoding='utf-8') as f_hb:
f_hb.write('0') f_hb.write('0')
@ -255,13 +255,13 @@ class HmiRequest(object):
with open(clibs.heartbeat, "w", encoding='utf-8') as f_hb: with open(clibs.heartbeat, "w", encoding='utf-8') as f_hb:
f_hb.write(_flag) f_hb.write(_flag)
if _flag == '0': if _flag == '0':
self.w2t(f"{_id} 心跳丢失,连接失败,重新连接中...", 0, 7, 'red', tab_name=self.tab_name) logger.info(f"{_id} 心跳丢失,连接失败,重新连接中...")
sleep(2) sleep(2)
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.debug(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:
@ -539,14 +539,17 @@ class HmiRequest(object):
sel.unregister(conn) sel.unregister(conn)
conn.close() conn.close()
sel = selectors.DefaultSelector() try:
sel.register(sock, selectors.EVENT_READ, to_read) sel = selectors.DefaultSelector()
sel.register(sock, selectors.EVENT_READ, to_read)
while self.t_bool: while self.t_bool:
events = sel.select() events = sel.select()
for key, mask in events: for key, mask in events:
callback = key.data callback = key.data
callback(key.fileobj, mask) callback(key.fileobj, mask)
except Exception as Err:
logger.warning(Err)
def unpackage_xs(self, sock): def unpackage_xs(self, sock):
def to_read(conn, mask): def to_read(conn, mask):
@ -559,14 +562,17 @@ class HmiRequest(object):
sel.unregister(conn) sel.unregister(conn)
conn.close() conn.close()
sel = selectors.DefaultSelector() try:
sel.register(sock, selectors.EVENT_READ, to_read) sel = selectors.DefaultSelector()
sel.register(sock, selectors.EVENT_READ, to_read)
while self.t_bool: while self.t_bool:
events = sel.select() events = sel.select()
for key, mask in events: for key, mask in events:
callback = key.data callback = key.data
callback(key.fileobj, mask) callback(key.fileobj, mask)
except Exception as Err:
logger.warning(Err)
def gen_id(self, command): def gen_id(self, command):
_now = time() _now = time()
@ -615,7 +621,8 @@ 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}: 请求发送失败...{Err}", 0, 0, 'red', tab_name=self.tab_name) # self.w2t(f"{cmd}: 请求发送失败...{Err}", 0, 0, 'red', tab_name=self.tab_name)
logger.info(f"{cmd}: 请求发送失败...{Err}")
return req['id'] return req['id']