st-ten-1/src/ui/diagnostics/diagnostics.py
2024-10-24 13:34:14 +02:00

133 lines
5.7 KiB
Python

import sys
from PyQt6 import QtGui, QtCore
from PyQt6.QtCore import Qt, pyqtSlot
from PyQt6.QtWidgets import QTableWidgetItem, QPushButton, QHeaderView, QLabel, QLineEdit
from ui.widget import Widget
class Diagnostics(Widget):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.simulate = "--sim-io" in sys.argv
self.inputs = self.parent.config["digital_inputs"]
self.outputs = self.parent.config["digital_outputs"]
self.color_red = "#f00"
self.color_green = "#0f0"
headers_out = ["OUTPUT", "SET"]
headers_in = ["INPUT", "STATUS"]
r = 0
self.latch = [False for o in range (len(self.outputs))]
self.latch_in = [False for i in range(len(self.inputs))]
# POPULATE OUTPUT TABLE
self.output_tb.setColumnCount(len(headers_out))
self.output_tb.setHorizontalHeaderLabels(headers_out)
self.output_tb.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.output_tb.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.output_tb.setRowCount(len(self.outputs))
self.output_tb.setVerticalHeaderLabels(list(self.outputs))
self.ICON_OK = QtGui.QPixmap("src/ui/icons/ok.png").scaled(30, 30, QtCore.Qt.KeepAspectRatio)
self.ICON_KO = QtGui.QPixmap("src/ui/icons/ko.png").scaled(30, 30, QtCore.Qt.KeepAspectRatio)
self.ICON_OFF = QtGui.QPixmap("src/ui/icons/off.png").scaled(30, 30, QtCore.Qt.KeepAspectRatio)
self.out_buttons=[QPushButton() for o in range(len(self.outputs))]
for output_name,output_idx in self.outputs.items():
for c, header in enumerate(headers_out):
if header == "ACTIVATE":
self.out_buttons[r].setCheckable(True)
self.out_buttons[r].setText("OFF")
self.output_tb.setCellWidget(r, c, self.out_buttons[r])
indexb = QtCore.QPersistentModelIndex(self.output_tb.model().index(r, c))
self.out_buttons[r].clicked.connect(lambda *args, index=indexb: self.plc_bit_toggle(index))
elif header == "OUTPUT":
i = QTableWidgetItem()
i.setText(str(output_idx))
self.output_tb.setItem(r, c, i)
r += 1
# POPULATE INPUT TABLE
self.input_tb.setColumnCount(len(headers_in))
self.input_tb.setHorizontalHeaderLabels(headers_in)
self.input_tb.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.input_tb.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.input_tb.setRowCount(len(self.inputs))
self.input_tb.setVerticalHeaderLabels(list(self.inputs))
r = 0
if self.simulate:
self.in_buttons = [QPushButton() for i in range(len(self.outputs))]
for input_name, input_idx in self.inputs.items():
for c, header in enumerate(headers_in):
if header == "STATUS":
if self.simulate:
self.in_buttons[r].setCheckable(True)
self.in_buttons[r].setText("OFF")
self.input_tb.setCellWidget(r, c, self.in_buttons[r])
indexb = QtCore.QPersistentModelIndex(self.input_tb.model().index(r, c))
self.in_buttons[r].clicked.connect(lambda *args, index=indexb: self.in_bit_toggle(index))
else:
w = QLabel()
w.setPixmap(self.ICON_KO)
self.input_tb.setCellWidget(r, c, w)
elif header == "INPUT":
i = QTableWidgetItem()
i.setText(str(input_idx))
self.input_tb.setItem(r, c, i)
r += 1
if not self.simulate:
self.parent.components["digital_io"].update.connect(self.update)
def plc_bit_toggle(self,bit_num):
bit_num=bit_num.row()
byte_idx = int(bit_num / 8)
bit_idx = bit_num % 8
if self.latch[bit_num] is True:
self.latch[bit_num]=False
self.out_buttons[bit_num].setText("OFF")
else:
self.latch[bit_num]=True
self.out_buttons[bit_num].setText("ON")
self.parent.components["digital_io"].set_bit(byte_idx, bit_idx, self.latch[bit_num])
def digital_int_update(self, bit_num, output_name):
row_num = bit_num.row()
item = self.output_tb.cellWidget(row_num, 1)
try:
value = int(item.text(), 10)
self.parent.components["digital_io"].set_int(output_name, value)
except ValueError:
item.setText("")
def in_bit_toggle(self, bit_num):
bit_num = bit_num.row()
byte_idx = int(bit_num / 8)
bit_idx = bit_num % 8
if self.latch_in[bit_num] is True:
self.latch_in[bit_num] = False
self.in_buttons[bit_num].setText("OFF")
else:
self.latch_in[bit_num] = True
self.in_buttons[bit_num].setText("ON")
self.parent.components["digital_io"].set_in_bit(byte_idx, bit_idx, self.latch_in[bit_num])
# UPDATE DIGITAL INPUTS DISPLAY
@pyqtSlot(dict)
def update(self, data):
r = 0
for input_name, input_idx in self.inputs.items():
item = self.input_tb.cellWidget(r, 1)
input_idx = int(input_idx)
byte_idx = int(input_idx / 8)
bit_idx = input_idx % 8
if data[1][byte_idx][bit_idx]:
item.setPixmap(self.ICON_OK)
else:
item.setPixmap(self.ICON_KO)
r += 1
pass
def closeEvent(self, event):
self.components["digital_io"].set_bit("")