You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

619 lines
25 KiB
Python

4 months ago
4 months ago
from ast import Mod
from math import comb
7 months ago
import typing
import sys
4 months ago
from numpy import var
7 months ago
import qtawesome
from PyQt5 import QtGui,QtCore,QtWidgets
from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt, QVariant, QSize
4 months ago
from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget, QMessageBox, QComboBox, QStyleOptionViewItem
from sympy import N
7 months ago
from protocol.Celery.MBTCPMaster import app as MBTCPMApp
from protocol.Celery.MBRTUMaster import app as MBRTUMApp
from protocol.Celery.MBRTUSlave import app as MBRTUSApp
from protocol.Celery.MBTCPSlave import app as MBTCPSApp
# from protocol.Celery.MBTCPMaster.MBTCPMTask import setValue as setMTcpValue
# from protocol.Celery.MBRTUMaster.MBRTUMTask import setValue as setMRTUValue
from celery.result import AsyncResult
from ..TrendManage.ActualTrendWidget import ActualTrend
from model.ProjectModel.VarManage import *
from utils import Globals
import re
sys.path.append('protocol/Celery/MBTCPMaster')
class QPushButton(QtWidgets.QPushButton):
def __init__(self, *__args: any,clicked = None):
super(QPushButton,self).__init__(*__args)
self.setCursor(Qt.PointingHandCursor)
self.setIconSize(QSize(25, 25))
class VarTableModel(QAbstractTableModel):
''' 变量表模型类'''
7 months ago
def __init__(self, header, data: list, modbusType = None, table = None):
7 months ago
'''
header : 表头变量
data : 表格内容
table : 缺省参数
'''
QAbstractTableModel.__init__(self, parent=None)
self.header = header
self.datas = data
self.checkList = ['Unchecked'] * len(self.datas)
self.supportedDragActions()
self.table = table
self.editableList = [] # 表格中可编辑项
7 months ago
self.modbusType = modbusType
7 months ago
def initTable(self):
self.datas = []
self.editableList = []
7 months ago
if self.table:
self.table.parent.initIcon()
varDatas = ModbusVarManage.getAllVar(self.modbusType)
7 months ago
if not varDatas:
# self.layoutChanged.emit()
self.table.proxy.invalidate()
return
for x in varDatas:
x.insert(1, '')
x.insert(2, '')
self.datas.append(x)
self.checkList = ['Unchecked'] * len(self.datas)
# self.layoutChanged.emit()
self.table.proxy.invalidate()
self.refreshComboBox()
def append_data(self, x):
self.datas.append(x)
self.checkList = ['Unchecked'] * len(self.datas)
self.table.proxy.invalidate()
# self.layoutChanged.emit()
def insert_data(self, x, index):
self.datas.insert(index, x)
self.checkList = ['Unchecked'] * len(self.datas)
self.table.proxy.invalidate()
def remove_row(self, row):
self.datas.pop(row)
self.checkList = ['UnChecked'] * len(self.datas)
self.table.proxy.invalidate()
def rowCount(self, parent: QModelIndex = ...) -> int:
if len(self.datas) > 0:
return len(self.datas)
return 0
def columnCount(self, parent: QModelIndex = ...) -> int:
return len(self.header)
def data(self, QModelIndex, role=None):
# print(Qt.__dict__.items())
if role == Qt.TextAlignmentRole:
return Qt.AlignCenter
if not QModelIndex.isValid():
print("行或者列有问题")
return QVariant()
if role == Qt.BackgroundColorRole:
if QModelIndex.row() % 2 == 0 and self.datas[QModelIndex.row()][3] not in Globals.getValue('forceVars'):
return QtGui.QColor('#EFEFEF')
if self.datas[QModelIndex.row()][3] in Globals.getValue('forceVars'):
return QtGui.QColor('#00FF7F')
if role == Qt.TextColorRole:
return QtGui.QColor('#1A1A1A')
if role == Qt.CheckStateRole:
if QModelIndex.column() == 0:
return Qt.Checked if self.checkList[QModelIndex.row()] == 'Checked' else Qt.Unchecked
else:
return None
if role == Qt.ToolTipRole:
if QModelIndex.column() == 0:
return self.checkList[QModelIndex.row()]
if role == Qt.DisplayRole or role == Qt.EditRole:
if QModelIndex.row() in self.editableList:
return self.datas[QModelIndex.row()][QModelIndex.column()]
if role != Qt.DisplayRole:
return QVariant()
# 获取变量值并插入表格
if QModelIndex.column() == 2:
varName = self.datas[QModelIndex.row()][3]
if varName != '':
# print(uid)
try:
uid = MBTCPMApp.backend.get('ModBus').decode('utf-8')
res = AsyncResult(uid) # 参数为task id
if res.result:
# print(res.result, res.date_done)
result = res.result[varName]
if result or result in [0, '0']:
self.datas[QModelIndex.row()][QModelIndex.column()] = result
except:
pass
return QVariant(self.datas[QModelIndex.row()][QModelIndex.column()])
def headerData(self, section: int, orientation: Qt.Orientation, role: int = ...) -> typing.Any: # 表头
if role != Qt.DisplayRole:
return None
if orientation == Qt.Horizontal:
return self.header[section]
def setData(self, index, value, role):
row = index.row()
col = index.column()
if role == Qt.CheckStateRole and col == 0:
self.checkList[row] = 'Checked' if value == Qt.Checked else 'Unchecked'
return True
if role == Qt.EditRole:
self.datas[row][col] = value
return True
return True
def flags(self, index):
if index.column() == 0:
return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable
if index.row() in self.editableList and index.column() or index.column() == 1:
return Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsEditable
return Qt.ItemIsEnabled
def headerClick(self, isOn):
self.beginResetModel()
if isOn:
self.checkList = []
self.checkList = ['Checked'] * len(self.datas)
else:
self.checkList = []
self.checkList = ['UnChecked'] * len(self.datas)
self.endResetModel()
def dragMoveEvent(self, event):
event.setDropAction(QtCore.Qt.MoveAction)
event.accept()
def moveRow(self, sourceParent: QModelIndex, sourceRow: int, destinationParent: QModelIndex,
destinationChild: int) -> bool:
if self.datas[destinationChild] == self.datas[sourceRow]:
return
self.datas[sourceRow], self.datas[destinationChild] = self.datas[destinationChild], self.datas[sourceRow]
self.table.proxy.invalidate()
def refreshComboBox(self):
#功能类型的index是5通讯类型index是10
7 months ago
for i in range(len(self.datas)):
cbRow = str('cb' + str(i) + str(5))
index = self.index(i, int(5))
delegate = self.table.itemDelegate(index)
delegate.paint(self.table, QStyleOptionViewItem(), index)
try:
comboBox = getattr(delegate, cbRow)
# print(comboBox, i, num, cbRow)
except Exception as e:
continue
if self.datas[i][5] in [0, 1]:
comboBox.setCurrentIndex(self.datas[i][5])
elif self.datas[i][5] in [3, 4]:
comboBox.setCurrentIndex(self.datas[i][5] - 1)
else:
comboBox.setCurrentIndex(-1)
7 months ago
class VarButtonDelegate(QItemDelegate):
"""该类用于向单元格中添加按钮 任务表格"""
trendWidgetDict = {}
def __init__(self, parent=None):
super(VarButtonDelegate, self).__init__(parent)
def trendWidget(self, varName):
if varName not in self.trendWidgetDict:
trendWidget = ActualTrend(varName = varName)
self.trendWidgetDict[varName] = trendWidget
return self.trendWidgetDict[varName]
def paint(self, painter, option, index):
if not self.parent().indexWidget(index):
button1 = QPushButton(
qtawesome.icon('fa.play', color='#1fbb6f'),
"",
self.parent(),
clicked=self.start_action
)
# button1.setIconSize(QSize(15, 15))
# button1.setStyleSheet("border:none;")
button2 = QPushButton(
qtawesome.icon('fa.pencil', color='#4c8cf2'),
"",
self.parent(),
clicked=self.edit_action
)
# button2.setStyleSheet("border:none;")
button3 = QPushButton(
qtawesome.icon('fa.trash', color='#ff6d6d'),
"",
self.parent(),
clicked=self.delete_action
)
# button3.setStyleSheet("border:none;")
button4 = QPushButton(
qtawesome.icon('fa.line-chart', color='#393c4e'),
"",
self.parent(),
clicked=self.trend_action
)
comboBox = QComboBox(self.parent())
comboBox.addItem('int', 0)
comboBox.addItem('ABCD', 1)
comboBox.addItem('CDAB', 2)
comboBox.addItem('BADC', 3)
comboBox.addItem('DCBA', 4)
4 months ago
comboBox.setCurrentText(str(self.parent().model.datas[index.row()][index.column()]))
7 months ago
# comboBox.setMinimumWidth(30)
comboBox.currentIndexChanged.connect(self.indexChange)
button1.clicked.connect(self.start_action)
button2.clicked.connect(self.edit_action)
button3.clicked.connect(self.delete_action)
button4.clicked.connect(self.trend_action)
button2.oldName = False
button2.isEdit = True
# button4.setStyleSheet("border:none;")
button1.index = [index.row(), index.column()]
button2.index = [index.row(), index.column()]
button3.index = [index.row(), index.column()]
button4.index = [index.row(), index.column()]
comboBox.index = [index.row(), index.column()]
data = self.parent().model.datas[index.row()]
4 months ago
for x in data[:-3]:
7 months ago
if x != '':
break
else:
button2.isEdit = False
button2.setIcon(qtawesome.icon('fa.save', color='#1fbb6f'))
self.parent().model.editableList.append(button2.index[0])
hboxLayout = QHBoxLayout()
hboxLayout.addWidget(comboBox)
hboxLayout.addWidget(button1)
hboxLayout.addWidget(button2)
hboxLayout.addWidget(button3)
hboxLayout.addWidget(button4)
hboxLayout.setContentsMargins(2, 0, 0, 2)
hboxLayout.setAlignment(Qt.AlignCenter)
widget = QWidget()
widget.setLayout(hboxLayout)
self.parent().setIndexWidget(
index,
widget
)
def indexChange(self):
sender = self.sender()
7 months ago
modbusType = self.parent().modbusType
7 months ago
index = sender.currentIndex()
text = sender.itemText(index)
name = self.parent().model.datas[sender.index[0]][3]
7 months ago
ModbusVarManage.editOrder(name, text, modbusType)
7 months ago
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
def start_action(self):
sender = self.sender()
model = self.parent().model
varMes = model.datas[sender.index[0]]
value, name, des, varType, slaveID, address, min, max, order = str(varMes[1]), str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[10])
pattern = re.compile(r'[^0-9\.-]+')
if not value or re.findall(pattern, str(value)):
reply = QMessageBox.question(self.parent(),
'警告',
"请输入强制值或数字",
QMessageBox.Yes)
return
if min and max:
if float(value) < float(min) or float(value) > float(max):
reply = QMessageBox.question(self.parent(),
'警告',
"超出量程范围",
QMessageBox.Yes)
return
elif min and not max:
if float(value) < float(min):
reply = QMessageBox.question(self.parent(),
'警告',
"超出量程范围",
QMessageBox.Yes)
return
elif max and not min:
if float(value) > float(max):
reply = QMessageBox.question(self.parent(),
'警告',
"超出量程范围",
QMessageBox.Yes)
return
# 0 : MODBUSTCP 主站模式
# 1 : MODBUSTCP 从站模式
# 2 : MODBUSRTU 主站模式
# 3 : MODBUSRTU 从站模式
proType = Globals.getValue('currentProType')
forceVars = Globals.getValue('forceVars')
forceVars.add(name)
Globals.setValue('forceVars', forceVars)
# print(Globals.getValue('forceVars'))
if proType == '0':
MBTCPMApp.send_task('protocol.Celery.MBTCPMaster.MBTCPMTask.setValue',args=[name, varType, slaveID, address, value, order])
if proType == '1':
MBTCPSApp.send_task('protocol.Celery.MBTCPSlave.MBTCPSTask.setValue',args=[name, varType, slaveID, address, value])
elif proType == '2':
MBRTUMApp.send_task('protocol.Celery.MBRTUMaster.MBRTUMTask.setValue',args=[name, varType, slaveID, address, value, order])
elif proType == '3':
MBRTUSApp.send_task('protocol.Celery.MBRTUSlave.MBRTUSTask.setValue',args=[name, varType, slaveID, address, value])
def edit_action(self):
sender = self.sender()
model = self.parent().model
7 months ago
modbusType = self.parent().modbusType
7 months ago
fucationCbRow = str('cb' + str(sender.index[0]) + str(5))
fucationIndex = self.parent().model.index(sender.index[0], 5)
fucationDelegate = self.parent().itemDelegate(fucationIndex)
fucationCheckbox = getattr(fucationDelegate, fucationCbRow)
if sender.isEdit:
sender.setIcon(qtawesome.icon('fa.save', color='#1fbb6f'))
sender.isEdit = False
sender.oldName = model.datas[sender.index[0]][3]
model.editableList.append(sender.index[0])
fucationCheckbox.setEnabled(True)
4 months ago
self.parent().viewport().update()
7 months ago
7 months ago
else:
varMes = model.datas[sender.index[0]]
4 months ago
name, des, varType, slaveID, address, min, max, varModel, order = str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[-2]), str(varMes[-1])
4 months ago
if varType == '':
4 months ago
varType = 0
4 months ago
if not name:
7 months ago
reply = QMessageBox.question(self.parent(),
'警告',
7 months ago
"有字段为空或输入错误",
7 months ago
QMessageBox.Yes)
return
4 months ago
if sender.oldName and ModbusVarManage.getByName(sender.oldName, modbusType):
if sender.oldName == name:
# 名称未改变,直接执行修改变量操作
ModbusVarManage.editVar(name=sender.oldName, Nname=name, des=des,
varType=varType, slaveID=slaveID, address=address,
min=min, max=max, order=order, modbusType=modbusType, varModel=varModel)
7 months ago
else:
# 名称改变,检查新名称是否已存在
if GlobalVarManager.isVarNameExist(name):
QMessageBox.information(self.parent(), '提示', '已有同名变量')
return
else:
# 执行修改变量操作
ModbusVarManage.editVar(name=sender.oldName, Nname=name, des=des,
varType=varType, slaveID=slaveID, address=address,
min=min, max=max, order=order, modbusType=modbusType, varModel=varModel)
else:
if GlobalVarManager.isVarNameExist(name):
7 months ago
QMessageBox.information(self.parent(), '提示', '已有同名变量')
return
else:
ModbusVarManage.createVar(varName = name, varType = varType, des = des,
7 months ago
address = address, slaveID = slaveID, min = min,
4 months ago
max = max, order = order, modbusType = modbusType, varModel= varModel)
7 months ago
sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2'))
rowIndex = sender.index[0]
7 months ago
varMes = ModbusVarManage.getByName(name, modbusType)
4 months ago
varMes.append('本地值')
7 months ago
varMes.append('int')
varMes.insert(1, '')
varMes.insert(2, '')
model.insert_data(varMes, rowIndex)
model.remove_row(rowIndex + 1)
sender.isEdit = True
fucationCheckbox.setEnabled(False)
4 months ago
# varModelCheckbox.setEnabled(False)
7 months ago
model.editableList.remove(sender.index[0])
4 months ago
self.parent().viewport().update()
7 months ago
def delete_action(self):
sender = self.sender()
model = self.parent().model
name = str(model.datas[sender.index[0]][3])
4 months ago
modbusType = self.parent().modbusType
ModbusVarManage.deleteVar(name = name, modbusType = modbusType)
7 months ago
model.remove_row(sender.index[0])
def trend_action(self):
model = self.parent().model
if model.table.parent._isPopenOpen:
sender = self.sender()
name = str(model.datas[sender.index[0]][3])
trend = self.trendWidget(varName = name)
trend.show()
class ModbusTypeBox(QItemDelegate):
def __init__(self, parent=None):
super(ModbusTypeBox, self).__init__(parent)
7 months ago
7 months ago
def paint(self, painter, option, index):
7 months ago
if (index.column() == 5) and index.row() not in self.parent().model.editableList:
7 months ago
data = self.parent().model.datas[index.row()]
comBox = str('cb' + str(index.row()) + str(index.column()))
setattr(self, comBox, QComboBox())
comboBox = getattr(self, comBox)
7 months ago
items = ['Coil Status', 'Input Status', 'Input Register', 'Holding Register']
comboBox.addItems(items)
if self.parent().model.datas[index.row()][index.column()] in [0, 1]:
comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()])
elif self.parent().model.datas[index.row()][index.column()] in [3, 4]:
comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()] - 1)
else:
comboBox.setCurrentIndex(0)
7 months ago
comboBox.currentIndexChanged.connect( self.indexChange)
comboBox.setObjectName('ModbusTypeBox')
comboBox.setEditable(True)
comboBox.lineEdit().setAlignment(Qt.AlignCenter)
# comboBox.setMinimumWidth(200)
# comboBox.setEnabled(False)
hboxLayout = QHBoxLayout()
hboxLayout.addWidget(comboBox)
hboxLayout.setContentsMargins(0, 0, 0, 0)
# hboxLayout.setAlignment(Qt.AlignCenter)
comboBox.index = [index.row(), index.column()]
row = index.row()
if row % 2 == 0:
comboBox.setStyleSheet("QComboBox { background-color: #EFEFEF; height: 40px; }")
else:
comboBox.setStyleSheet("QComboBox { background-color: #e9e7e3; height: 40px; }")
if str(data[index.column()]):
comboBox.setEnabled(False)
else:
comboBox.setEnabled(True)
widget = QWidget()
widget.setLayout(hboxLayout)
self.parent().setIndexWidget(
index,
widget
)
self.parent().openPersistentEditor(index)
def indexChange(self):
sender = self.sender()
index = sender.currentIndex()
7 months ago
if index in [2, 3]:
index += 1
self.parent().model.datas[sender.index[0]][sender.index[1]] = index
4 months ago
4 months ago
class ModbusVarModelBox(QItemDelegate):
4 months ago
def __init__(self, parent=None, comBoxColumn = 10):
4 months ago
super(ModbusVarModelBox, self).__init__(parent)
4 months ago
self.comBoxColumn = comBoxColumn
4 months ago
4 months ago
def paint(self, painter, option, index):
#本地值、模拟值、远程值 对应 0, 1, 2
4 months ago
if (index.column() == self.comBoxColumn) and not self.parent().indexWidget(index):
4 months ago
data = self.parent().model.datas[index.row()]
comBox = str('cb' + str(index.row()) + str(index.column()))
setattr(self, comBox, QComboBox())
comboBox = getattr(self, comBox)
4 months ago
comboBox = QComboBox(self.parent())
4 months ago
items = ['本地值', '模拟值', '远程值']
comboBox.addItems(items)
4 months ago
comboBox.setCurrentText(str(self.parent().model.datas[index.row()][index.column()]))
4 months ago
4 months ago
4 months ago
comboBox.currentIndexChanged.connect( self.indexChange)
comboBox.setObjectName('ModbusTypeBox')
comboBox.setEditable(True)
comboBox.lineEdit().setAlignment(Qt.AlignCenter)
hboxLayout = QHBoxLayout()
hboxLayout.addWidget(comboBox)
hboxLayout.setContentsMargins(0, 0, 0, 0)
comboBox.index = [index.row(), index.column()]
row = index.row()
if row % 2 == 0:
comboBox.setStyleSheet("QComboBox { background-color: #EFEFEF; height: 40px; }")
else:
comboBox.setStyleSheet("QComboBox { background-color: #e9e7e3; height: 40px; }")
widget = QWidget()
widget.setLayout(hboxLayout)
self.parent().setIndexWidget(
index,
widget
)
self.parent().openPersistentEditor(index)
4 months ago
def indexChange(self):
sender = self.sender()
modbusType = self.parent().modbusType
index = sender.currentIndex()
text = sender.itemText(index)
name = self.parent().model.datas[sender.index[0]][3]
ModbusVarManage.editVarModel(name, text, modbusType)
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
class HartVarModelBox(ModbusVarModelBox):
def __init__(self, parent=None, comBoxColumn = 8):
super(HartVarModelBox, self).__init__(parent)
self.comBoxColumn = comBoxColumn
def indexChange(self):
sender = self.sender()
index = sender.currentIndex()
text = sender.itemText(index)
name = self.parent().model.datas[sender.index[0]][1]
HartVarManage.editVarModel(name, text)
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
class TcRtdVarModelBox(ModbusVarModelBox):
def __init__(self, parent=None, comBoxColumn = 9):
super(TcRtdVarModelBox, self).__init__(parent)
self.comBoxColumn = comBoxColumn
4 months ago
def indexChange(self):
sender = self.sender()
index = sender.currentIndex()
4 months ago
text = sender.itemText(index)
name = self.parent().model.datas[sender.index[0]][3]
TcRtdManage.editVarModel(name, text)
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
class AnalogVarModelBox(ModbusVarModelBox):
def __init__(self, parent=None, comBoxColumn = 8):
super(AnalogVarModelBox, self).__init__(parent)
self.comBoxColumn = comBoxColumn
def indexChange(self):
sender = self.sender()
index = sender.currentIndex()
text = sender.itemText(index)
name = self.parent().model.datas[sender.index[0]][3]
AnalogManage.editVarModel(name, text, )
self.parent().model.datas[sender.index[0]][sender.index[1]] = text
class HartSimulateVarModelBox(ModbusVarModelBox):
def __init__(self, parent=None, comBoxColumn = 9):
super(HartSimulateVarModelBox, self).__init__(parent)
self.comBoxColumn = comBoxColumn
def indexChange(self):
sender = self.sender()
index = sender.currentIndex()
text = sender.itemText(index)
name = self.parent().model.datas[sender.index[0]][1]
HartSimulateVarManage.editVarModel(name, text)
self.parent().model.datas[sender.index[0]][sender.index[1]] = text