1217验收演示版本

main
DESKTOP-3D7M4SA\Hicent 1 month ago
parent 10619fea0c
commit b5f451cf9c

@ -911,7 +911,10 @@ class StepExecutor(QWidget):
varName = varName.strip()
try:
# 转换为浮点数,支持各种数值格式
if '.' in str(varValue):
numericValue = float(varValue)
else:
numericValue: float = int(varValue)
# print(f" 变量: {varName} = {numericValue}")
# 处理超时设置

@ -74,19 +74,8 @@ class ProfibusWidgets(QWidget):
super().__init__()
InitParameterDB()
self.setObjectName("MainWindow")
self.protocolManage = Globals.getValue('protocolManage')
self.usingSharedProfibus = False
self.devicesManange = None
if self.protocolManage and self.protocolManage.hasProfibusSupport():
sharedManager = self.protocolManage.getSharedProfibusManager()
if sharedManager:
self.devicesManange = sharedManager
self.usingSharedProfibus = True
if self.devicesManange is None:
print('没有找到共享的Profibus')
self.devicesManange = DevicesManange()
# self.batteryManange = BatteryManange()
self.dpv1Master = DPV1Master('192.168.4.38', 502)
self.blockParameterManageWidget = BlockParameterManageWidget()
self.process = None
@ -239,11 +228,10 @@ class ProfibusWidgets(QWidget):
self.refreshProgressBar()
self._connectProfibusBackend()
self.devicesManange.connect()
self.setWindowFlags(Qt.FramelessWindowHint)
# self.resize(800, 600)
# self.showMaximized()
@ -253,20 +241,16 @@ class ProfibusWidgets(QWidget):
self.startProtocolBtn.setText('停止通讯')
self.startProtocolBtn.setIcon(QIcon('./Static/pause.png'))
self.startProtocolBtn.setIconSize(QSize(22, 22))
self._connectProfibusBackend()
self.protocolTimer.start(500)
else:
self.startProtocolBtn.setText('开始通讯')
self.startProtocolBtn.setIcon(QIcon('./Static/start.png'))
self.protocolTimer.stop()
def readValues(self):
if not self._updateProfibusAreasForUI():
return
self.devicesManange.readAreas()
dockWidgets = self.findChildren(QDockWidget) #找到四个dockWidget窗口
for dockWidget in dockWidgets:
if dockWidget.widget().currentWidget().objectName() == 'initWidget':
# print(dockWidget.widget().currentWidget().objectName())
@ -296,24 +280,8 @@ class ProfibusWidgets(QWidget):
# except Exception as e:
# print(e)
def _connectProfibusBackend(self):
if self.usingSharedProfibus and self.protocolManage:
sharedManager = self.protocolManage.getSharedProfibusManager()
if sharedManager:
self.devicesManange = sharedManager
self.protocolManage.connectProfibus()
else:
self.devicesManange.connect()
def _updateProfibusAreasForUI(self):
if self.usingSharedProfibus and self.protocolManage:
self.protocolManage.updateProfibusAreas(force=True)
return True
self.devicesManange.readAreas()
return True
def refreshProgressBar(self):
# self.temp = temp / 10 if temp > -3276.8 else float('nan') # 假设温度值需要除以10得到实际℃数
# self.current = current # mA
# self.volt = volt # mV

@ -4,7 +4,6 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QPushButton, QGridLay
QHBoxLayout, QMessageBox, QSplitter, QRadioButton
from UI.ProfibusWidgets.SoftKeyBoardEdit import SoftKeyBoardEdit
from utils import Globals
class ForceButton(QPushButton):
def __init__(self, number = None, valueLabel = None, valueEdit = None, qualityValueLabel = None, \
@ -32,7 +31,6 @@ class RightAreaWidgets(QWidget):
self.qualityLabel = {}
self.areaWidget = areaWidget
self.devicesManange = self.areaWidget.devicesManange
self.protocolManage = Globals.getValue('protocolManage')
self.order = order
self.byteLineEdit = byteLineEdit
self.dataType = dataType
@ -207,45 +205,6 @@ class RightAreaWidgets(QWidget):
def readValues(self, curIndex):
# print(curIndex)
if not self.force:
# 优先通过ProtocolManage读取这样可以获取RPC同步的值
if self.valueName and self.protocolManage:
try:
value = self.protocolManage.readVariableValue(self.valueName)
if value is not None:
# 处理从ProtocolManage获取的值
if isinstance(value, dict) and 'value' in value:
actualValue = value['value']
qualityValue = value.get('quality', '0x00')
else:
actualValue = value
qualityValue = '0x00'
# 更新UI显示
if self.dataType in ['AI', 'AO']:
# 模拟量显示
if 0 in self.areaLabel:
self.areaLabel[0].setText(str(actualValue))
if 0 in self.qualityLabel:
self.qualityLabel[0].setText(str(qualityValue))
else:
# 离散量显示
for index, label in self.areaLabel.items():
if isinstance(actualValue, list) and index < len(actualValue):
bitValue = actualValue[index]
if bitValue == 1:
label.setText('ON')
label.setChecked(True)
else:
label.setText('OFF')
label.setChecked(False)
else:
label.setText('OFF')
label.setChecked(False)
return
except Exception as e:
print(f"通过ProtocolManage读取变量 {self.valueName} 失败: {e}")
# 回退到直接从设备读取
device = self.devicesManange.getDevice(self.deviceName)
values, qualityValueList = device.getAreaValues(curIndex)
# print(qualityValueList)
@ -289,19 +248,6 @@ class RightAreaWidgets(QWidget):
if valueList is None:
return
else:
# 通过ProtocolManage写入以便触发RPC同步
if self.valueName and self.protocolManage:
# 构造写入值(包含质量值)
writeValue = {
'value': float(value),
'quality': qualityValue
}
success = self.protocolManage.writeVariableValue(self.valueName, writeValue)
if not success:
# 如果ProtocolManage写入失败回退到直接写入
self.devicesManange.writeAreas(deviceName = self.deviceName, areaIndex = curIndex, values = valueList, qualityValueList = qualityValueList)
else:
# 如果没有变量名或ProtocolManage不可用使用直接写入
self.devicesManange.writeAreas(deviceName = self.deviceName, areaIndex = curIndex, values = valueList, qualityValueList = qualityValueList)
@ -315,14 +261,6 @@ class RightAreaWidgets(QWidget):
if valueList is None:
return
else:
# 通过ProtocolManage写入以便触发RPC同步
if self.valueName and self.protocolManage:
success = self.protocolManage.writeVariableValue(self.valueName, value)
if not success:
# 如果ProtocolManage写入失败回退到直接写入
self.devicesManange.writeAreas(deviceName = self.deviceName, areaIndex = curIndex, values = valueList)
else:
# 如果没有变量名或ProtocolManage不可用使用直接写入
self.devicesManange.writeAreas(deviceName = self.deviceName, areaIndex = curIndex, values = valueList)
if sender.isChecked():
sender.setText('ON')

@ -139,7 +139,7 @@ class VarTableView(QTableView):
self.verticalHeader().hide()
def setupColumnWidths(self):
self.setCustomColumnWidths([0.9, 0.9, 0.9, 1, 1, 1.4, 1, 1, 1, 1, 0.9, 1.3])
self.setCustomColumnWidths([0.9, 0.9, 0.9, 1.4, 1, 1.3, 0.9, 0.9, 0.9, 0.9, 0.9, 1.4])
def setCustomColumnWidths(self, ratios):
# 计算总比例

@ -309,7 +309,7 @@ class DevicesManange():
# print(bytes)
# print(bytes)
values = struct.unpack('!' + 'H' * int(len(bytes) / 2), bytes)
modbusM.writeMultipleRegisters(slaveId = 1, startAddress = 0, outputValues = values)
modbusM.writeMultipleRegisters(slaveId = 1, startAddress = 0, outputValues = values, order = 'int')
# print(struct.unpack('>f', struct.pack('!HH', *values[:2])))
def readAreas(self):

@ -888,7 +888,10 @@ class GlobalVarManager(object):
modelLists = ['ModbusTcpMasterTable', 'ModbusTcpSlaveTable', 'ModbusRtuMasterTable',
'ModbusRtuSlaveTable', 'HartTable', 'TcRtdTable', 'AnalogTable', 'HartSimulateTable', 'userTable']
for l in modelLists:
Globals.getValue(l).model.initTable()
tableObj = Globals.getValue(l)
# 检查对象是否存在且具有model属性
if tableObj and hasattr(tableObj, 'model'):
tableObj.model.initTable()
if errorConList:
return '\r\n'.join(errorConList)

@ -348,6 +348,40 @@ class ModbusManager:
print(f"读取RTU从站变量失败: {str(e)}")
return None
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 _getTcpSettings(self, tcpType):
@ -479,7 +513,7 @@ class ModbusManager:
if value != 'error' and self.variableValueCache is not None and self.cacheLock is not None:
with self.cacheLock:
self.variableValueCache[varName] = value
print(varName, value)
# print(varName, value)
except Exception as e:
print(f"读取TCP主站变量失败 {varName}: {str(e)}")
@ -509,15 +543,18 @@ class ModbusManager:
def _readModbusValue(self, master, slaveId, address, varType, order):
"""通用Modbus值读取方法"""
try:
# varType: 1=线圈, 2=离散输入, 3=输入寄存器, 4=保持寄存器
# varType: 0=线圈, 1=离散输入, 3=输入寄存器, 4=保持寄存器
# 对于寄存器类型需要读取2个寄存器来获取完整的浮点数
registerCount = 2 if varType in [3, 4] and order != 'int' else 1
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)
return master.readInputRegisters(slaveId, address, registerCount, order)
elif varType == 4: # 保持寄存器
return master.readHoldingRegisters(slaveId, address, 1, order)
return master.readHoldingRegisters(slaveId, address, registerCount, order)
else:
return 'error'
except Exception as e:

@ -35,12 +35,15 @@ class RTUMaster():
def writeSingleRegister(self, slaveId, address, outputValue, order='ABCD'):
try:
if '.' not in str(outputValue):
if '.' not in str(outputValue) and order == 'int':
# 整数值,使用单寄存器写入
outputValue = int(outputValue)
self.master.execute(slaveId, cst.WRITE_SINGLE_REGISTER, starting_address=address, output_value=outputValue)
else:
# 浮点数值需要使用多寄存器写入因为浮点数占用2个寄存器
if '.' not in str(outputValue):
outputValue = int(outputValue)
else:
outputValue = float(outputValue)
valueByte = None # 初始化变量
@ -54,14 +57,12 @@ class RTUMaster():
valueByte = floatToCDAB(outputValue)
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:
print(f'writeSingleRegister error: {e}')
@ -80,15 +81,19 @@ class RTUMaster():
try:
processedValues = []
for value in outputValues:
if '.' not in str(value):
# 整数值
processedValues.append(int(value))
if '.' not in str(value) and order == 'int':
# 整数值,使用单寄存器写入
value = int(value)
processedValues.append(value)
else:
# 浮点值 - 根据字节序转换为寄存器对
if '.' not in str(value):
floatValue = int(value)
else:
floatValue = float(value)
if order == 'ABCD': # 大端模式
if order == 'ABCD':
valueByte = floatToABCD(floatValue)
elif order == 'DCBA': # 小端模式
elif order == 'DCBA':
valueByte = floatToDCBA(floatValue)
elif order == 'BADC':
valueByte = floatToBADC(floatValue)
@ -124,8 +129,11 @@ class RTUMaster():
try:
if order == 'int':
valueByte = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, varNums)[0]
valueByte = int(valueByte)
else:
value = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, 2)
# 对于浮点数总是读取2个寄存器
readCount = 2 if order != 'int' else varNums
value = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, readCount)
if order == 'ABCD': # 大端模式
valueByte = ABCDToFloat(value)
elif order == 'DCBA': # 小端模式
@ -143,7 +151,9 @@ class RTUMaster():
if order == 'int':
valueByte = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, varNums)[0]
else:
value = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, 2)
# 对于浮点数总是读取2个寄存器
readCount = 2 if order != 'int' else varNums
value = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, readCount)
if order == 'ABCD': # 大端模式
valueByte = ABCDToFloat(value)
elif order == 'DCBA': # 小端模式

@ -48,10 +48,20 @@ class RTUSlave():
def setValue(self, slaveId, name, address, value, order = 'ABCD'):
try:
slave = self.server.get_slave(slaveId)
if '.' in str(value):
if '.' not in str(value) and order == 'int':
# 整数值处理
intValue = int(value)
slave.set_values(name, address, intValue)
else:
# 浮点数处理或者order != 'int'时的浮点数转换)
if '.' not in str(value):
floatValue = int(value)
else:
floatValue = float(value)
if order == 'ABCD': # 大端模式
valueByte = floatToABCD(floatValue)
elif order == 'DCBA': # 小端模式
@ -63,11 +73,9 @@ class RTUSlave():
else:
valueByte = floatToABCD(floatValue)
slave.set_values(name, address, valueByte)
else:
# print(value)
slave.set_values(name, address, int(value))
except Exception as e:
print(f"RTU Slave setValue error: {e}")
return 'error'
def readValue(self, slaveId, name, address, order = 'int'):

@ -18,12 +18,15 @@ class TcpMaster():
def writeSingleRegister(self, slaveId, address, outputValue, order='ABCD'):
try:
if '.' not in str(outputValue):
if '.' not in str(outputValue) and order == 'int':
# 整数值,使用单寄存器写入
outputValue = int(outputValue)
self.master.execute(slaveId, cst.WRITE_SINGLE_REGISTER, starting_address=address, output_value=outputValue)
else:
# 浮点数值需要使用多寄存器写入因为浮点数占用2个寄存器
if '.' not in str(outputValue):
outputValue = int(outputValue)
else:
outputValue = float(outputValue)
if order == 'ABCD': # 大端模式
valueByte = floatToABCD(outputValue)
@ -47,9 +50,16 @@ class TcpMaster():
"""写多个寄存器,支持不同数据类型和字节序"""
try:
processedValues = []
# print(outputValues)
for value in outputValues:
if '.' not in str(value) and order == 'int':
# 整数值,使用单寄存器写入
value = int(value)
# self.master.execute(slaveId, cst.WRITE_SINGLE_REGISTER, starting_address=startAddress, output_value=value)
processedValues.append(value)
else:
if '.' not in str(value):
processedValues.append(int(value))
floatValue = int(value)
else:
floatValue = float(value)
if order == 'ABCD':
@ -96,6 +106,7 @@ class TcpMaster():
try:
if order == 'int':
valueByte = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, varNums)[0]
valueByte = int(valueByte)
else:
value = self.master.execute(slaveId, cst.READ_HOLDING_REGISTERS, startAddress, varNums)
if order == 'ABCD':
@ -116,8 +127,11 @@ class TcpMaster():
try:
if order == 'int':
valueByte = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, varNums)[0]
valueByte = int(valueByte)
else:
value = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, 2)
# 对于浮点数总是读取2个寄存器
readCount = 2 if order != 'int' else varNums
value = self.master.execute(slaveId, cst.READ_INPUT_REGISTERS, startAddress, readCount)
if order == 'ABCD':
valueByte = ABCDToFloat(value)
elif order == 'DCBA':

@ -53,10 +53,18 @@ class TCPSlave():
def setValue(self, slaveId, name, address, value, order='ABCD'):
try:
slave = self.server.get_slave(slaveId)
# print(value)
if '.' in str(value):
# 浮点数处理
if '.' not in str(value) and order == 'int':
# 整数值处理
intValue = int(value)
slave.set_values(name, address, intValue)
else:
# 浮点数处理或者order != 'int'时的浮点数转换)
if '.' not in str(value):
floatValue = int(value)
else:
floatValue = float(value)
if order == 'ABCD': # 大端模式
valueByte = floatToABCD(floatValue)
elif order == 'DCBA': # 小端模式
@ -68,10 +76,6 @@ class TCPSlave():
else:
valueByte = floatToABCD(floatValue)
slave.set_values(name, address, valueByte)
else:
# 整数处理
intValue = int(value)
slave.set_values(name, address, intValue)
return True
except Exception as e:

@ -11,6 +11,7 @@ from protocol.TCP.TemToMv import temToMv
from protocol.RPC.RpcClient import RpcClient
from protocol.RPC.RpcServer import RpcServer
from protocol.ModBus.ModbusManager import ModbusManager
# from protocol.ProfibusManager import ProfibusManager
from utils import Globals
import threading
import time
@ -42,21 +43,16 @@ class ProtocolManage(object):
self.varInfoCache = {} # 保持驼峰命名
self.historyDBManage = Globals.getValue('historyDBManage')
self.variableValueCache = {} # {varName: value}
self.profibusManager = None
self.profibusDeviceMeta = {}
self.profibusEnabled = GlobalConfigManager.isModuleEnabled('profibusModule')
self._profibusConnected = False
self._profibusLastUpdate = 0
self.profibusLock = threading.Lock()
if self.profibusEnabled:
# print('yeyeye')
self._initializeProfibusSupport()
self.cacheLock = threading.Lock()
# Modbus 管理器
self.modbusManager = ModbusManager()
# 设置 Modbus 管理器的缓存锁
self.modbusManager.setVariableCache(self.variableValueCache, self.cacheLock, self.varInfoCache)
# self.modbusManager.setVariableCache(self.variableValueCache, None, self.varInfoCache)
# PROFIBUS管理器 (已删除,准备重新构建)
# self.profibusManager = DevicesManange()
# self.profibusEnabled = False
# HART模拟RTU从站管理器
self.hartRtuSlaveManager = None
@ -69,9 +65,6 @@ class ProtocolManage(object):
self.hartRtuSlaveManager = None
self.refreshVarCache()
self.cacheLock = threading.Lock()
# 设置 Modbus 管理器的缓存锁
self.modbusManager.setVariableCache(self.variableValueCache, self.cacheLock, self.varInfoCache)
self.readThreadStop = threading.Event()
self.readThread = threading.Thread(target=self._backgroundReadAllVariables, daemon=True)
@ -99,10 +92,11 @@ class ProtocolManage(object):
'modelType': modelClass.__name__,
'variableData': varData
}
except Exception as e:
print(f"刷新缓存时出错: {modelClass.__name__}: {e}")
if self.profibusEnabled and self.profibusManager:
self._registerProfibusVariables()
# self.getAllProfibusDevices()
# PROFIBUS变量注册 (已删除,准备重新构建)
@ -127,10 +121,7 @@ class ProtocolManage(object):
}
self.varInfoCache[variableName] = result # 写入缓存
return result
if self.profibusEnabled and self.profibusManager:
profibusResult = self._lookupProfibusVariable(variableName)
if profibusResult:
return profibusResult
# PROFIBUS变量查找 (已删除,准备重新构建)
return None
@ -254,12 +245,10 @@ class ProtocolManage(object):
trigger = FPGATrigger if trigger else trigger
self.tcpVarManager.writeValue(varType, channel, value, trigger=trigger, model=model, timeoutMS=timeoutMS)
# PROFIBUS变量处理
# PROFIBUS变量处理 (已删除,准备重新构建)
elif modelType == 'ProfibusVar':
success, normalizedValue = self._writeProfibusVariable(info, value)
if not success:
# PROFIBUS变量写入功能 (已删除,准备重新构建)
return False
value = normalizedValue
# HART模拟变量处理
@ -307,8 +296,7 @@ class ProtocolManage(object):
while not self.readThreadStop.is_set():
try:
allVarNames = list(self.getAllVariableNames())
if self.profibusEnabled and self.profibusManager:
self._updateProfibusAreas(force=True)
# PROFIBUS区域更新 (已删除,准备重新构建)
for varName in allVarNames:
if self.readThreadStop.is_set():
@ -328,351 +316,7 @@ class ProtocolManage(object):
print(f"后台读取线程异常: {e}")
time.sleep(5) # 异常时等待更长时间
# ==================== PROFIBUS 变量管理 ====================
def _initializeProfibusSupport(self):
try:
self.profibusManager = DevicesManange()
self._loadProfibusConfiguration()
self.profibusManager.recalculateAddress()
self._registerProfibusVariables()
except Exception as e:
print(f"初始化PROFIBUS管理器失败: {e}")
self.profibusManager = None
self.profibusEnabled = False
def _loadProfibusConfiguration(self):
self.profibusDeviceMeta = {}
allDevices = DevicesManange.getAllDevice()
if not allDevices or isinstance(allDevices, str):
return
for deviceRow in allDevices:
if not deviceRow:
continue
try:
deviceName = deviceRow[0]
except (IndexError, TypeError):
continue
proType = deviceRow[1] if len(deviceRow) > 1 else None
masterSlaveModel = deviceRow[2] if len(deviceRow) > 2 else None
areaJson = deviceRow[3] if len(deviceRow) > 3 else None
pvUpper = deviceRow[4] if len(deviceRow) > 4 else None
pvLower = deviceRow[5] if len(deviceRow) > 5 else None
pvUnit = deviceRow[6] if len(deviceRow) > 6 else None
self.profibusDeviceMeta[deviceName] = {
'pvUpperLimit': pvUpper,
'pvLowerLimit': pvLower,
'pvUnit': pvUnit
}
try:
self.profibusManager.addDevice(
proType=proType,
masterSlaveModel=masterSlaveModel,
deviceName=deviceName
)
except Exception as e:
print(f"初始化设备 {deviceName} 失败: {e}")
continue
self._addProfibusAreas(deviceName, areaJson)
def _addProfibusAreas(self, deviceName, areaJson):
if not areaJson:
return
try:
areas = json.loads(areaJson) if isinstance(areaJson, str) else areaJson
except Exception as e:
print(f"解析设备 {deviceName} 的区域配置失败: {e}")
return
device = self.profibusManager.getDevice(deviceName)
if not device or not areas:
return
for areaConfig in areas:
if not isinstance(areaConfig, dict):
continue
dataType = areaConfig.get('type')
valueName = areaConfig.get('valueName')
if not dataType or not valueName:
continue
order = areaConfig.get('order', 'ABCD')
bytesCount = areaConfig.get('bytes', 0)
try:
bytesCount = int(bytesCount)
except (TypeError, ValueError):
bytesCount = 0
try:
device.addArea(
type=dataType,
nums=1,
bytes=bytesCount,
order=order,
valueName=valueName
)
except Exception as e:
print(f"添加设备 {deviceName} 的区域 {valueName} 失败: {e}")
continue
def _registerProfibusVariables(self):
if not self.profibusEnabled or not self.profibusManager:
return
for areaInfo in self._iterProfibusAreas():
varName = areaInfo.get('valueName')
if not varName:
continue
self.varInfoCache[varName] = {
'modelType': 'ProfibusVar',
'variableData': dict(areaInfo)
}
def _iterProfibusAreas(self):
if not self.profibusManager:
return
deviceGroups = [
self.profibusManager.dpMasterDevices,
self.profibusManager.dpSlaveDevices,
self.profibusManager.paMasterDevices,
self.profibusManager.paSlaveDevices
]
for devicesDict in deviceGroups:
for deviceName, device in devicesDict.items():
deviceMeta = self.profibusDeviceMeta.get(deviceName, {})
for areaIndex, area in enumerate(device.areas):
yield {
'deviceName': deviceName,
'areaIndex': areaIndex,
'areaType': area.type,
'bytes': getattr(area, 'bytes', 0),
'order': getattr(area, 'order', 'ABCD'),
'valueName': getattr(area, 'valueName', None),
'proType': device.type,
'masterSlaveModel': device.masterOrSlave,
'min': deviceMeta.get('pvLowerLimit'),
'max': deviceMeta.get('pvUpperLimit'),
'unit': deviceMeta.get('pvUnit'),
'varType': area.type
}
def _lookupProfibusVariable(self, variableName):
if not self.profibusEnabled or not self.profibusManager:
return None
for areaInfo in self._iterProfibusAreas() or []:
if areaInfo.get('valueName') == variableName:
result = {
'modelType': 'ProfibusVar',
'variableData': dict(areaInfo)
}
self.varInfoCache[variableName] = result
return result
return None
def _ensureProfibusConnected(self):
if not self.profibusManager:
return False
if self._profibusConnected:
return True
try:
print(f"正在连接Profibus...")
self.profibusManager.connect()
self._profibusConnected = True
print(f"Profibus连接成功")
except Exception as e:
print(f"连接PROFIBUS失败: {e}")
self._profibusConnected = False
return False
return True
def _updateProfibusAreas(self, force=False):
if not self.profibusManager:
return
now = time.time()
if not force and (now - self._profibusLastUpdate) < 0.5:
return
if not self._ensureProfibusConnected():
print(f"Profibus连接失败跳过区域更新")
return
with self.profibusLock:
try:
print(f"正在读取Profibus区域数据...")
self.profibusManager.readAreas()
self._profibusLastUpdate = now
print(f"Profibus区域数据读取完成")
except Exception as e:
print(f"读取PROFIBUS区域失败: {e}")
def _writeProfibusVariable(self, info, rawValue):
if not self.profibusManager:
print(f"Profibus管理器未初始化")
return False, None
if not self._ensureProfibusConnected():
print(f"Profibus连接失败")
return False, None
device = self.profibusManager.getDevice(info['deviceName'])
if not device:
print(f"找不到设备: {info['deviceName']}")
return False, None
areaIndex = info['areaIndex']
if areaIndex >= len(device.areas):
print(f"区域索引超出范围: {areaIndex} >= {len(device.areas)}")
return False, None
area = device.areas[areaIndex]
print(f"写入设备 {info['deviceName']} 区域 {areaIndex} 类型 {area.type}{rawValue}")
if area.type in ['AI', 'AO']:
analogValue, qualityList = self._formatAnalogValue(rawValue)
if analogValue is None:
print(f"模拟量值格式化失败")
return False, None
valuesToWrite = [analogValue]
normalizedValue = analogValue
else:
valuesToWrite = self._formatDiscreteValues(area, rawValue)
if valuesToWrite is None:
print(f"离散量值格式化失败")
return False, None
qualityList = None
normalizedValue = valuesToWrite[:]
with self.profibusLock:
try:
print(f"调用writeAreas写入数据: {valuesToWrite}")
if qualityList is not None:
self.profibusManager.writeAreas(
deviceName=info['deviceName'],
areaIndex=areaIndex,
values=valuesToWrite,
qualityValueList=qualityList
)
else:
self.profibusManager.writeAreas(
deviceName=info['deviceName'],
areaIndex=areaIndex,
values=valuesToWrite
)
print(f"writeAreas调用成功更新本地缓存")
if area.type in ['AI', 'AO']:
area.currentValue = [normalizedValue]
if qualityList:
area.qualityValueList = qualityList
else:
area.currentValue = normalizedValue[:]
except Exception as e:
print(f"写入PROFIBUS变量 {info['valueName']} 失败: {e}")
return False, None
with self.cacheLock:
self.variableValueCache[info['valueName']] = normalizedValue
return True, normalizedValue
def _formatAnalogValue(self, rawValue):
qualityValue = None
targetValue = rawValue
if isinstance(rawValue, dict):
targetValue = rawValue.get('value')
qualityValue = rawValue.get('quality') or rawValue.get('qualityValue')
try:
analogValue = float(targetValue)
except (TypeError, ValueError):
return None, None
qualityList = None
if qualityValue is not None:
normalizedQuality = self._normalizeQualityValue(qualityValue)
if normalizedQuality is None:
return None, None
qualityList = [normalizedQuality]
return analogValue, qualityList
def _normalizeQualityValue(self, qualityValue):
try:
if isinstance(qualityValue, str):
qualityValue = qualityValue.strip()
if qualityValue.lower().startswith('0x'):
qualityInt = int(qualityValue, 16)
else:
qualityInt = int(qualityValue)
else:
qualityInt = int(qualityValue)
if qualityInt < 0 or qualityInt > 255:
return None
return f"0x{qualityInt:02X}"
except (TypeError, ValueError):
return None
def _formatDiscreteValues(self, area, rawValue):
bitLength = (area.bytes or 0) * 8
if bitLength <= 0:
bitLength = 16
if isinstance(getattr(area, 'currentValue', None), list) and area.currentValue:
baseValues = list(area.currentValue)
elif isinstance(getattr(area, 'forceValue', None), list) and area.forceValue:
baseValues = list(area.forceValue)
else:
baseValues = [0] * bitLength
if len(baseValues) < bitLength:
baseValues += [0] * (bitLength - len(baseValues))
else:
baseValues = baseValues[:bitLength]
if isinstance(rawValue, dict) and 'index' in rawValue:
try:
index = int(rawValue['index'])
except (TypeError, ValueError):
return None
if index < 0 or index >= bitLength:
return None
baseValues[index] = 1 if rawValue.get('value') in [1, True, '1', 'on', 'ON'] else 0
return baseValues
if isinstance(rawValue, (list, tuple)):
normalized = [1 if item in [1, True, '1', 'on', 'ON'] else 0 for item in rawValue]
if len(normalized) < bitLength:
normalized += [0] * (bitLength - len(normalized))
return normalized[:bitLength]
baseValues[0] = 1 if rawValue in [1, True, '1', 'on', 'ON'] else 0
return baseValues
def _readProfibusVariable(self, info):
if not self.profibusManager:
print(f"Profibus管理器未初始化")
return None
self._updateProfibusAreas()
device = self.profibusManager.getDevice(info['deviceName'])
if not device:
print(f"找不到设备: {info['deviceName']}")
return None
areaIndex = info['areaIndex']
if areaIndex >= len(device.areas):
print(f"区域索引超出范围: {areaIndex} >= {len(device.areas)}")
return None
area = device.areas[areaIndex]
print(f"读取设备 {info['deviceName']} 区域 {areaIndex} 类型 {area.type} 当前值: {getattr(area, 'currentValue', None)}")
if area.type in ['AI', 'AO']:
if isinstance(area.currentValue, list) and area.currentValue:
try:
return float(area.currentValue[0])
except (TypeError, ValueError):
return area.currentValue[0]
return None
if isinstance(area.currentValue, list) and area.currentValue:
bitLength = (area.bytes or 0) * 8
if bitLength <= 0:
bitLength = len(area.currentValue)
return area.currentValue[:bitLength]
return None
# ==================== 对外共享的 PROFIBUS 接口 ====================
def hasProfibusSupport(self) -> bool:
return self.profibusEnabled and self.profibusManager is not None
def getSharedProfibusManager(self):
return self.profibusManager
def connectProfibus(self) -> bool:
if not self.hasProfibusSupport():
return False
return self._ensureProfibusConnected()
def updateProfibusAreas(self, force: bool = False) -> bool:
if not self.hasProfibusSupport():
return False
self._updateProfibusAreas(force=force)
return True
# ==================== 对外共享的 PROFIBUS 接口 (已删除,准备重新构建) ====================
def getAllVariableNames(self):
@ -714,12 +358,13 @@ class ProtocolManage(object):
info = varInfo['variableData']
try:
# 拆分为独立的协议条件判断
# if modelType == 'ModbusTcpMasterVar':
# value = self.modbusManager.readModbusTcpMasterValue(info)
if modelType == 'ModbusTcpSlaveVar':
if modelType == 'ModbusTcpMasterVar':
value = self.modbusManager.readModbusTcpMasterValue(info)
# print(value)
elif modelType == 'ModbusTcpSlaveVar':
value = self.modbusManager.readModbusTcpSlaveValue(info)
# elif modelType == 'ModbusRtuMasterVar':
# value = self.modbusManager.readModbusRtuMasterValue(info)
elif modelType == 'ModbusRtuMasterVar':
value = self.modbusManager.readModbusRtuMasterValue(info)
elif modelType == 'ModbusRtuSlaveVar':
value = self.modbusManager.readModbusRtuSlaveValue(info)
elif modelType == 'HartVar':
@ -754,7 +399,13 @@ class ProtocolManage(object):
if varType in ['AI', 'AO']:
value = self.getRealAI(value, info['max'], info['min'])
elif modelType == 'ProfibusVar':
value = self._readProfibusVariable(info)
# PROFIBUS变量读取功能 (已删除,准备重新构建)
# value = None
# print(info)
# device = self.profibusManager.getDevice(info['deviceName'])
# values, qualityValueList = device.getAreaValues(info['id'])
# print(values, qualityValueList, info['valueName'])
pass
elif modelType == 'HartSimulateVar':
if not self.hartRtuSlaveManager:
@ -803,8 +454,10 @@ class ProtocolManage(object):
def readVariableValue(self, variableName):
with self.cacheLock:
# print(self.variableValueCache)
# print(variableName,111)
if variableName in self.variableValueCache:
# print(variableName)
return self.variableValueCache[variableName]
return self._readVariableValueOriginal(variableName)
@ -828,6 +481,8 @@ class ProtocolManage(object):
self.readThreadStop.set()
self.readThread.join(timeout=1)
# 关闭PROFIBUS管理器 (已删除,准备重新构建)
def getRealAO(self, value, highValue, lowValue):
if highValue:
lowValue = float(lowValue)
@ -948,3 +603,69 @@ class ProtocolManage(object):
if not self.hartRtuSlaveManager:
return None
return self.hartRtuSlaveManager.readVariable(variableName)
# ==================== PROFIBUS设备管理方法 ====================
def getAllProfibusDevices(self):
"""获取所有PROFIBUS设备和区域信息只返回变量名不为空的AREA"""
try:
# 使用DeviceManage的getAllDevice方法获取所有设备信息
devices = DevicesManange.getAllDevice()
if not devices:
return []
profibusDevices = []
for device in devices:
deviceName, proType, masterSlaveModel, areaJson, pvLowerLimit, pvUpperLimit, pvUnit = device
# 只处理PROFIBUS相关的设备DP或PA类型
if proType in ['DP', 'PA']:
deviceInfo = {
'deviceName': deviceName,
'proType': proType,
'masterSlaveModel': masterSlaveModel,
'pvLowerLimit': pvLowerLimit,
'pvUpperLimit': pvUpperLimit,
'pvUnit': pvUnit,
'areas': []
}
# 解析区域信息只添加变量名不为空的AREA
if areaJson and areaJson != '[]':
try:
areas = json.loads(areaJson)
for area in areas:
valueName = area.get('valueName', '')
# 只有当变量名不为空时才添加该AREA
if valueName and valueName.strip() != '':
areaInfo = {
'deviceName': deviceName,
'id': area.get('id', 0),
'type': area.get('type', ''),
'order': area.get('order', 'ABCD'),
'bytes': area.get('bytes', 4),
'valueName': valueName,
'nums': area.get('nums', 1),
'proType': proType,
'masterSlaveModel': masterSlaveModel,
}
# deviceInfo['areas'].append(areaInfo)
self.varInfoCache[valueName] = {
'modelType': 'ProfibusVar',
'variableData': areaInfo
}
# print(f"缓存变量: {valueName}", areaInfo)
except json.JSONDecodeError:
# 如果JSON解析失败跳过该设备
continue
# 只有当设备有变量名不为空的AREA时才添加到结果中
# if deviceInfo['areas']:
# profibusDevices.append(deviceInfo)
# return profibusDevices
except Exception as e:
print(f"获取PROFIBUS设备信息失败: {str(e)}")
return []

Loading…
Cancel
Save