summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/ebus_dump.py28
-rw-r--r--ebus/__init__.py51
-rw-r--r--ebus/model/__init__.py19
-rw-r--r--ebus/model/sql.py95
4 files changed, 111 insertions, 82 deletions
diff --git a/bin/ebus_dump.py b/bin/ebus_dump.py
index bfae56e..a437b0d 100755
--- a/bin/ebus_dump.py
+++ b/bin/ebus_dump.py
@@ -2,15 +2,33 @@
# -*- coding:utf8 -*-
import asyncore
from ebus import EbusReader
+from ebus.model.sql import ModelBase, EbusSQL, Value
+from ebus.model.sql import EbusSQL
+from sqlalchemy import create_engine
+from sqlalchemy.orm import sessionmaker
+
+engine = create_engine('sqlite:///:memory:', echo=True)
+#engine = create_engine("postgresql://yvesf:iii@10.2.2.13:5432/yvesf", echo=True)
+
+ModelBase.metadata.create_all(engine)
+
+Session = sessionmaker()
+Session.configure(bind=engine)
+session = Session()
+
class MyEbusReader(EbusReader):
def __init__(self,*args,**kwargs):
EbusReader.__init__(self,*args,**kwargs)
- self.debug=True
-
+ self.debug = True
+ self.sql = EbusSQL(session)
def handle_ebus(self,ebus_packet):
- if ebus_packet.values() != dict():
- print ebus_packet
+ for field in self.sql.get_values(ebus_packet):
+ session.add(field)
MyEbusReader()
-asyncore.loop()
+try:
+ asyncore.loop()
+except KeyboardInterrupt:
+ for data in session.query(Value).all():
+ print data
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 "<Sensor('%s','%s','%s')>" % (self.id, self.name, self.description)
+ return "<Sensor(id='%s',name='%s',description='%s')>" % (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 "<Value('%s','%s','%s','%s'>" % (self.id, self.sensor, self.value, self.timestamp)
+ return "<Value(id='%s',sensor='%s',value='%s',timestamp='%s'>" % (
+ 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