diff --git a/config/instruction_images/st-ten-15/DEFAULT.svg b/config/instruction_images/st-ten-15/DEFAULT.svg new file mode 100644 index 0000000..facc0bb --- /dev/null +++ b/config/instruction_images/st-ten-15/DEFAULT.svg @@ -0,0 +1,49 @@ + + + +DISEGNO NON DISPONIBILE diff --git a/config/instruction_images/st-ten-15/img/arw-yel-down.png b/config/instruction_images/st-ten-15/img/arw-yel-down.png new file mode 100644 index 0000000..bb3c668 Binary files /dev/null and b/config/instruction_images/st-ten-15/img/arw-yel-down.png differ diff --git a/config/instruction_images/st-ten-15/img/mb1.png b/config/instruction_images/st-ten-15/img/mb1.png new file mode 100644 index 0000000..731a437 Binary files /dev/null and b/config/instruction_images/st-ten-15/img/mb1.png differ diff --git a/config/instruction_images/st-ten-15/img/mi1.PNG b/config/instruction_images/st-ten-15/img/mi1.PNG new file mode 100644 index 0000000..6b0f9d9 Binary files /dev/null and b/config/instruction_images/st-ten-15/img/mi1.PNG differ diff --git a/config/instruction_images/st-ten-15/img/mi2.PNG b/config/instruction_images/st-ten-15/img/mi2.PNG new file mode 100644 index 0000000..9db21ff Binary files /dev/null and b/config/instruction_images/st-ten-15/img/mi2.PNG differ diff --git a/config/instruction_images/st-ten-15/img/ok.png b/config/instruction_images/st-ten-15/img/ok.png new file mode 100644 index 0000000..d576b7d Binary files /dev/null and b/config/instruction_images/st-ten-15/img/ok.png differ diff --git a/config/instruction_images/st-ten-15/img/rb1.PNG b/config/instruction_images/st-ten-15/img/rb1.PNG new file mode 100644 index 0000000..3050451 Binary files /dev/null and b/config/instruction_images/st-ten-15/img/rb1.PNG differ diff --git a/config/instruction_images/st-ten-15/img/rb2.PNG b/config/instruction_images/st-ten-15/img/rb2.PNG new file mode 100644 index 0000000..4bf5efc Binary files /dev/null and b/config/instruction_images/st-ten-15/img/rb2.PNG differ diff --git a/config/instruction_images/st-ten-15/img/rm1.PNG b/config/instruction_images/st-ten-15/img/rm1.PNG new file mode 100644 index 0000000..33f0eeb Binary files /dev/null and b/config/instruction_images/st-ten-15/img/rm1.PNG differ diff --git a/config/instruction_images/st-ten-15/img/rm2.PNG b/config/instruction_images/st-ten-15/img/rm2.PNG new file mode 100644 index 0000000..ef1496a Binary files /dev/null and b/config/instruction_images/st-ten-15/img/rm2.PNG differ diff --git a/config/instruction_images/st-ten-15/img/tape_black.png b/config/instruction_images/st-ten-15/img/tape_black.png new file mode 100644 index 0000000..0d51c4b Binary files /dev/null and b/config/instruction_images/st-ten-15/img/tape_black.png differ diff --git a/config/instruction_images/st-ten-15/img/tape_white.png b/config/instruction_images/st-ten-15/img/tape_white.png new file mode 100644 index 0000000..d4b64f0 Binary files /dev/null and b/config/instruction_images/st-ten-15/img/tape_white.png differ diff --git a/config/machine_settings/defaults.ini b/config/machine_settings/defaults.ini index 37534a4..fed355b 100644 --- a/config/machine_settings/defaults.ini +++ b/config/machine_settings/defaults.ini @@ -56,18 +56,20 @@ status_root:api/device-info-update/ download_root:media/uploads/ images_path: data/images -poll_time: 60 -hold_time: 30 +poll_time: 10 +hold_time: 10 service_account_json: config/machine_settings/gcloud_default.json bucket_id: st_ten_img [archive_synchronizer_extra] -archive_endpoint: https://r5portal.it/api/st-ten-save/ +portal_address: https://r5portal.it/ +archive_root:api/st-ten-save/ +status_root:api/device-info-update/ +download_root:media/uploads/ +archive_endpoint: http://172.20.3.13/api/st-ten-save/ images_path: data/images -poll_time: 60 -hold_time: 30 -service_account_json: config/machine_settings/gcloud_default.json -bucket_id: st_ten_img +poll_time: 10 +hold_time: 10 [label_printer] platform: windows diff --git a/config/machine_settings/st-ten-1.ini b/config/machine_settings/st-ten-1.ini index 063f5c1..c669810 100644 --- a/config/machine_settings/st-ten-1.ini +++ b/config/machine_settings/st-ten-1.ini @@ -5,6 +5,7 @@ image_for_warning= st-ten-1 [hardware_config] archive_synchronizer: present +archive_synchronizer_extra: present galaxy_camera: absent uvc_camera: absent label_printer: present @@ -18,6 +19,12 @@ screwdriver: absent digital_io: present external_flush_blow: absent +# VERO PROJECT LOCAL SERVER +[archive_synchronizer_extra] +portal_address: http://172.20.3.13:45006/ +poll_time: 10 +hold_time: 10 + [tecna_t3] port: COM4 model: t3l diff --git a/config/machine_settings/st-ten-14.ini b/config/machine_settings/st-ten-14.ini index c30cbc9..84eb5e9 100644 --- a/config/machine_settings/st-ten-14.ini +++ b/config/machine_settings/st-ten-14.ini @@ -5,6 +5,7 @@ image_for_warning= st-ten-14 [hardware_config] archive_synchronizer: present +archive_synchronizer_extra: present uvc_camera: absent label_printer: present neo_pixels: absent @@ -19,13 +20,19 @@ fixture_id: absent discard_box: absent enforce_piece_removal: no +# VERO PROJECT LOCAL SERVER +[archive_synchronizer_extra] +portal_address: http://172.20.3.13:45007/ +poll_time: 10 +hold_time: 10 + [tecna_t3] port: /dev/ttyUSB0 model: t3l [label_printer] platform: linux -printer: ZTC-ZD421-203dpi-ZPL +printer: Zebra_Technologies_ZTC_ZD421-203dpi_ZPL [digital_io] # OUTPUT MAP FOR FIXTURE CONNECTOR diff --git a/config/machine_settings/st-ten-15.ini b/config/machine_settings/st-ten-15.ini new file mode 100644 index 0000000..4ecb424 --- /dev/null +++ b/config/machine_settings/st-ten-15.ini @@ -0,0 +1,98 @@ +[machine] +description = ST-TEN-15 AUTOMATICO +instruction_folder = st-ten-15 +image_for_warning= st-ten-15 + +[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 +barcode_recipe_selection: present +fixture_id: present +discard_box: absent +second_leak_test: present +dual_channel: absent +#enforce_piece_removal: yes + +[tecna_t3] +port: /dev/ttyUSB0 +model: t3p + +[label_printer] +platform: linux +printer: zd421 + +[digital_io] +# OUTPUT MAP FOR FIXTURE CONNECTOR + +id_fixture: USB-5860,BID#0 +discard_idx:12 # BIT NUMBER OF THE I/0 MODULE USED FOR DISCARD SENSING + +[fixture_rfid] +port: dev/ttyUSB1 + +[recipe] +recipe_name_field: codice_ricetta +part_number_field: codice_prodotto +label_template_field: modello_etichetta +description_field: descrizione + +[recipes_defaults] +tester_discharge_enable: yes +dimensione_lotto_abilitata: x +tempo_pre_riempimento: 0 +pressione_pre_riempimento: 1000 +tempo_riempimento: 15 +tempo_assestamento: 15 +tempo_di_test: 10 +n_componenti:1 +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: 0 +pressione_svuotamento: 100 +canale_di_prova: 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: 0 +pressione_svuotamento_2: 100 +canale_di_prova_2: 2 +modello_etichetta: EtichettaR5_Montaggio_1prova.prn +pid_pressure_correction: 105 +istruzione_abilitata_extra: + +[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 \ No newline at end of file diff --git a/config/machine_settings/st-ten-4.ini b/config/machine_settings/st-ten-4.ini index 4b5d7f3..29c8aac 100644 --- a/config/machine_settings/st-ten-4.ini +++ b/config/machine_settings/st-ten-4.ini @@ -2,8 +2,10 @@ description = ST-TEN-4 - REPARTO PREFORMATURA - MAPPANO instruction_folder = st-ten-4 image_for_warning= st-ten-4 + [hardware_config] archive_synchronizer: present +archive_synchronizer_extra: present uvc_camera: absent label_printer: present neo_pixels: absent @@ -13,6 +15,12 @@ vision_saver: absent vision: absent screwdriver: absent +# VERO PROJECT LOCAL SERVER +[archive_synchronizer_extra] +portal_address: http://172.20.3.13:45008/ +poll_time: 10 +hold_time: 10 + [tecna_t3] port: COM4 model: t3p diff --git a/config/machine_settings/st-ten-6.ini b/config/machine_settings/st-ten-6.ini index 4e3807f..b73a0a8 100644 --- a/config/machine_settings/st-ten-6.ini +++ b/config/machine_settings/st-ten-6.ini @@ -16,6 +16,7 @@ screwdriver: absent #digital_io: present digital_io_flush_blow: present second_leak_test: present +barcode_recipe_selection: present external_flush_blow: present # EXTERNAL BOX CONTROLLING MULTI-CHANNEL TEST (IF PRESENT), BLOW-CLEANING AND EXTERNAL FLUSH dual_channel: present #fixture_id: present diff --git a/config/warning_images/st-ten-10/Img-G-8606466.png b/config/warning_images/st-ten-10/Img-G-8606466.png new file mode 100644 index 0000000..a8cd17b Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-8606466.png differ diff --git a/config/warning_images/st-ten-10/Img-G-8606706.png b/config/warning_images/st-ten-10/Img-G-8606706.png new file mode 100644 index 0000000..58060bb Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-8606706.png differ diff --git a/config/warning_images/st-ten-10/Img-G-8606707.png b/config/warning_images/st-ten-10/Img-G-8606707.png new file mode 100644 index 0000000..3ac1e12 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-8606707.png differ diff --git a/config/warning_images/st-ten-10/Img-G-8612523.png b/config/warning_images/st-ten-10/Img-G-8612523.png new file mode 100644 index 0000000..1ec91e5 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-8612523.png differ diff --git a/config/warning_images/st-ten-10/Img-G-8615927.png b/config/warning_images/st-ten-10/Img-G-8615927.png new file mode 100644 index 0000000..927a240 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-8615927.png differ diff --git a/config/warning_images/st-ten-10/Img-G-8615928.png b/config/warning_images/st-ten-10/Img-G-8615928.png new file mode 100644 index 0000000..9ce525d Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-8615928.png differ diff --git a/config/warning_images/st-ten-10/Img-G-8626311.png b/config/warning_images/st-ten-10/Img-G-8626311.png new file mode 100644 index 0000000..d9195fd Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-8626311.png differ diff --git a/config/warning_images/st-ten-10/Img-G-8626312.png b/config/warning_images/st-ten-10/Img-G-8626312.png new file mode 100644 index 0000000..4178684 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-8626312.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55680.png b/config/warning_images/st-ten-10/Img-G-R55680.png new file mode 100644 index 0000000..85777c8 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55680.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55681.png b/config/warning_images/st-ten-10/Img-G-R55681.png new file mode 100644 index 0000000..b54a65b Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55681.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55682.png b/config/warning_images/st-ten-10/Img-G-R55682.png new file mode 100644 index 0000000..558d944 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55682.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55683.png b/config/warning_images/st-ten-10/Img-G-R55683.png new file mode 100644 index 0000000..6279291 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55683.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55794.png b/config/warning_images/st-ten-10/Img-G-R55794.png new file mode 100644 index 0000000..f8cf446 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55794.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55795.png b/config/warning_images/st-ten-10/Img-G-R55795.png new file mode 100644 index 0000000..a7f23a9 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55795.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55796.png b/config/warning_images/st-ten-10/Img-G-R55796.png new file mode 100644 index 0000000..d047284 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55796.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55865.png b/config/warning_images/st-ten-10/Img-G-R55865.png new file mode 100644 index 0000000..0fa0946 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55865.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55866.png b/config/warning_images/st-ten-10/Img-G-R55866.png new file mode 100644 index 0000000..d414b18 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55866.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55916.png b/config/warning_images/st-ten-10/Img-G-R55916.png new file mode 100644 index 0000000..1961198 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55916.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R55918.png b/config/warning_images/st-ten-10/Img-G-R55918.png new file mode 100644 index 0000000..bca5437 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R55918.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56061.png b/config/warning_images/st-ten-10/Img-G-R56061.png new file mode 100644 index 0000000..06f4a45 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56061.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56063.png b/config/warning_images/st-ten-10/Img-G-R56063.png new file mode 100644 index 0000000..0b2698e Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56063.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56215.png b/config/warning_images/st-ten-10/Img-G-R56215.png new file mode 100644 index 0000000..97abd69 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56215.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56217.png b/config/warning_images/st-ten-10/Img-G-R56217.png new file mode 100644 index 0000000..e6a6517 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56217.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56219.png b/config/warning_images/st-ten-10/Img-G-R56219.png new file mode 100644 index 0000000..445fd92 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56219.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56401.png b/config/warning_images/st-ten-10/Img-G-R56401.png new file mode 100644 index 0000000..75219cf Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56401.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56583.png b/config/warning_images/st-ten-10/Img-G-R56583.png new file mode 100644 index 0000000..5d730d9 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56583.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56585.png b/config/warning_images/st-ten-10/Img-G-R56585.png new file mode 100644 index 0000000..db86ee9 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56585.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56632.png b/config/warning_images/st-ten-10/Img-G-R56632.png new file mode 100644 index 0000000..8213586 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56632.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56636.png b/config/warning_images/st-ten-10/Img-G-R56636.png new file mode 100644 index 0000000..d02b7f5 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56636.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56638.png b/config/warning_images/st-ten-10/Img-G-R56638.png new file mode 100644 index 0000000..cce66d0 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56638.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56738.png b/config/warning_images/st-ten-10/Img-G-R56738.png new file mode 100644 index 0000000..caec0b1 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56738.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R56739.png b/config/warning_images/st-ten-10/Img-G-R56739.png new file mode 100644 index 0000000..387bc08 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R56739.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R57023.png b/config/warning_images/st-ten-10/Img-G-R57023.png new file mode 100644 index 0000000..9e4fe87 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R57023.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R57025.png b/config/warning_images/st-ten-10/Img-G-R57025.png new file mode 100644 index 0000000..1f03119 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R57025.png differ diff --git a/config/warning_images/st-ten-10/Img-G-R57027.png b/config/warning_images/st-ten-10/Img-G-R57027.png new file mode 100644 index 0000000..1384c35 Binary files /dev/null and b/config/warning_images/st-ten-10/Img-G-R57027.png differ diff --git a/src/components/archive_synchronizer.py b/src/components/archive_synchronizer.py index 6e22717..40aa790 100644 --- a/src/components/archive_synchronizer.py +++ b/src/components/archive_synchronizer.py @@ -4,6 +4,7 @@ import re import sys import threading import time +from datetime import datetime from pathlib import Path import requests @@ -12,13 +13,14 @@ import requests from google.api_core.exceptions import Forbidden from google.cloud import storage from requests import JSONDecodeError - from lib.db import Archive, db +from lib.db.models import Log from PyQt5.QtCore import QThread from requests.adapters import HTTPAdapter, Retry from urllib3.exceptions import InsecureRequestWarning from .component import Component +from ui.helpers import get_main_window # Suppress insecure request warning requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) @@ -26,6 +28,7 @@ requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) class ArchiveSynchronizer(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.main_window = None self.simulate = "--sim-archiver" in sys.argv self.machine_status = "logged-in" self.machine_id = None @@ -43,23 +46,50 @@ class ArchiveSynchronizer(Component): self._do_set_period({"period": float(self.config[self.name]["poll_time"])}) self.hold_time = round(float(self.config[self.name]["hold_time"]) * 1000) - self.gcs_client = storage.Client.from_service_account_json(self.config[self.name]["service_account_json"]) - self.gcs_client._http.mount("", HTTPAdapter(max_retries=Retry(total=0))) # this seems to be useless - self.gcs_client._http.adapters.move_to_end("", last=False) # this seems to be useless - self.bucket_id = self.config[self.name]["bucket_id"] + if self.name == "archive_synchronizer": + self.gcs_client = storage.Client.from_service_account_json(self.config[self.name]["service_account_json"]) + self.gcs_client._http.mount("", HTTPAdapter(max_retries=Retry(total=0))) # this seems to be useless + self.gcs_client._http.adapters.move_to_end("", last=False) # this seems to be useless + self.bucket_id = self.config[self.name]["bucket_id"] self.gcs_bucket = None @db.connection_context() def _get(self): - for record in list(Archive.select().where((Archive.archived != True) | (Archive.uploaded != True))): # using "is not True" breaks the query.. # list() forces the complete execution of the query unlocking the db unlike __enter__() + if self.main_window is None: + self.main_window = get_main_window() + + if self.name != "archive_synchronizer_extra": + # MAIN SERVER + bit_pos = 0 + unsaved_records = Archive.select().where((Archive.archived == 0) | + (Archive.archived == 2) | + (Archive.uploaded == 0)) + else: + # EXTRA SERVER (VERO PROJECT SPA) + bit_pos = 1 + unsaved_records = Archive.select().where((Archive.archived == 0) | + (Archive.archived == 1)) + for record in unsaved_records: if not self.simulate: if record.archived is not True: - record.archived = self.remote_archive(record) is True + s = time.time() + save_ok = self.remote_archive(record) is True + e = time.time() + else: + save_ok=True if record.uploaded is not True: record.uploaded = self.remote_store(record) is True else: self.log.info("simulated archive synchronizer cycle") - record.save() + save_ok=True + + if save_ok: + record.archived |= (1 << bit_pos) + self.log.info(f"({self.name}) id {record.id}: archived remotely") + else: + self.log.info(f"({self.name}) id {record.id}: failed to archive remotely") + self.main_window.run_request.emit(record.save, [], {}) + if self.hold_time > 0: QThread.msleep(self.hold_time) self.gcs_bucket = None @@ -68,7 +98,9 @@ class ArchiveSynchronizer(Component): self.machine_status="working" super()._get() - self.update_machine_status() + + if self.name == "archive_synchronizer": + self.update_machine_status() def update_machine_status(self): status_call = f"{self.status_endpoint}?machine-id={self.machine_id.upper()}&status={self.machine_status}" @@ -132,16 +164,28 @@ class ArchiveSynchronizer(Component): if not self.simulate: with requests.Session() as s: s.mount("", HTTPAdapter(max_retries=Retry(total=0))) # this disables retries - r = requests.post(self.archive_endpoint, params={ - "data": json.dumps(record.test_data), - "machine_id": self.machine_id, - "overridden": record.overridden, - "recipe": record.test_data.get("recipe", {}).get("name", None), - "result": "OK" if record.result else "KO", - "serial": record.id, - "time": record.time.isoformat(), - "user": record.user.username, - }, timeout=5, verify=False) + if self.name == "archive_synchronizer": + r = requests.post(self.archive_endpoint, params={ + "data": json.dumps(record.test_data), + "machine_id": self.machine_id, + "overridden": record.overridden, + "recipe": record.test_data.get("recipe", {}).get("name", None), + "result": "OK" if record.result else "KO", + "serial": record.id, + "time": record.time.isoformat(), + "user": record.user.username, + }, timeout=5, verify=False) + else: + r = requests.get(self.archive_endpoint, params={ + "machine_id": self.machine_id, + "overridden": record.overridden, + "recipe": record.test_data.get("recipe", {}).get("name", None), + "result": "OK" if record.result else "KO", + "serial": record.id, + "time": record.time.isoformat(), + "user": record.user.username, + }, timeout=5, verify=False) + if r.status_code != 200: raise AssertionError("bad status response") except AssertionError as e: @@ -150,6 +194,8 @@ class ArchiveSynchronizer(Component): except (requests.ConnectionError, requests.Timeout) as e: self.log.warning(f"id: {record.id}: failed to archive remotely, archive_endpoint might be unreachable: {str(e)}") return False + self.log.info(f"Archived successfully: {record.id}") + return True def remote_store(self, record): @@ -182,16 +228,16 @@ class ArchiveSynchronizer(Component): return False except Exception: self.log.error(f"id: {record.id}: failed to store remotely:\n{traceback.format_exc()}") - self.log.info(f"id: {record.id}: stored remotely") + self.log.info(f"Stored successfully: {record.id}") return True def remote_fetch(self, remote_path=None, local_path=None): """ - download a single file from the server. + Download a single file from the server. - :param remote_path: path of where to download the file from - :param local_path: path of where to save the file to - :return: a dictionary with errors if any occur. + :param remote_path: Path of where to download the file from + :param local_path: Path of where to save the file to + :return: A dictionary with errors if any occur. """ if remote_path is None: raise ValueError("remote_path cannot be None") @@ -199,48 +245,68 @@ class ArchiveSynchronizer(Component): raise ValueError("local_path cannot be None") call_url = f"https://dev.r5portal.it/{remote_path}" + log_info_type = "Download" + log_time = datetime.now() + log_info = f"Attempted to download from {call_url}" + try: if not self.simulate: with requests.Session() as s: self.log.info(f"Fetching file from: {call_url}") - # Make the HTTP GET request to fetch the file response = s.get(call_url, timeout=5, verify=False) - # Log response details self.log.info(f"HTTP Status Code: {response.status_code}") - #self.log.info(f"Response Headers: {response.headers}") - #self.log.info(f"Response Content: {response.content}") - # Handle HTTP errors if response.status_code == 404: - self.log.warning(f"File not found: {call_url}. Please check the URL path.") + log_info += " - File not found" + self.log.warning(log_info) + self.log_to_db(log_time, log_info_type, log_info) return {"error": "File not found"} - elif response.status_code == 403 or response.status_code == 401: - self.log.warning(f"Access forbidden or not logged in for file: {call_url}") + elif response.status_code in [403, 401]: + log_info += " - Access forbidden or not logged in" + self.log.warning(log_info) + self.log_to_db(log_time, log_info_type, log_info) return {"error": "Access forbidden or not logged in"} elif response.status_code != 200: - self.log.error(f"Unexpected HTTP response status: {response.status_code} for URL: {call_url}") + log_info += f" - Unexpected HTTP response status: {response.status_code}" + self.log.error(log_info) + self.log_to_db(log_time, log_info_type, log_info) return {"error": "Unexpected HTTP response status"} - # Ensure the directory exists os.makedirs(local_path, exist_ok=True) - # Save the file to the local path local_file_path = os.path.join(local_path, os.path.basename(remote_path)) with open(local_file_path, "wb") as f: f.write(response.content) - self.log.info(f"File downloaded successfully: {local_file_path}") + log_info += f" - File downloaded successfully: {local_file_path}" + self.log.info(log_info) + self.log_to_db(log_time, log_info_type, log_info) return {"downloaded_file": local_file_path} except requests.ConnectionError as e: - self.log.error(f"Connection error occurred while fetching the file: {str(e)}") + log_info += f" - Connection error: {str(e)}" + self.log.error(log_info) + self.log_to_db(log_time, log_info_type, log_info) return {"error": "Connection error"} except requests.Timeout as e: - self.log.error(f"Timeout error occurred while fetching the file: {str(e)}") + log_info += f" - Timeout error: {str(e)}" + self.log.error(log_info) + self.log_to_db(log_time, log_info_type, log_info) return {"error": "Timeout error"} except Exception as e: - self.log.error(f"An unexpected error occurred: {str(e)}") + log_info += f" - Unexpected error: {str(e)}" + self.log.error(log_info) + self.log_to_db(log_time, log_info_type, log_info) return {"error": "Unexpected error"} + def log_to_db(self, log_time, log_info_type, log_info): + """Save log information to the database.""" + try: + # Use the Log class instead of the log instance + new_log_entry = Log(time=log_time, info_type=log_info_type, info=log_info) + new_log_entry.save() # Save the log entry to the database + except Exception as e: + self.log.error(f"Failed to save log to database: {str(e)}") + self.log.error(traceback.format_exc()) diff --git a/src/lib/db/__init__.py b/src/lib/db/__init__.py index bad5971..8e2ccf7 100644 --- a/src/lib/db/__init__.py +++ b/src/lib/db/__init__.py @@ -63,3 +63,4 @@ Users.register(username="USER", password="user") if True: # crud_db must be imported after db and models_reference are available from .crud_db import Crud_DB + diff --git a/src/lib/db/models/archive.py b/src/lib/db/models/archive.py index 1aae510..ce7220b 100644 --- a/src/lib/db/models/archive.py +++ b/src/lib/db/models/archive.py @@ -1,7 +1,7 @@ from datetime import datetime from peewee import (AutoField, BooleanField, DateTimeField, ForeignKeyField, - TextField) + TextField, IntegerField) from playhouse.sqlite_ext import JSONField from .base_model import BaseModel, db @@ -16,7 +16,7 @@ class Archive(BaseModel): overridden = BooleanField(null=False) test_data = JSONField(null=False) label = TextField(null=True) - archived = BooleanField(null=False, default=False) + archived = IntegerField(null=False, default=False) uploaded = BooleanField(null=False, default=False) @classmethod diff --git a/src/lib/db/models/log.py b/src/lib/db/models/log.py index d3d231b..4a187eb 100755 --- a/src/lib/db/models/log.py +++ b/src/lib/db/models/log.py @@ -5,7 +5,7 @@ from peewee import AutoField, DateTimeField, TextField from .base_model import BaseModel, db -log = logging.getLogger("db_log") +db_logger = logging.getLogger("db_log") class Log(BaseModel): @@ -18,7 +18,7 @@ class Log(BaseModel): @db.atomic() def log(cls, info_type, info=None): cls.create(info_type=info_type, info=info) - log.info(f"{info_type}: {info}") + db_logger.info(f"{info_type}: {info}") class Meta: table_name = "log" diff --git a/src/main.py b/src/main.py index 5ae3806..ce1b151 100644 --- a/src/main.py +++ b/src/main.py @@ -12,6 +12,7 @@ from datetime import datetime from pathlib import Path from ui.diagnostics import Diagnostics from lib.helpers.single_process import SingleProcess +from ui.logs_management.info import Logs_Management if platform.system().lower() == "windows": sys.path.append(f"{os.getcwd()}\src\components") @@ -71,7 +72,7 @@ try: from lib.helpers import ConfigReader from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot from PyQt5.QtWidgets import QApplication, QMessageBox - from ui import About, Archive, Login, Main_Window, Test, Users_Management, Recipe_Selection, \ + from ui import About, Archive, Login, Main_Window, Test, Users_Management,Logs_Management ,Recipe_Selection, \ Barcode_Recipe_Selection if "--vision" in sys.argv: @@ -100,6 +101,7 @@ try: # INIT COMPONENT self.components_specs = { "archive_synchronizer": {"c": ArchiveSynchronizer}, + "archive_synchronizer_extra": {"c": ArchiveSynchronizer}, "label_printer": {"c": Os_Label_Printer, "t": False}, "extra_label_printer": {"c": Os_Label_Printer, "t": False}, "label_printer_2": {"c": BrotherLabelPrinter, "t": False}, @@ -173,7 +175,6 @@ try: # GUI INIT if "--no-gui" not in sys.argv: - # 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, selfie=weakref.ref(self): selfie().logout()) @@ -190,6 +191,8 @@ try: self.main_window.about_a.triggered.connect( lambda checked, selfie=weakref.ref(self): selfie().main_window.open_dialog(About())) + self.main_window.download_a.triggered.connect( + lambda checked, selfie=weakref.ref(self): selfie().main_window.open_dialog(Logs_Management())) self.main_window.quit_a.triggered.connect(quit_app) self.main_window.users_management_a.triggered.connect( lambda checked, selfie=weakref.ref(self): selfie().main_window.open_dialog(Users_Management())) diff --git a/src/ui/__init__.py b/src/ui/__init__.py index b4b958b..8388ade 100644 --- a/src/ui/__init__.py +++ b/src/ui/__init__.py @@ -2,6 +2,7 @@ from .widget import Widget from .window import Window from .dialog import Dialog from .about import About +from .logs_management import Logs_Management from .archive import Archive from .barcodes_step_editor import Barcodes_Step_Editor from .barcode_recipe_selection import Barcode_Recipe_Selection diff --git a/src/ui/barcode_recipe_selection/barcode_recipe_selection.py b/src/ui/barcode_recipe_selection/barcode_recipe_selection.py index 7f5d9ca..a1f7061 100644 --- a/src/ui/barcode_recipe_selection/barcode_recipe_selection.py +++ b/src/ui/barcode_recipe_selection/barcode_recipe_selection.py @@ -75,7 +75,7 @@ class Barcode_Recipe_Selection(Test_Test): else: lines = data.splitlines() #lines = data.split("-") - candidates = [i for i in lines if len(i)==10] + candidates = [i for i in lines if len(i) in(10,12)] if len(candidates)>0: # RECIPE CODE FOUND self.recipe=candidates[-1] diff --git a/src/ui/helpers/__init__.py b/src/ui/helpers/__init__.py index 9ef44de..7cb7dbd 100644 --- a/src/ui/helpers/__init__.py +++ b/src/ui/helpers/__init__.py @@ -1,2 +1,3 @@ from .calc_foreground_color import calc_foreground_color +from .get_main_window import get_main_window from .replace_widget import replace_widget diff --git a/src/ui/helpers/get_main_window.py b/src/ui/helpers/get_main_window.py new file mode 100755 index 0000000..fec5fc5 --- /dev/null +++ b/src/ui/helpers/get_main_window.py @@ -0,0 +1,8 @@ +from PyQt5.QtWidgets import QApplication, QMainWindow + + +def get_main_window(): + tws = QApplication.topLevelWidgets() + for w in tws: + if isinstance(w, QMainWindow): + return w diff --git a/src/ui/logs_management/__init__.py b/src/ui/logs_management/__init__.py new file mode 100644 index 0000000..dd4009c --- /dev/null +++ b/src/ui/logs_management/__init__.py @@ -0,0 +1 @@ +from .info import Logs_Management diff --git a/src/ui/logs_management/info.py b/src/ui/logs_management/info.py new file mode 100644 index 0000000..f3b63f5 --- /dev/null +++ b/src/ui/logs_management/info.py @@ -0,0 +1,73 @@ +import traceback + +from lib.db import log # Presumendo che esista un modulo per accedere alla tabella "log" +from PyQt5.QtWidgets import QMessageBox, QTableWidget +from ui.crud import Crud, Line_Edit_Cell_Widget +from ui.widget import Widget + + +class Logs_Management(Widget): + def __init__(self): + super().__init__() + + class Info_Line_Edit_Cell_Widget(Line_Edit_Cell_Widget): + def render(self, data, row_number=None, crud=None): + super().render(data, row_number=row_number, crud=crud) + + def parse(self, action=None, row_number=None, crud=None): + return self.text() + + crud_aliases = { + "time": "Data", + "info_type": "Operazione", + "info": "Info", + } + self.crud = Crud( + "log", + display_name="LOG MANAGEMENT", + readonly=["id"], + select=list(crud_aliases.keys()), + fields_aliases=crud_aliases, + autocomplete={}, + widget_classes={ + "time": Info_Line_Edit_Cell_Widget, + "info_type": Info_Line_Edit_Cell_Widget, + "info": Info_Line_Edit_Cell_Widget, + }, + row_filter=self.row_filter + ) + + self.layout().addWidget(self.crud, 0, 0, -1, -1) + + # Adjust the column widths based on content + self.adjust_column_widths() + + def adjust_column_widths(self): + """Adjust the widths of columns to fit their content.""" + # Ensure that Crud has db_tw which is a QTableWidget + if hasattr(self.crud, 'db_tw') and isinstance(self.crud.db_tw, QTableWidget): + # Optionally, resize all columns to fit their contents initially + self.crud.db_tw.resizeColumnsToContents() + + # Set a specific column width for columns; for example, set 'Info' column + for column in range(self.crud.db_tw.columnCount()): + self.crud.db_tw.setColumnWidth(column, 200) # Set width to 300 pixels + + def row_filter(self, row, row_number, crud): + try: + + + log_entry = log.generate( + id=row["id"], + time=row["time"], + info_type=row["info_type"], + info=row["info"] + ) + except AssertionError as e: + self.log.exception(traceback.format_exc()) + self.crud.set_row_color(row_number, "red") + QMessageBox.critical(None, "Errore Salvataggio DB", f"Errore alla riga {row_number}:\n{str(e)}") + return False, None, True + + row.update(log_entry) + return True, row, False diff --git a/src/ui/logs_management/logs_management.ui b/src/ui/logs_management/logs_management.ui new file mode 100644 index 0000000..90a62c1 --- /dev/null +++ b/src/ui/logs_management/logs_management.ui @@ -0,0 +1,23 @@ + + + Users_Management + + + Qt::WindowModal + + + + 0 + 0 + 94 + 18 + + + + Logs Management + + + + + + diff --git a/src/ui/main_window/main_window.py b/src/ui/main_window/main_window.py index 214edaf..b02ec80 100644 --- a/src/ui/main_window/main_window.py +++ b/src/ui/main_window/main_window.py @@ -5,10 +5,16 @@ from ui.window import Window class Main_Window(Window): do = pyqtSignal(dict) + run_request = pyqtSignal(object, list, dict) + + @staticmethod + def run_request_handler(fn, a, ka): + fn(*a, **ka) def __init__(self): super().__init__() self.do.connect(self._do) + self.run_request.connect(self.run_request_handler) # print("MAIN_WINDOW ", str(int(QThread.currentThreadId())), flush=True) @staticmethod diff --git a/src/ui/main_window/main_window.ui b/src/ui/main_window/main_window.ui index 73a6db4..d67b0ee 100644 --- a/src/ui/main_window/main_window.ui +++ b/src/ui/main_window/main_window.ui @@ -38,6 +38,7 @@ Informazioni + @@ -134,6 +135,11 @@ Diagnostica + + + Aggiornamento + + diff --git a/src/ui/test/test.py b/src/ui/test/test.py index 1107316..005f4c5 100755 --- a/src/ui/test/test.py +++ b/src/ui/test/test.py @@ -368,7 +368,9 @@ class Test(Widget): elif self.step.step_type == "print": compiled_label = self.print(self.archived, self.step.spec.get("template", "EtichettaR5")) self.archived.label = compiled_label - self.archived.save() + self.log.info(f"Label printed. Saving...") + #self.archived.save() + self.main_window.main_window.run_request.emit(self.archived.save, [], {}) self.next_timer.start(500) elif self.step.step_type == "wait": self.next_timer.start(500)