From a9a6db23fd42e3caae31eaa633f4a248a70b8a28 Mon Sep 17 00:00:00 2001 From: gitea Date: Sun, 30 Mar 2025 12:27:57 +0800 Subject: [PATCH] =?UTF-8?q?=E7=95=8C=E9=9D=A2=E4=BC=98=E5=8C=96=EF=BC=8C?= =?UTF-8?q?=E7=9B=91=E6=8E=A7=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aio.py | 244 ++++++++++----- .../files/protocols/ec/close_reduced_mode.txt | 1 + .../files/protocols/ec/open_reduced_mode.txt | 1 + .../files/protocols/ec/soft_estop_state.txt | 1 + assets/files/protocols/ec/tcp_pos.txt | 1 - assets/files/protocols/ec/tcp_pose.txt | 1 + assets/media/green.png | Bin 0 -> 4498 bytes assets/media/red.png | Bin 0 -> 4484 bytes assets/qss/style.qss | 50 +++ codes/analysis/brake.py | 43 +-- codes/analysis/current.py | 43 +-- codes/analysis/iso.py | 32 +- codes/analysis/wavelogger.py | 21 +- codes/autotest/do_brake.py | 53 ++-- codes/autotest/do_current.py | 34 +-- codes/common/clibs.py | 65 ++-- codes/common/openapi.py | 140 +++------ codes/durable/factory_test.py | 34 +-- codes/ui/main_window.py | 118 ++++---- ui/main.ui | 286 ++++++++---------- 20 files changed, 574 insertions(+), 594 deletions(-) create mode 100644 assets/files/protocols/ec/close_reduced_mode.txt create mode 100644 assets/files/protocols/ec/open_reduced_mode.txt create mode 100644 assets/files/protocols/ec/soft_estop_state.txt delete mode 100644 assets/files/protocols/ec/tcp_pos.txt create mode 100644 assets/files/protocols/ec/tcp_pose.txt create mode 100644 assets/media/green.png create mode 100644 assets/media/red.png create mode 100644 assets/qss/style.qss diff --git a/aio.py b/aio.py index fff4f0b..82bd8aa 100644 --- a/aio.py +++ b/aio.py @@ -4,6 +4,7 @@ import os import re import sqlite3 import sys +import threading import time from urllib import request import os.path @@ -92,46 +93,43 @@ class MainWindow(main_window.Ui_MainWindow): def __init__(self): super(MainWindow, self).__init__() - self.close_on_net_error = None self.is_searching = False self.setupUi(self) - self.predoes() + self.pre_does() - def predoes(self): + def pre_does(self): # ========================= 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)) header = self.treew_log.header() for i in range(self.treew_log.columnCount()): 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 ========================= - self.setup_statusbar() - self.setWindowIcon(QIcon(f"{clibs.PREFIX}/media/icon.ico")) - # ========================= styleSheet ========================= - tws = [self.tw_funcs, self.tw_docs] - for tw in tws: - tw.setStyleSheet(""" - QTabBar::tab:selected { - background: #0078D4; - color: white; - border-radius: 4px; - } - QTabBar::tab:!selected { - background: #F0F0F0; - color: #333; - } - QTabWidget::pane { - border: 1px solid #CCCCCC; - } - """) - - # ============================↓↓↓debug↓↓↓============================ - # print(f"self.cb_data_func.currentIndex() = {self.cb_data_func.currentIndex()}") + logger_handler = clibs.LoggerHandler() + logger_handler.signal.connect(self.w2t) + clibs.logger = logger_handler.logger + # ========================= detection ========================= + self.detection_thread = StateDetection() + self.detection_thread.finished.connect(self.prog_done_detection) + self.detection_thread.start() + # ========================= debug ========================= + # for i in range(105): + # clibs.logger("DEBUG", "aio", "debug testing log for aio", color="gray") + # clibs.logger("INFO", "clibs", "info testing log for clibs", color="green") + # clibs.logger("WARNING", "iso", "warning testing log for aio", color="yellow") + # # clibs.logger("ERROR", "openapi", "error testing log for aio", color="red") def run_program_thread(self, prog, idx, prog_done, reserved): if idx != -98 and idx != -97: self.tw_docs.setCurrentIndex(0) - if idx != -99 and idx != -98: - prog.output.connect(self.w2t) self.t = QThread(self) 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) 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): self.tw_docs.setCurrentIndex(0) @@ -205,7 +209,6 @@ class MainWindow(main_window.Ui_MainWindow): idx_dict[tab_index].setText(dir_path) def curve_draw(self): - output = Signal(str, str) procs = self.get_checkbox_states() dir_path = self.le_durable_path.text() curve_map = { @@ -230,7 +233,7 @@ class MainWindow(main_window.Ui_MainWindow): self.w2t(f"需要选择至少一个功能,才能继续绘图......", "red") return - _, files = clibs.traversal_files(dir_path, output) + _, files = clibs.traversal_files(dir_path) csv_files = [] for file in files: 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 if end is None: 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}") records = clibs.cursor.fetchall() @@ -397,12 +400,12 @@ class MainWindow(main_window.Ui_MainWindow): line_number = self.treew_log.topLevelItemCount() 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 - end = int(start) + 100 - if int(start) <= len_records: + end = int(start) + 100 - 1 + if start <= len_records: clibs.cursor.execute(f"select * from logs where id between {start} and {end}") records = clibs.cursor.fetchall() 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 elif self.is_searching is True: @@ -688,25 +691,26 @@ class MainWindow(main_window.Ui_MainWindow): flag, result, ret, error, idx, network = results if flag is False: - ... - # self.w2t(f"{network.upper()}连接失败", "red") + self.w2t(f"{network.upper()}连接失败", "red") elif flag is True: clibs.status[network] = 1 if network == "hmi": self.btn_hmi_conn.setText("断开") + self.hmi_state.setText(f'HR  ') clibs.c_hr = result elif network == "md": self.btn_md_conn.setText("断开") + self.md_state.setText(f'MD  ') clibs.c_md = result elif network == "ec": self.btn_ec_conn.setText("断开") + self.ec_state.setText(f'EC  ') clibs.c_ec = result def prog_done_disconn(self, results): self.btn_hmi_conn.setDisabled(False) self.btn_md_conn.setDisabled(False) self.btn_ec_conn.setDisabled(False) - flag, result, ret, error, idx, network = results if flag is False: self.w2t(f"{network.upper()}断开连接失败", "red") @@ -714,13 +718,16 @@ class MainWindow(main_window.Ui_MainWindow): clibs.status[network] = 0 if network == "hmi": self.btn_hmi_conn.setText("连接") - clibs.c_hr = result + self.hmi_state.setText(f'HR  ') + clibs.c_hr = None elif network == "md": self.btn_md_conn.setText("连接") - clibs.c_md = result + self.md_state.setText(f'MD  ') + clibs.c_md = None elif network == "ec": self.btn_ec_conn.setText("连接") - clibs.c_ec = result + self.ec_state.setText(f'EC  ') + clibs.c_ec = None def hmi_conn(self): 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") 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.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): + 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.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): + 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.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): _, 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) for record in records: 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]) - self.pte_him_recv.appendPlainText(json.dumps(response, indent=4, separators=(",", ":"))) + self.pte_hmi_recv.appendPlainText(json.dumps(response, indent=4, separators=(",", ":"))) else: self.btn_hmi_send.setDisabled(False) @@ -852,9 +888,7 @@ class MainWindow(main_window.Ui_MainWindow): self.pte_ec_recv.clear() cmd = self.pte_ec_send.toPlainText().strip() try: - clibs.c_ec.s_string(cmd) - time.sleep(clibs.INTERVAL/2) - result = clibs.c_ec.r_string(cmd) + result = clibs.c_ec.sr_string(cmd) self.pte_ec_recv.appendPlainText(str(result)) except Exception as err: self.pte_ec_recv.appendPlainText(f"操作失败:{err}") @@ -862,7 +896,7 @@ class MainWindow(main_window.Ui_MainWindow): def hmi_cb_change(self): cmd = self.cb_hmi_cmd.currentText() 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: hmi_dict = json.load(f_hmi) 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() 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): try: interval = float(self.le_durable_interval.text()) @@ -894,13 +935,21 @@ class MainWindow(main_window.Ui_MainWindow): interval = clibs.CYCLE self.le_durable_interval.setText(str(interval)) - def state_detection(self): - while True: - time.sleep(clibs.INTERVAL) - if clibs.status["hmi"] == 0 and self.btn_hmi_conn.text() == "断开": - self.btn_hmi_conn.setText("连接") - elif clibs.status["hmi"] == 1 and self.btn_hmi_conn.text() == "连接": - self.btn_hmi_conn.setText("断开") + def prog_done_detection(self, finished): + if clibs.status["hmi"] == 0: + self.btn_hmi_conn.setText("连接") + self.hmi_state.setText(f'HR  ') + if clibs.status["md"] == 0: + self.btn_md_conn.setText("连接") + self.md_state.setText(f'MD  ') + if clibs.status["ec"] == 0: + self.btn_ec_conn.setText("连接") + self.ec_state.setText(f'EC  ') + # ============= Program running status ============= + if sum(clibs.running) == 1: + self.run_state.setText(f'BUSY') + else: + self.run_state.setText(f'IDLE') def closeEvent(self, event): 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) - _, logs = clibs.traversal_files(".", None) + _, logs = clibs.traversal_files(".") logs.sort() while len(logs) > 10: _ = 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: server_vers = f_server.read().strip() - update_label = QLabel() - version_label = QLabel() - self.statusbar.addWidget(version_label, 0) - self.statusbar.addPermanentWidget(update_label, 0) # 添加到右侧 + self.update_label, self.hmi_state, self.md_state, self.ec_state, self.run_state, self.version_label = QLabel(), ClickableLabel(), ClickableLabel(), ClickableLabel(), QLabel(), QLabel() + self.statusbar.addWidget(self.version_label, 0) + self.statusbar.addWidget(self.hmi_state, 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: - update_label.setText(f' 当前是最新版本,继续保持! ') + self.update_label.setText(f' Current is the latest version!') elif local_vers > server_vers: pass elif local_vers < server_vers: - update_label.setText(f''' v{server_vers.split('@')[0]}已经发布,尽快更新至最新版本! ''') + self.update_label.setText(f''' v{server_vers.split('@')[0]} has been released, update ASAP!''') - version_label.setText(f' {vers_info}') - update_label.setOpenExternalLinks(True) # 允许超链接在浏览器中打开 - # update_label.setAlignment(Qt.AlignmentFlag.AlignVCenter | Qt.AlignmentFlag.AlignRight) - update_label.setStyleSheet("border: none;") - update_label.setFrameShape(QFrame.Shape.NoFrame) - update_label.setFrameShadow(QFrame.Shadow.Plain) - self.close_on_net_error = False + self.version_label.setText(f'{vers_info}  ') + self.hmi_state.setText(f'HR  ') + self.md_state.setText(f'MD  ') + self.ec_state.setText(f'EC  ') + self.run_state.setText(f'IDLE') + self.update_label.setOpenExternalLinks(True) # 允许超链接在浏览器中打开 + + +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): @@ -994,13 +1087,16 @@ class SplashScreen(QApplication): self.splash.show() self.splash.showMessage("正在加载资源.....", Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignHCenter, Qt.GlobalColor.white) - self.t = QThread(self) - self.run = InitWork() - self.run.moveToThread(self.t) - self.run.completed.connect(self.prog_done) - self.action.connect(self.run.program) - self.t.start() - self.action.emit(1) + # self.t = QThread(self) + # self.run = InitWork() + # self.run.moveToThread(self.t) + # self.run.completed.connect(self.prog_done) + # self.action.connect(self.run.program) + # self.t.start() + # self.action.emit(1) + + # without validation of server version + self.prog_done("true") def prog_done(self, result): if result == "false" or result == "": diff --git a/assets/files/protocols/ec/close_reduced_mode.txt b/assets/files/protocols/ec/close_reduced_mode.txt new file mode 100644 index 0000000..4d55a3b --- /dev/null +++ b/assets/files/protocols/ec/close_reduced_mode.txt @@ -0,0 +1 @@ +close_reduced_mode \ No newline at end of file diff --git a/assets/files/protocols/ec/open_reduced_mode.txt b/assets/files/protocols/ec/open_reduced_mode.txt new file mode 100644 index 0000000..8ead59a --- /dev/null +++ b/assets/files/protocols/ec/open_reduced_mode.txt @@ -0,0 +1 @@ +open_reduced_mode \ No newline at end of file diff --git a/assets/files/protocols/ec/soft_estop_state.txt b/assets/files/protocols/ec/soft_estop_state.txt new file mode 100644 index 0000000..d68ce63 --- /dev/null +++ b/assets/files/protocols/ec/soft_estop_state.txt @@ -0,0 +1 @@ +soft_estop_state \ No newline at end of file diff --git a/assets/files/protocols/ec/tcp_pos.txt b/assets/files/protocols/ec/tcp_pos.txt deleted file mode 100644 index eb854fa..0000000 --- a/assets/files/protocols/ec/tcp_pos.txt +++ /dev/null @@ -1 +0,0 @@ -tcp_pos \ No newline at end of file diff --git a/assets/files/protocols/ec/tcp_pose.txt b/assets/files/protocols/ec/tcp_pose.txt new file mode 100644 index 0000000..d9858e9 --- /dev/null +++ b/assets/files/protocols/ec/tcp_pose.txt @@ -0,0 +1 @@ +tcp_pose \ No newline at end of file diff --git a/assets/media/green.png b/assets/media/green.png new file mode 100644 index 0000000000000000000000000000000000000000..2dfab9ea477cc9ae978e64ae54c24a2f736c2330 GIT binary patch literal 4498 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" msg += "命名规则:reachAA_loadBB_speedCC,AA/BB/CC 指的是臂展/负载/速度的比例
" msg += "规则解释:reach66_load100_speed33,表示 66% 臂展,100% 负载以及 33% 速度情况下的测试结果文件夹
" - 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: msg = f"数据目录 {rawdata_dir} 下数据文件个数错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件" - self.logger("ERROR", "brake", msg, "red", "WrongDataFile") + self.logger("ERROR", "brake", msg, "red") for rawdata_file in rawdata_files: if not rawdata_file.endswith(".data"): msg = f"数据文件 {rawdata_file} 后缀错误,每个数据目录下有且只能有三个以 .data 为后缀的数据文件" - self.logger("ERROR", "brake", msg, "red", "WrongDataFile") + self.logger("ERROR", "brake", msg, "red") result_files = [] for _ in [reach33_file, reach66_file, reach100_file]: @@ -77,7 +69,6 @@ class BrakeDataProcess(QThread): self.logger("INFO", "brake", "数据目录合规性检查结束,未发现问题......", "green") return config_file, result_files - @clibs.handle_exception def get_configs(self, config_file): try: 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] 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]) # 要处理的轴 rrs = [abs(_) for _ in configs["TRANSMISSION"]["REDUCTION_RATIO_NUMERATOR"]] # 减速比,rr for reduction ratio @@ -94,7 +85,7 @@ class BrakeDataProcess(QThread): av = avs[axis-1] return av, rr except Exception as Err: - self.logger("ERROR", "brake", f"无法打开 {config_file},或者使用了错误的机型配置文件,需检查
{Err}", "red", "OpenFileError") + self.logger("ERROR", "brake", f"无法打开 {config_file},或者使用了错误的机型配置文件,需检查
{Err}", "red") def now_doing_msg(self, docs, flag): 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} 数据已处理完毕") @staticmethod - @clibs.handle_exception def data2result(df, ws_result, row_start, row_end): data = [] 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=3).value = None - @clibs.handle_exception def get_row_range(self, data_file, df, conditions, av, rr): row_start, row_end = 0, 0 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 个点 break 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): 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 break 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) if abs(av_estop / av_max) < threshold: @@ -161,7 +150,6 @@ class BrakeDataProcess(QThread): return row_start, row_end @staticmethod - @clibs.handle_exception def get_shtname(conditions, count): # 33%负载_33%速度_1 - reach/load/speed load = conditions[1].removeprefix('load') @@ -170,7 +158,6 @@ class BrakeDataProcess(QThread): return result_sheet_name - @clibs.handle_exception def single_file_process(self, data_file, wb, count, av, rr): df = pandas.read_csv(data_file, sep='\t') 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) self.data2result(df, ws, row_start, row_end) - @clibs.handle_exception def data_process(self, result_file, rawdata_dirs, av, rr): filename = result_file.split("/")[-1] self.logger("INFO", "brake", f"正在打开文件 {filename},这可能需要一些时间......", "blue") try: wb = openpyxl.load_workbook(result_file) except Exception as Err: - self.logger("ERROR", "brake", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!
{Err}", "red", "CannotOpenFile") + self.logger("ERROR", "brake", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!
{Err}", "red") prefix = filename.split('_')[0] for rawdata_dir in rawdata_dirs: if rawdata_dir.split("/")[-1].split('_')[0] == prefix: 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): self.single_file_process(data_files[idx], wb, idx+1, av, rr) # threads = [ @@ -209,12 +195,11 @@ class BrakeDataProcess(QThread): wb.save(result_file) wb.close() - @clibs.handle_exception def processing(self): time_start = time.time() 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) av, rr = self.get_configs(config_file) diff --git a/codes/analysis/current.py b/codes/analysis/current.py index a88fcf1..bb8aebc 100644 --- a/codes/analysis/current.py +++ b/codes/analysis/current.py @@ -9,23 +9,15 @@ from codes.common import clibs class CurrentDataProcess(QThread): - output = Signal(str, str) - def __init__(self, dir_path, proc, /): super().__init__() self.dir_path = dir_path self.proc = proc 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): - _, data_files = clibs.traversal_files(self.dir_path, self.output) + _, data_files = clibs.traversal_files(self.dir_path) count, config_file = 0, None for data_file in data_files: filename = data_file.split("/")[-1] @@ -38,15 +30,14 @@ class CurrentDataProcess(QThread): if not re.match("^j[1-7].*\\.data$", filename): msg = f"不合规 {data_file}
" msg += "所有数据文件必须以 j[1-7]_ 开头,以 .data 结尾,比如j1_abcdef.data,请检查整改后重新运行" - self.logger("ERROR", "current", msg, "red", "FilenameIllegal") + self.logger("ERROR", "current", msg, "red") if count != 2: msg = "需要有一个机型配置文件\"*.cfg\",以及一个数据处理文件\"T_电机电流.xlsx\"表格,请检查整改后重新运行" - self.logger("ERROR", "current", msg, "red", "FilenameIllegal") + self.logger("ERROR", "current", msg, "red") return data_files, config_file - @clibs.handle_exception def current_max(self, data_files, rts): self.logger("INFO", "current", f"正在处理最大转矩值逻辑......") current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []} @@ -88,7 +79,6 @@ class CurrentDataProcess(QThread): self.logger("INFO", "current", f"最大转矩数据处理完毕......") return current - @clibs.handle_exception def current_avg(self, data_files, rts): self.logger("INFO", "current", f"正在处理平均转矩值逻辑......") current = {1: [], 2: [], 3: [], 4: [], 5: [], 6: []} @@ -131,7 +121,6 @@ class CurrentDataProcess(QThread): self.logger("INFO", "current", f"平均转矩数据处理完毕......") return current - @clibs.handle_exception def current_cycle(self, data_files, rrs, rts, params): result, hold, single, scenario, dur_time = None, [], [], [], 0 for data_file in data_files: @@ -150,8 +139,8 @@ class CurrentDataProcess(QThread): self.logger("INFO", "current", f"正在打开文件 {filename},这可能需要一些时间......", "blue") try: wb = openpyxl.load_workbook(result) - except Exception as Err: - self.logger("ERROR", "current", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!
{Err}", "red", "CannotOpenFile") + except Exception as err: + self.logger("ERROR", "current", f"{filename}文件打开失败,可能是文件已损坏,确认后重新执行!
{err}", "red") ws = wb["统计"] for idx in range(len(params)-1): @@ -175,7 +164,6 @@ class CurrentDataProcess(QThread): wb.save(result) 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): if flag == "lt": 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") return row_s, row_e else: - self.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red", "AnchorNotFound") + self.logger("ERROR", "current", f"{data_file} 数据有误,需要检查,无法找到第 {seq} 个有效点......", "red") elif flag == "gt": while row_e > end_point: 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") return row_s, row_e 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): count_1, count_2 = 0, 0 if flag == "start" or flag == "end": @@ -236,7 +223,6 @@ class CurrentDataProcess(QThread): self.logger("DEBUG", "current", f"{axis} 轴获取{places[flag]}数据 {row_e} 可能有异常,需关注!", "purple") return row_e - @clibs.handle_exception def p_single(self, wb, single, rrs): # 1. 先找到第一个速度为零的点,数据从后往前找,一开始就是零的情况不予考虑 # 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_end-row_middle+1}") 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 for row in range(row_start, row_end+1): @@ -340,7 +326,6 @@ class CurrentDataProcess(QThread): cell.value = None i += 1 - @clibs.handle_exception def p_scenario(self, wb, scenario, rrs, dur_time): self.logger("INFO", "current", f"本次处理的是电机电流场景数据,场景运动周期为 {dur_time}s", "blue") for data_file in scenario: @@ -359,7 +344,7 @@ class CurrentDataProcess(QThread): row_start = 3000 row_end = row_start + int(dur_time/cycle) 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 for row in range(row_start, row_end+1): @@ -383,7 +368,6 @@ class CurrentDataProcess(QThread): ws.cell((i//4)+2, 1).value = None i += 1 - @clibs.handle_exception def get_configs(self, config_file): try: 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_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 - except Exception as Err: - self.logger("ERROR", "current", f"get_config: 无法打开 {config_file},或获取配置文件参数错误 {Err}", "red", "OpenFileError") + except Exception as err: + self.logger("ERROR", "current", f"get_config: 无法打开 {config_file},或获取配置文件参数错误 {err}", "red") - @clibs.handle_exception def processing(self): time_start = time.time() clibs.running[self.idx] = 1 @@ -432,5 +415,5 @@ class CurrentDataProcess(QThread): self.logger("INFO", "current", "-"*60 + "
全部处理完毕
", "purple") 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) diff --git a/codes/analysis/iso.py b/codes/analysis/iso.py index a3b5a9c..258a3fc 100644 --- a/codes/analysis/iso.py +++ b/codes/analysis/iso.py @@ -7,20 +7,14 @@ from codes.common import clibs class IsoDataProcess(QThread): - output = Signal(str, str) - def __init__(self, dir_path, /): super().__init__() self.dir_path = dir_path self.idx = 2 + 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 p_iso(self, file, p_files, ws, tmpfile): + @staticmethod + def p_iso(file, p_files, ws, tmpfile): p_files.append(file) pdf = pdfplumber.open(file) @@ -79,7 +73,8 @@ class IsoDataProcess(QThread): pass 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) pdf = pdfplumber.open(file) @@ -112,7 +107,8 @@ class IsoDataProcess(QThread): pass 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) pdf = pdfplumber.open(file) @@ -146,9 +142,9 @@ class IsoDataProcess(QThread): pdf.close() 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: - self.logger("ERROR", "iso", f"init: 工作目录下不可以有文件夹!", "red", "InitFileError") + self.logger("ERROR", "iso", f"init: 工作目录下不可以有文件夹!", "red") for file in files: file = file.lower() @@ -161,7 +157,7 @@ class IsoDataProcess(QThread): elif file.endswith("iso.pdf"): pass else: - self.logger("ERROR", "iso", f"init: 工作目录下只允许有如下四个文件,不区分大小写,pdf文件最少有一个!
1. iso-results.xlsx
2. ISO.pdf
3. ISO-V100.pdf
4. ISO-V1000.pdf", "red", "InitFileError") + self.logger("ERROR", "iso", f"init: 工作目录下只允许有如下四个文件,不区分大小写,pdf文件最少有一个!
1. iso-results.xlsx
2. ISO.pdf
3. ISO-V100.pdf
4. ISO-V1000.pdf", "red") return files @@ -178,8 +174,8 @@ class IsoDataProcess(QThread): ws = wb.active for i in range(3, 50): ws.cell(row=i, column=7).value = None - except Exception as Err: - self.logger("ERROR", "iso", f"main: 无法打开文件 {filename}
{Err}", "red", "FileOpenError") + except Exception as err: + self.logger("ERROR", "iso", f"main: 无法打开文件 {filename}
{err}", "red") p_files = [] for file in files: @@ -204,11 +200,11 @@ class IsoDataProcess(QThread): wb.close() 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: os.remove(tmpfile) self.logger("INFO", "current-processing", "-" * 60 + "
全部处理完毕
", "purple") 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) diff --git a/codes/analysis/wavelogger.py b/codes/analysis/wavelogger.py index 1dc275e..ef3465d 100644 --- a/codes/analysis/wavelogger.py +++ b/codes/analysis/wavelogger.py @@ -8,18 +8,11 @@ from codes.common import clibs class WaveloggerDataProcess(QThread): - output = Signal(str, str) - def __init__(self, dir_path, /): super().__init__() self.dir_path = dir_path self.idx = 3 - - 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}") + self.logger = clibs.logger def find_point(self, bof, step, margin, threshold, pos, data_file, flag, df, row): # bof: backward or forward @@ -38,7 +31,7 @@ class WaveloggerDataProcess(QThread): break else: 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": row_target = row + margin # to end while loop in function `single_file_proc` elif flag == "lt": @@ -52,7 +45,7 @@ class WaveloggerDataProcess(QThread): break else: 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": row_target = row + margin # to end while loop in function `single_file_proc` return row_target @@ -85,11 +78,11 @@ class WaveloggerDataProcess(QThread): return row_end-row_middle, row_middle-row_start, row_end-row_start, df 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: 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 @@ -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() if value > 1: 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) count_i += 1 @@ -157,5 +150,5 @@ class WaveloggerDataProcess(QThread): self.logger("INFO", "wavelogger", "-" * 60 + "
全部处理完毕
", "purple") 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) diff --git a/codes/autotest/do_brake.py b/codes/autotest/do_brake.py index 4f3f8d0..36c0962 100644 --- a/codes/autotest/do_brake.py +++ b/codes/autotest/do_brake.py @@ -1,3 +1,4 @@ +import threading import time import os import paramiko @@ -9,27 +10,19 @@ from codes.common import clibs class DoBrakeTest(QThread): - output = Signal(str, str) - def __init__(self, dir_path, tool, /): super().__init__() self.dir_path = dir_path self.tool = tool self.idx = 4 - - 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}") + self.logger = clibs.logger def initialization(self, data_dirs, data_files): - @clibs.handle_exception def check_files(): msg = "初始路径下不允许有文件夹,只能存在如下五个文件,且文件为关闭状态,确认后重新运行!
" msg += "1. configs.xlsx
2. reach33/reach66/reach100_xxxx.xlsx
3. xxxx.zip" 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, [] for data_file in data_files: @@ -45,7 +38,7 @@ class DoBrakeTest(QThread): elif filename.endswith(".zip"): prj_file = data_file 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: os.mkdir(f"{self.dir_path}/j1") @@ -64,9 +57,8 @@ class DoBrakeTest(QThread): return config_file, prj_file, result_dirs else: - self.logger("ERROR", "do_brake", msg, "red", "InitFileError") + self.logger("ERROR", "do_brake", msg, "red") - @clibs.handle_exception def get_configs(): robot_type = None 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: configs = json.load(f_config) except Exception as Err: - self.logger("ERROR", "do_brake", f"无法打开 {local_file}
{Err}", "red", "OpenFileError") + self.logger("ERROR", "do_brake", f"无法打开 {local_file}
{Err}", "red") # 最大角速度,额定电流,减速比,额定转速 version = configs["VERSION"] @@ -97,7 +89,6 @@ class DoBrakeTest(QThread): self.logger("INFO", "do_brake", "数据目录合规性检查结束,未发现问题......", "green") 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): 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)) @@ -133,7 +124,7 @@ class DoBrakeTest(QThread): return "retry" else: clibs.count = 0 - self.logger("WARNING", "do_brake",f"尝试三次后仍无法获取正确数据,本次数据无效,继续执行...", "red") + self.logger("WARNING", "do_brake", f"尝试三次后仍无法获取正确数据,本次数据无效,继续执行...", "red") df1 = pandas.DataFrame.from_dict({"hw_joint_vel_feedback": d_vel}) df2 = pandas.DataFrame.from_dict({"device_servo_trq_feedback": d_trq}) @@ -143,7 +134,6 @@ class DoBrakeTest(QThread): df.to_csv(filename, sep="\t", index=False) @staticmethod - @clibs.handle_exception def change_curve_state(stat): if not stat: 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.set_params", display_pdo_params=display_pdo_params) - @clibs.handle_exception def run_rl(self, config_file, prj_file, result_dirs, avs): count, total, speed_target = 0, 63, 0 prj_name = ".".join(prj_file.split("/")[-1].split(".")[:-1]) @@ -172,7 +161,7 @@ class DoBrakeTest(QThread): elif pon == "negative": clibs.c_md.write_pon(0) 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) for condition in result_dirs: @@ -194,7 +183,7 @@ class DoBrakeTest(QThread): continue clibs.c_md.write_axis(axis) - self.logger("INFO", "brake", "-" * 90, "purple", flag="signal") + self.logger("INFO", "brake", "-" * 90, "purple") speed_max = 0 for rounds in range(1, 4): count += 1 @@ -207,7 +196,7 @@ class DoBrakeTest(QThread): # 1. 触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电 clibs.c_md.r_soft_estop(0) 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_clear_alarm() clibs.c_md.write_act(0) @@ -251,7 +240,7 @@ class DoBrakeTest(QThread): else: time.sleep(1) 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程序,最后清除相关记录 time.sleep(5) # 消除前 5s 的不稳定数据 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.handle_exception def get_speed_max(): _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") @@ -292,7 +280,7 @@ class DoBrakeTest(QThread): break 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_clear_alarm() clibs.c_md.write_act(0) @@ -310,7 +298,7 @@ class DoBrakeTest(QThread): else: time.sleep(2) 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): if clibs.c_md.read_ready_to_go() == 1: @@ -319,15 +307,14 @@ class DoBrakeTest(QThread): else: time.sleep(1) else: - self.logger("ERROR", "do_brake", "16s 内未收到机器人的运行信号,需要确认 RL 程序配置正确并正常执行...", "red", "ReadySignalTimeoutError") + self.logger("ERROR", "do_brake", "16s 内未收到机器人的运行信号,需要确认 RL 程序配置正确并正常执行...", "red") - @clibs.handle_exception def exec_brake(): flag, start, data, record = True, time.time(), None, None while flag: time.sleep(0.05) if time.time() - start > 20: - self.logger("ERROR", "do_brake", "20s 内未触发急停,需排查......", "red", "BrakeTimeoutError") + self.logger("ERROR", "do_brake", "20s 内未触发急停,需排查......", "red") try: clibs.lock.acquire(True) @@ -344,7 +331,7 @@ class DoBrakeTest(QThread): speed_moment = clibs.RADIAN * sum(item["value"]) / len(item["value"]) if abs(speed_moment) > speed_max - 2: 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 flag = False break @@ -364,14 +351,16 @@ class DoBrakeTest(QThread): msg = f"
{self.tool.removeprefix('tool')}%负载的制动性能测试执行完毕,如需采集其他负载,须切换负载类型,并更换其他负载,重新执行" self.logger("INFO", "do_brake", msg, "green") - @clibs.handle_exception def processing(self): time_start = time.time() clibs.running[self.idx] = 1 if clibs.status["hmi"] != 1 or clibs.status["md"] != 1 or clibs.status["ec"] != 1: - self.logger("ERROR", "do_brake", "processing: 需要在网络设置中连接HMI,Modbus通信以及外部通信!", "red", "NetworkError") + self.logger("ERROR", "do_brake", "processing: 需要在网络设置中连接HMI,Modbus通信以及外部通信!", "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) clibs.c_pd.push_prj_to_server(prj_file) self.run_rl(config_file, prj_file, result_dirs, avs) diff --git a/codes/autotest/do_current.py b/codes/autotest/do_current.py index d95ebc4..988ef38 100644 --- a/codes/autotest/do_current.py +++ b/codes/autotest/do_current.py @@ -8,27 +8,19 @@ from codes.common import clibs class DoCurrentTest(QThread): - output = Signal(str, str) - def __init__(self, dir_path, tool, /): super().__init__() self.dir_path = dir_path self.tool = tool self.idx = 5 - - 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}") + self.logger = clibs.logger def initialization(self, data_dirs, data_files): - @clibs.handle_exception def check_files(): msg = "初始路径下不允许有文件夹,初始路径下只能存在如下两个文件,且文件为关闭状态,确认后重新运行!
" msg += "1. T_电机电流.xlsx
2. xxxx.zip" 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 for data_file in data_files: @@ -39,10 +31,10 @@ class DoCurrentTest(QThread): count += 1 prj_file = data_file else: - self.logger("ERROR", "do_current", msg, "red", "InitFileError") + self.logger("ERROR", "do_current", msg, "red") if count != 2: - self.logger("ERROR", "do_current", msg, "red", "InitFileError") + self.logger("ERROR", "do_current", msg, "red") if self.tool == "tool100": os.mkdir(f"{self.dir_path}/single") @@ -52,11 +44,10 @@ class DoCurrentTest(QThread): elif self.tool == "inertia": os.mkdir(f"{self.dir_path}/inertia") else: - self.logger("ERROR", "do_current", "负载选择错误,电机电流测试只能选择 tool100/inertia 规格!", "red", "LoadSelectError") + self.logger("ERROR", "do_current", "负载选择错误,电机电流测试只能选择 tool100/inertia 规格!", "red") return prj_file - @clibs.handle_exception def get_configs(): robot_type = None msg_id = clibs.c_hr.execution("controller.get_params") @@ -74,7 +65,6 @@ class DoCurrentTest(QThread): self.logger("INFO", "do_current", "数据目录合规性检查结束,未发现问题......", "green") return _prj_file - @clibs.handle_exception def single_axis_proc(self, records, number): text = "single" if number < 6 else "hold" 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" df.to_csv(filename, sep="\t", index=False) - @clibs.handle_exception def scenario_proc(self, records, number, scenario_time): d_vel, d_trq, d_sensor, d_trans = [[], [], [], [], [], []], [[], [], [], [], [], []], [[], [], [], [], [], []], [[], [], [], [], [], []] 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" df.to_csv(filename, sep="\t", index=False) - @clibs.handle_exception def gen_result_file(self, number, start_time, end_time, scenario_time): - @clibs.handle_exception def get_records(): 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)) @@ -152,14 +139,12 @@ class DoCurrentTest(QThread): t.start() @staticmethod - @clibs.handle_exception def change_curve_state(stat): 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)] 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.handle_exception def run_rl(self, prj_file): prj_name = ".".join(prj_file.split("/")[-1].split(".")[:-1]) c_regular = [ @@ -235,7 +220,7 @@ class DoCurrentTest(QThread): else: time.sleep(1) if (time.time() - t_start) > 15: - self.logger("ERROR", "do_current", "15s 内未收到机器人的运行信号,需要确认RL程序和工具通信是否正常执行...", "red", "ReadySignalTimeoutError") + self.logger("ERROR", "do_current", "15s 内未收到机器人的运行信号,需要确认RL程序和工具通信是否正常执行...", "red") # 4. 执行采集 time.sleep(10) # 消除前 10s 的不稳定数据 @@ -256,7 +241,7 @@ class DoCurrentTest(QThread): else: time.sleep(1) 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) # 5.停止程序运行,保留数据并处理输出 @@ -271,14 +256,13 @@ class DoCurrentTest(QThread): elif self.tool == "inertia": self.logger("INFO", "do_current", "惯量负载电机电流采集完毕,如需采集单轴/场景/保持电机电流,须切换负载类型,并更换偏置负载,重新执行", "green") - @clibs.handle_exception def processing(self): time_start = time.time() clibs.running[self.idx] = 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) clibs.c_pd.push_prj_to_server(prj_file) self.run_rl(prj_file) diff --git a/codes/common/clibs.py b/codes/common/clibs.py index fc690fe..9a341da 100644 --- a/codes/common/clibs.py +++ b/codes/common/clibs.py @@ -2,14 +2,14 @@ import os import os.path import threading 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): - logger("ERROR", "clibs", f"数据文件夹{dir_path}不存在,请确认后重试......", "red", signal=signal) + logger("ERROR", "clibs", f"数据文件夹{dir_path}不存在,请确认后重试......", color="red") else: dirs, files = [], [] for item in os.scandir(dir_path): @@ -56,33 +56,42 @@ def db_lock(func): return wrapper -@db_lock -def logger(level, module, content, color="black", flag="both", signal=""): - global cursor - if "move.monitor" in content: - return +class LoggerHandler(QThread): + signal = Signal(str, str) - if flag == "signal": - signal.emit(content, color) - elif flag == "cursor": - cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level, module, content)) - elif flag == "both": - signal.emit(content, color) - cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level, module, content)) + def __init__(self, /): + super().__init__() + + @db_lock + def logger(self, level, module, content, color="black", flag="both"): + global cursor + if "move.monitor" in content: + return + + if level.upper() == "DEBUG": + flag = "cursor" + + if flag == "signal": + self.signal.emit(content, color) + elif flag == "cursor": + cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level, module, content)) + elif flag == "both": + self.signal.emit(content, color) + cursor.execute(f"INSERT INTO logs (level, module, content) VALUES (?, ?, ?)", (level, module, content)) + + if level.upper() == "ERROR": + raise Exception() -def handle_exception(func): - 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 +def running_detection(idx): + while True: + time.sleep(INTERVAL*2) + if not running[idx]: + raise Exception("") -PREFIX = "resources/assets" # for pyinstaller -# PREFIX = "assets" # for local testing +# PREFIX = "resources/assets" # for pyinstaller +PREFIX = "assets" # for local testing log_path = f"{PREFIX}/logs" lock = threading.Lock() 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 username, password = "luoshi", "luoshi2019" 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} c_joint_vel, c_servo_trq, c_sensor_trq, c_estimate_trans_trq, c_safety_estop = 1, 2, 3, 4, 3 # 各个指标所在列 diff --git a/codes/common/openapi.py b/codes/common/openapi.py index c6003b9..b329791 100644 --- a/codes/common/openapi.py +++ b/codes/common/openapi.py @@ -16,12 +16,12 @@ from codes.common import clibs class ModbusRequest(QThread): - output = Signal(str, str) - def __init__(self, ip, port, /): super().__init__() self.ip = ip self.port = port + self.c = None + self.logger = clibs.logger def net_conn(self): self.logger("INFO", "openapi", f"Modbus 正在连接中,需要配置设备,这可能需要一点时间......", "blue") @@ -30,21 +30,11 @@ class ModbusRequest(QThread): if self.c.connect(): self.logger("INFO", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) success!", "green") else: - self.logger("ERROR", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) failed!", "red", "MdConnFailed") - - 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}") + self.logger("ERROR", "openapi", f"Modbus connection({clibs.ip_addr}:{clibs.modbus_port}) failed!", "red") def close(self): - if self.c.connect(): - try: - self.c.close() - self.logger("INFO", "openapi", f"modbus: 关闭 Modbus 连接成功", "green") - except Exception as err: - self.logger("ERROR", "openapi", f"modbus: 关闭 Modbus 连接失败:{err}", "red", "MdCloseFailed") + self.c.close() + self.logger("INFO", "openapi", f"modbus: 关闭 Modbus 连接成功", "green") def __reg_high_pulse(self, addr: int) -> None: self.c.write_register(addr, 0) @@ -344,7 +334,6 @@ class HmiRequest(QThread): self.__port = port self.__port_xs = port_xs self.__close_hmi = False - self.__is_connected = False self.__index = 0 self.__previous_data = b"" self.__valid_data_length = 0 @@ -357,12 +346,10 @@ class HmiRequest(QThread): self.__half_pkg_flag = False self.__is_first_frame = True self.__is_debug = True + self.logger = clibs.logger def net_conn(self): 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.daemon = True self.__t_unpackage.start() @@ -370,30 +357,13 @@ class HmiRequest(QThread): self.__t_unpackage_xs.daemon = True 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): - if self.__is_connected: - try: - self.__is_connected = False - time.sleep(clibs.INTERVAL/2) - self.c.close() - self.c_xs.close() - clibs.status["hmi"] = 0 - self.logger("INFO", "openapi", f"hmi: 关闭 Socket 连接成功", "green") - except Exception as err: - self.logger("ERROR", "openapi", f"hmi: 关闭 Socket 连接失败 {err}", "red", "HmiCloseFailed") + self.c.close() + self.c_xs.close() + self.logger("INFO", "openapi", f"hmi: 关闭 Socket 连接成功", "green") def __socket_conn(self): - self.close() + # self.close() try: self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.c.settimeout(clibs.INTERVAL*5) @@ -405,16 +375,11 @@ class HmiRequest(QThread): state = None for i in range(3): _ = self.execution("controller.heart") - time.sleep(clibs.INTERVAL/2) - self.__is_connected = True + time.sleep(clibs.INTERVAL/4) + clibs.status["hmi"] = 1 self.logger("INFO", "openapi", "hmi: HMI connection success...", "green") - except Exception as err: - self.logger("ERROR", "openapi", f"hmi: HMI connection timeout...", "red", "HmiConnTimeout") - - def __heartbeat(self): - while self.__is_connected: - self.execution("controller.heart") - time.sleep(clibs.INTERVAL*2) + except Exception: + self.logger("ERROR", "openapi", f"hmi: HMI connection failed...", "red") @staticmethod def package(cmd): @@ -439,13 +404,13 @@ class HmiRequest(QThread): try: sel = selectors.DefaultSelector() sel.register(sock, selectors.EVENT_READ, to_read) - while self.__is_connected: + while clibs.status["hmi"]: events = sel.select() for key, mask in events: callback = key.data callback(key.fileobj, mask) - except Exception as Err: - self.logger("DEBUG", "openapi", f"hmi: 老协议解包报错 {Err}", "red", "UnpackageFailed") + except Exception as err: + self.logger("DEBUG", "openapi", f"hmi: 老协议解包报错 err = {err}") def __get_headers(self, index, data): if index + 8 < len(data): @@ -458,7 +423,7 @@ class HmiRequest(QThread): else: # print("hr-get_headers: 解包数据有误,需要确认!") # print(data) - self.logger("ERROR", "openapi", f"hmi: 解包数据有误,需要确认,最后一个数据包如下 {data}") + self.logger("ERROR", "openapi", f"hmi: 解包数据有误,需要确认,最后一个数据包如下 {data}", "red") else: self.__half_pkg = data[index:] self.__half_pkg_flag = True @@ -681,7 +646,7 @@ class HmiRequest(QThread): # if self.__valid_data_length < 0 or self.__leftovers > 1024: # print(f"data = {data}") # 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 def package_xs(cmd): @@ -701,13 +666,13 @@ class HmiRequest(QThread): sel = selectors.DefaultSelector() sel.register(sock, selectors.EVENT_READ, to_read) - while self.__is_connected: + while clibs.status["hmi"]: events = sel.select() for key, mask in events: callback = key.data callback(key.fileobj, mask) 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): char, response = "", self.__response_xs @@ -721,7 +686,6 @@ class HmiRequest(QThread): else: self.__response_xs = response - @clibs.handle_exception 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] t = ts.replace("T", " ") @@ -740,7 +704,7 @@ class HmiRequest(QThread): if flag is True: return records 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): req = None @@ -752,7 +716,7 @@ class HmiRequest(QThread): flag = req["p_type"] del req["p_type"] except Exception as err: - self.logger("ERROR", "openapi", f"hmi: 暂不支持 {command} 功能,或确认该功能存在... {err}", "red", "CommandNotSupport") + self.logger("ERROR", "openapi", f"hmi: 暂不支持 {command} 功能,或确认该功能存在...
err = {err}", "red") 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": @@ -768,17 +732,19 @@ class HmiRequest(QThread): cmd = json.dumps(req, separators=(",", ":")) try: self.c.send(self.package(cmd)) - time.sleep(clibs.INTERVAL/4) + time.sleep(clibs.INTERVAL/4) # 这里一定是要等几百毫秒的,避免多指令同一时间发送,导致xCore不响应 self.logger("DEBUG", "openapi", f"hmi: 老协议请求发送成功 {cmd}") 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: try: self.c_xs.send(self.package_xs(req)) time.sleep(clibs.INTERVAL/4) self.logger("DEBUG", "openapi", f"hmi: xService请求发送成功 {req}") - except Exception as Err: - self.logger("ERROR", "openapi", f"hr: xService请求发送失败 {req} 报错信息 {Err}", "red", "CommandSendFailed") + except Exception as err: + self.logger("ERROR", "openapi", f"hr: xService请求发送失败 {req} 报错信息 {err}", "red") return req["id"] @@ -796,7 +762,7 @@ class HmiRequest(QThread): case "off": self.execution("state.switch_motor_off") 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 """ @@ -810,7 +776,7 @@ class HmiRequest(QThread): case "manual": self.execution("state.switch_manual") 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 """ @@ -887,7 +853,7 @@ class HmiRequest(QThread): self.__sth_wrong("3min 内未能完成重新连接,需要查看后台控制器是否正常启动,或者 ip/port 是否正确") break for _ in range(3): - if not self.__is_connected: + if not clibs.status["hmi"]: break time.sleep(2) else: @@ -1517,7 +1483,7 @@ class HmiRequest(QThread): case "without": self.execution("state.set_tp_mode", tp_mode="without") 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 def get_tp_mode(self): # OK @@ -1772,8 +1738,6 @@ class HmiRequest(QThread): class ExternalCommunication(QThread): - output = Signal(str, str) - def __init__(self, ip, port, /): super().__init__() self.c = None @@ -1781,34 +1745,32 @@ class ExternalCommunication(QThread): self.port = int(port) self.suffix = "\r" self.exec_desc = " :--: 返回 true 表示执行成功,false 失败" - - 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}") + self.logger = clibs.logger 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) - # time.sleep(clibs.INTERVAL) + 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) 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.settimeout(clibs.INTERVAL*5) try: self.c.connect((self.ip, self.port)) self.logger("INFO", "openapi", f"ec: 外部通信连接成功...", "green") - return self.c + # return self.c except Exception as err: - self.logger("ERROR", "openapi", f"ec: 外部通信连接失败... {err}", "red", "EcConnFailed") + self.logger("ERROR", "openapi", f"ec: 外部通信连接失败... {err}", "red") def close(self): - if clibs.status["ec"]: - try: - self.c.close() - self.logger("INFO", "openapi", f"ec: 关闭外部通信连接成功", "green") - except Exception as err: - self.logger("ERROR", "openapi", f"ec: 关闭外部通信连接失败:{err}", "red", "EcCloseFailed") + self.c.close() + self.logger("INFO", "openapi", f"ec: 关闭外部通信连接成功", "green") + + @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): order = "".join([directive, self.suffix]) @@ -1820,7 +1782,7 @@ class ExternalCommunication(QThread): try: char = self.c.recv(1).decode(encoding="unicode_escape") 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]) return result @@ -2057,7 +2019,7 @@ class ExternalCommunication(QThread): def __exec_cmd(self, directive, description, more_desc=""): self.s_string(directive) - time.sleep(clibs.INTERVAL) + time.sleep(clibs.INTERVAL/2) result = self.r_string(directive).strip() self.logger("DEBUG", "openapi", f"ec: 执行{description}指令是 {directive},返回值为 {result}{more_desc}") return result @@ -2082,7 +2044,6 @@ class PreDos(object): print(f"predos: SSH 无法连接到 {self.ip}:{self.ssh_port},需检查网络连通性或者登录信息是否正确 {err}") raise Exception("SshConnFailed") - @clibs.handle_exception def push_prj_to_server(self, prj_file): # prj_file:本地工程完整路径 self.__ssh2server() @@ -2151,7 +2112,6 @@ class PreDos(object): class RobotInit(object): @staticmethod - @clibs.handle_exception def modbus_init(): clibs.c_pd = PreDos(clibs.ip_addr, clibs.ssh_port, clibs.username, clibs.password) # 推送配置文件 diff --git a/codes/durable/factory_test.py b/codes/durable/factory_test.py index 7b0e435..ef684c6 100644 --- a/codes/durable/factory_test.py +++ b/codes/durable/factory_test.py @@ -10,7 +10,6 @@ from codes.common import clibs class DoFactoryTest(QThread): - output = Signal(str, str) curve_map = { "周期内平均转矩": ["device_servo_trq_feedback", ], "周期内最大速度": ["hw_joint_vel_feedback", ], @@ -23,32 +22,25 @@ class DoFactoryTest(QThread): self.procs = procs self.idx = 6 self.curves = [] - - 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}") + self.logger = clibs.logger def initialization(self, data_dirs, data_files): - @clibs.handle_exception def check_files(): for proc_name, is_enabled in self.procs.items(): if is_enabled: self.curves.extend(self.curve_map[proc_name]) 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: - self.logger("ERROR", "factory", "初始路径下不允许有文件夹,且初始路径下只能存在一个工程文件 —— *.zip,确认后重新运行!", "red", "InitFileError") + self.logger("ERROR", "factory", "初始路径下不允许有文件夹,且初始路径下只能存在一个工程文件 —— *.zip,确认后重新运行!", "red") 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] - @clibs.handle_exception def get_configs(): robot_type, records = None, None 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: configs = json.load(f_config) except Exception as Err: - self.logger("ERROR", "factory", f"无法打开 {local_file}
{Err}", "red", "OpenFileError") + self.logger("ERROR", "factory", f"无法打开 {local_file}
{Err}", "red") # 最大角速度,额定电流,减速比,额定转速 version = configs["VERSION"] @@ -86,13 +78,11 @@ class DoFactoryTest(QThread): self.logger("INFO", "factory", "数据目录合规性检查结束,未发现问题......", "green") return params - @clibs.handle_exception def change_curve_state(self, stat): 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.set_params", display_pdo_params=display_pdo_params) - @clibs.handle_exception def run_rl(self, params): prj_file, interval = params["prj_file"], params["interval"] # 1. 关闭诊断曲线,触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电 @@ -123,7 +113,7 @@ class DoFactoryTest(QThread): break else: if (time.time() - t_start) > 15: - self.logger("ERROR", "factory", "15s 内未收到机器人的运行信号,需要确认RL程序编写正确并正常执行...", "red", "ReadySignalTimeoutError") + self.logger("ERROR", "factory", "15s 内未收到机器人的运行信号,需要确认RL程序编写正确并正常执行...", "red") else: time.sleep(clibs.INTERVAL) @@ -138,7 +128,7 @@ class DoFactoryTest(QThread): else: time.sleep(clibs.INTERVAL) 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. 准备数据保存文件 for proc_name, is_enabled in self.procs.items(): @@ -180,7 +170,6 @@ class DoFactoryTest(QThread): self.change_curve_state(False) self.logger("INFO", "factory", "后台数据清零完成,现在可以重新运行其他程序。", "green") - @clibs.handle_exception def gen_results(self, params, start_time, end_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)) @@ -193,7 +182,6 @@ class DoFactoryTest(QThread): self.data_proc(records, params) - @clibs.handle_exception def data_proc(self, records, params): for proc_name, is_enabled in self.procs.items(): if not is_enabled: @@ -210,7 +198,6 @@ class DoFactoryTest(QThread): t.daemon = True t.start() - @clibs.handle_exception def get_avg_trq(self, records, params, proc_name): d_trq, results = [[], [], [], [], [], []], [time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))] for record in records: @@ -231,7 +218,6 @@ class DoFactoryTest(QThread): csv_writer = csv.writer(f_csv) csv_writer.writerow(results) - @clibs.handle_exception 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()))] for record in records: @@ -255,7 +241,6 @@ class DoFactoryTest(QThread): @staticmethod def detect_db_size(): @clibs.db_lock - @clibs.handle_exception def release_memory(): line_number = 20000 leftover = 4000 # 200s @@ -272,18 +257,17 @@ class DoFactoryTest(QThread): release_memory() time.sleep(clibs.INTERVAL*10) - @clibs.handle_exception def processing(self): time_start = time.time() clibs.running[self.idx] = 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.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) params = self.initialization(data_dirs, data_files) clibs.c_pd.push_prj_to_server(params["prj_file"]) self.run_rl(params) diff --git a/codes/ui/main_window.py b/codes/ui/main_window.py index 2562ebf..13ac54b 100644 --- a/codes/ui/main_window.py +++ b/codes/ui/main_window.py @@ -19,15 +19,15 @@ from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QFormLayout, QFrame, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMainWindow, QPlainTextEdit, QPushButton, QScrollArea, QSizePolicy, QSpacerItem, QStackedWidget, - QStatusBar, QTabWidget, QTreeWidget, QTreeWidgetItem, - QVBoxLayout, QWidget) + QStatusBar, QTabWidget, QToolButton, QTreeWidget, + QTreeWidgetItem, QVBoxLayout, QWidget) class Ui_MainWindow(QMainWindow): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") MainWindow.setEnabled(True) - MainWindow.resize(1004, 560) + MainWindow.resize(1006, 568) sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) @@ -174,18 +174,15 @@ class Ui_MainWindow(QMainWindow): self.horizontalLayout.addWidget(self.le_data_path) - self.btn_data_open = QPushButton(self.tab_data) - self.btn_data_open.setObjectName(u"btn_data_open") - self.btn_data_open.setMaximumSize(QSize(30, 16777215)) - self.btn_data_open.setFont(font4) + self.toolButton = QToolButton(self.tab_data) + self.toolButton.setObjectName(u"toolButton") - self.horizontalLayout.addWidget(self.btn_data_open) + self.horizontalLayout.addWidget(self.toolButton) self.horizontalLayout.setStretch(0, 1) self.horizontalLayout.setStretch(1, 1) self.horizontalLayout.setStretch(2, 1) self.horizontalLayout.setStretch(3, 10) - self.horizontalLayout.setStretch(4, 1) self.verticalLayout.addLayout(self.horizontalLayout) @@ -235,18 +232,15 @@ class Ui_MainWindow(QMainWindow): self.hl_2_unit1.addWidget(self.le_unit_path) - self.btn_unit_open = QPushButton(self.tab_unit) - self.btn_unit_open.setObjectName(u"btn_unit_open") - self.btn_unit_open.setMaximumSize(QSize(30, 16777215)) - self.btn_unit_open.setFont(font4) + self.toolButton_2 = QToolButton(self.tab_unit) + self.toolButton_2.setObjectName(u"toolButton_2") - 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(1, 1) self.hl_2_unit1.setStretch(2, 1) self.hl_2_unit1.setStretch(3, 10) - self.hl_2_unit1.setStretch(4, 1) self.verticalLayout_2.addLayout(self.hl_2_unit1) @@ -287,7 +281,7 @@ class Ui_MainWindow(QMainWindow): self.sa_durable.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() 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.setObjectName(u"horizontalLayout_9") self.verticalLayout_5 = QVBoxLayout() @@ -343,13 +337,14 @@ class Ui_MainWindow(QMainWindow): self.horizontalLayout_6.addWidget(self.le_durable_path) - self.btn_durable_open = QPushButton(self.tab_durable) - self.btn_durable_open.setObjectName(u"btn_durable_open") - self.btn_durable_open.setMaximumSize(QSize(30, 16777215)) - self.btn_durable_open.setFont(font4) + self.toolButton_3 = QToolButton(self.tab_durable) + self.toolButton_3.setObjectName(u"toolButton_3") - 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) @@ -371,17 +366,8 @@ class Ui_MainWindow(QMainWindow): self.horizontalLayout_7.addWidget(self.le_durable_interval) - self.label_10 = QLabel(self.tab_durable) - self.label_10.setObjectName(u"label_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.horizontalLayout_7.setStretch(0, 1) + self.horizontalLayout_7.setStretch(1, 10) self.verticalLayout_6.addLayout(self.horizontalLayout_7) @@ -505,10 +491,10 @@ class Ui_MainWindow(QMainWindow): self.horizontalLayout_5.addWidget(self.pte_hmi_send) - self.pte_him_recv = QPlainTextEdit(self.page) - self.pte_him_recv.setObjectName(u"pte_him_recv") + self.pte_hmi_recv = QPlainTextEdit(self.page) + 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) @@ -746,23 +732,23 @@ class Ui_MainWindow(QMainWindow): self.verticalLayout_4 = QVBoxLayout() self.verticalLayout_4.setObjectName(u"verticalLayout_4") - self.pushButton = QPushButton(self.tab_network) - self.pushButton.setObjectName(u"pushButton") - self.pushButton.setFont(font5) + self.hmi_btn = QPushButton(self.tab_network) + self.hmi_btn.setObjectName(u"hmi_btn") + 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.pushButton_2.setObjectName(u"pushButton_2") - self.pushButton_2.setFont(font5) + self.md_btn = QPushButton(self.tab_network) + self.md_btn.setObjectName(u"md_btn") + 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.pushButton_3.setObjectName(u"pushButton_3") - self.pushButton_3.setFont(font5) + self.ec_btn = QPushButton(self.tab_network) + self.ec_btn.setObjectName(u"ec_btn") + 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) @@ -877,11 +863,11 @@ class Ui_MainWindow(QMainWindow): MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName(u"statusbar") - sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) - sizePolicy3.setHorizontalStretch(0) - sizePolicy3.setVerticalStretch(0) - sizePolicy3.setHeightForWidth(self.statusbar.sizePolicy().hasHeightForWidth()) - self.statusbar.setSizePolicy(sizePolicy3) + sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.statusbar.sizePolicy().hasHeightForWidth()) + self.statusbar.setSizePolicy(sizePolicy2) self.statusbar.setMinimumSize(QSize(0, 27)) self.statusbar.setStyleSheet(u"background-color: rgb(200, 200, 200);") MainWindow.setStatusBar(self.statusbar) @@ -890,11 +876,8 @@ class Ui_MainWindow(QMainWindow): self.btn_start.clicked.connect(MainWindow.prog_start) self.btn_stop.clicked.connect(MainWindow.prog_stop) 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.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_realtime.clicked.connect(MainWindow.realtime_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.cb_hmi_cmd.currentTextChanged.connect(MainWindow.hmi_cb_change) self.btn_hmi_send.clicked.connect(MainWindow.hmi_send) - self.pushButton.clicked.connect(MainWindow.hmi_page) - self.pushButton_2.clicked.connect(MainWindow.md_page) - self.pushButton_3.clicked.connect(MainWindow.ec_page) + self.hmi_btn.clicked.connect(MainWindow.hmi_page) + self.md_btn.clicked.connect(MainWindow.md_page) + self.ec_btn.clicked.connect(MainWindow.ec_page) self.cb_md_cmd.currentTextChanged.connect(MainWindow.md_cb_change) self.btn_md_send.clicked.connect(MainWindow.md_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.tw_docs.currentChanged.connect(MainWindow.switch_log_tab) 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.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.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.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)) @@ -952,19 +939,18 @@ class Ui_MainWindow(QMainWindow): self.cb_unit_tool.setItemText(3, QCoreApplication.translate("MainWindow", u"inertia", 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.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_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.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)) #if QT_CONFIG(whatsthis) self.le_durable_interval.setWhatsThis("") #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.label_10.setText("") 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.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(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(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(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(59, QCoreApplication.translate("MainWindow", u"hand_estop_state", None)) self.btn_ec_send.setText(QCoreApplication.translate("MainWindow", u"\u53d1\u9001", None)) - self.pushButton.setText(QCoreApplication.translate("MainWindow", u"HMI", None)) - self.pushButton_2.setText(QCoreApplication.translate("MainWindow", u"Modbus", None)) - self.pushButton_3.setText(QCoreApplication.translate("MainWindow", u"EC", None)) + self.hmi_btn.setText(QCoreApplication.translate("MainWindow", u"HMI", None)) + self.md_btn.setText(QCoreApplication.translate("MainWindow", u"Modbus", 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_docs.setTabText(self.tw_docs.indexOf(self.tab_output), QCoreApplication.translate("MainWindow", u"\u8f93\u51fa", None)) ___qtreewidgetitem = self.treew_log.headerItem() diff --git a/ui/main.ui b/ui/main.ui index bd94dde..0792226 100644 --- a/ui/main.ui +++ b/ui/main.ui @@ -9,8 +9,8 @@ 0 0 - 1004 - 563 + 1006 + 568 @@ -248,7 +248,7 @@ - + @@ -346,19 +346,7 @@ - - - - 30 - 16777215 - - - - - Consolas - 12 - - + ... @@ -387,7 +375,7 @@ - + @@ -483,19 +471,7 @@ - - - - 30 - 16777215 - - - - - Consolas - 12 - - + ... @@ -583,7 +559,7 @@ 0 0 - 212 + 213 78 @@ -645,7 +621,7 @@ - + @@ -679,19 +655,7 @@ - - - - 30 - 16777215 - - - - - Consolas - 12 - - + ... @@ -700,7 +664,7 @@ - + @@ -742,25 +706,6 @@ - - - - - 0 - 0 - - - - - 30 - 0 - - - - - - - @@ -977,7 +922,7 @@ - + @@ -1524,7 +1469,7 @@ - tcp_pos + tcp_pose @@ -1584,7 +1529,7 @@ - + Consolas @@ -1598,7 +1543,7 @@ - + Consolas @@ -1612,7 +1557,7 @@ - + Consolas @@ -1894,22 +1839,6 @@ - - btn_durable_open - clicked() - MainWindow - file_browser() - - - 964 - 69 - - - 990 - 97 - - - btn_draw clicked() @@ -1917,8 +1846,8 @@ curve_draw() - 692 - 136 + 326 + 80 701 @@ -1933,8 +1862,8 @@ durable_cb_change() - 566 - 135 + 326 + 80 546 @@ -1942,38 +1871,6 @@ - - btn_unit_open - clicked() - MainWindow - file_browser() - - - 981 - 78 - - - 974 - 181 - - - - - btn_data_open - clicked() - MainWindow - file_browser() - - - 964 - 73 - - - 941 - 180 - - - btn_docs_previous clicked() @@ -1981,8 +1878,8 @@ pre_page() - 408 - 507 + 326 + 266 307 @@ -1997,8 +1894,8 @@ realtime_page() - 489 - 507 + 326 + 266 435 @@ -2013,8 +1910,8 @@ next_page() - 570 - 507 + 326 + 266 520 @@ -2029,8 +1926,8 @@ search_keyword() - 730 - 507 + 326 + 266 688 @@ -2045,8 +1942,8 @@ search_keyword() - 838 - 505 + 326 + 266 932 @@ -2061,7 +1958,7 @@ hmi_cb_change() - 806 + 475 89 @@ -2077,7 +1974,7 @@ hmi_send() - 887 + 335 89 @@ -2087,14 +1984,14 @@ - pushButton + hmi_btn clicked() MainWindow hmi_page() - 980 - 85 + 326 + 80 744 @@ -2103,14 +2000,14 @@ - pushButton_2 + md_btn clicked() MainWindow md_page() - 980 - 124 + 326 + 80 784 @@ -2119,14 +2016,14 @@ - pushButton_3 + ec_btn clicked() MainWindow ec_page() - 980 - 163 + 326 + 80 969 @@ -2141,8 +2038,8 @@ md_cb_change() - 467 - 81 + 466 + 80 612 @@ -2157,8 +2054,8 @@ md_send() - 327 - 81 + 326 + 80 795 @@ -2173,8 +2070,8 @@ ec_send() - 327 - 81 + 326 + 80 652 @@ -2189,7 +2086,7 @@ hmi_conn() - 545 + 335 89 @@ -2205,8 +2102,8 @@ md_conn() - 327 - 81 + 326 + 80 398 @@ -2221,8 +2118,8 @@ ec_conn() - 327 - 81 + 326 + 80 412 @@ -2237,8 +2134,8 @@ check_interval() - 844 - 97 + 326 + 80 821 @@ -2253,8 +2150,8 @@ ec_cb_change() - 467 - 81 + 466 + 80 540 @@ -2269,8 +2166,8 @@ hmi_conn() - 420 - 79 + 385 + 89 216 @@ -2301,8 +2198,8 @@ show_item_content() - 441 - 321 + 308 + 230 205 @@ -2310,6 +2207,70 @@ + + cb_data_func + currentTextChanged(QString) + MainWindow + data_cb_change() + + + 273 + 61 + + + 208 + 7 + + + + + toolButton + clicked() + MainWindow + file_browser() + + + 973 + 69 + + + 1002 + 19 + + + + + toolButton_2 + clicked() + MainWindow + file_browser() + + + 326 + 80 + + + 1004 + 56 + + + + + toolButton_3 + clicked() + MainWindow + file_browser() + + + 326 + 80 + + + 1004 + 88 + + + prog_start() @@ -2338,5 +2299,6 @@ check_interval() switch_log_tab() show_item_content() + data_cb_change()