test leak
This commit is contained in:
parent
02cf4797eb
commit
817d62625e
|
|
@ -31,7 +31,7 @@ platform: cups
|
|||
printer:
|
||||
|
||||
|
||||
[tecna_marposs_provaset_t3]
|
||||
[tecna_t3]
|
||||
address: COM3
|
||||
baudrate: 115200
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ python -B -u "./src/main.py" \
|
|||
--no-autotest \
|
||||
--no-edgetpu \
|
||||
--no-gpu \
|
||||
--panel \
|
||||
--sim-camera \
|
||||
--sim-modbus \
|
||||
--sim-os-label-printer \
|
||||
|
|
|
|||
|
|
@ -105,22 +105,45 @@ class TecnaMarpossProvasetT3(ModbusComponent):
|
|||
]}
|
||||
if info["Running test: type of test"] is None:
|
||||
info.update(self.get_test_results())
|
||||
self.start_test()
|
||||
self.log.debug(str(info))
|
||||
super()._get([info])
|
||||
|
||||
def start_test(self):
|
||||
self.log.info("starting test")
|
||||
self.write("Start testing", 1)
|
||||
def start_test(self, table=1):
|
||||
self.log.info(f"starting test table {table!r}")
|
||||
self.write("Start testing", table)
|
||||
|
||||
def stop_test(self):
|
||||
self.log.warining("stopping test")
|
||||
self.log.warning("stopping test")
|
||||
self.write("Stop the test in progress", 0)
|
||||
|
||||
def get_test_results(self):
|
||||
self.log.info("getting test results")
|
||||
return {r: self.read(r) for r in [
|
||||
"Running test: measured leak",
|
||||
"Running test: calculated leak flow rate",
|
||||
"Running test: calculate RVP%",
|
||||
"Running test: result",
|
||||
]}
|
||||
|
||||
def write_recipe(self, recipe, table=1):
|
||||
# "pressure_ramp": self.pressure_ramp_sb,
|
||||
# "stabilization_cycles": self.stabilization_cycles_sb,
|
||||
recipe = {
|
||||
"Type of test": "LEAK TEST",
|
||||
# "Test flags": recipe.spec[""],
|
||||
"T0 - Pre-filling time": recipe.spec["pre_filling_time"],
|
||||
"P0 - Pre-filling pressure": recipe.spec["pre_filling_pressure"],
|
||||
"T1 - Filling time": recipe.spec["filling_time"],
|
||||
"T2 - Settling time": recipe.spec["settling_time"],
|
||||
"PR%- Lower tolerance on pressure / P- Minimum pressure": recipe.spec["settling_pressure_min_percent"],
|
||||
"PR%+ Superior tolerance on pressure / P+ Pressure max": recipe.spec["settling_pressure_max_percent"],
|
||||
"T3 - Measure time": recipe.spec["test_time"],
|
||||
"Q- Leak limit": recipe.spec["test_pressure_min_delta"],
|
||||
"PREL - Nominal test pressure": recipe.spec["test_pressure"],
|
||||
"Q+ Upper limit": recipe.spec["test_pressure_max_delta"],
|
||||
"FST - discharge time": recipe.spec["flush_time"],
|
||||
"FSL - discharge limit": recipe.spec["flush_pressure"],
|
||||
}
|
||||
self.log.debug(str(recipe))
|
||||
for register, value in recipe.items():
|
||||
self.write(register, value)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ registers = {
|
|||
4: "not used",
|
||||
5: "BLOCKAGE TEST PASSED",
|
||||
100: "LEAK TEST FAILED - UPPER LIMIT",
|
||||
101: "LEAK TEST – FAILED ANOMALY",
|
||||
101: "LEAK TEST - FAILED ANOMALY",
|
||||
102: "LEAK TEST - MAXIMUM LEAK FAILED",
|
||||
103: "BURST - BREAKAGE PRESSURE DEFLECTION",
|
||||
104: "VOLUMETRIC CONTROL - RVP% FAILED",
|
||||
|
|
@ -65,14 +65,14 @@ registers = {
|
|||
107: "BLOCKAGE - MAX PRESSURE FAILED",
|
||||
108: "BLOCKAGE - MIN PRESSURE FAILED",
|
||||
109: "BURST - MINIMUM PRESSURE FAILED",
|
||||
200: "LEAK TEST FAILED – PR% PRESSURE MINUM",
|
||||
200: "LEAK TEST FAILED - PR% PRESSURE MINUM",
|
||||
201: "LEAK TEST FAILED - PR% PRESSURE MAX",
|
||||
202: "LEAK TEST FAILED – P0% PRESSURE MINUM",
|
||||
202: "LEAK TEST FAILED - P0% PRESSURE MINUM",
|
||||
203: "LEAK TEST FAILED - P0% PRESSURE MAX",
|
||||
204: "ERROR - INTERNAL ALARMS",
|
||||
205: "ERROR - RELATIVE PRESSURE OUT OF RANGE",
|
||||
206: "ERROR - DIFFERENTIAL PRESSURE OUT OF RANGE",
|
||||
207: "ERROR – PRE-FILLING VALVE NOT OPENED",
|
||||
207: "ERROR - PRE-FILLING VALVE NOT OPENED",
|
||||
250: "TEST ABORTED",
|
||||
}, }],
|
||||
"Running test: type of test": [47, {"dt": "16bit_uint", "decoding": {
|
||||
|
|
@ -130,13 +130,20 @@ registers = {
|
|||
# 0= Only passed
|
||||
# 1= Only failed
|
||||
# 2=All
|
||||
"AUTOMATION: Marking – driving time": [624, {"dt": "16bit_uint", }],
|
||||
"AUTOMATION: Marking - driving time": [624, {"dt": "16bit_uint", }],
|
||||
# Format: x.x seconds
|
||||
"Type of test": [701, {"dt": "16bit_uint", }],
|
||||
# 1=LEAK TEST
|
||||
# 2=BLOCKAGE TEST
|
||||
# 3=LEAK TEST WITH VOLUME
|
||||
# 4=BURST TEST
|
||||
"Selection number of test table on which you intend to work": [700, {"dt": "16bit_uint", }],
|
||||
"Type of test": [701, {"dt": "16bit_uint", "encoding": {
|
||||
"LEAK TEST": 1,
|
||||
"BLOCKAGE TEST": 2,
|
||||
"LEAK TEST WITH VOLUME": 3,
|
||||
"BURST TEST": 4,
|
||||
}, "decoding": {
|
||||
1: "LEAK TEST",
|
||||
2: "BLOCKAGE TEST",
|
||||
3: "LEAK TEST WITH VOLUME",
|
||||
4: "BURST TEST",
|
||||
}, }],
|
||||
"Test flags": [702, {"dt": "16bit_uint", }],
|
||||
# T0/Pr: Phase filling mode T0 0= TIME 1= PRESSURE
|
||||
# T1/Pr: Phase filling mode T1 0= TIME 1=PRESSURE
|
||||
|
|
@ -149,39 +156,39 @@ registers = {
|
|||
# AT: 0=Tare pressure disabled 1=Tare pressure enabled
|
||||
# HR: 0=Resolution on loss 1 Pa 1=Resolution on loss 0.1 Pa (models with full scale <= 2 bar)
|
||||
# CH: Selected test channel (2-channel T3P2C model only)
|
||||
"T0 – Pre-filling time": [704, {"dt": "16bit_uint", "f": 26, }],
|
||||
"P0 – Pre-filling pressure": [705, {"dt": "16bit_uint", "f": 23, }],
|
||||
"T0 - Pre-filling time": [704, {"dt": "16bit_uint", "f": 26, }],
|
||||
"P0 - Pre-filling pressure": [705, {"dt": "16bit_uint", "f": 23, }],
|
||||
# In order to use a negative (vacuum) value, this parameter must however be written positively, but the P0- bit must
|
||||
# also be selected in register 702
|
||||
"T1 – Filling time": [706, {"dt": "16bit_uint", "f": 26, }],
|
||||
"T2 – Settling time": [707, {"dt": "16bit_uint", "f": 26, }],
|
||||
"T3 – Measure time": [708, {"dt": "16bit_uint", "f": 26, }],
|
||||
"PREL – Nominal test pressure": [709, {"dt": "16bit_uint", "f": 23, }],
|
||||
"T1 - Filling time": [706, {"dt": "16bit_uint", "f": 26, }],
|
||||
"T2 - Settling time": [707, {"dt": "16bit_uint", "f": 26, }],
|
||||
"T3 - Measure time": [708, {"dt": "16bit_uint", "f": 26, }],
|
||||
"PREL - Nominal test pressure": [709, {"dt": "16bit_uint", "f": 23, }],
|
||||
# To set a negative pressure (vacuum) this parameters must be written in absolute value and then set
|
||||
# bit Pr- in register 702
|
||||
"Pxx Minimum Pressure": [710, {"dt": "16bit_uint", }],
|
||||
"PR%- Lower tolerance on pressure / P- Minimum pressure": [710, {"dt": "16bit_uint", }],
|
||||
# PR%- Lower tolerance on pressure: LEAK: Format: x.x %
|
||||
# P- Minimum pressure: BLOCKAGE: Format as indicated in register 23
|
||||
# PR- Minimum pressure%: BURST: Format x.x%
|
||||
"Q + Upper limit": [711, {"dt": "16bit_uint", "f": 22, }],
|
||||
"Q+ Upper limit": [711, {"dt": "16bit_uint", "f": 22, }],
|
||||
# Format as indicated in the register 22
|
||||
"Q- Leak limit": [712, {"dt": "16bit_uint", "f": 22, }],
|
||||
# Format as indicated in the register 22
|
||||
"FST –discharge time": [713, {"dt": "16bit_uint", "f": 26, }],
|
||||
"FST - discharge time": [713, {"dt": "16bit_uint", "f": 26, }],
|
||||
# Format as indicated in the register 26
|
||||
"VP – Equivalent volume": [714, {"dt": "16bit_uint", "f": 25, }],
|
||||
"VP - Equivalent volume": [714, {"dt": "16bit_uint", "f": 25, }],
|
||||
# Format as indicated in the register 25
|
||||
"P% Pressure tolerance": [717, {"dt": "16bit_uint", }],
|
||||
# BLOCKAGE: Format x.x %
|
||||
"PB – Minimum burst pressure": [743, {"dt": "16bit_uint", "f": 23, }],
|
||||
"PB - Minimum burst pressure": [743, {"dt": "16bit_uint", "f": 23, }],
|
||||
# BURST: Format as indicated in the register 23
|
||||
"BD – Delta burst": [744, {"dt": "16bit_uint", "f": 23, }],
|
||||
"BD - Delta burst": [744, {"dt": "16bit_uint", "f": 23, }],
|
||||
# BURST: Format as indicated in the register 23
|
||||
"FSL – discharge limit": [745, {"dt": "16bit_uint", "f": 23, }],
|
||||
"FSL - discharge limit": [745, {"dt": "16bit_uint", "f": 23, }],
|
||||
# Format as indicated in the register 23
|
||||
"PR% + Superior tolerance on pressure": [747, {"dt": "16bit_uint", }],
|
||||
# LEAK: Format: x.x %
|
||||
# P + Pressure max BURST: Format as indicated in the register 23
|
||||
"PR%+ Superior tolerance on pressure / P+ Pressure max": [747, {"dt": "16bit_uint", }],
|
||||
# PR% + Superior tolerance on pressure: LEAK: Format: x.x %
|
||||
# P + Pressure max: BURST: Format as indicated in the register 23
|
||||
"RVP%: volumetric ratio": [750, {"dt": "16bit_uint", }],
|
||||
# VOLUME+LEAK: Format x.xx (from 0.00 to 649.99)
|
||||
"RVP%: max tolerance": [751, {"dt": "16bit_uint", }],
|
||||
|
|
|
|||
|
|
@ -64,24 +64,26 @@ Recipes.replace(id=0, name="TEST", spec={
|
|||
"client": "TEST_CLIENT",
|
||||
"part_number": "TEST_PART_NUMBER",
|
||||
"station": "TEST_STATION",
|
||||
# pressure
|
||||
"pressure_min": 0,
|
||||
"pressure_test": 1,
|
||||
"pressure_max": 2,
|
||||
"pressure_ramp": 3,
|
||||
# test
|
||||
"cleaning_time": 4,
|
||||
"tolerance": 5,
|
||||
"test_duration": 6,
|
||||
"flush_duration": 7,
|
||||
# stabilizarion
|
||||
"stabilization_time": 8,
|
||||
"stabilization_level_min": 9,
|
||||
"stabilization_level_max": 10,
|
||||
"stabilization_settling_time": 11,
|
||||
"stabilization_cycles": 12,
|
||||
# description
|
||||
"description": "TEST_DESCRIPTION",
|
||||
# pre-filling
|
||||
"pre_filling_time": 5,
|
||||
"pre_filling_pressure": 3000,
|
||||
# filling
|
||||
"filling_time": 5,
|
||||
"settling_time": 10,
|
||||
"settling_pressure_min_percent": 20,
|
||||
"settling_pressure_max_percent": 20,
|
||||
# test
|
||||
"test_time": 20,
|
||||
"test_pressure_min_delta": 3.00,
|
||||
"test_pressure": 3000,
|
||||
"test_pressure_max_delta": 0.25,
|
||||
"cycles": 1,
|
||||
# flush
|
||||
"flush_time": 2,
|
||||
"flush_pressure": 5,
|
||||
# vision
|
||||
"vision_recipe": 0,
|
||||
}, archived=False).execute()
|
||||
|
||||
if True:
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ try:
|
|||
"label_printer": {"c": Os_Label_Printer, "t": False},
|
||||
"neo_pixels": {"c": NeoPixels, "t": False},
|
||||
"remote_api": {"c": RemoteAPI, "k": {"main": self}},
|
||||
"tecna_marposs_provaset_t3": {"c": TecnaMarpossProvasetT3},
|
||||
"tecna_t3": {"c": TecnaMarpossProvasetT3, "k": {"paused": True}},
|
||||
"vision_saver": {"c": VisionSaver, "t": False},
|
||||
"vision": {"c": Vision, "k": {"paused": True}},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ from .test import Test
|
|||
from .test_admin_permission import Test_Admin_Permission
|
||||
from .test_autotest import Test_Autotest
|
||||
from .test_home import Test_Home
|
||||
from .test_leak import Test_Leak
|
||||
from .test_test import Test_Test
|
||||
from .test_vision import Test_Vision
|
||||
from .users_management import Users_Management
|
||||
from .widget import Widget
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ dialogs = {}
|
|||
class Dialog(QDialog):
|
||||
_closing = pyqtSignal()
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
global dialogs
|
||||
dialogs[id(self)] = self
|
||||
self.setAttribute(Qt.WA_DeleteOnClose)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
from PyQt5.QtWidgets import (QCheckBox, QComboBox, QDoubleSpinBox, QLineEdit,
|
||||
QRadioButton, QSpinBox, QPlainTextEdit)
|
||||
QPlainTextEdit, QRadioButton, QSpinBox)
|
||||
from ui.widget import Widget
|
||||
|
||||
|
||||
|
|
@ -11,26 +11,26 @@ class Recipe_Editor(Widget):
|
|||
"client": self.client_le,
|
||||
"part_number": self.part_number_le,
|
||||
"station": self.station_le,
|
||||
# pressure
|
||||
"pressure_min": self.pressure_min_sb,
|
||||
"pressure_test": self.pressure_test_sb,
|
||||
"pressure_max": self.pressure_max_sb,
|
||||
"pressure_ramp": self.pressure_ramp_sb,
|
||||
"description": self.description_pte,
|
||||
# pre-filling
|
||||
"pre_filling_time": self.pre_filling_time_sb,
|
||||
"pre_filling_pressure": self.pre_filling_pressure_sb,
|
||||
# filling
|
||||
"filling_time": self.filling_time_sb,
|
||||
"settling_time": self.settling_time_sb,
|
||||
"settling_pressure_min_percent": self.settling_pressure_min_percent_sb,
|
||||
"settling_pressure_max_percent": self.settling_pressure_max_percent_sb,
|
||||
# test
|
||||
"cleaning_time": self.cleaning_time_sb,
|
||||
"tolerance": self.tolerance_sb,
|
||||
"test_duration": self.test_duration_sb,
|
||||
"flush_duration": self.flush_duration_sb,
|
||||
"test_time": self.test_time_sb,
|
||||
"test_pressure_min_delta": self.test_pressure_min_delta_sb,
|
||||
"test_pressure": self.test_pressure_sb,
|
||||
"test_pressure_max_delta": self.test_pressure_max_delta_sb,
|
||||
"cycles": self.cycles_sb,
|
||||
# flush
|
||||
"flush_time": self.flush_time_sb,
|
||||
"flush_pressure": self.flush_pressure_sb,
|
||||
# vision
|
||||
"vision_recipe": self.vision_recipe_cb,
|
||||
# stabilizarion
|
||||
"stabilization_time": self.stabilization_time_sb,
|
||||
"stabilization_level_min": self.stabilization_level_min_sb,
|
||||
"stabilization_level_max": self.stabilization_level_max_sb,
|
||||
"stabilization_settling_time": self.stabilization_settling_time_sb,
|
||||
"stabilization_cycles": self.stabilization_cycles_sb,
|
||||
# description
|
||||
"description": self.description_pte,
|
||||
}
|
||||
|
||||
def set_readonly(self, readonly):
|
||||
|
|
|
|||
|
|
@ -6,66 +6,42 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>494</width>
|
||||
<height>733</height>
|
||||
<width>845</width>
|
||||
<height>696</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Descrizione</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPlainTextEdit" name="description_pte"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Test</string>
|
||||
<string>Pre-Riempimento</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="test_duration_sb"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="tolerance_sb"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Tempo di prova</string>
|
||||
<widget class="QSpinBox" name="pre_filling_pressure_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Tempo di scarico</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="flush_duration_sb"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="cleaning_time_sb"/>
|
||||
<widget class="QSpinBox" name="pre_filling_time_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Tempo di pulizia</string>
|
||||
<string>Tempo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>bar</string>
|
||||
<string>mbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -76,31 +52,290 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="label_21">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Tolleranza</string>
|
||||
<string>Pressione</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="2" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_7">
|
||||
<property name="title">
|
||||
<string>Riempimento</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Soglia min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Tempo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="settling_pressure_min_percent_sb">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="filling_time_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Soglia max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="settling_pressure_max_percent_sb">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Assestamento</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="settling_time_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Cicli</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QSpinBox" name="test_pressure_min_delta_sb">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QSpinBox" name="test_pressure_max_delta_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QSpinBox" name="test_time_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>mbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>mbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Delta min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Delta max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Tempo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>mbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QSpinBox" name="test_pressure_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Pressione</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QSpinBox" name="cycles_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Scarico</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Tempo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_30">
|
||||
<property name="text">
|
||||
<string>Pressione</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="flush_pressure_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="flush_time_sb">
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_31">
|
||||
<property name="text">
|
||||
<string>mbar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="4">
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Visione</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Ricetta visione</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="vision_recipe_cb"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Ricetta</string>
|
||||
|
|
@ -120,12 +355,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLineEdit" name="station_le"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="client_le"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
|
|
@ -133,191 +362,26 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="part_number_le"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="title">
|
||||
<string>Stabilizzazione</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Soglia max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Soglia min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="stabilization_cycles_sb"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="stabilization_time_sb"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="stabilization_settling_time_sb"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="stabilization_level_max_sb"/>
|
||||
<widget class="QLineEdit" name="station_le"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="stabilization_level_min_sb"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="text">
|
||||
<string>Tempo assestamento</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Numero di cicli</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Tempo</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="text">
|
||||
<string>%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="text">
|
||||
<string>%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Pressione</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="4" column="2">
|
||||
<widget class="QSpinBox" name="pressure_max_sb"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>Min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QSpinBox" name="pressure_min_sb"/>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="label_22">
|
||||
<property name="text">
|
||||
<string>bar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QSpinBox" name="pressure_test_sb"/>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QSpinBox" name="pressure_ramp_sb"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="text">
|
||||
<string>bar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Rampa di salita</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="label_23">
|
||||
<property name="text">
|
||||
<string>bar</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>bar/min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_6">
|
||||
<property name="title">
|
||||
<string>Visione</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Ricetta visione</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="part_number_le"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="vision_recipe_cb"/>
|
||||
<widget class="QLineEdit" name="client_le"/>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_5">
|
||||
<property name="title">
|
||||
<string>Descrizione</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPlainTextEdit" name="description_pte"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ from ui.helpers import replace_widget
|
|||
from ui.recipe_selection import Recipe_Selection
|
||||
from ui.test_assembly import Test_Assembly
|
||||
from ui.test_autotest import Test_Autotest
|
||||
from ui.test_leak import Test_Leak
|
||||
from ui.test_vision import Test_Vision
|
||||
from ui.widget import Widget
|
||||
|
||||
|
|
@ -39,13 +40,13 @@ class Test(Widget):
|
|||
"done": Test_Assembly(self.select_step_img("success"), u"COLLAUDO COMPLETATO - RIMUOVERE IL SENSORE"),
|
||||
"emergency": Test_Assembly(self.select_step_img("reset_emergency"), u"EMERGENZA INTERVENUTA - RIPRISTINARE PULSANTE E SELEZIONARE \"RESET EMERGENZA\" DAL MEN\u00d9 \"STRUMENTI\""),
|
||||
"fail": Test_Assembly(self.select_step_img("fail"), u"CICLO INTERROTTO - RIMUOVERE IL SENSORE"),
|
||||
"run_test": Test_Assembly(self.select_step_img("wait"), u"ESECUZIONE TEST IN CORSO - ATTENDERE", Test_Leak(components=self.components, recipe=self.recipe)),
|
||||
"select_recipe": Test_Assembly(None, u"SELEZIONARE IL CODICE DA COLLAUDARE", Recipe_Selection()),
|
||||
"vision": Test_Assembly(None, u"ESEGUIRE PROCEDURA DI AUTOTEST", Test_Vision(self.components, None)),
|
||||
"vision": Test_Assembly(None, u"ESEGUIRE PROCEDURA DI AUTOTEST", Test_Vision(components=self.components, recipe=self.recipe)),
|
||||
"wait": Test_Assembly(self.select_step_img("wait"), u"ATTENDERE - PAUSA INTER CICLO"),
|
||||
}
|
||||
self.cycle_loop = ["vision", "done", "wait"]
|
||||
self.cycle_loop = ["run_test", "vision", "done", "wait"]
|
||||
self.cycle_index = -1
|
||||
self.cycle_changing_state = False
|
||||
# SETUP AUTOTEST
|
||||
self.autotest_request = False
|
||||
if "--no-autotest" not in sys.argv:
|
||||
|
|
@ -54,23 +55,25 @@ class Test(Widget):
|
|||
else:
|
||||
self.autotest_period = None
|
||||
# INIT TEST DATA
|
||||
self.data = None
|
||||
self.data = {}
|
||||
# INIT PIECES COUNTER ([pieces_ok, pieces_failed])
|
||||
self.pieces = [0, 0]
|
||||
# CONNECT CYCLE CONTROLS
|
||||
self.cancel_b.clicked.connect(self.fail_cycle)
|
||||
self.change_recipe_b.clicked.connect(self.change_recipe)
|
||||
for w in self.cycle_states.values():
|
||||
if hasattr(w, "ko"):
|
||||
w.ko.connect(self.fail_cycle)
|
||||
if hasattr(w, "ok"):
|
||||
# custom ok handlers should call next again
|
||||
if type(w.widget) is Recipe_Selection:
|
||||
w.ok.connect(self.set_recipe)
|
||||
elif type(w.widget) is Test_Leak:
|
||||
w.ok.connect(self.set_leak)
|
||||
elif type(w.widget) is Test_Vision:
|
||||
w.ok.connect(self.set_vision)
|
||||
else:
|
||||
w.ok.connect(self.next)
|
||||
if hasattr(w, "ko"):
|
||||
w.ko.connect(self.fail_cycle)
|
||||
# TESTING
|
||||
if "--test" in sys.argv:
|
||||
self.testing = True
|
||||
|
|
@ -78,6 +81,9 @@ class Test(Widget):
|
|||
self.testing = False
|
||||
# /TESTING
|
||||
# START CYCLE
|
||||
self.next_timer = QTimer()
|
||||
self.next_timer.setSingleShot(True)
|
||||
self.next_timer.timeout.connect(self.next)
|
||||
self.next()
|
||||
|
||||
def refresh_time(self, init=False):
|
||||
|
|
@ -113,90 +119,6 @@ class Test(Widget):
|
|||
def setCentralWidget(self, widget):
|
||||
replace_widget(self, "centralWidget", widget)
|
||||
|
||||
# def check_next(self, interpreted):
|
||||
# self.disconnect(self.watched)
|
||||
# if "digital_io" in interpreted:
|
||||
# if interpreted["digital_io"]["emergency"] is True and self.cycle_state != "emergency":
|
||||
# self.cycle_state = "emergency"
|
||||
# self.next()
|
||||
# elif interpreted["digital_io"]["emergency"] is False and self.cycle_state == "emergency" and self.is_first_cycle_time:
|
||||
# self.is_first_cycle_time = False
|
||||
# # reset cycle
|
||||
# if self.recipe is None:
|
||||
# self.cycle_state = -1 # go to recipe selection
|
||||
# else:
|
||||
# self.cycle_state = 0 # skip recipe selection
|
||||
# self.next(fail=True)
|
||||
# if type(self.centralWidget()) is not Test_Autotest: # IGNORE DURING AUTOTEST
|
||||
# if self.cycle_state == 1: # WAIT FOR PIECE PRESENCE
|
||||
# if self.testing is True and self.is_first_cycle_time:
|
||||
# self.bench.inputs["io"].set_bit(*self.bench.parsers["digital_io"].presence1, True)
|
||||
# self.bench.inputs["io"].set_bit(*self.bench.parsers["digital_io"].presence2, True)
|
||||
# # /TESTING
|
||||
# if self.is_first_cycle_time:
|
||||
# self.is_first_cycle_time = False
|
||||
# log_msg("cycle state:", self.cycle_state, "done", msg_type="test")
|
||||
# if "digital_io" in interpreted and interpreted["digital_io"]["presence1"] and interpreted["digital_io"]["presence2"]:
|
||||
# self.bench.parsers["digital_io"].handler({"lock": True})
|
||||
# self.next()
|
||||
# elif self.cycle_state == 2: # PIECE INSERTED, LOCK PIECE AFTER DELAY
|
||||
# if self.is_first_cycle_time:
|
||||
# self.is_first_cycle_time = False
|
||||
# log_msg("cycle state:", self.cycle_state, "done", msg_type="test")
|
||||
# self.timer.start(2000)
|
||||
# elif self.cycle_state == 4: # CAMERA TEST & BARCODE READ DONE, START ASSEMBLY PHASE
|
||||
# if self.is_first_cycle_time:
|
||||
# self.is_first_cycle_time = False
|
||||
# log_msg("cycle state:", self.cycle_state, "done", msg_type="test")
|
||||
# self.timer.start(2000)
|
||||
# elif self.cycle_state == 5: # WAIT FOR SCREWDRIVER COUNTS
|
||||
# if self.is_first_cycle_time and self.bench.parsers["pick_to_light"].request is None:
|
||||
# self.bench.parsers["pick_to_light"].handler({
|
||||
# "vtfe10": self.recipe.vtfe10,
|
||||
# "vtfe11": self.recipe.vtfe11,
|
||||
# "vtfe13": self.recipe.vtfe13,
|
||||
# })
|
||||
# log_msg("SCREWDRIVER ENABLE", msg_type="test")
|
||||
# elif "pick_to_light" in interpreted and interpreted["pick_to_light"] is not None:
|
||||
# screws = [interpreted["pick_to_light"][k] for k in ["vtfe10", "vtfe11", "vtfe13"]]
|
||||
# needed = [self.bench.parsers["pick_to_light"].request[k] for k in ["vtfe10", "vtfe11", "vtfe13"]]
|
||||
# done = all([screwed >= requested for screwed, requested in zip(screws, needed)])
|
||||
# self.screw_text(screws)
|
||||
# if self.is_first_cycle_time and done:
|
||||
# self.is_first_cycle_time = False
|
||||
# log_msg("cycle state:", self.cycle_state, "done", msg_type="test")
|
||||
# self.bench.parsers["pick_to_light"].handler(None)
|
||||
# self.screw_text([0, 0, 0])
|
||||
# self.bench.parsers["digital_io"].handler({"lock": False})
|
||||
# self.next()
|
||||
# elif self.cycle_state == 6:
|
||||
# # TESTING
|
||||
# if self.testing is True:
|
||||
# self.bench.inputs["io"].set_bit(*self.bench.parsers["digital_io"].presence1, False)
|
||||
# self.bench.inputs["io"].set_bit(*self.bench.parsers["digital_io"].presence2, False)
|
||||
# # /TESTING
|
||||
# if not self.is_done:
|
||||
# self.is_done = True
|
||||
# self.done(True)
|
||||
# if self.is_done and "digital_io" in interpreted and not interpreted["digital_io"]["presence1"] and not interpreted["digital_io"]["presence2"] and self.is_first_cycle_time:
|
||||
# self.is_first_cycle_time = False
|
||||
# log_msg("cycle state:", self.cycle_state, "done", msg_type="test")
|
||||
# if self.skip:
|
||||
# # reset cycle
|
||||
# self.cycle_state = 0 # skip recipe selection
|
||||
# self.skip = False
|
||||
# self.next()
|
||||
# else:
|
||||
# self.timer.start(2000)
|
||||
# elif self.cycle_state == 7: # WAITING BEFORE NEW CYCLE
|
||||
# if self.is_first_cycle_time:
|
||||
# self.is_first_cycle_time = False
|
||||
# log_msg("cycle state:", self.cycle_state, "wait", msg_type="test")
|
||||
# # reset cycle
|
||||
# self.cycle_state = 0 # skip recipe selection
|
||||
# self.timer.start(6000)
|
||||
# self.watched = self.bench.interpreter.update.connect(self.check_next)
|
||||
|
||||
def request_autotest(self, reason): # you can cancel the request calling request_autotest(False)
|
||||
self.log.info(f"cycle request autotest: reason: {reason!r} autotest_request: {self.autotest_request!r}")
|
||||
if reason == "init":
|
||||
|
|
@ -219,11 +141,10 @@ class Test(Widget):
|
|||
if action == "change_recipe":
|
||||
self.log.info(f"cycle next: action: {action!r}")
|
||||
self.set_recipe(recipe=None)
|
||||
self.cycle_changing_state = True
|
||||
self.cycle_state = "select_recipe"
|
||||
self.cycle_index = -1
|
||||
# RESET TEST DATA
|
||||
self.data = None
|
||||
self.data.clear()
|
||||
elif action == "fail":
|
||||
self.log.info(f"cycle next: action: {action!r}")
|
||||
if self.cycle_state in self.cycle_loop:
|
||||
|
|
@ -231,32 +152,29 @@ class Test(Widget):
|
|||
# COUNT FAIL
|
||||
self.pieces[1] += 1
|
||||
# FAIL AND RESTART TEST
|
||||
self.cycle_changing_state = True
|
||||
self.cycle_state = "fail"
|
||||
self.cycle_index = -1
|
||||
# RESET TEST DATA
|
||||
self.data = None
|
||||
self.data.clear()
|
||||
elif action is not None:
|
||||
raise NotImplementedError(f"cycle next: action {action!r} is not a valid action")
|
||||
# if action did not set the next cycle_state
|
||||
# set next cycle_state normally
|
||||
if not self.cycle_changing_state:
|
||||
self.cycle_changing_state = True
|
||||
if self.recipe is None:
|
||||
# if recipe not set: select_recipe
|
||||
self.cycle_state = "select_recipe"
|
||||
if self.recipe is None:
|
||||
# if recipe not set: select_recipe
|
||||
self.cycle_state = "select_recipe"
|
||||
else:
|
||||
if self.cycle_index == -1 and self.autotest_request is not False:
|
||||
# if cycle_loop is not started or has ended
|
||||
# and autotest was requested
|
||||
self.autotest_request = False
|
||||
self.cycle_state = "autotest"
|
||||
if self.autotest_period is not None: # reset periodic autotest timer
|
||||
self.time_timer.start(self.autotest_period)
|
||||
else:
|
||||
if self.cycle_index == -1 and self.autotest_request is not False:
|
||||
# if cycle_loop is not started or has ended
|
||||
# and autotest was requested
|
||||
self.autotest_request = False
|
||||
self.cycle_state = "autotest"
|
||||
if self.autotest_period is not None: # reset periodic autotest timer
|
||||
self.time_timer.start(self.autotest_period)
|
||||
else:
|
||||
# goto next step in cycle_loop
|
||||
self.cycle_index = (self.cycle_index + 1) % len(self.cycle_loop)
|
||||
self.cycle_state = self.cycle_loop[self.cycle_index]
|
||||
# goto next step in cycle_loop
|
||||
self.cycle_index = (self.cycle_index + 1) % len(self.cycle_loop)
|
||||
self.cycle_state = self.cycle_loop[self.cycle_index]
|
||||
# enable/disable cycle controls
|
||||
self.change_recipe_b.setEnabled(self.recipe is not None)
|
||||
self.cancel_b.setEnabled(self.cycle_state not in {
|
||||
|
|
@ -268,16 +186,18 @@ class Test(Widget):
|
|||
self.log.info(f"cycle next: next cycle_state: {self.cycle_state!r}")
|
||||
# INIT TEST DATA IF STARTING CYCLE LOOP
|
||||
if self.cycle_index == 0:
|
||||
self.data = {}
|
||||
if self.cycle_state == "done":
|
||||
self.done()
|
||||
self.data.clear()
|
||||
w = self.cycle_states[self.cycle_state]
|
||||
if hasattr(w, "start"):
|
||||
w.start()
|
||||
w.start(recipe=self.recipe)
|
||||
self.setCentralWidget(w)
|
||||
if self.cycle_state == "done":
|
||||
self.done()
|
||||
self.next_timer.start(2000)
|
||||
elif self.cycle_state == "wait":
|
||||
self.next_timer.start(6000)
|
||||
# UPDATE PIECES DISPLAY
|
||||
self.pieces_count_l.setText(f"{self.pieces[0]} OK / {self.pieces[1]} NOK / {sum(self.pieces)} TOT")
|
||||
self.setCentralWidget(w)
|
||||
self.cycle_changing_state = False
|
||||
|
||||
def set_recipe(self, recipe=None):
|
||||
self.recipe = recipe
|
||||
|
|
@ -296,7 +216,13 @@ class Test(Widget):
|
|||
self.data["ok"] = self.data.get("ok", True) and self.data["vision"].get("ok", False)
|
||||
self.next()
|
||||
|
||||
def done(self, ok=False):
|
||||
def set_leak(self, leak=None):
|
||||
self.data["leak"] = leak
|
||||
self.data["overridden"] = self.data.get("overridden", False) or self.data["leak"].get("overridden", False)
|
||||
self.data["ok"] = self.data.get("ok", True) and self.data["leak"].get("ok", False)
|
||||
self.next()
|
||||
|
||||
def done(self, ok=False, next=False):
|
||||
self.log.info("cycle done")
|
||||
archived = Archive.archive(self.recipe, self.data, ok and self.data["ok"], overridden=self.data["overridden"])
|
||||
self.log.info(f"cycle archived locally: {archived!r}")
|
||||
|
|
|
|||
1
src/ui/test_leak/__init__.py
Normal file
1
src/ui/test_leak/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .test_leak import Test_Leak
|
||||
55
src/ui/test_leak/test_leak.py
Normal file
55
src/ui/test_leak/test_leak.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
from ui.test_test import Test_Test
|
||||
|
||||
|
||||
class Test_Leak(Test_Test):
|
||||
def start(self, recipe=None):
|
||||
super().start(recipe=recipe)
|
||||
# setup test loop
|
||||
self.components["tecna_t3"].write_recipe(self.recipe)
|
||||
self.get_connection = self.components["tecna_t3"].out.connect(self.get)
|
||||
self.components["tecna_t3"].resume()
|
||||
self.components["tecna_t3"].start_test()
|
||||
|
||||
def stop(self):
|
||||
# disable tes loop
|
||||
self.components["tecna_t3"].stop_test()
|
||||
self.components["tecna_t3"].pause()
|
||||
self.disconnect(self.get_connection)
|
||||
super().stop()
|
||||
|
||||
def get(self, data=None, override=False):
|
||||
if self.ok_timer.isActive():
|
||||
# avoid proccessing if vision was completed
|
||||
return
|
||||
if data is None or data[-1] is None:
|
||||
super().get(None, override=override)
|
||||
return
|
||||
data = data[-1]
|
||||
super().get([{
|
||||
"time": data.get("time", None),
|
||||
"results": {
|
||||
"ok": type(data["tecna_t3"]["Running test: result"]) is str and "passed" in data["tecna_t3"]["Running test: result"].lower(),
|
||||
"result": data["tecna_t3"]["Running test: result"],
|
||||
"data": data["tecna_t3"],
|
||||
},
|
||||
}], override=override)
|
||||
|
||||
def visualize(self, data=None):
|
||||
if data is None:
|
||||
data = {}
|
||||
d = data.get("results", {}).get("data", {})
|
||||
for register, label in {
|
||||
"Instrument status: active phase": self.test_phase_l,
|
||||
"Test circuit pressure, in real time": self.circuit_pressure_l,
|
||||
"Measured leak, in real time": self.leak_l,
|
||||
"Regulated pressure, in real time": self.regulated_pressure_l,
|
||||
# "Active alarm flags": self._l,
|
||||
"Running test: type of test": self.test_type_l,
|
||||
"Testing in progress: progressive sequence index": self.sequence_index_l,
|
||||
}.items():
|
||||
label.setText(str(d.get(register, "-")))
|
||||
super().visualize(data)
|
||||
|
||||
def save_last(self):
|
||||
if self.last is None:
|
||||
return
|
||||
230
src/ui/test_leak/test_leak.ui
Normal file
230
src/ui/test_leak/test_leak.ui
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Leak</class>
|
||||
<widget class="QWidget" name="Leak">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>322</width>
|
||||
<height>329</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Leak</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Test sequence index:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Regulated pressure:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Status:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Leak:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="leak_l">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QLabel" name="sequence_index_l">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="circuit_pressure_l">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Circuit pressure:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="regulated_pressure_l">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="instrument_status_l">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QPushButton" name="save_b">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SALVA IMMAGINE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Instrument status:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Type of test:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Risultato</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QProgressBar" name="ok_counter_pb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%v / %m</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="state_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLabel" name="test_type_l">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QPushButton" name="override_b">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FORZA ACCETTAZIONE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="img_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Test phase</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="test_phase_l">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
1
src/ui/test_test/__init__.py
Normal file
1
src/ui/test_test/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .test_test import Test_Test
|
||||
167
src/ui/test_test/test_test.py
Normal file
167
src/ui/test_test/test_test.py
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
import sys
|
||||
|
||||
from lib.helpers import timing
|
||||
from PyQt5.QtCore import Qt, QTimer, pyqtSignal
|
||||
from PyQt5.QtGui import QColor, QPalette, QPixmap
|
||||
from ui import Dialog
|
||||
from ui.test_admin_permission import Test_Admin_Permission
|
||||
from ui.widget import Widget
|
||||
|
||||
|
||||
class Test_Test(Widget):
|
||||
ok = pyqtSignal(dict)
|
||||
ko = pyqtSignal(dict)
|
||||
|
||||
def __init__(self, components=None, recipe=None):
|
||||
super().__init__()
|
||||
self.components = components
|
||||
self.recipe = recipe
|
||||
# setup variables
|
||||
self.ok_counter = 0
|
||||
self.ok_counter_limit = 1
|
||||
# setup controls
|
||||
self.ok_timer = QTimer()
|
||||
self.ok_timer.setSingleShot(True)
|
||||
self.ok_timer.setInterval(2000)
|
||||
self.ok_timer.timeout.connect(self.emit_ok)
|
||||
# setup save frame button
|
||||
self.last = None
|
||||
self.save_b.setEnabled(False)
|
||||
self.save_b.clicked.connect(self.save_last)
|
||||
# setup override
|
||||
self.admin_challenged = False
|
||||
self.override_b.clicked.connect(self.override)
|
||||
self.override_b.setEnabled(True)
|
||||
# setup vision staus gui
|
||||
self.status_imgs_full = {
|
||||
True: QPixmap("src/ui/imgs/success.png"),
|
||||
"": QPixmap("src/ui/imgs/neo.ico"),
|
||||
"warning": QPixmap("src/ui/imgs/warning.png"),
|
||||
False: QPixmap("src/ui/imgs/fail.png"),
|
||||
None: QPixmap("src/ui/imgs/wait.png"),
|
||||
}
|
||||
self.status_imgs_small = {k: i.scaled(32, 32, Qt.KeepAspectRatio, Qt.SmoothTransformation) for k, i in self.status_imgs_full.items()}
|
||||
self.status_palettes = {
|
||||
True: QPalette(),
|
||||
"": QPalette(),
|
||||
"warning": QPalette(),
|
||||
False: QPalette(),
|
||||
None: QPalette(),
|
||||
}
|
||||
self.status_palettes[True].setColor(QPalette.Base, Qt.green)
|
||||
self.status_palettes[False].setColor(QPalette.Base, Qt.red)
|
||||
self.status_palettes["warning"].setColor(QPalette.Base, QColor(255, 165, 0))
|
||||
self.status_palettes[""].setColor(QPalette.Base, QColor(255, 255, 0))
|
||||
self.visualize()
|
||||
|
||||
def start(self, recipe=None):
|
||||
self.recipe = recipe
|
||||
self.visualize()
|
||||
# start test
|
||||
self.start_time = timing()
|
||||
# TESTING
|
||||
if "--test" in sys.argv:
|
||||
if hasattr(self, "_test_overridden_test_"):
|
||||
del self._test_overridden_test_
|
||||
# /TESTING
|
||||
|
||||
def stop(self):
|
||||
pass
|
||||
|
||||
def get(self, data=None, override=False):
|
||||
if self.ok_timer.isActive():
|
||||
# avoid proccessing if test was completed
|
||||
return
|
||||
if data is None:
|
||||
if self.last is not None:
|
||||
data = self.last
|
||||
else:
|
||||
data = {}
|
||||
else:
|
||||
data = data[-1]
|
||||
if not override:
|
||||
result_ok = data.get("results", {}).get("ok", False)
|
||||
else:
|
||||
result_ok = True
|
||||
self.last = {
|
||||
**data,
|
||||
"overridden": override,
|
||||
"duration": timing() - self.start_time,
|
||||
"ok": result_ok,
|
||||
}
|
||||
if not override:
|
||||
if result_ok is True:
|
||||
self.ok_counter += 1
|
||||
else:
|
||||
self.ok_counter = 0
|
||||
else:
|
||||
self.ok_counter = self.ok_counter_limit
|
||||
# check if completed
|
||||
if self.ok_counter >= self.ok_counter_limit:
|
||||
self.stop()
|
||||
self.ok_timer.start()
|
||||
self.visualize(self.last)
|
||||
# TESTING
|
||||
if "--test" in sys.argv:
|
||||
if not hasattr(self, "_test_overridden_test_"):
|
||||
self._test_overridden_test_ = True
|
||||
self.override_b.click()
|
||||
# /TESTING
|
||||
|
||||
def visualize(self, data=None, img=None):
|
||||
if data is None:
|
||||
data = {}
|
||||
overridden = data.get("overridden", False)
|
||||
results = data.get("results", None)
|
||||
self.save_b.setEnabled(self.last is not None)
|
||||
if overridden:
|
||||
self.state_l.setPixmap(self.status_imgs_small["warning"])
|
||||
elif results is None:
|
||||
self.state_l.setPixmap(self.status_imgs_small[None])
|
||||
elif results.get("ok", False) is True:
|
||||
self.state_l.setPixmap(self.status_imgs_small[True])
|
||||
else:
|
||||
self.state_l.setPixmap(self.status_imgs_small[False])
|
||||
self.ok_counter_pb.setMaximum(self.ok_counter_limit)
|
||||
self.ok_counter_pb.setValue(min(self.ok_counter, self.ok_counter_limit))
|
||||
if self.ok_counter >= self.ok_counter_limit:
|
||||
self.ok_counter_pb.setPalette(self.status_palettes[True])
|
||||
else:
|
||||
self.ok_counter_pb.setPalette(self.status_palettes[False])
|
||||
if img is None:
|
||||
if overridden:
|
||||
self.img = self.status_imgs_full["warning"]
|
||||
else:
|
||||
self.img = self.status_imgs_full[None]
|
||||
else:
|
||||
self.img = img
|
||||
self.resizeEvent()
|
||||
|
||||
def save_last(self):
|
||||
if self.last is None:
|
||||
return
|
||||
|
||||
def resizeEvent(self, event=None):
|
||||
self.img_l.setPixmap(self.img.scaled(self.img_l.width(), self.img_l.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
|
||||
|
||||
def challenge_admin(self, info):
|
||||
if not self.admin_challenged:
|
||||
d = Dialog(parent=self)
|
||||
d.setCentralWidget(Test_Admin_Permission(info))
|
||||
d.setModal(True)
|
||||
d.show()
|
||||
r = d.exec()
|
||||
if r == d.Accepted:
|
||||
self.admin_challenged = True
|
||||
elif r == d.Rejected:
|
||||
self.admin_challenged ^= False
|
||||
else:
|
||||
raise AssertionError("Bad admin challenge dialog return code")
|
||||
return self.admin_challenged
|
||||
|
||||
def override(self):
|
||||
if self.challenge_admin("Si sta tentando di bypassare il test"):
|
||||
self.get(override=True)
|
||||
|
||||
def emit_ok(self):
|
||||
self.ok.emit(self.last)
|
||||
110
src/ui/test_test/test_test.ui
Normal file
110
src/ui/test_test/test_test.ui
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Test</class>
|
||||
<widget class="QWidget" name="Test">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>618</width>
|
||||
<height>835</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="override_b">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>FORZA ACCETTAZIONE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Risultato</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QProgressBar" name="ok_counter_pb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>50</number>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>%v / %m</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="state_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="img_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>700</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="save_b">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>SALVA IMMAGINE</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -1,158 +1,68 @@
|
|||
import sys
|
||||
|
||||
from lib.helpers import timing
|
||||
from PyQt5.QtCore import Qt, QTimer, pyqtSignal
|
||||
from PyQt5.QtGui import QColor, QImage, QPalette, QPixmap
|
||||
from ui import Dialog
|
||||
from ui.test_admin_permission import Test_Admin_Permission
|
||||
from ui.widget import Widget
|
||||
from PyQt5.QtCore import pyqtSignal
|
||||
from PyQt5.QtGui import QImage, QPixmap
|
||||
from ui.test_test import Test_Test
|
||||
|
||||
|
||||
class Test_Vision(Widget):
|
||||
ok = pyqtSignal(dict)
|
||||
class Test_Vision(Test_Test):
|
||||
request_frame = pyqtSignal()
|
||||
|
||||
def __init__(self, components, recipe):
|
||||
super().__init__()
|
||||
self.components = components
|
||||
self.recipe = recipe
|
||||
# setup vision variables
|
||||
self.vision = {}
|
||||
self.vision_ok_counter = 0
|
||||
def __init__(self, components=None, recipe=None):
|
||||
if "--sim-camera" not in sys.argv:
|
||||
self.vision_ok_counter_limit = 2
|
||||
self.ok_counter_limit = 2
|
||||
else:
|
||||
self.vision_ok_counter_limit = 1
|
||||
# setup vision controls
|
||||
self.ok_timer = QTimer()
|
||||
self.ok_timer.setSingleShot(True)
|
||||
self.ok_timer.setInterval(2000)
|
||||
self.ok_timer.timeout.connect(self.emit_ok)
|
||||
# setup save frame button
|
||||
self.last_vision = None
|
||||
self.save_frame_b.setEnabled(False)
|
||||
self.save_frame_b.clicked.connect(self.save_last_vision)
|
||||
# setup vision override
|
||||
self.admin_challenged = False
|
||||
self.vision_overridden = False
|
||||
self.override_b.clicked.connect(self.override_vision)
|
||||
self.override_b.setEnabled(True)
|
||||
# setup vision staus gui
|
||||
self.status_imgs_full = {
|
||||
True: QPixmap("src/ui/imgs/success.png"),
|
||||
"": QPixmap("src/ui/imgs/neo.ico"),
|
||||
"warning": QPixmap("src/ui/imgs/warning.png"),
|
||||
False: QPixmap("src/ui/imgs/fail.png"),
|
||||
None: QPixmap("src/ui/imgs/wait.png"),
|
||||
}
|
||||
self.status_imgs_small = {k: i.scaled(32, 32, Qt.KeepAspectRatio, Qt.SmoothTransformation) for k, i in self.status_imgs_full.items()}
|
||||
self.status_palettes = {
|
||||
True: QPalette(),
|
||||
"": QPalette(),
|
||||
"warning": QPalette(),
|
||||
False: QPalette(),
|
||||
None: QPalette(),
|
||||
}
|
||||
self.status_palettes[True].setColor(QPalette.Base, Qt.green)
|
||||
self.status_palettes[False].setColor(QPalette.Base, Qt.red)
|
||||
self.status_palettes["warning"].setColor(QPalette.Base, QColor(255, 165, 0))
|
||||
self.status_palettes[""].setColor(QPalette.Base, QColor(255, 255, 0))
|
||||
self.visualize_vision()
|
||||
self.ok_counter_limit = 1
|
||||
super().__init__(components, recipe)
|
||||
|
||||
def start(self):
|
||||
self.visualize_vision()
|
||||
# TESTING
|
||||
if "--test" in sys.argv:
|
||||
self.override_b.click()
|
||||
# /TESTING
|
||||
def start(self, recipe=None):
|
||||
super().start(recipe=recipe)
|
||||
# setup camera-vision loop
|
||||
self.components["galaxy_camera"].set_period(period=None) # only get frame on request
|
||||
self.components["galaxy_camera"].add_sources({"test_vision": self.request_frame})
|
||||
self.request_frame_connection = self.components["vision"].out.connect(self.request_frame) # request new frame as soon as vision finishes
|
||||
self.process_vision_connection = self.components["vision"].out.connect(self.process_vision)
|
||||
self.get_connection = self.components["vision"].out.connect(self.get)
|
||||
self.components["vision"].resume()
|
||||
self.components["galaxy_camera"].resume()
|
||||
# start test
|
||||
self.start_time = timing()
|
||||
self.request_frame.emit() # request first frame
|
||||
|
||||
def stop(self):
|
||||
# disable camera-vision loop
|
||||
self.components["galaxy_camera"].pause()
|
||||
self.components["vision"].pause()
|
||||
self.disconnect(self.process_vision_connection)
|
||||
self.disconnect(self.get_connection)
|
||||
self.disconnect(self.request_frame_connection)
|
||||
self.components["galaxy_camera"].remove_sources(["test_vision", ])
|
||||
super().stop()
|
||||
|
||||
def process_vision(self, data=None, override=False):
|
||||
def get(self, data=None, override=False):
|
||||
if self.ok_timer.isActive():
|
||||
# avoid proccessing if vision was completed
|
||||
return
|
||||
if data is None:
|
||||
data = [{"vision": {}}]
|
||||
if data is None or data[-1] is None:
|
||||
super().get(None, override=override)
|
||||
return
|
||||
data = data[-1]
|
||||
time = data.get("time", None)
|
||||
data = data["vision"]
|
||||
frame = data.get("frame", None)
|
||||
detections = data.get("detections", None)
|
||||
results = data.get("results", None)
|
||||
render = data.get("render", None)
|
||||
if not override:
|
||||
result_ok = data.get("vision", {}).get("ok", False)
|
||||
else:
|
||||
result_ok = True
|
||||
self.last_vision = {
|
||||
"time": time,
|
||||
"frame": frame,
|
||||
"detections": detections,
|
||||
"results": results,
|
||||
"render": render,
|
||||
"overridden": override,
|
||||
"vision_duration": timing() - self.start_time,
|
||||
"ok": result_ok,
|
||||
}
|
||||
if not override:
|
||||
if result_ok is True:
|
||||
self.vision_ok_counter += 1
|
||||
else:
|
||||
self.vision_ok_counter = 0
|
||||
else:
|
||||
self.vision_ok_counter = self.vision_ok_counter_limit
|
||||
# check if completed
|
||||
if self.vision_ok_counter >= self.vision_ok_counter_limit:
|
||||
self.stop()
|
||||
self.ok_timer.start()
|
||||
self.visualize_vision(
|
||||
time=time,
|
||||
frame=frame,
|
||||
detections=detections,
|
||||
results=results,
|
||||
render=render,
|
||||
overridden=override,
|
||||
)
|
||||
super().get([{
|
||||
"time": data.get("time", None),
|
||||
"frame": data["vision"].get("frame", None),
|
||||
"detections": data["vision"].get("detections", None),
|
||||
"results": data["vision"].get("results", None),
|
||||
"render": data["vision"].get("render", None),
|
||||
}], override=override)
|
||||
|
||||
def visualize_vision(self, time=None, frame=None, detections=None, results=None, render=None, overridden=False):
|
||||
self.save_frame_b.setEnabled(self.last_vision is not None)
|
||||
def visualize(self, data=None):
|
||||
if data is None:
|
||||
data = {}
|
||||
overridden = data.get("overridden", False)
|
||||
frame = data.get("frame", None)
|
||||
render = data.get("render", None)
|
||||
if overridden:
|
||||
self.state_l.setPixmap(self.status_imgs_small["warning"])
|
||||
elif results is None:
|
||||
self.state_l.setPixmap(self.status_imgs_small[None])
|
||||
elif results.get("ok", False) is True:
|
||||
self.state_l.setPixmap(self.status_imgs_small[True])
|
||||
else:
|
||||
self.state_l.setPixmap(self.status_imgs_small[False])
|
||||
self.ok_counter_pb.setMaximum(self.vision_ok_counter_limit)
|
||||
self.ok_counter_pb.setValue(min(self.vision_ok_counter, self.vision_ok_counter_limit))
|
||||
if self.vision_ok_counter >= self.vision_ok_counter_limit:
|
||||
self.ok_counter_pb.setPalette(self.status_palettes[True])
|
||||
else:
|
||||
self.ok_counter_pb.setPalette(self.status_palettes[False])
|
||||
if overridden:
|
||||
self.img = self.status_imgs_full["warning"]
|
||||
img = self.status_imgs_full["warning"]
|
||||
elif render is not None:
|
||||
self.img = render
|
||||
img = render
|
||||
elif frame is not None:
|
||||
self.img = QPixmap.fromImage(QImage(
|
||||
img = QPixmap.fromImage(QImage(
|
||||
frame.data,
|
||||
frame.shape[1], # width
|
||||
frame.shape[0], # height
|
||||
|
|
@ -160,34 +70,14 @@ class Test_Vision(Widget):
|
|||
QImage.Format_RGB888
|
||||
))
|
||||
else:
|
||||
self.img = self.status_imgs_full[None]
|
||||
self.resizeEvent()
|
||||
img = self.status_imgs_full[None]
|
||||
super().visualize(data, img=img)
|
||||
|
||||
def save_last_vision(self):
|
||||
if self.last_vision is None:
|
||||
def save_last(self):
|
||||
if self.last is None:
|
||||
return
|
||||
|
||||
def resizeEvent(self, event=None):
|
||||
self.frame_l.setPixmap(self.img.scaled(self.frame_l.width(), self.frame_l.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
|
||||
|
||||
def challenge_admin(self, info):
|
||||
if not self.admin_challenged:
|
||||
d = Dialog()
|
||||
d.setCentralWidget(Test_Admin_Permission(info))
|
||||
d.setModal(True)
|
||||
d.show()
|
||||
r = d.exec()
|
||||
if r == d.Accepted:
|
||||
self.admin_challenged = True
|
||||
elif r == d.Rejected:
|
||||
self.admin_challenged ^= False
|
||||
else:
|
||||
raise AssertionError("Bad admin challenge dialog return code")
|
||||
return self.admin_challenged
|
||||
|
||||
def override_vision(self):
|
||||
if self.challenge_admin("Si sta tentando di bypassare il test di visione"):
|
||||
self.process_vision(override=True)
|
||||
|
||||
def emit_ok(self):
|
||||
self.ok.emit(self.last_vision)
|
||||
self.last.pop("frame", None)
|
||||
self.last.pop("render", None)
|
||||
self.ok.emit(self.last)
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="frame_l">
|
||||
<widget class="QLabel" name="img_l">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
@ -91,7 +91,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="save_frame_b">
|
||||
<widget class="QPushButton" name="save_b">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ from ui.dialog import Dialog
|
|||
|
||||
|
||||
class Widget(QWidget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.setAttribute(Qt.WA_DeleteOnClose)
|
||||
me = self.__class__.__name__
|
||||
u = get_resource("ui/{0}/{0}.ui".format(me.lower()))
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ from ui.dialog import Dialog
|
|||
class Window(QMainWindow):
|
||||
_closing = pyqtSignal()
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.setAttribute(Qt.WA_DeleteOnClose)
|
||||
self.setWindowFlags(Qt.Window)
|
||||
me = self.__class__.__name__
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user