From e3090216710a34c5442ba97c2cc07ca6fafd0dfa Mon Sep 17 00:00:00 2001 From: matteo porta Date: Wed, 8 Jun 2022 09:11:38 +0200 Subject: [PATCH] ?tecna? --- simulate.sh | 1 + src/components/__init__.py | 2 + src/components/dummies/pymodbus/__init__.py | 1 + .../dummies/pymodbus/modbus_client.py | 29 ++ .../dummies/serial/__init__.py | 0 .../dummies/serial/serial.py | 0 src/components/modbus_component.py | 115 ++++++ src/components/serial_label_printer.py | 2 +- src/components/tecna_marposs_provaset_t3.py | 192 +++++----- .../tecna_marposs_provaset_t3_registers.py | 334 +++++++++--------- src/main.py | 17 +- 11 files changed, 415 insertions(+), 278 deletions(-) create mode 100644 src/components/dummies/pymodbus/__init__.py create mode 100644 src/components/dummies/pymodbus/modbus_client.py rename src/{lib => components}/dummies/serial/__init__.py (100%) rename src/{lib => components}/dummies/serial/serial.py (100%) create mode 100644 src/components/modbus_component.py diff --git a/simulate.sh b/simulate.sh index 63b4487..d83ddf3 100755 --- a/simulate.sh +++ b/simulate.sh @@ -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) # & diff --git a/src/components/__init__.py b/src/components/__init__.py index b0ec1b2..257932d 100644 --- a/src/components/__init__.py +++ b/src/components/__init__.py @@ -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 diff --git a/src/components/dummies/pymodbus/__init__.py b/src/components/dummies/pymodbus/__init__.py new file mode 100644 index 0000000..5775494 --- /dev/null +++ b/src/components/dummies/pymodbus/__init__.py @@ -0,0 +1 @@ +from .modbus_client import * diff --git a/src/components/dummies/pymodbus/modbus_client.py b/src/components/dummies/pymodbus/modbus_client.py new file mode 100644 index 0000000..4b90b9c --- /dev/null +++ b/src/components/dummies/pymodbus/modbus_client.py @@ -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 diff --git a/src/lib/dummies/serial/__init__.py b/src/components/dummies/serial/__init__.py similarity index 100% rename from src/lib/dummies/serial/__init__.py rename to src/components/dummies/serial/__init__.py diff --git a/src/lib/dummies/serial/serial.py b/src/components/dummies/serial/serial.py similarity index 100% rename from src/lib/dummies/serial/serial.py rename to src/components/dummies/serial/serial.py diff --git a/src/components/modbus_component.py b/src/components/modbus_component.py new file mode 100644 index 0000000..d50e4af --- /dev/null +++ b/src/components/modbus_component.py @@ -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() diff --git a/src/components/serial_label_printer.py b/src/components/serial_label_printer.py index db32926..9f2739b 100644 --- a/src/components/serial_label_printer.py +++ b/src/components/serial_label_printer.py @@ -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 diff --git a/src/components/tecna_marposs_provaset_t3.py b/src/components/tecna_marposs_provaset_t3.py index f70b84c..8944a15 100644 --- a/src/components/tecna_marposs_provaset_t3.py +++ b/src/components/tecna_marposs_provaset_t3.py @@ -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", + ]} diff --git a/src/components/tecna_marposs_provaset_t3_registers.py b/src/components/tecna_marposs_provaset_t3_registers.py index dac1e19..c5a85c6 100644 --- a/src/components/tecna_marposs_provaset_t3_registers.py +++ b/src/components/tecna_marposs_provaset_t3_registers.py @@ -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 } diff --git a/src/main.py b/src/main.py index f8c4d7f..6820d0e 100644 --- a/src/main.py +++ b/src/main.py @@ -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])