import sys sys.path.append('../../') import struct from enum import Enum from utils.DBModels.DeviceParModels import * from protocol.ModBus.DPV1Master import DPV1Master from model.ProjectModel.ParmManage import Parm import concurrent.futures import threading from PyQt5.QtCore import pyqtSignal, pyqtSlot, QThread class LoadDataThread(QThread): loadDataSignal = pyqtSignal(int, int) finished = pyqtSignal(list) def __init__(self, parent): super().__init__() self.parent = parent def run(self): valueList = [] for index, parm in enumerate(self.parent.parms.values()): self.loadDataSignal.emit(len(self.parent.parms), index + 1) valueList.append(parm.readValue()) self.finished.emit(valueList) class BlockType(Enum): TB = 1 PB = 0 FB = 2 class TBType(Enum): flowTB = -1 tempTB = -2 levelTB = -3 # 物位转换块 pressureTB = -4 wikaLevelTB = -5 kfFlowTB = -6 class BlockManage(): _instance = None _dpv1MasterPA = None _dpv1MasterDP = None # def __new__(cls, address): # if not cls._instance: # cls._instance = super().__new__(cls) # return cls._instance def __init__(self, _isPa, address = None): # print(_isPa) self._isPa = _isPa self.address = address self.TBTypeList = [] if address: # pass self.initBlocks() @property def DPV1Master(self): if not self._dpv1MasterPA or not self._dpv1MasterDP: self._dpv1MasterPA = DPV1Master('192.168.3.10', 502) self._dpv1MasterDP = DPV1Master('192.168.1.10', 502) if self._isPa: return self._dpv1MasterPA else: return self._dpv1MasterDP def initBlocks(self): # print(self._isPa,5555) if not self.DPV1Master.judgeSlave(self.address): # print(self.address) raise RuntimeError(f"连接从站{self.address}失败.") self.blockDict = { BlockType.PB : [], BlockType.TB : [], BlockType.FB : [], } self.TBTypeList = [] dirHeadDatas = self.DPV1Master.readParm(address = self.address, slot = 1, index = 0, length = 12) dirHeadDatas = struct.unpack('>6h', dirHeadDatas) DirID = dirHeadDatas[0] # 目录id DirRevNum = dirHeadDatas[1] # 目录版本号 NumDirObj = dirHeadDatas[2] # 目录对象的个数 (如果整个目录使用多于一个目录对象, # 则这此元素被连续定义,就如同使用一个较大的对象。 # 多个目录对象都被连续地列在该目录中。该对象计数整个目录所需的对象。Header对象不计人其) NumDirEntry = dirHeadDatas[3] # 目录登录项的总数 (应计算复合列表目录登录项和复合目录登录项的总个数;实际块数量为NumDirEntry - 3) FirstCompListDirEntry = dirHeadDatas[4] # 第1个复合列表目录登录项的目录登录项个数 (该数用来计数目录内的登录项, 而不包含该登 # 录项的参数地址。第1 个目录登录项是在复合列表目录登录项中的物理块引用。在计数登录 # 项时,复合列表目录登录项与复合目录登录项之间无间隔) NumCompListDirEntry = dirHeadDatas[5] # 功能块类型数量 复合列表目录登录项的个数 计数设备内的不同块类型(物理块、转换块和功能块)和对象类型 #(在本标准范围内仅针对链接对象) dirLength = 4 * NumCompListDirEntry dirDatas = self.DPV1Master.readParm(address = self.address, slot = 1, index = 1, length = dirLength) dirDatas = struct.unpack('>{}h'.format(int(dirLength/2)), dirDatas) entryTuples = [(dirDatas[i], dirDatas[i+1]) for i in range(0, len(dirDatas), 2)] # print(entryTuples) dirMesDic = {} for dirMes in entryTuples: blockIndex = struct.pack('>h', dirMes[0])[0] blockNums = dirMes[1] # print(blockIndex) if blockIndex in dirMesDic: dirMesDic[blockIndex] = dirMesDic[blockIndex] + blockNums else: dirMesDic[blockIndex] = blockNums # print(dirMesDic) # entryTuples = [] for key, value in dirMesDic.items(): # print(key, value) if key == 1: entryTuples = [] data = self.DPV1Master.readParm(address = self.address, slot = 1, index = 1, length = dirLength + 4 * value) else: data = self.DPV1Master.readParm(address = self.address, slot = 1, index = key, length = 4 * value) # print(data, int(len(data)/2)) # print(data) data = struct.unpack('>{}h'.format(int(len(data)/2)), data) # print(data) tuples = [(data[i], data[i+1]) for i in range(0, len(data), 2)] entryTuples += tuples # print(entryTuples) for typ in [BlockType.PB, BlockType.TB, BlockType.FB]: # print(typ) typeIndex = typ.value if type(typ.value) == int else 1 blkDirMesByte = struct.pack('>h', entryTuples[typeIndex][0]) blkIndex = int(blkDirMesByte[0]) # 目录对象编号 blkoffect = int(blkDirMesByte[1]) # 块从第几个Dir_Entry开始 # print(blkoffect) numBlk = entryTuples[typeIndex][1] # 块数量 # print(blkIndex, blkoffect, numBlk) for i in range(numBlk): blkEntryListIndex = blkoffect - 1 + i # print(blkEntryListIndex, entryTuples) blkPointerByte = struct.pack('>h', entryTuples[blkEntryListIndex][0]) numBlkParms = entryTuples[blkEntryListIndex][1] blkSlot = int(blkPointerByte[0]) blkStartIndex = int(blkPointerByte[1]) # print(111, blkStartIndex, ) block = Block(typ, self.DPV1Master) block.slot = blkSlot block.startIndex = blkStartIndex block.numParms = numBlkParms block.blockIndex = i block.address = self.address block.addParms() # print(block.startIndex, block.slot) if typ == BlockType.TB: self.TBTypeList.append(block.getTBType()) self.blockDict[typ].append(block) # print(blkSlot, blkIndex) # print(self.blockDict) # print(self.TBTypeList) def getBlockValues(self, blockType, blockIndex, callback, callback2): block = self.resetBlockType(blockType, blockIndex) return block.getParmsValue(callback, callback2) def getBlockParmValue(self, blockType, blockIndex, parmIndex): block = self.resetBlockType(blockType, blockIndex) parm = block.parms[int(parmIndex)] return parm.readValue() def writeParmValue(self, blockType, blockIndex, parmIndex, values): block = self.resetBlockType(blockType, blockIndex) parm = block.parms[int(parmIndex)] # print(values) result = parm.writeParm(values) return result def resetBlockType(self, blockType, blockIndex): if not isinstance(blockType, BlockType): typ = BlockType.TB block = self.blockDict[typ][blockIndex] block.blockType = blockType block.addParms() else: block = self.blockDict[blockType][blockIndex] return block def getBlockNums(self): # return [1,1,1] return [len(self.blockDict[BlockType.PB]), len(self.blockDict[BlockType.TB]), len(self.blockDict[BlockType.FB])] # def getTBTypes(self): @classmethod def searchSlave(self, callback): self.DPV1Master.searchSlave(callback) class Block(): slot = None startIndex = None numParms = None blockIndex = None address = None loadDataSignal = pyqtSignal(int, int) def __init__(self, blockType, DPV1Master): self.parms = {} self.blockType = blockType self.DPV1Master = DPV1Master # self.addParms() def addParms(self): self.parms = {} getParmsFunc = { BlockType.PB: PhysicalBlock.getallParame, BlockType.TB: PressureTranslationBlock.getallParame, BlockType.FB: AIFunctionBlock.getallParame, TBType.flowTB: FlowTranslationBlock.getallParame, TBType.pressureTB: PressureTranslationBlock.getallParame, TBType.tempTB: TemperatureTranslationBlock.getallParame, TBType.levelTB: LevelTranslationBlock.getallParame, TBType.wikaLevelTB: WiKaLevelTranslationBlock.getallParame, TBType.kfFlowTB: KaiFengFlowTranslationBlock.getallParame }.get(self.blockType, lambda: []) parmsData = getParmsFunc() for parmData in parmsData: # print(parmData) # print(self.startIndex, 3214) parm = Parm(parmData, self.slot, self.startIndex, self) self.parms[parm.relativeIndex] = parm # self.parms.append(parm) def getParmsValue(self, callback, callback2): valueList = [] # self.loadDataSignal.connect(callback.loadData) self.thread = LoadDataThread(self) self.thread.loadDataSignal.connect(callback) self.thread.start() self.thread.finished.connect(callback2) # thread.join() # print(valueList) # return valueList def getParmValue(self, index, callback, callback2): return def getTBType(self): value = int(self.parms[list(self.parms.keys())[0]].readValue()) # print(value, type(value)) match value: case 1: return TBType.pressureTB case 2: return TBType.tempTB case 3: return TBType.flowTB case 4: return TBType.levelTB def getParmIndex(self, blockType, paramName): match blockType: case "BlockType.PB": PhysicalBlock.getIndex(paramName) case "BlockType.FB": AIFunctionBlock.getIndex(paramName) case "BlockType.TB": pass if __name__ == '__main__': b = BlockManage(address = 55) c = BlockManage(address = 77) # b.initBlock()