From 73cf7cbf036b8f32720eb9b191256776f7b45fca Mon Sep 17 00:00:00 2001 From: Jonathan Roth Date: Tue, 8 Apr 2025 13:39:19 +0200 Subject: [PATCH] dev ok - before class split --- fdr1gui.py | 169 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 149 insertions(+), 20 deletions(-) diff --git a/fdr1gui.py b/fdr1gui.py index 96c703e..17984b6 100644 --- a/fdr1gui.py +++ b/fdr1gui.py @@ -5,25 +5,28 @@ import re import requests from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy, QPushButton) +from PyQt5.QtGui import QFont from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSize import time +import matplotlib.pyplot as plt +from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas class UpdateWorker(QThread): - update_signal = pyqtSignal(float, float, float, float) + update_signal = pyqtSignal(bool, float, float, float, float) data_received = pyqtSignal(str) stop_signal = pyqtSignal() not_homed_signal = pyqtSignal() mode_signal = pyqtSignal(int) - change_color_signal = pyqtSignal(str, str, str) # Signal to change button color with identifier + change_color_signal = pyqtSignal(str, str, str) def __init__(self, serial_number, bench_id, port, block_id): super().__init__() self.block = self.add_block(serial_number, bench_id, port, block_id) - + self.serial_number = serial_number self.bench_id = bench_id self.port = port - self.block_id = block_id # Unique identifier for the block + self.block_id = block_id self.running = True self.position_value = 0.0 self.diameter_value = 0.0 @@ -33,12 +36,13 @@ class UpdateWorker(QThread): self.prepare_ok = False self.reset_flag = False self.ignore_stop = False + self.is_running = False def run(self): try: with serial.Serial(self.port, 1000000, timeout=1) as ser: - ser.write(b'a') # Send the character 'F' - ser.write(b'F') # Send the character 'F + ser.write(b'a') + ser.write(b'F') self.change_color_signal.emit(self.block_id, 'btn_home', "#A0A000") while self.running: if ser.in_waiting > 0: @@ -64,8 +68,9 @@ class UpdateWorker(QThread): self.change_color_signal.emit(self.block_id, 'btn_prepare', "#0000FF") else: if data == '%STOP': - if not self.ignore_stop : + if not self.ignore_stop: self.change_color_signal.emit(self.block_id, 'btn_start', "#A00000") + self.is_running = False else: self.ignore_stop = False elif data == '$NOTHOMED': @@ -74,7 +79,6 @@ class UpdateWorker(QThread): print(f"Error with port {self.port}: {e}") def parse_data(self, data): - # Parse the data and update diameter_value and position_value match = re.match(r"[#d]:([\d.-]+),p:([\d.-]+)", data) if match: self.diameter_value = float(match.group(1)) @@ -83,10 +87,9 @@ class UpdateWorker(QThread): self.diameter_min = self.diameter_value if self.diameter_value > self.diameter_max: self.diameter_max = self.diameter_value - self.update_signal.emit(self.diameter_value, self.position_value, self.diameter_min, self.diameter_max) + self.update_signal.emit(self.is_running, self.diameter_value, self.position_value, self.diameter_min, self.diameter_max) self.reset_flag = True - # Parse mode and position data mode_match = re.match(r"#o:(\d+),l:(\d+),r:(\d+),c:(\d+)", data) if mode_match: mode = int(mode_match.group(1)) @@ -126,6 +129,17 @@ class UpdateWorker(QThread): self.diameter_min = self.diameter_value self.diameter_max = self.diameter_value + def start_running(self): + self.is_running = True + self.clear_graph() + + def stop_running(self): + self.is_running = False + + def clear_graph(self): + self.line.set_data([], []) + self.canvas.draw() + def add_block(self, serial_number, bench_id, port, block_id): block_widget = QWidget() block_layout = QHBoxLayout() @@ -133,14 +147,80 @@ class UpdateWorker(QThread): LABEL_SIZE = QSize(250, 20) BUTTON_SIZE = QSize(100, 25) + VALUE_SIZE = QSize(80, 25) + VALUEL_SIZE = QSize(25, 25) + + monospaced_font = QFont("unexistent", 10) + monospaced_font.setStyleHint(QFont.Monospace) left_layout = QVBoxLayout() - data_label = QLabel("---") + data_label = QLabel("No API data") + data_label.setAlignment(Qt.AlignLeft | Qt.AlignTop) bench_label = QLabel(f"Bench ID: {bench_id}") + bench_label.setAlignment(Qt.AlignCenter) bench_label.setFixedSize(LABEL_SIZE) left_layout.addWidget(bench_label) left_layout.addWidget(data_label) + left2_layout = QHBoxLayout() + left2L_layout = QVBoxLayout() + left2V_layout = QVBoxLayout() + max_label = QLabel("2.000 ") + max_label.setFont(monospaced_font) + avg_label = QLabel("2.0000") + avg_label.setFont(monospaced_font) + cur_label = QLabel("2.000 ") + cur_label.setFont(monospaced_font) + len_label = QLabel("12345.00") + len_label.setFont(monospaced_font) + wht_label = QLabel("12.345") + wht_label.setFont(monospaced_font) + min_label = QLabel("2.000 ") + min_label.setFont(monospaced_font) + maxL_label = QLabel("∨") + avgL_label = QLabel("⌀̄") + curL_label = QLabel("⌀") + lenL_label = QLabel("L") + whtL_label = QLabel("M") + minL_label = QLabel("∧") + avg_label.setAlignment(Qt.AlignRight) + max_label.setAlignment(Qt.AlignRight) + cur_label.setAlignment(Qt.AlignRight) + len_label.setAlignment(Qt.AlignRight) + wht_label.setAlignment(Qt.AlignRight) + min_label.setAlignment(Qt.AlignRight) + + max_label.setFixedSize(VALUE_SIZE) + avg_label.setFixedSize(VALUE_SIZE) + cur_label.setFixedSize(VALUE_SIZE) + len_label.setFixedSize(VALUE_SIZE) + wht_label.setFixedSize(VALUE_SIZE) + min_label.setFixedSize(VALUE_SIZE) + + maxL_label.setFixedSize(VALUEL_SIZE) + avgL_label.setFixedSize(VALUEL_SIZE) + curL_label.setFixedSize(VALUEL_SIZE) + lenL_label.setFixedSize(VALUEL_SIZE) + whtL_label.setFixedSize(VALUEL_SIZE) + minL_label.setFixedSize(VALUEL_SIZE) + + left2V_layout.addWidget(max_label) + left2V_layout.addWidget(avg_label) + left2V_layout.addWidget(cur_label) + left2V_layout.addWidget(len_label) + left2V_layout.addWidget(wht_label) + left2V_layout.addWidget(min_label) + + left2L_layout.addWidget(maxL_label) + left2L_layout.addWidget(avgL_label) + left2L_layout.addWidget(curL_label) + left2L_layout.addWidget(lenL_label) + left2L_layout.addWidget(whtL_label) + left2L_layout.addWidget(minL_label) + + left2_layout.addLayout(left2L_layout) + left2_layout.addLayout(left2V_layout) + center_layout = QVBoxLayout() graph_placeholder = QLabel("Graph Placeholder") graph_placeholder.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Ignored) @@ -157,10 +237,10 @@ class UpdateWorker(QThread): right_layout_1.addWidget(btn_prepare) btn_start = QPushButton("Start") - btn_start.clicked.connect(lambda: self.change_color_signal.emit(self.block_id, 'btn_start', "#00a000")) btn_start.clicked.connect(lambda: self.change_color_signal.emit(self.block_id, 'btn_prepare', "#5A5A5A")) btn_start.clicked.connect(self.reset_diameter_limits) + btn_start.clicked.connect(self.start_running) btn_start.clicked.connect(lambda: self.send_command('S')) right_layout_1.addWidget(btn_start) @@ -173,6 +253,7 @@ class UpdateWorker(QThread): btn_stop.clicked.connect(lambda: self.send_command('R')) btn_stop.clicked.connect(lambda: self.change_color_signal.emit(self.block_id, 'btn_start', "#a00000")) btn_stop.clicked.connect(lambda: self.change_color_signal.emit(self.block_id, 'btn_prepare', "#5A5A5A")) + btn_stop.clicked.connect(self.stop_running) right_layout_1.addWidget(btn_stop) btn_sleep = QPushButton("Sleep") @@ -215,6 +296,7 @@ class UpdateWorker(QThread): right_layout.addLayout(right_layout_3) block_layout.addLayout(left_layout) + block_layout.addLayout(left2_layout) block_layout.addLayout(center_layout) block_layout.addLayout(right_layout) @@ -228,10 +310,28 @@ class UpdateWorker(QThread): block_widget.btn_prepare = btn_prepare block_widget.data_label = data_label + block_widget.max_label = max_label + block_widget.avg_label = avg_label + block_widget.dia_label = cur_label + block_widget.len_label = len_label + block_widget.wht_label = wht_label + block_widget.min_label = min_label + + # Create a Matplotlib figure and canvas for the graph + plt.style.use('dark_background') + + fig, ax = plt.subplots() + plt.subplots_adjust(left=0.0, right=0.9995, top=1, bottom=0.005) + ax.set_facecolor('#3a3a3a') + ax.set_xticks([]) # Hide x-axis values + ax.set_frame_on(True) + # ax.set_ylabel('Diameter (mm)') # Show y-axis label + self.line, = ax.plot([], [], '#ff5000', linewidth=0.5) # Set line width to 0.5 + self.canvas = FigureCanvas(fig) + center_layout.addWidget(self.canvas) + return block_widget - - class BlockStackApp(QWidget): def __init__(self): super().__init__() @@ -368,14 +468,43 @@ class BlockStackApp(QWidget): # Handle the data received from the serial port print(f"Data received: {data}") - def update_block(self, diameter_value, position_value, diameter_min, diameter_max): + def update_block(self, is_running, diameter_value, position_value, diameter_min, diameter_max): # Update the block with diameter_value and position_value worker = self.sender() - worker.block.data_label.setText(f"⌀: {diameter_min:.3f} < ⌀̄ {diameter_value:.3f} mm < {diameter_max:.3f}\n" - f"L: {position_value/1000:.4f} m\n" - f"ρ: {1} g·cm¯³\n" - "\n- - -\n\n" - f"M: 0 g\nStop: at end") + diameter_avg = 2.0000 + est_wgh = 1234 + worker.block.min_label.setText(f"{diameter_min:.3f} ") + worker.block.max_label.setText(f"{diameter_max:.3f} ") + worker.block.dia_label.setText(f"{diameter_value:.3f} ") + worker.block.avg_label.setText(f"{diameter_avg:.4f}") + worker.block.len_label.setText(f"{20000/1000:.4f}") + worker.block.wht_label.setText(f"{est_wgh/1000:.3f} ") + worker.block.data_label.setText(f"No API data") + + # Update the graph with the new diameter value + if is_running: + self.update_graph(worker, diameter_value) + + def update_graph(self, worker, diameter_value): + # Update the graph with the new diameter value + x_data = worker.line.get_xdata() + y_data = worker.line.get_ydata() + x_data = list(x_data) + y_data = list(y_data) + + # Append new data point + x_data.append(len(x_data)) + y_data.append(diameter_value) + + # Update the line with the new data + worker.line.set_data(x_data, y_data) + + # Rescale the graph + worker.line.axes.relim() + worker.line.axes.autoscale_view() + + # Redraw the canvas + worker.canvas.draw() if __name__ == '__main__': app = QApplication(sys.argv)