This commit is contained in:
matteo porta 2022-06-08 09:11:38 +02:00
parent 0beb139753
commit e309021671
11 changed files with 415 additions and 278 deletions

View File

@ -15,6 +15,7 @@ export QT_NO_WARNING_OUTPUT=0
python -B -u "./src/main.py" \
--auto-login-admin \
--auto-select \
--sim-modbus \
--sim-os-label-printer \
--style windows \
$* 2> >(sed $'s/.*/\e[31m&\e[m/' >&2) # &

View File

@ -1,6 +1,8 @@
from .archive_synchronizer import ArchiveSynchronizer
from .modbus_component import ModbusComponent
from .os_label_printer import Os_Label_Printer
from .remote_api import RemoteAPI
from .serial_label_printer import Serial_Label_Printer
from .tecna_marposs_provaset_t3 import TecnaMarpossProvasetT3
from .test_component import TestComponent
from .vision_saver import VisionSaver

View File

@ -0,0 +1 @@
from .modbus_client import *

View File

@ -0,0 +1,29 @@
class ModbusClient:
def __init__(self, *args, **kwargs):
print(__name__, "initialized with", args, kwargs, flush=True)
def connect(self):
self._is_socket_open = True
return self._is_socket_open
def read_holding_registers(self, r, count=1, unit=None):
# print(__name__, unit, str(r) + "-" + str(r + count - 1), "read", flush=True)
return Readout([0] * count)
def write_register(self, r, d, unit=None):
print(__name__, unit, d, r, "write", flush=True)
return Readout()
def close(self):
self._is_socket_open = False
def is_socket_open(self):
return self._is_socket_open
class Readout:
def __init__(self, data=None):
self.registers = data
def isError(self):
return False

View File

@ -0,0 +1,115 @@
import sys
import traceback
import serial
from pymodbus.constants import Endian
# from pymodbus.exceptions import ModbusIOException
from pymodbus.payload import BinaryPayloadBuilder, BinaryPayloadDecoder
from PyQt5.QtCore import QMutex
if "--sim-modbus" not in sys.argv:
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
else:
from components.dummies.pymodbus import ModbusClient
from .component import Component
# from pymodbus.client.sync import ModbusSerialClient as ModbusClient
# import serial
# client = ModbusClient(method="rtu", port="COM3", stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, baudrate=115200, timeout=1, strict=False)
# client.connect()
# client.read_holding_registers(1, count=1)
class ModbusComponent(Component):
def __init__(self, config=None, name=None, period=1, lazy=True, paused=False, threaded=True, registers=None):
super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded)
self.registers = registers if registers is not None else {}
self.lock = QMutex()
def config_changed(self):
self.address = self.config[self.name]["address"]
self.baudrate = int(self.config[self.name]["baudrate"])
self.stopbits = getattr(serial, self.config[self.name].get("stopbits", "stopbits_one").upper())
self.parity = getattr(serial, self.config[self.name].get("parity", "parity_none").upper())
self.bytesize = getattr(serial, self.config[self.name].get("bytesize", "eightbits").upper())
self.byteorder = getattr(Endian, self.config[self.name].get("byteorder", "Big").title())
self.wordorder = getattr(Endian, self.config[self.name].get("wordorder", "Big").title())
self.timeout = int(self.config[self.name].get("timeout", 1))
self.lock.lock()
self.client = ModbusClient(
method="rtu",
port=self.address,
stopbits=self.stopbits,
bytesize=self.bytesize,
parity=self.parity,
baudrate=self.baudrate,
timeout=self.timeout,
strict=False
)
if not self.client.connect():
raise ConnectionError("device not reachable (could not connect): {} ({})".format(self.name, self.port))
if not self.client.is_socket_open():
raise ConnectionError("device not reachable (socket not open): {} ({})".format(self.name, self.port))
self.lock.unlock()
def _read(self, register, count=1):
self.lock.lock()
read = self.client.read_holding_registers(register, count=count)
self.lock.unlock()
if read.isError():
self.log.exception(traceback.format_exception(read))
return None
return read
def _write(self, register, value):
self.lock.lock()
wrote = self.client.write_register(register, value)
self.lock.unlock()
if wrote.isError():
self.log.exception(traceback.format_exception(wrote))
return False
return True
def _decode(self, read, data_type, *args, **kwargs):
decoder = BinaryPayloadDecoder.fromRegisters(read.registers, byteorder=self.byteorder, wordorder=self.wordorder)
return getattr(decoder, f"decode_{data_type}")(*args, **kwargs)
def _encode(self, data, data_type, *args, **kwargs):
builder = BinaryPayloadBuilder(byteorder=self.byteorder, wordorder=self.wordorder)
getattr(builder, f"add_{data_type}")(data, *args, **kwargs)
return builder.build()
def read(self, register, *args, **kwargs):
if type(register) is str:
register, s = self.registers[register]
if not len(args):
args = [s["dt"], *s.get("a", [])]
if not len(kwargs):
kwargs = s.get("k", {})
if args[0].startswith("16bit_"):
count = 1
elif args[0].startswith("32bit_"):
count = 2
else:
raise NotImplementedError(f"data_type {args[0]!r} is not supported")
return self._decode(self._read(register, count=count), *args, **kwargs)
def write(self, register, data, *args, **kwargs):
if type(register) is str:
register, s = self.registers[register]
if not len(args):
args = [s["dt"], *s.get("a", [])]
if not len(kwargs):
kwargs = s.get("k", {})
return self._write(register, self._encode(data, *args, **kwargs))
# def _get(self, data):
# # print("MODBUS", str(int(QThread.currentThreadId())), flush=True)
# super()._get(data)
def __del__(self, event=None):
self.lock.lock()
if self.client.is_socket_open():
self.client.close()
self.lock.unlock()

View File

@ -1,7 +1,7 @@
import sys
if "--sim-serial-label-printer" in sys.argv:
import lib.dummies.serial as serial
import components.dummies.serial as serial
else:
import serial

View File

@ -1,22 +1,5 @@
import sys
import traceback
import serial
from lib.helpers import timing
from pymodbus.constants import Endian
from pymodbus.exceptions import ModbusIOException
from PyQt5.QtCore import QMutex, Qt, QThread, QTimer, pyqtSlot
from .atv320_registers import registers
if "--sim-inverter" not in sys.argv:
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
else:
from lib.dummies.pymodbus import ModbusClient
from random import random
from .component import Component
from .modbus_component import ModbusComponent
from .tecna_marposs_provaset_t3_registers import registers
# from pymodbus.client.sync import ModbusSerialClient as ModbusClient
# import serial
@ -25,96 +8,101 @@ from .component import Component
# client.read_holding_registers(1, count=1)
class TecnaMarpossProvasetT3(Component):
class TecnaMarpossProvasetT3(ModbusComponent):
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.lock = QMutex()
super().__init__(config=config, name=name, period=period, lazy=lazy, paused=paused, threaded=threaded, registers=registers)
def config_changed(self):
self.address = self.config["tecna_marposs_provaset_t3"]["address"]
self.baudrate = int(self.config["tecna_marposs_provaset_t3"]["baudrate"])
self.stopbits = getattr(serial, self.config["tecna_marposs_provaset_t3"].get("stopbits", "stopbits_one").upper())
self.parity = getattr(serial, self.config["tecna_marposs_provaset_t3"].get("parity", "parity_none").upper())
self.bytesize = getattr(serial, self.config["tecna_marposs_provaset_t3"].get("bytesize", "eightbits").upper())
self.timeout = int(self.config["tecna_marposs_provaset_t3"].get("timeout", 1))
self.lock.lock()
self.client = ModbusClient(
method="rtu",
port=self.address,
stopbits=self.stopbits,
bytesize=self.bytesize,
parity=self.parity,
baudrate=self.baudrate,
timeout=self.timeout,
strict=False
)
if not self.client.connect():
raise ConnectionError("device not reachable (could not connect): {} ({})".format(self.name, self.port))
if not self.client.is_socket_open():
raise ConnectionError("device not reachable (socket not open): {} ({})".format(self.name, self.port))
self.lock.unlock()
self.registers = registers
self.last_get = {}
self.last_set = {}
self.last_error = 0
super().config_changed()
# self.set_measure_units()
self.units = self.get_measure_units()
def _read(self, register):
_pressure_units = {"mH2O": 0, "mbar": 1, "kPa": 2, "mmHg": 3, "inH2O": 4, "psi": 5, "mmH2O": 6, } # (se fondoscala <=6 bar)
_leak_units = {"mmH2O": 0, "mbar": 1, "Pa": 2, "mmHg": 3, "inH2O": 4, "psi": 5, }
_leak_flow_units = {"cm3/min": 0, "cm3/h": 1, }
_volume_units = {"litri": 0, "cm3": 1, }
_time_units = {"seconds": 0, }
_flow_units = {"liters/min": 0, "liters/h": 1, "m3/h": 2, }
_pressure_units_map = {v: k for k, v in _pressure_units.items()}
_leak_units_map = {v: k for k, v in _leak_units.items()}
_leak_flow_units_map = {v: k for k, v in _leak_flow_units.items()}
_volume_units_map = {v: k for k, v in _volume_units.items()}
_time_units_map = {v: k for k, v in _time_units.items()}
_flow_units_map = {v: k for k, v in _flow_units.items()}
def set_measure_units(self):
return [
self.write("MEASURE UNITS: pressure measure units", self._pressure_units["mbar"]),
self.write("MEASURE UNITS: Leak measure units", self._leak_units["mbar"]),
self.write("MEASURE UNITS: leak flow rate measure units", self._leak_flow_units["cm3/min"]),
self.write("MEASURE UNITS: Volume", self._volume_units["litri"]),
self.write("MEASURE UNITS: Flow rate measure units", self._flow_units["liters/min"]),
]
def get_measure_units(self):
units = {}
for [register, unit_map, unit_names] in [
["Relative pressure variable format - high resolution", self._pressure_units_map, ["pressure_hr", "red", "r", 21, ]], # also by documentation color and register number
["Relative pressure variable format - low resolution", self._pressure_units_map, ["pressure_lr", "purple", "p", 22, ]], # also by documentation color and register number
["Format of the variables related to the measurement of the differential leak pressure", self._leak_units_map, ["leak", "yellow", "y", 23, ]], # also by documentation color and register number
["Format of the variables related to the calculated leak flow", self._leak_flow_units_map, ["leak_flow", "blue", "b", 24, ]], # also by documentation color and register number
["Format of volume variables", self._volume_units_map, ["volume", "green", "g", 25, ]], # also by documentation color and register number
["Format of time variables", self._time_units_map, ["time", "tangerine", "t", 26, ]], # also by documentation color and register number
["Format of variables related to flow measurements", self._flow_units_map, ["flow", "orange", "o", 27, ]], # also by documentation color and register number
]:
v = self.read(register)
unit = [10**(-((v >> 8) & 0xff)), unit_map[v & 0xff]]
for unit_name in unit_names:
units[unit_name] = unit
return units
def _convert_from_format(self, data, format=None):
if format is None:
return data
# units = self.units[format]
# return [data * units[0], units[1]]
return data * self.units[format][0]
def _convert_to_format(self, data, format=None):
if format is None:
return data
return int(data / self.units[format][0])
def read(self, register, *args, format=None, **kwargs):
if type(register) is str:
r = self.registers[register]
else:
r = register
self.lock.lock()
read = self.client.read_holding_registers(r, count=1)
self.lock.unlock()
if read.isError():
self.log.exception(traceback.format_exception(read))
else:
return read.registers[0]
_, s = self.registers[register]
if format is None:
format = s.get("f")
return self._convert_from_format(super().read(register, *args, **kwargs), format=format)
decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big, wordorder=Endian.Big)
def write(self, register, data, *args, format=None, **kwargs):
if type(register) is str:
_, s = self.registers[register]
if format is None:
format = s.get("f")
return super().write(register, self._convert_to_format(data, format=format), *args, **kwargs)
@staticmethod
def tob(r, n=16):
if r is None:
return None
return "{0:0{n}b}".format(r, n=n)
@pyqtSlot()
def _get(self):
# print("ATV320", str(int(QThread.currentThreadId())), flush=True)
# print("TECNA", str(int(QThread.currentThreadId())), flush=True)
# READ INFO
info = {
"motor speed": self._read("RFRD"),
}
self.last_get = info
self.last_get = self.last_set
self.update.emit([{"time": timing(), self.name: self.last_get}])
self._timer.start()
if self.units is None:
self.set_measure_units()
self.units = self.get_measure_units()
info = {r: self.read(r) for r in [
"Instrument status: active phase",
"Test circuit pressure, in real time",
"Measured leak, in real time",
"Regulated pressure, in real time",
"Active alarm flags",
"Running test: type of test",
"Testing in progress: progressive sequence index",
]}
super()._get([info])
def set(self, register, value):
if type(register) is str:
r = self.registers[register]
else:
r = register
builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big)
self.lock.lock()
wrote = self.client.write_register(r, value)
self.lock.unlock()
if wrote.isError():
self.log.exception(traceback.format_exception(wrote))
def run_motor(self, rpm):
self.set(rpm, "LFRD")
self.set("on")
self.set("enable")
def pause_motor(self):
self.set("disable")
self.set("off")
self.set("stop")
def __del__(self, event=None):
self.lock.lock()
if self.client.is_socket_open():
self.client.close()
self.lock.unlock()
def get_test_results(self):
return {r: self.read(r) for r in [
"Running test: measured leak",
"Running test: calculated leak flow rate",
"Running test: calculate RVP%",
"Running test: result",
]}

View File

@ -1,169 +1,169 @@
registers = {
1 U16 Instrument type
2 U32 Test counter: FAILED
4 U32 Test counter: TOTAL TESTS
6 U32 Life counter: FAILED
8 U32 Life counter: TOTAL TESTS
11 S32 Test circuit pressure, in real time
13 S32 Measured leak, in real time
15 S16 Regulated pressure, in real time
16 U16 Active alarm flags
21 U16 Relative pressure variable format - high resolution
22 U16 Format of the variables related to the measurement of the differential leak pressure
23 U16 Relative pressure variable format - low resolution
24 U16 Format of the variables related to the calculated leak flow
25 U16 Format of volume variables
26 U16 Format of time variables
27 U16 Format of variables related to flow measurements
31 U16 Instrument status: table of parameters in use
32 U16 Instrument status: active phase
# 0 = NO TEST EXECUTED: WAITING START NEW TEST
# 10 = TEST IN PROGRESS: CHECK BARCODE CODE (if enabled)
# 20 = TEST IN PROGRESS: WAITING READING BARCODE CODE (if enabled)
# 30 = TEST IN PROGRESS: TEST INITIALIZATION
# 40 = TEST IN PROGRESS: AUTOMATIC CLOSING 1 (CAGE)
# 50 = TEST IN PROGRESS: AUTOMATIC CLOSING 2 (PLUG)
# 60 = TEST IN PROGRESS: ACTIVE TEST PROGRAM INITIALIZATION
# 70 = TEST IN PROGRESS: WAITING ACKNOWLEDGE WITH BI-START COMMAND (if used)
# 80 = TEST IN PROGRESS: WAITING DELAY (PSDEL parameter)
# 90 = TEST IN PROGRESS: WAITING CONSENT SIGNAL (PSIN parameter)
# 100 = TEST IN PROGRESS: PHASE T0 - PRE-FILLING
# 110 = TEST IN PROGRESS: PHASE T1 - FILLING
# 120 = TEST IN PROGRESS: PHASE T2 - ASSESTMENT
# 130 = TEST IN PROGRESS: PHASE T3- SIZE
# 140 = TEST IN PROGRESS: WAITING CONFIRMATION EXAMINED BY OPERATOR (if used)
# 150 = TEST IN PROGRESS: TEST RESULT PRESENT
# 160 = TEST IN PROGRESS: MARKING (only if last table of a sequence or not in sequence mode)
# 170 = TEST IN PROGRESS: PRESSURE DISCHARGE
# 180 = TEST IN PROGRESS: END OF TESTING TABLE - IF IN SEQUENCE MODE THE CYCLE STARTS FROM
# PHASE 60 WITH THE NEXT TABLE OF THE SEQUENCE
# 190 = TEST IN PROGRESS: AUTOMATIC OPENING 2 (BUFFER)
# 200 = TEST IN PROGRESS: AUTOMATIC OPENING 1 (CAGE)
# 210 = TEST TERMINATED: WAITING THE START OF A NEW TEST
33 U16 Running test: active phase backwards time
34 S32 Running test: T1 phase end pressure
36 S32 Running test: T2 phase end pressure
38 S32 Running test: burst pressure
40 S32 Running test: measured leak
42 S32 Running test: calculated leak flow rate
44 S32 Running test: calculate RVP%
46 U16 Running test: result
# 1 = LEAK TEST PASSED
# 2 = BURST TEST PASSED WITH BURST
# 3 = BURST TEST PASSED WITHOUT BURST
# 4 = not used
# 5 = BLOCKAGE TEST PASSED
# 100 = LEAK TEST FAILED - UPPER LIMIT
# 101 = LEAK TEST FAILED ANOMALY
# 102 = LEAK TEST - MAXIMUM LEAK FAILED
# 103 = BURST - BREAKAGE PRESSURE DEFLECTION
# 104 = VOLUMETRIC CONTROL - RVP% FAILED
# 105 = not used
# 106 = not used
# 107 = BLOCKAGE - MAX PRESSURE FAILED
# 108 = BLOCKAGE - MIN PRESSURE FAILED
# 109 = BURST - MINIMUM PRESSURE FAILED
# 200 = LEAK TEST FAILED PR% PRESSURE MINUM
# 201 = LEAK TEST FAILED - PR% PRESSURE MAX
# 202 = LEAK TEST FAILED P0% PRESSURE MINUM
# 203 = LEAK TEST FAILED - P0% PRESSURE MAX
# 204 = ERROR - INTERNAL ALARMS
# 205 = ERROR - RELATIVE PRESSURE OUT OF RANGE
# 206 = ERROR - DIFFERENTIAL PRESSURE OUT OF RANGE
# 207 = ERROR PRE-FILLING VALVE NOT OPENED
# 250 = TEST ABORTED
47 U16 Running test: type of test
# 1 = LEAK TEST
# 2 = BLOCKAGE TEST
# 3 = LEAK TEST WITH VOLUME CHECK
# 4 = BURST TEST
48 U16 Testing in progress: progressive sequence index
49 U16 Testing in progress: graphical sampling rate
50 U16 Testing in progress: number of samples of the graph
601 U16 DISLPAY and SOUND: Language
# 0=ITALIANO
# 1=ENGLISH
602 U16 INSTRUMENT SETTING: Test table from
# 0=PARAMETER
# 1=PLC BASE 1
# 2=PLC BASE 2
606 U16 MEASURE UNITS: pressure measure units
# 0=mH2O 1=mbar 2=kPa 3=mmHg 4=inH2O 5=psi 6=mmH2O (se fondoscala <=6 bar)
607 U16 MEASURE UNITS: Leak measure units
# 0=mmH2O 1=mbar 2=Pa 3=mmHg 4=inH2O 5=psi
608 U16 MEASURE UNITS: leak flow rate measure units
# 0=cm3/min 1=cm3/h
609 U16 MEASURE UNITS: Volume
# 0=litri 1=cm3
617 U16 MEASURE UNITS: Flow rate measure units
# 0=liters/min 1=liters/h 2=m3/h
618 U16 AUTOMATION: Cage - closing time
# Format: x.x seconds
619 U16 AUTOMATION: Cage - opening time
# Format: x.x seconds
620 U16 INSTRUMENT SETTINGS: MAX pressure
621 U16 AUTOMATION: Buffer - closing time
# Format: x.x seconds
622 U16 AUTOMATION: Buffer - opening time
# Format: x.x seconds
623 U16 AUTOMATION: Marking - result
# 0= Only passed
# 1= Only failed
# 2=All
624 U16 AUTOMATION: Marking driving time
# Format: x.x seconds
701 U16 Type of test
# 1=LEAK TEST
# 2=BLOCKAGE TEST
# 3=LEAK TEST WITH VOLUME
# 4=BURST TEST
702 U16 Test flags
# T0/Pr: Phase filling mode T0 0= TIME 1= PRESSURE
# T1/Pr: Phase filling mode T1 0= TIME 1=PRESSURE
# T3/Q: Phase mode T3 0= TIME 1=TERMINATE IMMEDIATELY IF FAILED
# TYPE PID: 0=FAST 1=MEDIUM 2=SLOW 4 = FIXED 5 = AUTOMATIC 6= PULSES (if enabled SWLP option)
# P0-: 0=Positive P0 pressure 1=P0 negative pressure (if enabled V or N option for vacuum tests)
# Pr-: 0=Positive pressure Pr 1=Pr negative pressure (if enabled V or N option for vacuum tests)
# Q+: 0=Q + positive parameter 1=parameter Q + negative
# Q-: 0=Q-positive parameter 1=Q-negative parameter
# AT: 0=Tare pressure disabled 1=Tare pressure enabled
# HR: 0=Resolution on loss 1 Pa 1=Resolution on loss 0.1 Pa (models with full scale <= 2 bar)
# CH: Selected test channel (2-channel T3P2C model only)
704 U16 T0 Pre-filling time
705 U16 P0 Pre-filling pressure
# In order to use a negative (vacuum) value, this parameter must however be written positively, but the P0- bit must
# also be selected in register 702
706 U16 T1 Filling time
707 U16 T2 Settling time
708 U16 T3 Measure time
709 U16 PREL Nominal test pressure
# To set a negative pressure (vacuum) this parameters must be written in absolute value and then set
# bit Pr- in register 702
710 U16 PR%- Lower tolerance on pressure
# LEAK: Format: x.x %
# P- Minimum pressure BLOCKAGE: Format as indicated in register 23
# PR- Minimum pressure% BURST: Format x.x%
711 U16 Q + Upper limit
# Format as indicated in the register 22
712 U16 Q- Leak limit
# Format as indicated in the register 22
713 U16 FST discharge time
# Format as indicated in the register 26
714 U16 VP Equivalent volume
# Format as indicated in the register 25
717 U16 P% Pressure tolerance
# BLOCKAGE: Format x.x %
743 U16 PB Minimum burst pressure
# BURST: Format as indicated in the register 23
744 U16 BD Delta burst
# BURST: Format as indicated in the register 23
745 U16 FSL discharge limit
# Format as indicated in the register 23
747 U16 PR% + Superior tolerance on pressure
# LEAK: Format: x.x %
# P + Pressure max BURST: Format as indicated in the register 23
750 U16 RVP%: volumetric ratio
# VOLUME+LEAK: Format x.xx (from 0.00 to 649.99)
751 U16 RVP%: max tolerance
# VOLUME+LEAK: Format: x.xx
"Instrument type": [1, {"dt": "16bit_uint", }],
"Test counter: FAILED": [2, {"dt": "32bit_uint", }],
"Test counter: TOTAL TESTS": [4, {"dt": "32bit_uint", }],
"Life counter: FAILED": [6, {"dt": "32bit_uint", }],
"Life counter: TOTAL TESTS": [8, {"dt": "32bit_uint", }],
"Test circuit pressure, in real time": [11, {"dt": "32bit_int", "f": 21, }],
"Measured leak, in real time": [13, {"dt": "32bit_int", "f": 22, }],
"Regulated pressure, in real time": [15, {"dt": "16bit_int", "f": 23, }],
"Active alarm flags": [16, {"dt": "16bit_uint", }],
"Relative pressure variable format - high resolution": [21, {"dt": "16bit_uint", }],
"Format of the variables related to the measurement of the differential leak pressure": [22, {"dt": "16bit_uint", }],
"Relative pressure variable format - low resolution": [23, {"dt": "16bit_uint", }],
"Format of the variables related to the calculated leak flow": [24, {"dt": "16bit_uint", }],
"Format of volume variables": [25, {"dt": "16bit_uint", }],
"Format of time variables": [26, {"dt": "16bit_uint", }],
"Format of variables related to flow measurements": [27, {"dt": "16bit_uint", }],
"Instrument status: table of parameters in use": [31, {"dt": "16bit_uint", }],
"Instrument status: active phase": [32, {"dt": "16bit_uint", }],
# 0 = NO TEST EXECUTED: WAITING START NEW TEST
# 10 = TEST IN PROGRESS: CHECK BARCODE CODE (if enabled)
# 20 = TEST IN PROGRESS: WAITING READING BARCODE CODE (if enabled)
# 30 = TEST IN PROGRESS: TEST INITIALIZATION
# 40 = TEST IN PROGRESS: AUTOMATIC CLOSING 1 (CAGE)
# 50 = TEST IN PROGRESS: AUTOMATIC CLOSING 2 (PLUG)
# 60 = TEST IN PROGRESS: ACTIVE TEST PROGRAM INITIALIZATION
# 70 = TEST IN PROGRESS: WAITING ACKNOWLEDGE WITH BI-START COMMAND (if used)
# 80 = TEST IN PROGRESS: WAITING DELAY (PSDEL parameter)
# 90 = TEST IN PROGRESS: WAITING CONSENT SIGNAL (PSIN parameter)
# 100 = TEST IN PROGRESS: PHASE T0 - PRE-FILLING
# 110 = TEST IN PROGRESS: PHASE T1 - FILLING
# 120 = TEST IN PROGRESS: PHASE T2 - ASSESTMENT
# 130 = TEST IN PROGRESS: PHASE T3- SIZE
# 140 = TEST IN PROGRESS: WAITING CONFIRMATION EXAMINED BY OPERATOR (if used)
# 150 = TEST IN PROGRESS: TEST RESULT PRESENT
# 160 = TEST IN PROGRESS: MARKING (only if last table of a sequence or not in sequence mode)
# 170 = TEST IN PROGRESS: PRESSURE DISCHARGE
# 180 = TEST IN PROGRESS: END OF TESTING TABLE - IF IN SEQUENCE MODE THE CYCLE STARTS FROM
# PHASE 60 WITH THE NEXT TABLE OF THE SEQUENCE
# 190 = TEST IN PROGRESS: AUTOMATIC OPENING 2 (BUFFER)
# 200 = TEST IN PROGRESS: AUTOMATIC OPENING 1 (CAGE)
# 210 = TEST TERMINATED: WAITING THE START OF A NEW TEST
"Running test: active phase backwards time": [33, {"dt": "16bit_uint", "f": 26, }],
"Running test: T1 phase end pressure": [34, {"dt": "32bit_int", "f": 21, }],
"Running test: T2 phase end pressure": [36, {"dt": "32bit_int", "f": 21, }],
"Running test: burst pressure": [38, {"dt": "32bit_int", "f": 21, }],
"Running test: measured leak": [40, {"dt": "32bit_int", "f": 22, }],
"Running test: calculated leak flow rate": [42, {"dt": "32bit_int", "f": 24, }],
"Running test: calculate RVP%": [44, {"dt": "32bit_int", }],
"Running test: result": [46, {"dt": "16bit_uint", }],
# 1 = LEAK TEST PASSED
# 2 = BURST TEST PASSED WITH BURST
# 3 = BURST TEST PASSED WITHOUT BURST
# 4 = not used
# 5 = BLOCKAGE TEST PASSED
# 100 = LEAK TEST FAILED - UPPER LIMIT
# 101 = LEAK TEST FAILED ANOMALY
# 102 = LEAK TEST - MAXIMUM LEAK FAILED
# 103 = BURST - BREAKAGE PRESSURE DEFLECTION
# 104 = VOLUMETRIC CONTROL - RVP% FAILED
# 105 = not used
# 106 = not used
# 107 = BLOCKAGE - MAX PRESSURE FAILED
# 108 = BLOCKAGE - MIN PRESSURE FAILED
# 109 = BURST - MINIMUM PRESSURE FAILED
# 200 = LEAK TEST FAILED PR% PRESSURE MINUM
# 201 = LEAK TEST FAILED - PR% PRESSURE MAX
# 202 = LEAK TEST FAILED P0% PRESSURE MINUM
# 203 = LEAK TEST FAILED - P0% PRESSURE MAX
# 204 = ERROR - INTERNAL ALARMS
# 205 = ERROR - RELATIVE PRESSURE OUT OF RANGE
# 206 = ERROR - DIFFERENTIAL PRESSURE OUT OF RANGE
# 207 = ERROR PRE-FILLING VALVE NOT OPENED
# 250 = TEST ABORTED
"Running test: type of test": [47, {"dt": "16bit_uint", }],
# 1 = LEAK TEST
# 2 = BLOCKAGE TEST
# 3 = LEAK TEST WITH VOLUME CHECK
# 4 = BURST TEST
"Testing in progress: progressive sequence index": [48, {"dt": "16bit_uint", }],
"Testing in progress: graphical sampling rate": [49, {"dt": "16bit_uint", }],
"Testing in progress: number of samples of the graph": [50, {"dt": "16bit_uint", }],
"DISLPAY and SOUND: Language": [601, {"dt": "16bit_uint", }],
# 0=ITALIANO
# 1=ENGLISH
"INSTRUMENT SETTING: Test table from": [602, {"dt": "16bit_uint", }],
# 0=PARAMETER
# 1=PLC BASE 1
# 2=PLC BASE 2
"MEASURE UNITS: pressure measure units": [606, {"dt": "16bit_uint", }],
# 0=mH2O 1=mbar 2=kPa 3=mmHg 4=inH2O 5=psi 6=mmH2O (se fondoscala <=6 bar)
"MEASURE UNITS: Leak measure units": [607, {"dt": "16bit_uint", }],
# 0=mmH2O 1=mbar 2=Pa 3=mmHg 4=inH2O 5=psi
"MEASURE UNITS: leak flow rate measure units": [608, {"dt": "16bit_uint", }],
# 0=cm3/min 1=cm3/h
"MEASURE UNITS: Volume": [609, {"dt": "16bit_uint", }],
# 0=litri 1=cm3
"MEASURE UNITS: Flow rate measure units": [617, {"dt": "16bit_uint", }],
# 0=liters/min 1=liters/h 2=m3/h
"AUTOMATION: Cage - closing time": [618, {"dt": "16bit_uint", }],
# Format: x.x seconds
"AUTOMATION: Cage - opening time": [619, {"dt": "16bit_uint", }],
# Format: x.x seconds
"INSTRUMENT SETTINGS: MAX pressure": [620, {"dt": "16bit_uint", }],
"AUTOMATION: Buffer - closing time": [621, {"dt": "16bit_uint", }],
# Format: x.x seconds
"AUTOMATION: Buffer - opening time": [622, {"dt": "16bit_uint", }],
# Format: x.x seconds
"AUTOMATION: Marking - result": [623, {"dt": "16bit_uint", }],
# 0= Only passed
# 1= Only failed
# 2=All
"AUTOMATION: Marking driving time": [624, {"dt": "16bit_uint", }],
# Format: x.x seconds
"Type of test": [701, {"dt": "16bit_uint", }],
# 1=LEAK TEST
# 2=BLOCKAGE TEST
# 3=LEAK TEST WITH VOLUME
# 4=BURST TEST
"Test flags": [702, {"dt": "16bit_uint", }],
# T0/Pr: Phase filling mode T0 0= TIME 1= PRESSURE
# T1/Pr: Phase filling mode T1 0= TIME 1=PRESSURE
# T3/Q: Phase mode T3 0= TIME 1=TERMINATE IMMEDIATELY IF FAILED
# TYPE PID: 0=FAST 1=MEDIUM 2=SLOW 4 = FIXED 5 = AUTOMATIC 6= PULSES (if enabled SWLP option)
# P0-: 0=Positive P0 pressure 1=P0 negative pressure (if enabled V or N option for vacuum tests)
# Pr-: 0=Positive pressure Pr 1=Pr negative pressure (if enabled V or N option for vacuum tests)
# Q+: 0=Q + positive parameter 1=parameter Q + negative
# Q-: 0=Q-positive parameter 1=Q-negative parameter
# AT: 0=Tare pressure disabled 1=Tare pressure enabled
# HR: 0=Resolution on loss 1 Pa 1=Resolution on loss 0.1 Pa (models with full scale <= 2 bar)
# CH: Selected test channel (2-channel T3P2C model only)
"T0 Pre-filling time": [704, {"dt": "16bit_uint", "f": 26, }],
"P0 Pre-filling pressure": [705, {"dt": "16bit_uint", "f": 23, }],
# In order to use a negative (vacuum) value, this parameter must however be written positively, but the P0- bit must
# also be selected in register 702
"T1 Filling time": [706, {"dt": "16bit_uint", "f": 26, }],
"T2 Settling time": [707, {"dt": "16bit_uint", "f": 26, }],
"T3 Measure time": [708, {"dt": "16bit_uint", "f": 26, }],
"PREL Nominal test pressure": [709, {"dt": "16bit_uint", "f": 23, }],
# To set a negative pressure (vacuum) this parameters must be written in absolute value and then set
# bit Pr- in register 702
"Pxx Minimum Pressure": [710, {"dt": "16bit_uint", }],
# PR%- Lower tolerance on pressure: LEAK: Format: x.x %
# P- Minimum pressure: BLOCKAGE: Format as indicated in register 23
# PR- Minimum pressure%: BURST: Format x.x%
"Q + Upper limit": [711, {"dt": "16bit_uint", "f": 22, }],
# Format as indicated in the register 22
"Q- Leak limit": [712, {"dt": "16bit_uint", "f": 22, }],
# Format as indicated in the register 22
"FST discharge time": [713, {"dt": "16bit_uint", "f": 26, }],
# Format as indicated in the register 26
"VP Equivalent volume": [714, {"dt": "16bit_uint", "f": 25, }],
# Format as indicated in the register 25
"P% Pressure tolerance": [717, {"dt": "16bit_uint", }],
# BLOCKAGE: Format x.x %
"PB Minimum burst pressure": [743, {"dt": "16bit_uint", "f": 23, }],
# BURST: Format as indicated in the register 23
"BD Delta burst": [744, {"dt": "16bit_uint", "f": 23, }],
# BURST: Format as indicated in the register 23
"FSL discharge limit": [745, {"dt": "16bit_uint", "f": 23, }],
# Format as indicated in the register 23
"PR% + Superior tolerance on pressure": [747, {"dt": "16bit_uint", }],
# LEAK: Format: x.x %
# P + Pressure max BURST: Format as indicated in the register 23
"RVP%: volumetric ratio": [750, {"dt": "16bit_uint", }],
# VOLUME+LEAK: Format x.xx (from 0.00 to 649.99)
"RVP%: max tolerance": [751, {"dt": "16bit_uint", }],
# VOLUME+LEAK: Format: x.xx
}

View File

@ -49,7 +49,7 @@ logging.basicConfig(
try:
# IMPORT PROJECT ONLY AFTER SETTING UP SIGNAL, FAULTHANDLER AND LOGGHING
from components import (ArchiveSynchronizer, Os_Label_Printer, RemoteAPI,
TestComponent, VisionSaver)
TecnaMarpossProvasetT3, TestComponent, VisionSaver)
from lib.db import Users
from lib.helpers import ConfigReader
from PyQt5.QtCore import QObject, QThread, pyqtSignal
@ -73,17 +73,18 @@ try:
self.config = ConfigReader()
# INIT COMPONENT
self.components_specs = {
"archive_synchronizer": {"c": ArchiveSynchronizer, "a": [], "k": {}, "t": True},
"remote_api": {"c": RemoteAPI, "a": [], "k": {"main": self}, "t": True},
"test_component": {"c": TestComponent, "a": [], "k": {}, "t": True},
"vision_savert": {"c": VisionSaver, "a": [], "k": {}, "t": False},
"label_printer": {"c": Os_Label_Printer, "a": [], "k": {}, "t": False},
"archive_synchronizer": {"c": ArchiveSynchronizer},
"remote_api": {"c": RemoteAPI, "k": {"main": self}},
"test_component": {"c": TestComponent},
"vision_savert": {"c": VisionSaver, "t": False},
"label_printer": {"c": Os_Label_Printer, "t": False},
"tecna_marposs_provaset_t3": {"c": TecnaMarpossProvasetT3},
}
self.components = {}
self.threads = {}
for component_name, spec in self.components_specs.items():
self.components[component_name] = spec["c"](*spec["a"], config=self.config, name=component_name, **spec["k"])
if spec["t"]:
self.components[component_name] = spec["c"](*spec.get("a", []), config=self.config, name=component_name, **spec.get("k", {}))
if spec.get("t", True):
self.threads[component_name] = QThread()
self.threads[component_name].setTerminationEnabled(True)
self.components[component_name].moveToThread(self.threads[component_name])