summaryrefslogtreecommitdiff
path: root/ebustest.py
diff options
context:
space:
mode:
Diffstat (limited to 'ebustest.py')
-rw-r--r--ebustest.py166
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()