pipe cutter wip

This commit is contained in:
edo-neo 2025-01-17 15:14:28 +01:00
parent b54903f6d1
commit 849db63176
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: absent
; external_flush_blow: absent # EXTERNAL BOX CONTROLLING MULTI-CHANNEL TEST (IF PRESENT), BLOW-CLEANING AND EXTERNAL FLUSH
;pipe_cutter: absent
[galaxy_camera]
horizontal_resolution: 2448

View File

@ -13,6 +13,7 @@ furness_controls: absent
barcode_recipe_selection : absent
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
pipe_cutter: present
[archive_synchronizer]
@ -80,6 +81,13 @@ pressione_svuotamento: 100
canale_di_prova: 0
n_componenti: 1
tester_discharge_enable: yes
tagliatubi: x
lunghezza_corrugato: 100
diametro_corrugato:21
[autotest_leak]
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 .furness_controls_leak_tester import FurnessControlsLeakTester
from .brother_label_printer import BrotherLabelPrinter
from .pipe_cutter_component import PipeCutterComponent
if "--vision" in sys.argv:
from .galaxy_camera import GalaxyCamera
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": {
"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": {
"pre_filling_time": safe_parse(row.get("tempo_pre_riempimento", defaults["tempo_pre_riempimento"])),
"pre_filling_pressure": safe_parse(
@ -228,6 +233,7 @@ def import_recipes(config, csv_path=None, defaults=None, unsupported_steps=None,
unsupported_steps or []),
"instruction_extra": len(row.get("istruzione_abilitata_extra", defaults[
"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(
row.get("prova_tenuta_abilitata", defaults["prova_tenuta_abilitata"])) and "leak_1" not in (
unsupported_steps or []),

View File

@ -67,7 +67,7 @@ try:
# IMPORT PROJECT ONLY AFTER SETTING UP SIGNAL, FAULTHANDLER AND LOGGING
from components import (ArchiveSynchronizer, Multicomp730424,
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.helpers import ConfigReader
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
@ -113,6 +113,7 @@ try:
"digital_io": {"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}},
"pipe_cutter": {"c": PipeCutterComponent, "k": {"paused": False}},
}
# VISION COMPONENT IS OPTIONAL AND DISABLED BY DEFAULT
if "--vision" in sys.argv:

View File

@ -1,41 +1,64 @@
import serial
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.client import ModbusSerialClient as ModbusClient
from pymodbus.exceptions import ModbusIOException
import logging
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.
:param client: An instance of ModbusClient
:param starting_register: The address of the register to start reading from
:param register_count: Number of registers to read
:param register_address: The address of the register to read
:param count: Number of registers to read
:return: List of register values or None if there was an error
"""
try:
read_data = client.read_holding_registers(starting_register, count=register_count)
if isinstance(read_data, ModbusIOException):
print("Error: ModbusIOException occurred during read operation.")
result = client.read_holding_registers(register_address, count=count, slave=1)
if result.isError():
print(f"Error reading register {register_address}: {result}")
return None
else:
return read_data.registers
return result.registers
except Exception as e:
print(f"Error: {e}")
print(f"Error reading register {register_address}: {e}")
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():
# Modbus client configuration
client = ModbusClient(
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,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
baudrate=38400,
timeout=1, # Timeout in seconds
strict=False
strict=False,
slave=1
)
# Attempt to connect to the Modbus server
@ -45,24 +68,32 @@ def main():
print("Failed to connect to Modbus client.")
return
# Starting the data read loop
try:
starting_register = 1 # Define the starting register address
register_count = 10 # Define the number of registers to read
# Define the register address and value
register_address = 30 # Address to read/write
write_value = 1100 # Value to write to the register
print("Starting data read loop...")
while True:
data = read_modbus_data(client, starting_register, register_count)
if data:
# Print read data
for i, value in enumerate(data):
print(f"Register {starting_register + i}: {value}")
else:
print("Failed to read data from Modbus server.")
# Step 1: Read the register value
print(f"Reading register {register_address}...")
read_data = read_register(client, register_address)
if read_data is not None:
print(f"Register {register_address} value before write: {read_data[0]}")
# Step 2: Write a value to the register
print(f"Writing value {write_value} to register {register_address}...")
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:
print("\nStopping read loop...")
print("\nStopping operation...")
finally:
client.close()
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 .screws_step_editor import Screws_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 .test import Test
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,
"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_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_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,
@ -222,6 +224,10 @@ class Recipe_Selection(Widget):
"quantity": row.get("viti", defaults["viti"])
},
"instruction": {},
"pipe_cutter": {
"length": row.get("lunghezza_corrugato", defaults["lunghezza_corrugato"]),
"diameter": row.get("diametro", defaults["diametro"]),
},
"leak_1": {
"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"]))),

View File

@ -5,6 +5,7 @@ from ui.count_step_editor import Count_Step_Editor
from ui.editor import Editor
from ui.helpers import replace_widget
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.resistance_step_editor import Resistance_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(),
"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:
self.steps_map.get(step_name, {})["hidden"] = True

View File

@ -19,18 +19,18 @@
<string>Recipe Spec And Step Editor</string>
</property>
<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">
<widget class="QPushButton" name="save_steps_b">
<property name="text">
<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>
</property>
</widget>
@ -298,6 +298,56 @@ Fasi di Test</string>
</item>
</layout>
</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">
<attribute name="title">
<string>Montaggio extra</string>

View File

@ -21,6 +21,7 @@ from ui.test_count import Test_Count
from ui.test_count_end import Test_Count_End
from ui.test_fail import Test_Fail
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_resistance import Test_Resistance
from ui.test_screws import Test_Screws
@ -83,6 +84,7 @@ class Test(Widget):
"resistance": {"multicomp", },
"leak_1": {self.tester_component, },
"leak_2": {self.tester_component, },
"pipe_cutter": {"pipe_cutter"},
"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"},
}
@ -122,6 +124,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)),
"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)),
"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",
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",
@ -429,6 +432,9 @@ class Test(Widget):
if step.spec["warning_img"]:
steps.insert(i, Step(step_type="warning_img", spec={"warning_img": step.spec["warning_img"]}))
skip.add(i + 1)
if step.step_type in "pipe_cutter":
self.pipe_cutter_step = step
if "assembly" in step.spec:
if step.spec["assembly"]:
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("cut_length", None))
self.cutter.write_od_of_pipe(self.recipe.spec.get("od_of_pipe", 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>