from utils.DBModels.ProtocolModel import ( ModbusTcpMasterVar, ModbusTcpSlaveVar, ModbusRtuMasterVar, ModbusRtuSlaveVar, HartVar, TcRtdVar, AnalogVar, HartSimulateVar ) from protocol.TCP.TCPVarManage import * from protocol.TCP.TemToMv import temToMv from protocol.RPC.RpcClient import RpcClient from protocol.RPC.RpcServer import RpcServer class ProtocolManage(object): """通讯变量查找类,用于根据变量名在数据库模型中检索变量信息""" # 支持的模型类列表 MODEL_CLASSES = [ ModbusTcpMasterVar, ModbusTcpSlaveVar, ModbusRtuMasterVar, ModbusRtuSlaveVar, HartVar, TcRtdVar, AnalogVar, HartSimulateVar ] def __init__(self): # self.tcpVarManager = TCPVarManager('192.168.1.50', 5055) self.tcpVarManager = TCPVarManager('127.0.0.1', 8000) self.writeTC = [0] * 8 self.writeRTD = [0] * 8 self.RpcClient = None self.RpcServer = None @classmethod def lookupVariable(cls, variableName): """ 根据变量名检索变量信息 :param variableName: 要查询的变量名 :return: 包含变量信息和模型类型的字典,如果未找到返回None """ for modelClass in cls.MODEL_CLASSES: varInstance = modelClass.getByName(variableName) if varInstance: # 获取变量字段信息 varData = {} for field in varInstance._meta.sorted_fields: fieldName = field.name varData[fieldName] = getattr(varInstance, fieldName) return { 'model_type': modelClass.__name__, 'variable_data': varData } return None def setClentMode(self, clentName, rabbitmqHost='localhost'): if self.RpcClient: self.RpcClient.close() self.RpcClient = RpcClient(clentName, rabbitmqHost) # 使用非阻塞方式启动RPC客户端 self.RpcClient.startNonBlocking() def closeClent(self): if self.RpcClient: self.RpcClient.close() self.RpcClient = None def setServerMode(self, rabbitmqHost='localhost'): if self.RpcServer: self.RpcServer.close() self.RpcServer = RpcServer(rabbitmqHost) def addClient(self, clientName): if self.RpcServer: self.RpcServer.addClient(clientName = clientName) else: return # print(11111111111) # time.sleep(3) # print(self.RpcServer.broadcastRead()) # self.RpcServer.broadcastRead() def closeServer(self): if self.RpcServer: self.RpcServer.close() self.RpcServer = None # @classmethod def writeVariableValue(self, variableName, value, trigger = None, timeoutMS = 2000): """ 根据变量名写入变量值,根据变量类型进行不同处理(不保存到数据库) :param variableName: 变量名 :param value: 要写入的值 :return: 写入成功返回True,否则返回False """ varInfo = self.lookupVariable(variableName) if not varInfo: return False modelType = varInfo['model_type'] info = varInfo['variable_data'] # print(info) try: # 拆分为四个独立的Modbus协议条件判断 if modelType == 'ModbusTcpMasterVar': # 仅设置值,不保存到数据库 pass if modelType == 'ModbusTcpSlaveVar': # 仅设置值,不保存到数据库 pass if modelType == 'ModbusRtuMasterVar': # 仅设置值,不保存到数据库 pass if modelType == 'ModbusRtuSlaveVar': # 仅设置值,不保存到数据库 pass # HART协议变量处理 elif modelType == 'HartVar': # 仅设置值,不保存到数据库 pass # 温度/RTD变量处理 elif modelType == 'TcRtdVar': channel = int(info['channelNumber']) - 1 varType = info['varType'] compensationVar = float(info['compensationVar']) varModel = info['varModel'] model = self.getModelType(varModel) if self.getModelType(varModel) else localModel # print(value + compensationVar) if model == localModel: if varType == 'PT100': self.writeRTD[channel] = value else: self.writeTC[channel] = value if varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A', 'PT100'] and model != SimModel: value = temToMv(varType, value + compensationVar) # 直接补偿温度 补偿mv调整到括号外 if trigger and varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']: trigger = TCTrigger if trigger and varType in ['PT100']: trigger = RTDTrigger self.tcpVarManager.writeValue(varType, channel, value, trigger=trigger, model=model, timeoutMS=timeoutMS) # 模拟量变量处理 elif modelType == 'AnalogVar': channel = int(info['channelNumber']) - 1 varType = info['varType'] varModel = info['varModel'] model = self.getModelType(varModel) if self.getModelType(varModel) else localModel if info['varType'] in ['AI','AO']: value = self.getRealAO(value, info['max'], info['min']) trigger = FPGATrigger if trigger else trigger self.tcpVarManager.writeValue(varType, channel, value, trigger=trigger, model=model, timeoutMS=timeoutMS) # print(1) # HART模拟变量处理 elif modelType == 'HartSimulateVar': # 仅设置值,不保存到数据库 pass if self.RpcClient: self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType']) return True except Exception as e: print(f"写入变量值失败: {str(e)}") return False # 添加读取函数 def readVariableValue(self, variableName): """ 根据变量名读取变量值,根据变量类型进行不同处理(留空) :param variableName: 变量名 :return: 读取的值或None(失败时) """ varInfo = self.lookupVariable(variableName) if not varInfo: return None modelType = varInfo['model_type'] info = varInfo['variable_data'] try: # 拆分为独立的协议条件判断 if modelType == 'ModbusTcpMasterVar': # 读取操作(留空) pass if modelType == 'ModbusTcpSlaveVar': pass if modelType == 'ModbusRtuMasterVar': pass if modelType == 'ModbusRtuSlaveVar': pass # HART协议变量处理 elif modelType == 'HartVar': pass # 温度/RTD变量处理 elif modelType == 'TcRtdVar': channel = int(info['channelNumber']) - 1 varType = info['varType'] varModel = info['varModel'] model = self.getModelType(varModel) if model == SimModel: if varType == 'PT100': value = self.tcpVarManager.simRTDData[channel] elif varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']: value = self.tcpVarManager.simTCData[channel] if self.RpcClient: self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType']) return value else: if varType == 'PT100': value = self.writeRTD[channel] elif varType in ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A']: value = self.writeTC[channel] if self.RpcClient: self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType']) return value # 模拟量变量处理 elif modelType == 'AnalogVar': channel = int(info['channelNumber']) - 1 varType = info['varType'] # print(varType, channel) varModel = info['varModel'] model = self.getModelType(varModel) value = self.tcpVarManager.readValue(varType, channel, model=model) if varType in ['AI','AO']: # print(value) value = self.getRealAI(value, info['max'], info['min']) if self.RpcClient: self.RpcClient.setVarContent(variableName, value, info['min'], info['max'], info['varType']) return value # print(1) # HART模拟变量处理 elif modelType == 'HartSimulateVar': pass return None # 暂时返回None except Exception as e: print(f"读取变量值失败: {str(e)}") return str(e) def readRpcVariable(self): if self.RpcServer: print(self.RpcServer.broadcastRead()) # def sendTrigger(self, variableName, value, timeoutMS): # self.writeVariableValue(variableName, value, trigger=True, timeoutMS = timeoutMS) def recvDeltaT(self): return self.tcpVarManager.recvDeltaT() def shutdown(self): self.tcpVarManager.shutdown() def getRealAO(self, value,highValue, lowValue): if highValue: lowValue = float(lowValue) highValue = float(highValue) return (16 * (value - lowValue) + 4 * (highValue-lowValue))/(1000 * (highValue - lowValue)) else: return value/1000 def getRealAI(self, mA, highValue, lowValue): """ 将毫安值转换为实际工程值(getRealAO的反向计算) :param mA: 毫安值 :param highValue: 工程值上限 :param lowValue: 工程值下限 :return: 实际工程值 """ try: if highValue: lowValue = float(lowValue) highValue = float(highValue) # 反向计算: value = (1000 * mA * (highValue - lowValue) - 4*(highValue - lowValue)) / 16 + lowValue return (1000 * mA * (highValue - lowValue) - 4 * (highValue - lowValue)) / 16.0 + lowValue else: return mA * 1000 except Exception as e: print(f"工程值转换失败: {str(e)}") return 0.0 # 默认返回0避免中断流程 def getModelType(self, varModel): if varModel == '本地值': return localModel elif varModel == '远程值': return NetModel elif varModel == '模拟值': return SimModel