|
|
|
|
@ -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:
|
|
|
|
|
return False
|
|
|
|
|
value = normalizedValue
|
|
|
|
|
# PROFIBUS变量写入功能 (已删除,准备重新构建)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 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 []
|
|
|
|
|
|
|
|
|
|
|