界面优化,监控逻辑优化

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

244
aio.py
View File

@ -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'<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
elif network == "md":
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
elif network == "ec":
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
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'<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":
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":
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):
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'<img src="{clibs.PREFIX}/media/red.png" width="10" height="10" /><font face="consolas" size="4"><b>HR&nbsp;&nbsp;</b></font>')
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):
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'<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:
pass
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>')
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'<font color="black" face="consolas" size="4"><b>{vers_info}&nbsp;&nbsp;</b></font>')
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.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>')
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>')
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>')
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 == "":