From 7ff580a6fe60f7e3ea160f7b181ff0fa934453ce Mon Sep 17 00:00:00 2001 From: yvesf Date: Sun, 15 Aug 2010 22:54:27 +0200 Subject: So 15. Aug 22:54:27 CEST 2010 --- ebus/__init__.py | 51 +++++++++++++++------------ ebus/model/__init__.py | 19 +++++----- ebus/model/sql.py | 95 ++++++++++++++++++++++++++------------------------ 3 files changed, 88 insertions(+), 77 deletions(-) (limited to 'ebus') diff --git a/ebus/__init__.py b/ebus/__init__.py index 832e9ff..58192b9 100644 --- a/ebus/__init__.py +++ b/ebus/__init__.py @@ -8,13 +8,16 @@ import os from lxml import objectify from lxml import etree +class UnknownPacketException(Exception): + pass + class EbusPacket(object): EBUS_SPECIFICATION = os.path.join(os.path.dirname(__file__), "ebus_specification.xml") ebus_xml = objectify.parse(open(EBUS_SPECIFICATION)) @staticmethod def address_to_type(address): - d=[dev.get("type") for dev in EbusXMLMixin.ebus_xml.xpath("/ebus/devices/device[@address=$address]", + d=[dev.get("type") for dev in EbusPacket.ebus_xml.xpath("/ebus/devices/device[@address=$address]", address="#x%.2x"%address)] return len(d)>0 and d[0] or None @@ -26,29 +29,28 @@ class EbusPacket(object): def __str__(self): #XXX self.length only in subclasses - return "<%-18s name=\"%s\" source=\"0x%.2x\" destination=\"0x%.2x\" primary=0x%x secondary=0x%x length=0x%x %s>" % \ + return "<%-18s name=\"%s\" source=\"0x%.2x\" destination=\"0x%.2x\" primary=0x%x secondary=0x%x length=0x%x>" % \ (self.__class__.__name__, self.name(), self.source, self.destination, \ - self.primary_command, self.secondary_command, self.length, \ - " ".join(map(lambda name: "%s=%s" % (name, self.values()[name]),self.values()))) + self.primary_command, self.secondary_command, self.length) def get_packet_description(self): - p=EbusXMLMixin.ebus_xml.xpath("/ebus/packets/packet[@primary=$primary and @secondary=$secondary]", + p=EbusPacket.ebus_xml.xpath("/ebus/packets/packet[@primary=$primary and @secondary=$secondary]", primary="#x%.2x"%self.primary_command, secondary="#x%.2x"%self.secondary_command) if len(p)>0 and p[0] is not None: return p[0] else: - raise "Unknown Packet, primary_command=#x%.2 secondary_command=#x%.2" % ( + raise UnknownPacketException("Unknown Packet, primary_command=#x%.2x secondary_command=#x%.2x" % ( self.primary_command, - self.secondardy_command) + self.secondary_command)) def _get_source_name(self): - s=EbusXMLMixin.ebus_xml.xpath("/ebus/devices/device[@address=$address]", + s=EbusPacket.ebus_xml.xpath("/ebus/devices/device[@address=$address]", address="#x%.2x"%self.source) return len(s)>0 and s[0] or None def _get_destination_name(self): - d=EbusXMLMixin.ebus_xml.xpath("/ebus/devices/device[@address=$address]", + d=EbusPacket.ebus_xml.xpath("/ebus/devices/device[@address=$address]", address="#x%.2x"%self.destination) return len(d)>0 and d[0] or None @@ -123,9 +125,9 @@ class EbusReader(asynchat.async_chat): print "GAGA" return source = ord(data[0]) - sourceType = EbusXMLMixin.address_to_type(source) + sourceType = EbusPacket.address_to_type(source) destination = ord(data[1]) - destinationType = EbusXMLMixin.address_to_type(destination) + destinationType = EbusPacket.address_to_type(destination) if len(data) < 9: print >>sys.stderr, "Unvollständige Daten" @@ -146,18 +148,21 @@ class EbusReader(asynchat.async_chat): " ".join(map(lambda byte: "%.2x"%ord(byte), payload))) - if sourceType == 'master' and destinationType == 'master': - p = EbusMasterMaster(source, destination, primaryCommand, secondaryCommand, payload) - self.handle_ebus(p) - elif sourceType == 'master' and destinationType == 'slave': - p = EbusMasterSlave(source, destination, primaryCommand, secondaryCommand, payload, None) #FIXME - print >>sys.stderr, "SKIP MASTER-SLAVE" - elif sourceType == 'master' and destinationType == 'broadcast': - p = EbusBroadcast(source, destination, primaryCommand, secondaryCommand, payload) - self.handle_ebus(p) - else: - print >>sys.stderr, "SKIP source=%s sourceType=%s destination=%s destType=%s" % \ - (source, sourceType, destination, destinationType) + try: + if sourceType == 'master' and destinationType == 'master': + p = EbusMasterMaster(source, destination, primaryCommand, secondaryCommand, payload) + self.handle_ebus(p) + elif sourceType == 'master' and destinationType == 'slave': + p = EbusMasterSlave(source, destination, primaryCommand, secondaryCommand, payload, None) #FIXME + print >>sys.stderr, "SKIP MASTER-SLAVE" + elif sourceType == 'master' and destinationType == 'broadcast': + p = EbusBroadcast(source, destination, primaryCommand, secondaryCommand, payload) + self.handle_ebus(p) + else: + print >>sys.stderr, "SKIP source=%s sourceType=%s destination=%s destType=%s" % \ + (source, sourceType, destination, destinationType) + except UnknownPacketException,e: + print e def handle_ebus(self,ebus_packet): print >>sys.stderr, "unhandled ebus_packet" diff --git a/ebus/model/__init__.py b/ebus/model/__init__.py index ecdf3bc..1e2d080 100644 --- a/ebus/model/__init__.py +++ b/ebus/model/__init__.py @@ -1,3 +1,4 @@ +# -*- coding:utf8 -*- class DataField(object): def __init__(self, name, offset): self.name = name @@ -5,20 +6,20 @@ class DataField(object): def value(self,data): raise NotImplemented() - class Data1b(DataField): - """ +class Data1b(DataField): + """ Beispiel für die Berechnung: if ((x & 80h) == 80h) // y negativ y = - [dez(!x) + 1] else y = dez(x) """ - def value(self,data): - x = ord(data[self.offset]) - if x & 0x80 == 0x80: - return (-1) * (0xff^x + 1) - else: - return x + def value(self,data): + x = ord(data[self.offset]) + if x & 0x80 == 0x80: + return (-1) * (0xff^x + 1) + else: + return x class Data1c(DataField): def value(self,data): @@ -81,7 +82,7 @@ class Byte(DataField): class ByteEnum(DataField): def __init__(self, name, offset, values): - fields.DataField.__init__(self, name, offset) + DataField.__init__(self, name, offset) self.values = values def value(self, data): diff --git a/ebus/model/sql.py b/ebus/model/sql.py index fa9b479..630e31c 100644 --- a/ebus/model/sql.py +++ b/ebus/model/sql.py @@ -3,6 +3,7 @@ from datetime import datetime from sqlalchemy import Column, Integer, Float, DateTime, String, ForeignKey from sqlalchemy.orm import relationship, backref from sqlalchemy.ext.declarative import declarative_base +from ebus import model ModelBase = declarative_base() @@ -18,7 +19,7 @@ class Sensor(ModelBase): self.description = description def __repr__(self): - return "" % (self.id, self.name, self.description) + return "" % (self.id, self.name, self.description) # http://www.sqlalchemy.org/docs/05/reference/ext/declarative.html#inheritance-configuration class Value(ModelBase): @@ -37,7 +38,8 @@ class Value(ModelBase): self.sensor = sensor def __repr__(self): - return "" % (self.id, self.sensor, self.value, self.timestamp) + return "" % ( + self.id, self.sensor, self.value(), self.timestamp) def value(self): raise NotImplementedException() @@ -76,53 +78,56 @@ class ValueString(Value): return self.value_string -class EbusPacketSQL(object): +class EbusSQL(object): def __init__(self,session): self.session = session def get_values(self,packet): packet_description = packet.get_packet_description() - sensor_name = packet._get_source_name() + sensor_name = str(packet._get_source_name()) sensor = self.session.query(Sensor) \ - .filter(Sensor.name==sensor_name) - - if packet is None: - return - - for field in packet_description.fields: - name = field.name - offset = int(field.offset) - if not name: - continue - elif field.tag == "bit": - yield ValueInt(sensor, \ - fields.Bit(name, offset).value()) - elif field.tag == "byte": - yield ValueInt(sensor, \ - fields.Byte(name, offset).value()) - elif field.tag == "word": - yield ValueInt(sensor, \ - fields.Word(name, offset).value()) - elif field.tag == "data1b": - yield ValueInt(sensor, \ - fields.Data1b(name, offset).value()) - elif field.tag == "data1c": - yield ValueInt(sensor, \ - fields.Data1c(name, offset).value()) - elif field.tag == "data2b": - yield ValueInt(sensor, \ - fields.Data2b(name, offset).value()) - elif field.tag == "data2c": - yield ValueInt(sensor, - fields.Data2c(name, offset).value()) - elif field.tag == "bcd": - yield ValueString(sensor, - fields.Bcd(name, offset).value()) - elif field.tag == "byteEnum": - options = dict(map(lambda opt: ( int(opt.get("value")[2:],16), opt.get("name")), - field.xpath("./option"))) - yield ValueString(sensor, - fields.ByteEnum(name, offset, options).value()) - else: - print "Unsupported field-type %s" % (name) + .filter(Sensor.name==sensor_name).first() + if sensor is None: + sensor = Sensor(sensor_name) + self.session.add(sensor) + + for field in packet_description.fields.iterchildren(): + try: + name = field.get("name") + offset = int(field.get("offset")) + if not name: + continue + elif field.tag == "bit": + yield ValueInt(sensor, \ + model.Bit(name, offset).value(packet.data)) + elif field.tag == "byte": + yield ValueInt(sensor, \ + model.Byte(name, offset).value(packet.data)) + elif field.tag == "word": + yield ValueInt(sensor, \ + model.Word(name, offset).value(packet.data)) + elif field.tag == "data1b": + yield ValueInt(sensor, \ + model.Data1b(name, offset).value(packet.data)) + elif field.tag == "data1c": + yield ValueInt(sensor, \ + model.Data1c(name, offset).value(packet.data)) + elif field.tag == "data2b": + yield ValueInt(sensor, \ + model.Data2b(name, offset).value(packet.data)) + elif field.tag == "data2c": + yield ValueInt(sensor, + model.Data2c(name, offset).value(packet.data)) + elif field.tag == "bcd": + yield ValueString(sensor, + model.Bcd(name, offset).value(packet.data)) + elif field.tag == "byteEnum": + options = dict(map(lambda opt: ( int(opt.get("value")[2:],16), opt.get("name")), + field.xpath("./option"))) + yield ValueString(sensor, + model.ByteEnum(name, offset, options).value(packet.data)) + else: + print "Unsupported field-type %s" % (name) + except Exception,e: + print "skip",e -- cgit v1.2.1