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 class BlockManage(): _instance = None _dpv1Master = None def __new__(cls, address): if not cls._instance: cls._instance = super().__new__(cls) return cls._instance def __init__(self, address = None): self.address = address if address: # pass self.initBlocks() @property def DPV1Master(self): if not self._dpv1Master: self._dpv1Master = DPV1Master('192.168.3.10', 502) return self._dpv1Master def initBlocks(self): if not self.DPV1Master.judgeSlave(self.address): raise RuntimeError(f"连接从站{self.address}失败.") self.blockDict = { BlockType.PB : [], BlockType.TB : [], BlockType.FB : [], } 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 * NumDirEntry 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)] for typ in [BlockType.PB, BlockType.TB, BlockType.FB]: 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开始 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() if not block.getTBType(): self.blockDict[typ].append(block) # print(blkSlot, blkIndex) # print(self.blockDict) 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)] 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])] @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, }.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): return 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()