st-ten-1/src/ui/test_instructions/test_instructions.py

264 lines
9.3 KiB
Python
Raw Normal View History

2023-01-30 15:50:02 +00:00
import os.path
2023-01-12 21:15:29 +00:00
import sys
import weakref
2023-01-30 15:50:02 +00:00
from PyQt5 import QtSvg
2023-01-12 21:15:29 +00:00
from PyQt5.QtCore import Qt
from lib.helpers import timing
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QKeySequence, QPixmap
2023-01-30 15:50:02 +00:00
from PyQt5.QtWidgets import QShortcut, QApplication, QVBoxLayout
2023-01-12 21:15:29 +00:00
from ui.test_test import Test_Test
2023-01-30 15:50:02 +00:00
from lxml import etree
2023-01-12 21:15:29 +00:00
class Test_Instructions(Test_Test):
2024-02-01 13:50:45 +00:00
def __init__(self,config ,components=None, recipe=None, step=None, run_once=False, reset_on_start=False, enable_override=True,bench_name="generic"):
2023-01-12 21:15:29 +00:00
super().__init__(components=components, recipe=recipe, step=step, run_once=run_once, reset_on_start=reset_on_start, enable_override=enable_override)
self.get_connection = None
2023-01-12 21:15:29 +00:00
self.bench_name = bench_name
2024-02-01 13:50:45 +00:00
self.config = config
2023-01-30 15:50:02 +00:00
self.recipe=recipe
self.svgWidget=None
self.svg_root=None
self.flag=False
2023-04-11 15:01:17 +00:00
self.inputs={}
2023-02-01 10:51:57 +00:00
self.svg_widget=QtSvg.QSvgWidget()
self.layout = QVBoxLayout()
self.layout.addWidget(self.svg_widget)
self.svg_w.setLayout(self.layout)
2024-10-09 10:07:41 +00:00
self.svg_path=os.path.join("config","instruction_images",self.config["machine"].get("instruction_folder","generic"),"")
2023-02-01 10:51:57 +00:00
self.timer = QTimer()
self.timer.timeout.connect(self.toggle_icons)
2023-07-27 10:02:37 +00:00
self.expected_input_state=True
2023-02-01 10:51:57 +00:00
2024-03-12 12:48:00 +00:00
if self.config["hardware_config"]["tecna_t3"] == "absent" and self.config["hardware_config"]["furness_controls"] == "absent":
if hasattr(self, "print_b"):
self.print_b.setVisible(True)
self.print_b.setEnabled(True)
self.print_b.clicked.connect(self.print_button)
# Read the keep_true configuration flag (defaults to disabled)
self.keep_true = str(self.config.get("digital_io", {}).get("keep_true", "no")).lower() in ["yes", "true", "1"]
2024-03-12 12:48:00 +00:00
2023-01-12 21:15:29 +00:00
def start(self, recipe=None, step=None, pieces=None):
show = super().start(recipe=recipe, step=step)
2023-04-11 15:01:17 +00:00
2023-01-30 15:50:02 +00:00
self.timer.start(1000)
self.inputs = {}
2023-02-01 10:51:57 +00:00
# setup test loop
if "digital_io" in self.components.keys():
self.get_connection = self.components["digital_io"].out.connect(self.get)
2025-01-28 17:29:00 +00:00
svg_path = f"{self.svg_path}{self.recipe}.svg"
2023-01-12 21:15:29 +00:00
if step is not None:
if step.step_type == "instruction":
svg_path = f"{self.svg_path}{self.recipe}.svg"
2024-12-02 15:26:33 +00:00
if step.step_type == "instruction_extra":
svg_path = f"{self.svg_path}{self.recipe}-extra.svg"
2023-02-01 10:51:57 +00:00
if not os.path.exists(svg_path):
2023-02-19 17:32:16 +00:00
svg_path=f"{self.svg_path}DEFAULT.svg"
2023-02-01 10:51:57 +00:00
self.svg_root = etree.parse(svg_path)
self.svg_str = etree.tostring(self.svg_root)
self.svg_str=etree.tostring(self.svg_root)
2025-03-19 11:38:24 +00:00
self.expected_input_state = True if step.step_type in ("instruction","instruction_extra") else False
2023-04-11 15:01:17 +00:00
self.monitored_ids=self.svg_root.xpath(f'''.//*[starts-with(@id, 'sensor_')]''')
self.warning_ids=self.svg_root.xpath(f'''.//*[starts-with(@id, 'warning_')]''')
2023-04-11 15:01:17 +00:00
self.tape_ids=self.svg_root.xpath(f'''.//*[starts-with(@id, 'tape_')]''')
2023-02-20 16:59:07 +00:00
self.done = False
2023-01-12 21:15:29 +00:00
return show
2024-07-16 11:02:01 +00:00
def toggle_icons(self, step=None):
self.flag = not self.flag
# Handle tape_ids
for elem in self.tape_ids:
if self.flag:
self.show_tape(elem)
else:
self.hide_tape(elem)
for elem in self.warning_ids:
warning_name = elem.attrib['id']
warning_index_part = warning_name.split("_")[1]
try:
warning_index = int(warning_index_part) - 3
except ValueError:
warning_index = warning_index_part
if warning_index not in self.inputs:
self.inputs[warning_index] = False
if self.inputs[warning_index]:
self.show_ok(elem)
self.show_icon(elem)
else:
self.show_warning_ko(elem)
if self.flag:
self.show_icon(elem)
else:
self.hide_icon(elem)
for elem in self.monitored_ids:
sensor_name = elem.attrib['id']
2024-09-18 12:47:54 +00:00
sensor_index_part = sensor_name.split("_")[1]
try:
sensor_index = int(sensor_index_part) - 3
except ValueError:
sensor_index = sensor_index_part
inverse = '_inv' in sensor_name
2024-07-16 11:02:01 +00:00
stat = '_stat' in sensor_name
if sensor_index not in self.inputs:
2024-09-18 12:47:54 +00:00
self.inputs[sensor_index] = False
2024-07-16 11:02:01 +00:00
if stat:
2024-07-18 07:43:42 +00:00
if inverse and not self.inputs[sensor_index]:
2024-07-16 11:08:40 +00:00
self.show_ok(elem)
2024-07-18 07:43:42 +00:00
self.show_icon(elem)
else:
2024-07-16 11:08:40 +00:00
self.show_ok(elem)
2024-07-18 07:43:42 +00:00
self.show_icon(elem)
2024-07-16 11:02:01 +00:00
else:
if inverse:
if not self.inputs[sensor_index]:
2024-09-18 12:47:54 +00:00
self.show_ko(elem)
self.show_icon(elem)
else:
2024-09-18 12:47:54 +00:00
self.show_ok(elem)
2024-07-16 11:02:01 +00:00
if self.flag:
self.show_icon(elem)
else:
self.hide_icon(elem)
else:
2024-07-16 11:02:01 +00:00
if self.inputs[sensor_index]:
self.show_ok(elem)
self.show_icon(elem)
else:
2024-07-16 11:02:01 +00:00
self.show_ko(elem)
if self.flag:
self.show_icon(elem)
else:
self.hide_icon(elem)
2023-01-30 15:50:02 +00:00
self.show_svg()
2024-03-12 12:48:00 +00:00
def print_button(self):
super().get([{
"time": timing(),
"results": {
"ok": True,
},
}], override=False, fail=False, skip_delay=False)
self.set_done()
self.toggle_icons()
2023-02-01 10:51:57 +00:00
def show_ok(self,id):
2023-04-11 15:01:17 +00:00
id.attrib["{http://www.w3.org/1999/xlink}href"]= f"{self.svg_path}img/ok.png"
2023-02-01 10:51:57 +00:00
def show_ko(self,id):
2023-04-11 15:01:17 +00:00
id.attrib["{http://www.w3.org/1999/xlink}href"]= f"{self.svg_path}img/arw-yel-down.png"
2023-02-01 10:51:57 +00:00
2023-01-30 15:50:02 +00:00
def show_icon(self,id):
id.set("display", "inline")
2023-02-01 10:51:57 +00:00
2023-01-30 15:50:02 +00:00
def hide_icon(self,id):
id.set("display", "none")
def show_warning_ko(self,id):
id.attrib["{http://www.w3.org/1999/xlink}href"]= f"{self.svg_path}img/warning.png"
2023-02-19 17:32:16 +00:00
def show_tape(self,id):
2023-04-11 15:01:17 +00:00
id.attrib["{http://www.w3.org/1999/xlink}href"]= f"{self.svg_path}img/tape_black.png"
2023-02-19 17:32:16 +00:00
id.set("display", "inline")
def hide_tape(self,id):
id.set("display", "none")
2023-01-30 15:50:02 +00:00
def show_svg(self):
2023-01-31 14:02:27 +00:00
self.svg_str = etree.tostring(self.svg_root)
2023-01-30 15:50:02 +00:00
self.svg_widget.load(self.svg_str)
QApplication.processEvents()
2023-01-12 21:15:29 +00:00
def get(self, data=None, override=False):
2024-10-09 10:07:41 +00:00
if self.parent_assembly_widget().parent().step.step_type == "select_recipe":
2023-09-23 10:58:55 +00:00
self.stop()
return
2023-01-12 21:15:29 +00:00
if self.done: # avoid proccessing if completed
return
if data is None:
super().get(None, override=override)
return
2023-02-01 10:51:57 +00:00
# check if all sensor are ok
2023-01-12 21:15:29 +00:00
ok = True
if len(data[0]["digital_io"]) == 0:
2023-02-20 15:30:23 +00:00
return
2023-04-11 15:01:17 +00:00
for sensor in self.monitored_ids:
2024-09-18 12:47:54 +00:00
sensor_name = sensor.attrib['id']
sensor_index_part = sensor.attrib['id'].split("_")[1]
try:
sensor_index = int(sensor_index_part) - 3
except ValueError:
sensor_index = sensor_index_part
inverse = 'inv' in sensor_name
byte_idx = int(sensor_index / 8) if isinstance(sensor_index, int) else None
bit_idx = sensor_index % 8 if isinstance(sensor_index, int) else None
2024-09-18 12:47:54 +00:00
current_bitstate = data[0]["digital_io"][byte_idx][bit_idx] if isinstance(sensor_index, int) else None
if 'stat' in sensor_name:
continue
if isinstance(sensor_index, int):
is_expected = (inverse and current_bitstate != self.expected_input_state) or (not inverse and current_bitstate == self.expected_input_state)
if self.keep_true:
# Memorize the True state if the condition is met
if is_expected:
self.inputs[sensor_index] = True
elif sensor_index not in self.inputs:
self.inputs[sensor_index] = False
else:
# Live tracking (Original behavior expectation when keep_true is not enabled)
self.inputs[sensor_index] = is_expected
if not self.inputs.get(sensor_index, False):
2024-09-18 12:47:54 +00:00
ok = False
2023-02-01 10:51:57 +00:00
else:
ok = False
2023-02-01 10:51:57 +00:00
if ok:
2023-09-23 10:58:55 +00:00
self.stop()
2023-02-01 10:51:57 +00:00
super().get([{
"time": timing(),
"results": {
"ok": ok,
},
}], override=override, fail=ok is False, skip_delay=False)
2023-09-23 10:58:55 +00:00
self.set_done()
2023-07-28 09:14:10 +00:00
self.toggle_icons()
2023-01-12 21:15:29 +00:00
def set_done(self):
self.done=True
self.done_ok=True
def stop(self):
#self.done=True
#self.done_ok = True
2023-02-01 10:51:57 +00:00
self.timer.stop()
if self.get_connection is not None:
self.disconnect(self.get_connection)
2023-01-12 21:15:29 +00:00
super().stop()
def reset(self):
super().reset()