# -*- coding: utf-8 -*- 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 ModelBase = declarative_base() class Sensor(ModelBase): __tablename__ = 'sensor' id = Column(Integer, primary_key=True) name = Column(String) description = Column(String, default="") def __init__(self, name, description=""): self.name = name self.description = description def __repr__(self): return "" % (self.id, self.name, self.description) # http://www.sqlalchemy.org/docs/05/reference/ext/declarative.html#inheritance-configuration class Value(ModelBase): __tablename__ = 'value' id = Column(Integer, primary_key=True) timestamp = Column(DateTime) sensor_id = Column(Integer, ForeignKey("sensor.id")) sensor = relationship(Sensor, backref=backref('values', order_by=timestamp)) discriminator = Column('type', String(50)) __mapper_args__ = {'polymorphic_on': discriminator} def __init__(self, sensor, timestamp=datetime.now()): self.timestamp = timestamp self.sensor = sensor def __repr__(self): return "" % (self.id, self.sensor, self.value, self.timestamp) def value(self): raise NotImplementedException() class ValueFloat(Value): __mapper_args__ = {'polymorphic_identity': 'float'} value_float = Column(Float(precision=4)) def __init__(self, sensor, value, timestamp=datetime.now()): Value.__init__(self, sensor, timestamp) self.value_float = value def value(self): return self.value_float class ValueInt(Value): __mapper_args__ = {'polymorphic_identity': 'int'} value_int = Column(Integer) def __init__(self, sensor, value, timestamp=datetime.now()): Value.__init__(self, sensor, timestamp) self.value_int = value def value(self): return self.value_int class ValueString(Value): __mapper_args__ = {'polymorphic_identity': 'string'} value_string = Column(String) def __init__(self, sensor, value, timestamp=datetime.now()): Value.__init__(self, sensor, timestamp) self.value_string = value def value(self): return self.value_string class EbusPacketSQL(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 = 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)