575 lines
23 KiB
Python
575 lines
23 KiB
Python
from PyQt5.QtCore import QThread, pyqtSignal, QSize, QTimer
|
||
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QSizePolicy, QPushButton, QComboBox
|
||
from PyQt5.QtCore import Qt
|
||
from PyQt5.QtGui import QFont
|
||
|
||
import serial
|
||
import re
|
||
import time
|
||
import matplotlib.pyplot as plt
|
||
import os
|
||
import struct
|
||
import requests
|
||
import subprocess
|
||
|
||
from datetime import datetime
|
||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||
|
||
class UpdateWorker(QThread):
|
||
update_signal = pyqtSignal(bool, float, float, float, float)
|
||
data_received = pyqtSignal(str)
|
||
stop_signal = pyqtSignal()
|
||
mode_signal = pyqtSignal(int)
|
||
offset_signal = pyqtSignal(int)
|
||
apitimer_signal = pyqtSignal()
|
||
change_color_signal = pyqtSignal(str, str, str)
|
||
|
||
def __init__(self, serial_number, bench_id, port, block_id, main_app):
|
||
super().__init__()
|
||
print(f"id{bench_id}:\tport {port}")
|
||
print(f"id{bench_id}:\tserial {serial_number}")
|
||
self.block = self.add_block(serial_number, bench_id, port, block_id, main_app)
|
||
self.main_app = main_app # Store the reference to the BlockStackApp instance
|
||
self.serial_number = serial_number
|
||
self.bench_id = bench_id
|
||
self.port = port
|
||
self.block_id = block_id
|
||
self.running = True
|
||
self.position_value = 0.0
|
||
self.diameter_total = 0.0 # for average calculation
|
||
self.diameter_count = 0
|
||
self.diameter_value = 0.0
|
||
self.diameter_min = 0.0
|
||
self.diameter_max = 0.0
|
||
self.density = 1.0
|
||
self.prepare_flag = False
|
||
self.prepare_ok = False
|
||
self.reset_flag = False
|
||
self.ignore_stop = False
|
||
self.is_running = False
|
||
self.reset_data = False
|
||
self.homed = False
|
||
self.can_start = False
|
||
self.current_job = None
|
||
self.current_job = None
|
||
self.data_list = []
|
||
self.profile_data = {} # Dictionary to store profile data
|
||
|
||
# run at startup
|
||
self.update_profiles()
|
||
|
||
self.timer = QTimer()
|
||
self.timer.timeout.connect(self.query_api)
|
||
self.timer.start(3000)
|
||
|
||
def run(self):
|
||
try:
|
||
with serial.Serial(self.port, 1000000, timeout=1) as ser:
|
||
ser.write(b'a')
|
||
ser.write(b'F')
|
||
ser.write(b'i')
|
||
ser.write(b' ')
|
||
while self.running:
|
||
if ser.in_waiting > 0:
|
||
data = ser.readline().decode('utf-8').strip()
|
||
if data:
|
||
self.parse_data(data)
|
||
if self.reset_flag and self.prepare_flag:
|
||
if self.position_value > 100 and self.reset_flag:
|
||
self.ignore_stop = True
|
||
self.change_color_signal.emit(self.block_id, 'btn_prepare', "#5A5A5A")
|
||
ser.write(b'R')
|
||
self.prepare_flag = False
|
||
if ((1.65 < self.diameter_value) and (self.diameter_value < 1.85)) or ((2.70 < self.diameter_value) and (self.diameter_value < 2.95)):
|
||
self.prepare_ok = True
|
||
else:
|
||
self.prepare_ok = False
|
||
if self.prepare_ok:
|
||
self.change_color_signal.emit(self.block_id, 'btn_prepare', "#00A000")
|
||
self.change_color_signal.emit(self.block_id, 'btn_start', "#A0A000")
|
||
else:
|
||
self.change_color_signal.emit(self.block_id, 'btn_prepare', "#A00000")
|
||
else:
|
||
self.change_color_signal.emit(self.block_id, 'btn_prepare', "#0000FF")
|
||
else:
|
||
if data == '%STOP':
|
||
self.stop_running()
|
||
# if not self.ignore_stop:
|
||
# self.change_color_signal.emit(self.block_id, 'btn_start', "#A00000")
|
||
# self.is_running = False
|
||
# self.save_data_to_file()
|
||
# else:
|
||
# self.ignore_stop = False
|
||
elif data == '$NOTHOMED':
|
||
self.homed = False
|
||
self.change_color_signal.emit(self.block_id, 'btn_home', "#a0a000")
|
||
elif data == '$HOMED':
|
||
# print(f"id{self.bench_id} :\tHoming ok")
|
||
self.homed = True
|
||
self.change_color_signal.emit(self.block_id, 'btn_home', "#5a5a5a")
|
||
except serial.SerialException as e:
|
||
print(f"Error with port {self.port}: {e}")
|
||
|
||
def save_data_to_file(self):
|
||
# format:
|
||
#
|
||
# #bench: FDR1-proto0
|
||
# #date: 20250224_232750
|
||
# #spool: R587
|
||
# #material: Enky PP Ortho V1-2106 20251007-00 N°7
|
||
# d:1.730,dm:1.730,dM:1.730,p:0.000,s:0.0,m:1500.0000,q:3,ap:0/3598
|
||
# d:1.730,dm:1.730,dM:1.730,p:2.291,s:0.0,m:1504.5000,q:3,ap:0/3598
|
||
# d:1.750,dm:1.730,dM:1.750,p:6.021,s:0.0,m:1504.5000,q:3,ap:0/3598
|
||
# d:1.730,dm:1.730,dM:1.750,p:11.192,s:0.0,m:1504.5000,q:3,ap:0/3598
|
||
# d:1.730,dm:1.730,dM:1.750,p:17.999,s:0.0,m:1504.5000,q:3,ap:0/3598
|
||
# d:1.730,dm:1.730,dM:1.750,p:26.049,s:0.0,m:1504.5000,q:3,ap:0/3598
|
||
#
|
||
# [...]
|
||
#
|
||
# d:1.750,dm:1.690,dM:1.820,p:1614324.750,s:49.6,m:969.1023,q:2,ap:1180/3598
|
||
# d:1.820,dm:1.690,dM:1.820,p:1614324.250,s:1.1,m:972.0096,q:2,ap:1180/3598
|
||
# MOTOR DISABLED: FILAMENT OUT OF RANGE
|
||
# #end: 20250224_232750
|
||
|
||
|
||
print(f"id{self.bench_id}:\tsaving job: {self.current_job}")
|
||
|
||
spool, vendor, material, batch, description, startstamp = self.current_job
|
||
endstamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
|
||
|
||
outfilename = os.path.join("data", f"{spool}_{startstamp}.fslp")
|
||
|
||
|
||
with open(outfilename, "w") as outfile:
|
||
outfile.write(F"#bench: {self.serial_number} (#{self.bench_id})\n")
|
||
outfile.write(F"#date: {startstamp}\n")
|
||
outfile.write(F"#spool: {spool}\n")
|
||
outfile.write(F"#material: {vendor} {material} {batch} {description}\n")
|
||
|
||
for ts, position, diameter in self.data_list:
|
||
outfile.write(f"t:{ts},d:{diameter},p:{position}\n")
|
||
|
||
outfile.write(F"#end: {endstamp}\n")
|
||
|
||
subprocess.run(["gzip", "-9", outfilename])
|
||
|
||
files = {'fsl': open(outfilename+'.gz', 'rb')}
|
||
url = f"http://462filament/api.php?data=upload"
|
||
|
||
r = requests.post(url, files=files)
|
||
|
||
def parse_data(self, data):
|
||
|
||
match = re.match(r"^[#d]:(-?[\d\.]+),p:(-?[\d\.]+)$", data)
|
||
if match:
|
||
self.diameter_value = float(match.group(1))
|
||
self.position_value = float(match.group(2))
|
||
self.update_signal.emit(self.is_running, self.diameter_value, self.position_value, self.diameter_min, self.diameter_max)
|
||
self.reset_flag = True
|
||
|
||
offset_match = re.match(r"^#h:(\d+)", data)
|
||
if offset_match:
|
||
home_offset = int(offset_match.group(1))
|
||
# print(f"id{self.bench_id}:\tOffset: {home_offset:.2f}")
|
||
self.block.btn_offset.setText(f"Offset: {home_offset:.2f}")
|
||
|
||
mode_match = re.match(r"^#o:(\d+)", data)
|
||
if mode_match:
|
||
mode = int(mode_match.group(1))
|
||
self.mode_signal.emit(mode)
|
||
match mode:
|
||
case 1:
|
||
self.change_color_signal.emit(self.block_id, 'btn_go_left', "#0000A0")
|
||
self.change_color_signal.emit(self.block_id, 'btn_go_right', "#5a5a5a")
|
||
self.change_color_signal.emit(self.block_id, 'btn_reset', "#5a5a5a")
|
||
case 2:
|
||
self.change_color_signal.emit(self.block_id, 'btn_go_left', "#5a5a5a")
|
||
self.change_color_signal.emit(self.block_id, 'btn_go_right', "#0000A0")
|
||
self.change_color_signal.emit(self.block_id, 'btn_reset', "#5a5a5a")
|
||
case 3:
|
||
self.change_color_signal.emit(self.block_id, 'btn_go_left', "#5a5a5a")
|
||
self.change_color_signal.emit(self.block_id, 'btn_go_right', "#5a5a5a")
|
||
self.change_color_signal.emit(self.block_id, 'btn_reset', "#00A0A0")
|
||
else:
|
||
self.mode_signal.emit(65535)
|
||
self.change_color_signal.emit(self.block_id, 'btn_go_left', "#5a5a5a")
|
||
self.change_color_signal.emit(self.block_id, 'btn_go_right', "#5a5a5a")
|
||
self.change_color_signal.emit(self.block_id, 'btn_reset', "#5A5A5A")
|
||
|
||
def send_command(self, command):
|
||
try:
|
||
with serial.Serial(self.port, 1000000, timeout=1) as ser:
|
||
ser.write(command.encode())
|
||
except serial.SerialException as e:
|
||
print(f"Could not send command to port {self.port}: {e}")
|
||
|
||
def int_to_two_bytes(self, value):
|
||
if not (0 <= value <= 0xFFFF):
|
||
raise ValueError("Value out of range for two bytes")
|
||
|
||
two_bytes = struct.pack('>H', value)
|
||
return two_bytes
|
||
|
||
def set_limits(self, left, right):
|
||
print(f"id{self.bench_id}:\tupdate limits to {left}+{right}")
|
||
try:
|
||
with serial.Serial(self.port, 1000000, timeout=1) as ser:
|
||
ser.write(b'\x04')
|
||
time.sleep(0.001)
|
||
ser.write(self.int_to_two_bytes(left))
|
||
time.sleep(0.003)
|
||
ser.write(self.int_to_two_bytes(right))
|
||
time.sleep(0.003)
|
||
ser.write(b'\x04')
|
||
time.sleep(0.001)
|
||
ser.write(b'\x00')
|
||
time.sleep(0.001)
|
||
except serial.SerialException as e:
|
||
print(f"Could not send command to port {self.port}: {e}")
|
||
|
||
def set_prepare(self, prepare):
|
||
self.position_value = 0
|
||
self.prepare_flag = True
|
||
self.reset_flag = False
|
||
|
||
def start_running(self):
|
||
if self.prepare_ok and self.can_start:
|
||
self.reset_data = True
|
||
self.is_running = True
|
||
|
||
self.current_job = (
|
||
self.api_job['spool'],
|
||
self.api_job['vendor'],
|
||
self.api_job['material'],
|
||
self.api_job['batch'],
|
||
self.api_job['description'],
|
||
datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
)
|
||
|
||
self.change_color_signal.emit(self.block_id, 'btn_start', "#00a000")
|
||
self.change_color_signal.emit(self.block_id, 'btn_prepare', "#5A5A5A")
|
||
|
||
self.send_command('S')
|
||
|
||
def stop_running(self):
|
||
if self.is_running:
|
||
self.send_command('R')
|
||
|
||
self.block.data_label.setText(
|
||
f"Job done, processing..."
|
||
)
|
||
|
||
# for position, diameter in self.data_list:
|
||
# print(f"{position} -> {diameter}")
|
||
|
||
self.change_color_signal.emit(self.block_id, 'btn_start', "#a00000")
|
||
self.change_color_signal.emit(self.block_id, 'btn_prepare', "#5A5A5A")
|
||
|
||
self.is_running = False
|
||
self.save_data_to_file()
|
||
self.prepare_ok = False
|
||
|
||
|
||
def clear_graph(self):
|
||
self.line.set_data([], [])
|
||
self.canvas.draw()
|
||
|
||
def add_block(self, serial_number, bench_id, port, block_id, main_app):
|
||
block_widget = QWidget()
|
||
block_layout = QHBoxLayout()
|
||
block_layout.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||
|
||
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)
|
||
|
||
monospaced_bold_font = QFont("unexistent", 10)
|
||
monospaced_bold_font.setStyleHint(QFont.Monospace)
|
||
monospaced_bold_font.setBold(True)
|
||
|
||
monospaced_italics_font = QFont("unexistent", 10)
|
||
monospaced_italics_font.setStyleHint(QFont.Monospace)
|
||
monospaced_italics_font.setItalic(True)
|
||
|
||
left_layout = QVBoxLayout()
|
||
data_label = QLabel("No API data")
|
||
data_label.setTextFormat(Qt.RichText)
|
||
data_label.setAlignment(Qt.AlignLeft | Qt.AlignTop)
|
||
bench_label = QLabel(f"Bench ID: {bench_id}")
|
||
bench_label.setToolTip(f"Serial number: {serial_number}\nCPU: Microchip PIC18F4431 @ 32 MHz\nPort: {port}\nBandwidth: 1 MBps\nPosition maxspd: 638 mm/s\nDiameter freq: ≈10.5 Hz")
|
||
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_bold_font)
|
||
avg_label = QLabel("2.0000")
|
||
avg_label.setFont(monospaced_font)
|
||
cur_label = QLabel("2.000 ")
|
||
cur_label.setFont(monospaced_bold_font)
|
||
len_label = QLabel("12345.00")
|
||
len_label.setFont(monospaced_font)
|
||
wht_label = QLabel("12.345 ")
|
||
wht_label.setFont(monospaced_italics_font)
|
||
min_label = QLabel("2.000 ")
|
||
min_label.setFont(monospaced_bold_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)
|
||
|
||
avg_label.setToolTip("<i>Average diameter</i> in <b>mm</b>")
|
||
max_label.setToolTip("<i>Maximum diameter</i> in <b>mm</b>")
|
||
cur_label.setToolTip("<i>Current diameter</i> in <b>mm</b>")
|
||
len_label.setToolTip("<i>Length</i> in <b>m</b>")
|
||
wht_label.setToolTip("<i>Estimated mass</i> in <b>kg</b>")
|
||
min_label.setToolTip("<i>Minimum diameter</i> in <b>mm</b>")
|
||
|
||
maxL_label.setToolTip("<i>Average diameter</i> in <b>mm</b>")
|
||
avgL_label.setToolTip("<i>Maximum diameter</i> in <b>mm</b>")
|
||
curL_label.setToolTip("<i>Current diameter</i> in <b>mm</b>")
|
||
lenL_label.setToolTip("<i>Length</i> in <b>m</b>")
|
||
whtL_label.setToolTip("<i>Estimated mass</i> in <b>kg</b>")
|
||
minL_label.setToolTip("<i>Minimum diameter</i> in <b>mm</b>")
|
||
|
||
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)
|
||
# center_layout.addWidget(graph_placeholder)
|
||
|
||
right_layout = QHBoxLayout()
|
||
right_layout_1 = QVBoxLayout()
|
||
right_layout_2 = QVBoxLayout()
|
||
right_layout_3 = QVBoxLayout()
|
||
|
||
btn_prepare = QPushButton("Prepare")
|
||
btn_prepare.clicked.connect(lambda: self.send_command('P'))
|
||
time.sleep(0.1)
|
||
btn_prepare.clicked.connect(lambda: self.set_prepare(True))
|
||
right_layout_1.addWidget(btn_prepare)
|
||
|
||
btn_start = QPushButton("Start")
|
||
btn_start.clicked.connect(self.start_running)
|
||
right_layout_1.addWidget(btn_start)
|
||
|
||
btn_reset = QPushButton("Reset/Zero")
|
||
btn_reset.clicked.connect(lambda: self.send_command('r'))
|
||
btn_reset.clicked.connect(lambda: self.change_color_signal.emit(self.block_id, 'btn_start', "#5A5A5A"))
|
||
right_layout_1.addWidget(btn_reset)
|
||
|
||
btn_stop = QPushButton("Stop")
|
||
btn_stop.clicked.connect(self.stop_running)
|
||
right_layout_1.addWidget(btn_stop)
|
||
|
||
btn_spare1 = QPushButton()
|
||
right_layout_1.addWidget(btn_spare1)
|
||
|
||
|
||
|
||
btn_sleep = QPushButton("Sleep")
|
||
btn_sleep.clicked.connect(lambda: self.send_command('a'))
|
||
right_layout_2.addWidget(btn_sleep)
|
||
|
||
btn_home = QPushButton("Home")
|
||
btn_home.clicked.connect(lambda: self.send_command(' '))
|
||
right_layout_2.addWidget(btn_home)
|
||
|
||
btn_go_left = QPushButton("Go Left")
|
||
btn_go_left.clicked.connect(lambda: self.send_command('1'))
|
||
right_layout_2.addWidget(btn_go_left)
|
||
|
||
btn_go_right = QPushButton("Go Right")
|
||
btn_go_right.clicked.connect(lambda: self.send_command('2'))
|
||
right_layout_2.addWidget(btn_go_right)
|
||
|
||
btn_offset = QPushButton()
|
||
right_layout_2.addWidget(btn_offset)
|
||
|
||
btn_down_left = QPushButton("Offset +")
|
||
btn_down_left.clicked.connect(lambda: self.send_command('b'))
|
||
right_layout_3.addWidget(btn_down_left)
|
||
|
||
btn_up_left = QPushButton("Offset -")
|
||
btn_up_left.clicked.connect(lambda: self.send_command('n'))
|
||
right_layout_3.addWidget(btn_up_left)
|
||
|
||
btn_save_offset = QPushButton("Save Offset")
|
||
btn_save_offset.clicked.connect(lambda: self.send_command('M'))
|
||
right_layout_3.addWidget(btn_save_offset)
|
||
|
||
|
||
|
||
dropd_profile = QComboBox()
|
||
|
||
dropd_profile.addItem("Select a profile...")
|
||
dropd_profile.model().item(0).setEnabled(False)
|
||
|
||
|
||
dropd_profile.currentIndexChanged.connect(self.on_profile_changed)
|
||
|
||
dropd_profile.setFixedWidth(120)
|
||
|
||
view = dropd_profile.view()
|
||
view.setMinimumWidth(350) # Set the minimum width of the dropdown list
|
||
|
||
right_layout_3.addWidget(dropd_profile)
|
||
|
||
btn_update_profiles = QPushButton("Reload profiles")
|
||
btn_update_profiles.clicked.connect(self.update_profiles)
|
||
right_layout_3.addWidget(btn_update_profiles)
|
||
|
||
|
||
right_layout.addLayout(right_layout_1)
|
||
right_layout.addLayout(right_layout_2)
|
||
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)
|
||
|
||
block_widget.setLayout(block_layout)
|
||
|
||
block_widget.btn_start = btn_start
|
||
block_widget.btn_home = btn_home
|
||
block_widget.btn_go_left = btn_go_left
|
||
block_widget.btn_go_right = btn_go_right
|
||
block_widget.btn_reset = btn_reset
|
||
block_widget.btn_prepare = btn_prepare
|
||
block_widget.data_label = data_label
|
||
block_widget.bench_label = bench_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
|
||
block_widget.btn_offset = btn_offset
|
||
block_widget.dropd_profile = dropd_profile
|
||
|
||
# Create a Matplotlib figure and canvas for the graph
|
||
plt.style.use('dark_background')
|
||
|
||
fig, ax = plt.subplots()
|
||
plt.subplots_adjust(left=-0.01, right=1, top=1.01, bottom=0)
|
||
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)
|
||
self.canvas = FigureCanvas(fig)
|
||
self.canvas.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Ignored)
|
||
center_layout.addWidget(self.canvas)
|
||
|
||
return block_widget
|
||
|
||
def on_profile_changed(self, index):
|
||
# Get the selected ID
|
||
selected_id = self.sender().itemData(index)
|
||
|
||
if selected_id in self.profile_data:
|
||
start_value = self.profile_data[selected_id]['start']
|
||
width_value = self.profile_data[selected_id]['width']
|
||
|
||
self.set_limits(start_value, width_value)
|
||
|
||
def update_profiles(self):
|
||
url = f"http://462filament/api.php?data=profiles"
|
||
try:
|
||
response = requests.get(url)
|
||
if response.status_code == 200:
|
||
profiles = response.json()
|
||
if profiles:
|
||
self.block.dropd_profile.clear()
|
||
self.block.dropd_profile.addItem("Select a profile...")
|
||
self.block.dropd_profile.model().item(0).setEnabled(False)
|
||
for profile in profiles:
|
||
profile_id = profile["id"]
|
||
profile_name = profile["show_name"]
|
||
start_value = int(profile["start"])
|
||
width_value = int(profile["width"])
|
||
self.block.dropd_profile.addItem(profile_name, profile_id)
|
||
self.profile_data[profile_id] = {'start': start_value, 'width': width_value}
|
||
except requests.RequestException as e:
|
||
print(f"Error making request to API: {e}")
|
||
return None
|
||
|
||
def query_api(self):
|
||
try:
|
||
url = f"http://462filament/api.php?data=bench&benchid={self.bench_id}"
|
||
response = requests.get(url)
|
||
response.raise_for_status() # Raise an exception for HTTP errors
|
||
api_job = response.json() # Parse the JSON response
|
||
|
||
self.api_job = api_job
|
||
|
||
if self.api_job is not None:
|
||
# print(f"id{self.bench_id}:\tgot job {api_job['spool']} from API")
|
||
self.block.data_label.setText(
|
||
f"Job/Spool: {api_job['spool']}<hr>"
|
||
f"Fabricant: {api_job['vendor']}<br>"
|
||
f"Matière: {api_job['material']}<br>"
|
||
f"Lot: {api_job['batch']}<br>"
|
||
f"Identifiant: {api_job['description']}<hr>"
|
||
f"ρ = {api_job['density']}<br>"
|
||
)
|
||
self.density = float(api_job['density'])
|
||
self.can_start = True
|
||
else:
|
||
# print(f"id{self.bench_id}:\tno job from API")
|
||
self.block.data_label.setText(
|
||
f"API responded with no job"
|
||
)
|
||
self.can_start = False
|
||
except requests.RequestException as e:
|
||
print(f"Error querying API: {e}")
|