You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.6 KiB
114 lines
3.6 KiB
import struct
|
|
from .CRC16 import modbus_crc16
|
|
|
|
|
|
def get_bit(byte, position):
|
|
return (byte >> position) & 1
|
|
|
|
|
|
class IdiBusMES:
|
|
def __init__(self, data: bytearray):
|
|
if len(data) == 0:
|
|
raise TypeError("Data is an empty bytearray")
|
|
self.data = data
|
|
def validate(self):
|
|
if self.getCRC() != modbus_crc16(self.data[0:-2]):
|
|
return -1
|
|
else:
|
|
return 0
|
|
def getAddress(self):
|
|
return int(self.data[0])
|
|
def getCRC(self):
|
|
return self.data[-2::]
|
|
def __repr__(self):
|
|
return f"Addr:{self.getAddress()}, Body:{self.data[1::]}"
|
|
class IdiBusMMESParser(IdiBusMES):
|
|
def __init__(self, data: bytearray):
|
|
super().__init__(data)
|
|
def getMMPS(self):
|
|
return self.data[1]
|
|
def getLongMes(self):
|
|
return get_bit(int(self.data[1]), 0)
|
|
def getMesType(self):
|
|
return get_bit(int(self.data[1]), 1)
|
|
def getAlarm(self):
|
|
return get_bit(int(self.data[1]), 6)
|
|
def getEncStatus(self):
|
|
return get_bit(int(self.data[1]), 7)
|
|
def getDEV(self):
|
|
return int(self.data[2])
|
|
def getCHAN(self):
|
|
return int(self.data[3])
|
|
def getCMD(self):
|
|
return int(self.data[4])
|
|
def getData(self):
|
|
return self.data[4:-2]
|
|
|
|
class IdiBusMMESGParser(IdiBusMES):
|
|
def __init__(self, data: bytearray):
|
|
super().__init__(data)
|
|
def getMMPS(self):
|
|
return int(self.data[1])
|
|
def getCMD(self):
|
|
return int(self.data[2])
|
|
def getData(self):
|
|
return self.data[3:-2]
|
|
class IdiBusSMESParser(IdiBusMES):
|
|
def __init__(self, data: bytearray):
|
|
super().__init__(data)
|
|
def getSPDU(self):
|
|
return int(self.data[1])
|
|
def getErrorBit(self):
|
|
return get_bit(self.data[1], 0)
|
|
def getLongMessage(self):
|
|
return get_bit(self.data[1], 1)
|
|
def getErrcode(self):
|
|
return int(self.data[2])
|
|
def getData(self):
|
|
return self.data[3:-2]
|
|
def getDataStruct(self, format_string):
|
|
try:
|
|
unpacked = struct.unpack(format_string, self.getData())
|
|
return unpacked
|
|
except struct.error as e:
|
|
print(f"Parse error: {e}")
|
|
return None
|
|
except UnicodeDecodeError as e:
|
|
print(f"Parse error: {e}")
|
|
return None
|
|
class IdiBusDeviceInfoParser():
|
|
# Формат: 'B H I f 10s'
|
|
# B - unsigned char (1 байт)
|
|
# H - unsigned short (2 байта)
|
|
# I - unsigned int (4 байта)
|
|
# f - float (4 байта)
|
|
# 10s - строка из 10 байт
|
|
format_string = '<B 3s 6s 3s 2B 7s 6s 2B I'
|
|
def __init__(self, data: bytearray):
|
|
if len(data) == 0:
|
|
raise TypeError("Data is an empty bytearray")
|
|
self.data = data
|
|
#print(data[-4::])
|
|
def getStruct(self):
|
|
try:
|
|
unpacked = struct.unpack(self.format_string, self.data)
|
|
packed = {
|
|
'Padding': unpacked[0],
|
|
'GS1_country': unpacked[1].decode('utf-8'),
|
|
'GS1_company': unpacked[2].decode('utf-8'),
|
|
'ModuleType': unpacked[3].decode('utf-8'),
|
|
'HW_revison': str(unpacked[4]) +"." + str(unpacked[5]),
|
|
'SN': unpacked[6].decode('utf-8'),
|
|
'MAC': unpacked[7].decode('utf-8'),
|
|
'SW': str(unpacked[8]) + "." + str(unpacked[9]),
|
|
'AppCRC': hex(unpacked[10]),
|
|
}
|
|
return packed
|
|
except struct.error as e:
|
|
print(f"Parse error: {e}")
|
|
return None
|
|
except UnicodeDecodeError as e:
|
|
print(f"Parse error: {e}")
|
|
return None
|
|
|