Merge remote-tracking branch 'origin/master'

This commit is contained in:
Eduardo 2024-01-23 12:48:13 +01:00
commit 1a258632af
6 changed files with 162 additions and 8615 deletions

22
README.md Normal file
View File

@ -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

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 642 KiB

After

Width:  |  Height:  |  Size: 642 KiB

View File

@ -125,7 +125,7 @@ pid_mode: 0 # 0=FAST 1=MEDIUM 2=SLOW 4 = FIXED 5 = AUTOMATIC 6 = FLOW 7 = LEAK W
pid_level: 1 pid_level: 1
pid_speed: 1 pid_speed: 1
tester_discharge_enable: no tester_discharge_enable: no
pid_pressure_correction: 110 pid_pressure_correction: 100
tempo_pre_riempimento: 0 tempo_pre_riempimento: 0
pressione_pre_riempimento: 1000 pressione_pre_riempimento: 1000

View File

@ -9,10 +9,9 @@ import nfc
from nfc.clf import RemoteTarget from nfc.clf import RemoteTarget
class RFID_PN532(Component): class RFID_PN532(Component):
new_id_signal = pyqtSignal(str) new_id_signal = pyqtSignal(str)
def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True): 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) super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
self.data_to_write = None self.data_to_write = None

View File

@ -24,6 +24,7 @@ parser = argparse.ArgumentParser(prog='ST-TEN', description='Leak test system')
parser.add_argument('-s', '--system-id') 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): def quit_app(signalnum=None, handler=None):
logging.info(f"quitting app. signal: {signalnum!r}, handler: {handler!r}") logging.info(f"quitting app. signal: {signalnum!r}, handler: {handler!r}")
global app global app
@ -170,10 +171,10 @@ try:
# self.main_window = Main_Window(self.bench) # self.main_window = Main_Window(self.bench)
self.main_window = Main_Window() self.main_window = Main_Window()
# CONNECT MAIN WINDOW ACTIONS # 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( self.main_window.archive_a.triggered.connect(
lambda checked, self=weakref.ref(self): self().main_window.open_dialog( lambda checked, selfie=weakref.ref(self): selfie().main_window.open_dialog(
Archive(hide_cloud_image="vision_saver" not in self().components))) Archive(hide_cloud_image="vision_saver" not in selfie().components)))
if "--archive" in sys.argv: if "--archive" in sys.argv:
self.main_window.archive_a.trigger() self.main_window.archive_a.trigger()
if "--about" in sys.argv: if "--about" in sys.argv:
@ -182,9 +183,11 @@ try:
# 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.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.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.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.barcode_selection_a.triggered.connect(self.set_recipe_mode_barcode)
self.main_window.ristampa_etichetta_a.triggered.connect(self.reprint_label) self.main_window.ristampa_etichetta_a.triggered.connect(self.reprint_label)
@ -201,7 +204,8 @@ try:
self.main_window.save_tecna_recipes_a.trigger() self.main_window.save_tecna_recipes_a.trigger()
else: else:
self.main_window.save_tecna_recipes_a.setVisible(False) 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 # OPEN LOGIN TAB
self.open_login() self.open_login()
@ -236,7 +240,8 @@ try:
def logout(self): def logout(self):
# Users.logout() # Users.logout()
self.main_window.admin_m.menuAction().setVisible(False) 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 # LOGOUT IMMEDIATELY IF NOT TESTING
Users.logout() Users.logout()
self.open_login() self.open_login()
@ -254,8 +259,11 @@ try:
def set_recipe_mode_barcode(self): def set_recipe_mode_barcode(self):
self.main_window.centralWidget().set_recipe_mode_barcode() self.main_window.centralWidget().set_recipe_mode_barcode()
def reprint_label(self): def reprint_label(self):
self.main_window.centralWidget().reprint_label() self.main_window.centralWidget().reprint_label()
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication(sys.argv) app = QApplication(sys.argv)

View File

@ -5,32 +5,33 @@ import sys
import weakref import weakref
from datetime import datetime, timedelta 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.db import Archive, Steps, Users
from lib.helpers import get_shift from lib.helpers import get_shift
from playhouse.shortcuts import model_to_dict from playhouse.shortcuts import model_to_dict
from PyQt5.QtCore import QTimer, pyqtSlot from ui.barcode_recipe_selection import Barcode_Recipe_Selection
from PyQt5.QtWidgets import QMessageBox
from ui.helpers import replace_widget from ui.helpers import replace_widget
from ui.recipe_selection import Recipe_Selection 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_assembly import Test_Assembly
from ui.test_barcodes import Test_Barcodes from ui.test_barcodes import Test_Barcodes
from ui.test_connector import Test_Connector from ui.test_connector import Test_Connector
from ui.test_count import Test_Count from ui.test_count import Test_Count
from ui.test_count_end import Test_Count_End 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_fail import Test_Fail
from ui.test_instructions import Test_Instructions
from ui.test_leak import Test_Leak from ui.test_leak import Test_Leak
from ui.test_resistance import Test_Resistance from ui.test_resistance import Test_Resistance
from ui.test_screws import Test_Screws from ui.test_screws import Test_Screws
from ui.test_vision import Test_Vision from ui.test_vision import Test_Vision
from ui.test_warning_img import Test_Warning_Img
from ui.widget import Widget from ui.widget import Widget
class Test(Widget): class Test(Widget):
def __init__(self, config, components=None, main_window=None): def __init__(self, config, components=None, main_window=None):
super().__init__() super().__init__()
self.autotest_timer = None
self.main_window = main_window self.main_window = main_window
self.config = config self.config = config
self.components = components self.components = components
@ -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), # "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()), "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)), "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)), "count": Test_Assembly(img_path=None, text=u"INSERIRE IL NUMERO DI PEZZI ATTESI PER IL LOTTO",
"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)), widget=Test_Count(components=self.components, recipe=self.recipe, step=self.step, pieces=self.pieces, 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)), "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), "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)), "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)), "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_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_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)), "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)), "instruction": Test_Assembly(img_path=None, text=u"ESEGUIRE LE OPERAZIONI DI MONTAGGIO INDICATE IN FIGURA",
"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)), 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), "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)), "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)), "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)), "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), "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), None: Test_Assembly(img_path=self.select_step_img("warning"), text=u"ATTENZIONE - LA RICETTA SELEZIONATA NON CONTIENE FASI DI TEST", widget=None),
@ -134,10 +143,10 @@ class Test(Widget):
for step_name, w in self.cycle_available_steps.items(): for step_name, w in self.cycle_available_steps.items():
if hasattr(w, "ok"): if hasattr(w, "ok"):
# custom ok handlers should call next again # 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) w.ok.connect(self.set_recipe)
else: 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"): if hasattr(w, "ko"):
w.ko.connect(self.fail_cycle) w.ko.connect(self.fail_cycle)
# CUSTOM STEP CONNECTIONS # CUSTOM STEP CONNECTIONS
@ -193,6 +202,7 @@ class Test(Widget):
def set_recipe_mode_barcode(self): def set_recipe_mode_barcode(self):
self.recipe_selection_mode = "barcode" self.recipe_selection_mode = "barcode"
self.change_recipe() self.change_recipe()
def reprint_label(self): def reprint_label(self):
self.print(self.last_label, self.print_step.spec.get("template", "EtichettaR5")) self.print(self.last_label, self.print_step.spec.get("template", "EtichettaR5"))
@ -217,7 +227,6 @@ class Test(Widget):
if reason == "logout": if reason == "logout":
self.next(action="abort") self.next(action="abort")
def request_periodic_autotest(self): def request_periodic_autotest(self):
self.request_autotest("periodic") self.request_autotest("periodic")
@ -503,9 +512,11 @@ class Test(Widget):
if not self.components[dependency].ready: if not self.components[dependency].ready:
missing_components.add(dependency) missing_components.add(dependency)
if len(unsupported_steps): 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): 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): if len(unsupported_steps) or len(missing_components):
self.change_recipe() self.change_recipe()