0718更新 修复Modbus相关

main
zcwBit 8 months ago
parent 02f42ab766
commit 165659ea10

@ -713,13 +713,13 @@ QCheckBox#userBox::indicator{
QCheckBox#userBox::indicator:checked{ QCheckBox#userBox::indicator:checked{
image: url(:/static/checkoff.png); image: url(./Static/checkoff.png);
} }
QCheckBox#userBox::indicator:enabled:unchecked{ QCheckBox#userBox::indicator:enabled:unchecked{
image: url(:/static/checkon.png); image: url(./Static/checkon.png);
} }
@ -816,7 +816,7 @@ QComboBox#timeBox::drop-down{
QComboBox#setBox::drop-down, QComboBox#ProTypeBox::drop-down,QComboBox#TcRtdTypeBox::drop-down, QComboBox#ModbusTypeBox::drop-down, QComboBox#timeBox::drop-down{ QComboBox#setBox::drop-down, QComboBox#ProTypeBox::drop-down,QComboBox#TcRtdTypeBox::drop-down, QComboBox#ModbusTypeBox::drop-down, QComboBox#timeBox::drop-down{
image: url(:/static/down.png); image: url(./Static/down.png);
} }

@ -28,7 +28,7 @@ class LoginWidget(QWidget):
self.resize(306, 451) self.resize(306, 451)
self.picLabel = QLabel() self.picLabel = QLabel()
self.picLabel.setPixmap(QPixmap(':/static/userPic.png')) self.picLabel.setPixmap(QPixmap('./Static/userPic.png'))
self.picLabel.setScaledContents(True) self.picLabel.setScaledContents(True)
self.userEdit = QLineEdit() self.userEdit = QLineEdit()

@ -45,7 +45,7 @@ class MainWindow(QMainWindow):
super(MainWindow, self).__init__() super(MainWindow, self).__init__()
InitParameterDB() InitParameterDB()
self.setupUi() self.setupUi()
# self.setStyleSheet(CommonHelper.readQss('static/main.qss')) # self.setStyleSheet(CommonHelper.readQss('Static/main.qss'))
self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowSystemMenuHint) self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowSystemMenuHint)
self.SHADOW_WIDTH = 0 #边框距离 self.SHADOW_WIDTH = 0 #边框距离
@ -130,7 +130,7 @@ class MainWindow(QMainWindow):
self.varManageTabWidget.addTab(self.rpcVarTableWidget, '远程通讯') self.varManageTabWidget.addTab(self.rpcVarTableWidget, '远程通讯')
#添加导入变量按钮 #添加导入变量按钮
self.importVarButton = QPushButton(QIcon(':/static/import.png'), '导入变量') self.importVarButton = QPushButton(QIcon('./Static/import.png'), '导入变量')
self.importVarButton.setObjectName('importBtn') self.importVarButton.setObjectName('importBtn')
self.importVarButton.setIconSize(QSize(22, 22)) self.importVarButton.setIconSize(QSize(22, 22))
self.importVarButton.setFlat(True) self.importVarButton.setFlat(True)
@ -421,7 +421,7 @@ class MainWindow(QMainWindow):
if __name__ == '__main__': if __name__ == '__main__':
app = QApplication(sys.argv) app = QApplication(sys.argv)
app.setStyle(QtWidgets.QStyleFactory.create('Fusion')) app.setStyle(QtWidgets.QStyleFactory.create('Fusion'))
app.setStyleSheet(CommonHelper.readQss('static/main.qss')) app.setStyleSheet(CommonHelper.readQss('Static/main.qss'))
# print(QtWidgets.QStyleFactory.keys()) # print(QtWidgets.QStyleFactory.keys())
ex = MainWindow() ex = MainWindow()
ex.show() ex.show()

@ -77,23 +77,23 @@ class MainLeft(QWidget):
self.protocolMag.setText("通讯配置") self.protocolMag.setText("通讯配置")
self.procedureMag.setText("规程管理") self.procedureMag.setText("规程管理")
self.createProject.setIcon(QIcon(':/static/newH.png')) self.createProject.setIcon(QIcon('./Static/newH.png'))
# self.openProject.setIcon(QIcon(':/static/open.png')) # self.openProject.setIcon(QIcon('./Static/open.png'))
self.varMag.setIcon(QIcon(':/static/varMag.png')) self.varMag.setIcon(QIcon('./Static/varMag.png'))
self.trendMag.setIcon(QIcon(':/static/trend.png')) self.trendMag.setIcon(QIcon('./Static/trend.png'))
self.userMag.setIcon(QIcon(':/static/userMag.png')) self.userMag.setIcon(QIcon('./Static/userMag.png'))
self.protocolMag.setIcon(QIcon(':/static/setting.png')) self.protocolMag.setIcon(QIcon('./Static/setting.png'))
self.procedureMag.setIcon(QIcon(':/static/procedure.png')) self.procedureMag.setIcon(QIcon('./Static/procedure.png'))
for btn in [self.createProject, self.varMag, self.trendMag, self.userMag, self.protocolMag, self.procedureMag]: for btn in [self.createProject, self.varMag, self.trendMag, self.userMag, self.protocolMag, self.procedureMag]:
self.setBtn(btn) self.setBtn(btn)
# self.openProject.clicked.connect(lambda:self.openProject.setIcon(QIcon(':/static/openH.png'))) # self.openProject.clicked.connect(lambda:self.openProject.setIcon(QIcon('./Static/openH.png')))
self.createProject.clicked.connect(lambda:self.createProject.setIcon(QIcon(':/static/newH.png'))) self.createProject.clicked.connect(lambda:self.createProject.setIcon(QIcon('./Static/newH.png')))
self.varMag.clicked.connect(lambda:self.varMag.setIcon(QIcon(':/static/varMagH.png'))) self.varMag.clicked.connect(lambda:self.varMag.setIcon(QIcon('./Static/varMagH.png')))
self.trendMag.clicked.connect(lambda:self.trendMag.setIcon(QIcon(':/static/trendH.png'))) self.trendMag.clicked.connect(lambda:self.trendMag.setIcon(QIcon('./Static/trendH.png')))
self.userMag.clicked.connect(lambda:self.userMag.setIcon(QIcon(':/static/userMagH.png'))) self.userMag.clicked.connect(lambda:self.userMag.setIcon(QIcon('./Static/userMagH.png')))
self.protocolMag.clicked.connect(lambda:self.protocolMag.setIcon(QIcon(':/static/settingH.png'))) self.protocolMag.clicked.connect(lambda:self.protocolMag.setIcon(QIcon('./Static/settingH.png')))
self.createProject.setChecked(True) self.createProject.setChecked(True)
self.createProject.setDown(True) self.createProject.setDown(True)
@ -114,45 +114,45 @@ class MainLeft(QWidget):
def eventFilter(self, object, event): def eventFilter(self, object, event):
if object == self.createProject: if object == self.createProject:
if event.type() == QtCore.QEvent.HoverEnter: if event.type() == QtCore.QEvent.HoverEnter:
self.createProject.setIcon(QIcon(':/static/newH.png')) self.createProject.setIcon(QIcon('./Static/newH.png'))
return True return True
if event.type() == QtCore.QEvent.HoverLeave and not self.createProject.isChecked(): if event.type() == QtCore.QEvent.HoverLeave and not self.createProject.isChecked():
self.createProject.setIcon(QIcon(':/static/new.png')) self.createProject.setIcon(QIcon('./Static/new.png'))
return True return True
# if object == self.openProject: # if object == self.openProject:
# if event.type() == QtCore.QEvent.HoverEnter: # if event.type() == QtCore.QEvent.HoverEnter:
# self.openProject.setIcon(QIcon(':/static/openH.png')) # self.openProject.setIcon(QIcon('./Static/openH.png'))
# return True # return True
# if event.type() == QtCore.QEvent.HoverLeave and not self.openProject.isChecked(): # if event.type() == QtCore.QEvent.HoverLeave and not self.openProject.isChecked():
# self.openProject.setIcon(QIcon(':/static/open.png')) # self.openProject.setIcon(QIcon('./Static/open.png'))
# return True # return True
if object == self.varMag: if object == self.varMag:
if event.type() == QtCore.QEvent.HoverEnter: if event.type() == QtCore.QEvent.HoverEnter:
self.varMag.setIcon(QIcon(':/static/varMagH.png')) self.varMag.setIcon(QIcon('./Static/varMagH.png'))
return True return True
if event.type() == QtCore.QEvent.HoverLeave and not self.varMag.isChecked(): if event.type() == QtCore.QEvent.HoverLeave and not self.varMag.isChecked():
self.varMag.setIcon(QIcon(':/static/varMag.png')) self.varMag.setIcon(QIcon('./Static/varMag.png'))
return True return True
if object == self.trendMag: if object == self.trendMag:
if event.type() == QtCore.QEvent.HoverEnter: if event.type() == QtCore.QEvent.HoverEnter:
self.trendMag.setIcon(QIcon(':/static/trendH.png')) self.trendMag.setIcon(QIcon('./Static/trendH.png'))
return True return True
if event.type() == QtCore.QEvent.HoverLeave and not self.trendMag.isChecked(): if event.type() == QtCore.QEvent.HoverLeave and not self.trendMag.isChecked():
self.trendMag.setIcon(QIcon(':/static/trend.png')) self.trendMag.setIcon(QIcon('./Static/trend.png'))
return True return True
if object == self.userMag: if object == self.userMag:
if event.type() == QtCore.QEvent.HoverEnter: if event.type() == QtCore.QEvent.HoverEnter:
self.userMag.setIcon(QIcon(':/static/userMagH.png')) self.userMag.setIcon(QIcon('./Static/userMagH.png'))
return True return True
if event.type() == QtCore.QEvent.HoverLeave and not self.userMag.isChecked(): if event.type() == QtCore.QEvent.HoverLeave and not self.userMag.isChecked():
self.userMag.setIcon(QIcon(':/static/userMag.png')) self.userMag.setIcon(QIcon('./Static/userMag.png'))
return True return True
if object == self.protocolMag: if object == self.protocolMag:
if event.type() == QtCore.QEvent.HoverEnter: if event.type() == QtCore.QEvent.HoverEnter:
self.protocolMag.setIcon(QIcon(':/static/settingH.png')) self.protocolMag.setIcon(QIcon('./Static/settingH.png'))
return True return True
if event.type() == QtCore.QEvent.HoverLeave and not self.protocolMag.isChecked(): if event.type() == QtCore.QEvent.HoverLeave and not self.protocolMag.isChecked():
self.protocolMag.setIcon(QIcon(':/static/setting.png')) self.protocolMag.setIcon(QIcon('./Static/setting.png'))
return True return True
return False return False
@ -164,9 +164,9 @@ class MainLeft(QWidget):
self.userMag.setDown(False) self.userMag.setDown(False)
self.protocolMag.setDown(False) self.protocolMag.setDown(False)
self.createProject.setIcon(QIcon(':/static/new.png')) self.createProject.setIcon(QIcon('./Static/new.png'))
# self.openProject.setIcon(QIcon(':/static/open.png')) # self.openProject.setIcon(QIcon('./Static/open.png'))
self.varMag.setIcon(QIcon(':/static/varMag.png')) self.varMag.setIcon(QIcon('./Static/varMag.png'))
self.trendMag.setIcon(QIcon(':/static/trend.png')) self.trendMag.setIcon(QIcon('./Static/trend.png'))
self.userMag.setIcon(QIcon(':/static/userMag.png')) self.userMag.setIcon(QIcon('./Static/userMag.png'))
self.protocolMag.setIcon(QIcon(':/static/setting.png')) self.protocolMag.setIcon(QIcon('./Static/setting.png'))

@ -24,7 +24,7 @@ class MainTop(QtWidgets.QWidget):
self.searchEdit = QtWidgets.QLineEdit() self.searchEdit = QtWidgets.QLineEdit()
action = QtWidgets.QAction(self) action = QtWidgets.QAction(self)
action.setIcon(QIcon(':/static/search.png')) action.setIcon(QIcon('./Static/search.png'))
self.searchEdit.addAction(action, QtWidgets.QLineEdit.LeadingPosition) self.searchEdit.addAction(action, QtWidgets.QLineEdit.LeadingPosition)
self.searchEdit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) self.searchEdit.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
self.searchEdit.setObjectName('searchEdit') self.searchEdit.setObjectName('searchEdit')
@ -35,16 +35,16 @@ class MainTop(QtWidgets.QWidget):
self.searchEdit.textChanged.connect(self.searchEditTextChanged) self.searchEdit.textChanged.connect(self.searchEditTextChanged)
# print(Globals.getValue('SearchWidget')) # print(Globals.getValue('SearchWidget'))
self.minBtn = QtWidgets.QPushButton(QIcon(':/static/min.png'), '' ,self) self.minBtn = QtWidgets.QPushButton(QIcon('./Static/min.png'), '' ,self)
self.minBtn.setObjectName("minBtn") self.minBtn.setObjectName("minBtn")
self.maxBtn = QtWidgets.QPushButton(QIcon(':/static/normal.png'), '' ,self) self.maxBtn = QtWidgets.QPushButton(QIcon('./Static/normal.png'), '' ,self)
self.maxBtn.setObjectName("maxBtn") self.maxBtn.setObjectName("maxBtn")
self.closeBtn = QtWidgets.QPushButton(QIcon(':/static/close.png'), '' ,self) self.closeBtn = QtWidgets.QPushButton(QIcon('./Static/close.png'), '' ,self)
self.closeBtn.setObjectName("closeBtn") self.closeBtn.setObjectName("closeBtn")
self.iconLabol.setPixmap(QPixmap(':/static/zhjt.png').scaled(50,50)) self.iconLabol.setPixmap(QPixmap('./Static/zhjt.png').scaled(50,50))
self.titleLabel.setText("信号发生装置") self.titleLabel.setText("信号发生装置")
self.closeBtn.clicked.connect(self.MainWindow.close) self.closeBtn.clicked.connect(self.MainWindow.close)
@ -95,14 +95,14 @@ class MainTop(QtWidgets.QWidget):
def showMax(self): def showMax(self):
if self.MainWindow.isMaximized(): if self.MainWindow.isMaximized():
self.MainWindow.showNormal() self.MainWindow.showNormal()
self.maxBtn.setIcon(QIcon(':/static/max.png')) self.maxBtn.setIcon(QIcon('./Static/max.png'))
self.MainWindow.verticalLayout.setStretch(0, 1) self.MainWindow.verticalLayout.setStretch(0, 1)
self.MainWindow.verticalLayout.setStretch(1, 15) self.MainWindow.verticalLayout.setStretch(1, 15)
else: else:
self.MainWindow.showMaximized() self.MainWindow.showMaximized()
self.MainWindow.verticalLayout.setStretch(0, 1) self.MainWindow.verticalLayout.setStretch(0, 1)
self.MainWindow.verticalLayout.setStretch(1, 18) self.MainWindow.verticalLayout.setStretch(1, 18)
self.maxBtn.setIcon(QIcon(':/static/normal.png')) self.maxBtn.setIcon(QIcon('./Static/normal.png'))
def mouseDoubleClickEvent(self, e): # 双击 def mouseDoubleClickEvent(self, e): # 双击
self.showMax() self.showMax()

@ -36,7 +36,7 @@ class AreaTabWidget(QTabWidget):
self.tabBar().setObjectName('areaTabBar') self.tabBar().setObjectName('areaTabBar')
self.addAreaButton = QPushButton("添加通道 ") self.addAreaButton = QPushButton("添加通道 ")
self.addAreaButton.setObjectName('addareabutton') self.addAreaButton.setObjectName('addareabutton')
self.addAreaButton.setIcon(QIcon(':/static/add.png')) self.addAreaButton.setIcon(QIcon('./Static/add.png'))
self.addAreaButton.setFlat(True) self.addAreaButton.setFlat(True)
self.addAreaButton.clicked.connect(self.addAreaTab) self.addAreaButton.clicked.connect(self.addAreaTab)
self.setCornerWidget(self.addAreaButton) self.setCornerWidget(self.addAreaButton)
@ -75,7 +75,7 @@ class AreaTabWidget(QTabWidget):
layout = QHBoxLayout() layout = QHBoxLayout()
addButton = QPushButton('添加通道') addButton = QPushButton('添加通道')
addButton.setObjectName('initAreaAddButton') addButton.setObjectName('initAreaAddButton')
icon = QIcon(':/static/add.png') icon = QIcon('./Static/add.png')
iconSize = QSize(50,50) iconSize = QSize(50,50)
addButton.setIcon(icon) addButton.setIcon(icon)
addButton.setIconSize(iconSize) addButton.setIconSize(iconSize)
@ -196,7 +196,7 @@ class AreaWidget(QWidget):
self.okBtnValue = True self.okBtnValue = True
self.delAreaBtn = QPushButton('删除') self.delAreaBtn = QPushButton('删除')
self.delAreaBtn.setIcon(QIcon(':/static/delete.png')) self.delAreaBtn.setIcon(QIcon('./Static/delete.png'))
self.delAreaBtn.setObjectName('delAreaBtn') self.delAreaBtn.setObjectName('delAreaBtn')
self.delAreaBtn.clicked.connect(self.removeAreaTab) self.delAreaBtn.clicked.connect(self.removeAreaTab)

@ -102,7 +102,7 @@ class ProfibusWidgets(QWidget):
self.startProtocolBtn = QPushButton() self.startProtocolBtn = QPushButton()
self.startProtocolBtn.setObjectName("profibusStartProtocolBtn") self.startProtocolBtn.setObjectName("profibusStartProtocolBtn")
# self.startProtocolBtn.setIcon(QIcon(':/static/startProtocol.png')) # self.startProtocolBtn.setIcon(QIcon('./Static/startProtocol.png'))
self.startProtocolBtn.setText('开始通讯') self.startProtocolBtn.setText('开始通讯')
self.startProtocolBtn.setIcon(QIcon('Static/start_green.png')) self.startProtocolBtn.setIcon(QIcon('Static/start_green.png'))
self.startProtocolBtn.setIconSize(QSize(23, 23)) self.startProtocolBtn.setIconSize(QSize(23, 23))
@ -149,9 +149,9 @@ class ProfibusWidgets(QWidget):
# 创建按钮 # 创建按钮
# self.minimizeButton = QPushButton(QIcon(':/static/min.png'), "") # self.minimizeButton = QPushButton(QIcon('./Static/min.png'), "")
# self.minimizeButton.setObjectName('minButton') # self.minimizeButton.setObjectName('minButton')
# self.closeButton = QPushButton(QIcon(':/static/close.png'), "") # self.closeButton = QPushButton(QIcon('./Static/close.png'), "")
# self.closeButton.setObjectName('closeButton') # self.closeButton.setObjectName('closeButton')
# # 按钮点击事件连接 # # 按钮点击事件连接
@ -162,7 +162,7 @@ class ProfibusWidgets(QWidget):
# hLayout.addWidget(self.closeButton) # hLayout.addWidget(self.closeButton)
iconLabel = QLabel() iconLabel = QLabel()
pix = QPixmap('static/Hicent.png') pix = QPixmap('Static/Hicent.png')
scaledPixmap = pix.scaled(168, 28, Qt.KeepAspectRatio) scaledPixmap = pix.scaled(168, 28, Qt.KeepAspectRatio)
iconLabel.setPixmap(scaledPixmap) iconLabel.setPixmap(scaledPixmap)
iconLabel.setScaledContents(True) iconLabel.setScaledContents(True)
@ -222,7 +222,7 @@ class ProfibusWidgets(QWidget):
self.setLayout(self.mainLayout) self.setLayout(self.mainLayout)
# self.setCentralWidget(self.stackWidget) # self.setCentralWidget(self.stackWidget)
self.setWindowIcon(QIcon(':/static/Hicent.jpg')) self.setWindowIcon(QIcon('./Static/Hicent.jpg'))
self.setWindowTitle("PROFIBUS总线测试工具") self.setWindowTitle("PROFIBUS总线测试工具")
@ -239,13 +239,13 @@ class ProfibusWidgets(QWidget):
if self.startProtocolBtn.isChecked(): if self.startProtocolBtn.isChecked():
self.startProtocolBtn.setText('停止通讯') self.startProtocolBtn.setText('停止通讯')
self.startProtocolBtn.setIcon(QIcon(':/static/pause.png')) self.startProtocolBtn.setIcon(QIcon('./Static/pause.png'))
self.startProtocolBtn.setIconSize(QSize(22, 22)) self.startProtocolBtn.setIconSize(QSize(22, 22))
self.protocolTimer.start(500) self.protocolTimer.start(500)
else: else:
self.startProtocolBtn.setText('开始通讯') self.startProtocolBtn.setText('开始通讯')
self.startProtocolBtn.setIcon(QIcon(':/static/start.png')) self.startProtocolBtn.setIcon(QIcon('./Static/start.png'))
self.protocolTimer.stop() self.protocolTimer.stop()
def readValues(self): def readValues(self):
@ -315,7 +315,7 @@ class ProfibusWidgets(QWidget):
self.process = subprocess.Popen("D:\\EnTalk PROFIBUS Manager\\DP.exe",startupinfo=startupInfo) self.process = subprocess.Popen("D:\\EnTalk PROFIBUS Manager\\DP.exe",startupinfo=startupInfo)
QTimer.singleShot(500, lambda:self.showLowerWidget(self.process)) QTimer.singleShot(500, lambda:self.showLowerWidget(self.process))
# self.showFullScreen() # self.showFullScreen()
# self.switchBtn.setIcon(QIcon(':/static/varMagH.png')) # self.switchBtn.setIcon(QIcon('./Static/varMagH.png'))
def switchDeviceValueManageWidget(self): def switchDeviceValueManageWidget(self):
self.stackWidget.setCurrentIndex(0) self.stackWidget.setCurrentIndex(0)

@ -13,17 +13,17 @@ class ProjectWidgets(QtWidgets.QWidget):
self.setupUi() self.setupUi()
def setupUi(self): def setupUi(self):
self.createBtn = QPushButton(QIcon(':/static/add.png'), '新建工程') self.createBtn = QPushButton(QIcon('./Static/add.png'), '新建工程')
self.createBtn.setObjectName('createBtn') self.createBtn.setObjectName('createBtn')
self.createBtn.setIconSize(QSize(22, 22)) self.createBtn.setIconSize(QSize(22, 22))
self.createBtn.clicked.connect(self.createProject) self.createBtn.clicked.connect(self.createProject)
self.importBtn = QPushButton(QIcon(':/static/import.png'), '导入工程') self.importBtn = QPushButton(QIcon('./Static/import.png'), '导入工程')
self.importBtn.setObjectName('importBtn') self.importBtn.setObjectName('importBtn')
self.importBtn.setIconSize(QSize(22, 22)) self.importBtn.setIconSize(QSize(22, 22))
self.importBtn.clicked.connect(self.importProject) self.importBtn.clicked.connect(self.importProject)
self.exportBtn = QPushButton(QIcon(':/static/export.png'), '导出工程') self.exportBtn = QPushButton(QIcon('./Static/export.png'), '导出工程')
self.exportBtn.setObjectName('exportBtn') self.exportBtn.setObjectName('exportBtn')
self.exportBtn.setIconSize(QSize(22, 22)) self.exportBtn.setIconSize(QSize(22, 22))
self.exportBtn.clicked.connect(self.exportPorject) self.exportBtn.clicked.connect(self.exportPorject)

@ -97,7 +97,7 @@ class RegisterWidget(QWidget):
self.setWindowTitle("Form") self.setWindowTitle("Form")
pix = QtGui.QPixmap(':/:/static/logo.png') pix = QtGui.QPixmap(':/Static/logo.png')
self.label.setPixmap(pix) self.label.setPixmap(pix)
self.label.setScaledContents(True) self.label.setScaledContents(True)
self.label.setMaximumSize(QSize(110,40)) self.label.setMaximumSize(QSize(110,40))
@ -145,7 +145,7 @@ class RegisterWidget(QWidget):
'提示', '提示',
"注册成功", "注册成功",
QMessageBox.Yes) QMessageBox.Yes)
with open('static/license.lic', 'w') as f: with open('Static/license.lic', 'w') as f:
f.write(passwd) f.write(passwd)
self.showMainWindow() self.showMainWindow()
self.close() self.close()

@ -16,16 +16,16 @@ class UserWidgets(QtWidgets.QWidget):
super(UserWidgets, self).__init__(parent) super(UserWidgets, self).__init__(parent)
self.setAttribute(Qt.WA_StyledBackground, True) self.setAttribute(Qt.WA_StyledBackground, True)
self.createBtn = QPushButton(QIcon(':/static/add.png'), '添加用户') self.createBtn = QPushButton(QIcon('./Static/add.png'), '添加用户')
self.createBtn.setObjectName('forceBtn') self.createBtn.setObjectName('forceBtn')
self.createBtn.setIconSize(QSize(22, 22)) self.createBtn.setIconSize(QSize(22, 22))
self.createBtn.clicked.connect(self.createUser) self.createBtn.clicked.connect(self.createUser)
# self.importBtn = QPushButton(QIcon(':/static/import.png'), '导入变量') # self.importBtn = QPushButton(QIcon('./Static/import.png'), '导入变量')
# self.importBtn.setObjectName('importBtn') # self.importBtn.setObjectName('importBtn')
# self.importBtn.setIconSize(QSize(22, 22)) # self.importBtn.setIconSize(QSize(22, 22))
self.delBtn = QPushButton(QIcon(':/static/delete.png'), '批量删除') self.delBtn = QPushButton(QIcon('./Static/delete.png'), '批量删除')
self.delBtn.setObjectName('delBtn') self.delBtn.setObjectName('delBtn')
self.delBtn.setIconSize(QSize(22, 22)) self.delBtn.setIconSize(QSize(22, 22))
self.delBtn.clicked.connect(self.deleteUser) self.delBtn.clicked.connect(self.deleteUser)

@ -1,116 +1,113 @@
from PyQt5.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QTextEdit, QHBoxLayout, QVBoxLayout, QGridLayout, QSpacerItem, QSizePolicy
QMetaObject, QObject, QPoint, QRect, from PyQt5.QtCore import Qt, QTimer, QCoreApplication
QSize, QTime, QUrl, Qt, QTimer) from PyQt5.QtGui import QIcon
from PyQt5.QtGui import (QBrush, QColor, QConicalGradient, QCursor, from utils import Globals
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PyQt5.QtWidgets import (QApplication, QGridLayout, QHBoxLayout, QLabel,
QPushButton, QSizePolicy, QSpacerItem, QTextEdit,
QWidget)
from protocol.Celery.MBTCPMaster import app
from Static import static
class MessageWidget(QWidget): class MessageWidget(QWidget):
def __init__(self, parent=None): def __init__(self, parent=None):
super(MessageWidget, self).__init__(parent) super(MessageWidget, self).__init__(parent)
self.setupUI()
self.setupConnections()
self.setObjectName(u"self") def setupUI(self):
"""设置UI界面"""
self.setObjectName("MessageWidget")
self.resize(1037, 648) self.resize(1037, 648)
self.setWindowTitle('报文查看')
# self.setWindowIcon(QIcon('./Static/file.png'))
self.decima = 16 # 创建控件
self.recvLabel = QLabel("接收到报文")
self.recvLabel = QLabel(self)
self.recvLabel.setObjectName("mesLabel") self.recvLabel.setObjectName("mesLabel")
self.recvLabel.setAlignment(Qt.AlignCenter) self.recvLabel.setAlignment(Qt.AlignCenter)
self.sendLabel = QLabel(self) self.sendLabel = QLabel("发送的报文")
self.sendLabel.setObjectName("mesLabel") self.sendLabel.setObjectName("mesLabel")
self.sendLabel.setAlignment(Qt.AlignCenter) self.sendLabel.setAlignment(Qt.AlignCenter)
self.clearButton = QPushButton(self) self.clearButton = QPushButton("清空报文")
self.clearButton.setObjectName("mesButton") self.clearButton.setObjectName("mesButton")
self.reButton = QPushButton(self) self.refreshButton = QPushButton("停止刷新")
self.reButton.setObjectName("mesButton") self.refreshButton.setObjectName("mesButton")
self.decimaButton = QPushButton(self)
self.decimaButton.setObjectName("mesButton")
self.recvEdit = QTextEdit(self) self.recvEdit = QTextEdit()
self.recvEdit.setObjectName("mesEdit") self.recvEdit.setObjectName("mesEdit")
self.sendEdit = QTextEdit(self) self.sendEdit = QTextEdit()
self.sendEdit.setObjectName("mesEdit") self.sendEdit.setObjectName("mesEdit")
self.horizontalLayout = QHBoxLayout() # 布局设置
self.horizontalLayout.setObjectName("horizontalLayout") self.setupLayout()
self.horizontalLayout.addWidget(self.clearButton)
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout.addItem(self.horizontalSpacer)
self.horizontalLayout.addWidget(self.reButton)
self.horizontalLayout.addWidget(self.decimaButton)
self.gridLayout = QGridLayout(self)
self.gridLayout.setObjectName("gridLayout")
self.gridLayout.addWidget(self.recvLabel, 1, 0, 1, 1)
self.gridLayout.addWidget(self.sendLabel, 1, 1, 1, 1)
self.gridLayout.addWidget(self.recvEdit, 2, 0, 1, 1)
self.gridLayout.addWidget(self.sendEdit, 2, 1, 1, 1)
self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 2)
self.setWindowTitle('报文查看')
self.setWindowIcon(QIcon('./:/static/file.png'))
self.recvLabel.setText(QCoreApplication.translate("Form", u"\u63a5\u6536\u5230\u62a5\u6587", None))
self.sendLabel.setText(QCoreApplication.translate("Form", u"\u53d1\u9001\u7684\u62a5\u6587", None))
self.clearButton.setText("清空报文")
self.reButton.setText('停止刷新')
self.decimaButton.setText('切换进制')
# 定时器设置
self.timer = QTimer(self) self.timer = QTimer(self)
# 将定时器超时信号与槽函数showTime()连接 self.timer.timeout.connect(self.updateMessages)
self.timer.timeout.connect(self.addText) self.timer.start(1000) # 每秒更新一次
self.timer.start(1000) # 启动timer
def setupLayout(self):
"""设置布局"""
# 按钮布局
buttonLayout = QHBoxLayout()
buttonLayout.addWidget(self.clearButton)
buttonSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
buttonLayout.addItem(buttonSpacer)
buttonLayout.addWidget(self.refreshButton)
# 主布局
mainLayout = QGridLayout(self)
mainLayout.addLayout(buttonLayout, 0, 0, 1, 2)
mainLayout.addWidget(self.recvLabel, 1, 0, 1, 1)
mainLayout.addWidget(self.sendLabel, 1, 1, 1, 1)
mainLayout.addWidget(self.recvEdit, 2, 0, 1, 1)
mainLayout.addWidget(self.sendEdit, 2, 1, 1, 1)
def setupConnections(self):
"""设置信号连接"""
self.clearButton.clicked.connect(self.clearMessages)
self.refreshButton.clicked.connect(self.toggleRefresh)
def updateMessages(self):
"""更新报文显示"""
try:
protocolManage = Globals.getValue('protocolManage')
if not protocolManage:
return
self.reButton.clicked.connect(self.stopRe) # 获取 Modbus 报文
self.decimaButton.clicked.connect(self.changeDecima) messages = protocolManage.getModbusMessages()
self.clearButton.clicked.connect(self.clearText)
def clearText(self): # 清空并更新接收报文
self.recvEdit.clear()
for msg in messages['receive']:
self.recvEdit.append(msg)
# 清空并更新发送报文
self.sendEdit.clear()
for msg in messages['send']:
self.sendEdit.append(msg)
except Exception as e:
pass
def clearMessages(self):
"""清空报文"""
self.recvEdit.clear() self.recvEdit.clear()
self.sendEdit.clear() self.sendEdit.clear()
def changeDecima(self): try:
if self.decima == 16: protocolManage = Globals.getValue('protocolManage')
self.decima = 10 if protocolManage:
elif self.decima == 10: protocolManage.clearModbusMessages()
self.decima = 16 except Exception as e:
pass
def stopRe(self): def toggleRefresh(self):
"""切换刷新状态"""
if self.timer.isActive(): if self.timer.isActive():
self.timer.stop() self.timer.stop()
self.reButton.setText('开始刷新') self.refreshButton.setText('开始刷新')
else: else:
self.timer.start() self.timer.start(1000)
self.reButton.setText('停止刷新') self.refreshButton.setText('停止刷新')
def addText(self):
try:
self.recvEdit.clear()
self.sendEdit.clear()
if self.decima == 16:
for x in app.backend.client.lrange("16R" , 0 , -1):
text = str(x)[2:-1]
self.recvEdit.append(text)
for x in app.backend.client.lrange("16S" , 0 , -1):
text = str(x)[2:-1]
self.sendEdit.append(text)
elif self.decima == 10:
for x in app.backend.client.lrange("10R" , 0 , -1):
text = str(x)[2:-1]
self.recvEdit.append(text)
for x in app.backend.client.lrange("10S" , 0 , -1):
text = str(x)[2:-1]
self.sendEdit.append(text)
except:
pass

@ -12,14 +12,7 @@ from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget, QMessageBox, QC
from sympy import N from sympy import N
from protocol.Celery.MBTCPMaster import app as MBTCPMApp # 移除 Celery 相关导入,现在使用 ProtocolManage 和 ModbusManager
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 ..TrendManage.ActualTrendWidget import ActualTrend
from model.ProjectModel.VarManage import * from model.ProjectModel.VarManage import *
@ -129,16 +122,13 @@ class VarTableModel(QAbstractTableModel):
if QModelIndex.column() == 2: if QModelIndex.column() == 2:
varName = self.datas[QModelIndex.row()][3] varName = self.datas[QModelIndex.row()][3]
if varName != '': if varName != '':
# print(uid)
try: try:
uid = MBTCPMApp.backend.get('ModBus').decode('utf-8') protocolManage = Globals.getValue('protocolManage')
res = AsyncResult(uid) # 参数为task id if protocolManage:
if res.result: result = protocolManage.readVariableValue(varName)
# print(res.result, res.date_done) if result is not None:
result = res.result[varName]
if result or result in [0, '0']:
self.datas[QModelIndex.row()][QModelIndex.column()] = result self.datas[QModelIndex.row()][QModelIndex.column()] = result
except: except Exception as e:
pass pass
return QVariant(self.datas[QModelIndex.row()][QModelIndex.column()]) return QVariant(self.datas[QModelIndex.row()][QModelIndex.column()])
@ -350,24 +340,24 @@ class VarButtonDelegate(QItemDelegate):
"超出量程范围", "超出量程范围",
QMessageBox.Yes) QMessageBox.Yes)
return return
# 0 : MODBUSTCP 主站模式
# 1 : MODBUSTCP 从站模式 # 使用新的 ProtocolManage 进行变量写入
# 2 : MODBUSRTU 主站模式 protocolManage = Globals.getValue('protocolManage')
# 3 : MODBUSRTU 从站模式 if protocolManage:
proType = Globals.getValue('currentProType') try:
forceVars = Globals.getValue('forceVars') result = protocolManage.writeVariableValue(name, value)
forceVars.add(name) if result:
Globals.setValue('forceVars', forceVars) forceVars = Globals.getValue('forceVars')
# print(Globals.getValue('forceVars')) if forceVars is None:
forceVars = set()
if proType == '0': forceVars.add(name)
MBTCPMApp.send_task('protocol.Celery.MBTCPMaster.MBTCPMTask.setValue',args=[name, varType, slaveID, address, value, order]) Globals.setValue('forceVars', forceVars)
if proType == '1': else:
MBTCPSApp.send_task('protocol.Celery.MBTCPSlave.MBTCPSTask.setValue',args=[name, varType, slaveID, address, value]) QMessageBox.warning(self.parent(), '错误', f'变量 {name} 写入失败', QMessageBox.Yes)
elif proType == '2': except Exception as e:
MBRTUMApp.send_task('protocol.Celery.MBRTUMaster.MBRTUMTask.setValue',args=[name, varType, slaveID, address, value, order]) QMessageBox.warning(self.parent(), '错误', f'写入变量时发生错误: {str(e)}', QMessageBox.Yes)
elif proType == '3': else:
MBRTUSApp.send_task('protocol.Celery.MBRTUSlave.MBRTUSTask.setValue',args=[name, varType, slaveID, address, value]) QMessageBox.warning(self.parent(), '错误', '协议管理器未初始化', QMessageBox.Yes)
def edit_action(self): def edit_action(self):
sender = self.sender() sender = self.sender()

@ -10,10 +10,7 @@ from UI.VarManages.MessageWidget import MessageWidget
from model.ProjectModel.ProjectManage import ProjectManage from model.ProjectModel.ProjectManage import ProjectManage
from model.ProjectModel.VarManage import ModbusVarManage from model.ProjectModel.VarManage import ModbusVarManage
from utils import Globals from utils import Globals
from protocol.Celery.MBTCPMaster import app as MBTCPMApp # 移除 Celery 相关导入,现在使用 ProtocolManage 和 ModbusManager
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.TCP.TemToMv import temToMv from protocol.TCP.TemToMv import temToMv
from protocol.TCP.Analog import getRealAO from protocol.TCP.Analog import getRealAO
import re import re
@ -28,37 +25,37 @@ class VarWidgets(QtWidgets.QWidget):
def setupUI(self): def setupUI(self):
self.setAttribute(Qt.WA_StyledBackground, True) self.setAttribute(Qt.WA_StyledBackground, True)
self.createBtn = QPushButton(QIcon(':/static/add.png'), '新建变量') self.createBtn = QPushButton(QIcon(':/Static/add.png'), '新建变量')
self.createBtn.setObjectName('createBtn') self.createBtn.setObjectName('createBtn')
self.createBtn.setIconSize(QSize(22, 22)) self.createBtn.setIconSize(QSize(22, 22))
self.createBtn.clicked.connect(self.createVar) self.createBtn.clicked.connect(self.createVar)
self.forceBtn = QPushButton(QIcon(':/static/start.png'), '批量强制') self.forceBtn = QPushButton(QIcon(':/Static/start.png'), '批量强制')
self.forceBtn.setObjectName('forceBtn') self.forceBtn.setObjectName('forceBtn')
self.forceBtn.setIconSize(QSize(22, 22)) self.forceBtn.setIconSize(QSize(22, 22))
self.forceBtn.clicked.connect(self.forceVar) self.forceBtn.clicked.connect(self.forceVar)
self.clearBtn = QPushButton(QIcon(':/static/clear.png'), '清除颜色') self.clearBtn = QPushButton(QIcon(':/Static/clear.png'), '清除颜色')
self.clearBtn.setObjectName('clearBtn') self.clearBtn.setObjectName('clearBtn')
self.clearBtn.setIconSize(QSize(22, 22)) self.clearBtn.setIconSize(QSize(22, 22))
self.clearBtn.clicked.connect(self.clearColour) self.clearBtn.clicked.connect(self.clearColour)
# self.importBtn = QPushButton(QIcon(':/static/import.png'), '导入变量') # self.importBtn = QPushButton(QIcon(':/Static/import.png'), '导入变量')
# self.importBtn.setObjectName('importBtn') # self.importBtn.setObjectName('importBtn')
# self.importBtn.setIconSize(QSize(22, 22)) # self.importBtn.setIconSize(QSize(22, 22))
# self.importBtn.clicked.connect(self.importVar) # self.importBtn.clicked.connect(self.importVar)
# self.exportBtn = QPushButton(QIcon(':/static/export.png'), '导出变量') # self.exportBtn = QPushButton(QIcon(':/Static/export.png'), '导出变量')
# self.exportBtn.setObjectName('exportBtn') # self.exportBtn.setObjectName('exportBtn')
# self.exportBtn.setIconSize(QSize(22, 22)) # self.exportBtn.setIconSize(QSize(22, 22))
# self.exportBtn.clicked.connect(self.exportVar) # self.exportBtn.clicked.connect(self.exportVar)
self.messageBtn = QPushButton(QIcon(':/static/message.png'), '查看报文') self.messageBtn = QPushButton(QIcon(':/Static/message.png'), '查看报文')
self.messageBtn.setObjectName('messageBtn') self.messageBtn.setObjectName('messageBtn')
self.messageBtn.setIconSize(QSize(22, 22)) self.messageBtn.setIconSize(QSize(22, 22))
self.messageBtn.clicked.connect(self.showMessage) self.messageBtn.clicked.connect(self.showMessage)
self.startProtocolBtn = QPushButton(QIcon(':/static/startProtocol.png'), '开始通讯') self.startProtocolBtn = QPushButton(QIcon(':/Static/startProtocol.png'), '开始通讯')
self.startProtocolBtn.setObjectName('startProtocolBtn') self.startProtocolBtn.setObjectName('startProtocolBtn')
self.startProtocolBtn.setIconSize(QSize(22, 22)) self.startProtocolBtn.setIconSize(QSize(22, 22))
self.startProtocolBtn.clicked.connect(self.startProtocol) self.startProtocolBtn.clicked.connect(self.startProtocol)
@ -210,51 +207,63 @@ class VarWidgets(QtWidgets.QWidget):
self.varView.model.append_data(['', '', '', '', '', '', '', '', '', '', '','本地值','int']) self.varView.model.append_data(['', '', '', '', '', '', '', '', '', '', '','本地值','int'])
def forceVar(self): def forceVar(self):
check = [i for i,x in enumerate(self.varView.model.checkList) if x == 'Checked'] check = [i for i, x in enumerate(self.varView.model.checkList) if x == 'Checked']
# check.sort(reverse=True) if not check:
QMessageBox.information(self, '提示', '请先勾选要强制的变量', QMessageBox.Yes)
return
protocolManage = Globals.getValue('protocolManage')
if not protocolManage:
QMessageBox.warning(self, '错误', '协议管理器未初始化', QMessageBox.Yes)
return
forceVars = Globals.getValue('forceVars')
if forceVars is None:
forceVars = set()
for i in check: for i in check:
varMes = self.varView.model.datas[i] varMes = self.varView.model.datas[i]
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]), str(varMes[11]) 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\.-]+') pattern = re.compile(r'[^0-9\.-]+')
if not value or re.findall(pattern, str(value)): if not value or re.findall(pattern, str(value)):
reply = QMessageBox.question(self.parent(), QMessageBox.warning(self, '警告', "请输入强制值或数字", QMessageBox.Yes)
'警告',
"请输入强制值或数字",
QMessageBox.Yes)
return return
if min and max: if min and max:
if float(value) < float(min) or float(value) > float(max): try:
reply = QMessageBox.question(self.parent(), if float(value) < float(min) or float(value) > float(max):
'警告', QMessageBox.warning(self, '警告', "超出量程范围", QMessageBox.Yes)
"超出量程范围", return
QMessageBox.Yes) except Exception:
QMessageBox.warning(self, '警告', "量程范围格式错误", QMessageBox.Yes)
return return
elif min and not max: elif min and not max:
if float(value) < float(min): try:
reply = QMessageBox.question(self.parent(), if float(value) < float(min):
'警告', QMessageBox.warning(self, '警告', "超出量程范围", QMessageBox.Yes)
"超出量程范围", return
QMessageBox.Yes) except Exception:
QMessageBox.warning(self, '警告', "量程范围格式错误", QMessageBox.Yes)
return return
elif max and not min: elif max and not min:
if float(value) > float(max): try:
reply = QMessageBox.question(self.parent(), if float(value) > float(max):
'警告', QMessageBox.warning(self, '警告', "超出量程范围", QMessageBox.Yes)
"超出量程范围", return
QMessageBox.Yes) except Exception:
QMessageBox.warning(self, '警告', "量程范围格式错误", QMessageBox.Yes)
return return
proType = Globals.getValue('currentProType')
forceVars = Globals.getValue('forceVars') # 使用新的 ProtocolManage 进行变量写入
forceVars.add(name) try:
Globals.setValue('forceVars', forceVars) result = protocolManage.writeVariableValue(name, value)
if proType == '0': if result:
MBTCPMApp.send_task('protocol.Celery.MBTCPMaster.MBTCPMTask.setValue',args=[name, varType, slaveID, address, value, order]) forceVars.add(name)
if proType == '1': else:
MBTCPSApp.send_task('protocol.Celery.MBTCPSlave.MBTCPSTask.setValue',args=[name, varType, slaveID, address, value]) QMessageBox.information(self, '提示', f'变量 {name} 写入失败', QMessageBox.Yes)
elif proType == '2': except Exception as e:
MBRTUMApp.send_task('protocol.Celery.MBRTUMaster.MBRTUMTask.setValue',args=[name, varType, slaveID, address, value, order]) QMessageBox.warning(self, '错误', f'写入变量 {name} 时发生错误: {str(e)}', QMessageBox.Yes)
elif proType == '3':
MBRTUSApp.send_task('protocol.Celery.MBRTUSlave.MBRTUSTask.setValue',args=[name, varType, slaveID, address, value]) Globals.setValue('forceVars', forceVars)
def importVar(self): def importVar(self):
@ -277,21 +286,59 @@ class VarWidgets(QtWidgets.QWidget):
self.messageWidget.show() self.messageWidget.show()
def startProtocol(self): def startProtocol(self):
protocolManage = Globals.getValue('protocolManage')
if not protocolManage:
QMessageBox.warning(self, '错误', '协议管理器未初始化', QMessageBox.Yes)
return
if not self._isPopenOpen: if not self._isPopenOpen:
ProjectManage.startProtocol() # 根据 modbusType 启动对应的 Modbus 通讯
self._isPopenOpen = True print(self.modbusType)
self.startProtocolBtn.setText('停止通讯') try:
self.startProtocolBtn.setIcon(QIcon(':/static/pause.png')) success = False
if self.modbusType == 'ModbusTcpMaster': # TCP Master
success = protocolManage.startModbusTcpMaster()
elif self.modbusType == 'ModbusTcpSlave': # TCP Slave
success = protocolManage.startModbusTcpSlave()
elif self.modbusType == 'ModbusRtuMaster': # RTU Master
success = protocolManage.startModbusRtuMaster()
elif self.modbusType == 'ModbusRtuSlave': # RTU Slave
success = protocolManage.startModbusRtuSlave()
if success:
self._isPopenOpen = True
self.startProtocolBtn.setText('停止通讯')
self.startProtocolBtn.setIcon(QIcon(':/Static/pause.png'))
else:
QMessageBox.warning(self, '错误', 'Modbus 通讯启动失败', QMessageBox.Yes)
except Exception as e:
QMessageBox.warning(self, '错误', f'启动通讯时发生错误: {str(e)}', QMessageBox.Yes)
else: else:
ProjectManage.closePopen() # 停止对应的 Modbus 通讯
self._isPopenOpen = False try:
self.startProtocolBtn.setText('开始通讯') success = False
self.startProtocolBtn.setIcon(QIcon(':/static/startProtocol.png')) if self.modbusType == 'ModbusTcpMaster': # TCP Master
success = protocolManage.stopModbusTcpMaster()
elif self.modbusType == 'ModbusTcpSlave': # TCP Slave
success = protocolManage.stopModbusTcpSlave()
elif self.modbusType == 'ModbusRtuMaster': # RTU Master
success = protocolManage.stopModbusRtuMaster()
elif self.modbusType == 'ModbusRtuSlave': # RTU Slave
success = protocolManage.stopModbusRtuSlave()
if success:
self._isPopenOpen = False
self.startProtocolBtn.setText('开始通讯')
self.startProtocolBtn.setIcon(QIcon(':/Static/startProtocol.png'))
else:
QMessageBox.warning(self, '错误', 'Modbus 通讯停止失败', QMessageBox.Yes)
except Exception as e:
QMessageBox.warning(self, '错误', f'停止通讯时发生错误: {str(e)}', QMessageBox.Yes)
def initIcon(self): def initIcon(self):
self._isPopenOpen = False self._isPopenOpen = False
self.startProtocolBtn.setText('开始通讯') self.startProtocolBtn.setText('开始通讯')
self.startProtocolBtn.setIcon(QIcon(':/static/startProtocol.png')) self.startProtocolBtn.setIcon(QIcon(':/Static/startProtocol.png'))
class HartWidgets(VarWidgets): class HartWidgets(VarWidgets):
@ -415,7 +462,7 @@ class TcRtdWidgets(VarWidgets):
except Exception: except Exception:
QMessageBox.warning(self, '警告', "量程范围格式错误", QMessageBox.Yes) QMessageBox.warning(self, '警告', "量程范围格式错误", QMessageBox.Yes)
return return
res = Globals.getValue('protocolManage').writeVariableValue(varName, float(value)) res = Globals.getValue('protocolManage').writeVariableValue(varName, value)
if res: if res:
forceVars.add(varName) forceVars.add(varName)
else: else:

@ -4,16 +4,21 @@ from utils import Globals
from model.ClientModel.Client import Client from model.ClientModel.Client import Client
from UI.RegisterWidgets.RegisterWidget import RegisterWidget from UI.RegisterWidgets.RegisterWidget import RegisterWidget
from model.ClientModel.RegisterManage import Register from model.ClientModel.RegisterManage import Register
# import Static.staticQrc_rc # 导入资源文件
import sys import sys
import logging
# 设置 modbus_tk 日志级别为 ERROR避免过多的调试信息和格式化错误
logging.getLogger('modbus_tk').setLevel(logging.ERROR)
if __name__ == '__main__': if __name__ == '__main__':
app = QApplication(sys.argv) app = QApplication(sys.argv)
app.setStyle(QStyleFactory.create('Fusion')) app.setStyle(QStyleFactory.create('Fusion'))
app.setStyleSheet(CommonHelper.readQss('static/Main.qss') app.setStyleSheet(CommonHelper.readQss('Static/Main.qss')
+ CommonHelper.readQss('static/profibus.qss') + CommonHelper.readQss('Static/profibus.qss')
+ CommonHelper.readQss('static/Area.qss')) + CommonHelper.readQss('Static/Area.qss'))
reg = Register() reg = Register()
if not reg.checkLicense(): if not reg.checkLicense():
regWidget = RegisterWidget() regWidget = RegisterWidget()

@ -49,6 +49,9 @@ class Client(object):
popenBeat = Globals.getValue('beatPopen') popenBeat = Globals.getValue('beatPopen')
histroyMan = Globals.getValue('historyDBManage') histroyMan = Globals.getValue('historyDBManage')
histroyMan.close() histroyMan.close()
protocolManage = Globals.getValue('protocolManage')
if protocolManage:
protocolManage.shutdown()
if popen: if popen:
popen.kill() popen.kill()
if popenBeat: if popenBeat:

@ -3,7 +3,7 @@ import json
from utils.DBModels.DeviceModels import DeviceDB from utils.DBModels.DeviceModels import DeviceDB
import numpy as np import numpy as np
from protocol.ModBus.ByteOrder import * from protocol.ModBus.ByteOrder import *
from protocol.ModBus.TCPMaster import * from protocol.ModBus.tcpmaster_example import TcpMaster
import struct import struct
import time import time
#从站 "AI" "DI"可强制 #从站 "AI" "DI"可强制

@ -1,7 +1,7 @@
import modbus_tk import modbus_tk
import modbus_tk.defines as cst import modbus_tk.defines as cst
from modbus_tk import modbus_tcp, hooks from modbus_tk import modbus_tcp
import logging import logging
import struct import struct
import threading import threading
@ -35,8 +35,7 @@ class DPV1Master():
self.master.set_timeout(5.0) self.master.set_timeout(5.0)
except Exception as e: except Exception as e:
self.master = None self.master = None
# hooks.install_hook("modbus_tcp.TcpMaster.after_recv", afterRecv)
# hooks.install_hook("modbus_tcp.TcpMaster.after_send", afterSend)
def writeMultipleRegister(self, slaveId, address, outputValue): def writeMultipleRegister(self, slaveId, address, outputValue):

@ -0,0 +1,703 @@
from utils.DBModels.ProtocolModel import TCPSetting, RTUSetting
from .tcpmaster_example import TcpMaster
from .rtumaster_example import RTUMaster
from .tcpslave_example import TCPSlave
from .rtuslave_example import RTUSlave
from modbus_tk import hooks
import threading
import time
class ModbusManager:
"""Modbus 通讯管理器,负责管理所有 Modbus TCP/RTU 主站和从站"""
def __init__(self):
# Modbus 通讯实例
self.modbusTcpMaster = None
self.modbusRtuMaster = None
self.modbusTcpSlave = None
self.modbusRtuSlave = None
# 线程管理
self.modbusReadThreads = {} # 存储各个Modbus读取线程
self.modbusStopEvents = {} # 存储各个Modbus停止事件
self.modbusLocks = {} # 存储各个Modbus的锁
# 变量缓存回调
self.variableValueCache = None
self.cacheLock = None
self.varInfoCache = None
# 报文记录
self.messageHistory = {
'send': [], # 发送的报文
'receive': [] # 接收的报文
}
self.maxMessageCount = 100 # 最大保存报文数量
self.messageLock = threading.Lock()
# 设置报文捕获 hooks
self._setupHooks()
def setVariableCache(self, variableValueCache, cacheLock, varInfoCache):
"""设置变量缓存引用"""
self.variableValueCache = variableValueCache
self.cacheLock = cacheLock
self.varInfoCache = varInfoCache
# ==================== 启动/停止方法 ====================
def startModbusTcpMaster(self):
"""启动 Modbus TCP 主站"""
try:
if self.modbusTcpMaster is not None:
return True
# 从数据库获取TCP设置
tcpSettings = self._getTcpSettings('master')
if not tcpSettings:
return False
# 创建TCP主站实例
# print(tcpSettings['host'], tcpSettings['port'])
self.modbusTcpMaster = TcpMaster(
host=tcpSettings['host'],
port=tcpSettings['port']
)
# 启动读取线程
self._startModbusReadThread('TCP_MASTER', tcpSettings['frequency'])
return True
except Exception as e:
print(f"启动 Modbus TCP 主站失败: {str(e)}")
return False
def stopModbusTcpMaster(self):
"""停止 Modbus TCP 主站"""
try:
if self.modbusTcpMaster is None:
return True
# 停止读取线程
self._stopModbusReadThread('TCP_MASTER')
# 清理主站实例
self.modbusTcpMaster = None
return True
except Exception as e:
return False
def startModbusRtuMaster(self):
"""启动 Modbus RTU 主站"""
try:
if self.modbusRtuMaster is not None:
return True
# 从数据库获取RTU设置
rtuSettings = self._getRtuSettings('master')
if not rtuSettings:
return False
# 创建RTU主站实例
self.modbusRtuMaster = RTUMaster(
port=rtuSettings['port'],
baudrate=rtuSettings['baudrate'],
bytesize=rtuSettings['byteSize'],
parity=rtuSettings['parity'][0], # 取第一个字符
stopbits=rtuSettings['stopbits']
)
# 启动读取线程
self._startModbusReadThread('RTU_MASTER', rtuSettings['frequency'])
return True
except Exception as e:
return False
def stopModbusRtuMaster(self):
"""停止 Modbus RTU 主站"""
try:
if self.modbusRtuMaster is None:
return True
# 停止读取线程
self._stopModbusReadThread('RTU_MASTER')
# 清理主站实例
self.modbusRtuMaster = None
return True
except Exception as e:
return False
def startModbusTcpSlave(self):
"""启动 Modbus TCP 从站"""
try:
if self.modbusTcpSlave is not None:
return True
# 从数据库获取TCP设置
tcpSettings = self._getTcpSettings('slave')
if not tcpSettings:
return False
# 创建TCP从站实例
self.modbusTcpSlave = TCPSlave(
address=tcpSettings['host'],
port=tcpSettings['port']
)
# 添加默认从站ID
self.modbusTcpSlave.addSlave(1)
return True
except Exception as e:
return False
def stopModbusTcpSlave(self):
"""停止 Modbus TCP 从站"""
try:
if self.modbusTcpSlave is None:
return True
# 停止从站服务器
if hasattr(self.modbusTcpSlave, 'server'):
self.modbusTcpSlave.server.stop()
self.modbusTcpSlave = None
return True
except Exception as e:
return False
def startModbusRtuSlave(self):
"""启动 Modbus RTU 从站"""
try:
if self.modbusRtuSlave is not None:
return True
# 从数据库获取RTU设置
rtuSettings = self._getRtuSettings('slave')
if not rtuSettings:
return False
# 创建RTU从站实例
self.modbusRtuSlave = RTUSlave(
port=rtuSettings['port'],
baudrate=rtuSettings['baudrate'],
bytesize=rtuSettings['byteSize'],
parity=rtuSettings['parity'][0], # 取第一个字符
stopbits=rtuSettings['stopbits']
)
# 启动从站服务器
self.modbusRtuSlave.start()
# 添加默认从站ID
self.modbusRtuSlave.addSlave(1)
return True
except Exception as e:
return False
def stopModbusRtuSlave(self):
"""停止 Modbus RTU 从站"""
try:
if self.modbusRtuSlave is None:
return True
# 停止从站服务器
if hasattr(self.modbusRtuSlave, 'server'):
self.modbusRtuSlave.server.stop()
self.modbusRtuSlave = None
return True
except Exception as e:
return False
def stopAllModbus(self):
"""停止所有 Modbus 通讯"""
results = []
results.append(self.stopModbusTcpMaster())
results.append(self.stopModbusRtuMaster())
results.append(self.stopModbusTcpSlave())
results.append(self.stopModbusRtuSlave())
return all(results)
def getModbusStatus(self):
"""获取所有 Modbus 通讯状态"""
return {
'tcpMaster': self.modbusTcpMaster is not None,
'rtuMaster': self.modbusRtuMaster is not None,
'tcpSlave': self.modbusTcpSlave is not None,
'rtuSlave': self.modbusRtuSlave is not None
}
# ==================== 读写方法 ====================
def writeModbusTcpMasterValue(self, info, value):
"""写入TCP主站变量值"""
try:
if self.modbusTcpMaster is None:
return False
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._writeModbusValue(self.modbusTcpMaster, slaveId, address, varType, value, order)
except Exception as e:
print(f"写入TCP主站变量失败: {str(e)}")
return False
def writeModbusRtuMasterValue(self, info, value):
"""写入RTU主站变量值"""
try:
if self.modbusRtuMaster is None:
return False
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._writeModbusValue(self.modbusRtuMaster, slaveId, address, varType, value, order)
except Exception as e:
print(f"写入RTU主站变量失败: {str(e)}")
return False
def writeModbusTcpSlaveValue(self, info, value):
"""写入TCP从站变量值"""
try:
if self.modbusTcpSlave is None:
print("Modbus TCP 从站未启动")
return False
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._writeModbusSlaveValue(self.modbusTcpSlave, slaveId, address, varType, value, order)
except Exception as e:
print(f"写入TCP从站变量失败: {str(e)}")
return False
def writeModbusRtuSlaveValue(self, info, value):
"""写入RTU从站变量值"""
try:
if self.modbusRtuSlave is None:
print("Modbus RTU 从站未启动")
return False
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._writeModbusSlaveValue(self.modbusRtuSlave, slaveId, address, varType, value, order)
except Exception as e:
print(f"写入RTU从站变量失败: {str(e)}")
return False
def readModbusTcpMasterValue(self, info):
"""读取TCP主站变量值"""
try:
if self.modbusTcpMaster is None:
return None
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._readModbusValue(self.modbusTcpMaster, slaveId, address, varType, order)
except Exception as e:
print(f"读取TCP主站变量失败: {str(e)}")
return None
def readModbusRtuMasterValue(self, info):
"""读取RTU主站变量值"""
try:
if self.modbusRtuMaster is None:
return None
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._readModbusValue(self.modbusRtuMaster, slaveId, address, varType, order)
except Exception as e:
print(f"读取RTU主站变量失败: {str(e)}")
return None
def readModbusTcpSlaveValue(self, info):
"""读取TCP从站变量值"""
try:
if self.modbusTcpSlave is None:
return None
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._readModbusSlaveValue(self.modbusTcpSlave, slaveId, address, varType, order)
except Exception as e:
print(f"读取TCP从站变量失败: {str(e)}")
return None
def readModbusRtuSlaveValue(self, info):
"""读取RTU从站变量值"""
try:
if self.modbusRtuSlave is None:
return None
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
return self._readModbusSlaveValue(self.modbusRtuSlave, slaveId, address, varType, order)
except Exception as e:
print(f"读取RTU从站变量失败: {str(e)}")
return None
# ==================== 私有方法 ====================
def _getTcpSettings(self, tcpType):
"""从数据库获取TCP设置"""
try:
setting = TCPSetting.select().where(TCPSetting.tcpType == tcpType).first()
if setting:
return {
'host': setting.host,
'port': setting.port,
'frequency': float(setting.frequency),
'offset': setting.offset
}
else:
# 如果没有设置,创建默认设置
newSetting = TCPSetting()
newSetting.initSetting(tcpType)
return {
'host': newSetting.host,
'port': newSetting.port,
'frequency': float(newSetting.frequency),
'offset': newSetting.offset
}
except Exception as e:
print(f"获取TCP设置失败: {str(e)}")
return None
def _getRtuSettings(self, tcpType):
"""从数据库获取RTU设置"""
try:
setting = RTUSetting.select().where(RTUSetting.tcpType == tcpType).first()
if setting:
return {
'port': setting.port,
'byteSize': setting.byteSize,
'baudrate': setting.baudrate,
'stopbits': setting.stopbits,
'parity': setting.parity,
'frequency': float(setting.frequency),
'offset': setting.offset
}
else:
# 如果没有设置,创建默认设置
newSetting = RTUSetting()
newSetting.initSetting(tcpType)
return {
'port': newSetting.port,
'byteSize': newSetting.byteSize,
'baudrate': newSetting.baudrate,
'stopbits': newSetting.stopbits,
'parity': newSetting.parity,
'frequency': float(newSetting.frequency),
'offset': newSetting.offset
}
except Exception as e:
print(f"获取RTU设置失败: {str(e)}")
return None
def _startModbusReadThread(self, protocolType, frequency):
"""启动Modbus读取线程"""
if protocolType in self.modbusReadThreads:
return
stopEvent = threading.Event()
lock = threading.Lock()
self.modbusStopEvents[protocolType] = stopEvent
self.modbusLocks[protocolType] = lock
readThread = threading.Thread(
target=self._modbusReadWorker,
args=(protocolType, frequency, stopEvent, lock),
daemon=True
)
self.modbusReadThreads[protocolType] = readThread
readThread.start()
def _stopModbusReadThread(self, protocolType):
"""停止Modbus读取线程"""
if protocolType in self.modbusStopEvents:
self.modbusStopEvents[protocolType].set()
if protocolType in self.modbusReadThreads:
self.modbusReadThreads[protocolType].join(timeout=2)
del self.modbusReadThreads[protocolType]
if protocolType in self.modbusStopEvents:
del self.modbusStopEvents[protocolType]
if protocolType in self.modbusLocks:
del self.modbusLocks[protocolType]
def _modbusReadWorker(self, protocolType, frequency, stopEvent, lock):
"""Modbus读取工作线程"""
interval = 1.0 / frequency if frequency > 0 else 1.0
while not stopEvent.is_set():
try:
with lock:
self._readModbusVariables(protocolType)
except Exception as e:
print(f"Modbus读取线程错误 ({protocolType}): {str(e)}")
time.sleep(interval)
def _readModbusVariables(self, protocolType):
"""读取指定协议类型的所有Modbus变量"""
if protocolType == 'TCP_MASTER':
self._readTcpMasterVariables()
elif protocolType == 'RTU_MASTER':
self._readRtuMasterVariables()
def _readTcpMasterVariables(self):
"""读取TCP主站变量"""
if self.modbusTcpMaster is None or self.varInfoCache is None:
return
for varName, varInfo in self.varInfoCache.items():
if varInfo['modelType'] == 'ModbusTcpMasterVar':
try:
info = varInfo['variableData']
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
value = self._readModbusValue(self.modbusTcpMaster, slaveId, address, varType, order)
if value != 'error' and self.variableValueCache is not None and self.cacheLock is not None:
with self.cacheLock:
self.variableValueCache[varName] = value
except Exception as e:
print(f"读取TCP主站变量失败 {varName}: {str(e)}")
def _readRtuMasterVariables(self):
"""读取RTU主站变量"""
if self.modbusRtuMaster is None or self.varInfoCache is None:
return
for varName, varInfo in self.varInfoCache.items():
if varInfo['modelType'] == 'ModbusRtuMasterVar':
try:
info = varInfo['variableData']
slaveId = int(info['slaveID'])
address = int(info['address'])
varType = int(info['varType'])
order = info['order']
value = self._readModbusValue(self.modbusRtuMaster, slaveId, address, varType, order)
if value != 'error' and self.variableValueCache is not None and self.cacheLock is not None:
with self.cacheLock:
self.variableValueCache[varName] = value
except Exception as e:
print(f"读取RTU主站变量失败 {varName}: {str(e)}")
def _readModbusValue(self, master, slaveId, address, varType, order):
"""通用Modbus值读取方法"""
try:
# varType: 1=线圈, 2=离散输入, 3=输入寄存器, 4=保持寄存器
if varType == 0: # 线圈
return master.readCoils(slaveId, address, 1)
elif varType == 1: # 离散输入
return master.readInputCoils(slaveId, address, 1)
elif varType == 3: # 输入寄存器
return master.readInputRegisters(slaveId, address, 1, order)
elif varType == 4: # 保持寄存器
return master.readHoldingRegisters(slaveId, address, 1, order)
else:
return 'error'
except Exception as e:
print(f"读取Modbus值失败: {str(e)}")
return 'error'
def _writeModbusValue(self, master, slaveId, address, varType, value, order):
"""通用Modbus主站值写入方法"""
try:
# varType: 0=线圈, 1=离散输入, 3=输入寄存器, 4=保持寄存器
if varType == 0: # 线圈
result = master.writeSingleCoil(slaveId, address, value)
return result != 'error'
elif varType == 4: # 保持寄存器
result = master.writeSingleRegister(slaveId, address, value, order)
return result != 'error'
else:
print(f"不支持写入的变量类型: {varType}")
return False
except Exception as e:
print(f"写入Modbus主站值失败: {str(e)}")
return False
def _writeModbusSlaveValue(self, slave, slaveId, address, varType, value, order):
"""通用Modbus从站值写入方法"""
try:
# 根据变量类型确定存储区名称
blockName = self._getModbusBlockName(varType, address)
if not blockName:
return False
# 转换地址为存储区内部地
slave.setValue(slaveId, blockName, address, value, order)
return True
except Exception as e:
print(f"写入Modbus从站值失败: {str(e)}")
return False
def _readModbusSlaveValue(self, slave, slaveId, address, varType, order):
"""通用Modbus从站值读取方法"""
try:
# 根据变量类型确定存储区名称
blockName = self._getModbusBlockName(varType, address)
if not blockName:
return None
return slave.readValue(slaveId, blockName, address, order)
except Exception as e:
print(f"读取Modbus从站值失败: {str(e)}")
return None
def _getModbusBlockName(self, varType, address):
"""根据变量类型和地址获取Modbus存储区名称"""
# varType: 0=线圈, 1=离散输入, 3=输入寄存器, 4=保持寄存器
if varType == 0: # 线圈 (0-9999)
return '0'
elif varType == 1: # 离散输入 (10000-19999)
return '1'
elif varType == 3: # 输入寄存器 (30000-39999)
return '3'
elif varType == 4: # 保持寄存器 (40000-49999)
return '4'
else:
print(f"未知的变量类型: {varType}")
return None
# ==================== 报文记录方法 ====================
def _setupHooks(self):
"""设置 modbus_tk hooks 来捕获报文"""
try:
def captureRequest(args):
"""捕获请求报文数据"""
try:
if args and len(args) > 0:
# args[-1] 通常包含报文数据
data = args[-1]
if isinstance(data, (list, tuple)):
hexData = ' '.join([f'{b:02X}' for b in data])
elif isinstance(data, bytes):
hexData = ' '.join([f'{b:02X}' for b in data])
else:
hexData = str(data)
self._addMessage('receive', f"接收请求: {hexData}")
except Exception as e:
pass
def captureResponse(args):
"""捕获响应报文数据"""
try:
if args and len(args) > 0:
# args[-1] 通常包含报文数据
data = args[-1]
if isinstance(data, (list, tuple)):
hexData = ' '.join([f'{b:02X}' for b in data])
elif isinstance(data, bytes):
hexData = ' '.join([f'{b:02X}' for b in data])
else:
hexData = str(data)
self._addMessage('send', f"发送响应: {hexData}")
except Exception as e:
pass
# 使用正确的 hook 名称
hooks.install_hook('modbus.Server.before_handle_request', captureRequest)
hooks.install_hook('modbus.Server.after_handle_request', captureResponse)
except Exception as e:
print(f"设置 hooks 失败: {e}")
# 如果 hooks 设置失败,不影响正常通讯功能
pass
def _addMessage(self, messageType, content):
"""添加报文记录"""
try:
with self.messageLock:
timestamp = time.strftime('%H:%M:%S')
message = f"[{timestamp}] {content}"
if messageType == 'send':
self.messageHistory['send'].append(message)
if len(self.messageHistory['send']) > self.maxMessageCount:
self.messageHistory['send'].pop(0)
elif messageType == 'receive':
self.messageHistory['receive'].append(message)
if len(self.messageHistory['receive']) > self.maxMessageCount:
self.messageHistory['receive'].pop(0)
except Exception as e:
pass
def getMessages(self):
"""获取报文信息"""
try:
with self.messageLock:
return {
'send': self.messageHistory['send'].copy(),
'receive': self.messageHistory['receive'].copy()
}
except Exception as e:
return {'send': [], 'receive': []}
def clearMessages(self):
"""清空报文记录"""
try:
with self.messageLock:
self.messageHistory['send'].clear()
self.messageHistory['receive'].clear()
except Exception as e:
pass

@ -3,7 +3,7 @@ import serial
import modbus_tk import modbus_tk
import modbus_tk.defines as cst import modbus_tk.defines as cst
from modbus_tk import modbus_rtu, hooks from modbus_tk import modbus_rtu
import sys import sys
from .ByteOrder import * from .ByteOrder import *
@ -31,33 +31,93 @@ class RTUMaster():
except Exception as e: except Exception as e:
pass pass
hooks.install_hook("modbus_rtu.RtuMaster.after_recv", afterRecv)
hooks.install_hook("modbus_rtu.RtuMaster.before_send", afterSend)
def writeSingleRegister(self, slaveId, address, outputValue, order = 'ABCD'):
def writeSingleRegister(self, slaveId, address, outputValue, order='ABCD'):
try: try:
if '.' not in str(outputValue): if '.' not in str(outputValue):
# 整数值,使用单寄存器写入
outputValue = int(outputValue) outputValue = int(outputValue)
# print(outputValue) self.master.execute(slaveId, cst.WRITE_SINGLE_REGISTER, starting_address=address, output_value=outputValue)
self.master.execute(slaveId, cst.WRITE_SINGLE_REGISTER, starting_address = address, output_value = outputValue)
else: else:
# 浮点数值需要使用多寄存器写入因为浮点数占用2个寄存器
outputValue = float(outputValue) outputValue = float(outputValue)
if order == 'ABCD': # 大端模式 valueByte = None # 初始化变量
if order == 'ABCD': # 大端模式
valueByte = floatToABCD(outputValue) valueByte = floatToABCD(outputValue)
elif order == 'DCBA': # 小端模式 elif order == 'DCBA': # 小端模式
valueByte = floatToDCBA(outputValue) valueByte = floatToDCBA(outputValue)
elif order == 'BADC': elif order == 'BADC':
valueByte = floatToBADC(outputValue) valueByte = floatToBADC(outputValue)
elif order == 'CDAB': elif order == 'CDAB':
valueByte = floatToCDAB(outputValue) valueByte = floatToCDAB(outputValue)
self.master.execute(slaveId, cst.WRITE_MULTIPLE_REGISTERS, starting_address = address, output_value=valueByte) else:
# 默认使用 ABCD 字节序
# print(f"Unknown byte order '{order}', using default ABCD")
valueByte = floatToABCD(outputValue)
if valueByte is not None:
# 浮点数必须使用 WRITE_MULTIPLE_REGISTERS因为需要写入2个寄存器
self.master.execute(slaveId, cst.WRITE_MULTIPLE_REGISTERS, starting_address=address, output_value=valueByte)
else:
# print(f"Failed to convert float value {outputValue} with order {order}")
return 'error'
except Exception as e: except Exception as e:
print('error') print(f'writeSingleRegister error: {e}')
return 'error'
def writeSingleCoil(self, slaveId, address, outputValue): def writeSingleCoil(self, slaveId, address, outputValue):
try:
outputValue = int(outputValue)
if outputValue in [0, 1]:
self.master.execute(slaveId, cst.WRITE_SINGLE_COIL, address, output_value=outputValue)
except Exception as e:
return 'error'
def writeMultipleRegisters(self, slaveId, startAddress, outputValues, order='ABCD'):
"""写多个寄存器,支持不同数据类型和字节序"""
try:
processedValues = []
for value in outputValues:
if '.' not in str(value):
# 整数值
processedValues.append(int(value))
else:
# 浮点值 - 根据字节序转换为寄存器对
floatValue = float(value)
if order == 'ABCD': # 大端模式
valueByte = floatToABCD(floatValue)
elif order == 'DCBA': # 小端模式
valueByte = floatToDCBA(floatValue)
elif order == 'BADC':
valueByte = floatToBADC(floatValue)
elif order == 'CDAB':
valueByte = floatToCDAB(floatValue)
processedValues.extend(valueByte)
self.master.execute(slaveId, cst.WRITE_MULTIPLE_REGISTERS, starting_address=startAddress, output_value=processedValues)
except Exception as e:
return 'error'
if outputValue in [0, 1]: def writeMultipleCoils(self, slaveId, startAddress, outputValues):
self.master.execute(slaveId, cst.WRITE_SINGLE_COIL, address, output_value = outputValue) """写多个线圈支持布尔值列表或0/1整数列表"""
try:
processedValues = []
for value in outputValues:
if isinstance(value, bool):
processedValues.append(1 if value else 0)
else:
intValue = int(value)
if intValue in [0, 1]:
processedValues.append(intValue)
else:
# 如果值不是0或1转换为布尔值
processedValues.append(1 if intValue else 0)
self.master.execute(slaveId, cst.WRITE_MULTIPLE_COILS, starting_address=startAddress, output_value=processedValues)
except Exception as e:
return 'error'
def readHoldingRegisters(self, slaveId, startAddress, varNums, order = 'ABCD'): def readHoldingRegisters(self, slaveId, startAddress, varNums, order = 'ABCD'):
@ -96,9 +156,10 @@ class RTUMaster():
except Exception as e: except Exception as e:
return 'error' return 'error'
def readCoils(self, slaveId, startAddress, varNums, order = 'ABCD'): def readCoils(self, slaveId, startAddress, varNums, order='ABCD'):
try: try:
value = self.master.execute(slaveId, cst.READ_COILS, startAddress, varNums) value = self.master.execute(slaveId, cst.READ_COILS, startAddress, varNums)
# 如果只读取一个线圈,返回单个值;否则返回列表
return value[0] return value[0]
except Exception as e: except Exception as e:
return 'error' return 'error'
@ -106,6 +167,7 @@ class RTUMaster():
def readInputCoils(self, slaveId, startAddress, varNums): def readInputCoils(self, slaveId, startAddress, varNums):
try: try:
value = self.master.execute(slaveId, cst.READ_DISCRETE_INPUTS, startAddress, varNums) value = self.master.execute(slaveId, cst.READ_DISCRETE_INPUTS, startAddress, varNums)
# 如果只读取一个线圈,返回单个值;否则返回列表
return value[0] return value[0]
except Exception as e: except Exception as e:
return 'error' return 'error'
@ -133,7 +195,7 @@ class RTUMaster():
# red = master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 9) # 这里可以修改需要读取的功能码 # red = master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 9) # 这里可以修改需要读取的功能码
# print(red) # print(red)
# alarm = "正常" # alarm = "正常"
# return list(red), alarm # return list(red), alarm#
# except Exception as exc: # except Exception as exc:
# print(str(exc)) # print(str(exc))

@ -18,8 +18,8 @@ class RTUSlave():
self.server = modbus_rtu.RtuServer(serial.Serial(port = port, baudrate = baudrate, bytesize = bytesize, parity = parity, stopbits = stopbits, xonxoff = xonxoff)) self.server = modbus_rtu.RtuServer(serial.Serial(port = port, baudrate = baudrate, bytesize = bytesize, parity = parity, stopbits = stopbits, xonxoff = xonxoff))
except Exception as e: except Exception as e:
return return
hooks.install_hook('modbus.Server.before_handle_request', afterRecv) # hooks.install_hook('modbus.Server.before_handle_request', afterRecv)
hooks.install_hook("modbus.Server.after_handle_request", afterSend) # hooks.install_hook("modbus.Server.after_handle_request", afterSend)
# self.server.set_timeout(5.0) # self.server.set_timeout(5.0)
# self.server.set_verbose(True) # self.server.set_verbose(True)
@ -59,6 +59,8 @@ class RTUSlave():
valueByte = floatToBADC(value) valueByte = floatToBADC(value)
elif order == 'CDAB': elif order == 'CDAB':
valueByte = floatToCDAB(value) valueByte = floatToCDAB(value)
else:
valueByte = floatToABCD(value)
slave.set_values(name, address, valueByte) slave.set_values(name, address, valueByte)
else: else:
@ -80,6 +82,8 @@ class RTUSlave():
value = BADCToFloat(value) value = BADCToFloat(value)
elif order == 'CDAB': elif order == 'CDAB':
value = CDABToFloat(value) value = CDABToFloat(value)
else:
value = ABCDToFloat(value)
return value return value
except Exception as e: except Exception as e:
print(e) print(e)

@ -1,7 +1,7 @@
import modbus_tk import modbus_tk
import modbus_tk.defines as cst import modbus_tk.defines as cst
from modbus_tk import modbus_tcp, hooks from modbus_tk import modbus_tcp
import logging import logging
import struct import struct
from .SetMessage import * from .SetMessage import *
@ -9,53 +9,96 @@ from .ByteOrder import *
class TcpMaster(): class TcpMaster():
def __init__(self, host = None, port = None): def __init__(self, host=None, port=None):
try: try:
self.master = modbus_tcp.TcpMaster(host = host, port = port) self.master = modbus_tcp.TcpMaster(host=host, port=port)
self.master.set_timeout(5.0) self.master.set_timeout(5.0)
except Exception as e: except Exception as e:
pass pass
hooks.install_hook("modbus_tcp.TcpMaster.after_recv", afterRecv) def writeSingleRegister(self, slaveId, address, outputValue, order='ABCD'):
hooks.install_hook("modbus_tcp.TcpMaster.before_send", afterSend)
def writeSingleRegister(self, slaveId, address, outputValue, order = 'ABCD'):
try: try:
if '.' not in str(outputValue): if '.' not in str(outputValue):
# 整数值,使用单寄存器写入
outputValue = int(outputValue) outputValue = int(outputValue)
print(outputValue) self.master.execute(slaveId, cst.WRITE_SINGLE_REGISTER, starting_address=address, output_value=outputValue)
self.master.execute(slaveId, cst.WRITE_SINGLE_REGISTER, starting_address = address, output_value = outputValue)
else: else:
# 浮点数值需要使用多寄存器写入因为浮点数占用2个寄存器
outputValue = float(outputValue) outputValue = float(outputValue)
if order == 'ABCD': # 大端模式 if order == 'ABCD': # 大端模式
valueByte = floatToABCD(outputValue) valueByte = floatToABCD(outputValue)
elif order == 'DCBA': # 小端模式 elif order == 'DCBA': # 小端模式
valueByte = floatToDCBA(outputValue) valueByte = floatToDCBA(outputValue)
elif order == 'BADC': elif order == 'BADC':
valueByte = floatToBADC(outputValue) valueByte = floatToBADC(outputValue)
elif order == 'CDAB': elif order == 'CDAB':
valueByte = floatToCDAB(outputValue) valueByte = floatToCDAB(outputValue)
self.master.execute(slaveId, cst.WRITE_MULTIPLE_REGISTERS, starting_address = address, output_value=valueByte) else:
valueByte = floatToABCD(outputValue)
# 浮点数必须使用 WRITE_MULTIPLE_REGISTERS因为需要写入2个寄存器
self.master.execute(slaveId, cst.WRITE_MULTIPLE_REGISTERS, starting_address=address, output_value=valueByte)
except Exception as e: except Exception as e:
return 'error' return 'error'
def writeMultipleRegisters(self, slaveId, startAddress, outputValues, order='ABCD'):
"""写多个寄存器,支持不同数据类型和字节序"""
try:
processedValues = []
for value in outputValues:
if '.' not in str(value):
processedValues.append(int(value))
else:
floatValue = float(value)
if order == 'ABCD':
valueByte = floatToABCD(floatValue)
elif order == 'DCBA':
valueByte = floatToDCBA(floatValue)
elif order == 'BADC':
valueByte = floatToBADC(floatValue)
elif order == 'CDAB':
valueByte = floatToCDAB(floatValue)
processedValues.extend(valueByte)
self.master.execute(slaveId, cst.WRITE_MULTIPLE_REGISTERS, starting_address=startAddress, output_value=processedValues)
except Exception as e:
return 'error'
def writeSingleCoil(self, slaveId, address, outputValue): def writeSingleCoil(self, slaveId, address, outputValue):
try: try:
outputValue = int(outputValue) outputValue = int(outputValue)
if outputValue in [0, 1]: if outputValue in [0, 1]:
self.master.execute(slaveId, cst.WRITE_SINGLE_COIL, address, output_value = outputValue) self.master.execute(slaveId, cst.WRITE_SINGLE_COIL, address, output_value=outputValue)
except Exception as e: except Exception as e:
return 'error' return 'error'
def readHoldingRegisters(self, slaveId, startAddress, varNums, order = 'ABCD'): def writeMultipleCoils(self, slaveId, startAddress, outputValues):
print(order) """写多个线圈支持布尔值列表或0/1整数列表"""
try:
processedValues = []
for value in outputValues:
if isinstance(value, bool):
processedValues.append(1 if value else 0)
else:
intValue = int(value)
if intValue in [0, 1]:
processedValues.append(intValue)
else:
processedValues.append(1 if intValue else 0)
self.master.execute(slaveId, cst.WRITE_MULTIPLE_COILS, starting_address=startAddress, output_value=processedValues)
except Exception as e:
return 'error'
def readHoldingRegisters(self, slaveId, startAddress, varNums, order='ABCD'):
try: try:
if order == 'int': if order == 'int':
valueByte = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, varNums)[0] valueByte = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, varNums)[0]
else: else:
value = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, 2) value = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, 2)
if order == 'ABCD': # 大端模式 if order == 'ABCD':
valueByte = ABCDToFloat(value) valueByte = ABCDToFloat(value)
elif order == 'DCBA': # 小端模式 elif order == 'DCBA':
valueByte = DCBAToFloat(value) valueByte = DCBAToFloat(value)
elif order == 'BADC': elif order == 'BADC':
valueByte = BADCToFloat(value) valueByte = BADCToFloat(value)
@ -65,15 +108,15 @@ class TcpMaster():
except: except:
return 'error' return 'error'
def readInputRegisters(self, slaveId, startAddress, varNums, order = 'ABCD'): def readInputRegisters(self, slaveId, startAddress, varNums, order='ABCD'):
try: try:
if order == 'int': if order == 'int':
valueByte = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, varNums)[0] valueByte = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, varNums)[0]
else: else:
value = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, 2) value = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, 2)
if order == 'ABCD': # 大端模式 if order == 'ABCD':
valueByte = ABCDToFloat(value) valueByte = ABCDToFloat(value)
elif order == 'DCBA': # 小端模式 elif order == 'DCBA':
valueByte = DCBAToFloat(value) valueByte = DCBAToFloat(value)
elif order == 'BADC': elif order == 'BADC':
valueByte = BADCToFloat(value) valueByte = BADCToFloat(value)
@ -83,18 +126,24 @@ class TcpMaster():
except Exception as e: except Exception as e:
return 'error' return 'error'
def readCoils(self, slaveId, startAddress, varNums, order = 'ABCD'): def readCoils(self, slaveId, startAddress, varNums, order='ABCD'):
try: try:
value = self.master.execute(slaveId, cst.READ_COILS, startAddress, varNums) value = self.master.execute(slaveId, cst.READ_COILS, startAddress, varNums)
return value[0] if varNums == 1:
return value[0] if value else 0
else:
return value
except Exception as e: except Exception as e:
return 'error' return 'error'
def readInputCoils(self, slaveId, startAddress, varNums): def readInputCoils(self, slaveId, startAddress, varNums):
print(slaveId, startAddress, varNums)
try: try:
value = self.master.execute(slaveId, cst.READ_DISCRETE_INPUTS, startAddress, varNums) value = self.master.execute(slaveId, cst.READ_DISCRETE_INPUTS, startAddress, varNums)
return value[0] if varNums == 1:
except: return value[0] if value else 0
else:
return value
except Exception as e:
return 'error' return 'error'

@ -12,13 +12,15 @@ from .SetMessage import *
class TCPSlave(): class TCPSlave():
def __init__(self, address = '127.0.0.1', port = 502): def __init__(self, address = '127.0.0.1', port = 502):
try: try:
self.server = modbus_tcp.TcpServer(address = address, port = port) self.server = modbus_tcp.TcpServer(address=address, port=port)
self.server.start() self.server.start()
print(f"TCP Slave started on {address}:{port}")
except Exception as e: except Exception as e:
pass print(f"Failed to start TCP Slave on {address}:{port}: {e}")
raise e
hooks.install_hook('modbus.Server.before_handle_request', afterRecv) # hooks.install_hook('modbus.Server.before_handle_request', afterRecv)
hooks.install_hook("modbus.Server.after_handle_request", afterSend) # hooks.install_hook("modbus.Server.after_handle_request", afterSend)
# 创建从站 # 创建从站
# 添加存储区 # 添加存储区
@ -29,36 +31,52 @@ class TCPSlave():
# ANALOG_INPUTS = 4 # ANALOG_INPUTS = 4
def addSlave(self, slaveId): def addSlave(self, slaveId):
try: try:
self.server.add_slave(slaveId) self.server.add_slave(slaveId)
slave = self.server.get_slave(slaveId) slave = self.server.get_slave(slaveId)
slave.add_block('0', cst.COILS, 0, 9999) # 从0开始创建10000个地址
slave.add_block('1', cst.DISCRETE_INPUTS, 10000,19999) # 添加存储区 - 使用正确的地址范围
slave.add_block('3', cst.ANALOG_INPUTS, 30000, 39999) slave.add_block('0', cst.COILS, 0, 9999) # 线圈 0-9999
slave.add_block('4', cst.HOLDING_REGISTERS, 40000, 49999) slave.add_block('1', cst.DISCRETE_INPUTS, 10000, 19999) # 离散输入 10000-19999
slave.add_block('3', cst.ANALOG_INPUTS, 30000, 39999) # 输入寄存器 30000-39999
slave.add_block('4', cst.HOLDING_REGISTERS, 40000, 49999) # 保持寄存器 40000-49999
print(f"Added slave {slaveId} with storage blocks")
return True
except Exception as e: except Exception as e:
pass print(f"Failed to add slave {slaveId}: {e}")
return False
def setValue(self, slaveId, name, address, value, order = 'ABCD'): def setValue(self, slaveId, name, address, value, order='ABCD'):
try: try:
slave = self.server.get_slave(slaveId) slave = self.server.get_slave(slaveId)
# print(value)
if '.' in str(value): if '.' in str(value):
if order == 'ABCD': # 大端模式 # 浮点数处理
valueByte = floatToABCD(value) floatValue = float(value)
elif order == 'DCBA': # 小端模式 if order == 'ABCD': # 大端模式
valueByte = floatToDCBA(value) valueByte = floatToABCD(floatValue)
elif order == 'DCBA': # 小端模式
valueByte = floatToDCBA(floatValue)
elif order == 'BADC': elif order == 'BADC':
valueByte = floatToBADC(value) valueByte = floatToBADC(floatValue)
elif order == 'CDAB': elif order == 'CDAB':
valueByte = floatToCDAB(value) valueByte = floatToCDAB(floatValue)
else:
valueByte = floatToABCD(floatValue)
slave.set_values(name, address, valueByte) slave.set_values(name, address, valueByte)
else: else:
slave.set_values(name, address, value) # 整数处理
intValue = int(value)
slave.set_values(name, address, intValue)
return True
except Exception as e: except Exception as e:
pass print(f"TCP Slave setValue error: {e}")
print(f"Error details - slaveId: {slaveId}, name: {name}, address: {address}, value: {value}")
return False
def readValue(self, slaveId, name, address, order = 'int'): def readValue(self, slaveId, name, address, order = 'int'):
try: try:

@ -7,6 +7,7 @@ from protocol.TCP.TCPVarManage import *
from protocol.TCP.TemToMv import temToMv from protocol.TCP.TemToMv import temToMv
from protocol.RPC.RpcClient import RpcClient from protocol.RPC.RpcClient import RpcClient
from protocol.RPC.RpcServer import RpcServer from protocol.RPC.RpcServer import RpcServer
from protocol.ModBus.ModbusManager import ModbusManager
from utils import Globals from utils import Globals
import threading import threading
import time import time
@ -31,13 +32,20 @@ class ProtocolManage(object):
self.varInfoCache = {} # 保持驼峰命名 self.varInfoCache = {} # 保持驼峰命名
self.historyDBManage = Globals.getValue('historyDBManage') self.historyDBManage = Globals.getValue('historyDBManage')
self.variableValueCache = {} # {varName: value} self.variableValueCache = {} # {varName: value}
# Modbus 管理器
self.modbusManager = ModbusManager()
self.modbusManager.setVariableCache(self.variableValueCache, None, self.varInfoCache)
self.refreshVarCache() self.refreshVarCache()
self.cacheLock = threading.Lock() self.cacheLock = threading.Lock()
# 设置 Modbus 管理器的缓存锁
self.modbusManager.setVariableCache(self.variableValueCache, self.cacheLock, self.varInfoCache)
self.readThreadStop = threading.Event() self.readThreadStop = threading.Event()
self.readThread = threading.Thread(target=self._backgroundReadAllVariables, daemon=True) self.readThread = threading.Thread(target=self._backgroundReadAllVariables, daemon=True)
self.readThread.start() self.readThread.start()
def clearVarCache(self): def clearVarCache(self):
"""清空变量信息缓存""" """清空变量信息缓存"""
self.varInfoCache.clear() self.varInfoCache.clear()
@ -68,7 +76,6 @@ class ProtocolManage(object):
:return: 包含变量信息和模型类型的字典如果未找到返回None :return: 包含变量信息和模型类型的字典如果未找到返回None
""" """
if variableName in self.varInfoCache: if variableName in self.varInfoCache:
# print(111)
return self.varInfoCache[variableName] return self.varInfoCache[variableName]
for modelClass in self.MODEL_CLASSES: for modelClass in self.MODEL_CLASSES:
varInstance = modelClass.getByName(variableName) varInstance = modelClass.getByName(variableName)
@ -102,24 +109,18 @@ class ProtocolManage(object):
return return
self.RpcServer = RpcServer(rabbitmqHost) self.RpcServer = RpcServer(rabbitmqHost)
def addClient(self, clientName): def addClient(self, clientName):
if self.RpcServer: if self.RpcServer:
self.RpcServer.addClient(clientName = clientName) self.RpcServer.addClient(clientName=clientName)
else: else:
return return
# print(11111111111)
# time.sleep(3)
# print(self.RpcServer.broadcastRead())
# self.RpcServer.broadcastRead()
def closeServer(self): def closeServer(self):
if self.RpcServer: if self.RpcServer:
self.RpcServer.close() self.RpcServer.close()
self.RpcServer = None self.RpcServer = None
# @classmethod def writeVariableValue(self, variableName, value, trigger=None, timeoutMS=2000):
def writeVariableValue(self, variableName, value, trigger = None, timeoutMS = 2000):
""" """
根据变量名写入变量值根据变量类型进行不同处理不保存到数据库 根据变量名写入变量值根据变量类型进行不同处理不保存到数据库
@ -130,40 +131,42 @@ class ProtocolManage(object):
varInfo = self.lookupVariable(variableName) varInfo = self.lookupVariable(variableName)
if not varInfo: if not varInfo:
if self.RpcServer: if self.RpcServer:
existsVar, clientNames = self.RpcServer.existsVar(variableName) existsVar, clientNames = self.RpcServer.existsVar(variableName)
if existsVar: if existsVar:
value = self.RpcServer.writeVar(variableName, value) value = self.RpcServer.writeVar(variableName, value)
return True return True
else: else:
return False return False
return False return False
modelType = varInfo['modelType'] modelType = varInfo['modelType']
info = varInfo['variableData'] info = varInfo['variableData']
# print(info)
try: try:
# 拆分为四个独立的Modbus协议条件判断 # 拆分为四个独立的Modbus协议条件判断
if modelType == 'ModbusTcpMasterVar': if modelType == 'ModbusTcpMasterVar':
# 仅设置值,不保存到数据库 res = self.modbusManager.writeModbusTcpMasterValue(info, value)
pass # print(res)
if res == 'error':
return
elif modelType == 'ModbusTcpSlaveVar': elif modelType == 'ModbusTcpSlaveVar':
# 仅设置值,不保存到数据库 res = self.modbusManager.writeModbusTcpSlaveValue(info, value)
pass if res == 'error':
return
elif modelType == 'ModbusRtuMasterVar': elif modelType == 'ModbusRtuMasterVar':
# 仅设置值,不保存到数据库 res = self.modbusManager.writeModbusRtuMasterValue(info, value)
pass if res == 'error':
return
elif modelType == 'ModbusRtuSlaveVar': elif modelType == 'ModbusRtuSlaveVar':
# 仅设置值,不保存到数据库 res = self.modbusManager.writeModbusRtuSlaveValue(info, value)
pass if res == 'error':
return
# HART协议变量处理 # HART协议变量处理
elif modelType == 'HartVar': elif modelType == 'HartVar':
# 仅设置值,不保存到数据库
pass pass
# 温度/RTD变量处理 # 温度/RTD变量处理
@ -173,40 +176,34 @@ class ProtocolManage(object):
compensationVar = float(info['compensationVar']) compensationVar = float(info['compensationVar'])
varModel = info['varModel'] varModel = info['varModel']
model = self.getModelType(varModel) if self.getModelType(varModel) else localModel model = self.getModelType(varModel) if self.getModelType(varModel) else localModel
# print(value + compensationVar)
if model == localModel: if model == localModel:
if varType == 'PT100': if varType == 'PT100':
self.writeRTD[channel] = value self.writeRTD[channel] = value
else: else:
self.writeTC[channel] = value self.writeTC[channel] = value
if varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A', 'PT100'] and model != SimModel: if varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A', 'PT100'] and model != SimModel:
value = temToMv(varType, value + compensationVar) # 直接补偿温度 补偿mv调整到括号外 value = temToMv(varType, value + compensationVar)
if trigger and varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']: if trigger and varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']:
trigger = TCTrigger trigger = TCTrigger
if trigger and varType in ['PT100']: if trigger and varType in ['PT100']:
trigger = RTDTrigger trigger = RTDTrigger
self.tcpVarManager.writeValue(varType, channel, value, trigger=trigger, model=model, timeoutMS=timeoutMS) self.tcpVarManager.writeValue(varType, channel, value, trigger=trigger, model=model, timeoutMS=timeoutMS)
# 模拟量变量处理 # 模拟量变量处理
elif modelType == 'AnalogVar': elif modelType == 'AnalogVar':
channel = int(info['channelNumber']) - 1 channel = int(info['channelNumber']) - 1
varType = info['varType'] varType = info['varType']
varModel = info['varModel'] varModel = info['varModel']
model = self.getModelType(varModel) if self.getModelType(varModel) else localModel model = self.getModelType(varModel) if self.getModelType(varModel) else localModel
if info['varType'] in ['AI','AO']: if info['varType'] in ['AI', 'AO']:
value = self.getRealAO(value, info['max'], info['min']) value = self.getRealAO(value, info['max'], info['min'])
trigger = FPGATrigger if trigger else trigger trigger = FPGATrigger if trigger else trigger
self.tcpVarManager.writeValue(varType, channel, value, trigger=trigger, model=model, timeoutMS=timeoutMS) self.tcpVarManager.writeValue(varType, channel, value, trigger=trigger, model=model, timeoutMS=timeoutMS)
# print(1)
# HART模拟变量处理 # HART模拟变量处理
elif modelType == 'HartSimulateVar': elif modelType == 'HartSimulateVar':
# 仅设置值,不保存到数据库
pass pass
if self.RpcClient: if self.RpcClient:
self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType']) self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType'])
return True return True
@ -224,12 +221,9 @@ class ProtocolManage(object):
time.sleep(interval) time.sleep(interval)
def getAllVariableNames(self): def getAllVariableNames(self):
# 直接从缓存获取所有变量名,降低与数据库模型的耦合
return list(self.varInfoCache.keys()) return list(self.varInfoCache.keys())
def _readVariableValueOriginal(self, variableName): def _readVariableValueOriginal(self, variableName):
# 完全保留原有读取逻辑
# print(12)
varInfo = self.lookupVariable(variableName) varInfo = self.lookupVariable(variableName)
value = None value = None
if not varInfo: if not varInfo:
@ -237,7 +231,6 @@ class ProtocolManage(object):
existsVar, clientNames = self.RpcServer.existsVar(variableName) existsVar, clientNames = self.RpcServer.existsVar(variableName)
if existsVar: if existsVar:
value = float(self.RpcServer.getVarValue(clientNames[0], variableName)['value']) value = float(self.RpcServer.getVarValue(clientNames[0], variableName)['value'])
# return value
else: else:
return None return None
return None return None
@ -246,13 +239,13 @@ class ProtocolManage(object):
try: try:
# 拆分为独立的协议条件判断 # 拆分为独立的协议条件判断
if modelType == 'ModbusTcpMasterVar': if modelType == 'ModbusTcpMasterVar':
pass value = self.modbusManager.readModbusTcpMasterValue(info)
elif modelType == 'ModbusTcpSlaveVar': elif modelType == 'ModbusTcpSlaveVar':
pass value = self.modbusManager.readModbusTcpSlaveValue(info)
elif modelType == 'ModbusRtuMasterVar': elif modelType == 'ModbusRtuMasterVar':
pass value = self.modbusManager.readModbusRtuMasterValue(info)
elif modelType == 'ModbusRtuSlaveVar': elif modelType == 'ModbusRtuSlaveVar':
pass value = self.modbusManager.readModbusRtuSlaveValue(info)
elif modelType == 'HartVar': elif modelType == 'HartVar':
pass pass
elif modelType == 'TcRtdVar': elif modelType == 'TcRtdVar':
@ -265,34 +258,25 @@ class ProtocolManage(object):
value = self.tcpVarManager.simRTDData[channel] value = self.tcpVarManager.simRTDData[channel]
elif varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']: elif varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']:
value = self.tcpVarManager.simTCData[channel] value = self.tcpVarManager.simTCData[channel]
# if self.RpcClient:
# self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType'])
# return value
else: else:
if varType == 'PT100': if varType == 'PT100':
value = self.writeRTD[channel] value = self.writeRTD[channel]
elif varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']: elif varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']:
value = self.writeTC[channel] value = self.writeTC[channel]
# if self.RpcClient:
# self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType'])
# return value
elif modelType == 'AnalogVar': elif modelType == 'AnalogVar':
channel = int(info['channelNumber']) - 1 channel = int(info['channelNumber']) - 1
varType = info['varType'] varType = info['varType']
varModel = info['varModel'] varModel = info['varModel']
model = self.getModelType(varModel) model = self.getModelType(varModel)
value = self.tcpVarManager.readValue(varType, channel, model=model) value = self.tcpVarManager.readValue(varType, channel, model=model)
if varType in ['AI','AO']: if varType in ['AI', 'AO']:
value = self.getRealAI(value, info['max'], info['min']) value = self.getRealAI(value, info['max'], info['min'])
# return value
elif modelType == 'HartSimulateVar': elif modelType == 'HartSimulateVar':
pass pass
if value is not None: if value is not None and value != 'error':
if self.RpcClient: if self.RpcClient:
self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType']) self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType'])
self.historyDBManage.writeVarValue(variableName, value) self.historyDBManage.writeVarValue(variableName, value)
# print('sucess')
return value return value
else: else:
return None return None
@ -301,56 +285,43 @@ class ProtocolManage(object):
return None return None
def readVariableValue(self, variableName): def readVariableValue(self, variableName):
# 优先从缓存读取,未命中则走原有逻辑
with self.cacheLock: with self.cacheLock:
if variableName in self.variableValueCache: if variableName in self.variableValueCache:
return self.variableValueCache[variableName] return self.variableValueCache[variableName]
return self._readVariableValueOriginal(variableName) return self._readVariableValueOriginal(variableName)
# def sendTrigger(self, variableName, value, timeoutMS):
# self.writeVariableValue(variableName, value, trigger=True, timeoutMS = timeoutMS)
def recvDeltaT(self): def recvDeltaT(self):
return self.tcpVarManager.recvDeltaT() return self.tcpVarManager.recvDeltaT()
def shutdown(self): def shutdown(self):
self.tcpVarManager.shutdown() self.tcpVarManager.shutdown()
# 关闭所有Modbus通讯
self.modbusManager.stopAllModbus()
# 关闭后台读取线程 # 关闭后台读取线程
if hasattr(self, 'readThreadStop') and hasattr(self, 'readThread'): if hasattr(self, 'readThreadStop') and hasattr(self, 'readThread'):
self.readThreadStop.set() self.readThreadStop.set()
self.readThread.join(timeout=1) self.readThread.join(timeout=1)
def getRealAO(self, value, highValue, lowValue):
def getRealAO(self, value,highValue, lowValue):
if highValue: if highValue:
lowValue = float(lowValue) lowValue = float(lowValue)
highValue = float(highValue) highValue = float(highValue)
return (16 * (value - lowValue) + 4 * (highValue-lowValue))/(1000 * (highValue - lowValue)) return (16 * (value - lowValue) + 4 * (highValue - lowValue)) / (1000 * (highValue - lowValue))
else: else:
return value/1000 return value / 1000
def getRealAI(self, mA, highValue, lowValue): def getRealAI(self, mA, highValue, lowValue):
""" """将毫安值转换为实际工程值getRealAO的反向计算"""
将毫安值转换为实际工程值getRealAO的反向计算
:param mA: 毫安值
:param highValue: 工程值上限
:param lowValue: 工程值下限
:return: 实际工程值
"""
try: try:
if highValue: if highValue:
lowValue = float(lowValue) lowValue = float(lowValue)
highValue = float(highValue) highValue = float(highValue)
# 反向计算: value = (1000 * mA * (highValue - lowValue) - 4*(highValue - lowValue)) / 16 + lowValue
return (1000 * mA * (highValue - lowValue) - 4 * (highValue - lowValue)) / 16.0 + lowValue return (1000 * mA * (highValue - lowValue) - 4 * (highValue - lowValue)) / 16.0 + lowValue
else: else:
return mA * 1000 return mA * 1000
except Exception as e: except Exception as e:
print(f"工程值转换失败: {str(e)}") print(f"工程值转换失败: {str(e)}")
return 0.0 # 默认返回0避免中断流程 return 0.0
def getModelType(self, varModel): def getModelType(self, varModel):
if varModel == '本地值': if varModel == '本地值':
@ -364,4 +335,52 @@ class ProtocolManage(object):
if self.RpcServer: if self.RpcServer:
self.RpcServer.removeClient(clientName) self.RpcServer.removeClient(clientName)
# ==================== Modbus 通讯管理方法(委托给 ModbusManager ====================
def startModbusTcpMaster(self):
"""启动 Modbus TCP 主站"""
return self.modbusManager.startModbusTcpMaster()
def stopModbusTcpMaster(self):
"""停止 Modbus TCP 主站"""
return self.modbusManager.stopModbusTcpMaster()
def startModbusRtuMaster(self):
"""启动 Modbus RTU 主站"""
return self.modbusManager.startModbusRtuMaster()
def stopModbusRtuMaster(self):
"""停止 Modbus RTU 主站"""
return self.modbusManager.stopModbusRtuMaster()
def startModbusTcpSlave(self):
"""启动 Modbus TCP 从站"""
return self.modbusManager.startModbusTcpSlave()
def stopModbusTcpSlave(self):
"""停止 Modbus TCP 从站"""
return self.modbusManager.stopModbusTcpSlave()
def startModbusRtuSlave(self):
"""启动 Modbus RTU 从站"""
return self.modbusManager.startModbusRtuSlave()
def stopModbusRtuSlave(self):
"""停止 Modbus RTU 从站"""
return self.modbusManager.stopModbusRtuSlave()
def stopAllModbus(self):
"""停止所有 Modbus 通讯"""
return self.modbusManager.stopAllModbus()
def getModbusStatus(self):
"""获取所有 Modbus 通讯状态"""
return self.modbusManager.getModbusStatus()
def getModbusMessages(self):
"""获取 Modbus 报文信息"""
return self.modbusManager.getMessages()
def clearModbusMessages(self):
"""清空 Modbus 报文记录"""
self.modbusManager.clearMessages()

@ -7,9 +7,9 @@ class InitParameterDB():
self.writeUnitParameter() self.writeUnitParameter()
def writeParameter(self) -> None: def writeParameter(self) -> None:
blockNames = pd.ExcelFile('static/PA块信息表.xlsx').sheet_names blockNames = pd.ExcelFile('Static/PA块信息表.xlsx').sheet_names
for blockName in blockNames: for blockName in blockNames:
parameters = pd.read_excel('static/PA块信息表.xlsx', sheet_name = str(blockName)) parameters = pd.read_excel('Static/PA块信息表.xlsx', sheet_name = str(blockName))
for index, row in parameters.iterrows(): for index, row in parameters.iterrows():
parameter = row.values parameter = row.values
@ -19,7 +19,7 @@ class InitParameterDB():
saveType = parameter[4], dataSize = parameter[5], accessType = parameter[6], transferType = parameter[7], description = parameter[8]) saveType = parameter[4], dataSize = parameter[5], accessType = parameter[6], transferType = parameter[7], description = parameter[8])
def writeUnitParameter(self): def writeUnitParameter(self):
parameters = pd.read_excel('static/UnitTable.xlsx', sheet_name = 'UnitTable') parameters = pd.read_excel('Static/UnitTable.xlsx', sheet_name = 'UnitTable')
for index, row in parameters.iterrows(): for index, row in parameters.iterrows():
parameter = row.values parameter = row.values
clsblockName = UnitTable() clsblockName = UnitTable()

Loading…
Cancel
Save