133 lines
5.7 KiB
Python
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("")
|