save recipes wip

This commit is contained in:
neo 2024-10-04 11:39:16 +02:00
parent e3db54583d
commit dd88b1eafa
7 changed files with 342 additions and 57 deletions

View File

@ -1,66 +1,107 @@
[machine]
description = ST-TEN-2 - COLLAUDO TUBI RISCALDATI VOLPIANO
instruction_folder = st-ten-2
image_for_warning= st-ten-2
description = ST-TEN-1
instruction_folder = st-ten-1
image_for_warning= st-ten-1
[hardware_config]
archive_synchronizer: present
galaxy_camera: absent
uvc_camera: absent
label_printer: present
neo_pixels: absent
remote_api: absent
tecna_t3: present
[digital_io]
# OUTPUT MAP FOR EXTERNAL FLUSH/BLOW UNIT
id_flush_blow: USB-5860,BID#0
blow_on: 0 # INPUT VALVE TO SERVICE AIR
flush_on: 1 # OUTPUT VALVE TO DIRT COLLECTOR
blow_led:2 # CLEAN INDICATOR
test_on_led:3 # LEAK TEST ACTIVE INDICATOR
flush_led:4 # FLUSH INDICATOR
vision_saver: absent
vision: absent
screwdriver: absent
fixture_id: absent
digital_io: present
external_flush_blow: absent
[tecna_t3]
port: /dev/ttyUSB0
model: t3l
[fixture_rfid]
port: COM5
[digital_io]
# OUTPUT MAP FOR FIXTURE CONNECTOR
id_fixture: USB-5862,BID#0
discard_idx:12 # BIT NUMBER OF THE I/0 MODULE USED FOR DISCARD SENSING
[recipe]
recipe_name_field: cod finito cliente
part_number_field: cod finito r5
barcode_enable_field: verifica_codice_a_barre_abilitata
barcode_serial_field: codice_a_barre
label_template_field: etichetta
description_field: cod semilavorato costampato
recipe_name_field: codice_ricetta
part_number_field: codice_prodotto
label_template_field: modello_etichetta
description_field: descrizione
[label_printer]
platform: windows
printer: zd420
[recipes_defaults]
prova_tenuta_abilitata: x
tester_discharge_enable: yes
codice_ricetta: specificare ricetta
cliente: IVECO
part_number: specificare part number
canale_di_prova: 0
warning_img:
dimensione_lotto_abilitata:
n_componenti:1
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: 1000
tempo_riempimento: 10
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: 15000
pressione_di_test: 5000
pressione_di_test_delta_massimo: 30
tempo_svuotamento: 1
pressione_svuotamento: 100
canale_di_prova: 0
tester_discharge_enable: yes
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: 5
filling_time: 10
settling_time: 10
settling_pressure_min_percent: 5
settling_pressure_max_percent: 5
test_pressure: 7000
test_time: 10
test_pressure_qneg: 5
test_pressure: 9000
test_pressure_qpos: 5
test_pressure_qpos: 10 #Q+ Upper test leak limit
test_pressure_qneg: 30 #Q- Lower test leak limit
test_pressure_tt_qpos: 1 # 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

View File

@ -0,0 +1,107 @@
[machine]
description = TEST-LINUX
instruction_folder = st-ten-1
image_for_warning= st-ten-1
[hardware_config]
archive_synchronizer: absent
galaxy_camera: absent
uvc_camera: absent
label_printer: present
neo_pixels: absent
remote_api: absent
tecna_t3: present
vision_saver: absent
vision: absent
screwdriver: absent
fixture_id: absent
digital_io: absent
external_flush_blow: absent
[tecna_t3]
port: /dev/ttyUSB0
model: t3p
[fixture_rfid]
port: COM5
[digital_io]
# OUTPUT MAP FOR FIXTURE CONNECTOR
id_fixture: USB-5862,BID#0
discard_idx:12 # BIT NUMBER OF THE I/0 MODULE USED FOR DISCARD SENSING
[recipe]
recipe_name_field: codice_ricetta
part_number_field: codice_prodotto
label_template_field: modello_etichetta
description_field: descrizione
[label_printer]
platform: windows
printer: zd420
[recipes_defaults]
tester_discharge_enable: yes
codice_ricetta: specificare ricetta
cliente: IVECO
part_number: specificare part number
canale_di_prova: 0
warning_img:
dimensione_lotto_abilitata:
n_componenti:1
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: 10
settling_time: 10
settling_pressure_min_percent: 5
settling_pressure_max_percent: 5
test_pressure: 7000
test_time: 10
test_pressure_qpos: 10 #Q+ Upper test leak limit
test_pressure_qneg: 30 #Q- Lower test leak limit
test_pressure_tt_qpos: 1 # 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

View File

@ -361,27 +361,29 @@ class TecnaMarpossProvasetT3(ModbusComponent):
self.log.info(f"saved {min(len(recipes), max(self.max_program_number - 1, 0))} recipes")
self._store_recipes_lock.release(1)
def read_recipe(self, recipe_number, step):
# SELECT & READ RECIPE FROM TECNA MEMORY
def read_recipe(self, recipe_number):
spec = {
"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"],
"T2 - Settling time": step.spec["settling_time"],
"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_qneg"],
"Q+ Upper test leak limit": step.spec["test_pressure_qpos"],
"FST - Discharge time": step.spec["flush_time"],
"FSL - Discharge limit": step.spec["flush_pressure"],
"T0 - Pre-filling time": "pre_filling_time",
"P0 - Pre-filling pressure": "pre_filling_pressure",
"T1 - Filling time": "filling_time",
"T2 - Settling time": "settling_time",
"PR- - Min pressure tolerance %": "settling_pressure_min_percent",
"PR+ - Max pressure tolerance % (P+)": "settling_pressure_max_percent",
"T3 - Measure time": "test_time",
"Q- Lower test leak limit": "test_pressure_qneg",
"Q+ Upper test leak limit": "test_pressure_qpos",
"FST - Discharge time": "flush_time",
"FSL - Discharge limit": "flush_pressure",
}
if self.model == "t3p":
spec.update({
"PREL - Nominal test pressure": step.spec["test_pressure"],
"PREL - Nominal test pressure": "test_pressure",
})
elif self.model == "t3l":
spec.update({
"Nominal peak pressure": step.spec["test_pressure"],
"Nominal peak pressure": "test_pressure",
})
else:
raise NotImplementedError(f"tecna t3 model {self.model!r} not implemented.")
@ -389,9 +391,9 @@ class TecnaMarpossProvasetT3(ModbusComponent):
# SET RECIPE NUMBER
self.write("Active test program number", recipe_number)
read_recipe={}
recipe_data={}
# READ ALL PARAMETERS
for register_name, field_name in spec.items():
read_recipe[field_name] = self.read(register_name)
recipe_data[field_name] = self.read(register_name)
return read_recipe
return recipe_data

View File

@ -1,11 +1,16 @@
#!/usr/bin/env python3
import argparse
import csv
import faulthandler
import logging
import os
import platform
import signal
import sys
sys.argv.append("--debug")
sys.argv.append("--sim-io")
sys.argv.append("--system-id=test-linux")
import traceback
import weakref
from datetime import datetime
@ -24,7 +29,6 @@ parser = argparse.ArgumentParser(prog='ST-TEN', description='Leak test system')
parser.add_argument('-s', '--system-id')
args, unspec = parser.parse_known_args()
def quit_app(signalnum=None, handler=None):
logging.info(f"quitting app. signal: {signalnum!r}, handler: {handler!r}")
global app
@ -68,7 +72,7 @@ try:
from lib.db import Users
from lib.helpers import ConfigReader
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QApplication, QMessageBox
from PyQt5.QtWidgets import QApplication, QMessageBox, QFileDialog
from ui import About, Archive, Login, Main_Window, Test, Users_Management, Recipe_Selection, \
Barcode_Recipe_Selection
@ -79,6 +83,7 @@ try:
def __init__(self, parent=None):
# print(f"MAIN {int(QThread.currentThreadId())}", flush=True)
super().__init__()
self.recipes = None
try:
# READ CONFIG
@ -116,20 +121,145 @@ try:
QMessageBox.critical(None, "Errore", f"Errore di avvio del programma di collaudo:\n\n{e}")
quit()
def save_recipes(self):
self.components["tecna_t3"].read_recipes
def read_recipes(self):
self.recipes = {}
for recipe_num in range(1,100):
self.recipes[recipe_num] = self.components["tecna_t3"].read_recipe(recipe_num)
def export_recipes(self, csv_path=None):
if csv_path is None:
csv_path, _ = QFileDialog.getSaveFileName(
None,
"Esportazione ricette",
"ricette.csv",
"CSV data (*.csv);;All Files (*)",
)
csv_path = str(csv_path)
if not len(csv_path):
return
if not csv_path.lower().endswith(".csv"):
csv_path += ".csv"
csv_dir = os.path.dirname(csv_path)
if len(csv_dir):
os.makedirs(csv_dir, exist_ok=True)
data = []
fieldnames = [
"ricetta",
"cliente",
"part_number",
"dimensione_lotto_abilitata",
"dimensione_lotto",
"verifica_connettore_abilitata",
"connettore",
"verifica_resistenza_connettore_abilitata",
"scala_resistenza",
"r nominale",
"tolleranza_resistenza_pos",
"tolleranza_resistenza_neg",
"avvitatura_abilitata",
"viti",
"prova_tenuta_abilitata",
"tempo_pre_riempimento",
"pressione_pre_riempimento",
"tempo_riempimento",
"tempo_assestamento",
"percentuale_minima_pressione_assestamento",
"percentuale_massima_pressione_assestamento",
"tempo_di_test",
"pressione_di_test_delta_minimo",
"pressione_di_test",
"pressione_di_test_delta_massimo",
"tempo_svuotamento",
"pressione_svuotamento",
"prova_tenuta_abilitata_2",
"tempo_pre_riempimento_2",
"pressione_pre_riempimento_2",
"tempo_riempimento_2",
"tempo_assestamento_2",
"percentuale_minima_pressione_assestamento_2",
"percentuale_massima_pressione_assestamento_2",
"tempo_di_test_2",
"pressione_di_test_delta_minimo_2",
"pressione_di_test_2",
"pressione_di_test_delta_massimo_2",
"tempo_svuotamento_2",
"pressione_svuotamento_2",
"test_visione_abilitato",
"ricetta_visione",
"stampa_etichetta_abilitata",
print_template_field,
]
for num,recipe in self.recipes.items():
steps = recipe.get_steps_map()
exportable = {
recipe_name_field: recipe.name,
"cliente": recipe.client,
"part_number": recipe.part_number,
# "dimensione_lotto_abilitata": "x" if recipe.spec["count"] else "",
# "dimensione_lotto": steps["count"].spec["amount"],
"verifica_connettore_abilitata": "x" if recipe.spec["connector"] else "",
"connettore": steps["connector"].spec["connector"],
barcode_enable_field: "x" if recipe.spec["barcodes"] else "",
barcode_serial_field: steps["barcodes"].spec["serial"],
"verifica_resistenza_connettore_abilitata": "x" if recipe.spec["resistance"] else "",
"scala_resistenza": steps["resistance"].spec["scale"],
"r nominale": steps["resistance"].spec["expected"],
"tolleranza_resistenza_pos": steps["resistance"].spec["tolerance_pos"],
"tolleranza_resistenza_neg": steps["resistance"].spec["tolerance_neg"],
# "avvitatura_abilitata": "x" if recipe.spec["screws"] else "",
# "viti": steps["screws"].spec["quantity"],
"prova_tenuta_abilitata": "x" if recipe.spec["leak_1"] else "",
"tempo_pre_riempimento": steps["leak_1"].spec["pre_filling_time"],
"pressione_pre_riempimento": steps["leak_1"].spec["pre_filling_pressure"],
"tempo_riempimento": steps["leak_1"].spec["filling_time"],
"tempo_assestamento": steps["leak_1"].spec["settling_time"],
"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_qneg"],
"pressione_di_test": steps["leak_1"].spec["test_pressure"],
"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 "",
"tempo_pre_riempimento_2": steps["leak_2"].spec["pre_filling_time"],
"pressione_pre_riempimento_2": steps["leak_2"].spec["pre_filling_pressure"],
"tempo_riempimento_2": steps["leak_2"].spec["filling_time"],
"tempo_assestamento_2": steps["leak_2"].spec["settling_time"],
"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_qneg"],
"pressione_di_test_2": steps["leak_2"].spec["test_pressure"],
"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"],
"ricetta_visione": steps["vision"].spec["recipe"],
"stampa_etichetta_abilitata": "x" if recipe.spec["print"] else "",
"modello_etichetta": steps["print"].spec["template"],
}
data.append(exportable)
if len(data):
self.log.info(f"recipes: exporting recipes to {csv_path}")
with open(csv_path, "w", newline="") as f:
w = csv.DictWriter(f, fieldnames, extrasaction="ignore")
w.writeheader()
w.writerows(data)
self.log.info(f"recipes: exported {len(data)} rows.")
if __name__ == "__main__":
app = QApplication(sys.argv)
with SingleProcess() as single_process_lock:
if not single_process_lock and "--no-lock" not in sys.argv:
logging.error(f"Program already opened, exiting...")
QMessageBox.critical(None, "ERRORE", "IL PROGRAMMA E' GIA' IN ESECUZIONE")
exit(0)
main = Main()
main.read_recipes()
main.export_recipes()
if "--no-gui" not in sys.argv:
app.exec()

View File

@ -1,5 +1,6 @@
import ast
import json
import logging
import traceback
import weakref
from datetime import datetime
@ -40,6 +41,7 @@ class Cell:
modified = pyqtSignal(bool)
def __init__(self, action=None, readonly=True, autocomplete=None, field_name=None, field_alias=None, field=None, row_number=None, crud=None):
self.log = logging.getLogger(f"{self.__class__.__name__} ({id(self)})")
self.readonly = readonly
self.autocomplete = autocomplete
self.field_name = field_name

View File

@ -182,6 +182,7 @@ class Recipe_Selection(Widget):
val = dict.get(key, self.defaults[key])
return val if val != "" else self.defaults[key]
# READ RECIPE STEPS FROM CSV ROW
def read_steps(self, row, defaults=None):
if defaults is None:
global noner
@ -273,6 +274,7 @@ class Recipe_Selection(Widget):
},
}
# IMPORT RECIPES FROM CSV FILE TO DATABASE
def import_recipes(self, csv_path=None, defaults=None):
if defaults is None:
global noner
@ -341,6 +343,7 @@ class Recipe_Selection(Widget):
self.log.info(f"recipes: imported {count} rows.")
self.crud.refresh()
# EXPORT RECIPES TABLE TO CSV FILE
def export_recipes(self, csv_path=None):
if csv_path is None:
csv_path, _ = QFileDialog.getSaveFileName(

View File

@ -43,7 +43,7 @@ class Test_Leak(Test_Test):
def start_test(self):
# print extra labels
if self.step.type == "leak_1":
if self.step.step_type == "leak_1":
self.parent.print_extra_labels()
# SELECT TEST CHANNEL
@ -93,8 +93,8 @@ 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":
if "leak_2" in [s.step_type for s in self.parent.cycle_steps]:
if self.step.step_type=="leak_1":
self.test_num_l.setText("1/2")
else:
self.test_num_l.setText("2/2")
@ -143,7 +143,7 @@ class Test_Leak(Test_Test):
time.sleep(2)
# AUTO START SECOND TEST
if step.type == "leak_2":
if step.step_type == "leak_2":
self.recipe_written = False
time.sleep(1)
self.start_b.setEnabled(True)