diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5c72d7 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# ST-TEN-1 + +CONTROL SOFTWARE FOR ERRECINQUE LEAK TEST SYSTEMS + +## Getting started + +This software is deployed on many different systems, each using one of the following leak test instruments: +-Tecna T3L +-Tecna T3P +-Furness controls FCO730 + +In addition to leak testing, the software supports many other functions, depending on which system is deployed: +-electrical resistance measurement +-vision test +-fixture digital I/O management + + +## Setup +-Clone the repository +-On Windows: ./init_win.bat +-On Linux: ./init.sh + diff --git a/src/components/rfid_pn532.py b/src/components/rfid_pn532.py index fde6449..a066754 100644 --- a/src/components/rfid_pn532.py +++ b/src/components/rfid_pn532.py @@ -9,10 +9,9 @@ import nfc from nfc.clf import RemoteTarget - - class RFID_PN532(Component): new_id_signal = pyqtSignal(str) + 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.data_to_write = None diff --git a/src/main.py b/src/main.py index 2bb87f5..55cc62d 100644 --- a/src/main.py +++ b/src/main.py @@ -22,7 +22,8 @@ app = None parser = argparse.ArgumentParser(prog='ST-TEN', description='Leak test system') parser.add_argument('-s', '--system-id') -args,unspec = parser.parse_known_args() +args, unspec = parser.parse_known_args() + def quit_app(signalnum=None, handler=None): logging.info(f"quitting app. signal: {signalnum!r}, handler: {handler!r}") @@ -65,7 +66,7 @@ try: # IMPORT PROJECT ONLY AFTER SETTING UP SIGNAL, FAULTHANDLER AND LOGGING from components import (ArchiveSynchronizer, Multicomp730424, Os_Label_Printer, RemoteAPI, - TecnaMarpossProvasetT3,FurnessControlsLeakTester, TecnaScrewdriver, USB_586x,RFID_PN532) + TecnaMarpossProvasetT3, FurnessControlsLeakTester, TecnaScrewdriver, USB_586x, RFID_PN532) from lib.db import Users from lib.helpers import ConfigReader from PyQt5.QtCore import QObject, QThread, pyqtSignal @@ -106,9 +107,9 @@ try: "screwdriver": {"c": TecnaScrewdriver, "k": {"paused": True}}, "tecna_t3": {"c": TecnaMarpossProvasetT3, "k": {"paused": True}}, "furness_controls": {"c": FurnessControlsLeakTester, "k": {"paused": True}}, - "digital_io":{"c":USB_586x,"k":{"paused":True}}, - "digital_io_flush_blow":{"c":USB_586x,"k":{"paused":True}}, - "fixture_id":{"c":RFID_PN532,"k":{"paused":False, "lazy":False}}, + "digital_io": {"c": USB_586x, "k": {"paused": True}}, + "digital_io_flush_blow": {"c": USB_586x, "k": {"paused": True}}, + "fixture_id": {"c": RFID_PN532, "k": {"paused": False, "lazy": False}}, } # VISION COMPONENT IS OPTIONAL AND DISABLED BY DEFAULT if "--vision" in sys.argv: @@ -170,10 +171,10 @@ try: # self.main_window = Main_Window(self.bench) self.main_window = Main_Window() # CONNECT MAIN WINDOW ACTIONS - self.main_window.logout_a.triggered.connect(lambda checked, self=weakref.ref(self): self().logout()) + self.main_window.logout_a.triggered.connect(lambda checked, selfie=weakref.ref(self): selfie().logout()) self.main_window.archive_a.triggered.connect( - lambda checked, self=weakref.ref(self): self().main_window.open_dialog( - Archive(hide_cloud_image="vision_saver" not in self().components))) + lambda checked, selfie=weakref.ref(self): selfie().main_window.open_dialog( + Archive(hide_cloud_image="vision_saver" not in selfie().components))) if "--archive" in sys.argv: self.main_window.archive_a.trigger() if "--about" in sys.argv: @@ -182,9 +183,11 @@ try: # 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.about_a.triggered.connect( + lambda checked, selfie=weakref.ref(self): selfie().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, selfie=weakref.ref(self): selfie().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) self.main_window.ristampa_etichetta_a.triggered.connect(self.reprint_label) @@ -201,7 +204,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.barcode_selection_a.setVisible( + self.config["hardware_config"]["barcode_recipe_selection"] == "present") # OPEN LOGIN TAB self.open_login() @@ -228,15 +232,16 @@ try: else: self.main_window.admin_m.menuAction().setVisible(False) # open test - self.main_window.open_tab(Test(self.config, self.components,self)) + self.main_window.open_tab(Test(self.config, self.components, self)) self.main_window.centralWidget().request_autotest("login") else: self.main_window.admin_m.menuAction().setVisible(False) def logout(self): - #Users.logout() + # Users.logout() self.main_window.admin_m.menuAction().setVisible(False) - if type(self.main_window.centralWidget().centralWidget.widget) in (Recipe_Selection,Barcode_Recipe_Selection): + if type(self.main_window.centralWidget().centralWidget.widget) in ( + Recipe_Selection, Barcode_Recipe_Selection): # LOGOUT IMMEDIATELY IF NOT TESTING Users.logout() self.open_login() @@ -254,8 +259,11 @@ try: def set_recipe_mode_barcode(self): self.main_window.centralWidget().set_recipe_mode_barcode() + def reprint_label(self): self.main_window.centralWidget().reprint_label() + + if __name__ == "__main__": app = QApplication(sys.argv) diff --git a/src/ui/test/test.py b/src/ui/test/test.py index f1dd5c1..4a02e8c 100755 --- a/src/ui/test/test.py +++ b/src/ui/test/test.py @@ -5,33 +5,34 @@ import sys import weakref from datetime import datetime, timedelta +from PyQt5.QtCore import QTimer, pyqtSlot +from PyQt5.QtWidgets import QMessageBox from lib.db import Archive, Steps, Users from lib.helpers import get_shift from playhouse.shortcuts import model_to_dict -from PyQt5.QtCore import QTimer, pyqtSlot -from PyQt5.QtWidgets import QMessageBox +from ui.barcode_recipe_selection import Barcode_Recipe_Selection from ui.helpers import replace_widget from ui.recipe_selection import Recipe_Selection -from ui.barcode_recipe_selection import Barcode_Recipe_Selection from ui.test_assembly import Test_Assembly from ui.test_barcodes import Test_Barcodes from ui.test_connector import Test_Connector from ui.test_count import Test_Count from ui.test_count_end import Test_Count_End -from ui.test_warning_img import Test_Warning_Img -from ui.test_instructions import Test_Instructions from ui.test_fail import Test_Fail +from ui.test_instructions import Test_Instructions from ui.test_leak import Test_Leak from ui.test_resistance import Test_Resistance from ui.test_screws import Test_Screws from ui.test_vision import Test_Vision +from ui.test_warning_img import Test_Warning_Img from ui.widget import Widget class Test(Widget): - def __init__(self, config, components=None,main_window=None): + def __init__(self, config, components=None, main_window=None): super().__init__() - self.main_window=main_window + self.autotest_timer = None + self.main_window = main_window self.config = config self.components = components # GET LOGGER @@ -50,7 +51,7 @@ class Test(Widget): # INIT RECIPE self.recipe = None - if self.config["hardware_config"]["barcode_recipe_selection"]=="present": + if self.config["hardware_config"]["barcode_recipe_selection"] == "present": self.recipe_selection_mode = "barcode" else: self.recipe_selection_mode = "table" @@ -60,12 +61,12 @@ class Test(Widget): self.steps_dependencies = { "count": set(), "connector": {"multicomp", }, - "instruction":{"digital_io"}, + "instruction": {"digital_io"}, "screws": {"screwdriver", "tecna_t3", }, "resistance": {"multicomp", }, "leak_1": {self.tester_component, }, "leak_2": {self.tester_component, }, - "vision": {("uvc_camera", "galaxy_camera", ), "vision", "vision_saver", }, # "neo_pixels", }, + "vision": {("uvc_camera", "galaxy_camera",), "vision", "vision_saver", }, # "neo_pixels", }, "print": {"label_printer", }, } self.unsupported_steps = set() @@ -86,23 +87,31 @@ class Test(Widget): # "assembly_1": Test_Assembly(img_path=self.select_step_img("assembly_1"), text=u"INSERIRE SENSORE", widget=None), "barcodes": Test_Assembly(img_path=self.select_step_img("scan"), text=u"LEGGERE IL BARCODE DEL PEZZO DA COLLAUDARE", widget=Test_Barcodes()), "connector": Test_Assembly(img_path=self.select_step_img("scan"), text=u"COLLEGARE IL CONNETTORE INDICATO AL PEZZO E LEGGERE IL SUO BARCODE", widget=Test_Connector(run_once=True)), - "count": Test_Assembly(img_path=None, text=u"INSERIRE IL NUMERO DI PEZZI ATTESI PER IL LOTTO", widget=Test_Count(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces, run_once=True)), - "warning_img": Test_Assembly(img_path=None, text=u"ATTENZIONE - PER QUESTO CODICE ESEGUIRE LE OPERAZIONI INDICATE IN FIGURA", widget=Test_Warning_Img(components=self.components, recipe=self.recipe, step=self.step,run_once=True)), - "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)), + "count": Test_Assembly(img_path=None, text=u"INSERIRE IL NUMERO DI PEZZI ATTESI PER IL LOTTO", + widget=Test_Count(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces, run_once=True)), + "warning_img": Test_Assembly(img_path=None, text=u"ATTENZIONE - PER QUESTO CODICE ESEGUIRE LE OPERAZIONI INDICATE IN FIGURA", + widget=Test_Warning_Img(components=self.components, recipe=self.recipe, step=self.step, run_once=True)), + "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), + "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(parent=self)), "blow": Test_Assembly(img_path=None, text=u"SOFFIAGGIO TUBO IN CORSO - ATTENDERE...", widget=Test_Warning_Img(components=self.components, recipe=self.recipe, step=self.step)), - "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,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, parent=self)), "flush": Test_Assembly(img_path=None, text=u"SCARICO ARIA IN CORSO - ATTENDERE...", widget=Test_Warning_Img(components=self.components, recipe=self.recipe, step=self.step)), - "instruction": Test_Assembly(img_path=None, text=u"ESEGUIRE LE OPERAZIONI DI MONTAGGIO INDICATE IN FIGURA", widget=Test_Instructions(components=self.components, recipe=self.recipe,bench_name=self.config.machine_id, step=self.step)), - "piece_removal": Test_Assembly(img_path=None, text=u"RIMUOVERE IL PEZZO APRENDO TUTTE LE CHIUSURE", widget=Test_Instructions(components=self.components, recipe=self.recipe,bench_name=self.config.machine_id, step=self.step)), + "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)), + "piece_removal": Test_Assembly(img_path=None, text=u"RIMUOVERE IL PEZZO APRENDO TUTTE LE CHIUSURE", + 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)), + "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)), "screws": Test_Assembly(img_path=None, text=u"AVVITARE TUTE LE VITI COME INDICATO", widget=Test_Screws(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces)), "select_recipe": Test_Assembly(img_path=None, text=u"SELEZIONARE IL CODICE DA COLLAUDARE", widget=Recipe_Selection(config=self.config, unsupported_steps=self.unsupported_steps)), - "barcode_recipe_selection": Test_Assembly(img_path=self.select_step_img("scan"), text=u"LEGGERE IL BARCODE SULLA DIMA DEL COMPONENTE DA COLLAUDARE", widget=Barcode_Recipe_Selection(parent=self)), + "barcode_recipe_selection": Test_Assembly(img_path=self.select_step_img("scan"), text=u"LEGGERE IL BARCODE SULLA DIMA DEL COMPONENTE DA COLLAUDARE", + widget=Barcode_Recipe_Selection(parent=self)), "vision": Test_Assembly(img_path=None, text=u"VERIFICARE CONTROLLO CON TELECAMERA", widget=Test_Vision(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces)), "wait": Test_Assembly(img_path=self.select_step_img("wait"), text=u"ATTENDERE - PAUSA INTER CICLO", widget=None), None: Test_Assembly(img_path=self.select_step_img("warning"), text=u"ATTENZIONE - LA RICETTA SELEZIONATA NON CONTIENE FASI DI TEST", widget=None), @@ -120,7 +129,7 @@ class Test(Widget): if "--no-autotest" not in sys.argv: self.autotest_period = int(8.5 * 60 * 60 * 1000) # 8.5 HOURS # self.autotest_period = 12 * 60 * 60 * 1000 # 12 HOURS - #if not self.config["autotest_done"]: + # if not self.config["autotest_done"]: # self.request_autotest("init") else: self.autotest_period = None @@ -134,15 +143,15 @@ class Test(Widget): for step_name, w in self.cycle_available_steps.items(): if hasattr(w, "ok"): # custom ok handlers should call next again - if isinstance(w.widget, (Recipe_Selection)): + if isinstance(w.widget, Recipe_Selection): w.ok.connect(self.set_recipe) else: - w.ok.connect(lambda data=None, step_name=step_name, self=weakref.ref(self): self().set_step(step_name, data)) + w.ok.connect(lambda data=None, step_namel=step_name, selfie=weakref.ref(self): selfie().set_step(step_namel, data)) if hasattr(w, "ko"): w.ko.connect(self.fail_cycle) # CUSTOM STEP CONNECTIONS self.cycle_available_steps["count"].ok.connect(self.cycle_available_steps["count_end"].widget.set_amount) - #self.cycle_available_steps["warning_img"].ok.connect(self.cycle_available_steps["warning_img"].widget.set_done) + # self.cycle_available_steps["warning_img"].ok.connect(self.cycle_available_steps["warning_img"].widget.set_done) if "fixture_id" in self.components.keys(): self.components["fixture_id"].new_id_signal.connect(self.load_recipe_from_rfid) @@ -193,6 +202,7 @@ class Test(Widget): def set_recipe_mode_barcode(self): self.recipe_selection_mode = "barcode" self.change_recipe() + def reprint_label(self): self.print(self.last_label, self.print_step.spec.get("template", "EtichettaR5")) @@ -206,7 +216,7 @@ class Test(Widget): if "--no-autotest" not in sys.argv: self.log.info(f"cycle request autotest: reason: {reason!r} autotest_request: {self.autotest_request!r}") - if reason in ("init","login"): + if reason in ("init", "login"): self.autotest_timer = QTimer() self.autotest_timer.setSingleShot(False) self.autotest_timer.timeout.connect(self.request_periodic_autotest) @@ -217,7 +227,6 @@ class Test(Widget): if reason == "logout": self.next(action="abort") - def request_periodic_autotest(self): self.request_autotest("periodic") @@ -236,12 +245,12 @@ class Test(Widget): self.cycle_available_steps["leak_2"].widget.recipe_written = False self.step = Steps(type="select_recipe") self.cycle_index = -1 - self.recipe=None - self.cycle_steps=None + self.recipe = None + self.cycle_steps = None # COUNT RESET self.pieces["ok"] = 0 self.pieces["ko"] = 0 - elif action in ("fail","abort"): + elif action in ("fail", "abort"): self.log.info(f"cycle next: action: {action!r}") # FAIL AND RESTART TEST self.step = Steps(type="fail") @@ -286,7 +295,7 @@ class Test(Widget): else: t = datetime.now() self.last_at_l.setText("{d}/{mo}/{y} {h}:{m}".format(y=t.year, mo=t.month, d=t.day, h=t.hour, m=t.minute)) - t+=timedelta(seconds=int(self.autotest_period/1000)) + t += timedelta(seconds=int(self.autotest_period / 1000)) self.next_at_l.setText("{d}/{mo}/{y} {h}:{m}".format(y=t.year, mo=t.month, d=t.day, h=t.hour, m=t.minute)) self.autotesting_reason = None self.cycle_index = -1 @@ -317,8 +326,8 @@ class Test(Widget): self.data["recipe"] = model_to_dict(self.recipe) w = self.cycle_available_steps[self.step.type] show = None - if self.step.type=="leak_2": - self.setCentralWidget(w) # NEED TO PRESHOW UI + if self.step.type == "leak_2": + self.setCentralWidget(w) # NEED TO PRESHOW UI if hasattr(w, "start"): show = w.start(recipe=self.recipe, step=self.step, pieces=self.pieces) if show is not False and w is not current_w: @@ -327,7 +336,7 @@ class Test(Widget): self.next_timer.start(0) if self.step.type == "done": self.archived = self.done() - self.last_label=copy.deepcopy(self.archived) + self.last_label = copy.deepcopy(self.archived) self.next_timer.start(500) elif self.step.type == "print": compiled_label = self.print(self.archived, self.step.spec.get("template", "EtichettaR5")) @@ -369,7 +378,7 @@ class Test(Widget): count_found = True if "warning_img" in step.spec: if step.spec["warning_img"]: - steps.insert(i,Steps(type="warning_img", spec={"warning_img":step.spec["warning_img"]})) + steps.insert(i, Steps(type="warning_img", spec={"warning_img": step.spec["warning_img"]})) skip.add(i + 1) if "assembly" in step.spec: if step.spec["assembly"]: @@ -378,7 +387,7 @@ class Test(Widget): if "require_discard_piece" in step.spec: if step.spec["require_discard_piece"]: self.require_discard_piece = True - if step.type == "resistance": # ADD STEP TO ENSURE REMOVAL OF CONNECTOR + if step.type == "resistance": # ADD STEP TO ENSURE REMOVAL OF CONNECTOR steps.insert(i + 1, Steps(type="resistance", spec={ "scale": 500, "expected": float("+inf"), @@ -396,7 +405,7 @@ class Test(Widget): steps.append(Steps(type="piece_removal")) if count_found: steps.append(Steps(type="count_end")) - if step.type in ("leak_1","leak_2"): + if step.type in ("leak_1", "leak_2"): self.leak_step = step if not print_found: @@ -406,52 +415,52 @@ class Test(Widget): steps.append(Steps(type="wait")) self.cycle_steps = steps self.check_steps_dependencies(self.cycle_steps) - leak_autotest_steps=[] + leak_autotest_steps = [] # CONFIGURE LEAK AUTOTEST PARAMETERS - if self.config["autotest_leak"]["enabled"]=="true": - l_at_1=copy.deepcopy(self.config["autotest_leak"]) + if self.config["autotest_leak"]["enabled"] == "true": + l_at_1 = copy.deepcopy(self.config["autotest_leak"]) l_at_1.pop("enabled") - l_at_1={a: float(x) for a, x in l_at_1.items()} - l_at_1["autotest"]="ko_check" - l_at_2=copy.deepcopy(self.config["autotest_leak"]) + l_at_1 = {a: float(x) for a, x in l_at_1.items()} + l_at_1["autotest"] = "ko_check" + 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)] + 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)] self.autotest_cycle_steps = [ *([ - Steps(type="resistance", spec={ - "scale": 500, - "expected": 1, - "tolerance_pos": 5, - "tolerance_neg": 5, - "autotest": True, - }), - Steps(type="resistance", spec={ - "scale": 500, - "expected": float("+inf"), - "tolerance_pos": 0, - "tolerance_neg": 0, - "autotest": True, - }), - Steps(type="resistance", spec={ - "scale": 500, - "expected": 10, - "tolerance_pos": 1, - "tolerance_neg": 1, - "autotest": True, - }), - Steps(type="resistance", spec={ - "scale": 500, - "expected": float("+inf"), - "tolerance_pos": 0, - "tolerance_neg": 0, - "autotest": True, - }), - ] if "resistance" not in self.unsupported_steps else []), + Steps(type="resistance", spec={ + "scale": 500, + "expected": 1, + "tolerance_pos": 5, + "tolerance_neg": 5, + "autotest": True, + }), + Steps(type="resistance", spec={ + "scale": 500, + "expected": float("+inf"), + "tolerance_pos": 0, + "tolerance_neg": 0, + "autotest": True, + }), + Steps(type="resistance", spec={ + "scale": 500, + "expected": 10, + "tolerance_pos": 1, + "tolerance_neg": 1, + "autotest": True, + }), + Steps(type="resistance", spec={ + "scale": 500, + "expected": float("+inf"), + "tolerance_pos": 0, + "tolerance_neg": 0, + "autotest": True, + }), + ] if "resistance" not in self.unsupported_steps else []), *(leak_autotest_steps), Steps(type="done"), Steps(type="wait"), @@ -503,9 +512,11 @@ class Test(Widget): if not self.components[dependency].ready: missing_components.add(dependency) if len(unsupported_steps): - QMessageBox.critical(None, "Errore Ricetta", f"Questa ricetta contiene uno o piu step non supportati da questo banco:\n{', '.join(sorted(unsupported_steps))}\nModificare la ricetta adeguatamente.") + QMessageBox.critical(None, "Errore Ricetta", + f"Questa ricetta contiene uno o piu step non supportati da questo banco:\n{', '.join(sorted(unsupported_steps))}\nModificare la ricetta adeguatamente.") if len(missing_components): - QMessageBox.critical(None, "Errore Componenti Ricetta", f"Questa ricetta richiede i seguenti componenti per essere eseguita:\n{', '.join(sorted(missing_components))}\nModificare la ricetta adeguatamente o collegare i componenti elencati.") + QMessageBox.critical(None, "Errore Componenti Ricetta", + f"Questa ricetta richiede i seguenti componenti per essere eseguita:\n{', '.join(sorted(missing_components))}\nModificare la ricetta adeguatamente o collegare i componenti elencati.") if len(unsupported_steps) or len(missing_components): self.change_recipe() @@ -514,10 +525,10 @@ class Test(Widget): self.data[step_name] = {} if data is not None: data["step"] = model_to_dict(self.step) - data["step"].pop("name",None) + data["step"].pop("name", None) # MAKE ARRAY ONLY IF MORE THAN ONE TEST OF SAME TYPE - if len(self.data[step_name])>1: + if len(self.data[step_name]) > 1: self.data[step_name][str(len(self.data[step_name]))] = data else: self.data[step_name] = data @@ -530,17 +541,17 @@ class Test(Widget): 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"]: + 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(): - results={k:self.data[leak]["results"][self.tester_component][k] for k in ["Running test: result"]} + results = {k: self.data[leak]["results"][self.tester_component][k] for k in ["Running test: result"]} - results.update({k:round(float(self.data[leak]["results"][self.tester_component][k]),2) for k in ["Running test: filling pressure", - "Running test: measured leak", - "Running test: pressure at the end of settling"]} + results.update({k: round(float(self.data[leak]["results"][self.tester_component][k]), 2) for k in ["Running test: filling pressure", + "Running test: measured leak", + "Running test: pressure at the end of settling"]} ) - self.data[leak]["results"]=results + self.data[leak]["results"] = results if "vision" in self.data: vision_test_1 = self.data.get("vision", {}).get("0", {}) @@ -607,10 +618,10 @@ class Test(Widget): leak_test_2_step_spec = leak_test_2_step.get("spec", {}) leak_test_2_results = leak_test_2.get("results", {}) - 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) + 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) leak_test_1_results["Running test: pressure at the end of measure"] = leak_test_1_results["Running test: pressure at the end of settling"] - leak_test_1_results["Running test: measured leak"] printer_fields = self.print_step.spec context = { @@ -685,10 +696,10 @@ class Test(Widget): "RESULT_L2": str("CONFORME" if leak_test_1_results.get("ok", False) else "SCARTO"), } for n in range(5): - field=f"labeltxt_{n+1}" + field = f"labeltxt_{n + 1}" if field in printer_fields.keys(): - if printer_fields[field] !="": - context[field.upper()]=printer_fields[field] + if printer_fields[field] != "": + context[field.upper()] = printer_fields[field] # PRINT MAIN PRODUCT LABEL compiled_label = self.components["label_printer"].print_label(label, context=context) @@ -705,7 +716,7 @@ class Test(Widget): self.components["extra_label_printer"].print_label(f"{label}.prn", context=None) @pyqtSlot(str) - def load_recipe_from_rfid(self,data): + def load_recipe_from_rfid(self, data): if self.step.type == "barcode_recipe_selection": if data is not None: self.cycle_available_steps["barcode_recipe_selection"].widget.get(data)