MeterbusLib/MeterbusLib.py

155 lines
4.6 KiB
Python
Raw Normal View History

2015-06-11 17:16:27 +02:00
'''
Created on 11.06.2015
@author: wn
'''
import MeterbusTypeConversion
class MeterbusLibException(Exception):
pass
class InvalidFrameCodeException(MeterbusLibException):
pass
class InvalidFrameException(MeterbusLibException):
pass
class InvalidChecksumException(MeterbusLibException):
pass
class InvalidStopCharException(MeterbusLibException):
pass
class InvalidStartCharException(MeterbusLibException):
pass
class InvalidLengthException(MeterbusLibException):
pass
class InvalidSecondLengthException(MeterbusLibException):
pass
class PayloadTooShortException(MeterbusLibException):
pass
class Frame(object):
def __init__(self, startCharacter, frameLength, firstPayload, telegram):
self.telegram = telegram
self.frameName = self.__class__.__name__
self.frameLength = frameLength
self.payloadLength = self.frameLength - 6
self.frameStartCharacter = startCharacter
self.firstPayload = firstPayload
def parse(self):
if self.telegram[0] != self.frameStartCharacter:
raise InvalidStartCharException()
if len(self.telegram) != self.frameLength:
raise InvalidLengthException()
self.verifyChecksumAndEnd()
self.parse2()
def verifyChecksumAndEnd(self):
if (self.firstPayload != 0):
checksum = sum(self.telegram[self.firstPayload:-2]) & 0xff
if checksum != self.telegram[-2]:
raise InvalidChecksumException()
if self.telegram[-1] != 0x16:
raise InvalidStopCharException()
def parse2(self):
raise NotImplementedError
def getJSON(self):
raise NotImplementedError
class SingleCharacter(Frame):
def __init__(self, telegram):
super(SingleCharacter, self).__init__(0xe5, 1, 0, telegram)
def parse2(self):
pass
class ShortFrame(Frame):
def __init__(self, telegram):
super(ShortFrame, self).__init__(0x10, 5, 1, telegram)
def parse2(self):
self.cField = self.telegram[1]
self.address = self.telegram[2]
class ControlFrame(Frame):
def __init__(self, telegram):
super(ControlFrame, self).__init__(0x68, (telegram[1] + 6), 4, telegram)
def parse2(self):
if self.telegram[2] != self.payloadLength:
raise InvalidSecondLengthException
if self.payloadLength < 3:
raise PayloadTooShortException("too short for c, a, ci fields")
self.cField = self.telegram[4]
self.address = self.telegram[5]
self.ciField = self.telegram[6]
class LongFrame(ControlFrame):
class FixedDataHeader(object):
def __init__(self, data):
self.data = data
print("Fixed header length: %d" % len(self.data))
def parse(self):
self.identNr = MeterbusTypeConversion.bcd(self.data[:4])
self.manufacturer = self.data[4:6]
self.version = self.data[6]
self.medium = self.data[7]
self.accessNo = self.data[8]
self.status = self.data[9]
self.signature = self.data[10:]
def parse2(self):
super(LongFrame, self).parse2()
if self.payloadLength < 3 + 12:
raise PayloadTooShortException("too short for fixed data header")
self.fixedDataHeader = LongFrame.FixedDataHeader(self.telegram[7:19])
self.fixedDataHeader.parse()
class Telegram(object):
def __init__(self):
pass
def fromHexString(self, hexString):
self.hexString = hexString
octetList = [int(o, 16) for o in self.hexString.split(' ')]
self.telegram = bytearray(octetList)
for i in self.telegram:
print(int(i))
def toHexString(self):
return str([hex(b) for b in self.telegram])
def parse(self):
if self.telegram[0] == 0x68 and self.telegram[1] == 0x03:
self.frame = ControlFrame(self.telegram)
elif self.telegram[0] == 0x68:
self.frame = LongFrame(self.telegram)
elif self.telegram[0] == 0x10:
self.frame = ShortFrame(self.telegram)
elif self.telegram[0] == 0xe5:
self.frame = SingleCharacter(self.telegram)
else:
raise InvalidStartCharException()
self.frame.parse()
print("Frame is %s" % self.frame)