1110更新 添加全局配置功能 添加HART模拟功能

main
DESKTOP-3D7M4SA\Hicent 4 weeks ago
parent 6b7deb84ef
commit a5a31fa623

@ -14,6 +14,7 @@ from ctypes.wintypes import MSG
from win32 import win32api, win32gui from win32 import win32api, win32gui
from win32.lib import win32con from win32.lib import win32con
from model.ProjectModel.VarManage import GlobalVarManager from model.ProjectModel.VarManage import GlobalVarManager
from model.ProjectModel.GlobalConfigManager import GlobalConfigManager
from UI.Main.MainLeft import MainLeft from UI.Main.MainLeft import MainLeft
from UI.Main.MainTop import MainTop from UI.Main.MainTop import MainTop
from ..ProjectManages.ProjectWidget import ProjectWidgets from ..ProjectManages.ProjectWidget import ProjectWidgets
@ -144,55 +145,117 @@ class MainWindow(QMainWindow):
# 添加圆角QSS # 添加圆角QSS
# self.centralwidget.setStyleSheet("") # self.centralwidget.setStyleSheet("")
def createWidgets(self): def createWidgets(self):
self.ModbusTcpMasterWidget = VarWidgets('ModbusTcpMaster') # 创建固定的widgets非变量管理相关
self.ModbusTcpSlaveWidget = VarWidgets('ModbusTcpSlave')
self.ModbusRtuMasterWidget = VarWidgets('ModbusRtuMaster')
self.ModbusRtuSlaveWidget = VarWidgets('ModbusRtuSlave')
self.userWidget = UserWidgets() self.userWidget = UserWidgets()
self.procedureManagerWidget = ProcedureManager() self.procedureManagerWidget = ProcedureManager()
self.controlWidget = getControlWidget() self.controlWidget = getControlWidget()
modbusWidgetList = [self.ModbusTcpMasterWidget, self.ModbusTcpSlaveWidget, self.ModbusRtuMasterWidget, self.ModbusRtuSlaveWidget]
modbusNameList = ['MODBUSTCP主站', 'MODBUSTCP从站', 'MODBUSRTU主站', 'MODBUSRTU从站',]
self.profibusWidget = ProfibusWidgets()
self.trendWidget = TrendWidgets() self.trendWidget = TrendWidgets()
self.SettingWidget = SettingWidget() self.SettingWidget = SettingWidget()
self.hartWidget = HartMainWindow()
self.tcrtdWidget = TcRtdWidgets()
self.analogWidget = AnalogWidgets()
self.hartsimulateWidget = HartSimulateWidgets()
self.rpcVarTableWidget = RpcVarTableView()
# 设置固定widgets的对象名
self.userWidget.setObjectName('userWidget') self.userWidget.setObjectName('userWidget')
self.projectWidget.setObjectName('projectWidget') self.projectWidget.setObjectName('projectWidget')
self.trendWidget.setObjectName('trendWidget') self.trendWidget.setObjectName('trendWidget')
self.hartWidget.setObjectName('hartWidget')
# self.ModBusWidget.setObjectName('varWidget')
self.analogWidget.setObjectName('analogWidget')
self.hartsimulateWidget.setObjectName('hartsimulateWidget')
# 创建变量管理标签页容器
self.varManageTabWidget = QTabWidget() self.varManageTabWidget = QTabWidget()
self.varManageTabWidget.setObjectName("varManageTabWidget") self.varManageTabWidget.setObjectName("varManageTabWidget")
self.varManageTabWidget.tabBar().setObjectName('varManageTabBar') self.varManageTabWidget.tabBar().setObjectName('varManageTabBar')
for widget, name in zip(modbusWidgetList, modbusNameList):
widget.setObjectName('varWidget')
self.varManageTabWidget.addTab(widget, name)
self.varManageTabWidget.addTab(self.analogWidget,'IO')
self.varManageTabWidget.addTab(self.tcrtdWidget,'TCRTD')
self.varManageTabWidget.addTab(self.hartWidget,'HART读取')
self.varManageTabWidget.addTab(self.hartsimulateWidget,'HART模拟')
self.varManageTabWidget.addTab(self.profibusWidget,'PROFIBUS')
self.varManageTabWidget.addTab(self.rpcVarTableWidget, '远程通讯')
self.varManageTabWidget.setCornerWidget(self.importVarButton) self.varManageTabWidget.setCornerWidget(self.importVarButton)
# 初始化变量管理widgets字典
self.varWidgets = {}
# 为QTabWidget添加updateTabs方法
self.varManageTabWidget.updateTabs = self.updateVarTabs
# 根据全局配置动态创建变量管理tabs
self.createDynamicVarTabs()
def createDynamicVarTabs(self):
"""根据全局配置动态创建变量管理标签页"""
try:
# 清空现有tabs
self.varManageTabWidget.clear()
self.varWidgets.clear()
# 获取全局配置
globalConfig = GlobalConfigManager.loadGlobalConfig()
variableModules = globalConfig.get('variableModules', {})
# 遍历所有可用模块,只创建启用的模块
for moduleKey, enabled in variableModules.items():
if enabled:
# 获取模块显示名称
displayName = GlobalConfigManager.getModuleDisplayName(moduleKey)
# 获取模块对应的Widget类
widgetClass = GlobalConfigManager.getModuleWidgetClass(moduleKey)
if widgetClass:
# 创建widget实例
widget = widgetClass()
# 设置对象名
if hasattr(widget, 'setObjectName'):
if moduleKey.startswith('modbus'):
widget.setObjectName('varWidget')
elif moduleKey == 'ioModule':
widget.setObjectName('analogWidget')
elif moduleKey == 'hartSimulateModule':
widget.setObjectName('hartsimulateWidget')
elif moduleKey == 'hartReadModule':
widget.setObjectName('hartWidget')
else:
widget.setObjectName(f'{moduleKey}Widget')
# 添加到标签页
self.varManageTabWidget.addTab(widget, displayName)
# 保存widget引用
self.varWidgets[moduleKey] = widget
except Exception as e:
print(f"创建动态变量管理标签页失败: {e}")
# 如果出错,创建默认的标签页
self.createDefaultVarTabs()
def createDefaultVarTabs(self):
"""创建默认的变量管理标签页(兼容性备用方案)"""
try:
# 创建默认widgets
defaultWidgets = [
(VarWidgets('ModbusTcpMaster'), 'MODBUSTCP主站'),
(VarWidgets('ModbusTcpSlave'), 'MODBUSTCP从站'),
(VarWidgets('ModbusRtuMaster'), 'MODBUSRTU主站'),
(VarWidgets('ModbusRtuSlave'), 'MODBUSRTU从站'),
(AnalogWidgets(), 'IO'),
(TcRtdWidgets(), 'TCRTD'),
(HartMainWindow(), 'HART读取'),
(HartSimulateWidgets(), 'HART模拟'),
(ProfibusWidgets(), 'PROFIBUS'),
(RpcVarTableView(), '远程通讯')
]
for widget, name in defaultWidgets:
if hasattr(widget, 'setObjectName'):
if 'Modbus' in name:
widget.setObjectName('varWidget')
elif name == 'IO':
widget.setObjectName('analogWidget')
elif name == 'HART模拟':
widget.setObjectName('hartsimulateWidget')
elif name == 'HART读取':
widget.setObjectName('hartWidget')
self.varManageTabWidget.addTab(widget, name)
except Exception as e:
print(f"创建默认变量管理标签页失败: {e}")
def updateVarTabs(self, globalConfig=None):
"""更新变量管理标签页(供外部调用)"""
self.createDynamicVarTabs()
self.rightWidget.addWidget(self.varManageTabWidget) self.rightWidget.addWidget(self.varManageTabWidget)
self.rightWidget.addWidget(self.trendWidget) self.rightWidget.addWidget(self.trendWidget)

@ -30,6 +30,7 @@ class AreaTabWidget(QTabWidget):
def initUI(self): def initUI(self):
self.deviceName = self.deviceWidget.deviceName self.deviceName = self.deviceWidget.deviceName
print(1231421)
# 创建一个 QTabWidget # 创建一个 QTabWidget
self.setObjectName('areaTabWidget') self.setObjectName('areaTabWidget')
self.setTabPosition(QTabWidget.South) self.setTabPosition(QTabWidget.South)

@ -116,7 +116,7 @@ class EditAddressWidget(QDialog):
self.setWindowOpacity(0.995) # 设置窗口透明度 self.setWindowOpacity(0.995) # 设置窗口透明度
self.setWindowFlag(Qt.FramelessWindowHint) self.setWindowFlag(Qt.FramelessWindowHint)
self.DPV1Master = DPV1Master('192.168.3.10', 502) self.DPV1Master = DPV1Master('192.168.4.38', 502)
self.exec_() self.exec_()
# def changeDeviceType(self, index): # def changeDeviceType(self, index):

@ -76,7 +76,7 @@ class ProfibusWidgets(QWidget):
self.setObjectName("MainWindow") self.setObjectName("MainWindow")
self.devicesManange = DevicesManange() self.devicesManange = DevicesManange()
# self.batteryManange = BatteryManange() # self.batteryManange = BatteryManange()
self.dpv1Master = DPV1Master('192.168.3.10', 502) self.dpv1Master = DPV1Master('192.168.4.38', 502)
self.blockParameterManageWidget = BlockParameterManageWidget() self.blockParameterManageWidget = BlockParameterManageWidget()
self.process = None self.process = None
# Globals.setValue('ProfibusWindow', self) # Globals.setValue('ProfibusWindow', self)
@ -92,7 +92,7 @@ class ProfibusWidgets(QWidget):
self.searchAddressTimer = QTimer() self.searchAddressTimer = QTimer()
self.searchAddressTimer.timeout.connect(self.searchSlave) self.searchAddressTimer.timeout.connect(self.searchSlave)
# self.searchAddressTimer.start(1000) self.searchAddressTimer.start(1000)
# self.searchAddressTimer.start(10000) # self.searchAddressTimer.start(10000)
# self.toolbarWidget = QWidget() # self.toolbarWidget = QWidget()
@ -297,7 +297,7 @@ class ProfibusWidgets(QWidget):
def searchSlave(self): def searchSlave(self):
address = self.dpv1Master.searchSlave() address = self.dpv1Master.searchSlave()
if address == '读取错误': if address == '读取错误':
self.dpv1Master = DPV1Master('192.168.3.10', 502) self.dpv1Master = DPV1Master('192.168.4.38', 502)
self.addressLabel.setText('在线仪表地址:') self.addressLabel.setText('在线仪表地址:')
self.addressLabel.setText('在线仪表地址:{}'.format(address)) self.addressLabel.setText('在线仪表地址:{}'.format(address))
@ -312,7 +312,7 @@ class ProfibusWidgets(QWidget):
startupInfo = subprocess.STARTUPINFO() startupInfo = subprocess.STARTUPINFO()
startupInfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW startupInfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupInfo.wShowWindow = 2 startupInfo.wShowWindow = 2
self.process = subprocess.Popen("D:\\EnTalk PROFIBUS Manager\\DP.exe",startupinfo=startupInfo) self.process = subprocess.Popen("C:\\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'))

@ -57,7 +57,7 @@ class SearchAddressWidget(QWidget):
self.setLayout(self.mainlayout) self.setLayout(self.mainlayout)
self.setWindowTitle('从站地址查找') self.setWindowTitle('从站地址查找')
self.DPV1Master = DPV1Master('192.168.3.10', 502) self.DPV1Master = DPV1Master('192.168.4.38', 502)
self.DPV1Master.searchSlave(self.updateProgress) self.DPV1Master.searchSlave(self.updateProgress)
self.cancelBtn.clicked.connect(self.close) self.cancelBtn.clicked.connect(self.close)
# self.timer = QTimer() # self.timer = QTimer()

@ -5,6 +5,7 @@ from PyQt5 import QtGui,QtCore,QtWidgets
from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt, QVariant, QSize from PyQt5.QtCore import QAbstractTableModel, QModelIndex, Qt, QVariant, QSize
from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget,QMessageBox from PyQt5.QtWidgets import QItemDelegate, QHBoxLayout, QWidget,QMessageBox
from model.ProjectModel.ProjectManage import ProjectManage from model.ProjectModel.ProjectManage import ProjectManage
from model.ProjectModel.GlobalConfigManager import GlobalConfigManager
from ..LoginWidgets.LoginWidget import LoginWidget from ..LoginWidgets.LoginWidget import LoginWidget
from utils import Globals from utils import Globals
@ -264,12 +265,17 @@ class ProjectButtonDelegate(QItemDelegate):
Globals.getValue('MainWindows').delecteWidget() Globals.getValue('MainWindows').delecteWidget()
Globals.getValue('MainWindows').createWidgets() Globals.getValue('MainWindows').createWidgets()
modelLists = ['ModbusTcpMasterTable', 'ModbusTcpSlaveTable', 'ModbusRtuMasterTable', \ # 根据全局配置获取启用的模型表列表
'ModbusRtuSlaveTable', 'TcRtdTable', 'AnalogTable', 'HartSimulateTable', 'userTable'] modelLists = GlobalConfigManager.getEnabledModelTables()
for l in modelLists: for l in modelLists:
# print(l) # print(l)
Globals.getValue(l).model.initTable() try:
QtWidgets.QApplication.processEvents() model_table = Globals.getValue(l)
if model_table and hasattr(model_table, 'model') and hasattr(model_table.model, 'initTable'):
model_table.model.initTable()
QtWidgets.QApplication.processEvents()
except Exception as e:
print(f"初始化模型表 {l} 失败: {e}")
Globals.clearValue('forceVars')#清除颜色 Globals.clearValue('forceVars')#清除颜色

@ -284,3 +284,5 @@ class ProjectWidgets(QtWidgets.QWidget):
proMes = ProjectManage.getByName(name) proMes = ProjectManage.getByName(name)
proMes.append('') proMes.append('')
self.projectView.model.append_data(proMes) self.projectView.model.append_data(proMes)

@ -216,6 +216,7 @@ class HartSimulateButtonDelegate(BaseButtonDelegate):
minSpan = model.datas[source_row][7] minSpan = model.datas[source_row][7]
maxSpan = model.datas[source_row][8] maxSpan = model.datas[source_row][8]
writeList = [str(x) for x in model.datas[source_row][3:9]] writeList = [str(x) for x in model.datas[source_row][3:9]]
# print(writeList)
pattern = re.compile(r'[^0-9\.-]+') pattern = re.compile(r'[^0-9\.-]+')
if minSpan and maxSpan and value1 and not re.findall(pattern, str(value1) + str(minSpan) + str(maxSpan)): if minSpan and maxSpan and value1 and not re.findall(pattern, str(value1) + str(minSpan) + str(maxSpan)):
if float(value1) < float(minSpan) or float(value1) > float(maxSpan): if float(value1) < float(minSpan) or float(value1) > float(maxSpan):
@ -226,21 +227,44 @@ class HartSimulateButtonDelegate(BaseButtonDelegate):
return return
for index, value in enumerate(writeList): for index, value in enumerate(writeList):
if re.findall(pattern, value): if re.findall(pattern, value):
print(value)
reply = QMessageBox.question(self.parent(), reply = QMessageBox.question(self.parent(),
'警告', '警告',
"请输入强制值或数字", "请输入强制值或数字",
QMessageBox.Yes) QMessageBox.Yes)
return return
try: try:
self.parent().workThread.HartSimulate.writeValue(index, value) # 使用HART RTU从站功能写入变量值
except: protocolManage = Globals.getValue('protocolManage')
reply = QMessageBox.question(self.parent(), print(protocolManage,protocolManage.hartRtuSlaveManager)
'警告', if not protocolManage or not protocolManage.hartRtuSlaveManager:
"请先打开通讯", return
QMessageBox.Yes)
return # 检查value是否为空或无效
if not value or str(value).strip() == '':
# print(f"HART变量{index}的值为空,跳过写入")
continue
try:
floatValue = float(value)
except (ValueError, TypeError):
print(f"HART变量{index}的值'{value}'无法转换为浮点数")
return
# 根据索引写入对应的变量
if index == 0: # 主变量
protocolManage.writeHartVariable('primaryVariable', floatValue)
# print(floatValue, 111)
elif index == 1: # 动态变量1
protocolManage.writeHartVariable('dynamicVariable1', floatValue)
elif index == 2: # 动态变量2
protocolManage.writeHartVariable('dynamicVariable2', floatValue)
elif index == 3: # 动态变量3
protocolManage.writeHartVariable('dynamicVariable3', floatValue)
# print('1111', floatValue)
except Exception as e:
print(f"写入HART变量失败: {e}")
forceVars = Globals.getValue('forceVars') forceVars = Globals.getValue('forceVars')
forceVars.add(model.datas[source_row][1]) forceVars.add(model.datas[source_row][1])
Globals.setValue('forceVars', forceVars) Globals.setValue('forceVars', forceVars)

@ -750,10 +750,10 @@ class HartSimulateWidgets(VarWidgets):
def setupUI(self): def setupUI(self):
self.setAttribute(Qt.WA_StyledBackground, True) self.setAttribute(Qt.WA_StyledBackground, True)
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)
self.varView = HartSimulateTableView() self.varView = HartSimulateTableView()
self.varView.setObjectName('varView') self.varView.setObjectName('varView')
@ -771,8 +771,23 @@ class HartSimulateWidgets(VarWidgets):
Globals.setValue('HartSimulateTable', self.varView) Globals.setValue('HartSimulateTable', self.varView)
# 添加HART RTU从站控制按钮
self.startProtocolBtn = QPushButton('启动HART RTU从站')
self.startProtocolBtn.setObjectName('startProtocolBtn')
self.startProtocolBtn.clicked.connect(self.startProtocol)
self.stopProtocolBtn = QPushButton('停止HART RTU从站')
self.stopProtocolBtn.setObjectName('stopProtocolBtn')
self.stopProtocolBtn.clicked.connect(self.stopProtocol)
# 创建按钮布局
self.buttonLayout = QtWidgets.QHBoxLayout()
self.buttonLayout.addWidget(self.startProtocolBtn)
self.buttonLayout.addWidget(self.stopProtocolBtn)
self.buttonLayout.addStretch() # 添加弹性空间
self.gridLayout = QtWidgets.QGridLayout(self) self.gridLayout = QtWidgets.QGridLayout(self)
self.gridLayout.addWidget(self.startProtocolBtn, 0, 0, 1, 1) self.gridLayout.addLayout(self.buttonLayout, 0, 0, 1, 26)
self.gridLayout.addWidget(self.varView, 1, 0, 10, 26) self.gridLayout.addWidget(self.varView, 1, 0, 10, 26)
self.gridLayout.setSpacing(20) self.gridLayout.setSpacing(20)
self.gridLayout.setContentsMargins(20, 30, 20, 20) self.gridLayout.setContentsMargins(20, 30, 20, 20)
@ -780,4 +795,23 @@ class HartSimulateWidgets(VarWidgets):
self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked) self.horizontalHeader.sectionClicked.connect(self.on_view_horizontalHeader_sectionClicked)
def startProtocol(self): def startProtocol(self):
pass """启动HART RTU从站"""
try:
protocolManage = Globals.getValue('protocolManage')
if protocolManage and protocolManage.hartRtuSlaveManager:
if protocolManage.startHartRtuSlave():
QMessageBox.information(self, '信息', 'HART RTU从站启动成功')
else:
QMessageBox.warning(self, '警告', 'HART RTU从站启动失败')
except Exception as e:
QMessageBox.critical(self, '错误', f'启动HART RTU从站时出错: {str(e)}')
def stopProtocol(self):
"""停止HART RTU从站"""
try:
protocolManage = Globals.getValue('protocolManage')
if protocolManage and protocolManage.hartRtuSlaveManager:
protocolManage.stopHartRtuSlave()
QMessageBox.information(self, '信息', 'HART RTU从站已停止')
except Exception as e:
QMessageBox.critical(self, '错误', f'停止HART RTU从站时出错: {str(e)}')

@ -65,8 +65,8 @@ class BlockManage():
@property @property
def DPV1Master(self): def DPV1Master(self):
if not self._dpv1MasterPA or not self._dpv1MasterDP: if not self._dpv1MasterPA or not self._dpv1MasterDP:
self._dpv1MasterPA = DPV1Master('192.168.3.10', 502) self._dpv1MasterPA = DPV1Master('192.168.4.38', 502)
self._dpv1MasterDP = DPV1Master('192.168.1.10', 502) self._dpv1MasterDP = DPV1Master('192.168.4.8', 502)
if self._isPa: if self._isPa:
return self._dpv1MasterPA return self._dpv1MasterPA
else: else:

@ -194,10 +194,10 @@ class DevicesManange():
self.paMasterDevices = collections.OrderedDict() self.paMasterDevices = collections.OrderedDict()
self.paSlaveDevices = collections.OrderedDict() self.paSlaveDevices = collections.OrderedDict()
def connect(self): def connect(self):
self.dpSlaveModbus = TcpMaster(host = '192.168.2.10', port = 502) self.dpSlaveModbus = TcpMaster(host = '192.168.4.18', port = 502)
self.paSlaveModbus = TcpMaster(host = '192.168.4.10', port = 502) self.paSlaveModbus = TcpMaster(host = '192.168.4.48', port = 502)
self.dpMasterModbus = TcpMaster(host = '192.168.1.10', port = 502) self.dpMasterModbus = TcpMaster(host = '192.168.4.8', port = 502)
self.paMasterModbus = TcpMaster(host = '192.168.3.10', port = 502) self.paMasterModbus = TcpMaster(host = '192.168.4.38', port = 502)
@ -287,9 +287,10 @@ class DevicesManange():
area.qualityValueList = qualityValueList area.qualityValueList = qualityValueList
if area.type in ['DO', 'DI'] and device.type == 'PA': if area.type in ['DO', 'DI'] and device.type == 'PA':
area.forceValue = values[8:] + values[:8] area.forceValue = values[8:] + values[:8]
elif area.type in ['DO', 'DI'] and device.type == 'DP' and device.masterOrSlave == "从站":
area.forceValue = values[8:] + values[:8]
elif area.type in ['DO', 'DI'] and device.type == 'DP' and device.masterOrSlave == "主站": elif area.type in ['DO', 'DI'] and device.type == 'DP' and device.masterOrSlave == "主站":
area.forceValue = values[8:] + values[:8] area.forceValue = values[8:] + values[:8]
for device in curProDict.values(): for device in curProDict.values():
forceAreas = device.outputAreas if device.masterOrSlave == "主站" else device.inputAreas forceAreas = device.outputAreas if device.masterOrSlave == "主站" else device.inputAreas
for area in forceAreas: for area in forceAreas:
@ -308,7 +309,7 @@ class DevicesManange():
# print(bytes) # print(bytes)
# print(bytes) # print(bytes)
values = struct.unpack('!' + 'H' * int(len(bytes) / 2), bytes) values = struct.unpack('!' + 'H' * int(len(bytes) / 2), bytes)
modbusM.writeMultipleRegister(slaveId = 1, address = 0, outputValue = values) modbusM.writeMultipleRegisters(slaveId = 1, startAddress = 0, outputValues = values)
# print(struct.unpack('>f', struct.pack('!HH', *values[:2]))) # print(struct.unpack('>f', struct.pack('!HH', *values[:2])))
def readAreas(self): def readAreas(self):
@ -336,7 +337,8 @@ class DevicesManange():
intNums = int(bytesNums / 2) if bytesNums % 2 == 0 else int(bytesNums / 2) + 1 intNums = int(bytesNums / 2) if bytesNums % 2 == 0 else int(bytesNums / 2) + 1
if bytesNums == 0: if bytesNums == 0:
continue continue
intValues = modbusM.readHoldingRegisters(slaveId = 1, startAddress = 0, varNums = intNums) intValues = modbusM.readHoldingRegisters(slaveId = 1, startAddress = 0, varNums = intNums, order = 'Profibus')
print(intValues, index)
if intValues == 'error': if intValues == 'error':
self.connect() self.connect()
return return
@ -366,10 +368,10 @@ class DevicesManange():
# print(area.qualityValueList) # print(area.qualityValueList)
# print(round(struct.unpack('!f', reorderBytes(byte, area.order))[0], 4)) # print(round(struct.unpack('!f', reorderBytes(byte, area.order))[0], 4))
elif area.type in ['DI', 'DO']: elif area.type in ['DI', 'DO']:
if device.masterOrSlave == '主站' and device.type == 'DP': # if device.masterOrSlave == '主站' and device.type == 'DP':
bytes = bytes # bytes = bytes
else: # else:
bytes = bytes[::-1] bytes = bytes[::-1]
area.currentValue = bytesToCoils(bytes) area.currentValue = bytesToCoils(bytes)
# print(area.currentValue, device.deviceName, area.startAddress,area.endAddress) # print(area.currentValue, device.deviceName, area.startAddress,area.endAddress)
# print() # print()

@ -0,0 +1,185 @@
import os
import json
from utils import Globals
class GlobalConfigManager:
"""全局配置管理器 - 所有工程使用统一配置"""
CONFIG_FILE = 'Static/global_config.json'
@classmethod
def loadGlobalConfig(cls):
"""加载全局配置文件"""
try:
with open(cls.CONFIG_FILE, 'r', encoding='utf-8') as f:
data = json.load(f)
return data.get('globalConfig', cls.getDefaultConfig())
except Exception as e:
print(f"加载全局配置文件失败: {e}")
return cls.getDefaultConfig()
@classmethod
def getDefaultConfig(cls):
"""获取默认配置(当配置文件不存在时使用)"""
return {
"name": "默认全局配置",
"description": "所有工程统一使用的默认配置",
"variableModules": {
"modbusTcpMaster": True,
"modbusTcpSlave": True,
"modbusRtuMaster": True,
"modbusRtuSlave": True,
"ioModule": True,
"tcRtdModule": True,
"hartReadModule": True,
"hartSimulateModule": True,
"profibusModule": True,
"rpcModule": True
}
}
@classmethod
def saveGlobalConfig(cls, config):
"""保存全局配置文件"""
try:
data = {"globalConfig": config}
with open(cls.CONFIG_FILE, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
return True
except Exception as e:
print(f"保存全局配置文件失败: {e}")
return False
@classmethod
def getModuleDisplayName(cls, moduleKey):
"""获取模块显示名称"""
displayNames = {
'modbusTcpMaster': 'MODBUSTCP主站',
'modbusTcpSlave': 'MODBUSTCP从站',
'modbusRtuMaster': 'MODBUSRTU主站',
'modbusRtuSlave': 'MODBUSRTU从站',
'ioModule': 'IO模块',
'tcRtdModule': 'TCRTD模块',
'hartReadModule': 'HART读取模块',
'hartSimulateModule': 'HART模拟模块',
'profibusModule': 'PROFIBUS模块',
'rpcModule': '远程通讯模块'
}
return displayNames.get(moduleKey, moduleKey)
@classmethod
def getModuleWidgetClass(cls, moduleKey):
"""获取模块对应的Widget类"""
from UI.VarManages.VarWidget import VarWidgets, TcRtdWidgets, AnalogWidgets, HartSimulateWidgets
from UI.HartWidgets.HartMainWindow import HartMainWindow
from UI.VarManages.VarTable import RpcVarTableView
from UI.ProfibusWidgets.ProfibusWindow import ProfibusWidgets
widgetClasses = {
'modbusTcpMaster': lambda: VarWidgets('ModbusTcpMaster'),
'modbusTcpSlave': lambda: VarWidgets('ModbusTcpSlave'),
'modbusRtuMaster': lambda: VarWidgets('ModbusRtuMaster'),
'modbusRtuSlave': lambda: VarWidgets('ModbusRtuSlave'),
'ioModule': AnalogWidgets,
'tcRtdModule': TcRtdWidgets,
'hartReadModule': HartMainWindow,
'hartSimulateModule': HartSimulateWidgets,
'profibusModule': ProfibusWidgets,
'rpcModule': RpcVarTableView
}
return widgetClasses.get(moduleKey)
@classmethod
def getEnabledModules(cls):
"""获取启用的模块列表"""
config = cls.loadGlobalConfig()
variableModules = config.get('variableModules', {})
return [moduleKey for moduleKey, enabled in variableModules.items() if enabled]
@classmethod
def isModuleEnabled(cls, moduleKey):
"""检查模块是否启用"""
config = cls.loadGlobalConfig()
variableModules = config.get('variableModules', {})
return variableModules.get(moduleKey, False)
@classmethod
def getEnabledModelTables(cls):
"""获取启用模块对应的模型表列表"""
config = cls.loadGlobalConfig()
variableModules = config.get('variableModules', {})
# 模块与模型表的映射关系
moduleToModelMapping = {
'modbusTcpMaster': 'ModbusTcpMasterTable',
'modbusTcpSlave': 'ModbusTcpSlaveTable',
'modbusRtuMaster': 'ModbusRtuMasterTable',
'modbusRtuSlave': 'ModbusRtuSlaveTable',
'tcRtdModule': 'TcRtdTable',
'ioModule': 'AnalogTable',
'hartSimulateModule': 'HartSimulateTable'
# 注意userTable 不在变量管理模块中,始终需要初始化
# hartReadModule 和 profibusModule 可能没有对应的表模型
# rpcModule 可能也没有对应的表模型
}
enabledTables = []
# 添加启用模块对应的表
for moduleKey, enabled in variableModules.items():
if enabled and moduleKey in moduleToModelMapping:
enabledTables.append(moduleToModelMapping[moduleKey])
# 始终添加用户表(非变量管理模块)
enabledTables.append('userTable')
return enabledTables
@classmethod
def getEnabledModelClasses(cls):
"""获取启用模块对应的数据库模型类列表"""
from utils.DBModels.ProtocolModel import (
ModbusTcpMasterVar, ModbusTcpSlaveVar, ModbusRtuMasterVar, ModbusRtuSlaveVar,
HartVar, TcRtdVar, AnalogVar, HartSimulateVar
)
config = cls.loadGlobalConfig()
variableModules = config.get('variableModules', {})
# 模块与数据库模型类的映射关系
moduleToModelClassMapping = {
'modbusTcpMaster': ModbusTcpMasterVar,
'modbusTcpSlave': ModbusTcpSlaveVar,
'modbusRtuMaster': ModbusRtuMasterVar,
'modbusRtuSlave': ModbusRtuSlaveVar,
'hartReadModule': HartVar,
'tcRtdModule': TcRtdVar,
'ioModule': AnalogVar,
'hartSimulateModule': HartSimulateVar
}
enabledModelClasses = []
# 添加启用模块对应的模型类
for moduleKey, enabled in variableModules.items():
if enabled and moduleKey in moduleToModelClassMapping:
enabledModelClasses.append(moduleToModelClassMapping[moduleKey])
return enabledModelClasses
@classmethod
def needsTcpVarManager(cls):
"""检查是否需要初始化TCPVarManager当启用IO或TCRTD模块时"""
config = cls.loadGlobalConfig()
variableModules = config.get('variableModules', {})
# TCPVarManager相关的模块
tcpVarModules = ['ioModule', 'tcRtdModule']
# 检查是否有任何相关模块被启用
for moduleKey in tcpVarModules:
if variableModules.get(moduleKey, False):
return True
return False

@ -17,6 +17,7 @@ from model.ClientModel.Client import Client
from model.HistoryDBModel.HistoryDBManage import HistoryDBManage from model.HistoryDBModel.HistoryDBManage import HistoryDBManage
from model.ProjectModel.VarManage import TcRtdManage, AnalogManage, HartVarManage, \ from model.ProjectModel.VarManage import TcRtdManage, AnalogManage, HartVarManage, \
HartSimulateVarManage HartSimulateVarManage
from model.ProjectModel.GlobalConfigManager import GlobalConfigManager
from model.UserModel.UserManage import UserManage from model.UserModel.UserManage import UserManage
from utils import Globals from utils import Globals
@ -50,8 +51,8 @@ class ProjectManage(object):
os.mkdir(os.path.join('project', name, 'config')) os.mkdir(os.path.join('project', name, 'config'))
os.mkdir(os.path.join('project', name, 'log')) os.mkdir(os.path.join('project', name, 'log'))
with open(os.path.join('project', name, 'config', 'config.json'), 'w') as f: # with open(os.path.join('project', name, 'config', 'config.json'), 'w') as f:
json.dump({'description' : des}, f) # json.dump({'description': des}, f)
project = Project() project = Project()
project.createProject(name, des) project.createProject(name, des)
@ -146,6 +147,10 @@ class ProjectManage(object):
Globals.setValue('currentProDB', projectDB) Globals.setValue('currentProDB', projectDB)
Globals.setValue('currentProType', 1)#切换工程 Globals.setValue('currentProType', 1)#切换工程
# 加载全局配置
globalConfig = GlobalConfigManager.loadGlobalConfig()
Globals.setValue('currentProjectConfig', globalConfig)
histroyTableName = 'p' + name histroyTableName = 'p' + name
historyDBManage = HistoryDBManage(table=histroyTableName) historyDBManage = HistoryDBManage(table=histroyTableName)
Globals.setValue('historyDBManage', historyDBManage) Globals.setValue('historyDBManage', historyDBManage)
@ -162,6 +167,10 @@ class ProjectManage(object):
Globals.getValue('HistoryWidget').exchangeProject() Globals.getValue('HistoryWidget').exchangeProject()
Globals.getValue('MainWindow').procedureManagerWidget.initDB() Globals.getValue('MainWindow').procedureManagerWidget.initDB()
Globals.getValue('MainWindow').procedureManagerWidget.initUI() Globals.getValue('MainWindow').procedureManagerWidget.initUI()
# 根据全局配置动态更新变量管理界面
self.updateDynamicVarWidgets(globalConfig)
# 通知控制系统工程已切换 # 通知控制系统工程已切换
try: try:
from control.ControlManager import getControlManager from control.ControlManager import getControlManager
@ -322,6 +331,24 @@ class ProjectManage(object):
os.rename(os.path.join('project', name), os.path.join('project', Nname)) os.rename(os.path.join('project', name), os.path.join('project', Nname))
self.switchProject(Nname) self.switchProject(Nname)
@classmethod
def updateDynamicVarWidgets(self, globalConfig):
"""根据全局配置动态更新变量管理界面"""
try:
mainWindow = Globals.getValue('MainWindows')
if not mainWindow:
return
# 获取变量管理标签页
varManageTabWidget = mainWindow.varManageTabWidget
if not hasattr(varManageTabWidget, 'updateTabs'):
return
# 更新标签页
varManageTabWidget.updateTabs(globalConfig)
except Exception as e:
print(f"更新动态变量管理界面失败: {e}")
@classmethod @classmethod
def getAllProject(self): def getAllProject(self):

@ -0,0 +1,234 @@
"""
HART模拟MODBUS-RTU从站管理器
使用modbus_tk实现HART一个主变量和三个动态变量的通讯
使用COM1端口站地址1寄存器地址0,3,5,7
"""
import threading
import time
import struct
from typing import Optional, List, Dict, Any
import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu
from protocol.ModBus.ByteOrder import *
class HartRtuSlaveManager:
"""HART模拟MODBUS-RTU从站管理器"""
def __init__(self, comPort='COM1', slaveId=1, baudRate=9600):
"""
初始化HART RTU从站管理器
:param comPort: 串口端口默认COM1
:param slaveId: 从站地址默认1
:param baudRate: 波特率默认9600
"""
self.comPort = comPort
self.slaveId = slaveId
self.baudRate = baudRate
self.rtuServer = None
self.rtuSlave = None
self.isConnected = False
self.isRunning = False
self.lock = threading.Lock()
# HART变量寄存器地址映射
self.registerMap = {
'primaryVariable': 0, # 主变量 - 寄存器地址0
'dynamicVariable1': 3, # 动态变量1 - 寄存器地址3
'dynamicVariable2': 5, # 动态变量2 - 寄存器地址5
'dynamicVariable3': 7 # 动态变量3 - 寄存器地址7
}
# 变量值缓存
self.variableValues = {
'primaryVariable': 0.0,
'dynamicVariable1': 0.0,
'dynamicVariable2': 0.0,
'dynamicVariable3': 0.0
}
def _initializeRegisters(self):
"""初始化寄存器数据"""
if not self.rtuSlave:
return
try:
# 初始化主变量寄存器地址0
self.rtuSlave.set_values("primary_var", 0, [0, 0])
# 初始化动态变量1寄存器地址3
self.rtuSlave.set_values("dynamic_var1", 3, [0, 0])
# 初始化动态变量2寄存器地址5
self.rtuSlave.set_values("dynamic_var2", 5, [0, 0])
# 初始化动态变量3寄存器地址7
self.rtuSlave.set_values("dynamic_var3", 7, [0, 0])
except Exception as e:
print(f"初始化寄存器失败: {e}")
def _floatToRegisters(self, value: float) -> tuple:
"""将浮点数转换为两个16位寄存器值"""
return floatToBADC(value)
def _registersToFloat(self, high: int, low: int) -> float:
"""将两个16位寄存器值转换为浮点数"""
return BADCToFloat([high, low])
def startSlave(self) -> bool:
"""启动RTU从站"""
try:
with self.lock:
if self.isConnected:
return True
# 创建串口对象
import serial
serialPort = serial.Serial(
port=self.comPort,
baudrate=self.baudRate,
bytesize=8,
parity='N',
stopbits=1,
timeout=1.0
)
# 创建RTU服务器
self.rtuServer = modbus_rtu.RtuServer(serialPort)
# 启动服务器
self.rtuServer.start()
# 添加从站
self.rtuSlave = self.rtuServer.add_slave(self.slaveId)
# 为每个HART变量添加独立的保持寄存器块
# 主变量寄存器0-1起始地址0长度2
self.rtuSlave.add_block("primary_var", cst.HOLDING_REGISTERS, 0, 2)
# 动态变量1寄存器3-4起始地址3长度2
self.rtuSlave.add_block("dynamic_var1", cst.HOLDING_REGISTERS, 3, 2)
# 动态变量2寄存器5-6起始地址5长度2
self.rtuSlave.add_block("dynamic_var2", cst.HOLDING_REGISTERS, 5, 2)
# 动态变量3寄存器7-8起始地址7长度2
self.rtuSlave.add_block("dynamic_var3", cst.HOLDING_REGISTERS, 7, 2)
# 初始化寄存器
self._initializeRegisters()
self.isConnected = True
self.isRunning = True
print(f"HART RTU从站启动成功: {self.comPort}, 站地址: {self.slaveId}")
return True
except Exception as e:
print(f"启动HART RTU从站时出错: {e}")
self.isConnected = False
return False
def stopSlave(self):
"""停止RTU从站"""
try:
with self.lock:
self.isRunning = False
if self.rtuServer:
self.rtuServer.stop()
self.rtuServer = None
self.rtuSlave = None
self.isConnected = False
print("HART RTU从站已停止")
except Exception as e:
print(f"停止HART RTU从站时出错: {e}")
# 移除数据同步线程相关方法modbus_tk会自动处理
def writeVariable(self, variableName: str, value: float) -> bool:
"""
写入HART变量值
:param variableName: 变量名称 ('primaryVariable', 'dynamicVariable1', etc.)
:param value: 变量值
:return: 写入是否成功
"""
if not self.isConnected or variableName not in self.registerMap:
return False
try:
with self.lock:
# 更新变量值缓存
self.variableValues[variableName] = value
# 获取对应的寄存器块名称
blockName = self._getBlockName(variableName)
if not blockName:
return False
# 将浮点数转换为寄存器值
high, low = self._floatToRegisters(value)
# 获取寄存器地址
regAddr = self.registerMap[variableName]
# 直接写入RTU从站寄存器使用绝对地址
if self.rtuSlave and self.isConnected:
self.rtuSlave.set_values(blockName, regAddr, [high, low])
return True
except Exception as e:
print(f"写入HART变量 {variableName} 失败: {e}")
return False
def readVariable(self, variableName: str) -> Optional[float]:
"""
读取HART变量值
:param variableName: 变量名称
:return: 变量值失败返回None
"""
if not self.isConnected or variableName not in self.registerMap:
return None
try:
with self.lock:
# 获取对应的寄存器块名称
blockName = self._getBlockName(variableName)
if not blockName:
return None
# 获取寄存器地址
regAddr = self.registerMap[variableName]
# 从RTU从站读取最新数据使用绝对地址
if self.rtuSlave:
values = self.rtuSlave.get_values(blockName, regAddr, 2)
if len(values) == 2:
high, low = values
value = self._registersToFloat(high, low)
self.variableValues[variableName] = value
return value
# 如果从RTU从站读取失败返回缓存值
return self.variableValues.get(variableName, 0.0)
except Exception as e:
print(f"读取HART变量 {variableName} 失败: {e}")
return None
def _getBlockName(self, variableName: str) -> Optional[str]:
"""根据变量名获取对应的寄存器块名称"""
blockMapping = {
'primaryVariable': 'primary_var',
'dynamicVariable1': 'dynamic_var1',
'dynamicVariable2': 'dynamic_var2',
'dynamicVariable3': 'dynamic_var3'
}
return blockMapping.get(variableName)
def isCommunicationOk(self) -> bool:
"""检查通讯是否正常"""
return self.isConnected and self.rtuServer is not None and self.rtuSlave is not None

@ -64,6 +64,8 @@ class DPV1Master():
# self.searchSlaveThread = SearchSlaveThread(callback = callback, master = self) # self.searchSlaveThread = SearchSlaveThread(callback = callback, master = self)
# self.searchSlaveThread.start() # self.searchSlaveThread.start()
data = self.readHoldingRegisters(1, 850, 64) data = self.readHoldingRegisters(1, 850, 64)
# print(1111)
# print(data)
if data == '读取错误': if data == '读取错误':
return data return data
dataHex = struct.pack('>64h', *data) dataHex = struct.pack('>64h', *data)

@ -33,6 +33,8 @@ class TcpMaster():
valueByte = floatToBADC(outputValue) valueByte = floatToBADC(outputValue)
elif order == 'CDAB': elif order == 'CDAB':
valueByte = floatToCDAB(outputValue) valueByte = floatToCDAB(outputValue)
# elif order == 'Profibus':
else: else:
valueByte = floatToABCD(outputValue) valueByte = floatToABCD(outputValue)
# 浮点数必须使用 WRITE_MULTIPLE_REGISTERS因为需要写入2个寄存器 # 浮点数必须使用 WRITE_MULTIPLE_REGISTERS因为需要写入2个寄存器
@ -95,7 +97,7 @@ class TcpMaster():
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, varNums)
if order == 'ABCD': if order == 'ABCD':
valueByte = ABCDToFloat(value) valueByte = ABCDToFloat(value)
elif order == 'DCBA': elif order == 'DCBA':
@ -104,6 +106,8 @@ class TcpMaster():
valueByte = BADCToFloat(value) valueByte = BADCToFloat(value)
elif order == 'CDAB': elif order == 'CDAB':
valueByte = CDABToFloat(value) valueByte = CDABToFloat(value)
elif order == 'Profibus':
return value
return valueByte return valueByte
except: except:
return 'error' return 'error'

@ -2,6 +2,8 @@ from utils.DBModels.ProtocolModel import (
ModbusTcpMasterVar, ModbusTcpSlaveVar, ModbusRtuMasterVar, ModbusRtuSlaveVar, ModbusTcpMasterVar, ModbusTcpSlaveVar, ModbusRtuMasterVar, ModbusRtuSlaveVar,
HartVar, TcRtdVar, AnalogVar, HartSimulateVar HartVar, TcRtdVar, AnalogVar, HartSimulateVar
) )
from model.ProjectModel.GlobalConfigManager import GlobalConfigManager
from protocol.HartRtuSlaveManager import HartRtuSlaveManager
from protocol.TCP.TCPVarManage import * from protocol.TCP.TCPVarManage import *
from protocol.TCP.TemToMv import temToMv from protocol.TCP.TemToMv import temToMv
@ -15,18 +17,21 @@ import time
class ProtocolManage(object): class ProtocolManage(object):
"""通讯变量查找类,用于根据变量名在数据库模型中检索变量信息""" """通讯变量查找类,用于根据变量名在数据库模型中检索变量信息"""
# 支持的模型类列表
MODEL_CLASSES = [
ModbusTcpMasterVar, ModbusTcpSlaveVar,
ModbusRtuMasterVar, ModbusRtuSlaveVar,
HartVar, TcRtdVar, AnalogVar, HartSimulateVar
]
def __init__(self): def __init__(self):
# self.tcpVarManager = TCPVarManager('192.168.1.50', 5055) # 根据全局配置动态获取启用的模型类
self.tcpVarManager = TCPVarManager('127.0.0.1', 8000) self.MODEL_CLASSES = GlobalConfigManager.getEnabledModelClasses()
self.writeTC = [0] * 8
self.writeRTD = [0] * 8 # 根据配置决定是否初始化TCPVarManager仅当启用IO或TCRTD模块时
if GlobalConfigManager.needsTcpVarManager():
# self.tcpVarManager = TCPVarManager('192.168.1.50', 5055)
self.tcpVarManager = TCPVarManager('127.0.0.1', 8000)
self.writeTC = [0] * 8
self.writeRTD = [0] * 8
else:
self.tcpVarManager = None
self.writeTC = None
self.writeRTD = None
self.RpcClient = None self.RpcClient = None
self.RpcServer = None self.RpcServer = None
self.varInfoCache = {} # 保持驼峰命名 self.varInfoCache = {} # 保持驼峰命名
@ -37,6 +42,16 @@ class ProtocolManage(object):
self.modbusManager = ModbusManager() self.modbusManager = ModbusManager()
# self.modbusManager.setVariableCache(self.variableValueCache, None, self.varInfoCache) # self.modbusManager.setVariableCache(self.variableValueCache, None, self.varInfoCache)
# HART模拟RTU从站管理器
self.hartRtuSlaveManager = None
if GlobalConfigManager.isModuleEnabled('hartSimulateModule'):
try:
self.hartRtuSlaveManager = HartRtuSlaveManager()
print("HART模拟RTU从站管理器已初始化")
except Exception as e:
print(f"初始化HART模拟RTU从站管理器失败: {e}")
self.hartRtuSlaveManager = None
self.refreshVarCache() self.refreshVarCache()
self.cacheLock = threading.Lock() self.cacheLock = threading.Lock()
# 设置 Modbus 管理器的缓存锁 # 设置 Modbus 管理器的缓存锁
@ -53,6 +68,8 @@ class ProtocolManage(object):
def refreshVarCache(self): def refreshVarCache(self):
"""重新加载所有变量信息到缓存(可选实现)""" """重新加载所有变量信息到缓存(可选实现)"""
self.varInfoCache.clear() self.varInfoCache.clear()
# 重新获取最新的启用模型类列表
self.MODEL_CLASSES = GlobalConfigManager.getEnabledModelClasses()
for modelClass in self.MODEL_CLASSES: for modelClass in self.MODEL_CLASSES:
try: try:
for varInstance in modelClass.select(): for varInstance in modelClass.select():
@ -175,6 +192,10 @@ class ProtocolManage(object):
# 温度/RTD变量处理 # 温度/RTD变量处理
elif modelType == 'TcRtdVar': elif modelType == 'TcRtdVar':
if not self.tcpVarManager:
print("TCPVarManager未初始化无法处理TcRtdVar变量")
return False
channel = int(info['channelNumber']) - 1 channel = int(info['channelNumber']) - 1
varType = info['varType'] varType = info['varType']
compensationVar = float(info['compensationVar']) compensationVar = float(info['compensationVar'])
@ -195,6 +216,10 @@ class ProtocolManage(object):
# 模拟量变量处理 # 模拟量变量处理
elif modelType == 'AnalogVar': elif modelType == 'AnalogVar':
if not self.tcpVarManager:
print("TCPVarManager未初始化无法处理AnalogVar变量")
return False
channel = int(info['channelNumber']) - 1 channel = int(info['channelNumber']) - 1
varType = info['varType'] varType = info['varType']
varModel = info['varModel'] varModel = info['varModel']
@ -206,7 +231,27 @@ class ProtocolManage(object):
# HART模拟变量处理 # HART模拟变量处理
elif modelType == 'HartSimulateVar': elif modelType == 'HartSimulateVar':
pass if not self.hartRtuSlaveManager:
print("HART RTU从站管理器未初始化无法处理HartSimulateVar变量")
return False
# 根据变量名确定是主变量还是动态变量
varName = variableName.lower()
if 'primary' in varName or '主变量' in variableName:
success = self.hartRtuSlaveManager.writeVariable('primaryVariable', float(value))
elif 'dynamic1' in varName or '动态变量1' in variableName:
success = self.hartRtuSlaveManager.writeVariable('dynamicVariable1', float(value))
elif 'dynamic2' in varName or '动态变量2' in variableName:
success = self.hartRtuSlaveManager.writeVariable('dynamicVariable2', float(value))
elif 'dynamic3' in varName or '动态变量3' in variableName:
success = self.hartRtuSlaveManager.writeVariable('dynamicVariable3', float(value))
else:
# 默认写入主变量
success = self.hartRtuSlaveManager.writeVariable('primaryVariable', float(value))
if not success:
print(f"HART模拟变量 {variableName} 写入失败")
return False
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'])
@ -286,6 +331,9 @@ class ProtocolManage(object):
elif modelType == 'HartVar': elif modelType == 'HartVar':
pass pass
elif modelType == 'TcRtdVar': elif modelType == 'TcRtdVar':
if not self.tcpVarManager:
return None
channel = int(info['channelNumber']) - 1 channel = int(info['channelNumber']) - 1
varType = info['varType'] varType = info['varType']
varModel = info['varModel'] varModel = info['varModel']
@ -297,10 +345,13 @@ class ProtocolManage(object):
value = self.tcpVarManager.simTCData[channel] value = self.tcpVarManager.simTCData[channel]
else: else:
if varType == 'PT100': if varType == 'PT100':
value = self.writeRTD[channel] value = self.writeRTD[channel] if self.writeRTD else 0
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.writeTC else 0
elif modelType == 'AnalogVar': elif modelType == 'AnalogVar':
if not self.tcpVarManager:
return None
channel = int(info['channelNumber']) - 1 channel = int(info['channelNumber']) - 1
varType = info['varType'] varType = info['varType']
varModel = info['varModel'] varModel = info['varModel']
@ -309,7 +360,22 @@ class ProtocolManage(object):
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'])
elif modelType == 'HartSimulateVar': elif modelType == 'HartSimulateVar':
pass if not self.hartRtuSlaveManager:
return None
# 根据变量名确定是主变量还是动态变量
varName = variableName.lower()
if 'primary' in varName or '主变量' in variableName:
value = self.hartRtuSlaveManager.readVariable('primaryVariable')
elif 'dynamic1' in varName or '动态变量1' in variableName:
value = self.hartRtuSlaveManager.readVariable('dynamicVariable1')
elif 'dynamic2' in varName or '动态变量2' in variableName:
value = self.hartRtuSlaveManager.readVariable('dynamicVariable2')
elif 'dynamic3' in varName or '动态变量3' in variableName:
value = self.hartRtuSlaveManager.readVariable('dynamicVariable3')
else:
# 默认读取主变量
value = self.hartRtuSlaveManager.readVariable('primaryVariable')
if value is not None and value != 'error': 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'])
@ -328,12 +394,18 @@ class ProtocolManage(object):
return self._readVariableValueOriginal(variableName) return self._readVariableValueOriginal(variableName)
def recvDeltaT(self): def recvDeltaT(self):
return self.tcpVarManager.recvDeltaT() if self.tcpVarManager:
return self.tcpVarManager.recvDeltaT()
return None
def shutdown(self): def shutdown(self):
self.tcpVarManager.shutdown() if self.tcpVarManager:
self.tcpVarManager.shutdown()
# 关闭所有Modbus通讯 # 关闭所有Modbus通讯
self.modbusManager.stopAllModbus() self.modbusManager.stopAllModbus()
# 关闭HART RTU从站
if self.hartRtuSlaveManager:
self.hartRtuSlaveManager.stopSlave()
self.closeClient() self.closeClient()
self.closeServer() self.closeServer()
# 关闭后台读取线程 # 关闭后台读取线程
@ -436,3 +508,28 @@ class ProtocolManage(object):
def clearModbusMessages(self): def clearModbusMessages(self):
"""清空 Modbus 报文记录""" """清空 Modbus 报文记录"""
self.modbusManager.clearMessages() self.modbusManager.clearMessages()
# ==================== HART模拟RTU从站管理方法 ====================
def startHartRtuSlave(self):
"""启动HART RTU从站"""
if not self.hartRtuSlaveManager:
return False
return self.hartRtuSlaveManager.startSlave()
def stopHartRtuSlave(self):
"""停止HART RTU从站"""
if self.hartRtuSlaveManager:
self.hartRtuSlaveManager.stopSlave()
def writeHartVariable(self, variableName: str, value: float) -> bool:
"""写入HART变量值"""
if not self.hartRtuSlaveManager:
return False
return self.hartRtuSlaveManager.writeVariable(variableName, value)
def readHartVariable(self, variableName: str):
"""读取HART变量值"""
if not self.hartRtuSlaveManager:
return None
return self.hartRtuSlaveManager.readVariable(variableName)
Loading…
Cancel
Save