# -*- 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()