界面优化,监控逻辑优化

This commit is contained in:
gitea 2025-03-30 12:27:57 +08:00
parent c325875dbb
commit a9a6db23fd
20 changed files with 574 additions and 594 deletions

242
aio.py
View File

@ -4,6 +4,7 @@ import os
import re import re
import sqlite3 import sqlite3
import sys import sys
import threading
import time import time
from urllib import request from urllib import request
import os.path import os.path
@ -92,46 +93,43 @@ class MainWindow(main_window.Ui_MainWindow):
def __init__(self): def __init__(self):
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
self.close_on_net_error = None
self.is_searching = False self.is_searching = False
self.setupUi(self) self.setupUi(self)
self.predoes() self.pre_does()
def predoes(self): def pre_does(self):
# ========================= treeview init ========================= # ========================= treeview init =========================
self.cb_data_current.setDisabled(True)
self.setup_statusbar()
self.setWindowIcon(QIcon(f"{clibs.PREFIX}/media/icon.ico"))
self.treew_log.header().setFont(QFont("Arial", 12, QFont.Weight.Bold)) self.treew_log.header().setFont(QFont("Arial", 12, QFont.Weight.Bold))
header = self.treew_log.header() header = self.treew_log.header()
for i in range(self.treew_log.columnCount()): for i in range(self.treew_log.columnCount()):
header.setSectionResizeMode(i, QHeaderView.ResizeMode.ResizeToContents) header.setSectionResizeMode(i, QHeaderView.ResizeMode.ResizeToContents)
self.md_btn.setStyleSheet("background-color: DarkGrey; color: white;")
self.ec_btn.setStyleSheet("background-color: DarkGrey; color: white;")
# ========================= stylesheet =========================
with open(f"{clibs.PREFIX}/qss/style.qss", mode="r", encoding="utf-8") as f_qss:
style_sheet = f_qss.read()
self.setStyleSheet(style_sheet)
# ========================= clibs ========================= # ========================= clibs =========================
self.setup_statusbar() logger_handler = clibs.LoggerHandler()
self.setWindowIcon(QIcon(f"{clibs.PREFIX}/media/icon.ico")) logger_handler.signal.connect(self.w2t)
# ========================= styleSheet ========================= clibs.logger = logger_handler.logger
tws = [self.tw_funcs, self.tw_docs] # ========================= detection =========================
for tw in tws: self.detection_thread = StateDetection()
tw.setStyleSheet(""" self.detection_thread.finished.connect(self.prog_done_detection)
QTabBar::tab:selected { self.detection_thread.start()
background: #0078D4; # ========================= debug =========================
color: white; # for i in range(105):
border-radius: 4px; # clibs.logger("DEBUG", "aio", "debug testing log for aio", color="gray")
} # clibs.logger("INFO", "clibs", "info testing log for clibs", color="green")
QTabBar::tab:!selected { # clibs.logger("WARNING", "iso", "warning testing log for aio", color="yellow")
background: #F0F0F0; # # clibs.logger("ERROR", "openapi", "error testing log for aio", color="red")
color: #333;
}
QTabWidget::pane {
border: 1px solid #CCCCCC;
}
""")
# ============================↓↓↓debug↓↓↓============================
# print(f"self.cb_data_func.currentIndex() = {self.cb_data_func.currentIndex()}")
def run_program_thread(self, prog, idx, prog_done, reserved): def run_program_thread(self, prog, idx, prog_done, reserved):
if idx != -98 and idx != -97: if idx != -98 and idx != -97:
self.tw_docs.setCurrentIndex(0) self.tw_docs.setCurrentIndex(0)
if idx != -99 and idx != -98:
prog.output.connect(self.w2t)
self.t = QThread(self) self.t = QThread(self)
self.run = RunProg() self.run = RunProg()
@ -191,7 +189,13 @@ class MainWindow(main_window.Ui_MainWindow):
self.run_program_thread(factory_test.DoFactoryTest(self.le_durable_path.text(), self.le_durable_interval.text(), self.get_checkbox_states()), 6, prog_done, None) self.run_program_thread(factory_test.DoFactoryTest(self.le_durable_path.text(), self.le_durable_interval.text(), self.get_checkbox_states()), 6, prog_done, None)
def prog_stop(self): def prog_stop(self):
QMessageBox.warning(self, "停止运行", "运行过程中不建议停止运行,可能会损坏文件,如果确实需要停止运行,可以直接关闭窗口!") if sum(clibs.running) == 0:
return
idx = clibs.running.index(1)
clibs.running[idx] = 0
clibs.logger("INFO", "aio", f"{clibs.functions[idx]}程序已经停止涉及Excel文件读写时可能会损坏该文件", "red")
# QMessageBox.warning(self, "停止运行", "运行过程中不建议停止运行,可能会损坏文件,如果确实需要停止运行,可以直接关闭窗口!")
def prog_reset(self): def prog_reset(self):
self.tw_docs.setCurrentIndex(0) self.tw_docs.setCurrentIndex(0)
@ -205,7 +209,6 @@ class MainWindow(main_window.Ui_MainWindow):
idx_dict[tab_index].setText(dir_path) idx_dict[tab_index].setText(dir_path)
def curve_draw(self): def curve_draw(self):
output = Signal(str, str)
procs = self.get_checkbox_states() procs = self.get_checkbox_states()
dir_path = self.le_durable_path.text() dir_path = self.le_durable_path.text()
curve_map = { curve_map = {
@ -230,7 +233,7 @@ class MainWindow(main_window.Ui_MainWindow):
self.w2t(f"需要选择至少一个功能,才能继续绘图......", "red") self.w2t(f"需要选择至少一个功能,才能继续绘图......", "red")
return return
_, files = clibs.traversal_files(dir_path, output) _, files = clibs.traversal_files(dir_path)
csv_files = [] csv_files = []
for file in files: for file in files:
if file.endswith(".csv"): if file.endswith(".csv"):
@ -320,7 +323,7 @@ class MainWindow(main_window.Ui_MainWindow):
end = first_id-1 if first_id-1 > 0 else None end = first_id-1 if first_id-1 > 0 else None
if end is None: if end is None:
return return
start = end-100 if end-100 > 0 else 1 start = end-100+1 if end-100+1 > 0 else 1
clibs.cursor.execute(f"SELECT * FROM logs WHERE id BETWEEN {start} AND {end}") clibs.cursor.execute(f"SELECT * FROM logs WHERE id BETWEEN {start} AND {end}")
records = clibs.cursor.fetchall() records = clibs.cursor.fetchall()
@ -397,12 +400,12 @@ class MainWindow(main_window.Ui_MainWindow):
line_number = self.treew_log.topLevelItemCount() line_number = self.treew_log.topLevelItemCount()
last_id = int(self.treew_log.topLevelItem(line_number-1).text(0)) last_id = int(self.treew_log.topLevelItem(line_number-1).text(0))
start = last_id + 1 if last_id % 100 == 0 else last_id - last_id % 100 + 1 start = last_id + 1 if last_id % 100 == 0 else last_id - last_id % 100 + 1
end = int(start) + 100 end = int(start) + 100 - 1
if int(start) <= len_records: if start <= len_records:
clibs.cursor.execute(f"select * from logs where id between {start} and {end}") clibs.cursor.execute(f"select * from logs where id between {start} and {end}")
records = clibs.cursor.fetchall() records = clibs.cursor.fetchall()
pages_all = len_records // 100 if len_records % 100 == 0 else len_records // 100 + 1 pages_all = len_records // 100 if len_records % 100 == 0 else len_records // 100 + 1
current_page = int(start) // 100 if int(start) % 100 == 0 else int(start) // 100 + 1 current_page = start // 100 if start % 100 == 0 else start // 100 + 1
return pages_all, current_page, records return pages_all, current_page, records
elif self.is_searching is True: elif self.is_searching is True:
@ -688,25 +691,26 @@ class MainWindow(main_window.Ui_MainWindow):
flag, result, ret, error, idx, network = results flag, result, ret, error, idx, network = results
if flag is False: if flag is False:
... self.w2t(f"{network.upper()}连接失败", "red")
# self.w2t(f"{network.upper()}连接失败", "red")
elif flag is True: elif flag is True:
clibs.status[network] = 1 clibs.status[network] = 1
if network == "hmi": if network == "hmi":
self.btn_hmi_conn.setText("断开") self.btn_hmi_conn.setText("断开")
self.hmi_state.setText(f'<img src="{clibs.PREFIX}/media/green.png" width="10" height="10" /><font face="consolas" size="4"><b>HR&nbsp;&nbsp;</b></font>')
clibs.c_hr = result clibs.c_hr = result
elif network == "md": elif network == "md":
self.btn_md_conn.setText("断开") self.btn_md_conn.setText("断开")
self.md_state.setText(f'<img src="{clibs.PREFIX}/media/green.png" width="10" height="10" /><font face="consolas" size="4"><b>MD&nbsp;&nbsp;</b></font>')
clibs.c_md = result clibs.c_md = result
elif network == "ec": elif network == "ec":
self.btn_ec_conn.setText("断开") self.btn_ec_conn.setText("断开")
self.ec_state.setText(f'<img src="{clibs.PREFIX}/media/green.png" width="10" height="10" /><font face="consolas" size="4"><b>EC&nbsp;&nbsp;</b></font>')
clibs.c_ec = result clibs.c_ec = result
def prog_done_disconn(self, results): def prog_done_disconn(self, results):
self.btn_hmi_conn.setDisabled(False) self.btn_hmi_conn.setDisabled(False)
self.btn_md_conn.setDisabled(False) self.btn_md_conn.setDisabled(False)
self.btn_ec_conn.setDisabled(False) self.btn_ec_conn.setDisabled(False)
flag, result, ret, error, idx, network = results flag, result, ret, error, idx, network = results
if flag is False: if flag is False:
self.w2t(f"{network.upper()}断开连接失败", "red") self.w2t(f"{network.upper()}断开连接失败", "red")
@ -714,13 +718,16 @@ class MainWindow(main_window.Ui_MainWindow):
clibs.status[network] = 0 clibs.status[network] = 0
if network == "hmi": if network == "hmi":
self.btn_hmi_conn.setText("连接") self.btn_hmi_conn.setText("连接")
clibs.c_hr = result self.hmi_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>HR&nbsp;&nbsp;</b></font>')
clibs.c_hr = None
elif network == "md": elif network == "md":
self.btn_md_conn.setText("连接") self.btn_md_conn.setText("连接")
clibs.c_md = result self.md_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>MD&nbsp;&nbsp;</b></font>')
clibs.c_md = None
elif network == "ec": elif network == "ec":
self.btn_ec_conn.setText("连接") self.btn_ec_conn.setText("连接")
clibs.c_ec = result self.ec_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>EC&nbsp;&nbsp;</b></font>')
clibs.c_ec = None
def hmi_conn(self): def hmi_conn(self):
self.btn_hmi_conn.setDisabled(True) self.btn_hmi_conn.setDisabled(True)
@ -759,22 +766,51 @@ class MainWindow(main_window.Ui_MainWindow):
self.run_program_thread(clibs.c_ec.close, -99, self.prog_done_disconn, "ec") self.run_program_thread(clibs.c_ec.close, -99, self.prog_done_disconn, "ec")
def hmi_page(self): def hmi_page(self):
self.pte_md_send.clear()
self.pte_md_recv.clear()
self.pte_ec_send.clear()
self.pte_ec_recv.clear()
self.tw_funcs.setCurrentIndex(3)
self.sw_network.setCurrentIndex(0) self.sw_network.setCurrentIndex(0)
self.hmi_btn.setStyleSheet("background-color: DarkCyan; color: white;")
self.md_btn.setStyleSheet("background-color: DarkGrey; color: white;")
self.ec_btn.setStyleSheet("background-color: DarkGrey; color: white;")
def md_page(self): def md_page(self):
self.pte_hmi_send.clear()
self.pte_hmi_recv.clear()
self.pte_ec_send.clear()
self.pte_ec_recv.clear()
self.tw_funcs.setCurrentIndex(3)
self.sw_network.setCurrentIndex(1) self.sw_network.setCurrentIndex(1)
self.hmi_btn.setStyleSheet("background-color: DarkGrey; color: white;")
self.md_btn.setStyleSheet("background-color: DarkCyan; color: white;")
self.ec_btn.setStyleSheet("background-color: DarkGrey; color: white;")
def ec_page(self): def ec_page(self):
self.pte_md_send.clear()
self.pte_md_recv.clear()
self.pte_hmi_send.clear()
self.pte_hmi_recv.clear()
self.tw_funcs.setCurrentIndex(3)
self.sw_network.setCurrentIndex(2) self.sw_network.setCurrentIndex(2)
self.hmi_btn.setStyleSheet("background-color: DarkGrey; color: white;")
self.md_btn.setStyleSheet("background-color: DarkGrey; color: white;")
self.ec_btn.setStyleSheet("background-color: DarkCyan; color: white;")
def prog_done_hmi_send(self, results): def prog_done_hmi_send(self, results):
_, result, ret, error, idx, (msg_id, flag) = results _, result, ret, error, idx, (msg_id, flag) = results
if _ is False:
self.btn_hmi_send.setDisabled(False)
clibs.logger("INFO", "aio", f"hmi: [send] 请求发送失败 {msg_id}", "red")
return
records = clibs.c_hr.get_from_id(msg_id) records = clibs.c_hr.get_from_id(msg_id)
for record in records: for record in records:
if "请求发送成功" not in record[0]: if "请求发送成功" not in record[0]:
self.pte_him_recv.clear() self.pte_hmi_recv.clear()
response = eval(record[0]) if flag == 0 else json.loads(record[0]) response = eval(record[0]) if flag == 0 else json.loads(record[0])
self.pte_him_recv.appendPlainText(json.dumps(response, indent=4, separators=(",", ":"))) self.pte_hmi_recv.appendPlainText(json.dumps(response, indent=4, separators=(",", ":")))
else: else:
self.btn_hmi_send.setDisabled(False) self.btn_hmi_send.setDisabled(False)
@ -852,9 +888,7 @@ class MainWindow(main_window.Ui_MainWindow):
self.pte_ec_recv.clear() self.pte_ec_recv.clear()
cmd = self.pte_ec_send.toPlainText().strip() cmd = self.pte_ec_send.toPlainText().strip()
try: try:
clibs.c_ec.s_string(cmd) result = clibs.c_ec.sr_string(cmd)
time.sleep(clibs.INTERVAL/2)
result = clibs.c_ec.r_string(cmd)
self.pte_ec_recv.appendPlainText(str(result)) self.pte_ec_recv.appendPlainText(str(result))
except Exception as err: except Exception as err:
self.pte_ec_recv.appendPlainText(f"操作失败:{err}") self.pte_ec_recv.appendPlainText(f"操作失败:{err}")
@ -862,7 +896,7 @@ class MainWindow(main_window.Ui_MainWindow):
def hmi_cb_change(self): def hmi_cb_change(self):
cmd = self.cb_hmi_cmd.currentText() cmd = self.cb_hmi_cmd.currentText()
self.pte_hmi_send.clear() self.pte_hmi_send.clear()
self.pte_him_recv.clear() self.pte_hmi_recv.clear()
with open(f"{clibs.PREFIX}/files/protocols/hmi/{cmd}.json", mode="r", encoding="utf-8") as f_hmi: with open(f"{clibs.PREFIX}/files/protocols/hmi/{cmd}.json", mode="r", encoding="utf-8") as f_hmi:
hmi_dict = json.load(f_hmi) hmi_dict = json.load(f_hmi)
t = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f") t = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")
@ -886,6 +920,13 @@ class MainWindow(main_window.Ui_MainWindow):
c_send = f_md.read() c_send = f_md.read()
self.pte_ec_send.appendPlainText(c_send) self.pte_ec_send.appendPlainText(c_send)
def data_cb_change(self):
proc = self.cb_data_func.currentText()
if proc != "转矩":
self.cb_data_current.setDisabled(True)
else:
self.cb_data_current.setDisabled(False)
def check_interval(self): def check_interval(self):
try: try:
interval = float(self.le_durable_interval.text()) interval = float(self.le_durable_interval.text())
@ -894,13 +935,21 @@ class MainWindow(main_window.Ui_MainWindow):
interval = clibs.CYCLE interval = clibs.CYCLE
self.le_durable_interval.setText(str(interval)) self.le_durable_interval.setText(str(interval))
def state_detection(self): def prog_done_detection(self, finished):
while True: if clibs.status["hmi"] == 0:
time.sleep(clibs.INTERVAL)
if clibs.status["hmi"] == 0 and self.btn_hmi_conn.text() == "断开":
self.btn_hmi_conn.setText("连接") self.btn_hmi_conn.setText("连接")
elif clibs.status["hmi"] == 1 and self.btn_hmi_conn.text() == "连接": self.hmi_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>HR&nbsp;&nbsp;</b></font>')
self.btn_hmi_conn.setText("断开") if clibs.status["md"] == 0:
self.btn_md_conn.setText("连接")
self.md_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>MD&nbsp;&nbsp;</b></font>')
if clibs.status["ec"] == 0:
self.btn_ec_conn.setText("连接")
self.ec_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>EC&nbsp;&nbsp;</b></font>')
# ============= Program running status =============
if sum(clibs.running) == 1:
self.run_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>BUSY</b></font>')
else:
self.run_state.setText(f'<img src="{clibs.PREFIX}/media/green.png" width="10" height="10" /><font face="consolas" size="4"><b>IDLE</b></font>')
def closeEvent(self, event): def closeEvent(self, event):
idx = -1 if clibs.running.count(1) == 0 else clibs.running.index(1) idx = -1 if clibs.running.count(1) == 0 else clibs.running.index(1)
@ -913,7 +962,7 @@ class MainWindow(main_window.Ui_MainWindow):
clibs.conn.backup(target=disk_conn, pages=1, progress=None) clibs.conn.backup(target=disk_conn, pages=1, progress=None)
_, logs = clibs.traversal_files(".", None) _, logs = clibs.traversal_files(".")
logs.sort() logs.sort()
while len(logs) > 10: while len(logs) > 10:
_ = logs.pop(0) _ = logs.pop(0)
@ -938,24 +987,68 @@ class MainWindow(main_window.Ui_MainWindow):
with open(f"{clibs.PREFIX}/files/version/server_vers", mode="r", encoding="utf-8") as f_server: with open(f"{clibs.PREFIX}/files/version/server_vers", mode="r", encoding="utf-8") as f_server:
server_vers = f_server.read().strip() server_vers = f_server.read().strip()
update_label = QLabel() self.update_label, self.hmi_state, self.md_state, self.ec_state, self.run_state, self.version_label = QLabel(), ClickableLabel(), ClickableLabel(), ClickableLabel(), QLabel(), QLabel()
version_label = QLabel() self.statusbar.addWidget(self.version_label, 0)
self.statusbar.addWidget(version_label, 0) self.statusbar.addWidget(self.hmi_state, 0)
self.statusbar.addPermanentWidget(update_label, 0) # 添加到右侧 self.statusbar.addWidget(self.md_state, 0)
self.statusbar.addWidget(self.ec_state, 0)
self.statusbar.addWidget(self.run_state, 0)
self.statusbar.addPermanentWidget(self.update_label, 0) # 添加到右侧
self.hmi_state.clicked.connect(self.hmi_page)
self.md_state.clicked.connect(self.md_page)
self.ec_state.clicked.connect(self.ec_page)
if local_vers == server_vers: if local_vers == server_vers:
update_label.setText(f'<img src="{clibs.PREFIX}/media/updated.png" width="12" height="12" /><font color="#0D8A3D" face="consolas" size="4"><b>&nbsp;当前是最新版本,继续保持!&nbsp;</b></font>') self.update_label.setText(f'<img src="{clibs.PREFIX}/media/updated.png" width="14" height="14" style="vertical-align: middle;" /><span style="vertical-align: middle; font-size: 14px; font-weight: bold; color: #0D8A3D;"> Current is the latest version</span>')
elif local_vers > server_vers: elif local_vers > server_vers:
pass pass
elif local_vers < server_vers: elif local_vers < server_vers:
update_label.setText(f'''<a href="https://www.rustle.cc/aio.zip" style="text-decoration: none;"><img src="{clibs.PREFIX}/media/upgrade.png" width="12" height="12" /><font color="#D81E06" face="consolas" size="4"><b>&nbsp;v{server_vers.split('@')[0]}已经发布,尽快更新至最新版本!&nbsp;</b></font></a>''') self.update_label.setText(f'''<a href="https://www.rustle.cc/aio.zip" style="text-decoration: none;"><img src="{clibs.PREFIX}/media/upgrade.png" width="14" height="14" style="vertical-align: middle;" /><span style="vertical-align: middle; font-size: 14px; font-weight: bold; color: #D81E06;"> v{server_vers.split('@')[0]} has been released, update ASAP!</span></a>''')
version_label.setText(f'<font color="black" face="consolas" size="4"><b>&nbsp;{vers_info}</b></font>') self.version_label.setText(f'<font color="black" face="consolas" size="4"><b>{vers_info}&nbsp;&nbsp;</b></font>')
update_label.setOpenExternalLinks(True) # 允许超链接在浏览器中打开 self.hmi_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>HR&nbsp;&nbsp;</b></font>')
# update_label.setAlignment(Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignRight) self.md_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>MD&nbsp;&nbsp;</b></font>')
update_label.setStyleSheet("border: none;") self.ec_state.setText(f'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>EC&nbsp;&nbsp;</b></font>')
update_label.setFrameShape(QFrame.Shape.NoFrame) self.run_state.setText(f'<img src="{clibs.PREFIX}/media/green.png" width="10" height="10" /><font face="consolas" size="4"><b>IDLE</b></font>')
update_label.setFrameShadow(QFrame.Shadow.Plain) self.update_label.setOpenExternalLinks(True) # 允许超链接在浏览器中打开
self.close_on_net_error = False
class StateDetection(QThread):
finished = Signal(bool)
def __init__(self, /):
super().__init__()
def run(self):
while True:
time.sleep(clibs.INTERVAL*2)
# ============= HMI connection status =============
try:
clibs.c_hr.execution("controller.heart")
except:
clibs.status["hmi"] = 0
# ============= MD connection status =============
try:
clibs.c_md.c.read_holding_registers(40503, count=1).registers[0]
except:
clibs.status["md"] = 0
# ============= EC connection status =============
try:
clibs.c_ec.sr_string("controller_is_running")
except:
clibs.status["ec"] = 0
self.finished.emit(True)
class ClickableLabel(QLabel):
def __init__(self, parent=None):
super().__init__(parent)
def mousePressEvent(self, event):
self.clicked.emit()
clicked = Signal()
class InitWork(QThread): class InitWork(QThread):
@ -994,13 +1087,16 @@ class SplashScreen(QApplication):
self.splash.show() self.splash.show()
self.splash.showMessage("正在加载资源.....", Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignHCenter, Qt.GlobalColor.white) self.splash.showMessage("正在加载资源.....", Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignHCenter, Qt.GlobalColor.white)
self.t = QThread(self) # self.t = QThread(self)
self.run = InitWork() # self.run = InitWork()
self.run.moveToThread(self.t) # self.run.moveToThread(self.t)
self.run.completed.connect(self.prog_done) # self.run.completed.connect(self.prog_done)
self.action.connect(self.run.program) # self.action.connect(self.run.program)
self.t.start() # self.t.start()
self.action.emit(1) # self.action.emit(1)
# without validation of server version
self.prog_done("true")
def prog_done(self, result): def prog_done(self, result):
if result == "false" or result == "": if result == "false" or result == "":

View File

@ -0,0 +1 @@
close_reduced_mode

View File

@ -0,0 +1 @@
open_reduced_mode

View File

@ -0,0 +1 @@
soft_estop_state

View File

@ -1 +0,0 @@
tcp_pos

View File

@ -0,0 +1 @@
tcp_pose

BIN
assets/media/green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
assets/media/red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

50
assets/qss/style.qss Normal file
View File

@ -0,0 +1,50 @@
/* ------------------------------------------- QTabBar -------------------------------------------*/
QTabBar::tab:selected {
padding: 6px;
background: #909090;
color: white;
border-radius: 0px;
}
QTabBar::tab:!selected {
padding: 4px;
background: #b0b0b0;
color: white;
}
QTabWidget::pane {
border: 4px solid #CCCCCC;
padding: 1px;
}
/* ------------------------------------------- QPushButton -------------------------------------------*/
QPushButton[objectName$="_btn"] {
background-color: DarkCyan; /* 按钮背景颜色 */
color: white; /* 按钮文本颜色 */
border: 1px solid DarkGray; /* 按钮边框 */
border-radius: 4px; /* 按钮圆角 */
padding: 2px 4px; /* 按钮内边距 */
}
QPushButton[objectName$="_btn"]:hover {
background-color: #000000;
}
QPushButton[objectName^="btn"] {
background-color: #666666; /* 按钮背景颜色 */
color: white; /* 按钮文本颜色 */
border: 1px solid #555555; /* 按钮边框 */
border-radius: 4px; /* 按钮圆角 */
padding: 4px 8px; /* 按钮内边距 */
}
QPushButton[objectName^="btn"]:hover {
background-color: #888888; /* 鼠标悬停时的背景颜色 */
}
QPushButton[objectName^="btn"]:pressed {
background-color: #8FBC8F; /* 按钮按下时的背景颜色 */
}
/* ------------------------------------------- QStatusBar -------------------------------------------*/
QStatusBar::item { border: 0px; }

View File

@ -9,27 +9,19 @@ from codes.common import clibs
class BrakeDataProcess(QThread): class BrakeDataProcess(QThread):
output = Signal(str, str)
def __init__(self, dir_path, /): def __init__(self, dir_path, /):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.idx = 0 self.idx = 0
self.logger = clibs.logger
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
@clibs.handle_exception
def check_files(self, rawdata_dirs, result_files): def check_files(self, rawdata_dirs, result_files):
msg_wrong = "需要有四个文件和若干个数据文件夹,可参考如下确认:<br>" msg_wrong = "需要有四个文件和若干个数据文件夹,可参考如下确认:<br>"
msg_wrong += "- reach33/66/100_XXXXXXX.xlsx<br>- *.cfg<br>" msg_wrong += "- reach33/66/100_XXXXXXX.xlsx<br>- *.cfg<br>"
msg_wrong += "- reach33_load33_speed33<br>- reach33_load33_speed66<br>...<br>- reach100_load100_speed66<br>- reach100_load100_speed100<br>" msg_wrong += "- reach33_load33_speed33<br>- reach33_load33_speed66<br>...<br>- reach100_load100_speed66<br>- reach100_load100_speed100<br>"
if len(result_files) != 4 or len(rawdata_dirs) == 0: if len(result_files) != 4 or len(rawdata_dirs) == 0:
self.logger("ERROR", "brake", msg_wrong, "red", "InitFileError") self.logger("ERROR", "brake", msg_wrong, "red")
config_file, reach33_file, reach66_file, reach100_file = None, None, None, None config_file, reach33_file, reach66_file, reach100_file = None, None, None, None
for result_file in result_files: for result_file in result_files:
@ -44,7 +36,7 @@ class BrakeDataProcess(QThread):
reach100_file = result_file reach100_file = result_file
else: else:
if not (config_file and reach33_file and reach66_file and reach100_file): if not (config_file and reach33_file and reach66_file and reach100_file):
self.logger("ERROR", "brake", msg_wrong, "red", "InitFileError") self.logger("ERROR", "brake", msg_wrong, "red")
reach_s = ['reach33', 'reach66', 'reach100'] reach_s = ['reach33', 'reach66', 'reach100']
load_s = ['load33', 'load66', 'load100'] load_s = ['load33', 'load66', 'load100']
@ -57,17 +49,17 @@ class BrakeDataProcess(QThread):
msg = f"报错信息:数据目录 {rawdata_dir} 命名不合规,请参考如下形式<br>" msg = f"报错信息:数据目录 {rawdata_dir} 命名不合规,请参考如下形式<br>"
msg += "命名规则reachAA_loadBB_speedCCAA/BB/CC 指的是臂展/负载/速度的比例<br>" msg += "命名规则reachAA_loadBB_speedCCAA/BB/CC 指的是臂展/负载/速度的比例<br>"
msg += "规则解释reach66_load100_speed33表示 66% 臂展100% 负载以及 33% 速度情况下的测试结果文件夹<br>" msg += "规则解释reach66_load100_speed33表示 66% 臂展100% 负载以及 33% 速度情况下的测试结果文件夹<br>"
self.logger("ERROR", "brake", msg, "red", "WrongDataFolder") self.logger("ERROR", "brake", msg, "red")
_, rawdata_files = clibs.traversal_files(rawdata_dir, self.output) _, rawdata_files = clibs.traversal_files(rawdata_dir)
if len(rawdata_files) != 3: if len(rawdata_files) != 3:
msg = f"数据目录 {rawdata_dir} 下数据文件个数错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件" msg = f"数据目录 {rawdata_dir} 下数据文件个数错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件"
self.logger("ERROR", "brake", msg, "red", "WrongDataFile") self.logger("ERROR", "brake", msg, "red")
for rawdata_file in rawdata_files: for rawdata_file in rawdata_files:
if not rawdata_file.endswith(".data"): if not rawdata_file.endswith(".data"):
msg = f"数据文件 {rawdata_file} 后缀错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件" msg = f"数据文件 {rawdata_file} 后缀错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件"
self.logger("ERROR", "brake", msg, "red", "WrongDataFile") self.logger("ERROR", "brake", msg, "red")
result_files = [] result_files = []
for _ in [reach33_file, reach66_file, reach100_file]: for _ in [reach33_file, reach66_file, reach100_file]:
@ -77,7 +69,6 @@ class BrakeDataProcess(QThread):
self.logger("INFO", "brake", "数据目录合规性检查结束,未发现问题......", "green") self.logger("INFO", "brake", "数据目录合规性检查结束,未发现问题......", "green")
return config_file, result_files return config_file, result_files
@clibs.handle_exception
def get_configs(self, config_file): def get_configs(self, config_file):
try: try:
with open(config_file, mode="r", encoding="utf-8") as f_config: with open(config_file, mode="r", encoding="utf-8") as f_config:
@ -85,7 +76,7 @@ class BrakeDataProcess(QThread):
p_dir = config_file.split('/')[-2] p_dir = config_file.split('/')[-2]
if not re.match("^[jJ][123]$", p_dir): if not re.match("^[jJ][123]$", p_dir):
self.logger("ERROR", "brake", "被处理的根文件夹命名必须是 [Jj][123] 的格式", "red", "DirNameError") self.logger("ERROR", "brake", "被处理的根文件夹命名必须是 [Jj][123] 的格式", "red")
axis = int(p_dir[-1]) # 要处理的轴 axis = int(p_dir[-1]) # 要处理的轴
rrs = [abs(_) for _ in configs["TRANSMISSION"]["REDUCTION_RATIO_NUMERATOR"]] # 减速比rr for reduction ratio rrs = [abs(_) for _ in configs["TRANSMISSION"]["REDUCTION_RATIO_NUMERATOR"]] # 减速比rr for reduction ratio
@ -94,7 +85,7 @@ class BrakeDataProcess(QThread):
av = avs[axis-1] av = avs[axis-1]
return av, rr return av, rr
except Exception as Err: except Exception as Err:
self.logger("ERROR", "brake", f"无法打开 {config_file},或者使用了错误的机型配置文件,需检查<br>{Err}", "red", "OpenFileError") self.logger("ERROR", "brake", f"无法打开 {config_file},或者使用了错误的机型配置文件,需检查<br>{Err}", "red")
def now_doing_msg(self, docs, flag): def now_doing_msg(self, docs, flag):
now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
@ -109,7 +100,6 @@ class BrakeDataProcess(QThread):
self.logger("INFO", "brake", f"[{now}] 文件 {docs} 数据已处理完毕") self.logger("INFO", "brake", f"[{now}] 文件 {docs} 数据已处理完毕")
@staticmethod @staticmethod
@clibs.handle_exception
def data2result(df, ws_result, row_start, row_end): def data2result(df, ws_result, row_start, row_end):
data = [] data = []
for row in range(row_start, row_end): for row in range(row_start, row_end):
@ -130,7 +120,6 @@ class BrakeDataProcess(QThread):
ws_result.cell(row=row, column=2).value = None ws_result.cell(row=row, column=2).value = None
ws_result.cell(row=row, column=3).value = None ws_result.cell(row=row, column=3).value = None
@clibs.handle_exception
def get_row_range(self, data_file, df, conditions, av, rr): def get_row_range(self, data_file, df, conditions, av, rr):
row_start, row_end = 0, 0 row_start, row_end = 0, 0
ratio = float(conditions[2].removeprefix('speed')) / 100 ratio = float(conditions[2].removeprefix('speed')) / 100
@ -142,7 +131,7 @@ class BrakeDataProcess(QThread):
row_start = row - 20 if row - 20 > 0 else 0 # 急停前找 20 个点 row_start = row - 20 if row - 20 > 0 else 0 # 急停前找 20 个点
break break
else: else:
self.logger("ERROR", "brake", f"数据文件 {data_file} 采集的数据中没有 ESTOP 为非 0 的情况,需要确认", "red", "StartNotFoundError") self.logger("ERROR", "brake", f"数据文件 {data_file} 采集的数据中没有 ESTOP 为非 0 的情况,需要确认", "red")
for row in range(row_start, df.index[-1] - 1, 10): for row in range(row_start, df.index[-1] - 1, 10):
speed_row = df.iloc[row, 0] * clibs.RADIAN * rr * 60 / 360 speed_row = df.iloc[row, 0] * clibs.RADIAN * rr * 60 / 360
@ -150,7 +139,7 @@ class BrakeDataProcess(QThread):
row_end = row + 100 if row + 100 <= df.index[-1] - 1 else df.index[-1] - 1 row_end = row + 100 if row + 100 <= df.index[-1] - 1 else df.index[-1] - 1
break break
else: else:
self.logger("ERROR", "brake", f"数据文件 {data_file} 最后的速度未降为零", "red", "SpeedNotZeroError") self.logger("ERROR", "brake", f"数据文件 {data_file} 最后的速度未降为零", "red")
av_estop = abs(df.iloc[row_start - 20:row_start, 0].abs().mean() * clibs.RADIAN) av_estop = abs(df.iloc[row_start - 20:row_start, 0].abs().mean() * clibs.RADIAN)
if abs(av_estop / av_max) < threshold: if abs(av_estop / av_max) < threshold:
@ -161,7 +150,6 @@ class BrakeDataProcess(QThread):
return row_start, row_end return row_start, row_end
@staticmethod @staticmethod
@clibs.handle_exception
def get_shtname(conditions, count): def get_shtname(conditions, count):
# 33%负载_33%速度_1 - reach/load/speed # 33%负载_33%速度_1 - reach/load/speed
load = conditions[1].removeprefix('load') load = conditions[1].removeprefix('load')
@ -170,7 +158,6 @@ class BrakeDataProcess(QThread):
return result_sheet_name return result_sheet_name
@clibs.handle_exception
def single_file_process(self, data_file, wb, count, av, rr): def single_file_process(self, data_file, wb, count, av, rr):
df = pandas.read_csv(data_file, sep='\t') df = pandas.read_csv(data_file, sep='\t')
conditions = data_file.split("/")[-2].split("_") # reach/load/speed conditions = data_file.split("/")[-2].split("_") # reach/load/speed
@ -180,20 +167,19 @@ class BrakeDataProcess(QThread):
row_start, row_end = self.get_row_range(data_file, df, conditions, av, rr) row_start, row_end = self.get_row_range(data_file, df, conditions, av, rr)
self.data2result(df, ws, row_start, row_end) self.data2result(df, ws, row_start, row_end)
@clibs.handle_exception
def data_process(self, result_file, rawdata_dirs, av, rr): def data_process(self, result_file, rawdata_dirs, av, rr):
filename = result_file.split("/")[-1] filename = result_file.split("/")[-1]
self.logger("INFO", "brake", f"正在打开文件 {filename},这可能需要一些时间......", "blue") self.logger("INFO", "brake", f"正在打开文件 {filename},这可能需要一些时间......", "blue")
try: try:
wb = openpyxl.load_workbook(result_file) wb = openpyxl.load_workbook(result_file)
except Exception as Err: except Exception as Err:
self.logger("ERROR", "brake", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!<br>{Err}", "red", "CannotOpenFile") self.logger("ERROR", "brake", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!<br>{Err}", "red")
prefix = filename.split('_')[0] prefix = filename.split('_')[0]
for rawdata_dir in rawdata_dirs: for rawdata_dir in rawdata_dirs:
if rawdata_dir.split("/")[-1].split('_')[0] == prefix: if rawdata_dir.split("/")[-1].split('_')[0] == prefix:
self.now_doing_msg(rawdata_dir, 'start') self.now_doing_msg(rawdata_dir, 'start')
_, data_files = clibs.traversal_files(rawdata_dir, self.output) _, data_files = clibs.traversal_files(rawdata_dir)
for idx in range(3): for idx in range(3):
self.single_file_process(data_files[idx], wb, idx+1, av, rr) self.single_file_process(data_files[idx], wb, idx+1, av, rr)
# threads = [ # threads = [
@ -209,12 +195,11 @@ class BrakeDataProcess(QThread):
wb.save(result_file) wb.save(result_file)
wb.close() wb.close()
@clibs.handle_exception
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
clibs.running[self.idx] = 1 clibs.running[self.idx] = 1
rawdata_dirs, result_files = clibs.traversal_files(self.dir_path, self.output) rawdata_dirs, result_files = clibs.traversal_files(self.dir_path)
config_file, result_files = self.check_files(rawdata_dirs, result_files) config_file, result_files = self.check_files(rawdata_dirs, result_files)
av, rr = self.get_configs(config_file) av, rr = self.get_configs(config_file)

View File

@ -9,23 +9,15 @@ from codes.common import clibs
class CurrentDataProcess(QThread): class CurrentDataProcess(QThread):
output = Signal(str, str)
def __init__(self, dir_path, proc, /): def __init__(self, dir_path, proc, /):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.proc = proc self.proc = proc
self.idx = 1 self.idx = 1
self.logger = clibs.logger
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
@clibs.handle_exception
def initialization(self): def initialization(self):
_, data_files = clibs.traversal_files(self.dir_path, self.output) _, data_files = clibs.traversal_files(self.dir_path)
count, config_file = 0, None count, config_file = 0, None
for data_file in data_files: for data_file in data_files:
filename = data_file.split("/")[-1] filename = data_file.split("/")[-1]
@ -38,15 +30,14 @@ class CurrentDataProcess(QThread):
if not re.match("^j[1-7].*\\.data$", filename): if not re.match("^j[1-7].*\\.data$", filename):
msg = f"不合规 {data_file}<br>" msg = f"不合规 {data_file}<br>"
msg += "所有数据文件必须以 j[1-7]_ 开头,以 .data 结尾比如j1_abcdef.data请检查整改后重新运行" msg += "所有数据文件必须以 j[1-7]_ 开头,以 .data 结尾比如j1_abcdef.data请检查整改后重新运行"
self.logger("ERROR", "current", msg, "red", "FilenameIllegal") self.logger("ERROR", "current", msg, "red")
if count != 2: if count != 2:
msg = "需要有一个机型配置文件\"*.cfg\",以及一个数据处理文件\"T_电机电流.xlsx\"表格,请检查整改后重新运行" msg = "需要有一个机型配置文件\"*.cfg\",以及一个数据处理文件\"T_电机电流.xlsx\"表格,请检查整改后重新运行"
self.logger("ERROR", "current", msg, "red", "FilenameIllegal") self.logger("ERROR", "current", msg, "red")
return data_files, config_file return data_files, config_file
@clibs.handle_exception
def current_max(self, data_files, rts): def current_max(self, data_files, rts):
self.logger("INFO", "current", f"正在处理最大转矩值逻辑......") self.logger("INFO", "current", f"正在处理最大转矩值逻辑......")
current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []} current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []}
@ -88,7 +79,6 @@ class CurrentDataProcess(QThread):
self.logger("INFO", "current", f"最大转矩数据处理完毕......") self.logger("INFO", "current", f"最大转矩数据处理完毕......")
return current return current
@clibs.handle_exception
def current_avg(self, data_files, rts): def current_avg(self, data_files, rts):
self.logger("INFO", "current", f"正在处理平均转矩值逻辑......") self.logger("INFO", "current", f"正在处理平均转矩值逻辑......")
current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []} current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []}
@ -131,7 +121,6 @@ class CurrentDataProcess(QThread):
self.logger("INFO", "current", f"平均转矩数据处理完毕......") self.logger("INFO", "current", f"平均转矩数据处理完毕......")
return current return current
@clibs.handle_exception
def current_cycle(self, data_files, rrs, rts, params): def current_cycle(self, data_files, rrs, rts, params):
result, hold, single, scenario, dur_time = None, [], [], [], 0 result, hold, single, scenario, dur_time = None, [], [], [], 0
for data_file in data_files: for data_file in data_files:
@ -150,8 +139,8 @@ class CurrentDataProcess(QThread):
self.logger("INFO", "current", f"正在打开文件 {filename},这可能需要一些时间......", "blue") self.logger("INFO", "current", f"正在打开文件 {filename},这可能需要一些时间......", "blue")
try: try:
wb = openpyxl.load_workbook(result) wb = openpyxl.load_workbook(result)
except Exception as Err: except Exception as err:
self.logger("ERROR", "current", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!<br>{Err}", "red", "CannotOpenFile") self.logger("ERROR", "current", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!<br>{err}", "red")
ws = wb["统计"] ws = wb["统计"]
for idx in range(len(params)-1): for idx in range(len(params)-1):
@ -175,7 +164,6 @@ class CurrentDataProcess(QThread):
wb.save(result) wb.save(result)
wb.close() wb.close()
@clibs.handle_exception
def find_point(self, data_file, df, flag, row_s, row_e, threshold, step, end_point, skip_scale, axis, seq): def find_point(self, data_file, df, flag, row_s, row_e, threshold, step, end_point, skip_scale, axis, seq):
if flag == "lt": if flag == "lt":
while row_e > end_point: while row_e > end_point:
@ -192,7 +180,7 @@ class CurrentDataProcess(QThread):
self.logger("WARNING", "current", f"【lt】{axis} 轴第 {seq} 次查找数据可能有异常row_s = {row_s}, row_e = {row_e}", "purple") self.logger("WARNING", "current", f"【lt】{axis} 轴第 {seq} 次查找数据可能有异常row_s = {row_s}, row_e = {row_e}", "purple")
return row_s, row_e return row_s, row_e
else: else:
self.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red", "AnchorNotFound") self.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red")
elif flag == "gt": elif flag == "gt":
while row_e > end_point: while row_e > end_point:
speed_avg = df.iloc[row_s:row_e].abs().mean() speed_avg = df.iloc[row_s:row_e].abs().mean()
@ -208,9 +196,8 @@ class CurrentDataProcess(QThread):
self.logger("WARNING", "current", f"【gt】{axis} 轴第 {seq} 次查找数据可能有异常row_s = {row_s}, row_e = {row_e}", "purple") self.logger("WARNING", "current", f"【gt】{axis} 轴第 {seq} 次查找数据可能有异常row_s = {row_s}, row_e = {row_e}", "purple")
return row_s, row_e return row_s, row_e
else: else:
self.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red", "AnchorNotFound") self.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red")
@clibs.handle_exception
def get_row_number(self, threshold, flag, df, row_s, row_e, axis): def get_row_number(self, threshold, flag, df, row_s, row_e, axis):
count_1, count_2 = 0, 0 count_1, count_2 = 0, 0
if flag == "start" or flag == "end": if flag == "start" or flag == "end":
@ -236,7 +223,6 @@ class CurrentDataProcess(QThread):
self.logger("DEBUG", "current", f"{axis} 轴获取{places[flag]}数据 {row_e} 可能有异常,需关注!", "purple") self.logger("DEBUG", "current", f"{axis} 轴获取{places[flag]}数据 {row_e} 可能有异常,需关注!", "purple")
return row_e return row_e
@clibs.handle_exception
def p_single(self, wb, single, rrs): def p_single(self, wb, single, rrs):
# 1. 先找到第一个速度为零的点,数据从后往前找,一开始就是零的情况不予考虑 # 1. 先找到第一个速度为零的点,数据从后往前找,一开始就是零的情况不予考虑
# 2. 记录第一个点的位置,继续向前查找第二个速度为零的点,同理,一开始为零的点不予考虑 # 2. 记录第一个点的位置,继续向前查找第二个速度为零的点,同理,一开始为零的点不予考虑
@ -316,7 +302,7 @@ class CurrentDataProcess(QThread):
self.logger("DEBUG", "current", f"{axis} 轴数据非零段点数:{row_middle-row_start+1}") self.logger("DEBUG", "current", f"{axis} 轴数据非零段点数:{row_middle-row_start+1}")
self.logger("DEBUG", "current", f"{axis} 轴数据为零段点数:{row_end-row_middle+1}") self.logger("DEBUG", "current", f"{axis} 轴数据为零段点数:{row_end-row_middle+1}")
if abs(row_end+row_start-2*row_middle) > 1000: if abs(row_end+row_start-2*row_middle) > 1000:
self.logger("DEBUG", "current", f"{axis} 轴数据占空比异常", "purple") self.logger("WARNING", "current", f"{axis} 轴数据占空比异常,处理数据可能有误,需检查", "purple")
data, first_c, second_c, third_c, fourth_c = [], clibs.c_joint_vel-1, clibs.c_servo_trq-1, clibs.c_sensor_trq-1, clibs.c_estimate_trans_trq-1 data, first_c, second_c, third_c, fourth_c = [], clibs.c_joint_vel-1, clibs.c_servo_trq-1, clibs.c_sensor_trq-1, clibs.c_estimate_trans_trq-1
for row in range(row_start, row_end+1): for row in range(row_start, row_end+1):
@ -340,7 +326,6 @@ class CurrentDataProcess(QThread):
cell.value = None cell.value = None
i += 1 i += 1
@clibs.handle_exception
def p_scenario(self, wb, scenario, rrs, dur_time): def p_scenario(self, wb, scenario, rrs, dur_time):
self.logger("INFO", "current", f"本次处理的是电机电流场景数据,场景运动周期为 {dur_time}s", "blue") self.logger("INFO", "current", f"本次处理的是电机电流场景数据,场景运动周期为 {dur_time}s", "blue")
for data_file in scenario: for data_file in scenario:
@ -359,7 +344,7 @@ class CurrentDataProcess(QThread):
row_start = 3000 row_start = 3000
row_end = row_start + int(dur_time/cycle) row_end = row_start + int(dur_time/cycle)
if row_end > df.index[-1]: if row_end > df.index[-1]:
self.logger("ERROR", "current", f"位置超限:{data_file} 共有 {df.index[-1]} 条数据,无法取到第 {row_end} 条数据,需要确认场景周期时间...", "blue", "DataOverLimit") self.logger("ERROR", "current", f"位置超限:{data_file} 共有 {df.index[-1]} 条数据,无法取到第 {row_end} 条数据,需要确认场景周期时间...", "red")
data, first_c, second_c, third_c, fourth_c = [], clibs.c_joint_vel-1, clibs.c_servo_trq-1, clibs.c_sensor_trq-1, clibs.c_estimate_trans_trq-1 data, first_c, second_c, third_c, fourth_c = [], clibs.c_joint_vel-1, clibs.c_servo_trq-1, clibs.c_sensor_trq-1, clibs.c_estimate_trans_trq-1
for row in range(row_start, row_end+1): for row in range(row_start, row_end+1):
@ -383,7 +368,6 @@ class CurrentDataProcess(QThread):
ws.cell((i//4)+2, 1).value = None ws.cell((i//4)+2, 1).value = None
i += 1 i += 1
@clibs.handle_exception
def get_configs(self, config_file): def get_configs(self, config_file):
try: try:
if re.match("^[NXEC]B.*", config_file.split("/")[-1]): if re.match("^[NXEC]B.*", config_file.split("/")[-1]):
@ -412,10 +396,9 @@ class CurrentDataProcess(QThread):
self.logger("INFO", "current", f"get_configs: 额定转矩 {m_rts}") self.logger("INFO", "current", f"get_configs: 额定转矩 {m_rts}")
self.logger("INFO", "current", f"get_configs: 最大角速度 {m_avs}") self.logger("INFO", "current", f"get_configs: 最大角速度 {m_avs}")
return sc, r_rrs, m_avs, m_stall_ts, m_rts, m_max_ts, m_r_rpms, m_max_rpms, r_max_sst, r_max_t, r_avg_t, robot_type return sc, r_rrs, m_avs, m_stall_ts, m_rts, m_max_ts, m_r_rpms, m_max_rpms, r_max_sst, r_max_t, r_avg_t, robot_type
except Exception as Err: except Exception as err:
self.logger("ERROR", "current", f"get_config: 无法打开 {config_file},或获取配置文件参数错误 {Err}", "red", "OpenFileError") self.logger("ERROR", "current", f"get_config: 无法打开 {config_file},或获取配置文件参数错误 {err}", "red")
@clibs.handle_exception
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
clibs.running[self.idx] = 1 clibs.running[self.idx] = 1
@ -432,5 +415,5 @@ class CurrentDataProcess(QThread):
self.logger("INFO", "current", "-"*60 + "<br>全部处理完毕<br>", "purple") self.logger("INFO", "current", "-"*60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s\n" msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "current", msg) self.logger("INFO", "current", msg)

View File

@ -7,20 +7,14 @@ from codes.common import clibs
class IsoDataProcess(QThread): class IsoDataProcess(QThread):
output = Signal(str, str)
def __init__(self, dir_path, /): def __init__(self, dir_path, /):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.idx = 2 self.idx = 2
self.logger = clibs.logger
def logger(self, level, module, content, color="black", error="", flag="both"): @staticmethod
flag = "cursor" if level.upper() == "DEBUG" else "both" def p_iso(file, p_files, ws, tmpfile):
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
def p_iso(self, file, p_files, ws, tmpfile):
p_files.append(file) p_files.append(file)
pdf = pdfplumber.open(file) pdf = pdfplumber.open(file)
@ -79,7 +73,8 @@ class IsoDataProcess(QThread):
pass pass
pdf.close() pdf.close()
def p_iso_100(self, file, p_files, ws, tmpfile): @staticmethod
def p_iso_100(file, p_files, ws, tmpfile):
p_files.append(file) p_files.append(file)
pdf = pdfplumber.open(file) pdf = pdfplumber.open(file)
@ -112,7 +107,8 @@ class IsoDataProcess(QThread):
pass pass
pdf.close() pdf.close()
def p_iso_1000(self, file, p_files, ws, tmpfile): @staticmethod
def p_iso_1000(file, p_files, ws, tmpfile):
p_files.append(file) p_files.append(file)
pdf = pdfplumber.open(file) pdf = pdfplumber.open(file)
@ -146,9 +142,9 @@ class IsoDataProcess(QThread):
pdf.close() pdf.close()
def initialization(self): def initialization(self):
dirs, files = clibs.traversal_files(self.dir_path, self.output) dirs, files = clibs.traversal_files(self.dir_path)
if len(dirs) != 0: if len(dirs) != 0:
self.logger("ERROR", "iso", f"init: 工作目录下不可以有文件夹!", "red", "InitFileError") self.logger("ERROR", "iso", f"init: 工作目录下不可以有文件夹!", "red")
for file in files: for file in files:
file = file.lower() file = file.lower()
@ -161,7 +157,7 @@ class IsoDataProcess(QThread):
elif file.endswith("iso.pdf"): elif file.endswith("iso.pdf"):
pass pass
else: else:
self.logger("ERROR", "iso", f"init: 工作目录下只允许有如下四个文件不区分大小写pdf文件最少有一个<br>1. iso-results.xlsx<br>2. ISO.pdf<br>3. ISO-V100.pdf<br>4. ISO-V1000.pdf", "red", "InitFileError") self.logger("ERROR", "iso", f"init: 工作目录下只允许有如下四个文件不区分大小写pdf文件最少有一个<br>1. iso-results.xlsx<br>2. ISO.pdf<br>3. ISO-V100.pdf<br>4. ISO-V1000.pdf", "red")
return files return files
@ -178,8 +174,8 @@ class IsoDataProcess(QThread):
ws = wb.active ws = wb.active
for i in range(3, 50): for i in range(3, 50):
ws.cell(row=i, column=7).value = None ws.cell(row=i, column=7).value = None
except Exception as Err: except Exception as err:
self.logger("ERROR", "iso", f"main: 无法打开文件 {filename}<br>{Err}", "red", "FileOpenError") self.logger("ERROR", "iso", f"main: 无法打开文件 {filename}<br>{err}", "red")
p_files = [] p_files = []
for file in files: for file in files:
@ -204,11 +200,11 @@ class IsoDataProcess(QThread):
wb.close() wb.close()
if len(p_files) == 0: if len(p_files) == 0:
self.logger("ERROR", "iso", f"目录 {self.dir_path} 下没有需要处理的文件,需要确认......", "red", "FileNotFound") self.logger("ERROR", "iso", f"目录 {self.dir_path} 下没有需要处理的文件,需要确认......", "red")
else: else:
os.remove(tmpfile) os.remove(tmpfile)
self.logger("INFO", "current-processing", "-" * 60 + "<br>全部处理完毕<br>", "purple") self.logger("INFO", "current-processing", "-" * 60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s\n" msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "current-processing", msg) self.logger("INFO", "current-processing", msg)

View File

@ -8,18 +8,11 @@ from codes.common import clibs
class WaveloggerDataProcess(QThread): class WaveloggerDataProcess(QThread):
output = Signal(str, str)
def __init__(self, dir_path, /): def __init__(self, dir_path, /):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.idx = 3 self.idx = 3
self.logger = clibs.logger
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
def find_point(self, bof, step, margin, threshold, pos, data_file, flag, df, row): def find_point(self, bof, step, margin, threshold, pos, data_file, flag, df, row):
# bof: backward or forward # bof: backward or forward
@ -38,7 +31,7 @@ class WaveloggerDataProcess(QThread):
break break
else: else:
if bof == "backward": if bof == "backward":
self.logger("ERROR", "wavelogger", f"find_point-gt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red", "DataError") self.logger("ERROR", "wavelogger", f"find_point-gt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red")
elif bof == "forward": elif bof == "forward":
row_target = row + margin # to end while loop in function `single_file_proc` row_target = row + margin # to end while loop in function `single_file_proc`
elif flag == "lt": elif flag == "lt":
@ -52,7 +45,7 @@ class WaveloggerDataProcess(QThread):
break break
else: else:
if bof == "backward": if bof == "backward":
self.logger("ERROR", "wavelogger", f"find_point-lt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red", "DataError") self.logger("ERROR", "wavelogger", f"find_point-lt: [{pos}] 在 {data_file} 中,无法正确识别数据,需要确认...", "red")
elif bof == "forward": elif bof == "forward":
row_target = row + margin # to end while loop in function `single_file_proc` row_target = row + margin # to end while loop in function `single_file_proc`
return row_target return row_target
@ -85,11 +78,11 @@ class WaveloggerDataProcess(QThread):
return row_end-row_middle, row_middle-row_start, row_end-row_start, df return row_end-row_middle, row_middle-row_start, row_end-row_start, df
def initialization(self): def initialization(self):
_, data_files = clibs.traversal_files(self.dir_path, self.output) _, data_files = clibs.traversal_files(self.dir_path)
for data_file in data_files: for data_file in data_files:
if not data_file.lower().endswith(".csv"): if not data_file.lower().endswith(".csv"):
self.logger("ERROR", "wavelogger", f"init: {data_file} 文件后缀错误,只允许 .csv 文件,需要确认!", "red", "FileTypeError") self.logger("ERROR", "wavelogger", f"init: {data_file} 文件后缀错误,只允许 .csv 文件,需要确认!", "red")
return data_files return data_files
@ -115,7 +108,7 @@ class WaveloggerDataProcess(QThread):
value = df.iloc[start:end, 2].astype(float).mean() + 3 * df.iloc[start:end, 2].astype(float).std() value = df.iloc[start:end, 2].astype(float).mean() + 3 * df.iloc[start:end, 2].astype(float).std()
if value > 1: if value > 1:
msg = f"\n" msg = f"\n"
self.logger("WARNING", "wavelogger", f"{data_file} 文件第 {count} 轮 第 {count_i} 个数据可能有问题,需人工手动确认,确认有问题可删除,无问题则保留", "purple") self.logger("WARNING", "wavelogger", f"{data_file} 文件第 {count} 轮 第 {count_i} 个数据可能有问题,需人工手动确认,确认有问题可删除,无问题则保留")
data[count].append(value) data[count].append(value)
count_i += 1 count_i += 1
@ -157,5 +150,5 @@ class WaveloggerDataProcess(QThread):
self.logger("INFO", "wavelogger", "-" * 60 + "<br>全部处理完毕<br>", "purple") self.logger("INFO", "wavelogger", "-" * 60 + "<br>全部处理完毕<br>", "purple")
time_total = time.time() - time_start time_total = time.time() - time_start
msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s\n" msg = f"数据处理时间:{time_total // 3600:02.0f} h {time_total % 3600 // 60:02.0f} m {time_total % 60:02.0f} s"
self.logger("INFO", "wavelogger", msg) self.logger("INFO", "wavelogger", msg)

View File

@ -1,3 +1,4 @@
import threading
import time import time
import os import os
import paramiko import paramiko
@ -9,27 +10,19 @@ from codes.common import clibs
class DoBrakeTest(QThread): class DoBrakeTest(QThread):
output = Signal(str, str)
def __init__(self, dir_path, tool, /): def __init__(self, dir_path, tool, /):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.tool = tool self.tool = tool
self.idx = 4 self.idx = 4
self.logger = clibs.logger
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
def initialization(self, data_dirs, data_files): def initialization(self, data_dirs, data_files):
@clibs.handle_exception
def check_files(): def check_files():
msg = "初始路径下不允许有文件夹,只能存在如下五个文件,且文件为关闭状态,确认后重新运行!<br>" msg = "初始路径下不允许有文件夹,只能存在如下五个文件,且文件为关闭状态,确认后重新运行!<br>"
msg += "1. configs.xlsx<br>2. reach33/reach66/reach100_xxxx.xlsx<br>3. xxxx.zip" msg += "1. configs.xlsx<br>2. reach33/reach66/reach100_xxxx.xlsx<br>3. xxxx.zip"
if len(data_dirs) != 0 or len(data_files) != 5: if len(data_dirs) != 0 or len(data_files) != 5:
self.logger("ERROR", "do_brake", msg, "red", "InitFileError") self.logger("ERROR", "do_brake", msg, "red")
config_file, reach33_file, reach66_file, reach100_file, prj_file, result_dirs = None, None, None, None, None, [] config_file, reach33_file, reach66_file, reach100_file, prj_file, result_dirs = None, None, None, None, None, []
for data_file in data_files: for data_file in data_files:
@ -45,7 +38,7 @@ class DoBrakeTest(QThread):
elif filename.endswith(".zip"): elif filename.endswith(".zip"):
prj_file = data_file prj_file = data_file
else: else:
self.logger("ERROR", "do_brake", msg, "red", "InitFileError") self.logger("ERROR", "do_brake", msg, "red")
if config_file and reach33_file and reach66_file and reach100_file and prj_file: if config_file and reach33_file and reach66_file and reach100_file and prj_file:
os.mkdir(f"{self.dir_path}/j1") os.mkdir(f"{self.dir_path}/j1")
@ -64,9 +57,8 @@ class DoBrakeTest(QThread):
return config_file, prj_file, result_dirs return config_file, prj_file, result_dirs
else: else:
self.logger("ERROR", "do_brake", msg, "red", "InitFileError") self.logger("ERROR", "do_brake", msg, "red")
@clibs.handle_exception
def get_configs(): def get_configs():
robot_type = None robot_type = None
msg_id = clibs.c_hr.execution("controller.get_params") msg_id = clibs.c_hr.execution("controller.get_params")
@ -82,7 +74,7 @@ class DoBrakeTest(QThread):
with open(local_file, mode="r", encoding="utf-8") as f_config: with open(local_file, mode="r", encoding="utf-8") as f_config:
configs = json.load(f_config) configs = json.load(f_config)
except Exception as Err: except Exception as Err:
self.logger("ERROR", "do_brake", f"无法打开 {local_file}<br>{Err}", "red", "OpenFileError") self.logger("ERROR", "do_brake", f"无法打开 {local_file}<br>{Err}", "red")
# 最大角速度,额定电流,减速比,额定转速 # 最大角速度,额定电流,减速比,额定转速
version = configs["VERSION"] version = configs["VERSION"]
@ -97,7 +89,6 @@ class DoBrakeTest(QThread):
self.logger("INFO", "do_brake", "数据目录合规性检查结束,未发现问题......", "green") self.logger("INFO", "do_brake", "数据目录合规性检查结束,未发现问题......", "green")
return _config_file, _prj_file, _result_dirs, _avs return _config_file, _prj_file, _result_dirs, _avs
@clibs.handle_exception
def gen_result_file(self, axis, end_time, reach, load, speed, speed_max, rounds): def gen_result_file(self, axis, end_time, reach, load, speed, speed_max, rounds):
d_vel, d_trq, d_stop, threshold = [], [], [], 0.95 d_vel, d_trq, d_stop, threshold = [], [], [], 0.95
s_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time-clibs.INTERVAL*12)) s_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time-clibs.INTERVAL*12))
@ -143,7 +134,6 @@ class DoBrakeTest(QThread):
df.to_csv(filename, sep="\t", index=False) df.to_csv(filename, sep="\t", index=False)
@staticmethod @staticmethod
@clibs.handle_exception
def change_curve_state(stat): def change_curve_state(stat):
if not stat: if not stat:
display_pdo_params = [] display_pdo_params = []
@ -153,7 +143,6 @@ class DoBrakeTest(QThread):
clibs.c_hr.execution("diagnosis.open", open=stat, display_open=stat) clibs.c_hr.execution("diagnosis.open", open=stat, display_open=stat)
clibs.c_hr.execution("diagnosis.set_params", display_pdo_params=display_pdo_params) clibs.c_hr.execution("diagnosis.set_params", display_pdo_params=display_pdo_params)
@clibs.handle_exception
def run_rl(self, config_file, prj_file, result_dirs, avs): def run_rl(self, config_file, prj_file, result_dirs, avs):
count, total, speed_target = 0, 63, 0 count, total, speed_target = 0, 63, 0
prj_name = ".".join(prj_file.split("/")[-1].split(".")[:-1]) prj_name = ".".join(prj_file.split("/")[-1].split(".")[:-1])
@ -172,7 +161,7 @@ class DoBrakeTest(QThread):
elif pon == "negative": elif pon == "negative":
clibs.c_md.write_pon(0) clibs.c_md.write_pon(0)
else: else:
self.logger("ERROR", "do_brake", "configs.xlsx 中 Target 页面 B5 单元格填写不正确,检查后重新运行...", "red", "DirectionError") self.logger("ERROR", "do_brake", "configs.xlsx 中 Target 页面 B5 单元格填写不正确,检查后重新运行...", "red")
self.change_curve_state(True) self.change_curve_state(True)
for condition in result_dirs: for condition in result_dirs:
@ -194,7 +183,7 @@ class DoBrakeTest(QThread):
continue continue
clibs.c_md.write_axis(axis) clibs.c_md.write_axis(axis)
self.logger("INFO", "brake", "-" * 90, "purple", flag="signal") self.logger("INFO", "brake", "-" * 90, "purple")
speed_max = 0 speed_max = 0
for rounds in range(1, 4): for rounds in range(1, 4):
count += 1 count += 1
@ -207,7 +196,7 @@ class DoBrakeTest(QThread):
# 1. 触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电 # 1. 触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电
clibs.c_md.r_soft_estop(0) clibs.c_md.r_soft_estop(0)
clibs.c_md.r_soft_estop(1) clibs.c_md.r_soft_estop(1)
clibs.c_ec.setdo_value(io_name, "true") clibs.c_ec.sr_string(f"setdo:{io_name},true")
clibs.c_md.r_reset_estop() clibs.c_md.r_reset_estop()
clibs.c_md.r_clear_alarm() clibs.c_md.r_clear_alarm()
clibs.c_md.write_act(0) clibs.c_md.write_act(0)
@ -251,7 +240,7 @@ class DoBrakeTest(QThread):
else: else:
time.sleep(1) time.sleep(1)
if (time.time() - t_start) > 15: if (time.time() - t_start) > 15:
self.logger("ERROR", "do_brake", "15s 内未收到机器人的运行信号,需要确认 RL 程序编写正确并正常执行...", "red", "ReadySignalTimeoutError") self.logger("ERROR", "do_brake", "15s 内未收到机器人的运行信号,需要确认 RL 程序编写正确并正常执行...", "red")
# 4. 找出最大速度传递给RL程序最后清除相关记录 # 4. 找出最大速度传递给RL程序最后清除相关记录
time.sleep(5) # 消除前 5s 的不稳定数据 time.sleep(5) # 消除前 5s 的不稳定数据
start_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) start_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
@ -261,7 +250,6 @@ class DoBrakeTest(QThread):
# 找出最大速度 # 找出最大速度
@clibs.db_lock @clibs.db_lock
@clibs.handle_exception
def get_speed_max(): def get_speed_max():
_speed_max = 0 _speed_max = 0
clibs.cursor.execute(f"SELECT content FROM logs WHERE timestamp BETWEEN '{start_time}' AND '{end_time}' AND content LIKE '%diagnosis.result%' ORDER BY id ASC") clibs.cursor.execute(f"SELECT content FROM logs WHERE timestamp BETWEEN '{start_time}' AND '{end_time}' AND content LIKE '%diagnosis.result%' ORDER BY id ASC")
@ -292,7 +280,7 @@ class DoBrakeTest(QThread):
break break
while 1: while 1:
clibs.c_ec.setdo_value(io_name, "true") clibs.c_ec.sr_string(f"setdo:{io_name},true")
clibs.c_md.r_reset_estop() clibs.c_md.r_reset_estop()
clibs.c_md.r_clear_alarm() clibs.c_md.r_clear_alarm()
clibs.c_md.write_act(0) clibs.c_md.write_act(0)
@ -310,7 +298,7 @@ class DoBrakeTest(QThread):
else: else:
time.sleep(2) time.sleep(2)
if time.time() - t_start > 60: if time.time() - t_start > 60:
self.logger("ERROR", "do_brake", "60s 内程序未能正常执行,需检查...", "red", "RlProgramStartTimeout") self.logger("ERROR", "do_brake", "60s 内程序未能正常执行,需检查...", "red")
for i in range(16): for i in range(16):
if clibs.c_md.read_ready_to_go() == 1: if clibs.c_md.read_ready_to_go() == 1:
@ -319,15 +307,14 @@ class DoBrakeTest(QThread):
else: else:
time.sleep(1) time.sleep(1)
else: else:
self.logger("ERROR", "do_brake", "16s 内未收到机器人的运行信号,需要确认 RL 程序配置正确并正常执行...", "red", "ReadySignalTimeoutError") self.logger("ERROR", "do_brake", "16s 内未收到机器人的运行信号,需要确认 RL 程序配置正确并正常执行...", "red")
@clibs.handle_exception
def exec_brake(): def exec_brake():
flag, start, data, record = True, time.time(), None, None flag, start, data, record = True, time.time(), None, None
while flag: while flag:
time.sleep(0.05) time.sleep(0.05)
if time.time() - start > 20: if time.time() - start > 20:
self.logger("ERROR", "do_brake", "20s 内未触发急停,需排查......", "red", "BrakeTimeoutError") self.logger("ERROR", "do_brake", "20s 内未触发急停,需排查......", "red")
try: try:
clibs.lock.acquire(True) clibs.lock.acquire(True)
@ -344,7 +331,7 @@ class DoBrakeTest(QThread):
speed_moment = clibs.RADIAN * sum(item["value"]) / len(item["value"]) speed_moment = clibs.RADIAN * sum(item["value"]) / len(item["value"])
if abs(speed_moment) > speed_max - 2: if abs(speed_moment) > speed_max - 2:
if (pon == "positive" and speed_moment > 0) or (pon == "negative" and speed_moment < 0): if (pon == "positive" and speed_moment > 0) or (pon == "negative" and speed_moment < 0):
clibs.c_ec.setdo_value(io_name, "false") clibs.c_ec.sr_string(f"setdo:{io_name},false")
time.sleep(clibs.INTERVAL*2) # wait speed goes down to 0 time.sleep(clibs.INTERVAL*2) # wait speed goes down to 0
flag = False flag = False
break break
@ -364,14 +351,16 @@ class DoBrakeTest(QThread):
msg = f"<br>{self.tool.removeprefix('tool')}%负载的制动性能测试执行完毕,如需采集其他负载,须切换负载类型,并更换其他负载,重新执行" msg = f"<br>{self.tool.removeprefix('tool')}%负载的制动性能测试执行完毕,如需采集其他负载,须切换负载类型,并更换其他负载,重新执行"
self.logger("INFO", "do_brake", msg, "green") self.logger("INFO", "do_brake", msg, "green")
@clibs.handle_exception
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
clibs.running[self.idx] = 1 clibs.running[self.idx] = 1
if clibs.status["hmi"] != 1 or clibs.status["md"] != 1 or clibs.status["ec"] != 1: if clibs.status["hmi"] != 1 or clibs.status["md"] != 1 or clibs.status["ec"] != 1:
self.logger("ERROR", "do_brake", "processing: 需要在网络设置中连接HMIModbus通信以及外部通信", "red", "NetworkError") self.logger("ERROR", "do_brake", "processing: 需要在网络设置中连接HMIModbus通信以及外部通信", "red")
t = threading.Thread(target=clibs.running_detection, args=(self.idx, ))
t.daemon = True
t.start()
data_dirs, data_files = clibs.traversal_files(self.dir_path, self.output) data_dirs, data_files = clibs.traversal_files(self.dir_path)
config_file, prj_file, result_dirs, avs = self.initialization(data_dirs, data_files) config_file, prj_file, result_dirs, avs = self.initialization(data_dirs, data_files)
clibs.c_pd.push_prj_to_server(prj_file) clibs.c_pd.push_prj_to_server(prj_file)
self.run_rl(config_file, prj_file, result_dirs, avs) self.run_rl(config_file, prj_file, result_dirs, avs)

View File

@ -8,27 +8,19 @@ from codes.common import clibs
class DoCurrentTest(QThread): class DoCurrentTest(QThread):
output = Signal(str, str)
def __init__(self, dir_path, tool, /): def __init__(self, dir_path, tool, /):
super().__init__() super().__init__()
self.dir_path = dir_path self.dir_path = dir_path
self.tool = tool self.tool = tool
self.idx = 5 self.idx = 5
self.logger = clibs.logger
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
def initialization(self, data_dirs, data_files): def initialization(self, data_dirs, data_files):
@clibs.handle_exception
def check_files(): def check_files():
msg = "初始路径下不允许有文件夹,初始路径下只能存在如下两个文件,且文件为关闭状态,确认后重新运行!<br>" msg = "初始路径下不允许有文件夹,初始路径下只能存在如下两个文件,且文件为关闭状态,确认后重新运行!<br>"
msg += "1. T_电机电流.xlsx<br>2. xxxx.zip" msg += "1. T_电机电流.xlsx<br>2. xxxx.zip"
if len(data_dirs) != 0 or len(data_files) != 2: if len(data_dirs) != 0 or len(data_files) != 2:
self.logger("ERROR", "do_current", msg, "red", "InitFileError") self.logger("ERROR", "do_current", msg, "red")
prj_file, count = None, 0 prj_file, count = None, 0
for data_file in data_files: for data_file in data_files:
@ -39,10 +31,10 @@ class DoCurrentTest(QThread):
count += 1 count += 1
prj_file = data_file prj_file = data_file
else: else:
self.logger("ERROR", "do_current", msg, "red", "InitFileError") self.logger("ERROR", "do_current", msg, "red")
if count != 2: if count != 2:
self.logger("ERROR", "do_current", msg, "red", "InitFileError") self.logger("ERROR", "do_current", msg, "red")
if self.tool == "tool100": if self.tool == "tool100":
os.mkdir(f"{self.dir_path}/single") os.mkdir(f"{self.dir_path}/single")
@ -52,11 +44,10 @@ class DoCurrentTest(QThread):
elif self.tool == "inertia": elif self.tool == "inertia":
os.mkdir(f"{self.dir_path}/inertia") os.mkdir(f"{self.dir_path}/inertia")
else: else:
self.logger("ERROR", "do_current", "负载选择错误,电机电流测试只能选择 tool100/inertia 规格!", "red", "LoadSelectError") self.logger("ERROR", "do_current", "负载选择错误,电机电流测试只能选择 tool100/inertia 规格!", "red")
return prj_file return prj_file
@clibs.handle_exception
def get_configs(): def get_configs():
robot_type = None robot_type = None
msg_id = clibs.c_hr.execution("controller.get_params") msg_id = clibs.c_hr.execution("controller.get_params")
@ -74,7 +65,6 @@ class DoCurrentTest(QThread):
self.logger("INFO", "do_current", "数据目录合规性检查结束,未发现问题......", "green") self.logger("INFO", "do_current", "数据目录合规性检查结束,未发现问题......", "green")
return _prj_file return _prj_file
@clibs.handle_exception
def single_axis_proc(self, records, number): def single_axis_proc(self, records, number):
text = "single" if number < 6 else "hold" text = "single" if number < 6 else "hold"
number = number if number < 6 else number - 6 number = number if number < 6 else number - 6
@ -100,7 +90,6 @@ class DoCurrentTest(QThread):
filename = f"{self.dir_path}/single/j{number + 1}_{text}_{time.time()}.data" filename = f"{self.dir_path}/single/j{number + 1}_{text}_{time.time()}.data"
df.to_csv(filename, sep="\t", index=False) df.to_csv(filename, sep="\t", index=False)
@clibs.handle_exception
def scenario_proc(self, records, number, scenario_time): def scenario_proc(self, records, number, scenario_time):
d_vel, d_trq, d_sensor, d_trans = [[], [], [], [], [], []], [[], [], [], [], [], []], [[], [], [], [], [], []], [[], [], [], [], [], []] d_vel, d_trq, d_sensor, d_trans = [[], [], [], [], [], []], [[], [], [], [], [], []], [[], [], [], [], [], []], [[], [], [], [], [], []]
for record in records: for record in records:
@ -126,9 +115,7 @@ class DoCurrentTest(QThread):
filename = f"{self.dir_path}/s_{number-11}/j{axis+1}_s_{number-11}_{scenario_time}_{time.time()}.data" filename = f"{self.dir_path}/s_{number-11}/j{axis+1}_s_{number-11}_{scenario_time}_{time.time()}.data"
df.to_csv(filename, sep="\t", index=False) df.to_csv(filename, sep="\t", index=False)
@clibs.handle_exception
def gen_result_file(self, number, start_time, end_time, scenario_time): def gen_result_file(self, number, start_time, end_time, scenario_time):
@clibs.handle_exception
def get_records(): def get_records():
s_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time)) s_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time))
e_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time+clibs.INTERVAL)) e_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time+clibs.INTERVAL))
@ -152,14 +139,12 @@ class DoCurrentTest(QThread):
t.start() t.start()
@staticmethod @staticmethod
@clibs.handle_exception
def change_curve_state(stat): def change_curve_state(stat):
curves = ["hw_joint_vel_feedback", "device_servo_trq_feedback", "hw_sensor_trq_feedback", "hw_estimate_trans_trq_res"] curves = ["hw_joint_vel_feedback", "device_servo_trq_feedback", "hw_sensor_trq_feedback", "hw_estimate_trans_trq_res"]
display_pdo_params = [] if not stat else [{"name": curve, "channel": chl} for curve in curves for chl in range(6)] display_pdo_params = [] if not stat else [{"name": curve, "channel": chl} for curve in curves for chl in range(6)]
clibs.c_hr.execution("diagnosis.open", open=stat, display_open=stat) clibs.c_hr.execution("diagnosis.open", open=stat, display_open=stat)
clibs.c_hr.execution("diagnosis.set_params", display_pdo_params=display_pdo_params) clibs.c_hr.execution("diagnosis.set_params", display_pdo_params=display_pdo_params)
@clibs.handle_exception
def run_rl(self, prj_file): def run_rl(self, prj_file):
prj_name = ".".join(prj_file.split("/")[-1].split(".")[:-1]) prj_name = ".".join(prj_file.split("/")[-1].split(".")[:-1])
c_regular = [ c_regular = [
@ -235,7 +220,7 @@ class DoCurrentTest(QThread):
else: else:
time.sleep(1) time.sleep(1)
if (time.time() - t_start) > 15: if (time.time() - t_start) > 15:
self.logger("ERROR", "do_current", "15s 内未收到机器人的运行信号需要确认RL程序和工具通信是否正常执行...", "red", "ReadySignalTimeoutError") self.logger("ERROR", "do_current", "15s 内未收到机器人的运行信号需要确认RL程序和工具通信是否正常执行...", "red")
# 4. 执行采集 # 4. 执行采集
time.sleep(10) # 消除前 10s 的不稳定数据 time.sleep(10) # 消除前 10s 的不稳定数据
@ -256,7 +241,7 @@ class DoCurrentTest(QThread):
else: else:
time.sleep(1) time.sleep(1)
if (time.time()-t_start) > 180: if (time.time()-t_start) > 180:
self.logger("ERROR", "do_current", f"180s 内未收到场景{number - 11}的周期时间需要确认RL程序和工具通信交互是否正常执行...", "red", "GetScenarioTimeError") self.logger("ERROR", "do_current", f"180s 内未收到场景{number - 11}的周期时间需要确认RL程序和工具通信交互是否正常执行...", "red")
time.sleep(20) time.sleep(20)
# 5.停止程序运行,保留数据并处理输出 # 5.停止程序运行,保留数据并处理输出
@ -271,14 +256,13 @@ class DoCurrentTest(QThread):
elif self.tool == "inertia": elif self.tool == "inertia":
self.logger("INFO", "do_current", "惯量负载电机电流采集完毕,如需采集单轴/场景/保持电机电流,须切换负载类型,并更换偏置负载,重新执行", "green") self.logger("INFO", "do_current", "惯量负载电机电流采集完毕,如需采集单轴/场景/保持电机电流,须切换负载类型,并更换偏置负载,重新执行", "green")
@clibs.handle_exception
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
clibs.running[self.idx] = 1 clibs.running[self.idx] = 1
if clibs.status["hmi"] != 1 or clibs.status["md"] != 1: if clibs.status["hmi"] != 1 or clibs.status["md"] != 1:
self.logger("ERROR", "do_current", "processing: 需要在网络设置中连接HMI以及Modbus通信", "red", "NetworkError") self.logger("ERROR", "do_current", "processing: 需要在网络设置中连接HMI以及Modbus通信", "red")
data_dirs, data_files = clibs.traversal_files(self.dir_path, self.output) data_dirs, data_files = clibs.traversal_files(self.dir_path)
prj_file = self.initialization(data_dirs, data_files) prj_file = self.initialization(data_dirs, data_files)
clibs.c_pd.push_prj_to_server(prj_file) clibs.c_pd.push_prj_to_server(prj_file)
self.run_rl(prj_file) self.run_rl(prj_file)

View File

@ -2,14 +2,14 @@ import os
import os.path import os.path
import threading import threading
import sqlite3 import sqlite3
import time
from PySide6.QtCore import Signal, QThread
def traversal_files(dir_path, signal): def traversal_files(dir_path):
# 功能:以列表的形式分别返回指定路径下的文件和文件夹,不包含子目录
# 参数:路径/信号/游标/功能编号
# 返回值:路径下的文件夹列表 路径下的文件列表
if not os.path.exists(dir_path): if not os.path.exists(dir_path):
logger("ERROR", "clibs", f"数据文件夹{dir_path}不存在,请确认后重试......", "red", signal=signal) logger("ERROR", "clibs", f"数据文件夹{dir_path}不存在,请确认后重试......", color="red")
else: else:
dirs, files = [], [] dirs, files = [], []
for item in os.scandir(dir_path): for item in os.scandir(dir_path):
@ -56,33 +56,42 @@ def db_lock(func):
return wrapper return wrapper
class LoggerHandler(QThread):
signal = Signal(str, str)
def __init__(self, /):
super().__init__()
@db_lock @db_lock
def logger(level, module, content, color="black", flag="both", signal=""): def logger(self, level, module, content, color="black", flag="both"):
global cursor global cursor
if "move.monitor" in content: if "move.monitor" in content:
return return
if level.upper() == "DEBUG":
flag = "cursor"
if flag == "signal": if flag == "signal":
signal.emit(content, color) self.signal.emit(content, color)
elif flag == "cursor": elif flag == "cursor":
cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level, module, content)) cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level, module, content))
elif flag == "both": elif flag == "both":
signal.emit(content, color) self.signal.emit(content, color)
cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level, module, content)) cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level, module, content))
if level.upper() == "ERROR":
def handle_exception(func): raise Exception()
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as err:
print(f"{func.__name__} err = {err}")
logger("DEBUG", "clibs", f"{func.__name__} err = {err}", flag="cursor")
return wrapper
PREFIX = "resources/assets" # for pyinstaller def running_detection(idx):
# PREFIX = "assets" # for local testing while True:
time.sleep(INTERVAL*2)
if not running[idx]:
raise Exception("")
# PREFIX = "resources/assets" # for pyinstaller
PREFIX = "assets" # for local testing
log_path = f"{PREFIX}/logs" log_path = f"{PREFIX}/logs"
lock = threading.Lock() lock = threading.Lock()
running = [0, 0, 0, 0, 0, 0, 0] # 制动数据/转矩数据/激光数据/精度数据/制动自动化/转矩自动化/耐久数据采集 running = [0, 0, 0, 0, 0, 0, 0] # 制动数据/转矩数据/激光数据/精度数据/制动自动化/转矩自动化/耐久数据采集
@ -91,7 +100,7 @@ levels = ["DEBUG", "INFO", "WARNING", "ERROR"]
ip_addr, ssh_port, socket_port, xService_port, external_port, modbus_port, upgrade_port = "", 22, 5050, 6666, 8080, 502, 4567 ip_addr, ssh_port, socket_port, xService_port, external_port, modbus_port, upgrade_port = "", 22, 5050, 6666, 8080, 502, 4567
username, password = "luoshi", "luoshi2019" username, password = "luoshi", "luoshi2019"
INTERVAL, RADIAN, MAX_FRAME_SIZE, MAX_LOG_NUMBER, CYCLE = 1, 57.3, 1024, 10, 300 INTERVAL, RADIAN, MAX_FRAME_SIZE, MAX_LOG_NUMBER, CYCLE = 1, 57.3, 1024, 10, 300
c_md, c_hr, c_ec, c_pd, conn, cursor, search_records = None, None, None, None, None, None, None c_md, c_hr, c_ec, c_pd, conn, cursor, search_records, logger, count = None, None, None, None, None, None, None, None, 0
status = {"mysql": 0, "hmi": 0, "md": 0, "ec": 0} status = {"mysql": 0, "hmi": 0, "md": 0, "ec": 0}
c_joint_vel, c_servo_trq, c_sensor_trq, c_estimate_trans_trq, c_safety_estop = 1, 2, 3, 4, 3 # 各个指标所在列 c_joint_vel, c_servo_trq, c_sensor_trq, c_estimate_trans_trq, c_safety_estop = 1, 2, 3, 4, 3 # 各个指标所在列

View File

@ -16,12 +16,12 @@ from codes.common import clibs
class ModbusRequest(QThread): class ModbusRequest(QThread):
output = Signal(str, str)
def __init__(self, ip, port, /): def __init__(self, ip, port, /):
super().__init__() super().__init__()
self.ip = ip self.ip = ip
self.port = port self.port = port
self.c = None
self.logger = clibs.logger
def net_conn(self): def net_conn(self):
self.logger("INFO", "openapi", f"Modbus 正在连接中,需要配置设备,这可能需要一点时间......", "blue") self.logger("INFO", "openapi", f"Modbus 正在连接中,需要配置设备,这可能需要一点时间......", "blue")
@ -30,21 +30,11 @@ class ModbusRequest(QThread):
if self.c.connect(): if self.c.connect():
self.logger("INFO", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) success!", "green") self.logger("INFO", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) success!", "green")
else: else:
self.logger("ERROR", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) failed!", "red", "MdConnFailed") self.logger("ERROR", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) failed!", "red")
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
def close(self): def close(self):
if self.c.connect():
try:
self.c.close() self.c.close()
self.logger("INFO", "openapi", f"modbus: 关闭 Modbus 连接成功", "green") self.logger("INFO", "openapi", f"modbus: 关闭 Modbus 连接成功", "green")
except Exception as err:
self.logger("ERROR", "openapi", f"modbus: 关闭 Modbus 连接失败:{err}", "red", "MdCloseFailed")
def __reg_high_pulse(self, addr: int) -> None: def __reg_high_pulse(self, addr: int) -> None:
self.c.write_register(addr, 0) self.c.write_register(addr, 0)
@ -344,7 +334,6 @@ class HmiRequest(QThread):
self.__port = port self.__port = port
self.__port_xs = port_xs self.__port_xs = port_xs
self.__close_hmi = False self.__close_hmi = False
self.__is_connected = False
self.__index = 0 self.__index = 0
self.__previous_data = b"" self.__previous_data = b""
self.__valid_data_length = 0 self.__valid_data_length = 0
@ -357,12 +346,10 @@ class HmiRequest(QThread):
self.__half_pkg_flag = False self.__half_pkg_flag = False
self.__is_first_frame = True self.__is_first_frame = True
self.__is_debug = True self.__is_debug = True
self.logger = clibs.logger
def net_conn(self): def net_conn(self):
self.__socket_conn() self.__socket_conn()
self.__t_heartbeat = threading.Thread(target=self.__heartbeat)
self.__t_heartbeat.daemon = True
self.__t_heartbeat.start()
self.__t_unpackage = threading.Thread(target=self.__unpackage, args=(self.c,)) self.__t_unpackage = threading.Thread(target=self.__unpackage, args=(self.c,))
self.__t_unpackage.daemon = True self.__t_unpackage.daemon = True
self.__t_unpackage.start() self.__t_unpackage.start()
@ -370,30 +357,13 @@ class HmiRequest(QThread):
self.__t_unpackage_xs.daemon = True self.__t_unpackage_xs.daemon = True
self.__t_unpackage_xs.start() self.__t_unpackage_xs.start()
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
@property
def status(self):
return self.__is_connected
def close(self): def close(self):
if self.__is_connected:
try:
self.__is_connected = False
time.sleep(clibs.INTERVAL/2)
self.c.close() self.c.close()
self.c_xs.close() self.c_xs.close()
clibs.status["hmi"] = 0
self.logger("INFO", "openapi", f"hmi: 关闭 Socket 连接成功", "green") self.logger("INFO", "openapi", f"hmi: 关闭 Socket 连接成功", "green")
except Exception as err:
self.logger("ERROR", "openapi", f"hmi: 关闭 Socket 连接失败 {err}", "red", "HmiCloseFailed")
def __socket_conn(self): def __socket_conn(self):
self.close() # self.close()
try: try:
self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.c.settimeout(clibs.INTERVAL*5) self.c.settimeout(clibs.INTERVAL*5)
@ -405,16 +375,11 @@ class HmiRequest(QThread):
state = None state = None
for i in range(3): for i in range(3):
_ = self.execution("controller.heart") _ = self.execution("controller.heart")
time.sleep(clibs.INTERVAL/2) time.sleep(clibs.INTERVAL/4)
self.__is_connected = True clibs.status["hmi"] = 1
self.logger("INFO", "openapi", "hmi: HMI connection success...", "green") self.logger("INFO", "openapi", "hmi: HMI connection success...", "green")
except Exception as err: except Exception:
self.logger("ERROR", "openapi", f"hmi: HMI connection timeout...", "red", "HmiConnTimeout") self.logger("ERROR", "openapi", f"hmi: HMI connection failed...", "red")
def __heartbeat(self):
while self.__is_connected:
self.execution("controller.heart")
time.sleep(clibs.INTERVAL*2)
@staticmethod @staticmethod
def package(cmd): def package(cmd):
@ -439,13 +404,13 @@ class HmiRequest(QThread):
try: try:
sel = selectors.DefaultSelector() sel = selectors.DefaultSelector()
sel.register(sock, selectors.EVENT_READ, to_read) sel.register(sock, selectors.EVENT_READ, to_read)
while self.__is_connected: while clibs.status["hmi"]:
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: except Exception as err:
self.logger("DEBUG", "openapi", f"hmi: 老协议解包报错 {Err}", "red", "UnpackageFailed") self.logger("DEBUG", "openapi", f"hmi: 老协议解包报错 err = {err}")
def __get_headers(self, index, data): def __get_headers(self, index, data):
if index + 8 < len(data): if index + 8 < len(data):
@ -458,7 +423,7 @@ class HmiRequest(QThread):
else: else:
# print("hr-get_headers: 解包数据有误,需要确认!") # print("hr-get_headers: 解包数据有误,需要确认!")
# print(data) # print(data)
self.logger("ERROR", "openapi", f"hmi: 解包数据有误,需要确认,最后一个数据包如下 {data}") self.logger("ERROR", "openapi", f"hmi: 解包数据有误,需要确认,最后一个数据包如下 {data}", "red")
else: else:
self.__half_pkg = data[index:] self.__half_pkg = data[index:]
self.__half_pkg_flag = True self.__half_pkg_flag = True
@ -681,7 +646,7 @@ class HmiRequest(QThread):
# if self.__valid_data_length < 0 or self.__leftovers > 1024: # if self.__valid_data_length < 0 or self.__leftovers > 1024:
# print(f"data = {data}") # print(f"data = {data}")
# raise Exception("DataError") # raise Exception("DataError")
self.logger("ERROR", "openapi", "hmi: Will never be here", "red", "WillNeverBeHere") self.logger("ERROR", "openapi", "hmi: will never be here", "red")
@staticmethod @staticmethod
def package_xs(cmd): def package_xs(cmd):
@ -701,13 +666,13 @@ class HmiRequest(QThread):
sel = selectors.DefaultSelector() sel = selectors.DefaultSelector()
sel.register(sock, selectors.EVENT_READ, to_read) sel.register(sock, selectors.EVENT_READ, to_read)
while self.__is_connected: while clibs.status["hmi"]:
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: except Exception as err:
self.logger("DEBUG", "openapi", f"hmi: xService解包报错 {err}", "red", "XsUnpackageFailed") self.logger("DEBUG", "openapi", f"hmi: xService解包报错 err = {err}")
def get_response_xs(self, data): def get_response_xs(self, data):
char, response = "", self.__response_xs char, response = "", self.__response_xs
@ -721,7 +686,6 @@ class HmiRequest(QThread):
else: else:
self.__response_xs = response self.__response_xs = response
@clibs.handle_exception
def get_from_id(self, msg_id): def get_from_id(self, msg_id):
f_text, flag, records, time_delay, ts = f"%{msg_id}%", False, "Null", clibs.INTERVAL*10, msg_id.split("@")[-1] f_text, flag, records, time_delay, ts = f"%{msg_id}%", False, "Null", clibs.INTERVAL*10, msg_id.split("@")[-1]
t = ts.replace("T", " ") t = ts.replace("T", " ")
@ -740,7 +704,7 @@ class HmiRequest(QThread):
if flag is True: if flag is True:
return records return records
else: else:
self.logger("ERROR", "openapi", f"hmi: {time_delay}s内无法找到请求 {msg_id} 的响应!", "red", "ResponseNotFound") self.logger("ERROR", "openapi", f"hmi: {time_delay}s内无法找到请求 {msg_id} 的响应!", "red")
def execution(self, command, **kwargs): def execution(self, command, **kwargs):
req = None req = None
@ -752,7 +716,7 @@ class HmiRequest(QThread):
flag = req["p_type"] flag = req["p_type"]
del req["p_type"] del req["p_type"]
except Exception as err: except Exception as err:
self.logger("ERROR", "openapi", f"hmi: 暂不支持 {command} 功能,或确认该功能存在... {err}", "red", "CommandNotSupport") self.logger("ERROR", "openapi", f"hmi: 暂不支持 {command} 功能,或确认该功能存在...<br>err = {err}", "red")
match command: match command:
case "state.set_tp_mode" | "overview.set_autoload" | "overview.reload" | "rl_task.pp_to_main" | "rl_task.run" | "rl_task.stop" | "rl_task.set_run_params" | "diagnosis.set_params" | "diagnosis.open" | "drag.set_params" | "controller.set_params" | "collision.set_state" | "collision.set_params" | "move.set_quickstop_distance" | "move.set_params" | "move.set_monitor_cfg" | "modbus.get_values" | "modbus.set_params" | "system_io.update_configuration" | "diagnosis.get_params" | "jog.set_params" | "jog.start" | "move.stop" | "move.quick_turn" | "move.set_quickturn_pos" | "soft_limit.set_params" | "fieldbus_device.set_params" | "socket.set_params" | "diagnosis.save" | "register.set_value": case "state.set_tp_mode" | "overview.set_autoload" | "overview.reload" | "rl_task.pp_to_main" | "rl_task.run" | "rl_task.stop" | "rl_task.set_run_params" | "diagnosis.set_params" | "diagnosis.open" | "drag.set_params" | "controller.set_params" | "collision.set_state" | "collision.set_params" | "move.set_quickstop_distance" | "move.set_params" | "move.set_monitor_cfg" | "modbus.get_values" | "modbus.set_params" | "system_io.update_configuration" | "diagnosis.get_params" | "jog.set_params" | "jog.start" | "move.stop" | "move.quick_turn" | "move.set_quickturn_pos" | "soft_limit.set_params" | "fieldbus_device.set_params" | "socket.set_params" | "diagnosis.save" | "register.set_value":
@ -768,17 +732,19 @@ class HmiRequest(QThread):
cmd = json.dumps(req, separators=(",", ":")) cmd = json.dumps(req, separators=(",", ":"))
try: try:
self.c.send(self.package(cmd)) self.c.send(self.package(cmd))
time.sleep(clibs.INTERVAL/4) time.sleep(clibs.INTERVAL/4) # 这里一定是要等几百毫秒的避免多指令同一时间发送导致xCore不响应
self.logger("DEBUG", "openapi", f"hmi: 老协议请求发送成功 {cmd}") self.logger("DEBUG", "openapi", f"hmi: 老协议请求发送成功 {cmd}")
except Exception as err: except Exception as err:
self.logger("ERROR", "openapi", f"hmi: 老协议请求发送失败 {cmd},报错信息 {err}", "red", "CommandSendFailed") if "controller.heart" in cmd:
raise Exception()
self.logger("ERROR", "openapi", f"hmi: 老协议请求发送失败 {cmd},报错信息 {err}", "red")
elif flag == 1: elif flag == 1:
try: try:
self.c_xs.send(self.package_xs(req)) self.c_xs.send(self.package_xs(req))
time.sleep(clibs.INTERVAL/4) time.sleep(clibs.INTERVAL/4)
self.logger("DEBUG", "openapi", f"hmi: xService请求发送成功 {req}") self.logger("DEBUG", "openapi", f"hmi: xService请求发送成功 {req}")
except Exception as Err: except Exception as err:
self.logger("ERROR", "openapi", f"hr: xService请求发送失败 {req} 报错信息 {Err}", "red", "CommandSendFailed") self.logger("ERROR", "openapi", f"hr: xService请求发送失败 {req} 报错信息 {err}", "red")
return req["id"] return req["id"]
@ -796,7 +762,7 @@ class HmiRequest(QThread):
case "off": case "off":
self.execution("state.switch_motor_off") self.execution("state.switch_motor_off")
case _: case _:
self.logger("ERROR", "openapi", f"hmi: switch_motor_state 参数错误 {state} 非法参数,只接受 on/off", "red", "ArgumentError") self.logger("ERROR", "openapi", f"hmi: switch_motor_state 参数错误 {state} 非法参数,只接受 on/off", "red")
def switch_operation_mode(self, mode: str): # OK def switch_operation_mode(self, mode: str): # OK
""" """
@ -810,7 +776,7 @@ class HmiRequest(QThread):
case "manual": case "manual":
self.execution("state.switch_manual") self.execution("state.switch_manual")
case _: case _:
self.logger("ERROR", "openapi", f"hmi: switch_operation_mode 参数错误 {mode},非法参数,只接受 auto/manual", "red", "ArgumentError") self.logger("ERROR", "openapi", f"hmi: switch_operation_mode 参数错误 {mode},非法参数,只接受 auto/manual", "red")
def reload_project(self, prj_name: str, tasks: list): # OK def reload_project(self, prj_name: str, tasks: list): # OK
""" """
@ -887,7 +853,7 @@ class HmiRequest(QThread):
self.__sth_wrong("3min 内未能完成重新连接,需要查看后台控制器是否正常启动,或者 ip/port 是否正确") self.__sth_wrong("3min 内未能完成重新连接,需要查看后台控制器是否正常启动,或者 ip/port 是否正确")
break break
for _ in range(3): for _ in range(3):
if not self.__is_connected: if not clibs.status["hmi"]:
break break
time.sleep(2) time.sleep(2)
else: else:
@ -1517,7 +1483,7 @@ class HmiRequest(QThread):
case "without": case "without":
self.execution("state.set_tp_mode", tp_mode="without") self.execution("state.set_tp_mode", tp_mode="without")
case _: case _:
self.logger("ERROR", "openapi", f"hmi: switch_tp_mode 参数错误{mode} 非法参数,只接受 with/without", "red", "ArgumentError") self.logger("ERROR", "openapi", f"hmi: switch_tp_mode 参数错误{mode} 非法参数,只接受 with/without", "red")
@property @property
def get_tp_mode(self): # OK def get_tp_mode(self): # OK
@ -1772,8 +1738,6 @@ class HmiRequest(QThread):
class ExternalCommunication(QThread): class ExternalCommunication(QThread):
output = Signal(str, str)
def __init__(self, ip, port, /): def __init__(self, ip, port, /):
super().__init__() super().__init__()
self.c = None self.c = None
@ -1781,34 +1745,32 @@ class ExternalCommunication(QThread):
self.port = int(port) self.port = int(port)
self.suffix = "\r" self.suffix = "\r"
self.exec_desc = " :--: 返回 true 表示执行成功false 失败" self.exec_desc = " :--: 返回 true 表示执行成功false 失败"
self.logger = clibs.logger
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
def net_conn(self): def net_conn(self):
# clibs.c_hr.execution("socket.set_params", enable=False, ip="0.0.0.0", port=str(self.port), suffix="\r", type=1) clibs.c_hr.execution("socket.set_params", enable=False, ip="0.0.0.0", port=str(self.port), suffix="\r", type=1)
# time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
clibs.c_hr.execution("socket.set_params", enable=True, ip="0.0.0.0", port=str(self.port), suffix="\r", type=1) clibs.c_hr.execution("socket.set_params", enable=True, ip="0.0.0.0", port=str(self.port), suffix="\r", type=1)
time.sleep(clibs.INTERVAL*2) # time.sleep(clibs.INTERVAL*2)
self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.c.settimeout(clibs.INTERVAL*5) self.c.settimeout(clibs.INTERVAL*5)
try: try:
self.c.connect((self.ip, self.port)) self.c.connect((self.ip, self.port))
self.logger("INFO", "openapi", f"ec: 外部通信连接成功...", "green") self.logger("INFO", "openapi", f"ec: 外部通信连接成功...", "green")
return self.c # return self.c
except Exception as err: except Exception as err:
self.logger("ERROR", "openapi", f"ec: 外部通信连接失败... {err}", "red", "EcConnFailed") self.logger("ERROR", "openapi", f"ec: 外部通信连接失败... {err}", "red")
def close(self): def close(self):
if clibs.status["ec"]:
try:
self.c.close() self.c.close()
self.logger("INFO", "openapi", f"ec: 关闭外部通信连接成功", "green") self.logger("INFO", "openapi", f"ec: 关闭外部通信连接成功", "green")
except Exception as err:
self.logger("ERROR", "openapi", f"ec: 关闭外部通信连接失败:{err}", "red", "EcCloseFailed") @clibs.db_lock
def sr_string(self, directive, interval=clibs.INTERVAL/2):
self.s_string(directive)
time.sleep(interval)
result = self.r_string(directive)
return result
def s_string(self, directive): def s_string(self, directive):
order = "".join([directive, self.suffix]) order = "".join([directive, self.suffix])
@ -1820,7 +1782,7 @@ class ExternalCommunication(QThread):
try: try:
char = self.c.recv(1).decode(encoding="unicode_escape") char = self.c.recv(1).decode(encoding="unicode_escape")
except Exception as err: except Exception as err:
self.logger("ERROR", "openapi", f"ec: 获取请求指令 {directive} 的返回数据超时,需确认指令发送格式以及内容正确!具体报错信息如下 {err}", "red", "RecvMsgFailed") self.logger("ERROR", "openapi", f"ec: 获取请求指令 {directive} 的返回数据超时,需确认指令发送格式以及内容正确!具体报错信息如下 {err}", "red")
result = "".join([result, char]) result = "".join([result, char])
return result return result
@ -2057,7 +2019,7 @@ class ExternalCommunication(QThread):
def __exec_cmd(self, directive, description, more_desc=""): def __exec_cmd(self, directive, description, more_desc=""):
self.s_string(directive) self.s_string(directive)
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL/2)
result = self.r_string(directive).strip() result = self.r_string(directive).strip()
self.logger("DEBUG", "openapi", f"ec: 执行{description}指令是 {directive},返回值为 {result}{more_desc}") self.logger("DEBUG", "openapi", f"ec: 执行{description}指令是 {directive},返回值为 {result}{more_desc}")
return result return result
@ -2082,7 +2044,6 @@ class PreDos(object):
print(f"predos: SSH 无法连接到 {self.ip}:{self.ssh_port},需检查网络连通性或者登录信息是否正确 {err}") print(f"predos: SSH 无法连接到 {self.ip}:{self.ssh_port},需检查网络连通性或者登录信息是否正确 {err}")
raise Exception("SshConnFailed") raise Exception("SshConnFailed")
@clibs.handle_exception
def push_prj_to_server(self, prj_file): def push_prj_to_server(self, prj_file):
# prj_file本地工程完整路径 # prj_file本地工程完整路径
self.__ssh2server() self.__ssh2server()
@ -2151,7 +2112,6 @@ class PreDos(object):
class RobotInit(object): class RobotInit(object):
@staticmethod @staticmethod
@clibs.handle_exception
def modbus_init(): def modbus_init():
clibs.c_pd = PreDos(clibs.ip_addr, clibs.ssh_port, clibs.username, clibs.password) clibs.c_pd = PreDos(clibs.ip_addr, clibs.ssh_port, clibs.username, clibs.password)
# 推送配置文件 # 推送配置文件

View File

@ -10,7 +10,6 @@ from codes.common import clibs
class DoFactoryTest(QThread): class DoFactoryTest(QThread):
output = Signal(str, str)
curve_map = { curve_map = {
"周期内平均转矩": ["device_servo_trq_feedback", ], "周期内平均转矩": ["device_servo_trq_feedback", ],
"周期内最大速度": ["hw_joint_vel_feedback", ], "周期内最大速度": ["hw_joint_vel_feedback", ],
@ -23,32 +22,25 @@ class DoFactoryTest(QThread):
self.procs = procs self.procs = procs
self.idx = 6 self.idx = 6
self.curves = [] self.curves = []
self.logger = clibs.logger
def logger(self, level, module, content, color="black", error="", flag="both"):
flag = "cursor" if level.upper() == "DEBUG" else "both"
clibs.logger(level, module, content, color, flag, signal=self.output)
if level.upper() == "ERROR":
raise Exception(f"{error} | {content}")
def initialization(self, data_dirs, data_files): def initialization(self, data_dirs, data_files):
@clibs.handle_exception
def check_files(): def check_files():
for proc_name, is_enabled in self.procs.items(): for proc_name, is_enabled in self.procs.items():
if is_enabled: if is_enabled:
self.curves.extend(self.curve_map[proc_name]) self.curves.extend(self.curve_map[proc_name])
if len(self.curves) == 0: if len(self.curves) == 0:
self.logger("ERROR", "factory", "未查询到需要记录数据的曲线,至少选择一个!", "red", "CurveNameError") self.logger("ERROR", "factory", "未查询到需要记录数据的曲线,至少选择一个!", "red")
if len(data_dirs) != 0 or len(data_files) != 1: if len(data_dirs) != 0 or len(data_files) != 1:
self.logger("ERROR", "factory", "初始路径下不允许有文件夹,且初始路径下只能存在一个工程文件 —— *.zip确认后重新运行", "red", "InitFileError") self.logger("ERROR", "factory", "初始路径下不允许有文件夹,且初始路径下只能存在一个工程文件 —— *.zip确认后重新运行", "red")
if not data_files[0].endswith(".zip"): if not data_files[0].endswith(".zip"):
self.logger("ERROR", "factory", f"{data_files[0]} 不是一个有效的工程文件,需确认!", "red", "ProjectFileError") self.logger("ERROR", "factory", f"{data_files[0]} 不是一个有效的工程文件,需确认!", "red")
return data_files[0] return data_files[0]
@clibs.handle_exception
def get_configs(): def get_configs():
robot_type, records = None, None robot_type, records = None, None
msg_id = clibs.c_hr.execution("controller.get_params") msg_id = clibs.c_hr.execution("controller.get_params")
@ -64,7 +56,7 @@ class DoFactoryTest(QThread):
with open(local_file, mode="r", encoding="utf-8") as f_config: with open(local_file, mode="r", encoding="utf-8") as f_config:
configs = json.load(f_config) configs = json.load(f_config)
except Exception as Err: except Exception as Err:
self.logger("ERROR", "factory", f"无法打开 {local_file}<br>{Err}", "red", "OpenFileError") self.logger("ERROR", "factory", f"无法打开 {local_file}<br>{Err}", "red")
# 最大角速度,额定电流,减速比,额定转速 # 最大角速度,额定电流,减速比,额定转速
version = configs["VERSION"] version = configs["VERSION"]
@ -86,13 +78,11 @@ class DoFactoryTest(QThread):
self.logger("INFO", "factory", "数据目录合规性检查结束,未发现问题......", "green") self.logger("INFO", "factory", "数据目录合规性检查结束,未发现问题......", "green")
return params return params
@clibs.handle_exception
def change_curve_state(self, stat): def change_curve_state(self, stat):
display_pdo_params = [{"name": name, "channel": chl} for name in self.curves for chl in range(6)] display_pdo_params = [{"name": name, "channel": chl} for name in self.curves for chl in range(6)]
clibs.c_hr.execution("diagnosis.open", open=stat, display_open=stat) clibs.c_hr.execution("diagnosis.open", open=stat, display_open=stat)
clibs.c_hr.execution("diagnosis.set_params", display_pdo_params=display_pdo_params) clibs.c_hr.execution("diagnosis.set_params", display_pdo_params=display_pdo_params)
@clibs.handle_exception
def run_rl(self, params): def run_rl(self, params):
prj_file, interval = params["prj_file"], params["interval"] prj_file, interval = params["prj_file"], params["interval"]
# 1. 关闭诊断曲线,触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电 # 1. 关闭诊断曲线,触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电
@ -123,7 +113,7 @@ class DoFactoryTest(QThread):
break break
else: else:
if (time.time() - t_start) > 15: if (time.time() - t_start) > 15:
self.logger("ERROR", "factory", "15s 内未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", "red", "ReadySignalTimeoutError") self.logger("ERROR", "factory", "15s 内未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", "red")
else: else:
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
@ -138,7 +128,7 @@ class DoFactoryTest(QThread):
else: else:
time.sleep(clibs.INTERVAL) time.sleep(clibs.INTERVAL)
if (time.time() - t_start) > 900: if (time.time() - t_start) > 900:
self.logger("ERROR", "factory", f"900s内未收到耐久工程的周期时间需要确认RL程序和工具通信交互是否正常执行支持最长工程周期时间为300s......", "red", "GetScenarioTimeError") self.logger("ERROR", "factory", f"900s内未收到耐久工程的周期时间需要确认RL程序和工具通信交互是否正常执行支持最长工程周期时间为300s......", "red")
# 6. 准备数据保存文件 # 6. 准备数据保存文件
for proc_name, is_enabled in self.procs.items(): for proc_name, is_enabled in self.procs.items():
@ -180,7 +170,6 @@ class DoFactoryTest(QThread):
self.change_curve_state(False) self.change_curve_state(False)
self.logger("INFO", "factory", "后台数据清零完成,现在可以重新运行其他程序。", "green") self.logger("INFO", "factory", "后台数据清零完成,现在可以重新运行其他程序。", "green")
@clibs.handle_exception
def gen_results(self, params, start_time, end_time): def gen_results(self, params, start_time, end_time):
s_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time)) s_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time))
e_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time)) e_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(end_time))
@ -193,7 +182,6 @@ class DoFactoryTest(QThread):
self.data_proc(records, params) self.data_proc(records, params)
@clibs.handle_exception
def data_proc(self, records, params): def data_proc(self, records, params):
for proc_name, is_enabled in self.procs.items(): for proc_name, is_enabled in self.procs.items():
if not is_enabled: if not is_enabled:
@ -210,7 +198,6 @@ class DoFactoryTest(QThread):
t.daemon = True t.daemon = True
t.start() t.start()
@clibs.handle_exception
def get_avg_trq(self, records, params, proc_name): def get_avg_trq(self, records, params, proc_name):
d_trq, results = [[], [], [], [], [], []], [time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))] d_trq, results = [[], [], [], [], [], []], [time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))]
for record in records: for record in records:
@ -231,7 +218,6 @@ class DoFactoryTest(QThread):
csv_writer = csv.writer(f_csv) csv_writer = csv.writer(f_csv)
csv_writer.writerow(results) csv_writer.writerow(results)
@clibs.handle_exception
def get_joint_max_vel(self, records, params, proc_name): def get_joint_max_vel(self, records, params, proc_name):
d_trq, results = [[], [], [], [], [], []], [time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))] d_trq, results = [[], [], [], [], [], []], [time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))]
for record in records: for record in records:
@ -255,7 +241,6 @@ class DoFactoryTest(QThread):
@staticmethod @staticmethod
def detect_db_size(): def detect_db_size():
@clibs.db_lock @clibs.db_lock
@clibs.handle_exception
def release_memory(): def release_memory():
line_number = 20000 line_number = 20000
leftover = 4000 # 200s leftover = 4000 # 200s
@ -272,18 +257,17 @@ class DoFactoryTest(QThread):
release_memory() release_memory()
time.sleep(clibs.INTERVAL*10) time.sleep(clibs.INTERVAL*10)
@clibs.handle_exception
def processing(self): def processing(self):
time_start = time.time() time_start = time.time()
clibs.running[self.idx] = 1 clibs.running[self.idx] = 1
if clibs.status["hmi"] != 1 or clibs.status["md"] != 1: if clibs.status["hmi"] != 1 or clibs.status["md"] != 1:
self.logger("ERROR", "factory", "processing: 需要在网络设置中连接HMI以及Modbus通信", "red", "NetworkError") self.logger("ERROR", "factory", "processing: 需要在网络设置中连接HMI以及Modbus通信", "red")
t = threading.Thread(target=self.detect_db_size) t = threading.Thread(target=self.detect_db_size)
t.daemon = True t.daemon = True
t.start() t.start()
data_dirs, data_files = clibs.traversal_files(self.dir_path, self.output) data_dirs, data_files = clibs.traversal_files(self.dir_path)
params = self.initialization(data_dirs, data_files) params = self.initialization(data_dirs, data_files)
clibs.c_pd.push_prj_to_server(params["prj_file"]) clibs.c_pd.push_prj_to_server(params["prj_file"])
self.run_rl(params) self.run_rl(params)

View File

@ -19,15 +19,15 @@ from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QFormLayout,
QFrame, QHBoxLayout, QHeaderView, QLabel, QFrame, QHBoxLayout, QHeaderView, QLabel,
QLineEdit, QMainWindow, QPlainTextEdit, QPushButton, QLineEdit, QMainWindow, QPlainTextEdit, QPushButton,
QScrollArea, QSizePolicy, QSpacerItem, QStackedWidget, QScrollArea, QSizePolicy, QSpacerItem, QStackedWidget,
QStatusBar, QTabWidget, QTreeWidget, QTreeWidgetItem, QStatusBar, QTabWidget, QToolButton, QTreeWidget,
QVBoxLayout, QWidget) QTreeWidgetItem, QVBoxLayout, QWidget)
class Ui_MainWindow(QMainWindow): class Ui_MainWindow(QMainWindow):
def setupUi(self, MainWindow): def setupUi(self, MainWindow):
if not MainWindow.objectName(): if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow") MainWindow.setObjectName(u"MainWindow")
MainWindow.setEnabled(True) MainWindow.setEnabled(True)
MainWindow.resize(1004, 560) MainWindow.resize(1006, 568)
sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
@ -174,18 +174,15 @@ class Ui_MainWindow(QMainWindow):
self.horizontalLayout.addWidget(self.le_data_path) self.horizontalLayout.addWidget(self.le_data_path)
self.btn_data_open = QPushButton(self.tab_data) self.toolButton = QToolButton(self.tab_data)
self.btn_data_open.setObjectName(u"btn_data_open") self.toolButton.setObjectName(u"toolButton")
self.btn_data_open.setMaximumSize(QSize(30, 16777215))
self.btn_data_open.setFont(font4)
self.horizontalLayout.addWidget(self.btn_data_open) self.horizontalLayout.addWidget(self.toolButton)
self.horizontalLayout.setStretch(0, 1) self.horizontalLayout.setStretch(0, 1)
self.horizontalLayout.setStretch(1, 1) self.horizontalLayout.setStretch(1, 1)
self.horizontalLayout.setStretch(2, 1) self.horizontalLayout.setStretch(2, 1)
self.horizontalLayout.setStretch(3, 10) self.horizontalLayout.setStretch(3, 10)
self.horizontalLayout.setStretch(4, 1)
self.verticalLayout.addLayout(self.horizontalLayout) self.verticalLayout.addLayout(self.horizontalLayout)
@ -235,18 +232,15 @@ class Ui_MainWindow(QMainWindow):
self.hl_2_unit1.addWidget(self.le_unit_path) self.hl_2_unit1.addWidget(self.le_unit_path)
self.btn_unit_open = QPushButton(self.tab_unit) self.toolButton_2 = QToolButton(self.tab_unit)
self.btn_unit_open.setObjectName(u"btn_unit_open") self.toolButton_2.setObjectName(u"toolButton_2")
self.btn_unit_open.setMaximumSize(QSize(30, 16777215))
self.btn_unit_open.setFont(font4)
self.hl_2_unit1.addWidget(self.btn_unit_open) self.hl_2_unit1.addWidget(self.toolButton_2)
self.hl_2_unit1.setStretch(0, 1) self.hl_2_unit1.setStretch(0, 1)
self.hl_2_unit1.setStretch(1, 1) self.hl_2_unit1.setStretch(1, 1)
self.hl_2_unit1.setStretch(2, 1) self.hl_2_unit1.setStretch(2, 1)
self.hl_2_unit1.setStretch(3, 10) self.hl_2_unit1.setStretch(3, 10)
self.hl_2_unit1.setStretch(4, 1)
self.verticalLayout_2.addLayout(self.hl_2_unit1) self.verticalLayout_2.addLayout(self.hl_2_unit1)
@ -287,7 +281,7 @@ class Ui_MainWindow(QMainWindow):
self.sa_durable.setWidgetResizable(True) self.sa_durable.setWidgetResizable(True)
self.scrollAreaWidgetContents = QWidget() self.scrollAreaWidgetContents = QWidget()
self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents")
self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 212, 78)) self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 213, 78))
self.horizontalLayout_9 = QHBoxLayout(self.scrollAreaWidgetContents) self.horizontalLayout_9 = QHBoxLayout(self.scrollAreaWidgetContents)
self.horizontalLayout_9.setObjectName(u"horizontalLayout_9") self.horizontalLayout_9.setObjectName(u"horizontalLayout_9")
self.verticalLayout_5 = QVBoxLayout() self.verticalLayout_5 = QVBoxLayout()
@ -343,13 +337,14 @@ class Ui_MainWindow(QMainWindow):
self.horizontalLayout_6.addWidget(self.le_durable_path) self.horizontalLayout_6.addWidget(self.le_durable_path)
self.btn_durable_open = QPushButton(self.tab_durable) self.toolButton_3 = QToolButton(self.tab_durable)
self.btn_durable_open.setObjectName(u"btn_durable_open") self.toolButton_3.setObjectName(u"toolButton_3")
self.btn_durable_open.setMaximumSize(QSize(30, 16777215))
self.btn_durable_open.setFont(font4)
self.horizontalLayout_6.addWidget(self.btn_durable_open) self.horizontalLayout_6.addWidget(self.toolButton_3)
self.horizontalLayout_6.setStretch(0, 1)
self.horizontalLayout_6.setStretch(1, 10)
self.horizontalLayout_6.setStretch(2, 1)
self.verticalLayout_6.addLayout(self.horizontalLayout_6) self.verticalLayout_6.addLayout(self.horizontalLayout_6)
@ -371,17 +366,8 @@ class Ui_MainWindow(QMainWindow):
self.horizontalLayout_7.addWidget(self.le_durable_interval) self.horizontalLayout_7.addWidget(self.le_durable_interval)
self.label_10 = QLabel(self.tab_durable) self.horizontalLayout_7.setStretch(0, 1)
self.label_10.setObjectName(u"label_10") self.horizontalLayout_7.setStretch(1, 10)
sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Preferred)
sizePolicy2.setHorizontalStretch(0)
sizePolicy2.setVerticalStretch(0)
sizePolicy2.setHeightForWidth(self.label_10.sizePolicy().hasHeightForWidth())
self.label_10.setSizePolicy(sizePolicy2)
self.label_10.setMinimumSize(QSize(30, 0))
self.horizontalLayout_7.addWidget(self.label_10)
self.verticalLayout_6.addLayout(self.horizontalLayout_7) self.verticalLayout_6.addLayout(self.horizontalLayout_7)
@ -505,10 +491,10 @@ class Ui_MainWindow(QMainWindow):
self.horizontalLayout_5.addWidget(self.pte_hmi_send) self.horizontalLayout_5.addWidget(self.pte_hmi_send)
self.pte_him_recv = QPlainTextEdit(self.page) self.pte_hmi_recv = QPlainTextEdit(self.page)
self.pte_him_recv.setObjectName(u"pte_him_recv") self.pte_hmi_recv.setObjectName(u"pte_hmi_recv")
self.horizontalLayout_5.addWidget(self.pte_him_recv) self.horizontalLayout_5.addWidget(self.pte_hmi_recv)
self.verticalLayout_10.addLayout(self.horizontalLayout_5) self.verticalLayout_10.addLayout(self.horizontalLayout_5)
@ -746,23 +732,23 @@ class Ui_MainWindow(QMainWindow):
self.verticalLayout_4 = QVBoxLayout() self.verticalLayout_4 = QVBoxLayout()
self.verticalLayout_4.setObjectName(u"verticalLayout_4") self.verticalLayout_4.setObjectName(u"verticalLayout_4")
self.pushButton = QPushButton(self.tab_network) self.hmi_btn = QPushButton(self.tab_network)
self.pushButton.setObjectName(u"pushButton") self.hmi_btn.setObjectName(u"hmi_btn")
self.pushButton.setFont(font5) self.hmi_btn.setFont(font5)
self.verticalLayout_4.addWidget(self.pushButton) self.verticalLayout_4.addWidget(self.hmi_btn)
self.pushButton_2 = QPushButton(self.tab_network) self.md_btn = QPushButton(self.tab_network)
self.pushButton_2.setObjectName(u"pushButton_2") self.md_btn.setObjectName(u"md_btn")
self.pushButton_2.setFont(font5) self.md_btn.setFont(font5)
self.verticalLayout_4.addWidget(self.pushButton_2) self.verticalLayout_4.addWidget(self.md_btn)
self.pushButton_3 = QPushButton(self.tab_network) self.ec_btn = QPushButton(self.tab_network)
self.pushButton_3.setObjectName(u"pushButton_3") self.ec_btn.setObjectName(u"ec_btn")
self.pushButton_3.setFont(font5) self.ec_btn.setFont(font5)
self.verticalLayout_4.addWidget(self.pushButton_3) self.verticalLayout_4.addWidget(self.ec_btn)
self.horizontalLayout_12.addLayout(self.verticalLayout_4) self.horizontalLayout_12.addLayout(self.verticalLayout_4)
@ -877,11 +863,11 @@ class Ui_MainWindow(QMainWindow):
MainWindow.setCentralWidget(self.centralwidget) MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QStatusBar(MainWindow) self.statusbar = QStatusBar(MainWindow)
self.statusbar.setObjectName(u"statusbar") self.statusbar.setObjectName(u"statusbar")
sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
sizePolicy3.setHorizontalStretch(0) sizePolicy2.setHorizontalStretch(0)
sizePolicy3.setVerticalStretch(0) sizePolicy2.setVerticalStretch(0)
sizePolicy3.setHeightForWidth(self.statusbar.sizePolicy().hasHeightForWidth()) sizePolicy2.setHeightForWidth(self.statusbar.sizePolicy().hasHeightForWidth())
self.statusbar.setSizePolicy(sizePolicy3) self.statusbar.setSizePolicy(sizePolicy2)
self.statusbar.setMinimumSize(QSize(0, 27)) self.statusbar.setMinimumSize(QSize(0, 27))
self.statusbar.setStyleSheet(u"background-color: rgb(200, 200, 200);") self.statusbar.setStyleSheet(u"background-color: rgb(200, 200, 200);")
MainWindow.setStatusBar(self.statusbar) MainWindow.setStatusBar(self.statusbar)
@ -890,11 +876,8 @@ class Ui_MainWindow(QMainWindow):
self.btn_start.clicked.connect(MainWindow.prog_start) self.btn_start.clicked.connect(MainWindow.prog_start)
self.btn_stop.clicked.connect(MainWindow.prog_stop) self.btn_stop.clicked.connect(MainWindow.prog_stop)
self.btn_reset.clicked.connect(MainWindow.prog_reset) self.btn_reset.clicked.connect(MainWindow.prog_reset)
self.btn_durable_open.clicked.connect(MainWindow.file_browser)
self.btn_draw.clicked.connect(MainWindow.curve_draw) self.btn_draw.clicked.connect(MainWindow.curve_draw)
self.cb_durable_total.checkStateChanged.connect(MainWindow.durable_cb_change) self.cb_durable_total.checkStateChanged.connect(MainWindow.durable_cb_change)
self.btn_unit_open.clicked.connect(MainWindow.file_browser)
self.btn_data_open.clicked.connect(MainWindow.file_browser)
self.btn_docs_previous.clicked.connect(MainWindow.pre_page) self.btn_docs_previous.clicked.connect(MainWindow.pre_page)
self.btn_docs_realtime.clicked.connect(MainWindow.realtime_page) self.btn_docs_realtime.clicked.connect(MainWindow.realtime_page)
self.btn_docs_next.clicked.connect(MainWindow.next_page) self.btn_docs_next.clicked.connect(MainWindow.next_page)
@ -902,9 +885,9 @@ class Ui_MainWindow(QMainWindow):
self.le_docs_search.returnPressed.connect(MainWindow.search_keyword) self.le_docs_search.returnPressed.connect(MainWindow.search_keyword)
self.cb_hmi_cmd.currentTextChanged.connect(MainWindow.hmi_cb_change) self.cb_hmi_cmd.currentTextChanged.connect(MainWindow.hmi_cb_change)
self.btn_hmi_send.clicked.connect(MainWindow.hmi_send) self.btn_hmi_send.clicked.connect(MainWindow.hmi_send)
self.pushButton.clicked.connect(MainWindow.hmi_page) self.hmi_btn.clicked.connect(MainWindow.hmi_page)
self.pushButton_2.clicked.connect(MainWindow.md_page) self.md_btn.clicked.connect(MainWindow.md_page)
self.pushButton_3.clicked.connect(MainWindow.ec_page) self.ec_btn.clicked.connect(MainWindow.ec_page)
self.cb_md_cmd.currentTextChanged.connect(MainWindow.md_cb_change) self.cb_md_cmd.currentTextChanged.connect(MainWindow.md_cb_change)
self.btn_md_send.clicked.connect(MainWindow.md_send) self.btn_md_send.clicked.connect(MainWindow.md_send)
self.btn_ec_send.clicked.connect(MainWindow.ec_send) self.btn_ec_send.clicked.connect(MainWindow.ec_send)
@ -916,6 +899,10 @@ class Ui_MainWindow(QMainWindow):
self.le_hmi_ip.returnPressed.connect(MainWindow.hmi_conn) self.le_hmi_ip.returnPressed.connect(MainWindow.hmi_conn)
self.tw_docs.currentChanged.connect(MainWindow.switch_log_tab) self.tw_docs.currentChanged.connect(MainWindow.switch_log_tab)
self.treew_log.itemDoubleClicked.connect(MainWindow.show_item_content) self.treew_log.itemDoubleClicked.connect(MainWindow.show_item_content)
self.cb_data_func.currentTextChanged.connect(MainWindow.data_cb_change)
self.toolButton.clicked.connect(MainWindow.file_browser)
self.toolButton_2.clicked.connect(MainWindow.file_browser)
self.toolButton_3.clicked.connect(MainWindow.file_browser)
self.tw_funcs.setCurrentIndex(0) self.tw_funcs.setCurrentIndex(0)
self.sw_network.setCurrentIndex(0) self.sw_network.setCurrentIndex(0)
@ -941,7 +928,7 @@ class Ui_MainWindow(QMainWindow):
self.cb_data_current.setItemText(2, QCoreApplication.translate("MainWindow", u"\u5e73\u5747\u503c", None)) self.cb_data_current.setItemText(2, QCoreApplication.translate("MainWindow", u"\u5e73\u5747\u503c", None))
self.label_4.setText(QCoreApplication.translate("MainWindow", u"\u8def\u5f84", None)) self.label_4.setText(QCoreApplication.translate("MainWindow", u"\u8def\u5f84", None))
self.btn_data_open.setText(QCoreApplication.translate("MainWindow", u"...", None)) self.toolButton.setText(QCoreApplication.translate("MainWindow", u"...", None))
self.tw_funcs.setTabText(self.tw_funcs.indexOf(self.tab_data), QCoreApplication.translate("MainWindow", u"\u6570\u636e\u5904\u7406", None)) self.tw_funcs.setTabText(self.tw_funcs.indexOf(self.tab_data), QCoreApplication.translate("MainWindow", u"\u6570\u636e\u5904\u7406", None))
self.cb_unit_func.setItemText(0, QCoreApplication.translate("MainWindow", u"\u5236\u52a8", None)) self.cb_unit_func.setItemText(0, QCoreApplication.translate("MainWindow", u"\u5236\u52a8", None))
self.cb_unit_func.setItemText(1, QCoreApplication.translate("MainWindow", u"\u8f6c\u77e9", None)) self.cb_unit_func.setItemText(1, QCoreApplication.translate("MainWindow", u"\u8f6c\u77e9", None))
@ -952,19 +939,18 @@ class Ui_MainWindow(QMainWindow):
self.cb_unit_tool.setItemText(3, QCoreApplication.translate("MainWindow", u"inertia", None)) self.cb_unit_tool.setItemText(3, QCoreApplication.translate("MainWindow", u"inertia", None))
self.label_6.setText(QCoreApplication.translate("MainWindow", u"\u8def\u5f84", None)) self.label_6.setText(QCoreApplication.translate("MainWindow", u"\u8def\u5f84", None))
self.btn_unit_open.setText(QCoreApplication.translate("MainWindow", u"...", None)) self.toolButton_2.setText(QCoreApplication.translate("MainWindow", u"...", None))
self.tw_funcs.setTabText(self.tw_funcs.indexOf(self.tab_unit), QCoreApplication.translate("MainWindow", u"\u6574\u673a\u6d4b\u8bd5", None)) self.tw_funcs.setTabText(self.tw_funcs.indexOf(self.tab_unit), QCoreApplication.translate("MainWindow", u"\u6574\u673a\u6d4b\u8bd5", None))
self.label_11.setText(QCoreApplication.translate("MainWindow", u"\u9009\u62e9\u6307\u6807", None)) self.label_11.setText(QCoreApplication.translate("MainWindow", u"\u9009\u62e9\u6307\u6807", None))
self.cb_1.setText(QCoreApplication.translate("MainWindow", u"\u5468\u671f\u5185\u5e73\u5747\u8f6c\u77e9", None)) self.cb_1.setText(QCoreApplication.translate("MainWindow", u"\u5468\u671f\u5185\u5e73\u5747\u8f6c\u77e9", None))
self.cb_2.setText(QCoreApplication.translate("MainWindow", u"\u5468\u671f\u5185\u6700\u5927\u901f\u5ea6", None)) self.cb_2.setText(QCoreApplication.translate("MainWindow", u"\u5468\u671f\u5185\u6700\u5927\u901f\u5ea6", None))
self.label_8.setText(QCoreApplication.translate("MainWindow", u"\u8def\u5f84", None)) self.label_8.setText(QCoreApplication.translate("MainWindow", u"\u8def\u5f84", None))
self.btn_durable_open.setText(QCoreApplication.translate("MainWindow", u"...", None)) self.toolButton_3.setText(QCoreApplication.translate("MainWindow", u"...", None))
self.label_9.setText(QCoreApplication.translate("MainWindow", u"\u95f4\u9694", None)) self.label_9.setText(QCoreApplication.translate("MainWindow", u"\u95f4\u9694", None))
#if QT_CONFIG(whatsthis) #if QT_CONFIG(whatsthis)
self.le_durable_interval.setWhatsThis("") self.le_durable_interval.setWhatsThis("")
#endif // QT_CONFIG(whatsthis) #endif // QT_CONFIG(whatsthis)
self.le_durable_interval.setPlaceholderText(QCoreApplication.translate("MainWindow", u"\u6bcf\u6b21\u6570\u636e\u91c7\u96c6\u7684\u65f6\u95f4\u95f4\u9694\uff0c\u9ed8\u8ba4(\u6700\u5c0f)300s", None)) self.le_durable_interval.setPlaceholderText(QCoreApplication.translate("MainWindow", u"\u6bcf\u6b21\u6570\u636e\u91c7\u96c6\u7684\u65f6\u95f4\u95f4\u9694\uff0c\u9ed8\u8ba4(\u6700\u5c0f)300s", None))
self.label_10.setText("")
self.cb_durable_total.setText(QCoreApplication.translate("MainWindow", u"\u5168\u90e8\u6253\u5f00/\u5173\u95ed", None)) self.cb_durable_total.setText(QCoreApplication.translate("MainWindow", u"\u5168\u90e8\u6253\u5f00/\u5173\u95ed", None))
self.btn_draw.setText(QCoreApplication.translate("MainWindow", u"\u7ed8\u56fe", None)) self.btn_draw.setText(QCoreApplication.translate("MainWindow", u"\u7ed8\u56fe", None))
self.label_3.setText("") self.label_3.setText("")
@ -1053,16 +1039,16 @@ class Ui_MainWindow(QMainWindow):
self.cb_ec_cmd.setItemText(52, QCoreApplication.translate("MainWindow", u"safe_door_open", None)) self.cb_ec_cmd.setItemText(52, QCoreApplication.translate("MainWindow", u"safe_door_open", None))
self.cb_ec_cmd.setItemText(53, QCoreApplication.translate("MainWindow", u"soft_estop_state", None)) self.cb_ec_cmd.setItemText(53, QCoreApplication.translate("MainWindow", u"soft_estop_state", None))
self.cb_ec_cmd.setItemText(54, QCoreApplication.translate("MainWindow", u"cart_vel", None)) self.cb_ec_cmd.setItemText(54, QCoreApplication.translate("MainWindow", u"cart_vel", None))
self.cb_ec_cmd.setItemText(55, QCoreApplication.translate("MainWindow", u"tcp_pos", None)) self.cb_ec_cmd.setItemText(55, QCoreApplication.translate("MainWindow", u"tcp_pose", None))
self.cb_ec_cmd.setItemText(56, QCoreApplication.translate("MainWindow", u"tcp_vel", None)) self.cb_ec_cmd.setItemText(56, QCoreApplication.translate("MainWindow", u"tcp_vel", None))
self.cb_ec_cmd.setItemText(57, QCoreApplication.translate("MainWindow", u"tcp_vel_mag", None)) self.cb_ec_cmd.setItemText(57, QCoreApplication.translate("MainWindow", u"tcp_vel_mag", None))
self.cb_ec_cmd.setItemText(58, QCoreApplication.translate("MainWindow", u"ext_estop_state", None)) self.cb_ec_cmd.setItemText(58, QCoreApplication.translate("MainWindow", u"ext_estop_state", None))
self.cb_ec_cmd.setItemText(59, QCoreApplication.translate("MainWindow", u"hand_estop_state", None)) self.cb_ec_cmd.setItemText(59, QCoreApplication.translate("MainWindow", u"hand_estop_state", None))
self.btn_ec_send.setText(QCoreApplication.translate("MainWindow", u"\u53d1\u9001", None)) self.btn_ec_send.setText(QCoreApplication.translate("MainWindow", u"\u53d1\u9001", None))
self.pushButton.setText(QCoreApplication.translate("MainWindow", u"HMI", None)) self.hmi_btn.setText(QCoreApplication.translate("MainWindow", u"HMI", None))
self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"Modbus", None)) self.md_btn.setText(QCoreApplication.translate("MainWindow", u"Modbus", None))
self.pushButton_3.setText(QCoreApplication.translate("MainWindow", u"EC", None)) self.ec_btn.setText(QCoreApplication.translate("MainWindow", u"EC", None))
self.tw_funcs.setTabText(self.tw_funcs.indexOf(self.tab_network), QCoreApplication.translate("MainWindow", u"\u7f51\u7edc\u8bbe\u7f6e", None)) self.tw_funcs.setTabText(self.tw_funcs.indexOf(self.tab_network), QCoreApplication.translate("MainWindow", u"\u7f51\u7edc\u8bbe\u7f6e", None))
self.tw_docs.setTabText(self.tw_docs.indexOf(self.tab_output), QCoreApplication.translate("MainWindow", u"\u8f93\u51fa", None)) self.tw_docs.setTabText(self.tw_docs.indexOf(self.tab_output), QCoreApplication.translate("MainWindow", u"\u8f93\u51fa", None))
___qtreewidgetitem = self.treew_log.headerItem() ___qtreewidgetitem = self.treew_log.headerItem()

View File

@ -9,8 +9,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1004</width> <width>1006</width>
<height>563</height> <height>568</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -248,7 +248,7 @@
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1,10,1"> <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,1,1,10,0">
<item> <item>
<widget class="QComboBox" name="cb_data_func"> <widget class="QComboBox" name="cb_data_func">
<property name="minimumSize"> <property name="minimumSize">
@ -346,19 +346,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="btn_data_open"> <widget class="QToolButton" name="toolButton">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Consolas</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>...</string>
</property> </property>
@ -387,7 +375,7 @@
</attribute> </attribute>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<layout class="QHBoxLayout" name="hl_2_unit1" stretch="1,1,1,10,1"> <layout class="QHBoxLayout" name="hl_2_unit1" stretch="1,1,1,10,0">
<item> <item>
<widget class="QComboBox" name="cb_unit_func"> <widget class="QComboBox" name="cb_unit_func">
<property name="minimumSize"> <property name="minimumSize">
@ -483,19 +471,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="btn_unit_open"> <widget class="QToolButton" name="toolButton_2">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Consolas</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>...</string>
</property> </property>
@ -583,7 +559,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>212</width> <width>213</width>
<height>78</height> <height>78</height>
</rect> </rect>
</property> </property>
@ -645,7 +621,7 @@
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_6"> <layout class="QVBoxLayout" name="verticalLayout_6">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_6"> <layout class="QHBoxLayout" name="horizontalLayout_6" stretch="1,10,1">
<item> <item>
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="sizePolicy"> <property name="sizePolicy">
@ -679,19 +655,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="btn_durable_open"> <widget class="QToolButton" name="toolButton_3">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="font">
<font>
<family>Consolas</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="text"> <property name="text">
<string>...</string> <string>...</string>
</property> </property>
@ -700,7 +664,7 @@
</layout> </layout>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_7"> <layout class="QHBoxLayout" name="horizontalLayout_7" stretch="1,10">
<item> <item>
<widget class="QLabel" name="label_9"> <widget class="QLabel" name="label_9">
<property name="sizePolicy"> <property name="sizePolicy">
@ -742,25 +706,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="label_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -977,7 +922,7 @@
<widget class="QPlainTextEdit" name="pte_hmi_send"/> <widget class="QPlainTextEdit" name="pte_hmi_send"/>
</item> </item>
<item> <item>
<widget class="QPlainTextEdit" name="pte_him_recv"/> <widget class="QPlainTextEdit" name="pte_hmi_recv"/>
</item> </item>
</layout> </layout>
</item> </item>
@ -1524,7 +1469,7 @@
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>tcp_pos</string> <string>tcp_pose</string>
</property> </property>
</item> </item>
<item> <item>
@ -1584,7 +1529,7 @@
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_4"> <layout class="QVBoxLayout" name="verticalLayout_4">
<item> <item>
<widget class="QPushButton" name="pushButton"> <widget class="QPushButton" name="hmi_btn">
<property name="font"> <property name="font">
<font> <font>
<family>Consolas</family> <family>Consolas</family>
@ -1598,7 +1543,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_2"> <widget class="QPushButton" name="md_btn">
<property name="font"> <property name="font">
<font> <font>
<family>Consolas</family> <family>Consolas</family>
@ -1612,7 +1557,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="pushButton_3"> <widget class="QPushButton" name="ec_btn">
<property name="font"> <property name="font">
<font> <font>
<family>Consolas</family> <family>Consolas</family>
@ -1894,22 +1839,6 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>btn_durable_open</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>file_browser()</slot>
<hints>
<hint type="sourcelabel">
<x>964</x>
<y>69</y>
</hint>
<hint type="destinationlabel">
<x>990</x>
<y>97</y>
</hint>
</hints>
</connection>
<connection> <connection>
<sender>btn_draw</sender> <sender>btn_draw</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
@ -1917,8 +1846,8 @@
<slot>curve_draw()</slot> <slot>curve_draw()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>692</x> <x>326</x>
<y>136</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>701</x> <x>701</x>
@ -1933,8 +1862,8 @@
<slot>durable_cb_change()</slot> <slot>durable_cb_change()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>566</x> <x>326</x>
<y>135</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>546</x> <x>546</x>
@ -1942,38 +1871,6 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>btn_unit_open</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>file_browser()</slot>
<hints>
<hint type="sourcelabel">
<x>981</x>
<y>78</y>
</hint>
<hint type="destinationlabel">
<x>974</x>
<y>181</y>
</hint>
</hints>
</connection>
<connection>
<sender>btn_data_open</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>file_browser()</slot>
<hints>
<hint type="sourcelabel">
<x>964</x>
<y>73</y>
</hint>
<hint type="destinationlabel">
<x>941</x>
<y>180</y>
</hint>
</hints>
</connection>
<connection> <connection>
<sender>btn_docs_previous</sender> <sender>btn_docs_previous</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
@ -1981,8 +1878,8 @@
<slot>pre_page()</slot> <slot>pre_page()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>408</x> <x>326</x>
<y>507</y> <y>266</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>307</x> <x>307</x>
@ -1997,8 +1894,8 @@
<slot>realtime_page()</slot> <slot>realtime_page()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>489</x> <x>326</x>
<y>507</y> <y>266</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>435</x> <x>435</x>
@ -2013,8 +1910,8 @@
<slot>next_page()</slot> <slot>next_page()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>570</x> <x>326</x>
<y>507</y> <y>266</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>520</x> <x>520</x>
@ -2029,8 +1926,8 @@
<slot>search_keyword()</slot> <slot>search_keyword()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>730</x> <x>326</x>
<y>507</y> <y>266</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>688</x> <x>688</x>
@ -2045,8 +1942,8 @@
<slot>search_keyword()</slot> <slot>search_keyword()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>838</x> <x>326</x>
<y>505</y> <y>266</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>932</x> <x>932</x>
@ -2061,7 +1958,7 @@
<slot>hmi_cb_change()</slot> <slot>hmi_cb_change()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>806</x> <x>475</x>
<y>89</y> <y>89</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
@ -2077,7 +1974,7 @@
<slot>hmi_send()</slot> <slot>hmi_send()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>887</x> <x>335</x>
<y>89</y> <y>89</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
@ -2087,14 +1984,14 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>pushButton</sender> <sender>hmi_btn</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
<receiver>MainWindow</receiver> <receiver>MainWindow</receiver>
<slot>hmi_page()</slot> <slot>hmi_page()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>980</x> <x>326</x>
<y>85</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>744</x> <x>744</x>
@ -2103,14 +2000,14 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>pushButton_2</sender> <sender>md_btn</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
<receiver>MainWindow</receiver> <receiver>MainWindow</receiver>
<slot>md_page()</slot> <slot>md_page()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>980</x> <x>326</x>
<y>124</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>784</x> <x>784</x>
@ -2119,14 +2016,14 @@
</hints> </hints>
</connection> </connection>
<connection> <connection>
<sender>pushButton_3</sender> <sender>ec_btn</sender>
<signal>clicked()</signal> <signal>clicked()</signal>
<receiver>MainWindow</receiver> <receiver>MainWindow</receiver>
<slot>ec_page()</slot> <slot>ec_page()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>980</x> <x>326</x>
<y>163</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>969</x> <x>969</x>
@ -2141,8 +2038,8 @@
<slot>md_cb_change()</slot> <slot>md_cb_change()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>467</x> <x>466</x>
<y>81</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>612</x> <x>612</x>
@ -2157,8 +2054,8 @@
<slot>md_send()</slot> <slot>md_send()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>327</x> <x>326</x>
<y>81</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>795</x> <x>795</x>
@ -2173,8 +2070,8 @@
<slot>ec_send()</slot> <slot>ec_send()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>327</x> <x>326</x>
<y>81</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>652</x> <x>652</x>
@ -2189,7 +2086,7 @@
<slot>hmi_conn()</slot> <slot>hmi_conn()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>545</x> <x>335</x>
<y>89</y> <y>89</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
@ -2205,8 +2102,8 @@
<slot>md_conn()</slot> <slot>md_conn()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>327</x> <x>326</x>
<y>81</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>398</x> <x>398</x>
@ -2221,8 +2118,8 @@
<slot>ec_conn()</slot> <slot>ec_conn()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>327</x> <x>326</x>
<y>81</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>412</x> <x>412</x>
@ -2237,8 +2134,8 @@
<slot>check_interval()</slot> <slot>check_interval()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>844</x> <x>326</x>
<y>97</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>821</x> <x>821</x>
@ -2253,8 +2150,8 @@
<slot>ec_cb_change()</slot> <slot>ec_cb_change()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>467</x> <x>466</x>
<y>81</y> <y>80</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>540</x> <x>540</x>
@ -2269,8 +2166,8 @@
<slot>hmi_conn()</slot> <slot>hmi_conn()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>420</x> <x>385</x>
<y>79</y> <y>89</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>216</x> <x>216</x>
@ -2301,8 +2198,8 @@
<slot>show_item_content()</slot> <slot>show_item_content()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>441</x> <x>308</x>
<y>321</y> <y>230</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>205</x> <x>205</x>
@ -2310,6 +2207,70 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>cb_data_func</sender>
<signal>currentTextChanged(QString)</signal>
<receiver>MainWindow</receiver>
<slot>data_cb_change()</slot>
<hints>
<hint type="sourcelabel">
<x>273</x>
<y>61</y>
</hint>
<hint type="destinationlabel">
<x>208</x>
<y>7</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>file_browser()</slot>
<hints>
<hint type="sourcelabel">
<x>973</x>
<y>69</y>
</hint>
<hint type="destinationlabel">
<x>1002</x>
<y>19</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_2</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>file_browser()</slot>
<hints>
<hint type="sourcelabel">
<x>326</x>
<y>80</y>
</hint>
<hint type="destinationlabel">
<x>1004</x>
<y>56</y>
</hint>
</hints>
</connection>
<connection>
<sender>toolButton_3</sender>
<signal>clicked()</signal>
<receiver>MainWindow</receiver>
<slot>file_browser()</slot>
<hints>
<hint type="sourcelabel">
<x>326</x>
<y>80</y>
</hint>
<hint type="destinationlabel">
<x>1004</x>
<y>88</y>
</hint>
</hints>
</connection>
</connections> </connections>
<slots> <slots>
<slot>prog_start()</slot> <slot>prog_start()</slot>
@ -2338,5 +2299,6 @@
<slot>check_interval()</slot> <slot>check_interval()</slot>
<slot>switch_log_tab()</slot> <slot>switch_log_tab()</slot>
<slot>show_item_content()</slot> <slot>show_item_content()</slot>
<slot>data_cb_change()</slot>
</slots> </slots>
</ui> </ui>