seems to work
This commit is contained in:
parent
d64e8bff98
commit
88e36b0170
147
MeterbusLib.py
147
MeterbusLib.py
@ -12,6 +12,12 @@ import MeterbusTypeConversion
|
||||
from MeterbusLibExceptions import *
|
||||
import struct
|
||||
|
||||
class Device(object):
|
||||
def __init__(self, address, comment, dataItems):
|
||||
self.address = address
|
||||
self.comment = comment
|
||||
self.dataItems = dataItems
|
||||
|
||||
class Frame(object):
|
||||
def __init__(self, startCharacter, frameLength, firstPayload, telegram):
|
||||
self.telegram = telegram
|
||||
@ -88,6 +94,14 @@ class ControlFrame(Frame):
|
||||
|
||||
|
||||
class LongFrame(ControlFrame):
|
||||
def __init__(self, telegram, devices=[]):
|
||||
super(LongFrame, self).__init__(telegram)
|
||||
self.devices = devices
|
||||
if self.devices != None:
|
||||
for device in self.devices:
|
||||
if not isinstance(device, Device):
|
||||
raise InvalidDevicesStructureException()
|
||||
|
||||
class FixedDataHeader(object):
|
||||
def __init__(self, data):
|
||||
self.data = data
|
||||
@ -102,6 +116,7 @@ class LongFrame(ControlFrame):
|
||||
self.signature = [s for s in self.data[10:]]
|
||||
if self.signature[0] != 0 or self.signature[1] != 0:
|
||||
raise InvalidFrameException("signature should be zero")
|
||||
#print("FixedDataHeader: " + str(self.getJSON()))
|
||||
|
||||
def getJSON(self):
|
||||
j = {'identNr': self.identNr, 'manufacturer': self.manufacturer, 'version': self.version, 'medium': self.medium,
|
||||
@ -109,24 +124,34 @@ class LongFrame(ControlFrame):
|
||||
return j
|
||||
|
||||
class DataInformationElement(object):
|
||||
def __init__(self, data):
|
||||
def __init__(self, data, comment):
|
||||
self.data = data
|
||||
self.comment = comment
|
||||
self.consumed = 0
|
||||
|
||||
@classmethod
|
||||
def create(cls, data):
|
||||
def create(cls, data, comment):
|
||||
if data[0] != 0x0f:
|
||||
return LongFrame.DataInformationBlock(data)
|
||||
return LongFrame.DataInformationBlock(data, comment)
|
||||
else:
|
||||
return LongFrame.ManufacturerSpecificDataBlock(data)
|
||||
return LongFrame.ManufacturerSpecificDataBlock(data, comment)
|
||||
|
||||
def getJSON(self):
|
||||
j = {'comment': self.comment}
|
||||
return j
|
||||
|
||||
|
||||
class ManufacturerSpecificDataBlock(DataInformationElement):
|
||||
def parse(self):
|
||||
self.dif = self.data[0]
|
||||
self.mdh = self.data[1:]
|
||||
self.mdh = [ m for m in self.data[1:]]
|
||||
self.consumed = len(self.data)
|
||||
return self.consumed
|
||||
|
||||
def getJSON(self):
|
||||
superJSON = super(LongFrame.ManufacturerSpecificDataBlock, self).getJSON()
|
||||
j = {'dif': self.dif, 'mdh': self.mdh}
|
||||
j.update(superJSON)
|
||||
return j
|
||||
|
||||
class DataInformationBlock(DataInformationElement):
|
||||
@ -136,7 +161,7 @@ class LongFrame(ControlFrame):
|
||||
('16 Bit Integer', 2, lambda x: (x[1] << 8) + x[0]),
|
||||
('24 Bit Integer', 3, lambda x: (x[2] << 16) + (x[1] << 8) + x[0]),
|
||||
('32 Bit Integer', 4, lambda x: (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]),
|
||||
('32 Bit Real', 4, lambda x: struct.unpack('f', x.getAll())[0]),
|
||||
('32 Bit Real', 4, lambda x: struct.unpack('f', str(bytearray(x)))[0]),
|
||||
('48 Bit Integer', 6, lambda x: (x[5] << 40) + (x[4] << 32) + (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]),
|
||||
('64 Bit Integer', 8, lambda x: (x[7] << 56) + (x[6] << 48) + (x[5] << 40) + (x[4] << 32) + (x[3] << 24) + (x[2] << 16) + (x[1] << 8) + x[0]),
|
||||
('Selection for Readout', 0, None),
|
||||
@ -153,24 +178,24 @@ class LongFrame(ControlFrame):
|
||||
(0b01111000, 0b00001000, 'Energy', 'J', 0b00000111, lambda d: 10**d),
|
||||
(0b01111000, 0b00010000, 'Volume', 'm**3', 0b00000111, lambda d: 10**(d-6)),
|
||||
(0b01111000, 0b00011000, 'Mass', 'kg', 0b00000111, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b00100000, 'On Time', 'TimeCalc', 0b00000011, lambda d: d),
|
||||
(0b01111100, 0b00100100, 'Operating Time', 'TimeCalc', 0b00000011, lambda d: d),
|
||||
(0b01111100, 0b00100000, 'On Time', 'TimeCalc', 0b00000011, None),
|
||||
(0b01111100, 0b00100100, 'Operating Time', 'TimeCalc', 0b00000011, None),
|
||||
(0b01111000, 0b00101000, 'Power', 'W', 0b00000111, lambda d: 10**(d-3)),
|
||||
(0b01111000, 0b00110000, 'Power', 'J/h', 0b00000111, lambda d: 10**d),
|
||||
(0b01111000, 0b00111000, 'Volume Flow', 'm**3/h', 0b00000111, lambda d: 10**(d-6)),
|
||||
(0b01111000, 0b01000000, 'Volume Flow ext.', 'm**3/min', 0b00000111, lambda d: 10**(d-7)),
|
||||
(0b01111000, 0b01001000, 'Volume Flow ext.', 'm**3/s', 0b00000111, lambda d: 10**(d-9)),
|
||||
(0b01111000, 0b01010000, 'Mass Flow', 'kg/h', 0b00000111, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01011000, 'Flow Temperature', '°C', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01011100, 'Return Temperature', '°C', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01100000, 'Temperature Diff.', 'K', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01100100, 'Extern. Temp', '°C', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01011000, 'Flow Temperature', 'Celsius', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01011100, 'Return Temperature', 'Celsius', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01100000, 'Temperature Diff.', 'Kelvin', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01100100, 'Extern. Temp', 'Celsius', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01101000, 'Pressure', 'bar', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111110, 0b01101100, 'Time Point', 'TimePointCalc', 0b00000001,lambda d: d),
|
||||
(0b01111110, 0b01101100, 'Time Point', 'TimePointCalc', 0b00000001,None),
|
||||
(0b01111111, 0b01101110, 'Units for H.C.A.', '', 0, None),
|
||||
(0b01111111, 0b01101111, 'Reserved', '', 0, None),
|
||||
(0b01111100, 0b01110000, 'Averaging Duration', 'TimeCalc', 0b00000011, lambda d: d),
|
||||
(0b01111100, 0b01110100, 'Actuality Duration', 'TimeCalc', 0b00000011, lambda d: d),
|
||||
(0b01111100, 0b01110000, 'Averaging Duration', 'TimeCalc', 0b00000011, None),
|
||||
(0b01111100, 0b01110100, 'Actuality Duration', 'TimeCalc', 0b00000011, None),
|
||||
(0b01111111, 0b01111000, 'Fabrication Number', '', 0, None),
|
||||
(0b01111111, 0b01111001, 'Enhanced Ident.', '', 0, None),
|
||||
(0b01111111, 0b01111010, 'Bus Address', '', 0, None),
|
||||
@ -258,13 +283,13 @@ class LongFrame(ControlFrame):
|
||||
(0b01111110, 0b00101010, 'Reserved', '', 0, None),
|
||||
(0b01111100, 0b00101100, 'Reserved', '', 0, None),
|
||||
(0b01111110, 0b00110000, 'Power', 'GJ/h', 0b00000001, lambda d: 10**(d-1)),
|
||||
(0b01111100, 0b01011000, 'Flow Temperature', '°F', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01011100, 'Return Temperature', '°F', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01100000, 'Temperature Diff.', '°F', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01100100, 'Extern. Temp.', '°F', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01011000, 'Flow Temperature', 'Fahrenheit', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01011100, 'Return Temperature', 'Fahrenheit', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01100000, 'Temperature Diff.', 'Fahrenheit', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01100100, 'Extern. Temp.', 'Fahrenheit', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111000, 0b01101000, 'Reserved', '', 0, None),
|
||||
(0b01111100, 0b01110000, 'Cold/Warm Temp.Limit', '°F', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01110100, 'Cold/Warm Temp.Limit', '°C', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01110000, 'Cold/Warm Temp.Limit', 'Fahrenheit', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111100, 0b01110100, 'Cold/Warm Temp.Limit', 'Celsius', 0b00000011, lambda d: 10**(d-3)),
|
||||
(0b01111000, 0b01111000, 'cumul. count max power', 'W', 0b00000111, lambda d: 10**(d-3))
|
||||
)
|
||||
|
||||
@ -276,52 +301,50 @@ class LongFrame(ControlFrame):
|
||||
def extVifCalc(cls, table, vife):
|
||||
retDescr = 'unknown'
|
||||
retUnit = 'unknown'
|
||||
retRange = 'unknown'
|
||||
retFactor = 1
|
||||
|
||||
for vifeCode in table:
|
||||
# print vifeCode
|
||||
(mask, value, descr, unit, rangeMask, rangeFunc) = vifeCode
|
||||
(mask, value, descr, unit, factorMask, factorFunc) = vifeCode
|
||||
if (vife & mask) == value:
|
||||
if rangeFunc == None:
|
||||
retRange = 1
|
||||
if factorFunc == None:
|
||||
retFactor = 1
|
||||
else:
|
||||
rangeHelper = vife & rangeMask
|
||||
retRange = rangeFunc(rangeHelper)
|
||||
factorHelper = vife & factorMask
|
||||
retFactor = factorFunc(factorHelper)
|
||||
retDescr = descr
|
||||
retUnit = unit
|
||||
break
|
||||
return (retDescr, retUnit, retRange)
|
||||
return (retDescr, retUnit, retFactor)
|
||||
|
||||
|
||||
@classmethod
|
||||
def vifCalc(cls, vif, vife):
|
||||
retDescr = 'unknown'
|
||||
retUnit = 'unknown'
|
||||
retRange = 1
|
||||
retFactor = 1
|
||||
for vifCode in cls.VIF_CODES:
|
||||
(mask, value, descr, unit, rangeMask, rangeFunc) = vifCode
|
||||
(mask, value, descr, unit, factorMask, factorFunc) = vifCode
|
||||
if (vif & mask) == value:
|
||||
if unit == 'TimeCalc':
|
||||
retDescr = descr
|
||||
retUnit = cls.TIME_UNITS[vif & rangeMask]
|
||||
retRange = None
|
||||
elif unit == 'Table8.4.4a':
|
||||
(retDescr, retUnit, retRange) = cls.extVifCalc(cls.TABLE844a, vife[0])
|
||||
elif unit == 'Table8.4.4b':
|
||||
(retDescr, retUnit, retRange) = cls.extVifCalc(cls.TABLE844b, vife[0])
|
||||
retUnit = cls.TIME_UNITS[vif & factorMask]
|
||||
elif unit == 'TimePointCalc':
|
||||
retDescr = descr
|
||||
retUnit = cls.TIME_POINT_UNITS[vif & rangeMask]
|
||||
retRange = None
|
||||
retUnit = cls.TIME_POINT_UNITS[vif & factorMask]
|
||||
elif unit == 'Table8.4.4a':
|
||||
(retDescr, retUnit, retFactor) = cls.extVifCalc(cls.TABLE844a, vife[0])
|
||||
elif unit == 'Table8.4.4b':
|
||||
(retDescr, retUnit, retFactor) = cls.extVifCalc(cls.TABLE844b, vife[0])
|
||||
else:
|
||||
retDescr = descr
|
||||
retUnit = unit
|
||||
if rangeFunc != None:
|
||||
rangeHelper = vif & rangeMask
|
||||
retRange = rangeFunc(rangeHelper)
|
||||
if factorFunc != None:
|
||||
factorHelper = vif & factorMask
|
||||
retFactor = factorFunc(factorHelper)
|
||||
break
|
||||
# print("vifCalc: %s %s %s %s" % (retDescr, retRange, retUnit, rangeHelper))
|
||||
return (retDescr, retUnit, retRange)
|
||||
return (retDescr, retUnit, retFactor)
|
||||
|
||||
|
||||
def parse(self):
|
||||
@ -355,19 +378,28 @@ class LongFrame(ControlFrame):
|
||||
self.userData = [u for u in self.data[self.consumed:self.consumed+userDataLength]]
|
||||
self.consumed += userDataLength
|
||||
|
||||
self.value = LongFrame.DataInformationBlock.DATA_FIELD_CODES[self.dif & 0x0f][2](self.userData)
|
||||
dataConvFunc = LongFrame.DataInformationBlock.DATA_FIELD_CODES[self.dif & 0x0f][2]
|
||||
if dataConvFunc == None:
|
||||
self.rawValue = 0
|
||||
else:
|
||||
self.rawValue = dataConvFunc(self.userData)
|
||||
self.dataType = LongFrame.DataInformationBlock.DATA_FIELD_CODES[self.dif & 0x0f][0]
|
||||
(self.quantity, self.unit, self.factor) = LongFrame.DataInformationBlock.vifCalc(self.vif, self.vife)
|
||||
self.value = self.rawValue * self.factor
|
||||
|
||||
return self.consumed
|
||||
|
||||
|
||||
def getJSON(self):
|
||||
superJSON = super(LongFrame.DataInformationBlock, self).getJSON()
|
||||
j = {'dif': self.dif, 'dife': self.dife, 'vif': self.vif, 'vife': self.vife,
|
||||
'vifData': self.vifData, 'userData':self.userData,
|
||||
'dataType': self.dataType, 'value':self.value,
|
||||
'dataType': self.dataType, 'rawValue':self.rawValue,
|
||||
'value': self.value,
|
||||
'quantity': self.quantity, 'factor': self.factor, 'unit': self.unit,
|
||||
'comment': self.comment
|
||||
}
|
||||
j.update(superJSON)
|
||||
return j
|
||||
|
||||
|
||||
@ -378,11 +410,27 @@ class LongFrame(ControlFrame):
|
||||
raise PayloadTooShortException("too short for fixed data header")
|
||||
self.fixedDataHeader = LongFrame.FixedDataHeader(self.telegram[7:19])
|
||||
self.fixedDataHeader.parse()
|
||||
device = None
|
||||
for d in self.devices:
|
||||
if d.address == self.address:
|
||||
print("device found")
|
||||
device = d
|
||||
break
|
||||
if device != None:
|
||||
self.comment = device.comment
|
||||
else:
|
||||
self.comment = '-'
|
||||
self.dib = []
|
||||
consumed = 0
|
||||
dibIndex = 0
|
||||
#print("Telegram length: %d" % len(self.telegram))
|
||||
while True:
|
||||
curDib = LongFrame.DataInformationElement.create(self.telegram[(19 + consumed):-2])
|
||||
if device != None:
|
||||
comment = device.dataItems[dibIndex]
|
||||
else:
|
||||
comment = '-'
|
||||
dibIndex += 1
|
||||
curDib = LongFrame.DataInformationElement.create(self.telegram[(19 + consumed):-2], comment)
|
||||
consumed += curDib.parse()
|
||||
self.dib.append(curDib)
|
||||
#print("PayloadLength: %d, Consumed: %d" % (self.payloadLength, consumed))
|
||||
@ -391,15 +439,16 @@ class LongFrame(ControlFrame):
|
||||
if (consumed + 3 + 12 + 2 - 1) >= self.payloadLength:
|
||||
break
|
||||
|
||||
|
||||
def getJSON(self):
|
||||
superJSON = super(LongFrame, self).getJSON()
|
||||
j = {'header': self.fixedDataHeader.getJSON(), 'dib': [dib.getJSON() for dib in self.dib]}
|
||||
j = {'comment': self.comment, 'header': self.fixedDataHeader.getJSON(), 'dib': [dib.getJSON() for dib in self.dib]}
|
||||
j.update(superJSON)
|
||||
return j
|
||||
|
||||
class Telegram(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
def __init__(self, devices=[]):
|
||||
self.devices = devices
|
||||
|
||||
def fromHexString(self, hexString):
|
||||
self.hexString = hexString
|
||||
@ -413,7 +462,7 @@ class Telegram(object):
|
||||
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)
|
||||
self.frame = LongFrame(self.telegram, self.devices)
|
||||
elif self.telegram[0] == 0x10:
|
||||
self.frame = ShortFrame(self.telegram)
|
||||
elif self.telegram[0] == 0xe5:
|
||||
|
@ -33,3 +33,9 @@ class PayloadTooShortException(MeterbusLibException):
|
||||
|
||||
class MediumConversionException(MeterbusLibException):
|
||||
pass
|
||||
|
||||
class InvalidDevicesStructureException(MeterbusLibException):
|
||||
pass
|
||||
|
||||
class DeviceItemsMismatchException(MeterbusLibException):
|
||||
pass
|
||||
|
@ -13,6 +13,7 @@ def bcd(data):
|
||||
for c in reversed(data):
|
||||
v += str((c & 0xf0) >> 4)
|
||||
v += str(c & 0x0f)
|
||||
v = int(v)
|
||||
return v
|
||||
|
||||
def manufCode(data):
|
||||
|
16
test1.py
16
test1.py
@ -53,7 +53,7 @@ class TestFrameParsing(unittest.TestCase):
|
||||
self.assertEqual(telegram.frame.cField, 0x08);
|
||||
self.assertEqual(telegram.frame.address, 0x53);
|
||||
self.assertEqual(telegram.frame.ciField, 0x72);
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, "17001300")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, 130017)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.manufacturer, "FIN")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.version, 36)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.medium, "Electrity")
|
||||
@ -79,7 +79,7 @@ class TestFrameParsing(unittest.TestCase):
|
||||
self.assertEqual(telegram.frame.cField, 0x08);
|
||||
self.assertEqual(telegram.frame.address, 0x50);
|
||||
self.assertEqual(telegram.frame.ciField, 0x72);
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, "81140111")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, 11011481)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.manufacturer, "FIN")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.version, 22)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.medium, "Electrity")
|
||||
@ -92,7 +92,7 @@ class TestFrameParsing(unittest.TestCase):
|
||||
self.assertEqual(telegram.frame.cField, 0x08);
|
||||
self.assertEqual(telegram.frame.address, 0x30);
|
||||
self.assertEqual(telegram.frame.ciField, 0x72);
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, "45714300")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, 437145)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.manufacturer, "HYD")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.version, 37)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.medium, "Water")
|
||||
@ -106,7 +106,7 @@ class TestFrameParsing(unittest.TestCase):
|
||||
self.assertEqual(telegram.frame.cField, 0x08);
|
||||
self.assertEqual(telegram.frame.address, 0x40);
|
||||
self.assertEqual(telegram.frame.ciField, 0x72);
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, "43605200")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, 526043)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.manufacturer, "ACW")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.version, 20)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.medium, "Gas")
|
||||
@ -119,7 +119,7 @@ class TestFrameParsing(unittest.TestCase):
|
||||
self.assertEqual(telegram.frame.cField, 0x08);
|
||||
self.assertEqual(telegram.frame.address, 0x21);
|
||||
self.assertEqual(telegram.frame.ciField, 0x72);
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, "00000000")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.identNr, 0)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.manufacturer, "@@@")
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.version, 1)
|
||||
self.assertEqual(telegram.frame.fixedDataHeader.medium, "Other")
|
||||
@ -178,9 +178,9 @@ class TestFrameParsing(unittest.TestCase):
|
||||
telegram.parse()
|
||||
|
||||
def test_bcd(self):
|
||||
self.assertEqual(MeterbusTypeConversion.bcd([0x99]), '99')
|
||||
self.assertEqual(MeterbusTypeConversion.bcd([0x12, 0x34]), '1234')
|
||||
self.assertEqual(MeterbusTypeConversion.bcd([0x12, 0x34, 0x56, 0x78]), '12345678')
|
||||
self.assertEqual(MeterbusTypeConversion.bcd([0x99]), 99)
|
||||
self.assertEqual(MeterbusTypeConversion.bcd([0x12, 0x34]), 3412)
|
||||
self.assertEqual(MeterbusTypeConversion.bcd([0x12, 0x34, 0x56, 0x78]), 78563412)
|
||||
|
||||
def test_manufCode(self):
|
||||
self.assertEqual(MeterbusTypeConversion.manufCode([0x77, 0x04]), 'ACW')
|
||||
|
22
test2.py
22
test2.py
@ -8,11 +8,29 @@ Created on 11.06.2015
|
||||
import MeterbusLib
|
||||
import json
|
||||
|
||||
devices = []
|
||||
device_1phase_electric = MeterbusLib.Device(0x53, "1 Phase Electric", ["Energy total", "Energy partial", "Voltage", "Current", "Power", "img. Power"])
|
||||
devices.append(device_1phase_electric)
|
||||
inputOkLongFrame_1phase_electric = "68 38 38 68 " + "08 53 72 " + "17 00 13 00 2E 19 24 02 D6 00 00 00 " + "8C 10 04 01 02 00 00 " + "8C 11 04 01 02 00 00 " + "02 FD C9 FF 01 E4 00 " + "02 FD DB FF 01 03 00 " + "02 AC FF 01 01 00 " + "82 40 AC FF 01 FA FF " + "20 16"
|
||||
device_3phase_electric = MeterbusLib.Device(0x50, "3 Phase Electric", ["Energy T1 total", "Energy T1 partial", "Energy T2 total", "Energy T2 partial",
|
||||
"Voltage phase 1", "Current phase 1", "Power phase 1", "img. Power phase 1",
|
||||
"Voltage phase 2", "Current phase 2", "Power phase 2", "img. Power phase 2",
|
||||
"Voltage phase 3", "Current phase 3", "Power phase 3", "img. Power phase 3",
|
||||
"converter ratio", "Power total", "img. Power total", "tariff"
|
||||
])
|
||||
devices.append(device_3phase_electric)
|
||||
inputOkLongFrame_3phase_electric = "68 92 92 68 08 50 72 81 14 01 11 2E 19 16 02 88 00 00 00 8C 10 04 58 43 86 00 8C 11 04 58 43 86 00 8C 20 04 00 00 00 00 8C 21 04 00 00 00 00 02 FD C9 FF 01 E4 00 02 FD DB FF 01 5A 00 02 AC FF 01 D2 00 82 40 AC FF 01 00 00 02 FD C9 FF 02 DF 00 02 FD DB FF 02 0F 00 02 AC FF 02 21 00 82 40 AC FF 02 FD FF 02 FD C9 FF 03 E3 00 02 FD DB FF 03 04 00 02 AC FF 03 02 00 82 40 AC FF 03 F4 FF 02 FF 68 00 00 02 AC FF 00 F5 00 82 40 AC FF 00 F1 FF 01 FF 13 00 F4 16"
|
||||
device_thermometer = MeterbusLib.Device(0x21, "Thermometer", ["Uptime Seconds", "Uptime Minutes", "Uptime Hours", "Uptime Days",
|
||||
"Temperature 1", "Temperature 2", "Temperature 3", "Temperature 4",
|
||||
"rawdata"
|
||||
])
|
||||
devices.append(device_thermometer)
|
||||
inputOkLongFrame_thermometer = "68 61 61 68 08 21 72 00 00 00 00 00 00 01 00 7F 00 00 00 01 24 02 01 25 30 01 26 10 02 27 07 00 05 67 43 B6 DA 3D 05 67 DC 90 50 BD 05 67 AA E8 AA 41 05 67 AF 57 BA 41 0F 77 C0 00 00 7F 27 00 00 0A 00 00 00 00 00 00 00 01 00 00 00 A2 C3 7F 3F A5 BA 7F 3F 85 A7 7F 3F E7 F9 7F 3F CD CC CC 3D E8 03 00 00 02 16"
|
||||
inputOkLongFrame_water = "68 46 46 68 08 30 72 45 71 43 00 24 23 25 07 F6 00 00 00 0C 13 97 95 43 00 8C 10 13 00 00 00 00 0B 3B 00 00 00 0B 26 14 60 01 02 5A AC 00 04 6D 14 0E EB 16 4C 13 96 41 33 00 CC 10 13 00 00 00 00 42 6C DF 1C 42 EC 7E FF 1C 99 16"
|
||||
inputOkLongFrame_gas = "68 56 56 68 08 40 72 43 60 52 00 77 04 14 03 FF 10 00 00 0C 78 76 03 01 10 0D 7C 08 44 49 20 2E 74 73 75 63 0A 30 30 30 30 30 30 30 30 30 30 04 6D 06 0E EB 16 02 7C 09 65 6D 69 74 20 2E 74 61 62 A3 09 04 13 98 AE 04 00 04 93 7F 4E 01 00 00 44 13 FC A5 04 00 0F 01 00 1F 51 16"
|
||||
|
||||
telegram = MeterbusLib.Telegram()
|
||||
telegram.fromHexString(inputOkLongFrame_3phase_electric)
|
||||
telegram = MeterbusLib.Telegram(devices)
|
||||
telegram.fromHexString(inputOkLongFrame_thermometer)
|
||||
telegram.parse()
|
||||
|
||||
print(json.dumps(telegram.getJSON(), indent=2))
|
||||
|
Loading…
x
Reference in New Issue
Block a user