You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
10 KiB
Python

6 months ago
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()