diff --git a/config/label_designs/STANDARD/EtichettaR5.nlbl b/config/label_designs/STANDARD/EtichettaR5.nlbl
index 0769605..5af1648 100644
Binary files a/config/label_designs/STANDARD/EtichettaR5.nlbl and b/config/label_designs/STANDARD/EtichettaR5.nlbl differ
diff --git a/config/label_designs/STANDARD/EtichettaR5_Pitesti.nlbl b/config/label_designs/STANDARD/EtichettaR5_Pitesti.nlbl
new file mode 100644
index 0000000..6474ee4
Binary files /dev/null and b/config/label_designs/STANDARD/EtichettaR5_Pitesti.nlbl differ
diff --git a/config/label_templates/ETACL-40_130.prn b/config/label_templates/ETACL-40_130.prn
index 3d374dc..e445358 100644
--- a/config/label_templates/ETACL-40_130.prn
+++ b/config/label_templates/ETACL-40_130.prn
@@ -1,4 +1,4 @@
-SIZE 37.5 mm, 130 mm
+SIZE 27.5 mm, 50 mm
GAP 3 mm, 0 mm
SPEED 2
DENSITY 7
@@ -10,10 +10,9 @@ SET CUTTER OFF
SET PARTIAL_CUTTER OFF
SET TEAR ON
CLS
-DMATRIX 116,270,184,184,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
+DMATRIX 82,230,138,138,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
CODEPAGE 1252
-TEXT 261,377,"ROMAN.TTF",180,1,7,"{RECIPE}-{DD}{MO}{YY}{SN5}"
-DMATRIX 116,175,184,184,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
-DMATRIX 116,78,184,184,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
-BOX 13,16,287,401,3
+TEXT 212,357,"ROMAN.TTF",180,1,7,"{RECIPE}-{DD}{MO}{YY}{SN5}"
+DMATRIX 82,129,138,138,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
+DMATRIX 82,28,138,138,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
PRINT 1,1
diff --git a/config/label_templates/ETACL.prn b/config/label_templates/ETACL.prn
index c610911..e445358 100644
--- a/config/label_templates/ETACL.prn
+++ b/config/label_templates/ETACL.prn
@@ -12,7 +12,7 @@ SET TEAR ON
CLS
DMATRIX 82,230,138,138,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
CODEPAGE 1252
-TEXT 212,357,"ROMAN.TTF",180,1,7,"{RECIPE}-{DD}{MO}{YY}"
+TEXT 212,357,"ROMAN.TTF",180,1,7,"{RECIPE}-{DD}{MO}{YY}{SN5}"
DMATRIX 82,129,138,138,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
DMATRIX 82,28,138,138,x3,22,22,"{RECIPE}-{DD}{MO}{YY}{SN5}"
PRINT 1,1
diff --git a/config/label_templates/EtichettaR5.prn b/config/label_templates/EtichettaR5.prn
index cf1999f..fd3080f 100644
--- a/config/label_templates/EtichettaR5.prn
+++ b/config/label_templates/EtichettaR5.prn
@@ -18,25 +18,25 @@
^XZ
^XA
^MMT
-^PW320
-^LL1119
+^PW496
+^LL1559
^LS0
-^FT33,86^A0N,45,46^FH\^CI28^FDERRECINQUE^FS^CI27
-^BY2,3,56^FT44,310^BCN,,N,N
+^FT61,119^A0N,67,68^FH\^CI28^FDERRECINQUE^FS^CI27
+^BY2,3,83^FT77,430^BCN,,N,N
^FH\^FD>:{PART}^FS
-^FT15,347^A0N,31,30^FH\^CI28^FDPart number:^FS^CI27
-^FT15,427^A0N,31,30^FH\^CI28^FD{PART}^FS^CI27
-^FT17,136^A0N,17,18^FH\^CI28^FDVia Meucci 31/A - 10079 Mappano(TO)^FS^CI27
-^FT53,193^A0N,39,38^FH\^CI28^FDFPT^FS^CI27
-^FT53,235^A0N,39,38^FH\^CI28^FDLEAK TEST^FS^CI27
-^FT15,387^A0N,31,30^FH\^CI28^FD{DESCRIPTION}^FS^CI27
-^FT15,740^A0N,31,30^FH\^CI28^FDSequential number:^FS^CI27
-^FT15,779^A0N,31,30^FH\^CI28^FD{SN5}^FS^CI27
-^FT15,856^A0N,17,18^FH\^CI28^FD{DD}/{MM}/{YY}^FS^CI27
-^FT161,856^A0N,17,18^FH\^CI28^FD{HH}:{MI}:{SS}^FS^CI27
-^FT17,1081^A0N,31,30^FH\^CI28^FDESITO:^FS^CI27
-^FT143,1081^A0N,31,30^FH\^CI28^FDCONFORME^FS^CI27
-^FT15,934^A0N,25,25^FH\^CI28^FDOperatore^FS^CI27
-^FT15,967^A0N,25,25^FH\^CI28^FD{OPERATOR}^FS^CI27
+^FT34,482^A0N,46,46^FH\^CI28^FDPart number:^FS^CI27
+^FT34,595^A0N,46,46^FH\^CI28^FD{PART}^FS^CI27
+^FT37,172^A0N,25,25^FH\^CI28^FDVia Meucci 31/A - 10079 Mappano(TO)^FS^CI27
+^FT91,256^A0N,58,56^FH\^CI28^FDFPT^FS^CI27
+^FT91,312^A0N,58,56^FH\^CI28^FDLEAK TEST^FS^CI27
+^FT34,530^A0N,46,46^FH\^CI28^FD{DESCRIPTION}^FS^CI27
+^FT34,1243^A0N,46,46^FH\^CI28^FDSequential number:^FS^CI27
+^FT34,1291^A0N,46,46^FH\^CI28^FD{SN5}^FS^CI27
+^FT34,1361^A0N,33,33^FH\^CI28^FD{DD}/{MO}/{YY}^FS^CI27
+^FT250,1361^A0N,33,33^FH\^CI28^FD{HH}:{MI}:{SS}^FS^CI27
+^FT37,1487^A0N,46,46^FH\^CI28^FDCHECK:^FS^CI27
+^FT223,1487^A0N,46,46^FH\^CI28^FDCONFORME^FS^CI27
+^FT34,1427^A0N,38,38^FH\^CI28^FDOperatore^FS^CI27
+^FT223,1427^A0N,38,38^FH\^CI28^FD{OPERATOR}^FS^CI27
^PQ1,0,1,Y
^XZ
diff --git a/config/label_templates/EtichettaR5_Pitesti.prn b/config/label_templates/EtichettaR5_Pitesti.prn
new file mode 100644
index 0000000..7d4787a
--- /dev/null
+++ b/config/label_templates/EtichettaR5_Pitesti.prn
@@ -0,0 +1,45 @@
+CT~~CD,~CC^~CT~
+^XA
+~TA000
+~JSN
+^LT0
+^MNW
+^MTT
+^PON
+^PMN
+^LH0,0
+^JMA
+^PR2,2
+~SD22
+^JUS
+^LRN
+^CI27
+^PA0,1,1,0
+^XZ
+^XA
+^MMT
+^PW320
+^LL1119
+^LS0
+^FT57,105^A0N,39,38^FH\^CI28^FDERRECINQUE^FS^CI27
+^FT58,148^A0N,20,20^FH\^CI28^FDVia Meucci 31/A^FS^CI27
+^FT58,173^A0N,20,20^FH\^CI28^FD10079 Mappano(TO)^FS^CI27
+^FT18,758^A0N,23,20^FH\^CI28^FD{DD}/{MO}/{YY}^FS^CI27
+^FT183,758^A0N,23,20^FH\^CI28^FD{HH}:{MI}:{SS}^FS^CI27
+^FT18,981^A0N,31,30^FH\^CI28^FDESITO:^FS^CI27
+^FT144,981^A0N,31,30^FH\^CI28^FDCONFORME^FS^CI27
+^FT24,471^A0N,25,25^FH\^CI28^FDPart number:^FS^CI27
+^FT24,513^A0N,23,23^FH\^CI28^FD{PART}^FS^CI27
+^FT24,555^A0N,25,25^FH\^CI28^FDSequential number:^FS^CI27
+^FT24,598^A0N,23,23^FH\^CI28^FD{SN4}^FS^CI27
+^FT18,833^A0N,23,23^FH\^CI28^FDOperatore:^FS^CI27
+^FT157,674^A0N,23,23^FH\^CI28^FD{RESLEAK} mbar^FS^CI27
+^FT18,674^A0N,23,23^FH\^CI28^FD{TTEST} s^FS^CI27
+^FT18,724^A0N,23,23^FH\^CI28^FD{PTEST} mbar^FS^CI27
+^BY1,3,64^FT58,384^BCN,,N,N
+^FH\^FD>:{PART}^FS
+^FT58,241^A0N,25,25^FH\^CI28^FD{DESCRIPTION}^FS^CI27
+^FT58,292^A0N,45,46^FH\^CI28^FDLEAK TEST^FS^CI27
+^FT165,833^A0N,23,23^FH\^CI28^FD{BADGE_NUM}^FS^CI27
+^PQ1,0,1,Y
+^XZ
diff --git a/config/machine_settings/defaults.ini b/config/machine_settings/defaults.ini
index 23ac1bd..22004bd 100644
--- a/config/machine_settings/defaults.ini
+++ b/config/machine_settings/defaults.ini
@@ -162,9 +162,9 @@ settling_time: 5
settling_pressure_min_percent: 5
settling_pressure_max_percent: 5
test_time: 10
-test_pressure_min_delta: 5
+test_pressure_qneg: 5
test_pressure: 9000
-test_pressure_max_delta: 5
+test_pressure_qpos: 5
flush_time: 1
flush_pressure: 100
diff --git a/config/machine_settings/hostnames.ini b/config/machine_settings/hostnames.ini
index 664d451..819d1f9 100644
--- a/config/machine_settings/hostnames.ini
+++ b/config/machine_settings/hostnames.ini
@@ -2,6 +2,8 @@
ST-TEN-1: st-ten-1
ST-TEN-2: st-ten-2
stten3: st-ten-3
-stten4: st-ten-4
+ST-TEN-4: st-ten-4
st-ten-5: st-ten-5
st-ten-6: st-ten-6
+st-ten-7: st-ten-7
+st-ten-8: st-ten-8
diff --git a/config/machine_settings/st-ten-1.ini b/config/machine_settings/st-ten-1.ini
index 5a60b38..0a022fa 100644
--- a/config/machine_settings/st-ten-1.ini
+++ b/config/machine_settings/st-ten-1.ini
@@ -10,7 +10,7 @@ neo_pixels: present
remote_api: absent
tecna_t3: present
vision_saver: present
-vision: absent
+vision: present
screwdriver: present
[tecna_t3]
@@ -29,3 +29,67 @@ description_field: descrizione
[label_printer]
platform: windows
printer: zd420
+
+[recipes_defaults]
+
+
+codice_ricetta: specificare ricetta
+cliente: IVECO
+part_number: specificare part number
+config_elettrovalvole: 0
+warning_img:
+
+dimensione_lotto_abilitata:
+
+istruzione_abilitata: x
+numero nastri (n):0
+numero sensori anello (sa):0
+numero sensori presenza (sp):0
+
+prova_tenuta_abilitata: x
+tempo_pre_riempimento: 0
+pressione_pre_riempimento: 5000
+tempo_riempimento: 5
+tempo_assestamento: 10
+percentuale_minima_pressione_assestamento: 5
+percentuale_massima_pressione_assestamento: 5
+tempo_di_test: 10
+pressione_di_test_delta_minimo: 30
+pressione_di_test: 5000
+pressione_di_test_delta_massimo: 30
+tempo_svuotamento: 1
+pressione_svuotamento: 100
+
+prova_tenuta_abilitata_2:
+tempo_pre_riempimento_2: 0
+pressione_pre_riempimento_2: 1000
+tempo_riempimento_2: 5
+tempo_assestamento_2: 5
+percentuale_minima_pressione_assestamento_2: 5
+percentuale_massima_pressione_assestamento_2: 5
+tempo_di_test_2: 5
+pressione_di_test_delta_minimo_2: 200
+pressione_di_test_2: 1000
+pressione_di_test_delta_massimo_2: 200
+tempo_svuotamento_2: 1
+pressione_svuotamento_2: 100
+
+stampa_etichetta_abilitata: x
+modello_etichetta: ETA30x16_203dpi.prn
+descrizione: inserire descrizione ricetta
+
+[autotest_leak]
+enabled: true
+pre_filling_time: 0
+pre_filling_pressure: 1000
+filling_time: 15
+settling_time: 10
+settling_pressure_min_percent: 5
+settling_pressure_max_percent: 5
+test_time: 10
+test_pressure_qneg: 10
+test_pressure: 7000
+test_pressure_qpos: 5
+flush_time: 1
+flush_pressure: 100
+relay_config: 1
\ No newline at end of file
diff --git a/config/machine_settings/st-ten-2.ini b/config/machine_settings/st-ten-2.ini
index 41cc687..621a3ef 100644
--- a/config/machine_settings/st-ten-2.ini
+++ b/config/machine_settings/st-ten-2.ini
@@ -39,3 +39,19 @@ pressione_di_test_delta_massimo: 30
tempo_svuotamento: 1
pressione_svuotamento: 100
config_elettrovalvole: 0
+
+[autotest_leak]
+enabled: true
+pre_filling_time: 0
+pre_filling_pressure: 1000
+filling_time: 5
+settling_time: 10
+settling_pressure_min_percent: 5
+settling_pressure_max_percent: 5
+test_time: 10
+test_pressure_qneg: 5
+test_pressure: 9000
+test_pressure_qpos: 5
+flush_time: 1
+flush_pressure: 100
+relay_config: 1
\ No newline at end of file
diff --git a/config/machine_settings/st-ten-5.ini b/config/machine_settings/st-ten-5.ini
index 58b56e5..228f784 100644
--- a/config/machine_settings/st-ten-5.ini
+++ b/config/machine_settings/st-ten-5.ini
@@ -10,6 +10,7 @@ remote_api: absent
tecna_t3: present
digital_io: present
barcode_recipe_selection: present
+show_instructions: yes
[tecna_t3]
port: COM4
@@ -90,9 +91,9 @@ settling_time: 10
settling_pressure_min_percent: 5
settling_pressure_max_percent: 5
test_time: 10
-test_pressure_min_delta: 10
+test_pressure_qneg: 10
test_pressure: 5000
-test_pressure_max_delta: 5
+test_pressure_qpos: 5
flush_time: 1
flush_pressure: 100
relay_config: 1
\ No newline at end of file
diff --git a/config/machine_settings/st-ten-6.ini b/config/machine_settings/st-ten-6.ini
index 6fd8e6b..46555b6 100644
--- a/config/machine_settings/st-ten-6.ini
+++ b/config/machine_settings/st-ten-6.ini
@@ -3,8 +3,7 @@ description = ST-TEN-6 DOPPIA PROVA PRESSIONE 6/20 BAR
[hardware_config]
archive_synchronizer: present
-; galaxy_camera: present
-uvc_camera: present
+uvc_camera: absent
label_printer: present
neo_pixels: present
remote_api: absent
@@ -28,6 +27,7 @@ printer: zd421
[digital_io]
id: USB-5860,BID#0
+
[recipe]
recipe_name_field: codice_ricetta
part_number_field: codice_prodotto
@@ -38,8 +38,8 @@ description_field: descrizione
dimensione_lotto_abilitata:
tempo_pre_riempimento: 0
pressione_pre_riempimento: 1000
-tempo_riempimento: 15
-tempo_assestamento: 15
+tempo_riempimento: 10
+tempo_assestamento: 10
tempo_di_test: 10
percentuale_minima_pressione_assestamento: 5
percentuale_massima_pressione_assestamento: 5
@@ -52,8 +52,8 @@ config_elettrovalvole: 1
prova_tenuta_abilitata_2:
tempo_pre_riempimento_2: 0
pressione_pre_riempimento_2: 1000
-tempo_riempimento_2: 20
-tempo_assestamento_2: 20
+tempo_riempimento_2: 10
+tempo_assestamento_2: 10
tempo_di_test_2: 10
percentuale_minima_pressione_assestamento_2: 5
percentuale_massima_pressione_assestamento_2: 5
@@ -69,14 +69,16 @@ modello_etichetta: EtichettaR5_Montaggio_1prova.prn
enabled: true
pre_filling_time: 0
pre_filling_pressure: 1000
-filling_time: 15
+filling_time: 10
settling_time: 10
settling_pressure_min_percent: 5
settling_pressure_max_percent: 5
+test_pressure: 7000
test_time: 10
-test_pressure_min_delta: 35
-test_pressure: 15000
-test_pressure_max_delta: 5
+test_pressure_qpos: 5 #Q+ Upper test leak limit
+test_pressure_qneg: 15 #Q- Lower test leak limit
+test_pressure_tt_qpos: 0 # Q+ Upper test leak limit (tube-tube)
+test_pressure_tt_qneg: 5 # Q- Lower test leak limit (tube-tube)
flush_time: 1
flush_pressure: 100
relay_config: 1
\ No newline at end of file
diff --git a/config/machine_settings/st-ten-7.ini b/config/machine_settings/st-ten-7.ini
new file mode 100644
index 0000000..3b3e1f8
--- /dev/null
+++ b/config/machine_settings/st-ten-7.ini
@@ -0,0 +1,82 @@
+[machine]
+description = ST-TEN-7 SECONDO BANCO IVECO DAILY ELETTRICO
+
+[hardware_config]
+archive_synchronizer: present
+uvc_camera: absent
+label_printer: present
+neo_pixels: present
+remote_api: absent
+tecna_t3: present
+vision_saver: absent
+vision: absent
+screwdriver: absent
+digital_io: present
+second_leak_test: present
+
+[tecna_t3]
+port: COM4
+model: t3l
+
+[neo_pixels]
+port: COM5
+
+[label_printer]
+platform: windows
+printer: zd421
+
+[digital_io]
+id: USB-5860,BID#0
+
+[recipe]
+recipe_name_field: codice_ricetta
+part_number_field: codice_prodotto
+label_template_field: modello_etichetta
+description_field: descrizione
+
+[recipes_defaults]
+dimensione_lotto_abilitata:
+tempo_pre_riempimento: 0
+pressione_pre_riempimento: 1000
+tempo_riempimento: 15
+tempo_assestamento: 15
+tempo_di_test: 10
+percentuale_minima_pressione_assestamento: 5
+percentuale_massima_pressione_assestamento: 5
+pressione_di_test_delta_minimo: 30
+pressione_di_test: 7000
+pressione_di_test_delta_massimo: 30
+tempo_svuotamento: 1
+pressione_svuotamento: 100
+config_elettrovalvole: 1
+prova_tenuta_abilitata_2:
+tempo_pre_riempimento_2: 0
+pressione_pre_riempimento_2: 1000
+tempo_riempimento_2: 20
+tempo_assestamento_2: 20
+tempo_di_test_2: 10
+percentuale_minima_pressione_assestamento_2: 5
+percentuale_massima_pressione_assestamento_2: 5
+pressione_di_test_delta_minimo_2: 30
+pressione_di_test_2: 15000
+pressione_di_test_delta_massimo_2: 30
+tempo_svuotamento_2: 1
+pressione_svuotamento_2: 100
+config_elettrovalvole_2: 2
+modello_etichetta: EtichettaR5_Montaggio_1prova.prn
+
+[autotest_leak]
+enabled: true
+pre_filling_time: 0
+pre_filling_pressure: 1000
+filling_time: 15
+settling_time: 10
+settling_pressure_min_percent: 5
+settling_pressure_max_percent: 5
+test_time: 10
+test_pressure_qneg: 35
+test_pressure: 15000
+test_pressure_qpos: 5
+flush_time: 1
+flush_pressure: 100
+relay_config: 1
\ No newline at end of file
diff --git a/config/machine_settings/st-ten-8.ini b/config/machine_settings/st-ten-8.ini
new file mode 100644
index 0000000..f9d764b
--- /dev/null
+++ b/config/machine_settings/st-ten-8.ini
@@ -0,0 +1,85 @@
+[machine]
+description = ST-TEN-8 DAILY AUTOMATICO
+
+[hardware_config]
+archive_synchronizer: present
+uvc_camera: absent
+label_printer: present
+neo_pixels: absent
+remote_api: absent
+tecna_t3: present
+vision_saver: absent
+vision: absent
+screwdriver: absent
+digital_io: present
+second_leak_test: absent
+fixture_id: present
+discard_box: present
+
+[tecna_t3]
+port: COM4
+model: t3l
+
+[label_printer]
+platform: windows
+printer: zd421
+
+[digital_io]
+id: USB-5860,BID#0
+discard_idx:15 # BIT NUMBER OF THE I/0 MODULE USED FOR DISCARD SENSING
+
+[fixture_rfid]
+port: COM5
+
+[recipe]
+recipe_name_field: codice_ricetta
+part_number_field: codice_prodotto
+label_template_field: modello_etichetta
+description_field: descrizione
+
+[recipes_defaults]
+dimensione_lotto_abilitata:
+tempo_pre_riempimento: 0
+pressione_pre_riempimento: 1000
+tempo_riempimento: 15
+tempo_assestamento: 15
+tempo_di_test: 10
+percentuale_minima_pressione_assestamento: 5
+percentuale_massima_pressione_assestamento: 5
+pressione_di_test_delta_minimo: 30
+pressione_di_test: 7000
+pressione_di_test_delta_massimo: 30
+tempo_svuotamento: 1
+pressione_svuotamento: 100
+config_elettrovalvole: 1
+prova_tenuta_abilitata_2:
+tempo_pre_riempimento_2: 0
+pressione_pre_riempimento_2: 1000
+tempo_riempimento_2: 20
+tempo_assestamento_2: 20
+tempo_di_test_2: 10
+percentuale_minima_pressione_assestamento_2: 5
+percentuale_massima_pressione_assestamento_2: 5
+pressione_di_test_delta_minimo_2: 30
+pressione_di_test_2: 15000
+pressione_di_test_delta_massimo_2: 30
+tempo_svuotamento_2: 1
+pressione_svuotamento_2: 100
+config_elettrovalvole_2: 2
+modello_etichetta: EtichettaR5_Montaggio_1prova.prn
+
+[autotest_leak]
+enabled: true
+pre_filling_time: 0
+pre_filling_pressure: 1000
+filling_time: 15
+settling_time: 10
+settling_pressure_min_percent: 5
+settling_pressure_max_percent: 5
+test_time: 10
+test_pressure_qneg: 35
+test_pressure: 15000
+test_pressure_qpos: 5
+flush_time: 1
+flush_pressure: 100
+relay_config: 1
\ No newline at end of file
diff --git a/config/vision/labels/000952054.pbtxt b/config/vision/labels/000952054.pbtxt
new file mode 100644
index 0000000..12fa2ca
--- /dev/null
+++ b/config/vision/labels/000952054.pbtxt
@@ -0,0 +1,10 @@
+item {
+ id: 1
+ name: 'ok'
+ color: '0x55AA55'
+}
+item {
+ id: 2
+ name: 'ko'
+ color: '0xff0000'
+}
diff --git a/config/vision/labels/labels.pbtxt b/config/vision/labels/labels.pbtxt
index 4ab5798..12fa2ca 100644
--- a/config/vision/labels/labels.pbtxt
+++ b/config/vision/labels/labels.pbtxt
@@ -1,10 +1,10 @@
item {
id: 1
- name: 'hs-ok'
+ name: 'ok'
color: '0x55AA55'
}
item {
id: 2
- name: 'hs-ko'
+ name: 'ko'
color: '0xff0000'
}
diff --git a/config/vision/labels/termorestringente_923578.pbtxt b/config/vision/labels/termorestringente_923578.pbtxt
new file mode 100644
index 0000000..4ab5798
--- /dev/null
+++ b/config/vision/labels/termorestringente_923578.pbtxt
@@ -0,0 +1,10 @@
+item {
+ id: 1
+ name: 'hs-ok'
+ color: '0x55AA55'
+}
+item {
+ id: 2
+ name: 'hs-ko'
+ color: '0xff0000'
+}
diff --git a/config/vision/recipes/000952054.ini b/config/vision/recipes/000952054.ini
new file mode 100644
index 0000000..95003a3
--- /dev/null
+++ b/config/vision/recipes/000952054.ini
@@ -0,0 +1,33 @@
+# O-RING PRESENCE DETECTOR
+# FOR FERRARI 000952054
+
+[general]
+name: ORING
+instruction: CONTROLLARE PRESENZA N. 2 O-RING SU RACCORDI
+neural_network: od1-50000
+type: targeted
+
+# POINTS FORMAT:
+# point_name: point_center point_size fill_color border_color border_thickness shape
+# EXAMPLE:
+# name: X,Y W,H 0xAARRGGBB 0xAARRGGBB T SHAPE CLASS
+# ZONES FORMAT:
+# region_name: region_center region_margin class
+# margin can be a box (XM*2,YM*2) or a radius (R)
+# EXAMPLES:
+# name: X,Y XM,YM T SHAPE CLASS
+# name: X,Y R T SHAPE CLASS
+# LABELS FORMAT:
+# label_name: label_start_location font_size fill_color border_color border_thickness text
+# EXAMPLE:
+# name: X,Y S 0xAARRGGBB 0xAARRGGBB T TEXT
+
+[markers]
+
+[zones]
+p1: 430,1140 520,260 ok
+p2: 2900,1140 520,260 ok
+
+[labels]
+p1: 180,900 120 0xffffffff 0xff000000 4 O-RING 1
+p2: 2600,900 120 0xffffffff 0xff000000 4 O-RING 2
diff --git a/config/vision/recipes/termorestringente_923578.ini b/config/vision/recipes/termorestringente_923578.ini
index 861193a..4a05850 100644
--- a/config/vision/recipes/termorestringente_923578.ini
+++ b/config/vision/recipes/termorestringente_923578.ini
@@ -3,6 +3,8 @@
[general]
name: TERMORESTRINGENTE
instruction: CONTROLLARE PRESENZA TERMORESTRINGENTE
+neural_network: hs5-20000
+type: global
# POINTS FORMAT:
# point_name: point_center point_size fill_color border_color border_thickness shape
diff --git a/config/warning_images/generic/Img-07.png b/config/warning_images/generic/Img-07.png
index f76247f..dcccb1d 100644
Binary files a/config/warning_images/generic/Img-07.png and b/config/warning_images/generic/Img-07.png differ
diff --git a/config/warning_images/generic/Img-10.png b/config/warning_images/generic/Img-10.png
new file mode 100644
index 0000000..a8a3ffd
Binary files /dev/null and b/config/warning_images/generic/Img-10.png differ
diff --git a/config/warning_images/generic/Img-11.png b/config/warning_images/generic/Img-11.png
new file mode 100644
index 0000000..0109a3d
Binary files /dev/null and b/config/warning_images/generic/Img-11.png differ
diff --git a/init_win.bat b/init_win.bat
index c7208b9..b266984 100644
--- a/init_win.bat
+++ b/init_win.bat
@@ -2,7 +2,13 @@
:: RUN FROM POWERSHELL W/ADMIN RIGHTS:
:: Set-ExecutionPolicy Unrestricted -Scope CurrentUser
+pip install -r src/requirements.txt
+
+mkdir tmp
cd tmp
+:: Advantech XNAVI
+Invoke-WebRequest -uri "https://downloadt.advantech.com/download/downloadsr.aspx?File_Id=1-2BZC0F1" -usebasicparsing -outfile xnavi.zip
+
:: GXIPY
-Invoke-WebRequest -uri "https://dahengimaging.com/downloads/Galaxy_Windows_EN_32bits%2064bits_1.18.2208.9301.zip" -OutFile Galaxy_Windows_EN_32bits_64bits_1.18.2208.9301.zip
\ No newline at end of file
+Invoke-WebRequest -uri "https://dahengimaging.com/downloads/Galaxy_Windows_EN_32bits%2064bits_1.18.2208.9301.zip" -usebasicparsing -OutFile Galaxy_Windows_EN_32bits_64bits_1.18.2208.9301.zip
\ No newline at end of file
diff --git a/runme_custom.sh b/runme_custom.sh
deleted file mode 100755
index ce0f29a..0000000
--- a/runme_custom.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash -e
-cd "$(dirname "$0")"
-source "./venv/bin/activate" || source "./venv/Scripts/activate" || :
-python -O "./src/main.py" --auto-accept-test-admin-permission --auto-login-admin --no-edgetpu --no-gpu --panel --system-id=st-ten-5 --no-autotest --sim-camera --sim-modbus --sim-os-label-printer --sim-serial --style windows $*
diff --git a/runme_noautotest.bat b/runme_noautotest.bat
new file mode 100644
index 0000000..0e1d578
--- /dev/null
+++ b/runme_noautotest.bat
@@ -0,0 +1,4 @@
+echo on
+SET mypath=%~dp0
+cd %mypath%
+.\venv\Scripts\activate.bat && python -O "./src/main.py" --no-edgetpu --no-tflite --no-autotest
diff --git a/src/components/rfid.py b/src/components/rfid.py
new file mode 100644
index 0000000..69af776
--- /dev/null
+++ b/src/components/rfid.py
@@ -0,0 +1,42 @@
+import ctypes
+import sys
+import platform
+from PyQt5.QtCore import QMutex, Qt, QTimer, pyqtSlot, pyqtSignal
+from .component import Component
+import nfc
+from nfc.clf import RemoteTarget
+
+
+
+is_win = platform.system() == "Windows"
+
+class RFID(Component):
+ def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True):
+ super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
+ self.mutex = QMutex()
+ self.simulate="--sim-rfid" in sys.argv
+ self.clf = nfc.ContactlessFrontend()
+
+ def open_device(self):
+ self.clf.open('tty:USB0:pn532')
+
+ def close_device(self):
+ pass
+
+ @pyqtSlot()
+ def start(self):
+ # ACQUISITION TIMER
+ self.timer = QTimer()
+ self.timer.setTimerType(Qt.PreciseTimer)
+ self.timer.setInterval(int(1000 / 20))
+ self.timer.timeout.connect(self.get)
+ self.timer.start()
+ super().start()
+
+ @pyqtSlot()
+ def get(self):
+ data=None
+ if data is not None:
+ super()._get([data])
+
+
diff --git a/src/components/tecna_marposs_provaset_t3.py b/src/components/tecna_marposs_provaset_t3.py
index 6276e20..93c45f2 100644
--- a/src/components/tecna_marposs_provaset_t3.py
+++ b/src/components/tecna_marposs_provaset_t3.py
@@ -205,15 +205,16 @@ class TecnaMarpossProvasetT3(ModbusComponent):
# READ INFO
info = {r: self.read(r) for r in [
"Real time test pressure output",
- "Real time differential pressure output",
"Real time pressure line regulator",
- "Active alarm flags",
- "Active test program number",
+ #"Real time differential pressure output",
+ #"Active alarm flags",
+ #"Active test program number",
"Running test: active phase",
"Running test: test type",
+ "Running test: measured leak",
"Running test: sequence index",
"Digital inputs status (mask)",
- # "Digital outputs status (mask)",
+ "Digital outputs status (mask)",
]}
if self.model == "t3p":
pass
@@ -222,9 +223,12 @@ class TecnaMarpossProvasetT3(ModbusComponent):
"Active not severe alarm flags",
]})
else:
- raise NotImplementedError(f"techna t3 model {self.model!r} not implemented.")
+ raise NotImplementedError(f"Tecna t3 model {self.model!r} not implemented.")
if info["Running test: active phase"] == "FINE TEST": # "END TEST, WAITING THE START OF A NEW TEST":
info.update(self.get_test_results())
+ for round_me in ["measured leak"]:
+ if round_me in info.keys():
+ info.update({round_me:float(f"{info[round_me]:.2f}")})
self.log.debug(str(info))
super()._get([info])
@@ -251,13 +255,13 @@ class TecnaMarpossProvasetT3(ModbusComponent):
def get_test_results(self):
self.log.info("getting test results")
return {r: self.read(r) for r in [
- "Running test: phase backwards time",
+ #"Running test: phase backwards time",
"Running test: filling pressure",
"Running test: pressure at the end of settling",
- "Running test: burst pressure",
+ #"Running test: burst pressure",
"Running test: measured leak",
- "Running test: calculated leak flow rate",
- "Running test: calculate RVP%",
+ #"Running test: calculated leak flow rate",
+ #"Running test: calculate RVP%",
"Running test: result",
]}
@@ -277,7 +281,8 @@ class TecnaMarpossProvasetT3(ModbusComponent):
# **{769 - 1 + i: (recipe_name[i * 2 + 1] << 8) + recipe_name[i * 2] for i in range(8)}, # print field 2
"Print options": 0b0000000000000000 | self.saver_label_count << 12 | self.saver_print_on_fail << 8 | self.saver_label_template,
"Test type": "Leak Test",
- "Test flags": 0b0110000001011100 if step.spec.get("autotest", False) is not True else 0b0110000001010100,
+ # "Test flags": 0b0110000001011100 if step.spec.get("autotest", False) is not True else 0b0110000001010100,
+ "Test flags": 0b0110100001010100 if step.spec.get("autotest", False) in ("ok_check","ko_check") else 0b0110000001010100,
"T0 - Pre-filling time": step.spec["pre_filling_time"],
"P0 - Pre-filling pressure": step.spec["pre_filling_pressure"],
"T1 - Filling time": step.spec["filling_time"],
@@ -285,9 +290,9 @@ class TecnaMarpossProvasetT3(ModbusComponent):
"PR- - Min pressure tolerance %": step.spec["settling_pressure_min_percent"],
"PR+ - Max pressure tolerance % (P+)": step.spec["settling_pressure_max_percent"],
"T3 - Measure time": step.spec["test_time"],
- "Q- Lower test leak limit": step.spec["test_pressure_min_delta"],
+ "Q- Lower test leak limit": step.spec["test_pressure_qneg"],
"PREL - Nominal test pressure": step.spec["test_pressure"],
- "Q+ Upper test leak limit": step.spec["test_pressure_max_delta"],
+ "Q+ Upper test leak limit": step.spec["test_pressure_qpos"],
"FST - Discharge time": step.spec["flush_time"],
"FSL - Discharge limit": step.spec["flush_pressure"],
}
diff --git a/src/components/tecna_marposs_provaset_t3l_registers.py b/src/components/tecna_marposs_provaset_t3l_registers.py
index cf0bb3f..3b28ab0 100644
--- a/src/components/tecna_marposs_provaset_t3l_registers.py
+++ b/src/components/tecna_marposs_provaset_t3l_registers.py
@@ -80,7 +80,7 @@ registers = {
"Running test: calculated leak flow rate": [42 - 1, {"dt": "32bit_int", "f": 1507, }],
"Running test: calculate RVP%": [44 - 1, {"dt": "32bit_int", }],
"Running test: result": [46 - 1, {"dt": "16bit_uint", "decoding": {
- 1: "LEAK TEST PASSED (also used in Volume+Leak tests)",
+ 1: "LEAK TEST PASSED",
2: "BURST TEST PASSED WITH BURST",
3: "BURST TEST PASSED WITHOUT BURST",
4: "APERTURE TEST PASSED",
diff --git a/src/components/tecna_marposs_provaset_t3p_registers.py b/src/components/tecna_marposs_provaset_t3p_registers.py
index 62a2535..750e8bb 100644
--- a/src/components/tecna_marposs_provaset_t3p_registers.py
+++ b/src/components/tecna_marposs_provaset_t3p_registers.py
@@ -59,7 +59,7 @@ registers = {
"Running test: calculated leak flow rate": [42 - 1, {"dt": "32bit_int", "f": 24, }],
"Running test: calculate RVP%": [44 - 1, {"dt": "32bit_int", }],
"Running test: result": [46 - 1, {"dt": "16bit_uint", "decoding": {
- 1: "LEAK TEST PASSED (also used in Volume+Leak tests)",
+ 1: "LEAK TEST PASSED",
2: "BURST TEST PASSED WITH BURST",
3: "BURST TEST PASSED WITHOUT BURST",
4: "APERTURE TEST PASSED",
diff --git a/src/components/vision.py b/src/components/vision.py
index 5f0bc65..bd4a9cb 100644
--- a/src/components/vision.py
+++ b/src/components/vision.py
@@ -57,7 +57,7 @@ else:
class Vision(Component):
- """everything is expected the have shape with height (y) first then width (x)"""
+ """everything is expected to have shape with height (y) first then width (x)"""
status_signal = pyqtSignal(object)
loading_model_signal = pyqtSignal(object)
@@ -66,6 +66,7 @@ class Vision(Component):
super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
self.lock = QMutex()
self.simulate = "--sim-vision" in sys.argv
+ self.vision_config = None
def start(self):
self.model = None
@@ -96,7 +97,7 @@ class Vision(Component):
self.render_consumer.out.connect(self.process_render_consumed)
super().start()
- def config_changed(self):
+ def config_changed(self,vision_recipe=None):
# OBJECT DETECTION
self.detection_threshold = float(self.config[self.name].get("detection_threshold", 0.5))
# recipe
@@ -104,7 +105,8 @@ class Vision(Component):
self.labels = None
# LOAD RECIPE
self.recipes_dir = Path(self.config[self.name].get("recipes_dir", "./config/vision/recipes"))
- self.set_recipe(None)
+ self.set_recipe(vision_recipe)
+ self.vision_recipe=vision_recipe
self.recipe_watcher = QFileSystemWatcher([])
self.recipe_watcher.fileChanged.connect(self._set_recipe)
# LOAD MODEL
@@ -119,9 +121,11 @@ class Vision(Component):
if "--no-tflite" in sys.argv:
self.allowed_modes.pop("edgetpu", None)
self.allowed_modes.pop("tflite", None)
- self.load_model(self.config[self.name].get("neural_network", None))
+ if self.vision_config is not None:
+ self.load_model(self.vision_config["neural_network"])
# LOAD LABELS
- label_map = label_map_util.load_labelmap("./config/vision/labels/labels.pbtxt")
+ label_file="labels" if vision_recipe is None else vision_recipe
+ label_map = label_map_util.load_labelmap(f"./config/vision/labels/{label_file}.pbtxt")
self.num_classes = len(label_map.item)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=self.num_classes, use_display_name=True)
self.category_index = label_map_util.create_category_index(categories)
@@ -148,7 +152,7 @@ class Vision(Component):
return pow((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2, 1 / 2)
def clear_recipe(self):
- self.recipe = None
+ self.recipe_name = None
self.markers = {}
self.zones = {}
self.labels = {}
@@ -170,6 +174,7 @@ class Vision(Component):
if len(read) != 1 or self.recipe_path not in read:
raise AssertionError("Recipe could not be read.")
os.path.splitext(os.path.basename(read[0]))[0]
+ self.vision_config = config._sections.get("general", None)
self.markers = self.parse_markers(config._sections.get("markers", None))
self.zones = self.parse_zones(config._sections.get("zones", None))
self.labels = self.parse_labels(config._sections.get("labels", None))
@@ -179,7 +184,7 @@ class Vision(Component):
self.log.exception(f"Error reading {self.recipe_path!r}:")
self.clear_recipe()
self.status_signal.emit({
- "recipe": self.recipe,
+ "recipe": self.recipe_name,
"markers": self.markers,
"zones": self.zones,
"labels": self.labels,
@@ -189,8 +194,8 @@ class Vision(Component):
if recipe is None:
self.clear_recipe()
else:
- self.recipe = recipe
- self._set_recipe(self.recipes_dir / str(recipe))
+ self.recipe_name = recipe.split(".")[0]
+ self._set_recipe(self.recipes_dir / f"{self.recipe_name}.ini")
def parse_markers(self, config=None):
if config is None:
@@ -434,11 +439,104 @@ class Vision(Component):
parsed_detections.append(detection)
return parsed_detections
+ def check_features_targeted(self, frame, lock=True):
+ parsed_detections = []
+ for zone_name,zone in self.zones.items():
+ y1,x1,y2,x2=int(zone["box"][0]),int(zone["box"][1]),int(zone["box"][2]),int(zone["box"][3])
+ crop = frame[y1:y2,x1:x2]
+
+ if self.interpreter is not None and frame.shape != self.interpreter.get_input_details()[0]["shape"][1:3]:
+ tensor = np.expand_dims(cv2.resize(crop, self.interpreter.get_input_details()[0]["shape"][1:3], interpolation=cv2.INTER_LINEAR), axis=0)
+ else:
+ frame_resized = cv2.resize(crop, (256, 256), interpolation=cv2.INTER_LINEAR)
+ tensor = tf.convert_to_tensor(np.asarray(frame_resized))
+ tensor = tensor[tf.newaxis, ...]
+ # tensor = np.expand_dims(frame, axis=0)
+ # Run inference
+ if lock:
+ self.lock.lock()
+ if self.simulate or self.tf_mode == "simulation":
+ detections = {
+ "detection_scores": [[1.0]],
+ "detection_boxes": [[[0.2, 0.2, 0.8, 0.8]]],
+ "detection_classes": [[1]],
+ }
+ if lock:
+ self.lock.unlock()
+ elif self.tf_mode in {"edgetpu", "tflite"}:
+ i_d = self.interpreter.get_input_details()
+ # print(i_d)
+ o_d = self.interpreter.get_output_details()
+ # print(o_d)
+ self.interpreter.set_tensor(i_d[0]["index"], tensor)
+ self.interpreter.invoke()
+ # PARSE TFLITE DETECTIONS
+ # signature_list = self.interpreter._get_full_signature_list()
+ # if signature_list:
+ # if len(signature_list) > 1:
+ # raise ValueError("Only support model with one signature.")
+ # signature = signature_list[next(iter(signature_list))]
+ # # count = int(self.interpreter.get_tensor(signature["outputs"]["output_0"])[0])
+ # scores = self.interpreter.get_tensor(signature["outputs"]["output_1"])[0]
+ # class_ids = self.interpreter.get_tensor(signature["outputs"]["output_2"])[0]
+ # boxes = self.interpreter.get_tensor(signature["outputs"]["output_3"])[0]
+ if self.interpreter.get_tensor(o_d[3]["index"]).size == 1:
+ boxes = self.interpreter.get_tensor(o_d[0]["index"])[0]
+ class_ids = self.interpreter.get_tensor(o_d[1]["index"])[0]
+ scores = self.interpreter.get_tensor(o_d[2]["index"])[0]
+ # count = int(self.interpreter.get_tensor(o_d[3]["index"])[0])
+ else:
+ scores = self.interpreter.get_tensor(o_d[0]["index"])[0]
+ boxes = self.interpreter.get_tensor(o_d[1]["index"])[0]
+ # count = int(self.interpreter.get_tensor(o_d[2]["index"])[0])
+ class_ids = self.interpreter.get_tensor(o_d[3]["index"])[0]
+ if lock:
+ self.lock.unlock()
+ detections = {
+ "detection_scores": [scores],
+ "detection_boxes": [boxes],
+ "detection_classes": [map(lambda class_id: class_id + 1, class_ids)],
+ }
+ else:
+ detections = self.model(tensor)
+ if lock:
+ self.lock.unlock()
+ detections = {
+ "detection_scores": detections["detection_scores"].numpy().tolist(),
+ "detection_boxes": detections["detection_boxes"].numpy().tolist(),
+ "detection_classes": detections["detection_classes"],
+ }
+ # WARNING: results other than the ones related to tensor[-1] will be discarded
+ for d_score, d_box, d_class in zip( # , d_mask in zip(
+ detections["detection_scores"][-1],
+ detections["detection_boxes"][-1],
+ detections["detection_classes"][-1],
+ # detections["detection_masks"][-1],
+ ):
+ if d_score < self.detection_threshold:
+ continue
+ box = list(d_box)
+ box = [i * s for i, s in zip(box, crop.shape[:2] * 2)] # rescale detection to frame size
+ box_real=[box[0]+y1,box[1]+x1,box[2]+y1,box[3]+x1]
+ detection = {
+ "score": d_score,
+ "box": box_real,
+ "class": self.category_index[int(d_class)],
+ # "mask": d_mask,
+ "center": self.get_center(box),
+ "size": self.get_size(box),
+ }
+
+ parsed_detections.append(detection)
+ break # keep only first detection
+
+ return parsed_detections
+
def detections_to_items(self, detections):
# DRAW DETECTIONS
if detections is not None and len(detections):
style = {
- "border_thickness": 25,
+ "border_thickness": 5,
"fill_color": QColor("#00000000"),
"shape": "rect",
"convert_negative_placement": False,
@@ -460,7 +558,7 @@ class Vision(Component):
# MATCH DETECTIONS WITH RECIPE
results = dict.fromkeys(self.zones)
for detection in detections:
- # find closest zone center to the detection
+ # find the closest zone center to the detection
# filtering out those that do not contain the detection
min_distance = sys.maxsize
closest_zone = None
@@ -586,7 +684,7 @@ class Vision(Component):
**style,
"border_color": Qt.green if item["ok"] else Qt.red,
}
- return items
+ return items
else:
return {}
@@ -744,7 +842,11 @@ class Vision(Component):
# VISION_CONSUMER TASK
if consumable is None:
return
- detections = self.check_features(consumable["frame"])
+ if self.vision_config["type"]=="targeted":
+ detections = self.check_features_targeted(consumable["frame"])
+ else:
+ detections = self.check_features(consumable["frame"])
+
results = self.process_detections(detections)
return {"detections": detections, "results": results}
diff --git a/src/lib/db/__init__.py b/src/lib/db/__init__.py
index fcf7ce0..fb0510d 100644
--- a/src/lib/db/__init__.py
+++ b/src/lib/db/__init__.py
@@ -60,8 +60,8 @@ def init_db():
# "connector": {"connector": row["connector"]},
# "barcodes": {"serial": ""},
# "resistance": {"scale": 500, "expected": float(row["resistance_expected"]), "tolerance": float(row["resistance_tolerance"])},
- # "leak_1": {"pre_filling_time": 1, "pre_filling_pressure": 1000, "filling_time": 1, "settling_time": 1, "settling_pressure_min_percent": 5, "settling_pressure_max_percent": 5, "test_time": 5, "test_pressure_min_delta": 100, "test_pressure": 1000, "test_pressure_max_delta": 100, "flush_time": 1, "flush_pressure": 100},
- # "leak_2": {"pre_filling_time": 1, "pre_filling_pressure": 1000, "filling_time": 1, "settling_time": 1, "settling_pressure_min_percent": 5, "settling_pressure_max_percent": 5, "test_time": 5, "test_pressure_min_delta": 100, "test_pressure": 1000, "test_pressure_max_delta": 100, "flush_time": 1, "flush_pressure": 100},
+ # "leak_1": {"pre_filling_time": 1, "pre_filling_pressure": 1000, "filling_time": 1, "settling_time": 1, "settling_pressure_min_percent": 5, "settling_pressure_max_percent": 5, "test_time": 5, "test_pressure_qneg": 100, "test_pressure": 1000, "test_pressure_qpos": 100, "flush_time": 1, "flush_pressure": 100},
+ # "leak_2": {"pre_filling_time": 1, "pre_filling_pressure": 1000, "filling_time": 1, "settling_time": 1, "settling_pressure_min_percent": 5, "settling_pressure_max_percent": 5, "test_time": 5, "test_pressure_qneg": 100, "test_pressure": 1000, "test_pressure_qpos": 100, "flush_time": 1, "flush_pressure": 100},
# "vision": {"recipe": "termorestringente_923578.ini"},
# "print": {"template": "EtichettaR5.prn", },
# }.items():
diff --git a/src/lib/db/models/archive.py b/src/lib/db/models/archive.py
index 32e1e7d..1aae510 100644
--- a/src/lib/db/models/archive.py
+++ b/src/lib/db/models/archive.py
@@ -10,7 +10,7 @@ from .users import Users
class Archive(BaseModel):
id = AutoField(primary_key=True, unique=True, null=False)
- time = DateTimeField(unique=True, null=False, default=datetime.now)
+ time = DateTimeField(unique=True, null=False, default=datetime.now())
user = ForeignKeyField(Users, Users.username, null=False)
result = BooleanField(null=False)
overridden = BooleanField(null=False)
@@ -22,7 +22,11 @@ class Archive(BaseModel):
@classmethod
@db.atomic()
def archive(cls, test_data, result, overridden):
+ time=datetime.now()
+ test_data["time"]=time.strftime("%d/%m/%Y %H:%M:%S")
+ test_data["user"]=Users.get_session().username
return cls.create(
+ time=time,
user=Users.get_session().user,
result=result,
overridden=overridden,
diff --git a/src/lib/db/models/users.py b/src/lib/db/models/users.py
index 2eae003..ad3423d 100755
--- a/src/lib/db/models/users.py
+++ b/src/lib/db/models/users.py
@@ -136,11 +136,9 @@ class Users(BaseModel):
def delete_by_username(cls, username):
cls.update(password="").where(cls.username == username).execute()
- @classmethod
- def delete(cls, *args, **kwargs):
- # OVERRIDE DELETION
- # so that deleting a user will only disable it
- return cls.update(password="")
+# @classmethod
+# def delete(cls, *args, **kwargs):
+# return cls.delete()
@property
def is_admin(self):
diff --git a/src/lib/helpers/config_reader.py b/src/lib/helpers/config_reader.py
index f248296..61d39ad 100644
--- a/src/lib/helpers/config_reader.py
+++ b/src/lib/helpers/config_reader.py
@@ -48,7 +48,7 @@ class ConfigReader(QObject):
def read_config_file(self, config_path):
config_path = str(config_path)
- config = ConfigParser(*self._args, **self._kwargs)
+ config = ConfigParser(*self._args, **self._kwargs, allow_no_value=True,comment_prefixes="#",inline_comment_prefixes="#")
read = config.read(config_path)
if len(read) != 1 or config_path != read[0]:
raise AssertionError(f"Config file {config_path} could not be read.")
diff --git a/src/lib/helpers/timing.py b/src/lib/helpers/timing.py
index cae4c92..742b766 100644
--- a/src/lib/helpers/timing.py
+++ b/src/lib/helpers/timing.py
@@ -1,7 +1,7 @@
from time import perf_counter, time
ref = time() - perf_counter()
-
+pass
def timing():
global ref
diff --git a/src/main.py b/src/main.py
index 1030df4..d779608 100644
--- a/src/main.py
+++ b/src/main.py
@@ -68,7 +68,7 @@ try:
from lib.helpers import ConfigReader
from PyQt5.QtCore import QObject, QThread, pyqtSignal
from PyQt5.QtWidgets import QApplication, QMessageBox
- from ui import About, Archive, Login, Main_Window, Test, Users_Management
+ from ui import About, Archive, Login, Main_Window, Test, Users_Management, Recipe_Selection
if "--vision" in sys.argv:
from components import GalaxyCamera, NeoPixels, UVCCamera, Vision, VisionSaver
@@ -166,23 +166,22 @@ try:
Archive(hide_cloud_image="vision_saver" not in self().components)))
if "--archive" in sys.argv:
self.main_window.archive_a.trigger()
- self.main_window.about_a.triggered.connect(
- lambda checked, self=weakref.ref(self): self().main_window.open_dialog(About()))
if "--about" in sys.argv:
self.main_window.about_a.trigger()
- self.main_window.admin_m.menuAction().setVisible(
- False) # admin menu should not be visible before an admin logs in
+
+ # admin menu should not be visible before an admin logs in
+ self.main_window.admin_m.menuAction().setVisible(False)
+
+ self.main_window.about_a.triggered.connect(lambda checked, self=weakref.ref(self): self().main_window.open_dialog(About()))
self.main_window.quit_a.triggered.connect(quit_app)
- self.main_window.users_management_a.triggered.connect(
- lambda checked, self=weakref.ref(self): self().main_window.open_dialog(Users_Management()))
+ self.main_window.users_management_a.triggered.connect(lambda checked, self=weakref.ref(self): self().main_window.open_dialog(Users_Management()))
+ self.main_window.table_selection_a.triggered.connect(self.set_recipe_mode_table)
+ self.main_window.barcode_selection_a.triggered.connect(self.set_recipe_mode_barcode)
+
if "--users-management" in sys.argv:
self.main_window.users_management_a.trigger()
- # self.main_window.recipes_management_a.triggered.connect(lambda checked, self=weakref.ref(self): self().main_window.open_dialog(Recipes_Management()))
- # if "--recipes-management" in sys.argv:
- # self.main_window.recipes_management_a.trigger()
- # self.main_window.steps_management_a.triggered.connect(lambda checked, self=weakref.ref(self): self().main_window.open_dialog(Steps_Management()))
- # if "--steps-management" in sys.argv:
- # self.main_window.steps_management_a.trigger()
+
+ # CONFIG-SPECIFIC MENU ENTRY ACTIVATION
if "tecna_t3" in self.components and (
"--enable-saving-tecna-recipes" in sys.argv or self.config.get("tecna_t3", {}).get("saver",
None) == "present"):
@@ -192,9 +191,8 @@ try:
self.main_window.save_tecna_recipes_a.trigger()
else:
self.main_window.save_tecna_recipes_a.setVisible(False)
+ self.main_window.barcode_selection_a.setVisible(self.config["hardware_config"]["barcode_recipe_selection"] == "present")
- self.main_window.table_selection_a.triggered.connect(self.set_recipe_mode_table)
- self.main_window.barcode_selection_a.triggered.connect(self.set_recipe_mode_barcode)
# OPEN LOGIN TAB
self.open_login()
# SHOW MAIN WINDOW
@@ -220,16 +218,23 @@ try:
else:
self.main_window.admin_m.menuAction().setVisible(False)
# open test
- self.main_window.open_tab(Test(self.config, self.components))
+ self.main_window.open_tab(Test(self.config, self.components,self))
else:
self.main_window.admin_m.menuAction().setVisible(False)
def logout(self):
- if type(self.main_window.centralWidget) is Test:
- self.main_window.centralWidget.change_recipe()
Users.logout()
self.main_window.admin_m.menuAction().setVisible(False)
- self.open_login()
+ if type(self.main_window.centralWidget().centralWidget.widget) is Recipe_Selection:
+ # LOGOUT IMMEDIATELY IF NOT TESTING
+ self.open_login()
+ else:
+ if not self.main_window.centralWidget().autotesting:
+ self.main_window.centralWidget().change_recipe() # STOP CURRENT TEST
+ self.main_window.centralWidget().request_autotest("logout")
+ else:
+ # LOGOUT IMMEDIATELY IF AUTOTESTING
+ self.open_login()
def set_recipe_mode_table(self):
self.main_window.centralWidget().set_recipe_mode_table()
diff --git a/src/scripts/csv_extract_LEAK.py b/src/scripts/csv_extract_LEAK.py
new file mode 100644
index 0000000..30d7a8d
--- /dev/null
+++ b/src/scripts/csv_extract_LEAK.py
@@ -0,0 +1,35 @@
+import csv
+import json
+
+file="STTEN5"
+with open(f"tmp/{file}.csv",) as csv_file:
+ csv_reader = csv.reader(csv_file, delimiter=',')
+
+ with open(f'tmp/{file}_out.csv', 'w') as csv_out:
+
+ # create the csv writer
+ writer = csv.writer(csv_out, lineterminator="\n")
+
+ line_count = 0
+ for row in csv_reader:
+ if line_count == 0:
+ print(f'Column names are {", ".join(row)}')
+ row.append("caduta")
+ row.append("pressione")
+ row.pop(1) # remove data column
+ line_count += 1
+ writer.writerow(row)
+ else:
+ data=json.loads(row[1])
+ if "leak_1" in data.keys():
+ leak=data["leak_1"]["0"]["results"]["data"]["""Running test: measured leak"""]
+ press=data["leak_1"]["0"]["results"]["data"]["""Running test: filling pressure"""]
+ leakstr=f'{leak:.3f}'
+ pressstr = f'{press:.3f}'
+ line_count += 1
+ row.append(leakstr)
+ row.append(pressstr)
+ row.pop(1) # remove data column
+ writer.writerow(row)
+
+ print(f'Processed {line_count} lines.')
\ No newline at end of file
diff --git a/src/test/csv_import/Tabella_e_daily_p3.csv b/src/test/csv_import/Tabella_e_daily_p3.csv
new file mode 100644
index 0000000..186549c
--- /dev/null
+++ b/src/test/csv_import/Tabella_e_daily_p3.csv
@@ -0,0 +1,40 @@
+codice_ricetta,Priorita ,descrizione,etichette_supplementari,Numero nastri (N),Numero sensori anello (SA),Numero sensori presenza (SP)
+5803223729,3,priorita 3,,,,
+5803223730,3,priorita 3,,,,
+5803223731,3,priorita 3,,,,
+5803223732,3,priorita 3,,,,
+5803223733,3,priorita 3,,,,
+5803223734,3,priorita 3,,,,
+5803223735,3,priorita 3,,,,
+5803223736,3,priorita 3,,,,
+5803223737,3,priorita 3,,,,
+5803223738,3,priorita 3,,,,
+5803223739,3,priorita 3,,,,
+5803223740,3,priorita 3,,,,
+5803223741,3,priorita 3,,,,
+5803223742,3,priorita 3,,,,
+5803223743,3,priorita 3,,,,
+5803223744,3,priorita 3,,,,
+5803223745,3,priorita 3,,,,
+5803223746,3,priorita 3,,,,
+5803223747,3,priorita 3,,,,
+5803223748,3,priorita 3,,,,
+5803223749,3,priorita 3,,,,
+5803223750,3,priorita 3,,,,
+5803223751,3,priorita 3,,,,
+5803223752,3,priorita 3,,,,
+5803223753,3,priorita 3,,,,
+5803120372,3,priorita 3,,,,
+5803120373,3,priorita 3,,,,
+5803120374,3,priorita 3,,,,
+5803120375,3,priorita 3,,,,
+5803101543,3,priorita 3,,,,
+5803101544,3,priorita 3,,,,
+5803101545,3,priorita 3,,,,
+5803101546,3,priorita 3,,,,
+5803101547,3,priorita 3,,,,
+5803223754,3,priorita 3,,,,
+5803223755,3,priorita 3,,,,
+5803120371,3,priorita 3,,,,
+5803228584,3,priorita 3,,,,
+5803228585,3,priorita 3,,,,
diff --git a/src/test/rfid.py b/src/test/rfid.py
new file mode 100644
index 0000000..74fa362
--- /dev/null
+++ b/src/test/rfid.py
@@ -0,0 +1,46 @@
+import time
+import ndef
+import nfc
+from nfc.clf import RemoteTarget
+
+clf = nfc.ContactlessFrontend()
+connected=False
+while True:
+ try:
+ if not connected:
+ connected=clf.open('tty:USB0:pn532')
+ if connected:
+ target = clf.sense(RemoteTarget('106A'), RemoteTarget('106B'), RemoteTarget('212F'))
+ if target is not None:
+ tag = nfc.tag.activate(clf, target)
+ if tag is not None:
+ print(tag)
+ if tag.ndef is not None:
+ if not len(tag.ndef.records):
+ print("EMPTY TAG - WRITING...")
+ if not tag.ndef.is_writeable:
+ print("This Tag is not writeable.")
+ break
+ else:
+ tag.format()
+ #tag.ndef.records = [ndef.TextRecord("Errecinque"),ndef.TextRecord("5812345678")]
+ record=ndef.TextRecord("Errecinque,fixture,5812345678")
+ tag.ndef.records = [record]
+ if tag.ndef.has_changed:
+ print("WRITE ERROR")
+ else:
+ print("WRITE OK")
+
+ for record in tag.ndef.records:
+ print(record)
+ else:
+ print("ERROR NOT NDEF")
+ else:
+ print("NO TARGET")
+ except Exception as e:
+ print(f"EXCEPTION {e}")
+ connected=False
+ time.sleep(0.3)
+
+print("EXITING")
+clf.close()
\ No newline at end of file
diff --git a/src/ui/crud/crud.py b/src/ui/crud/crud.py
index 79605ac..6eb3e3d 100755
--- a/src/ui/crud/crud.py
+++ b/src/ui/crud/crud.py
@@ -6,7 +6,7 @@ from datetime import datetime
from lib.db import Crud_DB
from peewee import TextField
-from PyQt5.QtCore import Qt, QTimer, pyqtSignal
+from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QSize
from PyQt5.QtWidgets import (QAbstractItemView, QComboBox, QDialog,
QGridLayout, QHeaderView, QLineEdit, QMessageBox,
QPlainTextEdit, QPushButton)
@@ -148,6 +148,7 @@ class Combo_Box_Cell_Widget(QComboBox, Cell):
class External_Dialog_Cell_Widget(QPushButton, Cell):
def __init__(self, action=None, readonly=True, autocomplete=None, field_name=None, field_alias=None, field=None, row_number=None, crud=None):
self.dialog = QDialog()
+ self.dialog.resize(QSize(800,800))
self.editor = QPlainTextEdit()
self.dialog.setLayout(QGridLayout())
self.dialog.layout().setSpacing(0)
diff --git a/src/ui/leak_step_editor/leak_step_editor.py b/src/ui/leak_step_editor/leak_step_editor.py
index 2d5203f..e157ef2 100644
--- a/src/ui/leak_step_editor/leak_step_editor.py
+++ b/src/ui/leak_step_editor/leak_step_editor.py
@@ -15,9 +15,9 @@ class Leak_Step_Editor(Editor):
"settling_pressure_max_percent": self.settling_pressure_max_percent_sb,
# test
"test_time": self.test_time_sb,
- "test_pressure_min_delta": self.test_pressure_min_delta_sb,
+ "test_pressure_qneg": self.test_pressure_qneg_sb,
"test_pressure": self.test_pressure_sb,
- "test_pressure_max_delta": self.test_pressure_max_delta_sb,
+ "test_pressure_qpos": self.test_pressure_qpos_sb,
# flush
"flush_time": self.flush_time_sb,
"flush_pressure": self.flush_pressure_sb,
diff --git a/src/ui/leak_step_editor/leak_step_editor.ui b/src/ui/leak_step_editor/leak_step_editor.ui
index 7b1356b..1bf8742 100644
--- a/src/ui/leak_step_editor/leak_step_editor.ui
+++ b/src/ui/leak_step_editor/leak_step_editor.ui
@@ -221,7 +221,7 @@
-
-
+
0
@@ -238,7 +238,7 @@
-
-
+
9999
diff --git a/src/ui/main_window/main_window.ui b/src/ui/main_window/main_window.ui
index f404bef..0ec3684 100644
--- a/src/ui/main_window/main_window.ui
+++ b/src/ui/main_window/main_window.ui
@@ -25,7 +25,7 @@
0
0
843
- 28
+ 31
@@ -72,7 +72,7 @@
- Powered by
+ Contatti
diff --git a/src/ui/recipe_selection/recipe_selection.py b/src/ui/recipe_selection/recipe_selection.py
index 7cba138..06ec26b 100755
--- a/src/ui/recipe_selection/recipe_selection.py
+++ b/src/ui/recipe_selection/recipe_selection.py
@@ -128,8 +128,8 @@ class Recipe_Selection(Widget):
self.export_b.setVisible(False)
self.delete_all_b.setVisible(False)
# TESTING
- if "--auto-select" in sys.argv or "--test" in sys.argv:
- recipe = "5802850925"
+ if "--auto-select" in sys.argv:
+ recipe = "000952054"
cn = self.crud.select_index["name"]
self.crud.db_tw.clearSelection()
for rn in range(1, self.crud.db_tw.rowCount()):
@@ -214,9 +214,9 @@ class Recipe_Selection(Widget):
"settling_pressure_min_percent": int(row.get("percentuale_minima_pressione_assestamento", defaults["percentuale_minima_pressione_assestamento"])),
"settling_pressure_max_percent": int(row.get("percentuale_massima_pressione_assestamento", defaults["percentuale_massima_pressione_assestamento"])),
"test_time": int(row.get("tempo_di_test", defaults["tempo_di_test"])),
- "test_pressure_min_delta": int(row.get("pressione_di_test_delta_minimo", defaults["pressione_di_test_delta_minimo"])),
+ "test_pressure_qneg": int(row.get("pressione_di_test_delta_minimo", defaults["pressione_di_test_delta_minimo"])),
"test_pressure": int(row.get("pressione_di_test", defaults["pressione_di_test"])),
- "test_pressure_max_delta": int(row.get("pressione_di_test_delta_massimo", defaults["pressione_di_test_delta_massimo"])),
+ "test_pressure_qpos": int(row.get("pressione_di_test_delta_massimo", defaults["pressione_di_test_delta_massimo"])),
"flush_time": int(row.get("tempo_svuotamento", defaults["tempo_svuotamento"])),
"flush_pressure": int(row.get("pressione_svuotamento", defaults["pressione_svuotamento"])),
"relay_config": int(row.get("config_elettrovalvole", defaults["config_elettrovalvole"]))
@@ -229,9 +229,9 @@ class Recipe_Selection(Widget):
"settling_pressure_min_percent": int(row.get("percentuale_minima_pressione_assestamento_2", defaults["percentuale_minima_pressione_assestamento_2"])),
"settling_pressure_max_percent": int(row.get("percentuale_massima_pressione_assestamento_2", defaults["percentuale_massima_pressione_assestamento_2"])),
"test_time": int(row.get("tempo_di_test_2", defaults["tempo_di_test_2"])),
- "test_pressure_min_delta": int(row.get("pressione_di_test_delta_minimo_2", defaults["pressione_di_test_delta_minimo_2"])),
+ "test_pressure_qneg": int(row.get("pressione_di_test_delta_minimo_2", defaults["pressione_di_test_delta_minimo_2"])),
"test_pressure": int(row.get("pressione_di_test_2", defaults["pressione_di_test_2"])),
- "test_pressure_max_delta": int(row.get("pressione_di_test_delta_massimo_2", defaults["pressione_di_test_delta_massimo_2"])),
+ "test_pressure_qpos": int(row.get("pressione_di_test_delta_massimo_2", defaults["pressione_di_test_delta_massimo_2"])),
"flush_time": int(row.get("tempo_svuotamento_2", defaults["tempo_svuotamento_2"])),
"flush_pressure": int(row.get("pressione_svuotamento_2", defaults["pressione_svuotamento_2"])),
"relay_config": int(row.get("config_elettrovalvole_2", defaults["config_elettrovalvole_2"]))
@@ -434,9 +434,9 @@ class Recipe_Selection(Widget):
"percentuale_minima_pressione_assestamento": steps["leak_1"].spec["settling_pressure_min_percent"],
"percentuale_massima_pressione_assestamento": steps["leak_1"].spec["settling_pressure_max_percent"],
"tempo_di_test": steps["leak_1"].spec["test_time"],
- "pressione_di_test_delta_minimo": steps["leak_1"].spec["test_pressure_min_delta"],
+ "pressione_di_test_delta_minimo": steps["leak_1"].spec["test_pressure_qneg"],
"pressione_di_test": steps["leak_1"].spec["test_pressure"],
- "pressione_di_test_delta_massimo": steps["leak_1"].spec["test_pressure_max_delta"],
+ "pressione_di_test_delta_massimo": steps["leak_1"].spec["test_pressure_qpos"],
"tempo_svuotamento": steps["leak_1"].spec["flush_time"],
"pressione_svuotamento": steps["leak_1"].spec["flush_pressure"],
"prova_tenuta_abilitata_2": "x" if recipe.spec["leak_2"] else "",
@@ -447,9 +447,9 @@ class Recipe_Selection(Widget):
"percentuale_minima_pressione_assestamento_2": steps["leak_2"].spec["settling_pressure_min_percent"],
"percentuale_massima_pressione_assestamento_2": steps["leak_2"].spec["settling_pressure_max_percent"],
"tempo_di_test_2": steps["leak_2"].spec["test_time"],
- "pressione_di_test_delta_minimo_2": steps["leak_2"].spec["test_pressure_min_delta"],
+ "pressione_di_test_delta_minimo_2": steps["leak_2"].spec["test_pressure_qneg"],
"pressione_di_test_2": steps["leak_2"].spec["test_pressure"],
- "pressione_di_test_delta_massimo_2": steps["leak_2"].spec["test_pressure_max_delta"],
+ "pressione_di_test_delta_massimo_2": steps["leak_2"].spec["test_pressure_qpos"],
"tempo_svuotamento_2": steps["leak_2"].spec["flush_time"],
"pressione_svuotamento_2": steps["leak_2"].spec["flush_pressure"],
"test_visione_abilitato": recipe.spec["vision"],
diff --git a/src/ui/rfid_recipe_selection/__init__.py b/src/ui/rfid_recipe_selection/__init__.py
new file mode 100644
index 0000000..b3a3f30
--- /dev/null
+++ b/src/ui/rfid_recipe_selection/__init__.py
@@ -0,0 +1 @@
+from .rfid_recipe_selection import RFID_Recipe_Selection
diff --git a/src/ui/rfid_recipe_selection/rfid_recipe_selection.py b/src/ui/rfid_recipe_selection/rfid_recipe_selection.py
new file mode 100644
index 0000000..9b2ee0b
--- /dev/null
+++ b/src/ui/rfid_recipe_selection/rfid_recipe_selection.py
@@ -0,0 +1,85 @@
+import sys
+
+import peewee
+from PyQt5 import Qt
+
+from lib.helpers import timing
+from PyQt5.QtCore import Qt, QTimer, QThread
+from PyQt5.QtGui import QKeySequence, QPixmap, QPalette, QColor
+from PyQt5.QtWidgets import QShortcut, QApplication
+from ui.widget import Widget
+from lib import db
+from lib.db.models import Recipes
+
+class RFID(Widget):
+ def __init__(self, parent):
+ super().__init__()
+ self.parent=parent
+ self.recipe_db_model=Recipes
+ 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.delay_timer = QTimer()
+ self.delay_timer.setSingleShot(True)
+ self.delay_timer.timeout.connect(self.reset_display)
+
+ self.ok_timer = QTimer()
+ self.ok_timer.setSingleShot(True)
+ self.ok_timer.timeout.connect(self.set_recipe)
+
+ def start(self, recipe=None, step=None, pieces=None):
+
+ self.rfid_input_l.setPalette(self.status_palettes[None])
+ self.rfid_input_l.setPlainText("")
+
+ def get(self, data=None, override=False):
+ if not len(data):
+ data = None
+ if data is None:
+ return
+ else:
+ lines = data
+ if lines[0]=="ERRECINQUE RFID":
+ # RECIPE CODE FOUND
+ self.recipe=lines[1]
+ self.rfid_input_l.setPalette(self.status_palettes[True])
+ self.ok_timer.start(2000)
+
+ else:
+ # RECIPE CODE NOT FOUND
+ self.rfid_input_l.setPalette(self.status_palettes[False])
+ self.instruction_text("FORMATO RFID DIMA NON VALIDO", "red")
+ self.delay_timer.start(3000)
+
+ # LOOKUP RECIPE
+
+ def set_recipe(self):
+ try:
+ recipe = self.recipe_db_model.get_by_id(self.recipe)
+ self.parent.set_recipe(recipe)
+ except peewee.DoesNotExist:
+ self.rfid_input_l.setPalette(self.status_palettes[False])
+ self.instruction_text("RICETTA NON TROVATA","red")
+ self.delay_timer.start(3000)
+
+
+ def reset_display(self):
+ self.rfid_input_l.setFocus()
+ self.rfid_input_l.setPlainText("")
+ self.rfid_input_l.setPalette(self.status_palettes[""])
+ self.instruction_text("SCANSIONARE BARCODE SELEZIONE RICETTA")
+
+ def instruction_text(self,text,color=None):
+ if getattr(self.parent.centralWidget, "set_text"):
+ self.parent.centralWidget.set_text(text, color=color)
+
+
diff --git a/src/ui/rfid_recipe_selection/rfid_recipe_selection.ui b/src/ui/rfid_recipe_selection/rfid_recipe_selection.ui
new file mode 100644
index 0000000..2805d48
--- /dev/null
+++ b/src/ui/rfid_recipe_selection/rfid_recipe_selection.ui
@@ -0,0 +1,95 @@
+
+
+ Test_Connector
+
+
+
+ 0
+ 0
+ 1445
+ 793
+
+
+
+ Test Connector
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 200
+ 200
+
+
+
+
+ 12
+
+
+
+
+
+
+
+ -
+
+
+
+ 600
+ 0
+
+
+
+
+ 600
+ 200
+
+
+
+
+ 20
+
+
+
+ 123
+456
+abc
+
+
+
+ -
+
+
+
+ 20
+
+
+
+ TORNA ALLA TABELLA RICETTE
+
+
+
+
+
+
+
+
diff --git a/src/ui/test/test.py b/src/ui/test/test.py
index e3cded2..bf2faf7 100755
--- a/src/ui/test/test.py
+++ b/src/ui/test/test.py
@@ -29,16 +29,15 @@ from ui.widget import Widget
class Test(Widget):
- def __init__(self, config, components=None):
+ def __init__(self, config, components=None,main_window=None):
super().__init__()
+ self.main_window=main_window
self.config = config
self.components = components
# GET LOGGER
self.log = logging.getLogger("Test")
# SHOW MACHINE DESCRIPTION
self.machine_description_l.setText(self.config.get("machine", {}).get("description", "N/A"))
- # SHOW USERNAME
-
# SHOW USERNAME
session = Users.get_session()
self.user_l.setText(session.username)
@@ -91,9 +90,9 @@ class Test(Widget):
"count_end": Test_Assembly(img_path=None, text=u"LOTTO TERMINATO, PREMERE CONTINUA PERCOMINCIARNE UNO NUOVO", widget=Test_Count_End(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces)),
"done": Test_Assembly(img_path=self.select_step_img("success"), text=u"COLLAUDO COMPLETATO", widget=None),
"emergency": Test_Assembly(img_path=self.select_step_img("reset_emergency"), text=u"EMERGENZA INTERVENUTA - RIPRISTINARE PULSANTE E SELEZIONARE \"RESET EMERGENZA\" DAL MEN\u00d9 \"STRUMENTI\"", widget=None),
- "fail": Test_Assembly(img_path=self.select_step_img("fail"), text=u"CICLO INTERROTTO, PREMERE CONTINUA PER COMINCIARE UN NUOVO CICLO", widget=Test_Fail()),
+ "fail": Test_Assembly(img_path=self.select_step_img("fail"), text=u"CICLO INTERROTTO, PREMERE CONTINUA PER COMINCIARE UN NUOVO CICLO", widget=Test_Fail(parent=self)),
"leak_1": Test_Assembly(img_path=None, text=None, widget=Test_Leak(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces,parent=self)),
- "leak_2": Test_Assembly(img_path=None, text=None, widget=Test_Leak(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces)),
+ "leak_2": Test_Assembly(img_path=None, text=None, widget=Test_Leak(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces,parent=self)),
"instruction": Test_Assembly(img_path=None, text=u"ESEGUIRE LE OPERAZIONI DI MONTAGGIO INDICATE IN FIGURA", widget=Test_Instructions(components=self.components, recipe=self.recipe,bench_name=self.config.machine_id, step=self.step)),
"print": Test_Assembly(img_path=self.select_step_img("print"), text=u"STAMPA ETICHETTA IN CORSO", widget=None),
"resistance": Test_Assembly(img_path=None, text=u"COLLEGARE CONNETTORE ELETTRICO PER EFFETTUARE PROVA RESISTENZA", widget=Test_Resistance(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces)),
@@ -113,7 +112,8 @@ class Test(Widget):
self.autotesting_reason = None
self.autotest_cycle_steps = None
if "--no-autotest" not in sys.argv:
- self.autotest_period = 12 * 60 * 60 * 1000
+ self.autotest_period = 8.5 * 60 * 60 * 1000 # 8.5 HOURS
+ # self.autotest_period = 12 * 60 * 60 * 1000 # 12 HOURS
if not self.config["autotest_done"]:
self.request_autotest("init")
else:
@@ -314,6 +314,8 @@ class Test(Widget):
for i, step in enumerate(steps):
if i in skip:
continue
+ if step.type == "vision":
+ self.components["vision"].config_changed(vision_recipe=self.recipe.name)
if step.type == "count":
count_found = True
if "warning_img" in step.spec:
@@ -349,6 +351,7 @@ class Test(Widget):
self.cycle_steps = steps
self.check_steps_dependencies(self.cycle_steps)
leak_autotest_steps=[]
+ # CONFIGURE LEAK AUTOTEST PARAMETERS
if self.config["autotest_leak"]["enabled"]=="true":
l_at_1=copy.deepcopy(self.config["autotest_leak"])
l_at_1.pop("enabled")
@@ -357,6 +360,8 @@ class Test(Widget):
l_at_2=copy.deepcopy(self.config["autotest_leak"])
l_at_2.pop("enabled")
l_at_2={a: float(x) for a, x in l_at_2.items()}
+ l_at_2["test_pressure_qneg"]=l_at_2["test_pressure_tt_qneg"]
+ l_at_2["test_pressure_qpos"]=l_at_2["test_pressure_tt_qpos"]
l_at_2["autotest"]="ok_check"
leak_autotest_steps=[Steps(type="leak_1",spec=l_at_1),Steps(type="leak_1",spec=l_at_2)]
@@ -452,13 +457,32 @@ class Test(Widget):
self.data[step_name] = {}
if data is not None:
data["step"] = model_to_dict(self.step)
- self.data[step_name][str(len(self.data[step_name]))] = data
+ data["step"].pop("name",None)
+
+ # MAKE ARRAY ONLY IF MORE THAN ONE TEST OF SAME TYPE
+ if len(self.data[step_name])>1:
+ self.data[step_name][str(len(self.data[step_name]))] = data
+ else:
+ self.data[step_name] = data
+
self.data["overridden"] = self.data["overridden"] or data.get("overridden", False)
self.data["ok"] = self.data["ok"] and data.get("ok", False)
self.next()
def done(self, ok=True):
- self.log.info("cycle done")
+ self.log.info("cycle done, saving data...")
+
+ #remove useless info
+ self.data.get("recipe",{}).get("spec",{}).pop("steps",None)
+ self.data.get("recipe",{}).get("spec",{}).pop("available_steps",None)
+ for leak in ["leak_1","leak_2"]:
+ if leak in self.data.keys():
+ self.data[leak]["results"]={k:self.data[leak]["results"]["tecna_t3"][k] for k in ["Running test: filling pressure",
+ "Running test: measured leak",
+ "Running test: pressure at the end of settling",
+ "Running test: result"]
+
+ }
if "vision" in self.data:
vision_test_1 = self.data.get("vision", {}).get("0", {})
out_paths = self.components["vision_saver"].save(
@@ -471,6 +495,9 @@ class Test(Widget):
for vision in self.data.get("vision", {}).values():
vision.pop("frame", None)
vision.pop("render", None)
+ vision.pop("detections", None)
+ if "results" in vision.keys():
+ vision["results"].pop("results", None)
if self.autotesting:
self.data["autotest"] = True
self.data["autotest_reason"] = self.autotesting_reason
@@ -483,6 +510,11 @@ class Test(Widget):
self.pieces["ok"] += 1
else:
self.pieces["ko"] += 1
+ else:
+ if self.autotesting_reason == "logout":
+ if ok:
+ self.main_window.show_login()
+
return archived
@staticmethod
@@ -503,21 +535,19 @@ class Test(Widget):
self.log.info("cycle printed already compiled label")
# LABEL PRINT
recipe = archived.test_data.get("recipe", {})
- leak_test_1 = archived.test_data.get("leak_1", {}).get("0", {})
+ leak_test_1 = archived.test_data.get("leak_1", {})
leak_test_1_step = leak_test_1.get("step", {})
leak_test_1_step_spec = leak_test_1_step.get("spec", {})
leak_test_1_results = leak_test_1.get("results", {})
- leak_test_1_results_data = leak_test_1_results.get("data", {})
- leak_test_2 = archived.test_data.get("leak_2", {}).get("0", {})
+ leak_test_2 = archived.test_data.get("leak_2", {})
leak_test_2_step = leak_test_2.get("step", {})
leak_test_2_step_spec = leak_test_2_step.get("spec", {})
leak_test_2_results = leak_test_2.get("results", {})
- leak_test_2_results_data = leak_test_2_results.get("data", {})
- psetminp_a = leak_test_1_step_spec.get("test_pressure", 0) * (100+leak_test_1_step_spec.get("test_pressure_min_delta", 0)/100)
- psetmaxp_a = leak_test_1_step_spec.get("settling_pressure_max_percent", 0) * (100+leak_test_1_step_spec.get("test_pressure_max_delta", 0)/100)
- psetminp2_a = leak_test_2_step_spec.get("settling_pressure_min_percent", 0) * (100+leak_test_2_step_spec.get("test_pressure_min_delta", 0)/100)
- psetmaxp2_a = leak_test_2_step_spec.get("settling_pressure_max_percent", 0) * (100+leak_test_2_step_spec.get("test_pressure_max_delta", 0)/100)
+ psetminp_a = leak_test_1_step_spec.get("test_pressure", 0) * (100+leak_test_1_step_spec.get("test_pressure_qneg", 0)/100)
+ psetmaxp_a = leak_test_1_step_spec.get("settling_pressure_max_percent", 0) * (100+leak_test_1_step_spec.get("test_pressure_qpos", 0)/100)
+ psetminp2_a = leak_test_2_step_spec.get("settling_pressure_min_percent", 0) * (100+leak_test_2_step_spec.get("test_pressure_qneg", 0)/100)
+ psetmaxp2_a = leak_test_2_step_spec.get("settling_pressure_max_percent", 0) * (100+leak_test_2_step_spec.get("test_pressure_qpos", 0)/100)
printer_fields = self.step.spec
context = {
@@ -525,6 +555,7 @@ class Test(Widget):
"RECIPE": self.labellify(recipe.get("name", "-")),
"CLIENT": self.labellify(recipe.get("client", "-")),
"PART": self.labellify(recipe.get("part_number", "-")),
+ "DESCRIPTION": self.labellify(recipe.get("description", "-")),
# STEP SPEC
"TPREFILL": self.labellify(leak_test_1_step_spec.get("pre_filling_time", "-")),
"PPREFILL": self.labellify(leak_test_1_step_spec.get("pre_filling_pressure", "-")),
@@ -544,24 +575,22 @@ class Test(Widget):
"PSETMAXP2_A": self.labellify(psetmaxp2_a),
"TTEST": self.labellify(leak_test_1_step_spec.get("test_time", "-")),
"TTEST2": self.labellify(leak_test_2_step_spec.get("test_time", "-")),
- "PMIN": self.labellify(leak_test_1_step_spec.get("test_pressure_min_delta", "-")),
- "PMIN2": self.labellify(leak_test_2_step_spec.get("test_pressure_min_delta", "-")),
+ "PMIN": self.labellify(leak_test_1_step_spec.get("test_pressure_qneg", "-")),
+ "PMIN2": self.labellify(leak_test_2_step_spec.get("test_pressure_qneg", "-")),
"PTEST": self.labellify(leak_test_1_step_spec.get("test_pressure", "-")),
"PTEST2": self.labellify(leak_test_2_step_spec.get("test_pressure", "-")),
- "PMAX": self.labellify(leak_test_1_step_spec.get("test_pressure_max_delta", "-")),
+ "PMAX": self.labellify(leak_test_1_step_spec.get("test_pressure_qpos", "-")),
"TFLUSH": self.labellify(leak_test_1_step_spec.get("flush_time", "-")),
"PFLUSH": self.labellify(leak_test_1_step_spec.get("flush_pressure", "-")),
# ACTUAL TESTED VALUES
- "RESTPB": self.labellify(leak_test_1_results_data.get("Running test: phase backwards time", "-")),
- "RESPFILL": self.labellify(leak_test_1_results_data.get("Running test: filling pressure", "-")),
- "RESPSET": self.labellify(leak_test_1_results_data.get("Running test: pressure at the end of settling", "-")),
- "RESPSET2": self.labellify(leak_test_2_results_data.get("Running test: pressure at the end of settling", "-")),
- "RESPB": self.labellify(leak_test_1_results_data.get("Running test: burst pressure", "-")),
- "RESLEAK": self.labellify(leak_test_1_results_data.get("Running test: measured leak", "-")),
- "RESLEAK2": self.labellify(leak_test_2_results_data.get("Running test: measured leak", "-")),
- "RESFLOW": self.labellify(leak_test_1_results_data.get("Running test: calculated leak flow rate", "-")),
- "RESRVP": self.labellify(leak_test_1_results_data.get("Running test: calculate RVP%", "-")),
- "RESRES": self.labellify(leak_test_1_results_data.get("Running test: result", "-")),
+ "RESPFILL": self.labellify(leak_test_1_results.get("Running test: filling pressure", "-")),
+ "RESPFILL2": self.labellify(leak_test_2_results.get("Running test: filling pressure", "-")),
+ "RESPSET": self.labellify(leak_test_1_results.get("Running test: pressure at the end of settling", "-")),
+ "RESPSET2": self.labellify(leak_test_2_results.get("Running test: pressure at the end of settling", "-")),
+ "RESLEAK": self.labellify(leak_test_1_results.get("Running test: measured leak", "-")),
+ "RESLEAK2": self.labellify(leak_test_2_results.get("Running test: measured leak", "-")),
+ "RESRES": self.labellify(leak_test_1_results.get("Running test: result", "-")),
+ "RESRES2": self.labellify(leak_test_2_results.get("Running test: result", "-")),
# SERIAL DEFINITION
"SN": str(archived.id),
"SN4": f"{archived.id:0>4}",
@@ -597,6 +626,13 @@ class Test(Widget):
# PRINT MAIN PRODUCT LABEL
compiled_label = self.components["label_printer"].print_label(label, context=context)
+ # if recipe.get("part_number", "-") == "5802814210 R.3":
+ # num_labels=2
+ # else:
+ # num_labels=1
+ #
+ # for i in range(num_labels):
+ # compiled_label = self.components["label_printer"].print_label(label, context=context)
self.log.info(f"Main label printed: {context!r}")
return compiled_label
diff --git a/src/ui/test/test.ui b/src/ui/test/test.ui
index 9bdf1aa..ac9e4b9 100755
--- a/src/ui/test/test.ui
+++ b/src/ui/test/test.ui
@@ -6,8 +6,8 @@
0
0
- 842
- 118
+ 1252
+ 146
@@ -52,52 +52,7 @@
3
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
- 200
- 40
-
-
-
-
- 12
- 75
- true
-
-
-
- CAMBIA DISEGNO
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
+
-
Qt::Horizontal
@@ -110,71 +65,6 @@
- -
-
-
-
- 12
- 75
- true
-
-
-
- 12345
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
-
- 12
- 75
- true
-
-
-
- PEZZI FATTI
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
-
- 12
- 75
- true
-
-
-
- 12345
-567
-
-
- Qt::AlignCenter
-
-
-
-
@@ -201,14 +91,38 @@
- -
-
-
-
- 0
- 0
-
+
-
+
+
+ Qt::Horizontal
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 16
+ 75
+ true
+
+
+
+ -
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
12
@@ -217,25 +131,14 @@
- N. DISEGNO:
+ 12345
+
+
+ Qt::AlignCenter
- -
-
-
-
- 12
- 75
- true
-
-
-
- OPERATORE:
-
-
-
- -
+
-
@@ -268,7 +171,7 @@
-
-
+
12
@@ -277,11 +180,66 @@
- -
+ OPERATORE:
- -
+
-
+
+
+
+ 12
+ 75
+ true
+
+
+
+ 12345
+567
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ N. DISEGNO:
+
+
+
+ -
+
+
+
+ 12
+ 75
+ true
+
+
+
+ PEZZI FATTI
+
+
+ Qt::AlignCenter
+
+
+
+ -
Qt::Horizontal
@@ -297,11 +255,24 @@
- -
-
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
- 16
+ 12
75
true
@@ -309,6 +280,69 @@
-
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 200
+ 40
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ CAMBIA DISEGNO
+
+
+
+ -
+
+
+
+ 12
+ 75
+ true
+
+
+
+ ULTIMO AUTOTEST:
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 12
+ 75
+ true
+
+
+
+ DD/MM/YY HH:MM
+
Qt::AlignCenter
diff --git a/src/ui/test_connector/test_connector.py b/src/ui/test_connector/test_connector.py
index 69a6eaa..af8f0a5 100644
--- a/src/ui/test_connector/test_connector.py
+++ b/src/ui/test_connector/test_connector.py
@@ -90,4 +90,4 @@ class Test_Connector(Test_Test):
return barcode is not None and len(barcode)
def set_focus(self):
- self.barcodes_le.setFocus()
+ self.connector_le.setFocus()
diff --git a/src/ui/test_fail/test_fail.py b/src/ui/test_fail/test_fail.py
index f01da20..ffcc5d2 100644
--- a/src/ui/test_fail/test_fail.py
+++ b/src/ui/test_fail/test_fail.py
@@ -10,14 +10,24 @@ from ui.test_test import Test_Test
class Test_Fail(Test_Test):
- def __init__(self, components=None, recipe=None, step=None, pieces=None, run_once=False, reset_on_start=True, enable_override=False):
+ def __init__(self, components=None, recipe=None, step=None, pieces=None, run_once=False, reset_on_start=True, enable_override=False,parent=None):
super().__init__(components=components, recipe=recipe, step=step, pieces=pieces, run_once=run_once, reset_on_start=reset_on_start, enable_override=enable_override)
self.continue_b.clicked.connect(lambda checked, self=weakref.ref(self): self().ok.emit(None))
+ self.parent=parent
+ self.discard_timer=QTimer()
+ self.discard_timer.timeout.connect(self.wait_discard)
def start(self, recipe=None, step=None, pieces=None):
show = super().start(recipe=recipe, step=step, pieces=pieces)
if show is False:
return show
+ if "discard_box" in self.parent.config["hardware_config"].keys():
+ if self.parent_assembly_widget is not None :
+ self.continue_b.setVisible(False)
+ self.discard_timer.start(100)
+ self.parent_assembly_widget().set_text(text="TEST KO - INSERIRE IL PEZZO COLLAUDATO NEL CONTENITORE DI SEGREGAZIONE SCARTI")
+ self.io_connection=self.components["digital_io"].out.connect(self.wait_discard)
+
self.visualize()
# TESTING
if "--test" in sys.argv:
@@ -25,11 +35,21 @@ class Test_Fail(Test_Test):
self.test_timer.setSingleShot(True)
self.test_timer.timeout.connect(self.continue_b.click)
self.test_timer.start(500)
- # /TESTING
return show
- # def stop(self):
- # super().stop()
+ def stop(self):
+ if "discard_box" in self.parent.config["hardware_config"].keys():
+ self.disconnect(self.io_connection)
+ super().stop()
+
+ def wait_discard(self,data=None):
+ if data is not None:
+ if len(data[0]["digital_io"]) == 0:
+ return
+ else:
+ sensor_index = int(self.parent.config["digital_io"]["discard_idx"])
+ byte_idx = int(sensor_index / 8)
+ bit_idx = sensor_index % 8
+ if data[0]["digital_io"][byte_idx][bit_idx]:
+ self.ok.emit(None)
- # def reset(self):
- # super().reset()
diff --git a/src/ui/test_leak/test_leak.py b/src/ui/test_leak/test_leak.py
index 4fe6330..70d4669 100644
--- a/src/ui/test_leak/test_leak.py
+++ b/src/ui/test_leak/test_leak.py
@@ -2,24 +2,33 @@ import sys
import time
import weakref
-from PyQt5.QtWidgets import QMessageBox
+from PyQt5.QtWidgets import QMessageBox, QDialog
+from ui import Dialog
from ui.test_test import Test_Test
from components.Automation.BDaq import ErrorCode
class Test_Leak(Test_Test):
def __init__(self, components=None, recipe=None, step=None, pieces=None, run_once=False, reset_on_start=True, enable_override=False,parent=None):
super().__init__(components=components, recipe=recipe, step=step, pieces=pieces, run_once=run_once, reset_on_start=reset_on_start, enable_override=enable_override)
+ self.parent=parent
self.step=step
self.start_b.clicked.connect(self.start_test)
self.stop_b.clicked.connect(lambda checked, self=weakref.ref(self): self().components["tecna_t3"].stop_test())
- self.parent=parent
+ self.show_instruction_b.setVisible("show_instructions" in self.parent.config["hardware_config"].keys())
+ self.show_instruction_b.clicked.connect(self.show_instruction)
+
+ def show_instruction(self):
+ dialog=Dialog()
+ dialog.setCentralWidget(self.parent.cycle_available_steps["instruction"])
+ dialog.show()
def start_test(self):
# print extra labels
if self.step.type == "leak_1":
self.parent.print_extra_labels()
- self.components["tecna_t3"].start_test()
+
+ self.components["tecna_t3"].start_test()
def start(self, recipe=None, step=None, pieces=None):
# TESTING
@@ -32,6 +41,17 @@ class Test_Leak(Test_Test):
if show is False:
return show
+ if "leak_2" in [s.type for s in self.parent.cycle_steps]:
+ if self.step.type=="leak_1":
+ self.test_num_l.setText("1/2")
+ else:
+ self.test_num_l.setText("2/2")
+ else:
+ self.test_num_l.setText("1/1")
+
+ self.recipe_pressure_l.setText(f"{self.step.spec['test_pressure']}")
+ self.leak_min_l.setText(f"{self.step.spec['test_pressure_qneg']}")
+ self.leak_max_l.setText(f"{self.step.spec['test_pressure_qpos']}")
# setup test loop
self.components["tecna_t3"].write_recipe(self.recipe, self.step)
self.get_connection = self.components["tecna_t3"].out.connect(self.get)
@@ -102,7 +122,7 @@ class Test_Leak(Test_Test):
if step == "ok_check":
ok = type(result) is str and "passed" in result.lower() # AUTOTEST - NO LEAK
elif step == "ko_check":
- ok = type(result) is str and "failed" in result.lower() # AUTOTEST - LEAK
+ ok = type(result) is str and "passed" in result.lower() # AUTOTEST - LEAK
else:
ok = type(result) is str and "passed" in result.lower() # NORMAL TEST
@@ -112,25 +132,30 @@ class Test_Leak(Test_Test):
ret = self.components["digital_io"].set_bit_verify(0, 1, 0)
else:
- result = None
+ #result = None
ok = None
+
+ results={"ok":ok}
+ results.update(data)
super().get([{
"time": data.get("time", None),
- "results": {
- "ok": ok,
- "result": result,
- "data": data["tecna_t3"],
- },
+ "results": results
+ #"results": {
+ #"ok": ok,
+ #"result": result,
+ #"data": data["tecna_t3"],
+ #},
}], override=override, fail=ok is False)
def visualize(self, data=None):
if data is None:
data = {}
- d = data.get("results", {}).get("data", {})
+ d = data.get("results", {}).get("tecna_t3", {})
for k, l in {
"Running test: active phase": self.test_phase_l,
"Real time test pressure output": self.circuit_pressure_l,
- "Real time differential pressure output": self.leak_l,
+ #"Real time differential pressure output": self.leak_l,
+ "Running test: measured leak": self.leak_l,
"Real time pressure line regulator": self.regulated_pressure_l,
# "Active alarm flags": self._l,
"Running test: test type": self.test_type_l,
@@ -156,6 +181,9 @@ class Test_Leak(Test_Test):
if self.parent_assembly_widget is not None:
self.parent_assembly_widget().set_text(text="COLLEGARE GLI ATTACCHI PNEUMATICI E PREMERE START PER INIZIARE LA PROVA TENUTA")
self.start_b.setEnabled(True)
+ self.start_b.setDefault(True)
+ self.start_b.setFocus()
+
self.stop_b.setEnabled(False)
else:
if self.step is not None:
diff --git a/src/ui/test_leak/test_leak.ui b/src/ui/test_leak/test_leak.ui
index 90ef48e..a9844d9 100644
--- a/src/ui/test_leak/test_leak.ui
+++ b/src/ui/test_leak/test_leak.ui
@@ -6,8 +6,8 @@
0
0
- 370
- 491
+ 1611
+ 894
@@ -26,313 +26,8 @@
0
- -
-
-
-
- 12
- 75
- true
-
-
-
- PROVA TENUTA
-
-
-
-
-
-
-
- 16
- 50
- false
-
-
-
- Tipo di test
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- Pressione del circuito
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- Fase del test
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- Pressione regolatore
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 130
- 16777215
-
-
-
-
- 20
- 50
- false
-
-
-
- background-color: rgb(255, 255, 255);
-border: 1px solid black;
-
-
-
- -
-
-
-
- -
-
-
-
- 130
- 16777215
-
-
-
-
- 20
- 50
- false
-
-
-
- background-color: rgb(255, 255, 255);
-border: 1px solid black;
-
-
-
- -
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- Perdita
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- -
-
-
-
- -
-
-
-
- 130
- 16777215
-
-
-
-
- 20
- 50
- false
-
-
-
- background-color: rgb(255, 255, 255);
-border: 1px solid black;
-
-
-
- -
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- Indice di sequenza del test
-
-
- Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- mbar
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- mbar
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- mbar
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- background-color: rgb(255, 255, 255);
-border: 1px solid black;
-
-
-
- -
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- background-color: rgb(255, 255, 255);
-border: 1px solid black;
-
-
-
- -
-
-
-
- -
-
-
-
- 16
- 50
- false
-
-
-
- background-color: rgb(255, 255, 255);
-border: 1px solid black;
-
-
-
- -
-
-
-
-
-
-
- -
-
+
-
+
0
@@ -345,529 +40,10 @@ border: 1px solid black;
100
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 127
- 255
- 127
-
-
-
-
-
-
- 63
- 255
- 63
-
-
-
-
-
-
- 0
- 127
- 0
-
-
-
-
-
-
- 0
- 170
- 0
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 127
- 255
- 127
-
-
-
-
-
-
- 255
- 255
- 220
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 127
- 255
- 127
-
-
-
-
-
-
- 63
- 255
- 63
-
-
-
-
-
-
- 0
- 127
- 0
-
-
-
-
-
-
- 0
- 170
- 0
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 127
- 255
- 127
-
-
-
-
-
-
- 255
- 255
- 220
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 0
- 127
- 0
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 127
- 255
- 127
-
-
-
-
-
-
- 63
- 255
- 63
-
-
-
-
-
-
- 0
- 127
- 0
-
-
-
-
-
-
- 0
- 170
- 0
-
-
-
-
-
-
- 0
- 127
- 0
-
-
-
-
-
-
- 255
- 255
- 255
-
-
-
-
-
-
- 0
- 127
- 0
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 85
- 255
- 127
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 0
- 255
- 0
-
-
-
-
-
-
- 255
- 255
- 220
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
- 0
- 0
- 0
-
-
-
-
-
-
-
-
- 20
- 75
- true
-
-
-
- background-color:rgb(85, 255, 127);
-
-
- START
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 12
- 75
- true
-
-
-
- Risultato
-
-
-
-
-
-
-
- 0
- 0
-
-
-
- %v / %m
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 32
- 32
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
+
- 0
- 100
+ 16777215
+ 16777215
@@ -1327,7 +503,1018 @@ border: 1px solid black;
- -
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 100
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 255
+ 127
+ 127
+
+
+
+
+
+
+ 255
+ 63
+ 63
+
+
+
+
+
+
+ 127
+ 0
+ 0
+
+
+
+
+
+
+ 170
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 127
+ 127
+
+
+
+
+
+
+ 255
+ 255
+ 220
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 255
+ 127
+ 127
+
+
+
+
+
+
+ 255
+ 63
+ 63
+
+
+
+
+
+
+ 127
+ 0
+ 0
+
+
+
+
+
+
+ 170
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 127
+ 127
+
+
+
+
+
+
+ 255
+ 255
+ 220
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 127
+ 0
+ 0
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 255
+ 127
+ 127
+
+
+
+
+
+
+ 255
+ 63
+ 63
+
+
+
+
+
+
+ 127
+ 0
+ 0
+
+
+
+
+
+
+ 170
+ 0
+ 0
+
+
+
+
+
+
+ 127
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 127
+ 0
+ 0
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 112
+ 112
+ 255
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 255
+ 220
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 20
+ 75
+ true
+
+
+
+ background-color:rgb(112, 112, 255);
+
+
+ MOSTRA ISTRUZIONE
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 12
+ 75
+ true
+
+
+
+ Risultato
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ %v / %m
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 32
+ 32
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 100
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 127
+ 255
+ 127
+
+
+
+
+
+
+ 63
+ 255
+ 63
+
+
+
+
+
+
+ 0
+ 127
+ 0
+
+
+
+
+
+
+ 0
+ 170
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 127
+ 255
+ 127
+
+
+
+
+
+
+ 255
+ 255
+ 220
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 127
+ 255
+ 127
+
+
+
+
+
+
+ 63
+ 255
+ 63
+
+
+
+
+
+
+ 0
+ 127
+ 0
+
+
+
+
+
+
+ 0
+ 170
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 127
+ 255
+ 127
+
+
+
+
+
+
+ 255
+ 255
+ 220
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 0
+ 127
+ 0
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 127
+ 255
+ 127
+
+
+
+
+
+
+ 63
+ 255
+ 63
+
+
+
+
+
+
+ 0
+ 127
+ 0
+
+
+
+
+
+
+ 0
+ 170
+ 0
+
+
+
+
+
+
+ 0
+ 127
+ 0
+
+
+
+
+
+
+ 255
+ 255
+ 255
+
+
+
+
+
+
+ 0
+ 127
+ 0
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 85
+ 255
+ 127
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 255
+ 0
+
+
+
+
+
+
+ 255
+ 255
+ 220
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 20
+ 75
+ true
+
+
+
+ background-color:rgb(85, 255, 127);
+
+
+ START
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+ -
@@ -1347,6 +1534,558 @@ border: 1px solid black;
+ -
+
+
+
+ 12
+ 75
+ true
+
+
+
+ PROVA TENUTA
+
+
+
-
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Caduta massima ammessa
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Indice di sequenza del test
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Pressione regolatore
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ mbar
+
+
+
+ -
+
+
+
+ 130
+ 16777215
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Tipo di test
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 130
+ 16777215
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 150
+ 0
+
+
+
+
+ 150
+ 16777215
+
+
+
+
+ 48
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ 1/1
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Minimum
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ mbar
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Pressione del circuito
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 130
+ 16777215
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ mbar
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ mbar
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ mbar
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Fase del test
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 130
+ 16777215
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Caduta di pressione misurata
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 130
+ 16777215
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Pressione di test da ricetta
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ Caduta minima ammessa
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ mbar
+
+
+
+ -
+
+
+
+ 130
+ 16777215
+
+
+
+
+ 20
+ 50
+ false
+
+
+
+ background-color: rgb(255, 255, 255);
+border: 1px solid black;
+
+
+
+ -
+
+
+
+ -
+
+
+
+ 16
+ 50
+ false
+
+
+
+ 0
+
+
+ NUMERO TEST
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ -
+
+
+ Qt::AlignCenter
+
+
+
+
+
+
diff --git a/src/ui/test_test/test_test.py b/src/ui/test_test/test_test.py
index 34413bd..d14f358 100644
--- a/src/ui/test_test/test_test.py
+++ b/src/ui/test_test/test_test.py
@@ -1,5 +1,7 @@
import sys
+import time
import weakref
+from datetime import datetime
from lib.helpers import timing
from PyQt5.QtCore import Qt, QTimer, pyqtSignal
@@ -119,6 +121,7 @@ class Test_Test(Widget):
self.last = None
def get(self, data=None, override=False, fail=False, preserve_counter=False, skip_delay=False):
+ cur_timing = timing()
if self.done: # avoid proccessing if completed
return
if data is None:
@@ -129,18 +132,19 @@ class Test_Test(Widget):
data = self.last if self.last is not None else {}
else:
data = data[-data_usable.index(True) - 1]
- if data.get("time", None) is None:
- data["time"] = timing()
+ data["time"] = datetime.now().strftime("%H:%M:%S")
if fail:
result_ok = False
elif override:
result_ok = True
else:
result_ok = data.get("results", {}).get("ok", None)
+ duration=cur_timing - self.start_time
+ data.pop("step",None)
self.last = {
**data,
"overridden": override,
- "duration": timing() - self.start_time,
+ "duration": float(f"{duration:.2f}"),
"ok": result_ok,
}
if fail: