Merge remote-tracking branch 'origin/master'

This commit is contained in:
gg 2025-01-17 19:17:25 +01:00
commit 1353aa14e0
19 changed files with 524 additions and 36 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 KiB

View File

@ -18,6 +18,7 @@ barcode_recipe_selection: absent
; vision_saver: absent ; vision_saver: absent
; vision: absent ; vision: absent
; external_flush_blow: absent # EXTERNAL BOX CONTROLLING MULTI-CHANNEL TEST (IF PRESENT), BLOW-CLEANING AND EXTERNAL FLUSH ; external_flush_blow: absent # EXTERNAL BOX CONTROLLING MULTI-CHANNEL TEST (IF PRESENT), BLOW-CLEANING AND EXTERNAL FLUSH
;pipe_cutter: absent
[galaxy_camera] [galaxy_camera]
horizontal_resolution: 2448 horizontal_resolution: 2448

View File

@ -13,6 +13,7 @@ furness_controls: absent
barcode_recipe_selection : absent barcode_recipe_selection : absent
digital_io: absent # used only for instruction images digital_io: absent # used only for instruction images
leak_disabled: active #disable the tecna_t3 and furness_controls from starting by setting the tester-component to None leak_disabled: active #disable the tecna_t3 and furness_controls from starting by setting the tester-component to None
pipe_cutter: present
[archive_synchronizer] [archive_synchronizer]
@ -80,6 +81,13 @@ pressione_svuotamento: 100
canale_di_prova: 0 canale_di_prova: 0
n_componenti: 1 n_componenti: 1
tester_discharge_enable: yes tester_discharge_enable: yes
tagliatubi: x
lunghezza_corrugato: 100
diametro_corrugato:21
[autotest_leak] [autotest_leak]
enabled: false enabled: false
[pipe_cutter]
port: /dev/ttyUSB0
baudrate: 38600

View File

@ -13,6 +13,7 @@ from .usb_586x import USB_586x
from .rfid_pn532 import RFID_PN532 from .rfid_pn532 import RFID_PN532
from .furness_controls_leak_tester import FurnessControlsLeakTester from .furness_controls_leak_tester import FurnessControlsLeakTester
from .brother_label_printer import BrotherLabelPrinter from .brother_label_printer import BrotherLabelPrinter
from .pipe_cutter_component import PipeCutterComponent
if "--vision" in sys.argv: if "--vision" in sys.argv:
from .galaxy_camera import GalaxyCamera from .galaxy_camera import GalaxyCamera
from .neo_pixels import NeoPixels from .neo_pixels import NeoPixels

View File

@ -0,0 +1,86 @@
import logging
import time
from .modbus_component import ModbusComponent
class PipeCutterComponent(ModbusComponent):
def __init__(self, config=None, name="pipe_cutter", period=1, lazy=True, paused=False, threaded=True):
"""Initialize the Pipe Cutter Component."""
super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
self.log = logging.getLogger(self.name)
self.current_total_length = None
self.current_od_of_pipe = None
self.machine_status = None
def read_total_length(self):
"""Read the total length (Register 4X30)."""
try:
self.current_total_length = self.read(register_address=30, data_type="16bit_uint")
self.log.info(f"Total length (Register 4X30): {self.current_total_length}")
return self.current_total_length
except Exception as e:
self.log.error(f"Failed to read total length (Register 4X30): {e}")
raise
def read_od_of_pipe(self):
"""Read the OD of the pipe (Register 4X60)."""
try:
self.current_od_of_pipe = self.read(register_address=60, data_type="16bit_uint")
self.log.info(f"OD of the pipe (Register 4X60): {self.current_od_of_pipe}")
return self.current_od_of_pipe
except Exception as e:
self.log.error(f"Failed to read OD of the pipe (Register 4X60): {e}")
raise
def read_machine_status(self):
try:
self.machine_status = self.read(register_address=1,register=766 ,data_type="16bit_uint")
self.log.info(f"Machine status (Register 4X766): {self.machine_status}")
return self.machine_status
except Exception as e:
self.log.error(f"Failed to read machine status (Register 4X766): {e}")
raise
def write_total_length(self, value):
try:
self.write(register_address=1,register=30, value=value, data_type="16bit_uint")
self.log.info(f"Wrote total length (Register 4X30): {value}")
except Exception as e:
self.log.error(f"Failed to write total length (Register 4X30): {e}")
raise
def write_od_of_pipe(self, value):
try:
self.write(register_address=1,register=60, value=value, data_type="16bit_uint")
self.log.info(f"Wrote OD of pipe (Register 4X60): {value}")
except Exception as e:
self.log.error(f"Failed to write OD of pipe (Register 4X60): {e}")
raise
def write_bit_with_delay(self, register_address, bit_position, delay_ms):
"""
Set a specific bit in a Modbus register, wait for a specified time, and reset it.
:param register_address: The register address to write to.
:param bit_position: The bit position to modify (0-15).
:param delay_ms: The delay in milliseconds before resetting the bit to 0 .
"""
try:
# Step 1: Set the bit to 1
current_value = self.read(register_address, data_type="16bit_uint")
new_value = current_value | (1 << bit_position) # Set the bit
self.write(register_address, new_value, data_type="16bit_uint")
self.log.info(f"Set bit {bit_position} in register {register_address} to 1")
# Step 2: Wait for the specified delay
time.sleep(delay_ms / 1000) # Convert milliseconds to seconds
# Step 3: Reset the bit to 0
current_value = self.read(register_address, data_type="16bit_uint")
new_value = current_value & ~(1 << bit_position) # Clear the bit
self.write(register_address, new_value, data_type="16bit_uint")
self.log.info(f"Reset bit {bit_position} in register {register_address} to 0")
except Exception as e:
self.log.error(f"Failed to set and reset bit {bit_position} in register {register_address}: {e}")
raise

View File

@ -63,7 +63,12 @@ def read_steps(row, config, defaults=None, unsupported_steps=None):
"screws": { "screws": {
"quantity": row.get("viti", defaults["viti"]), "quantity": row.get("viti", defaults["viti"]),
}, },
"instruction": {}, # Empty placeholder for future extensions "instruction": {},
"pipe_cutter": {
"lenght": row.get("lunghezza_corrugato", defaults["lunghezza_corrugato"]),
"diameter": row.get("diametro_corrugato", defaults["diametro_corrugato"]),
},
# Empty placeholder for future extensions
"leak_1": { "leak_1": {
"pre_filling_time": safe_parse(row.get("tempo_pre_riempimento", defaults["tempo_pre_riempimento"])), "pre_filling_time": safe_parse(row.get("tempo_pre_riempimento", defaults["tempo_pre_riempimento"])),
"pre_filling_pressure": safe_parse( "pre_filling_pressure": safe_parse(
@ -228,6 +233,7 @@ def import_recipes(config, csv_path=None, defaults=None, unsupported_steps=None,
unsupported_steps or []), unsupported_steps or []),
"instruction_extra": len(row.get("istruzione_abilitata_extra", defaults[ "instruction_extra": len(row.get("istruzione_abilitata_extra", defaults[
"istruzione_abilitata_extra"])) and "instruction_extra" not in (unsupported_steps or []), "istruzione_abilitata_extra"])) and "instruction_extra" not in (unsupported_steps or []),
"pipe_cutter": len(row.get("tagliatubi", defaults["tagliatubi"])) and "pipe_cutter" not in (unsupported_steps or []),
"leak_1": len( "leak_1": len(
row.get("prova_tenuta_abilitata", defaults["prova_tenuta_abilitata"])) and "leak_1" not in ( row.get("prova_tenuta_abilitata", defaults["prova_tenuta_abilitata"])) and "leak_1" not in (
unsupported_steps or []), unsupported_steps or []),

View File

@ -69,7 +69,7 @@ try:
# IMPORT PROJECT ONLY AFTER SETTING UP SIGNAL, FAULTHANDLER AND LOGGING # IMPORT PROJECT ONLY AFTER SETTING UP SIGNAL, FAULTHANDLER AND LOGGING
from components import (ArchiveSynchronizer, Multicomp730424, from components import (ArchiveSynchronizer, Multicomp730424,
Os_Label_Printer, RemoteAPI, Os_Label_Printer, RemoteAPI,
TecnaMarpossProvasetT3, FurnessControlsLeakTester, TecnaScrewdriver, USB_586x, RFID_PN532,BrotherLabelPrinter) TecnaMarpossProvasetT3, FurnessControlsLeakTester, TecnaScrewdriver, USB_586x, RFID_PN532,BrotherLabelPrinter,PipeCutterComponent)
from lib.db import Users from lib.db import Users
from lib.helpers import ConfigReader from lib.helpers import ConfigReader
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
@ -115,6 +115,7 @@ try:
"digital_io": {"c": USB_586x, "k": {"paused": True}}, "digital_io": {"c": USB_586x, "k": {"paused": True}},
"digital_io_flush_blow": {"c": USB_586x, "k": {"paused": True}}, "digital_io_flush_blow": {"c": USB_586x, "k": {"paused": True}},
"fixture_id": {"c": RFID_PN532, "k": {"paused": False, "lazy": False}}, "fixture_id": {"c": RFID_PN532, "k": {"paused": False, "lazy": False}},
"pipe_cutter": {"c": PipeCutterComponent, "k": {"paused": False}},
} }
# VISION COMPONENT IS OPTIONAL AND DISABLED BY DEFAULT # VISION COMPONENT IS OPTIONAL AND DISABLED BY DEFAULT
if "--vision" in sys.argv: if "--vision" in sys.argv:

View File

@ -1,41 +1,64 @@
import serial import serial
from pymodbus.client.sync import ModbusSerialClient as ModbusClient from pymodbus.client import ModbusSerialClient as ModbusClient
from pymodbus.exceptions import ModbusIOException from pymodbus.exceptions import ModbusIOException
import logging
import time import time
def read_modbus_data(client, starting_register, register_count):
def read_register(client, register_address, count=1):
""" """
Reads data from the Modbus server. Reads data from the Modbus server.
:param client: An instance of ModbusClient :param client: An instance of ModbusClient
:param starting_register: The address of the register to start reading from :param register_address: The address of the register to read
:param register_count: Number of registers to read :param count: Number of registers to read
:return: List of register values or None if there was an error :return: List of register values or None if there was an error
""" """
try: try:
read_data = client.read_holding_registers(starting_register, count=register_count) result = client.read_holding_registers(register_address, count=count, slave=1)
if isinstance(read_data, ModbusIOException): if result.isError():
print("Error: ModbusIOException occurred during read operation.") print(f"Error reading register {register_address}: {result}")
return None return None
else: return result.registers
return read_data.registers
except Exception as e: except Exception as e:
print(f"Error: {e}") print(f"Error reading register {register_address}: {e}")
return None return None
def write_register(client, register_address, value):
"""
Writes data to a Modbus register.
:param client: An instance of ModbusClient
:param register_address: The address of the register to write
:param value: The value to write to the register
:return: True if the write was successful, False otherwise
"""
try:
result = client.write_register(register_address, value, slave=1)
if result.isError():
print(f"Error writing value {value} to register {register_address}: {result}")
return False
return True
except Exception as e:
print(f"Error writing value {value} to register {register_address}: {e}")
return False
def main(): def main():
# Modbus client configuration # Modbus client configuration
client = ModbusClient( client = ModbusClient(
method="rtu", method="rtu",
port="/dev/ttyUSB0", # Specify the correct port for your serial connection port="/dev/ttyUSB0", # Ensure the correct port for your setup
stopbits=serial.STOPBITS_ONE, stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS, bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE, parity=serial.PARITY_NONE,
baudrate=38400, baudrate=38400,
timeout=1, # Timeout in seconds timeout=1, # Timeout in seconds
strict=False strict=False,
slave=1
) )
# Attempt to connect to the Modbus server # Attempt to connect to the Modbus server
@ -45,24 +68,32 @@ def main():
print("Failed to connect to Modbus client.") print("Failed to connect to Modbus client.")
return return
# Starting the data read loop
try: try:
starting_register = 1 # Define the starting register address # Define the register address and value
register_count = 10 # Define the number of registers to read register_address = 30 # Address to read/write
write_value = 1100 # Value to write to the register
print("Starting data read loop...") # Step 1: Read the register value
while True: print(f"Reading register {register_address}...")
data = read_modbus_data(client, starting_register, register_count) read_data = read_register(client, register_address)
if data: if read_data is not None:
# Print read data print(f"Register {register_address} value before write: {read_data[0]}")
for i, value in enumerate(data):
print(f"Register {starting_register + i}: {value}") # Step 2: Write a value to the register
else: print(f"Writing value {write_value} to register {register_address}...")
print("Failed to read data from Modbus server.") if write_register(client, register_address, write_value):
print(f"Successfully wrote value {write_value} to register {register_address}.")
else:
print(f"Failed to write value {write_value} to register {register_address}.")
# Step 3: Read the register again to confirm the write
print(f"Reading register {register_address} after write...")
read_data = read_register(client, register_address)
if read_data is not None:
print(f"Register {register_address} value after write: {read_data[0]}")
time.sleep(1) # Wait 1 second before the next read (adjust as necessary)
except KeyboardInterrupt: except KeyboardInterrupt:
print("\nStopping read loop...") print("\nStopping operation...")
finally: finally:
client.close() client.close()
print("Modbus client connection closed.") print("Modbus client connection closed.")

View File

@ -30,6 +30,7 @@ from .recipes_management import Recipes_Management
from .resistance_step_editor import Resistance_Step_Editor from .resistance_step_editor import Resistance_Step_Editor
from .screws_step_editor import Screws_Step_Editor from .screws_step_editor import Screws_Step_Editor
from .instruction_step_editor import Instruction_Step_Editor from .instruction_step_editor import Instruction_Step_Editor
from .pipe_cutter_step_editor import Pipe_Cutter_Step_Editor
from .steps_management import Steps_Management from .steps_management import Steps_Management
from .test import Test from .test import Test
from .test_admin_permission import Test_Admin_Permission from .test_admin_permission import Test_Admin_Permission

View File

@ -0,0 +1 @@
from .pipe_cutter_step_editor import Pipe_Cutter_Step_Editor

View File

@ -0,0 +1,11 @@
from ui.editor import Editor
class Pipe_Cutter_Step_Editor(Editor):
def __init__(self, action=None, cell_widget=None):
super().__init__(action=action, cell_widget=cell_widget)
self.spec.update({
"lenght": self.lenght_le,
"diameter":self.diameter_le
})

View File

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Pipe_Cutter_Step_Editor</class>
<widget class="QWidget" name="Pipe_Cutter_Step_Editor">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1004</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Connector Step Editor</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<weight>50</weight>
<bold>false</bold>
</font>
</property>
<property name="title">
<string>Specifica Taglia Corrugati</string>
</property>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>131</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Lunghezza Corrugato</string>
</property>
</widget>
<widget class="QLineEdit" name="lenght_le">
<property name="geometry">
<rect>
<x>160</x>
<y>30</y>
<width>141</width>
<height>36</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>20</x>
<y>80</y>
<width>121</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Diametro Corrugato</string>
</property>
</widget>
<widget class="QLineEdit" name="diameter_le">
<property name="geometry">
<rect>
<x>160</x>
<y>70</y>
<width>141</width>
<height>36</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>320</x>
<y>40</y>
<width>101</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>mm</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>320</x>
<y>80</y>
<width>101</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>mm</string>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -96,6 +96,8 @@ class Recipe_Selection(Widget):
self.config.get("recipes_defaults", noner)["verifica_resistenza_connettore_abilitata"]) and "resistance" not in self.unsupported_steps, self.config.get("recipes_defaults", noner)["verifica_resistenza_connettore_abilitata"]) and "resistance" not in self.unsupported_steps,
"screws": len(self.config.get("recipes_defaults", noner)["avvitatura_abilitata"]) and "screws" not in self.unsupported_steps, "screws": len(self.config.get("recipes_defaults", noner)["avvitatura_abilitata"]) and "screws" not in self.unsupported_steps,
"instruction": len(self.config.get("recipes_defaults", noner)["istruzione_abilitata"]) and "instruction" not in self.unsupported_steps, "instruction": len(self.config.get("recipes_defaults", noner)["istruzione_abilitata"]) and "instruction" not in self.unsupported_steps,
"instruction_extra": len(self.config.get("recipes_defaults", noner)["istruzione_abilitata_extra"]) and "instruction_extra" not in self.unsupported_steps,
"pipe_cutter": len(self.config.get("recipes_defaults", noner)["tagliatubi"]) and "pipe_cutter" not in self.unsupported_steps,
"leak_1": len(self.config.get("recipes_defaults", noner)["prova_tenuta_abilitata"]) and "leak_1" not in self.unsupported_steps, "leak_1": len(self.config.get("recipes_defaults", noner)["prova_tenuta_abilitata"]) and "leak_1" not in self.unsupported_steps,
"leak_2": len(self.config.get("recipes_defaults", noner)["prova_tenuta_abilitata_2"]) and "leak_2" not in self.unsupported_steps, "leak_2": len(self.config.get("recipes_defaults", noner)["prova_tenuta_abilitata_2"]) and "leak_2" not in self.unsupported_steps,
"vision": len(self.config.get("recipes_defaults", noner)["test_visione_abilitato"]) and "vision" not in self.unsupported_steps, "vision": len(self.config.get("recipes_defaults", noner)["test_visione_abilitato"]) and "vision" not in self.unsupported_steps,
@ -222,6 +224,10 @@ class Recipe_Selection(Widget):
"quantity": row.get("viti", defaults["viti"]) "quantity": row.get("viti", defaults["viti"])
}, },
"instruction": {}, "instruction": {},
"pipe_cutter": {
"length": row.get("lunghezza_corrugato", defaults["lunghezza_corrugato"]),
"diameter": row.get("diametro", defaults["diametro"]),
},
"leak_1": { "leak_1": {
"pre_filling_time": int(float(row.get("tempo_pre_riempimento", defaults["tempo_pre_riempimento"]))), "pre_filling_time": int(float(row.get("tempo_pre_riempimento", defaults["tempo_pre_riempimento"]))),
"pre_filling_pressure": int(float(row.get("pressione_pre_riempimento", defaults["pressione_pre_riempimento"]))), "pre_filling_pressure": int(float(row.get("pressione_pre_riempimento", defaults["pressione_pre_riempimento"]))),

View File

@ -5,6 +5,7 @@ from ui.count_step_editor import Count_Step_Editor
from ui.editor import Editor from ui.editor import Editor
from ui.helpers import replace_widget from ui.helpers import replace_widget
from ui.leak_step_editor import Leak_Step_Editor from ui.leak_step_editor import Leak_Step_Editor
from ui.pipe_cutter_step_editor import Pipe_Cutter_Step_Editor
from ui.print_step_editor import Print_Step_Editor from ui.print_step_editor import Print_Step_Editor
from ui.resistance_step_editor import Resistance_Step_Editor from ui.resistance_step_editor import Resistance_Step_Editor
from ui.screws_step_editor import Screws_Step_Editor from ui.screws_step_editor import Screws_Step_Editor
@ -95,6 +96,13 @@ class Recipe_Spec_And_Step_Editor(Editor):
"editor": Print_Step_Editor(), "editor": Print_Step_Editor(),
"tab": self.print_t, "tab": self.print_t,
}, },
"pipe_cutter": {
"type": "pipe_cutter",
"enable": self.pipe_cutter_enabled_cb,
"widget": "pipe_cutter_editor_w",
"editor": Pipe_Cutter_Step_Editor(),
"tab": self.pipe_cutter_t,
},
} }
for step_name in unsupported_steps: for step_name in unsupported_steps:
self.steps_map.get(step_name, {})["hidden"] = True self.steps_map.get(step_name, {})["hidden"] = True

View File

@ -19,18 +19,18 @@
<string>Recipe Spec And Step Editor</string> <string>Recipe Spec And Step Editor</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QPushButton" name="reset_steps_b">
<property name="text">
<string>Resetta configurazione
Fasi di Test</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QPushButton" name="save_steps_b"> <widget class="QPushButton" name="save_steps_b">
<property name="text"> <property name="text">
<string>Salva configurazione <string>Salva configurazione
Fasi di Test</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="reset_steps_b">
<property name="text">
<string>Resetta configurazione
Fasi di Test</string> Fasi di Test</string>
</property> </property>
</widget> </widget>
@ -298,6 +298,56 @@ Fasi di Test</string>
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="pipe_cutter_t">
<attribute name="title">
<string>Taglia Tubi</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_12">
<item row="0" column="2">
<spacer name="horizontalSpacer_46">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>572</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_45">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>572</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="pipe_cutter_enabled_cb">
<property name="text">
<string>Fase Abilitata</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QWidget" name="pipe_cutter_editor_w" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="instruction_extra_t"> <widget class="QWidget" name="instruction_extra_t">
<attribute name="title"> <attribute name="title">
<string>Montaggio extra</string> <string>Montaggio extra</string>

View File

@ -20,6 +20,7 @@ from ui.test_count import Test_Count
from ui.test_count_end import Test_Count_End from ui.test_count_end import Test_Count_End
from ui.test_fail import Test_Fail from ui.test_fail import Test_Fail
from ui.test_instructions import Test_Instructions from ui.test_instructions import Test_Instructions
from ui.test_pipe_cutter import Test_Pipe_Cutter
from ui.test_leak import Test_Leak from ui.test_leak import Test_Leak
from ui.test_resistance import Test_Resistance from ui.test_resistance import Test_Resistance
from ui.test_screws import Test_Screws from ui.test_screws import Test_Screws
@ -82,6 +83,7 @@ class Test(Widget):
"resistance": {"multicomp", }, "resistance": {"multicomp", },
"leak_1": {self.tester_component, }, "leak_1": {self.tester_component, },
"leak_2": {self.tester_component, }, "leak_2": {self.tester_component, },
"pipe_cutter": {"pipe_cutter"},
"vision": {("uvc_camera", "galaxy_camera",), "vision", "vision_saver", }, # "neo_pixels", }, "vision": {("uvc_camera", "galaxy_camera",), "vision", "vision_saver", }, # "neo_pixels", },
"print": {"label_printer_2"} if self.config["hardware_config"]["label_printer"] != "present" else {"label_printer"}, "print": {"label_printer_2"} if self.config["hardware_config"]["label_printer"] != "present" else {"label_printer"},
} }
@ -121,6 +123,7 @@ class Test(Widget):
"flush": Test_Assembly(img_path=None, text=u"SCARICO ARIA IN CORSO - ATTENDERE...", widget=Test_Warning_Img(components=self.components, recipe=self.recipe, step=self.step)), "flush": Test_Assembly(img_path=None, text=u"SCARICO ARIA IN CORSO - ATTENDERE...", widget=Test_Warning_Img(components=self.components, recipe=self.recipe, step=self.step)),
"instruction": Test_Assembly(img_path=None, text=u"ESEGUIRE LE OPERAZIONI DI MONTAGGIO INDICATE IN FIGURA", "instruction": Test_Assembly(img_path=None, text=u"ESEGUIRE LE OPERAZIONI DI MONTAGGIO INDICATE IN FIGURA",
widget=Test_Instructions(config=self.config,components=self.components, recipe=self.recipe, bench_name=self.config.machine_id, step=self.step)), widget=Test_Instructions(config=self.config,components=self.components, recipe=self.recipe, bench_name=self.config.machine_id, step=self.step)),
"pipe_cutter": Test_Assembly(img_path=None, text=u"ATTENZIONE TAGLIO CORRUGATOIN CORSO",widget=Test_Pipe_Cutter(config=self.config, components=self.components,recipe=self.recipe, bench_name=self.config.machine_id,step=self.step)),
"instruction_extra": Test_Assembly(img_path=None, text=u"ESEGUIRE LE OPERAZIONI DI MONTAGGIO EXTRA INDICATE IN FIGURA", "instruction_extra": Test_Assembly(img_path=None, text=u"ESEGUIRE LE OPERAZIONI DI MONTAGGIO EXTRA INDICATE IN FIGURA",
widget=Test_Instructions(config=self.config, components=self.components,recipe=self.recipe, bench_name=self.config.machine_id,step=self.step)), widget=Test_Instructions(config=self.config, components=self.components,recipe=self.recipe, bench_name=self.config.machine_id,step=self.step)),
"piece_removal": Test_Assembly(img_path=None, text=u"RIMUOVERE IL PEZZO APRENDO TUTTE LE CHIUSURE", "piece_removal": Test_Assembly(img_path=None, text=u"RIMUOVERE IL PEZZO APRENDO TUTTE LE CHIUSURE",
@ -428,6 +431,9 @@ class Test(Widget):
if step.spec["warning_img"]: if step.spec["warning_img"]:
steps.insert(i, Step(step_type="warning_img", spec={"warning_img": step.spec["warning_img"]})) steps.insert(i, Step(step_type="warning_img", spec={"warning_img": step.spec["warning_img"]}))
skip.add(i + 1) skip.add(i + 1)
if step.step_type in "pipe_cutter":
self.pipe_cutter_step = step
if "assembly" in step.spec: if "assembly" in step.spec:
if step.spec["assembly"]: if step.spec["assembly"]:
steps.insert(i, Step(step_type="instructions", spec={})) steps.insert(i, Step(step_type="instructions", spec={}))

View File

@ -0,0 +1 @@
from .test_pipe_cutter import Test_Pipe_Cutter

View File

@ -0,0 +1,86 @@
from PyQt5.QtGui import QMovie
import logging
from ui.test_test import Test_Test
from components import PipeCutterComponent
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class Test_Pipe_Cutter(Test_Test):
"""
A class to manage and operate a pipe cutter machine in a test environment.
"""
def __init__(self, config, components, recipe=None, run_once=False,
reset_on_start=False, enable_override=False, bench_name="generic", step=None,):
super().__init__(components=components, recipe=recipe, step=None, run_once=run_once,
reset_on_start=reset_on_start, enable_override=enable_override,)
self.bench_name = bench_name
self.cutter = PipeCutterComponent()
self.current_cut_length = 0.0
self.max_cut_length = config.get("max_cut_length", 10.0)
self.movie = QMovie(config.get("config/instruction_images/st-ten-10/pipe.gif ")) # Animation Path
self.current_status = None
def start(self, recipe=None, step=None, pieces=None):
if step is not None :
self.start_cutting()
self.display_cutting_animation(True)
self.stop_cutting()
def start_cutting(self,recipe=None,step=None):
"""
Start the pipe cutting process and activate the pipe cutter component.
"""
self.current_status = self.cutter.read_machine_status()
if self.current_status == 102 : # ready for operation
try:
self.reset_machine()
self.cutter.write_total_length(self.recipe.spec.get("length", None))
self.cutter.write_od_of_pipe(self.recipe.spec.get("diameter", None))
self.cutter.write_bit_with_delay(600,0,100)
except Exception as e:
logger.error(f"Failed to start the pipe cutting process: {e}")
else:
try:
self.cutter.write_bit_with_delay(600, 1, 100) # resetting
except Exception as e:
logger.error(f"Failed to reset the pipe cutting process: {e}")
def stop_cutting(self):
"""
Stop the pipe cutting process and deactivate the pipe cutter component.
"""
try:
self.current_status = self.cutter.read_machine_status()
if self.current_status in(106,107):
self.cutter.write_bit_with_delay(600, 2, 100)
self.reset_machine()
except Exception as e:
logger.error(f"Failed to stop the pipe cutting process: {e}")
def reset_machine(self):
"""
Reset the pipe cutter machine to its initial state.
"""
try:
self.cutter.write_bit_with_delay(600, 1, 100)
except Exception as e:
logger.error(f"Failed to reset the pipe cutter machine: {e}")
def display_cutting_animation(self, show: bool):
"""
Show or hide the cutting animation GIF.
Args:
show (bool): Whether to display or stop the animation.
"""
if show:
self.pipe_gif.setVisible(True)
self.movie.start()
logger.info("Cutting animation started.")
else:
self.movie.stop()
self.pipe_gif.setVisible(False)
logger.info("Cutting animation stopped.")

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Test_Warning_Img</class>
<widget class="QWidget" name="Test_Warning_Img">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1657</width>
<height>922</height>
</rect>
</property>
<property name="windowTitle">
<string>Test Count End</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="6" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>20</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="title">
<string>TAGLIA CORRUGATO</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="pipe_gif">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>