Merge remote-tracking branch 'origin/master'
49
config/instruction_images/st-ten-15/DEFAULT.svg
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="1200"
|
||||||
|
height="700"
|
||||||
|
viewBox="0 0 1200 700"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.2 (1:1.2.2+202212051550+b0a8486541)"
|
||||||
|
sodipodi:docname="DEFAULT.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.0570734"
|
||||||
|
inkscape:cx="365.15913"
|
||||||
|
inkscape:cy="357.59106"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1023"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" /><defs
|
||||||
|
id="defs2" /><g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"><text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#ff7f2a;fill-opacity:1;stroke:#aa4400"
|
||||||
|
x="277.31964"
|
||||||
|
y="373.9111"
|
||||||
|
id="text226"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan224"
|
||||||
|
x="277.31964"
|
||||||
|
y="373.9111"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:53.3333px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke:#aa4400;fill:#ff7f2a">DISEGNO NON DISPONIBILE</tspan></text></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
BIN
config/instruction_images/st-ten-15/img/arw-yel-down.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
config/instruction_images/st-ten-15/img/mb1.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
config/instruction_images/st-ten-15/img/mi1.PNG
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
config/instruction_images/st-ten-15/img/mi2.PNG
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
config/instruction_images/st-ten-15/img/ok.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
config/instruction_images/st-ten-15/img/rb1.PNG
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
config/instruction_images/st-ten-15/img/rb2.PNG
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
config/instruction_images/st-ten-15/img/rm1.PNG
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
config/instruction_images/st-ten-15/img/rm2.PNG
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
config/instruction_images/st-ten-15/img/tape_black.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
config/instruction_images/st-ten-15/img/tape_white.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
|
|
@ -56,18 +56,20 @@ status_root:api/device-info-update/
|
||||||
download_root:media/uploads/
|
download_root:media/uploads/
|
||||||
|
|
||||||
images_path: data/images
|
images_path: data/images
|
||||||
poll_time: 60
|
poll_time: 10
|
||||||
hold_time: 30
|
hold_time: 10
|
||||||
service_account_json: config/machine_settings/gcloud_default.json
|
service_account_json: config/machine_settings/gcloud_default.json
|
||||||
bucket_id: st_ten_img
|
bucket_id: st_ten_img
|
||||||
|
|
||||||
[archive_synchronizer_extra]
|
[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
|
images_path: data/images
|
||||||
poll_time: 60
|
poll_time: 10
|
||||||
hold_time: 30
|
hold_time: 10
|
||||||
service_account_json: config/machine_settings/gcloud_default.json
|
|
||||||
bucket_id: st_ten_img
|
|
||||||
|
|
||||||
[label_printer]
|
[label_printer]
|
||||||
platform: windows
|
platform: windows
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ image_for_warning= st-ten-1
|
||||||
|
|
||||||
[hardware_config]
|
[hardware_config]
|
||||||
archive_synchronizer: present
|
archive_synchronizer: present
|
||||||
|
archive_synchronizer_extra: present
|
||||||
galaxy_camera: absent
|
galaxy_camera: absent
|
||||||
uvc_camera: absent
|
uvc_camera: absent
|
||||||
label_printer: present
|
label_printer: present
|
||||||
|
|
@ -18,6 +19,12 @@ screwdriver: absent
|
||||||
digital_io: present
|
digital_io: present
|
||||||
external_flush_blow: absent
|
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]
|
[tecna_t3]
|
||||||
port: COM4
|
port: COM4
|
||||||
model: t3l
|
model: t3l
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ image_for_warning= st-ten-14
|
||||||
|
|
||||||
[hardware_config]
|
[hardware_config]
|
||||||
archive_synchronizer: present
|
archive_synchronizer: present
|
||||||
|
archive_synchronizer_extra: present
|
||||||
uvc_camera: absent
|
uvc_camera: absent
|
||||||
label_printer: present
|
label_printer: present
|
||||||
neo_pixels: absent
|
neo_pixels: absent
|
||||||
|
|
@ -19,13 +20,19 @@ fixture_id: absent
|
||||||
discard_box: absent
|
discard_box: absent
|
||||||
enforce_piece_removal: no
|
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]
|
[tecna_t3]
|
||||||
port: /dev/ttyUSB0
|
port: /dev/ttyUSB0
|
||||||
model: t3l
|
model: t3l
|
||||||
|
|
||||||
[label_printer]
|
[label_printer]
|
||||||
platform: linux
|
platform: linux
|
||||||
printer: ZTC-ZD421-203dpi-ZPL
|
printer: Zebra_Technologies_ZTC_ZD421-203dpi_ZPL
|
||||||
|
|
||||||
[digital_io]
|
[digital_io]
|
||||||
# OUTPUT MAP FOR FIXTURE CONNECTOR
|
# OUTPUT MAP FOR FIXTURE CONNECTOR
|
||||||
|
|
|
||||||
98
config/machine_settings/st-ten-15.ini
Normal file
|
|
@ -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
|
||||||
|
|
@ -2,8 +2,10 @@
|
||||||
description = ST-TEN-4 - REPARTO PREFORMATURA - MAPPANO
|
description = ST-TEN-4 - REPARTO PREFORMATURA - MAPPANO
|
||||||
instruction_folder = st-ten-4
|
instruction_folder = st-ten-4
|
||||||
image_for_warning= st-ten-4
|
image_for_warning= st-ten-4
|
||||||
|
|
||||||
[hardware_config]
|
[hardware_config]
|
||||||
archive_synchronizer: present
|
archive_synchronizer: present
|
||||||
|
archive_synchronizer_extra: present
|
||||||
uvc_camera: absent
|
uvc_camera: absent
|
||||||
label_printer: present
|
label_printer: present
|
||||||
neo_pixels: absent
|
neo_pixels: absent
|
||||||
|
|
@ -13,6 +15,12 @@ vision_saver: absent
|
||||||
vision: absent
|
vision: absent
|
||||||
screwdriver: 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]
|
[tecna_t3]
|
||||||
port: COM4
|
port: COM4
|
||||||
model: t3p
|
model: t3p
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ screwdriver: absent
|
||||||
#digital_io: present
|
#digital_io: present
|
||||||
digital_io_flush_blow: present
|
digital_io_flush_blow: present
|
||||||
second_leak_test: 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
|
external_flush_blow: present # EXTERNAL BOX CONTROLLING MULTI-CHANNEL TEST (IF PRESENT), BLOW-CLEANING AND EXTERNAL FLUSH
|
||||||
dual_channel: present
|
dual_channel: present
|
||||||
#fixture_id: present
|
#fixture_id: present
|
||||||
|
|
|
||||||
BIN
config/warning_images/st-ten-10/Img-G-8606466.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
config/warning_images/st-ten-10/Img-G-8606706.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
config/warning_images/st-ten-10/Img-G-8606707.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
config/warning_images/st-ten-10/Img-G-8612523.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
config/warning_images/st-ten-10/Img-G-8615927.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
config/warning_images/st-ten-10/Img-G-8615928.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
config/warning_images/st-ten-10/Img-G-8626311.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
config/warning_images/st-ten-10/Img-G-8626312.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55680.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55681.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55682.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55683.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55794.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55795.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55796.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55865.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55866.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55916.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R55918.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56061.png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56063.png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56215.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56217.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56219.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56401.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56583.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56585.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56632.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56636.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56638.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56738.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R56739.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R57023.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R57025.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
config/warning_images/st-ten-10/Img-G-R57027.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
|
|
@ -4,6 +4,7 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
@ -12,13 +13,14 @@ import requests
|
||||||
from google.api_core.exceptions import Forbidden
|
from google.api_core.exceptions import Forbidden
|
||||||
from google.cloud import storage
|
from google.cloud import storage
|
||||||
from requests import JSONDecodeError
|
from requests import JSONDecodeError
|
||||||
|
|
||||||
from lib.db import Archive, db
|
from lib.db import Archive, db
|
||||||
|
from lib.db.models import Log
|
||||||
from PyQt5.QtCore import QThread
|
from PyQt5.QtCore import QThread
|
||||||
from requests.adapters import HTTPAdapter, Retry
|
from requests.adapters import HTTPAdapter, Retry
|
||||||
from urllib3.exceptions import InsecureRequestWarning
|
from urllib3.exceptions import InsecureRequestWarning
|
||||||
|
|
||||||
from .component import Component
|
from .component import Component
|
||||||
|
from ui.helpers import get_main_window
|
||||||
# Suppress insecure request warning
|
# Suppress insecure request warning
|
||||||
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
|
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
|
||||||
|
|
||||||
|
|
@ -26,6 +28,7 @@ requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
|
||||||
class ArchiveSynchronizer(Component):
|
class ArchiveSynchronizer(Component):
|
||||||
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.main_window = None
|
||||||
self.simulate = "--sim-archiver" in sys.argv
|
self.simulate = "--sim-archiver" in sys.argv
|
||||||
self.machine_status = "logged-in"
|
self.machine_status = "logged-in"
|
||||||
self.machine_id = None
|
self.machine_id = None
|
||||||
|
|
@ -43,23 +46,50 @@ class ArchiveSynchronizer(Component):
|
||||||
|
|
||||||
self._do_set_period({"period": float(self.config[self.name]["poll_time"])})
|
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.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"])
|
if self.name == "archive_synchronizer":
|
||||||
self.gcs_client._http.mount("", HTTPAdapter(max_retries=Retry(total=0))) # this seems to be useless
|
self.gcs_client = storage.Client.from_service_account_json(self.config[self.name]["service_account_json"])
|
||||||
self.gcs_client._http.adapters.move_to_end("", last=False) # this seems to be useless
|
self.gcs_client._http.mount("", HTTPAdapter(max_retries=Retry(total=0))) # this seems to be useless
|
||||||
self.bucket_id = self.config[self.name]["bucket_id"]
|
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
|
self.gcs_bucket = None
|
||||||
|
|
||||||
@db.connection_context()
|
@db.connection_context()
|
||||||
def _get(self):
|
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 not self.simulate:
|
||||||
if record.archived is not True:
|
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:
|
if record.uploaded is not True:
|
||||||
record.uploaded = self.remote_store(record) is True
|
record.uploaded = self.remote_store(record) is True
|
||||||
else:
|
else:
|
||||||
self.log.info("simulated archive synchronizer cycle")
|
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:
|
if self.hold_time > 0:
|
||||||
QThread.msleep(self.hold_time)
|
QThread.msleep(self.hold_time)
|
||||||
self.gcs_bucket = None
|
self.gcs_bucket = None
|
||||||
|
|
@ -68,7 +98,9 @@ class ArchiveSynchronizer(Component):
|
||||||
self.machine_status="working"
|
self.machine_status="working"
|
||||||
|
|
||||||
super()._get()
|
super()._get()
|
||||||
self.update_machine_status()
|
|
||||||
|
if self.name == "archive_synchronizer":
|
||||||
|
self.update_machine_status()
|
||||||
|
|
||||||
def update_machine_status(self):
|
def update_machine_status(self):
|
||||||
status_call = f"{self.status_endpoint}?machine-id={self.machine_id.upper()}&status={self.machine_status}"
|
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:
|
if not self.simulate:
|
||||||
with requests.Session() as s:
|
with requests.Session() as s:
|
||||||
s.mount("", HTTPAdapter(max_retries=Retry(total=0))) # this disables retries
|
s.mount("", HTTPAdapter(max_retries=Retry(total=0))) # this disables retries
|
||||||
r = requests.post(self.archive_endpoint, params={
|
if self.name == "archive_synchronizer":
|
||||||
"data": json.dumps(record.test_data),
|
r = requests.post(self.archive_endpoint, params={
|
||||||
"machine_id": self.machine_id,
|
"data": json.dumps(record.test_data),
|
||||||
"overridden": record.overridden,
|
"machine_id": self.machine_id,
|
||||||
"recipe": record.test_data.get("recipe", {}).get("name", None),
|
"overridden": record.overridden,
|
||||||
"result": "OK" if record.result else "KO",
|
"recipe": record.test_data.get("recipe", {}).get("name", None),
|
||||||
"serial": record.id,
|
"result": "OK" if record.result else "KO",
|
||||||
"time": record.time.isoformat(),
|
"serial": record.id,
|
||||||
"user": record.user.username,
|
"time": record.time.isoformat(),
|
||||||
}, timeout=5, verify=False)
|
"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:
|
if r.status_code != 200:
|
||||||
raise AssertionError("bad status response")
|
raise AssertionError("bad status response")
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
|
|
@ -150,6 +194,8 @@ class ArchiveSynchronizer(Component):
|
||||||
except (requests.ConnectionError, requests.Timeout) as e:
|
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)}")
|
self.log.warning(f"id: {record.id}: failed to archive remotely, archive_endpoint might be unreachable: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
self.log.info(f"Archived successfully: {record.id}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def remote_store(self, record):
|
def remote_store(self, record):
|
||||||
|
|
@ -182,16 +228,16 @@ class ArchiveSynchronizer(Component):
|
||||||
return False
|
return False
|
||||||
except Exception:
|
except Exception:
|
||||||
self.log.error(f"id: {record.id}: failed to store remotely:\n{traceback.format_exc()}")
|
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
|
return True
|
||||||
|
|
||||||
def remote_fetch(self, remote_path=None, local_path=None):
|
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 remote_path: Path of where to download the file from
|
||||||
:param local_path: path of where to save the file to
|
:param local_path: Path of where to save the file to
|
||||||
:return: a dictionary with errors if any occur.
|
:return: A dictionary with errors if any occur.
|
||||||
"""
|
"""
|
||||||
if remote_path is None:
|
if remote_path is None:
|
||||||
raise ValueError("remote_path cannot be None")
|
raise ValueError("remote_path cannot be None")
|
||||||
|
|
@ -199,48 +245,68 @@ class ArchiveSynchronizer(Component):
|
||||||
raise ValueError("local_path cannot be None")
|
raise ValueError("local_path cannot be None")
|
||||||
|
|
||||||
call_url = f"https://dev.r5portal.it/{remote_path}"
|
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:
|
try:
|
||||||
if not self.simulate:
|
if not self.simulate:
|
||||||
with requests.Session() as s:
|
with requests.Session() as s:
|
||||||
self.log.info(f"Fetching file from: {call_url}")
|
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)
|
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"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:
|
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"}
|
return {"error": "File not found"}
|
||||||
elif response.status_code == 403 or response.status_code == 401:
|
elif response.status_code in [403, 401]:
|
||||||
self.log.warning(f"Access forbidden or not logged in for file: {call_url}")
|
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"}
|
return {"error": "Access forbidden or not logged in"}
|
||||||
elif response.status_code != 200:
|
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"}
|
return {"error": "Unexpected HTTP response status"}
|
||||||
|
|
||||||
# Ensure the directory exists
|
|
||||||
os.makedirs(local_path, exist_ok=True)
|
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))
|
local_file_path = os.path.join(local_path, os.path.basename(remote_path))
|
||||||
with open(local_file_path, "wb") as f:
|
with open(local_file_path, "wb") as f:
|
||||||
f.write(response.content)
|
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}
|
return {"downloaded_file": local_file_path}
|
||||||
|
|
||||||
except requests.ConnectionError as e:
|
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"}
|
return {"error": "Connection error"}
|
||||||
except requests.Timeout as e:
|
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"}
|
return {"error": "Timeout error"}
|
||||||
except Exception as e:
|
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"}
|
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())
|
||||||
|
|
|
||||||
|
|
@ -63,3 +63,4 @@ Users.register(username="USER", password="user")
|
||||||
if True:
|
if True:
|
||||||
# crud_db must be imported after db and models_reference are available
|
# crud_db must be imported after db and models_reference are available
|
||||||
from .crud_db import Crud_DB
|
from .crud_db import Crud_DB
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from peewee import (AutoField, BooleanField, DateTimeField, ForeignKeyField,
|
from peewee import (AutoField, BooleanField, DateTimeField, ForeignKeyField,
|
||||||
TextField)
|
TextField, IntegerField)
|
||||||
from playhouse.sqlite_ext import JSONField
|
from playhouse.sqlite_ext import JSONField
|
||||||
|
|
||||||
from .base_model import BaseModel, db
|
from .base_model import BaseModel, db
|
||||||
|
|
@ -16,7 +16,7 @@ class Archive(BaseModel):
|
||||||
overridden = BooleanField(null=False)
|
overridden = BooleanField(null=False)
|
||||||
test_data = JSONField(null=False)
|
test_data = JSONField(null=False)
|
||||||
label = TextField(null=True)
|
label = TextField(null=True)
|
||||||
archived = BooleanField(null=False, default=False)
|
archived = IntegerField(null=False, default=False)
|
||||||
uploaded = BooleanField(null=False, default=False)
|
uploaded = BooleanField(null=False, default=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from peewee import AutoField, DateTimeField, TextField
|
||||||
|
|
||||||
from .base_model import BaseModel, db
|
from .base_model import BaseModel, db
|
||||||
|
|
||||||
log = logging.getLogger("db_log")
|
db_logger = logging.getLogger("db_log")
|
||||||
|
|
||||||
|
|
||||||
class Log(BaseModel):
|
class Log(BaseModel):
|
||||||
|
|
@ -18,7 +18,7 @@ class Log(BaseModel):
|
||||||
@db.atomic()
|
@db.atomic()
|
||||||
def log(cls, info_type, info=None):
|
def log(cls, info_type, info=None):
|
||||||
cls.create(info_type=info_type, info=info)
|
cls.create(info_type=info_type, info=info)
|
||||||
log.info(f"{info_type}: {info}")
|
db_logger.info(f"{info_type}: {info}")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
table_name = "log"
|
table_name = "log"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from ui.diagnostics import Diagnostics
|
from ui.diagnostics import Diagnostics
|
||||||
from lib.helpers.single_process import SingleProcess
|
from lib.helpers.single_process import SingleProcess
|
||||||
|
from ui.logs_management.info import Logs_Management
|
||||||
|
|
||||||
if platform.system().lower() == "windows":
|
if platform.system().lower() == "windows":
|
||||||
sys.path.append(f"{os.getcwd()}\src\components")
|
sys.path.append(f"{os.getcwd()}\src\components")
|
||||||
|
|
@ -71,7 +72,7 @@ try:
|
||||||
from lib.helpers import ConfigReader
|
from lib.helpers import ConfigReader
|
||||||
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import QApplication, QMessageBox
|
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
|
Barcode_Recipe_Selection
|
||||||
|
|
||||||
if "--vision" in sys.argv:
|
if "--vision" in sys.argv:
|
||||||
|
|
@ -100,6 +101,7 @@ try:
|
||||||
# INIT COMPONENT
|
# INIT COMPONENT
|
||||||
self.components_specs = {
|
self.components_specs = {
|
||||||
"archive_synchronizer": {"c": ArchiveSynchronizer},
|
"archive_synchronizer": {"c": ArchiveSynchronizer},
|
||||||
|
"archive_synchronizer_extra": {"c": ArchiveSynchronizer},
|
||||||
"label_printer": {"c": Os_Label_Printer, "t": False},
|
"label_printer": {"c": Os_Label_Printer, "t": False},
|
||||||
"extra_label_printer": {"c": Os_Label_Printer, "t": False},
|
"extra_label_printer": {"c": Os_Label_Printer, "t": False},
|
||||||
"label_printer_2": {"c": BrotherLabelPrinter, "t": False},
|
"label_printer_2": {"c": BrotherLabelPrinter, "t": False},
|
||||||
|
|
@ -173,7 +175,6 @@ try:
|
||||||
|
|
||||||
# GUI INIT
|
# GUI INIT
|
||||||
if "--no-gui" not in sys.argv:
|
if "--no-gui" not in sys.argv:
|
||||||
# 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, selfie=weakref.ref(self): selfie().logout())
|
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(
|
self.main_window.about_a.triggered.connect(
|
||||||
lambda checked, selfie=weakref.ref(self): selfie().main_window.open_dialog(About()))
|
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.quit_a.triggered.connect(quit_app)
|
||||||
self.main_window.users_management_a.triggered.connect(
|
self.main_window.users_management_a.triggered.connect(
|
||||||
lambda checked, selfie=weakref.ref(self): selfie().main_window.open_dialog(Users_Management()))
|
lambda checked, selfie=weakref.ref(self): selfie().main_window.open_dialog(Users_Management()))
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from .widget import Widget
|
||||||
from .window import Window
|
from .window import Window
|
||||||
from .dialog import Dialog
|
from .dialog import Dialog
|
||||||
from .about import About
|
from .about import About
|
||||||
|
from .logs_management import Logs_Management
|
||||||
from .archive import Archive
|
from .archive import Archive
|
||||||
from .barcodes_step_editor import Barcodes_Step_Editor
|
from .barcodes_step_editor import Barcodes_Step_Editor
|
||||||
from .barcode_recipe_selection import Barcode_Recipe_Selection
|
from .barcode_recipe_selection import Barcode_Recipe_Selection
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ class Barcode_Recipe_Selection(Test_Test):
|
||||||
else:
|
else:
|
||||||
lines = data.splitlines()
|
lines = data.splitlines()
|
||||||
#lines = data.split("-")
|
#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:
|
if len(candidates)>0:
|
||||||
# RECIPE CODE FOUND
|
# RECIPE CODE FOUND
|
||||||
self.recipe=candidates[-1]
|
self.recipe=candidates[-1]
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
from .calc_foreground_color import calc_foreground_color
|
from .calc_foreground_color import calc_foreground_color
|
||||||
|
from .get_main_window import get_main_window
|
||||||
from .replace_widget import replace_widget
|
from .replace_widget import replace_widget
|
||||||
|
|
|
||||||
8
src/ui/helpers/get_main_window.py
Executable file
|
|
@ -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
|
||||||
1
src/ui/logs_management/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
from .info import Logs_Management
|
||||||
73
src/ui/logs_management/info.py
Normal file
|
|
@ -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
|
||||||
23
src/ui/logs_management/logs_management.ui
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Users_Management</class>
|
||||||
|
<widget class="QWidget" name="Users_Management">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::WindowModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>94</width>
|
||||||
|
<height>18</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Logs Management</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout"/>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
|
|
@ -5,10 +5,16 @@ from ui.window import Window
|
||||||
|
|
||||||
class Main_Window(Window):
|
class Main_Window(Window):
|
||||||
do = pyqtSignal(dict)
|
do = pyqtSignal(dict)
|
||||||
|
run_request = pyqtSignal(object, list, dict)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def run_request_handler(fn, a, ka):
|
||||||
|
fn(*a, **ka)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.do.connect(self._do)
|
self.do.connect(self._do)
|
||||||
|
self.run_request.connect(self.run_request_handler)
|
||||||
# print("MAIN_WINDOW ", str(int(QThread.currentThreadId())), flush=True)
|
# print("MAIN_WINDOW ", str(int(QThread.currentThreadId())), flush=True)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
<string>Informazioni</string>
|
<string>Informazioni</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="about_a"/>
|
<addaction name="about_a"/>
|
||||||
|
<addaction name="download_a"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="admin_m">
|
<widget class="QMenu" name="admin_m">
|
||||||
<property name="font">
|
<property name="font">
|
||||||
|
|
@ -134,6 +135,11 @@
|
||||||
<string>Diagnostica</string>
|
<string>Diagnostica</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="download_a">
|
||||||
|
<property name="text">
|
||||||
|
<string>Aggiornamento</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,9 @@ class Test(Widget):
|
||||||
elif self.step.step_type == "print":
|
elif self.step.step_type == "print":
|
||||||
compiled_label = self.print(self.archived, self.step.spec.get("template", "EtichettaR5"))
|
compiled_label = self.print(self.archived, self.step.spec.get("template", "EtichettaR5"))
|
||||||
self.archived.label = compiled_label
|
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)
|
self.next_timer.start(500)
|
||||||
elif self.step.step_type == "wait":
|
elif self.step.step_type == "wait":
|
||||||
self.next_timer.start(500)
|
self.next_timer.start(500)
|
||||||
|
|
|
||||||