diff options
Diffstat (limited to 'ebustest.py')
-rw-r--r-- | ebustest.py | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/ebustest.py b/ebustest.py new file mode 100644 index 0000000..e9b7d2e --- /dev/null +++ b/ebustest.py @@ -0,0 +1,166 @@ +# -*- coding:utf8 -*- +import asynchat +import asyncore +import socket +import sys +import json +# Master-Master +# 1 quell +# 1 ziel +# 1 1primaerbefehl +# 1 sekundaerbefehl +# 1 n=laenge (bytes) +# n daten.... +# 1 CRC +# 1 ack (=0x00 || 0xff) +# 1 syn (=0xaa) + +# Master-Slave +# 1 quell +# 1 ziel +# 1 1primaerbefehl +# 1 sekundaerbefehl +# 1 n=laenge (bytes) +# n daten vom master/Anfrage.... +# 1 CRC +# 1 ack (=0x00 || 0xff) +# 1 m=länge (bytes) +# m daten vom slave/Antwort... +# 1 syn (=0xaa) +deviceDescription = [ + {'address':0x03, 'type':'master', 'description':'Feuerungsautomat'}, + {'address':0x10, 'type':'master', 'description':'Heizungsregler #2'}, + {'address':0x30, 'type':'master', 'description':'Heizkreisregler 1'}, + {'address':0x70, 'type':'master', 'description':'Heizkreisregler 2'}, + {'address':0x71, 'type':'master', 'description':'Heizungsregler #9'}, + {'address':0xf1, 'type':'master', 'description':'Heizungsregler #10'}, + {'address':0x50, 'type':'slave', 'description':'Mischer 1'}, + {'address':0x51, 'type':'slave', 'description':'Mischer 2'}, + {'address':0xfe, 'type':'broadcast', 'description':'Broadcast'}, +] + +packetDescription = [ + {'primary':0x7, 'secondary':0x9, 'name':'UNKNOWN'}, + {'primary':0x14, 'secondary':0x7, 'name':'UNKNOWN'}, + # Response + #p[0] = Einheit (1=>Liter, 2=>Kubik) + #p[1] = 10^0 + #p[2] = 10^2 + #p[3] = 10^4 + #p[4] = 10^6 + {'primary':0x3, 'secondary':0x8, 'name':'Gesamtbrennstoffmengenzähle lesen'}, + {'primary':''}, +] + +def formatHex(data): + return " ".join(map(lambda byte: "%.2x"%ord(byte), data)) + +def getDsc(address): + dev=filter(lambda dev: dev['address'] == address, deviceDescription) + if len(dev)>0: + return dev[0]['description'] + else: + return None + +class EbusPacket(object): + def __init__(self, source, destination, primary_command, secondary_command): + self.source = source + self.destination = destination + self.primary_command = primary_command + self.secondary_command = secondary_command + + def name(self): + desc = filter(lambda p: p['primary'] == self.primary_command \ + and p['secondary'] == self.secondary_command, packetDescription) + if len(desc) > 0: + return desc[0]['name'] + else: + return "UNKNOWN" + + def __str__(self): + return "<%-18s name=\"%-15s\" source=\"%s\" destination=\"%s\" primary=0x%x secondary=0x%x>" % \ + (self.__class__.__name__, self.name(), getDsc(self.source), getDsc(self.destination), \ + self.primary_command, self.secondary_command) + +class EbusMasterMaster(EbusPacket): + def __init__(self, source, destination, primary_command, secondary_command, data): + EbusPacket.__init__(self, source, destination, primary_command, secondary_command) + self.data = data + + +class EbusMasterSlave(EbusPacket): + def __init__(self, source, destination, primary_command, secondary_command, request, response): + EbusPacket.__init__(self, source, destination, primary_command, secondary_command) + self.request = request + self.response = response + +class EbusBroadcast(EbusPacket): + def __init__(self, source, destination, primary_command, secondary_command, data): + EbusPacket.__init__(self, source, destination, primary_command, secondary_command) + self.data = data + + + +class Fetcher(asynchat.async_chat): + def __init__(self): + self.buffer = "" + + asynchat.async_chat.__init__(self) + self.set_terminator("") + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.connect(("10.2.2.200", 7970)) + + self.packetIndex = 0 + self.buf = "" + + def collect_incoming_data(self,data): + for it in range(len(data)): + if data[it] == "\xaa": + if it+1 < len(data) and data[it+1] != "\xaa": + self._parse(self.buf) + self.buf = "" + self.packetIndex = 0 + else: + self.buf += data[it] + self.packetIndex = self.packetIndex + 1 + #print "%.2x [%d]" % (ord(data[it]),self.packetIndex) + + def _parse(self,data): + if len(data) < 2: + print "GAGA" + return + source = ord(data[0]) + destination = ord(data[1]) + + sourceDevice = filter(lambda dev: dev['address'] == source, deviceDescription) + destinationDevice = filter(lambda dev: dev['address'] == destination, deviceDescription) + if len(sourceDevice) == 0 or len(destinationDevice) == 0: + print "Unbekanntes Paket: source=%x destination=%x" % (source, destination) + return + + if len(data) < 9: + print "Unvollständige Daten" + return + + primaryCommand = ord(data[3]) + secondaryCommand = ord(data[4]) + payloadLength = ord(data[5]) + payload = data[6:6+payloadLength] + p = None + if sourceDevice[0]['type'] == 'master' and destinationDevice[0]['type'] == 'master': + p = EbusMasterMaster(source, destination, primaryCommand, secondaryCommand, payload) + print p + print "payload=%s" % formatHex(payload) + elif sourceDevice[0]['type'] == 'master' and destinationDevice[0]['type'] == 'slave': + p = EbusMasterSlave(source, destination, primaryCommand, secondaryCommand, None, None) + print p + elif sourceDevice[0]['type'] == 'master' and destinationDevice[0]['type'] == 'broadcast': + p = EbusBroadcast(source, destination, primaryCommand, secondaryCommand, payload) + print p + print "payload=%s" % formatHex(payload) + else: + print "KOMISCHES ZEUG" + return + +Fetcher() +asyncore.loop() |