|
|
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() |