|
|
|
@ -10,16 +10,18 @@ import struct
|
|
|
|
|
#从站 "AI" "DI"可强制
|
|
|
|
|
#主站 "AO" "DO"可强制
|
|
|
|
|
class Device():
|
|
|
|
|
inputStartAddress = None
|
|
|
|
|
inputEndAddress = None
|
|
|
|
|
outputStartAddress = None
|
|
|
|
|
outputEndAddress = None
|
|
|
|
|
inputStartAddress = 0
|
|
|
|
|
inputEndAddress = 0
|
|
|
|
|
outputStartAddress = 0
|
|
|
|
|
outputEndAddress = 0
|
|
|
|
|
protocolType = None
|
|
|
|
|
masterOrSlave = None
|
|
|
|
|
deviceName = None
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.inputAreas = []
|
|
|
|
|
self.outputAreas = []
|
|
|
|
|
self.indexDict = collections.OrderedDict()
|
|
|
|
|
# 有序字典 键:总区域索引 值: [类型(输入 : 0, 或输出 : 1), 该类型的第几个区域索引]
|
|
|
|
|
|
|
|
|
|
def addArea(self, type, nums, bytes, order = 'ABCD'):
|
|
|
|
|
area = Area()
|
|
|
|
@ -29,32 +31,34 @@ class Device():
|
|
|
|
|
area.bytes = bytes
|
|
|
|
|
area.length = self.getLength(nums, bytes)
|
|
|
|
|
area.nums = nums
|
|
|
|
|
area.currentValue = [0] * nums
|
|
|
|
|
if type in ["AI", "DI"]:
|
|
|
|
|
area.startAddress = 0 if not self.inputEndAddress else self.inputEndAddress + 1
|
|
|
|
|
area.endAddress = area.startAddress + area.length
|
|
|
|
|
self.inputEndAddress = area.endAddress
|
|
|
|
|
area.addressList = np.arange(area.startAddress, area.endAddress + 1, area.bytes).tolist()
|
|
|
|
|
self.indexDict[len(self.indexDict.values())] = len(self.inputAreas)
|
|
|
|
|
self.inputAreas.append(area)
|
|
|
|
|
elif type in ["DO" , "AO"]:
|
|
|
|
|
area.startAddress = 0 if not self.outputEndAddress else self.outputEndAddress + 1
|
|
|
|
|
area.endAddress = area.startAddress + area.length
|
|
|
|
|
self.outputEndAddress = area.endAddress
|
|
|
|
|
area.addressList = np.arange(area.startAddress, area.endAddress + 1, area.bytes).tolist()
|
|
|
|
|
self.indexDict[len(self.indexDict.values())] = len(self.outputAreas)
|
|
|
|
|
self.outputAreas.append(area)
|
|
|
|
|
# print(self.inputAreas)
|
|
|
|
|
|
|
|
|
|
# print(id(self), self.outputAreas)
|
|
|
|
|
# print(area.addressList, area.startAddress, area.endAddress, self.outputAreas)
|
|
|
|
|
|
|
|
|
|
def delArea(self, index, type):
|
|
|
|
|
if type in ["DI", "AI"]:
|
|
|
|
|
self.inputAreas.pop(index)
|
|
|
|
|
self.inputAreas.pop(self.indexDict[index])
|
|
|
|
|
elif type in ["AO", "DO"]:
|
|
|
|
|
self.outputAreas.pop(index)
|
|
|
|
|
self.outputAreas.pop(self.indexDict[index])
|
|
|
|
|
# self.recalculateAddress()
|
|
|
|
|
|
|
|
|
|
def recalculateAddress(self):
|
|
|
|
|
endAddress = 0
|
|
|
|
|
for inputOrOutput, areas in enumerate([self.inputAreas, self.outputAreas]):
|
|
|
|
|
endAddress = 0
|
|
|
|
|
for index, area in enumerate(areas):
|
|
|
|
|
if index == 0 and inputOrOutput == 0:
|
|
|
|
|
area.startAddress = self.inputStartAddress
|
|
|
|
@ -64,37 +68,37 @@ class Device():
|
|
|
|
|
area.startAddress = areas[index - 1].endAddress + 1
|
|
|
|
|
area.endAddress = area.startAddress + area.length
|
|
|
|
|
area.addressList = np.arange(area.startAddress, area.endAddress + 1, area.bytes).tolist()
|
|
|
|
|
print(area.addressList, area.startAddress, area.endAddress, self.deviceName)
|
|
|
|
|
endAddress = area.endAddress
|
|
|
|
|
else:
|
|
|
|
|
if inputOrOutput == 0:
|
|
|
|
|
self.inputEndAddress = endAddress
|
|
|
|
|
elif inputOrOutput == 1:
|
|
|
|
|
self.outputEndAddress = endAddress
|
|
|
|
|
endAddress = 0
|
|
|
|
|
|
|
|
|
|
# endAddress = 0
|
|
|
|
|
# print(self.deviceName, self.inputEndAddress)
|
|
|
|
|
|
|
|
|
|
def editArea(self, index, type, order, bytes):
|
|
|
|
|
if type in ["DI", "AI"]:
|
|
|
|
|
self.inputAreas[index].type = type
|
|
|
|
|
self.inputAreas[index].order = order
|
|
|
|
|
self.inputAreas[index].bytes = bytes
|
|
|
|
|
self.inputAreas[self.indexDict[index]].order = order
|
|
|
|
|
self.inputAreas[self.indexDict[index]].bytes = bytes
|
|
|
|
|
elif type in ["AO", "DO"]:
|
|
|
|
|
self.outputAreas[index].type = type
|
|
|
|
|
self.outputAreas[index].order = order
|
|
|
|
|
self.outputAreas[index].bytes = bytes
|
|
|
|
|
self.outputAreas[self.indexDict[index]].order = order
|
|
|
|
|
self.outputAreas[self.indexDict[index]].bytes = bytes
|
|
|
|
|
# self.recalculateAddress()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getAreaValues(self, index):
|
|
|
|
|
if self.masterOrSlave == "主站"
|
|
|
|
|
if self.masterOrSlave == "从站":
|
|
|
|
|
return self.outputAreas[index].currentValue
|
|
|
|
|
else:
|
|
|
|
|
# print(self.inputAreas, index)
|
|
|
|
|
return self.inputAreas[index].currentValue
|
|
|
|
|
|
|
|
|
|
def getLength(self, nums, bytes):
|
|
|
|
|
length = int(nums) * int(bytes)
|
|
|
|
|
# length = length / 2
|
|
|
|
|
return length - 1
|
|
|
|
|
return length
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -176,9 +180,18 @@ class DevicesManange():
|
|
|
|
|
|
|
|
|
|
def recalculateAddress(self):
|
|
|
|
|
for devicesDict in [self.paMasterDevices, self.paSlaveDevices, self.dpMasterDevices, self.dpSlaveDevices]:
|
|
|
|
|
# print(len(devicesDict))
|
|
|
|
|
for index, (deviceName, device) in enumerate(devicesDict.items()):
|
|
|
|
|
device.inputStartAddress = 0 if index == 0 else list(devicesDict.values())[index - 1].inputEndAddress + 1
|
|
|
|
|
device.outputStartAddress = 0 if index == 0 else list(devicesDict.values())[index - 1].outputEndAddress + 1
|
|
|
|
|
if index == 0:
|
|
|
|
|
device.inputStartAddress = 0
|
|
|
|
|
device.outputStartAddress = 0
|
|
|
|
|
else:
|
|
|
|
|
inputAddress = list(devicesDict.values())[index - 1].inputEndAddress
|
|
|
|
|
outputAddress = list(devicesDict.values())[index - 1].outputEndAddress
|
|
|
|
|
device.inputStartAddress = 0 if inputAddress == 0 else inputAddress + 1
|
|
|
|
|
device.outputStartAddress = 0 if outputAddress == 0 else outputAddress + 1
|
|
|
|
|
# print(device.inputStartAddress, device.inputEndAddress, deviceName, '输入')
|
|
|
|
|
# print(device.outputStartAddress, device.outputEndAddress, deviceName, 'shuchu')
|
|
|
|
|
device.recalculateAddress()
|
|
|
|
|
# previousDevice = device
|
|
|
|
|
|
|
|
|
@ -189,8 +202,10 @@ class DevicesManange():
|
|
|
|
|
return devicesDict[deviceName]
|
|
|
|
|
|
|
|
|
|
def writeAreas(self, deviceName, values):
|
|
|
|
|
# print(values)
|
|
|
|
|
bytes = b""
|
|
|
|
|
device = self.getDevice(deviceName)
|
|
|
|
|
# print(device, deviceName)
|
|
|
|
|
if device.type == "DP" and device.masterOrSlave == "主站":
|
|
|
|
|
curProDict = self.dpMasterDevices
|
|
|
|
|
areas = device.outputAreas
|
|
|
|
@ -207,58 +222,73 @@ class DevicesManange():
|
|
|
|
|
areas = device.inputAreas
|
|
|
|
|
curProDict = self.paSlaveDevices
|
|
|
|
|
modbusM = self.paSlaveModbus
|
|
|
|
|
# print(values)
|
|
|
|
|
for area, value in zip(areas, values):
|
|
|
|
|
area.forceValue = value
|
|
|
|
|
if area.type in ['DI', 'DO']:
|
|
|
|
|
area.forceValue = value[8:] + value[:8]
|
|
|
|
|
|
|
|
|
|
for device in curProDict.values():
|
|
|
|
|
forceAreas = device.outputAreas if device.masterOrSlave == "主站" else device.inputAreas
|
|
|
|
|
for area in forceAreas:
|
|
|
|
|
# print(area.type)
|
|
|
|
|
# print(area.forceValue)
|
|
|
|
|
if area.type in ["AI", "AO"]:
|
|
|
|
|
byte = floatToBytes(area.forceValue, area.bytes, order = area.order)
|
|
|
|
|
elif area.type in ["DI", "DO"]:
|
|
|
|
|
if device.type == "PA" and device.masterOrSlave == "从站" and len(area.forceValue) == 16:
|
|
|
|
|
area.forceValue = area.forceValue[8:] + area.forceValue[:8]
|
|
|
|
|
# if device.type == "PA" and device.masterOrSlave == "从站" and len(area.forceValue) == 16:
|
|
|
|
|
byte = coilsToBytes([int(x) for x in area.forceValue], area.bytes)
|
|
|
|
|
bytes += byte
|
|
|
|
|
else:
|
|
|
|
|
if len(bytes) % 2 != 0:
|
|
|
|
|
bytes += struct.pack('B', 0)
|
|
|
|
|
# print(bytes)
|
|
|
|
|
values = struct.unpack('!' + 'H' * int(len(bytes) / 2), bytes)
|
|
|
|
|
modbusM.writeMultipleRegister(slaveId = 1, address = 0, outputValue = values)
|
|
|
|
|
# print(struct.unpack('>f', struct.pack('!HH', *values[:2])))
|
|
|
|
|
|
|
|
|
|
def readAreas(self):
|
|
|
|
|
for index, curProDict enumerate(devicesDict) in [self.paMasterDevices, self.paSlaveDevices, self.dpMasterDevices, self.dpSlaveDevices]:
|
|
|
|
|
for index, curProDict in enumerate([self.paMasterDevices, self.paSlaveDevices, self.dpMasterDevices, self.dpSlaveDevices]):
|
|
|
|
|
match index:
|
|
|
|
|
case 0:
|
|
|
|
|
areaType = 'output'
|
|
|
|
|
areaType = 'input'
|
|
|
|
|
modbusM = self.paMasterModbus
|
|
|
|
|
case 1:
|
|
|
|
|
areaType = 'input'
|
|
|
|
|
modbusM = self.paSlaverModbus
|
|
|
|
|
case 2:
|
|
|
|
|
areaType = 'output'
|
|
|
|
|
modbusM = self.paSlaveModbus
|
|
|
|
|
case 2:
|
|
|
|
|
areaType = 'input'
|
|
|
|
|
modbusM = self.dpMasterModbus
|
|
|
|
|
case 3:
|
|
|
|
|
areaType = 'input'
|
|
|
|
|
modbusM = self.dpSlaverModbus
|
|
|
|
|
lastDevice = list(curProDict.values())[-1]
|
|
|
|
|
bytesNums = lastDevice.inputEndAddress if areaType == 'input' else lastDevice.outputEndAddress
|
|
|
|
|
areaType = 'output'
|
|
|
|
|
modbusM = self.dpSlaveModbus
|
|
|
|
|
if len(list(curProDict.values())) == 0:
|
|
|
|
|
continue
|
|
|
|
|
inputEndAddress = max([x.inputEndAddress for x in list(curProDict.values())])
|
|
|
|
|
outputEndAddress = max([x.outputEndAddress for x in list(curProDict.values())])
|
|
|
|
|
bytesNums = inputEndAddress if areaType == 'input' else outputEndAddress
|
|
|
|
|
intNums = int(bytesNums / 2) if bytesNums % 2 == 0 else int(bytesNums / 2) + 1
|
|
|
|
|
intValues = modbusM.readHoldingRegisters(slaveId = 1, startAddress = 0, intNums)
|
|
|
|
|
bytesValues = struct.pack(f"!{'H' * len(intValues)}")
|
|
|
|
|
if bytesNums == 0:
|
|
|
|
|
continue
|
|
|
|
|
intValues = modbusM.readHoldingRegisters(slaveId = 1, startAddress = 0, varNums = intNums)
|
|
|
|
|
bytesValues = struct.pack(f"!{'H' * len(intValues)}", *intValues)
|
|
|
|
|
for device in curProDict.values():
|
|
|
|
|
readAreas = device.inputAreas if areaType == 'input' else device.outputAreas
|
|
|
|
|
for area in readAreas:
|
|
|
|
|
bytes = bytesValues[area.startAddress, area.endAddress + 1]
|
|
|
|
|
if area.startAddress == 0:
|
|
|
|
|
bytes = bytesValues[area.startAddress:area.endAddress]
|
|
|
|
|
else:
|
|
|
|
|
bytes = bytesValues[area.startAddress - 1:area.endAddress]
|
|
|
|
|
|
|
|
|
|
if area.type in ['AI', 'AO']:
|
|
|
|
|
for i in range(0, len(bytes), 4):
|
|
|
|
|
byte = byte[i:i+4]
|
|
|
|
|
byte = bytes[i:i+4]
|
|
|
|
|
if len(byte) != 4:
|
|
|
|
|
return
|
|
|
|
|
area.currentValue[i] = struct.unpack('!f', reorderBytes(byte))
|
|
|
|
|
continue
|
|
|
|
|
area.currentValue[i] = round(struct.unpack('!f', reorderBytes(byte, area.order))[0], 4)
|
|
|
|
|
elif area.type in ['DI', 'DO']:
|
|
|
|
|
area.currentValue = bytesToCoils(byte)
|
|
|
|
|
bytes = bytes[::-1]
|
|
|
|
|
area.currentValue = bytesToCoils(bytes)
|
|
|
|
|
# print(area.currentValue)
|
|
|
|
|
@classmethod
|
|
|
|
|
def addAreas(self, type, order, bytes, deviceName):
|
|
|
|
|
if DeviceDB.getByName(deviceName=deviceName).areaJson is None:
|
|
|
|
|