diff options
-rw-r--r-- | ebustest.py | 112 |
1 files changed, 75 insertions, 37 deletions
diff --git a/ebustest.py b/ebustest.py index c9531eb..908e2da 100644 --- a/ebustest.py +++ b/ebustest.py @@ -3,30 +3,7 @@ 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'}, @@ -41,27 +18,86 @@ deviceDescription = [ {'address':0xfe, 'type':'broadcast', 'description':'Broadcast'}, ] +"""ebus specific data field formats""" class fields: class DataField(object): def __init__(self, offset): self.offset = offset - def value(self,payload): + def value(self,data): raise NotImplemented() class Data2c(DataField): - def value(self,payload): - highByte = ord(payload[self.offset+1]) - lowByte= ord(payload[self.offset]) - return highByte*16 + (lowByte>>4) + (lowByte&0xf)/16.0 + """ + Beispiel für die Berechnung: + if ((x & 8000h) == 8000h) // y negativ + y = - [dez(High_Byte(!x)) 16 + dez(High_Nibble (Low_Byte (!x))) + + (dez(Low_Nibble (Low_Byte (!x))) +1 ) / 16] + else // y positiv + y = dez(High_Byte(x)) 16 + dez(High_ Nibble (Low Byte (x))) + + dez(Low_ Nibble (Low Byte (x))) / 16 + """ + def value(self,data): + highByte = ord(data[self.offset+1]) + lowByte= ord(data[self.offset]) + if (0x8000 & (highByte<<8 | lowByte)) == 0x8000: + return (-1) * ( (0xff^highByte)*16 + (0xf^(lowByte>>4)) + (0x0f^(0x0&flowByte) + 1)/16.0 ) + else: + return highByte*16 + (lowByte>>4) + (lowByte&0xf)/16.0 + + class Data2b(DataField): + """ + if ((x&8000h) == 8000h) // y negativ + y = - [dez(High_Byte(!x)) + (dez(Low_Byte(!x)) + 1) / 256] + else // y positiv + y = dez(High_Byte (x)) + dez(Low_Byte (x)) / 256 + """ + def value(self,data): + highByte = ord(data[self.offset+1]) + lowByte= ord(data[self.offset]) + if (0x8000 & (highByte<<8 | lowByte)) == 0x8000: + return (-1) * ((0xff^highByte) + (0xff^lowByte+1)/256.0) + else: + return highByte + lowByte/256.0 class Bit(DataField): - def value(self, payload): - return ord(payload[self.offset]) == 0x1 + def value(self, data): + return ord(data[self.offset]) == 0x1 + + class ByteEnum(DataField): + def __init__(self, offset, values): + self.values = values + fields.DataField.__init__(self, offset) + def value(self, data): + value = ord(data[self.offset]) + if self.values.has_key(value): + return self.values[value] + else: + return None packetDescription = [ # Service 0x05 (Brennersteuerbefehle) {'primary':0x5, 'secondary':0x3, 'name':'Betriebsdaten des Feuerungsautomaten an den Regler Block1'}, - {'primary':0x5, 'secondary':0x7, 'name':'Betriebsdaten des Reglers an den Feuerungsautomaten'}, + {'primary':0x5, 'secondary':0x7, 'name':'Betriebsdaten des Reglers an den Feuerungsautomaten','format': { + 'betriebszustand':fields.ByteEnum(0, { + 0x00:'Brenner Abschalten', + 0x01:'Keine Aktion', + 0x55:'Brauchwassbereitung', + 0xaa:'Heizbetrieb', + 0xcc:'Emmissionskontroll', + 0xdd:'TÜV-Funktion', + 0xee:'Regler Stopp', + 0x66:'Brauchwasserbereitung bei Reglerstoppfunktion', + 0xbb:'Brauchwasserbereitung bei Heizbetrieb', + 0x44:'Reglerstoppfunktion bei stufigem Betrieb'}), + 'betriebszustand2':fields.ByteEnum(1, { + 0x00:'Keine Aktion', + 0x01:'Ausschalten Kesselpumpe', + 0x02:'Einschalten Kesselpumpe', + 0x03:'Ausschalten variable Verbraucher', + 0x04:'Einschalten variabler Verbraucher'}), + 'kesselSollwertTemperatur':fields.Data2c(2), + 'kesselSollwertDruck':fields.Data2b(4), + }}, # Service 0x07 (Systemdatenbefehle) {'primary':0x7, 'secondary':0x0, 'name':'Datum/Zeit - Meldung eines eBUS Masters'}, {'primary':0x7, 'secondary':0x4, 'name':'Identifikation'}, @@ -76,7 +112,9 @@ packetDescription = [ #p[4] = 10^6 {'primary':0x3, 'secondary':0x8, 'name':'Gesamtbrennstoffmengenzähle lesen'}, {'primary':0x50, 'secondary':0x17, 'name':'Solar Daten', 'format':{ - 'solarPumpe':fields.Bit(0), 'tempKollektor':fields.Data2c(2), 'tempWarmwasserSolar':fields.Data2c(4)} }, + 'solarPumpe':fields.Bit(0), + 'tempKollektor':fields.Data2c(2), + 'tempWarmwasserSolar':fields.Data2c(4)}}, ] def formatHex(data): @@ -231,18 +269,18 @@ class Fetcher(asynchat.async_chat): 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, payload, None) - #print p - ###print "payload=%s" % formatHex(payload) + ###print "payload=%s" % formatHex(payload) elif sourceDevice[0]['type'] == 'master' and destinationDevice[0]['type'] == 'broadcast': p = EbusBroadcast(source, destination, primaryCommand, secondaryCommand, payload) - print p else: print "KOMISCHES ZEUG" return + if p and p.values() != dict(): + print p + Fetcher() asyncore.loop() |