[dss-commits] digitalSTROM Server branch, master, updated. 6a3fde853a2a5e0e5b8bff55b8c0c8e281d20c65

git version control dss-commits at forum.digitalstrom.org
Wed Jan 6 18:50:30 CET 2010


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "digitalSTROM Server".

The branch, master has been updated
       via  6a3fde853a2a5e0e5b8bff55b8c0c8e281d20c65 (commit)
       via  cb3e3cfaa56443f010061a6fc552ecd560f23dcb (commit)
       via  23944ad01ec31a2aaf7e81f97b65da65fb37ac6c (commit)
       via  8e5380b5a4b08d6ed0792fee70fbd3f53273ab16 (commit)
       via  5c4175d99f9de3c93508235d84604d16ffee8762 (commit)
       via  34a6da26b695684a72f9fe7144db30cf068e5429 (commit)
       via  d50e304f481ea010157bce2d01111cee32f5c303 (commit)
      from  a2574b34c80a3ea556da7c2de9c512226204f753 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 6a3fde853a2a5e0e5b8bff55b8c0c8e281d20c65
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Wed Jan 6 18:48:49 2010 +0100

    Externalized Apartments event processing
    
    All event-processing is now done in ModelMaintenance (better name
    anyone?).

commit cb3e3cfaa56443f010061a6fc552ecd560f23dcb
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Wed Jan 6 17:05:56 2010 +0100

    Frame handling moved to BusInterfaceHandler

commit 23944ad01ec31a2aaf7e81f97b65da65fb37ac6c
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Wed Jan 6 14:33:31 2010 +0100

    FrameBucketBase/Collector removed from ds485proxy

commit 8e5380b5a4b08d6ed0792fee70fbd3f53273ab16
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Wed Jan 6 14:11:45 2010 +0100

    Don't rename XML-tags yet

commit 5c4175d99f9de3c93508235d84604d16ffee8762
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Wed Jan 6 14:00:06 2010 +0100

    Removed ReceivedFrame

commit 34a6da26b695684a72f9fe7144db30cf068e5429
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Wed Jan 6 12:12:52 2010 +0100

    Remove second parameter in Apartments constructor
    
    Everyone passed NULL in anyway.

commit d50e304f481ea010157bce2d01111cee32f5c303
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Wed Jan 6 11:58:33 2010 +0100

    Extracted more classes out of DS485Interface

-----------------------------------------------------------------------

Changes:
diff --git a/core/DS485Interface.h b/core/DS485Interface.h
index 9f7a53b..bbb37f8 100644
--- a/core/DS485Interface.h
+++ b/core/DS485Interface.h
@@ -92,21 +92,8 @@ namespace dss {
     virtual ~StructureQueryBusInterface() {}; // please the compiler (virtual dtor)
   }; // StructureQueryBusInterface
   
-  /** Interface to be implemented by any implementation of the DS485 interface */
-  class DS485Interface {
+  class StructureModifyingBusInterface {
   public:
-    virtual ~DS485Interface() {};
-
-    virtual DeviceBusInterface* getDeviceBusInterface() = 0;
-    virtual StructureQueryBusInterface* getStructureQueryBusInterface() = 0;
-
-    /** Returns true when the interface is ready to transmit user generated DS485Packets */
-    virtual bool isReady() = 0;
-
-    virtual void sendFrame(DS485CommandFrame& _frame) = 0;
-
-    //------------------------------------------------ Specialized Commands (system)
-
     /** Adds the given device to the specified zone. */
     virtual void setZoneID(const int _dsMeterID, const devid_t _deviceID, const int _zoneID) = 0;
 
@@ -126,13 +113,40 @@ namespace dss {
     /** Removes a user group */
     virtual void removeUserGroup(const int _dsMeterID, const int _groupID) = 0;
 
+    virtual ~StructureModifyingBusInterface() {}; // please the compiler (virtual dtor)
+  }; // StructureModifyingBusInterface
 
-    //------------------------------------------------ Metering
+  class MeteringBusInterface {
+  public:
     /** Returns the current power-consumption in mW */
     virtual unsigned long getPowerConsumption(const int _dsMeterID) = 0;
 
     /** Returns the meter value in Wh */
     virtual unsigned long getEnergyMeterValue(const int _dsMeterID) = 0;
+
+    virtual ~MeteringBusInterface() {}; // please the compiler (virtual dtor)
+  }; // MeteringBusInterface
+
+  class FrameSenderInterface {
+  public:
+    virtual void sendFrame(DS485CommandFrame& _frame) = 0;
+
+    virtual ~FrameSenderInterface() {}; // please the compiler (virtual dtor)
+  }; // FrameSender
+
+  /** Interface to be implemented by any implementation of the DS485 interface */
+  class DS485Interface {
+  public:
+    virtual ~DS485Interface() {};
+
+    virtual DeviceBusInterface* getDeviceBusInterface() = 0;
+    virtual StructureQueryBusInterface* getStructureQueryBusInterface() = 0;
+    virtual MeteringBusInterface* getMeteringBusInterface() = 0;
+    virtual StructureModifyingBusInterface* getStructureModifyingBusInterface() = 0;
+    virtual FrameSenderInterface* getFrameSenderInterface() = 0;
+
+    /** Returns true when the interface is ready to transmit user generated DS485Packets */
+    virtual bool isReady() = 0;
   };
 
   class DS485ApiError : public DSSException {
diff --git a/core/ds485/CMakeLists.txt b/core/ds485/CMakeLists.txt
index 9c7d8c6..602febd 100644
--- a/core/ds485/CMakeLists.txt
+++ b/core/ds485/CMakeLists.txt
@@ -1 +1,2 @@
-add_library(ds485 ds485busrequestdispatcher.cpp ds485.cpp ds485proxy.cpp)
\ No newline at end of file
+add_library(ds485 ds485busrequestdispatcher.cpp ds485.cpp ds485proxy.cpp
+	framebucketbase.cpp framebucketcollector.cpp businterfacehandler.cpp)
diff --git a/core/ds485/businterfacehandler.cpp b/core/ds485/businterfacehandler.cpp
new file mode 100644
index 0000000..44e89c6
--- /dev/null
+++ b/core/ds485/businterfacehandler.cpp
@@ -0,0 +1,450 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "businterfacehandler.h"
+
+#include <sstream>
+
+#include "core/foreach.h"
+#include "core/dss.h"
+#include "core/model/modelevent.h"
+#include "core/model/modelmaintenance.h"
+#include "core/ds485const.h"
+#include "core/event.h"
+#include "core/ds485/framebucketbase.h"
+#include "core/sim/dssim.h"
+
+namespace dss {
+
+  const char* FunctionIDToString(const int _functionID);
+
+  //================================================== BusInterfaceHandler
+
+  BusInterfaceHandler::BusInterfaceHandler(DSS* _pDSS, ModelMaintenance& _apartment)
+  : Subsystem(_pDSS, "BusInterfaceHandler"),
+    m_ModelMaintenance(_apartment)
+  {}
+
+  void BusInterfaceHandler::initialize() {
+    Subsystem::initialize();
+  } // initialize
+
+  void BusInterfaceHandler::execute() {
+    while(!m_Terminated) {
+      if(!m_IncomingFrames.empty() || m_PacketHere.waitFor(50)) {
+        while(!m_IncomingFrames.empty()) {
+          m_IncomingFramesGuard.lock();
+          // process packets and put them into a functionID-hash
+          boost::shared_ptr<DS485CommandFrame> frame = m_IncomingFrames.front();
+          m_IncomingFrames.erase(m_IncomingFrames.begin());
+          m_IncomingFramesGuard.unlock();
+          log("R");
+
+          const std::vector<unsigned char>& ch = frame->getPayload().toChar();
+          if(ch.size() < 1) {
+            log("received Command Frame w/o function identifier", lsFatal);
+            continue;
+          }
+
+          uint8_t functionID = ch.front();
+          if((frame->getCommand() == CommandRequest || frame->getCommand() == CommandEvent) && functionID != FunctionDSLinkReceive) {
+            std::string functionIDStr = FunctionIDToString(functionID);
+            if(functionIDStr.empty()) {
+              functionIDStr = "Unknown function id: " + intToString(functionID, true);
+            }
+            std::ostringstream sstream;
+            sstream << "Got request: " << functionIDStr << " from " << int(frame->getHeader().getSource()) << " ";
+            if(frame->getFrameSource() == fsWire) {
+              sstream << "over the wire ";
+            } else {
+              sstream << "from the dss ";
+            }
+
+            PayloadDissector pdDump(frame->getPayload());
+            while(!pdDump.isEmpty()) {
+              uint8_t data = pdDump.get<uint8_t>();
+              sstream << "(0x" << std::hex << (unsigned int)data << ", " << std::dec << (int)data << "d)";
+            }
+            sstream << std::dec;
+            log(sstream.str());
+
+
+            PayloadDissector pd(frame->getPayload());
+
+#ifdef WITH_SIM
+            if(frame->getFrameSource() == fsWire) {
+              getDSS().getSimulation().process(*frame.get());
+            }
+#endif
+            if(functionID == FunctionZoneAddDevice) {
+              log("New device");
+              pd.get<uint8_t>(); // function id
+              int modID = frame->getHeader().getSource();
+              int zoneID = pd.get<uint16_t>();
+              int devID = pd.get<uint16_t>();
+              pd.get<uint16_t>(); // version
+              int functionID = pd.get<uint16_t>();
+
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etNewDevice);
+              pEvent->addParameter(modID);
+              pEvent->addParameter(zoneID);
+              pEvent->addParameter(devID);
+              pEvent->addParameter(functionID);
+              raiseModelEvent(pEvent);
+            } else if(functionID == FunctionGroupCallScene) {
+              pd.get<uint8_t>(); // function id
+              uint16_t zoneID = pd.get<uint16_t>();
+              uint16_t groupID = pd.get<uint16_t>();
+              uint16_t sceneID = pd.get<uint16_t>();
+              if(frame->getCommand() == CommandRequest) {
+                boost::shared_ptr<Event> sceneEvent(new Event("callScene"));
+                sceneEvent->setProperty("sceneID", intToString(sceneID & 0x00ff));
+                sceneEvent->setProperty("groupID", intToString(groupID));
+                sceneEvent->setProperty("zoneID", intToString(zoneID));
+                if(DSS::hasInstance()) {
+                  getDSS().getEventQueue().pushEvent(sceneEvent);
+                }
+              }
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etCallSceneGroup);
+              pEvent->addParameter(zoneID);
+              pEvent->addParameter(groupID);
+              pEvent->addParameter(sceneID);
+              raiseModelEvent(pEvent);
+            } else if(functionID == FunctionDeviceCallScene) {
+              pd.get<uint8_t>(); // functionID
+              uint16_t devID = pd.get<uint16_t>();
+              uint16_t sceneID = pd.get<uint16_t>();
+              int modID = frame->getHeader().getDestination();
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etCallSceneDevice);
+              pEvent->addParameter(modID);
+              pEvent->addParameter(devID);
+              pEvent->addParameter(sceneID);
+              raiseModelEvent(pEvent);
+            } else if(functionID == EventDSLinkInterrupt) {
+              pd.get<uint8_t>(); // functionID
+              uint16_t devID = pd.get<uint16_t>();
+              uint16_t priority = pd.get<uint16_t>();
+              int modID = frame->getHeader().getSource();
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etDSLinkInterrupt);
+              pEvent->addParameter(modID);
+              pEvent->addParameter(devID);
+              pEvent->addParameter(priority);
+              raiseModelEvent(pEvent);
+            } else if(functionID == EventDeviceReceivedTelegramShort) {
+              pd.get<uint8_t>(); // function id
+              uint16_t p1 = pd.get<uint16_t>();
+              uint16_t p2 = pd.get<uint16_t>();
+              uint16_t p3 = pd.get<uint16_t>();
+              uint16_t address = p1 & 0x007F;
+              uint16_t buttonNumber = p2 & 0x000F;
+              uint16_t kind = p3 & 0x000F;
+              boost::shared_ptr<Event> buttonEvt(new Event("buttonPressed"));
+              buttonEvt->setProperty("address", intToString(address));
+              buttonEvt->setProperty("buttonNumber", intToString(buttonNumber));
+              buttonEvt->setProperty("kind", intToString(kind));
+              getDSS().getEventQueue().pushEvent(buttonEvt);
+            } else if(functionID == EventDeviceReceivedTelegramLong) {
+              pd.get<uint8_t>(); // function id
+              pd.get<uint16_t>();
+              uint16_t p2 = pd.get<uint16_t>();
+              uint16_t p3 = pd.get<uint16_t>();
+              uint16_t p4 = pd.get<uint16_t>();
+              uint16_t address = ((p3&0x0f00) | (p4&0x00f0) | (p4&0x000f))>>2;
+              uint16_t subqualifier = ((p4 & 0xf000)>>12);
+              uint8_t mainqualifier = (p4&0x0f00)>>8;
+              uint16_t data = ((p2 &0x0f00)<< 4)&0xf000;
+              data |= ((p3&0x00f0) << 4) &0x0f00;
+              data |= ((p3 &0x000f)<<4)&0x00f0;
+              data |= ((p3&0xf000)>> 12) &0x000f;
+              boost::shared_ptr<Event> telEvt(new Event("deviceReceivedTelegram"));
+              telEvt->setProperty("data", intToString(data));
+              telEvt->setProperty("address", intToString(address));
+              telEvt->setProperty("subqualifier", intToString(subqualifier));
+              telEvt->setProperty("mainqualifier", intToString(mainqualifier));
+              getDSS().getEventQueue().pushEvent(telEvt);
+            } else if(functionID == EventNewDS485Device) {
+              pd.get<uint8_t>(); // functionID
+              int modID = pd.get<uint16_t>();
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etNewDSMeter);
+              pEvent->addParameter(modID);
+              raiseModelEvent(pEvent);
+            } else if(functionID == EventLostDS485Device) {
+              pd.get<uint8_t>(); // functionID
+              int modID = pd.get<uint16_t>();
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etLostDSMeter);
+              pEvent->addParameter(modID);
+              raiseModelEvent(pEvent);
+            } else if(functionID == EventDeviceReady) {
+              int modID = frame->getHeader().getDestination();
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etDSMeterReady);
+              pEvent->addParameter(modID);
+              raiseModelEvent(pEvent);
+            }
+          } else {
+            std::ostringstream sstream;
+            sstream << "Response: ";
+            PayloadDissector pd(frame->getPayload());
+            while(!pd.isEmpty()) {
+              uint8_t data = pd.get<uint8_t>();
+              sstream << "(0x" << std::hex << (unsigned int)data << ", " << std::dec << (int)data << "d)";
+            }
+            sstream << std::dec;
+            sstream << " from " << int(frame->getHeader().getSource());
+            log(sstream.str());
+
+            log(std::string("Response for: ") + FunctionIDToString(functionID));
+
+            PayloadDissector pd2(frame->getPayload());
+            pd2.get<uint8_t>();
+            if (functionID == FunctionDSMeterGetPowerConsumption) {
+              /* hard optimized */
+              //getDSS().getApartment().getDSMeterByBusID((int)(frame->getHeader().getSource())).setPowerConsumption(pd2.get<uint32_t>());
+                int modID = frame->getHeader().getSource();
+                ModelEvent* pEvent = new ModelEvent(ModelEvent::etPowerConsumption);
+                pEvent->addParameter(modID);
+                pEvent->addParameter(pd2.get<uint32_t>());
+                raiseModelEvent(pEvent);
+            } else if (functionID == FunctionDSMeterGetEnergyMeterValue) {
+              /* hard optimized */
+              //getDSS().getApartment().getDSMeterByBusID((int)(frame->getHeader().getSource())).setEnergyMeterValue(pd2.get<uint32_t>());
+                int modID = frame->getHeader().getSource();
+                ModelEvent* pEvent = new ModelEvent(ModelEvent::etEnergyMeterValue);
+                pEvent->addParameter(modID);
+                pEvent->addParameter(pd2.get<uint32_t>());
+                raiseModelEvent(pEvent);
+            } else if (functionID == FunctionDSMeterGetDSID) {
+              int sourceID = frame->getHeader().getSource();
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etDS485DeviceDiscovered);
+              pEvent->addParameter(sourceID);
+              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
+              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
+              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
+              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
+              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
+              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
+              raiseModelEvent(pEvent);
+            }
+
+            bool bucketFound = false;
+            // search for a bucket to put the frame in
+            m_FrameBucketsGuard.lock();
+            foreach(FrameBucketBase* bucket, m_FrameBuckets) {
+              if(bucket->getFunctionID() == functionID) {
+                if((bucket->getSourceID() == -1) || (bucket->getSourceID() == frame->getHeader().getSource())) {
+                  if(bucket->addFrame(frame)) {
+                    bucketFound = true;
+                  }
+                }
+              }
+            }
+            m_FrameBucketsGuard.unlock();
+            if(!bucketFound) {
+              log("No bucket found for " + intToString(frame->getHeader().getSource()));
+            }
+
+          }
+        }
+      }
+    }
+  } // execute
+
+  void BusInterfaceHandler::raiseModelEvent(ModelEvent* _pEvent) {
+    m_ModelMaintenance.addModelEvent(_pEvent);
+  } // raiseModelEvent
+
+  void BusInterfaceHandler::collectFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
+    uint8_t commandID = _frame->getCommand();
+    if(commandID != CommandResponse && commandID != CommandRequest && commandID != CommandEvent) {
+      log("discarded non response/request/command frame", lsInfo);
+      log(std::string("frame type ") + commandToString(commandID));
+    } else {
+      m_IncomingFramesGuard.lock();
+      m_IncomingFrames.push_back(_frame);
+      m_IncomingFramesGuard.unlock();
+      m_PacketHere.signal();
+    }
+  } // collectFrame
+
+  void BusInterfaceHandler::addFrameBucket(FrameBucketBase* _bucket) {
+    m_FrameBucketsGuard.lock();
+    m_FrameBuckets.push_back(_bucket);
+    m_FrameBucketsGuard.unlock();
+  } // addFrameBucket
+
+  void BusInterfaceHandler::removeFrameBucket(FrameBucketBase* _bucket) {
+    m_FrameBucketsGuard.lock();
+    std::vector<FrameBucketBase*>::iterator pos = find(m_FrameBuckets.begin(), m_FrameBuckets.end(), _bucket);
+    if(pos != m_FrameBuckets.end()) {
+      m_FrameBuckets.erase(pos);
+    }
+    m_FrameBucketsGuard.unlock();
+  } // removeFrameBucket
+
+  void BusInterfaceHandler::doStart() {
+    // call Thread::run()
+    run();
+  } // doStart
+
+
+  //================================================== Helper
+
+  const char* FunctionIDToString(const int _functionID) {
+    switch(_functionID) {
+    case  FunctionDSMeterAddZone:
+      return "DSMeter Add Zone";
+    case  FunctionDSMeterRemoveZone:
+      return "DSMeter Remove Zone";
+    case  FunctionDSMeterRemoveAllZones:
+      return "DSMeter Remove All Zones";
+    case  FunctionDSMeterCountDevInZone:
+      return "DSMeter Count Dev In Zone";
+    case  FunctionDSMeterDevKeyInZone:
+      return "DSMeter Dev Key In Zone";
+    case  FunctionDSMeterGetGroupsSize:
+      return "DSMeter Get Groups Size";
+    case  FunctionDSMeterGetZonesSize:
+      return "DSMeter Get Zones Size";
+    case  FunctionDSMeterGetZoneIdForInd:
+      return "DSMeter Get Zone Id For Index";
+    case  FunctionDSMeterAddToGroup:
+      return "DSMeter Add To Group";
+    case  FunctionDSMeterRemoveFromGroup:
+      return "DSMeter Remove From Group";
+    case  FunctionGroupAddDeviceToGroup:
+      return "Group Add Device";
+    case  FunctionGroupRemoveDeviceFromGroup:
+      return "Group Remove Device";
+    case  FunctionGroupGetDeviceCount:
+      return "Group Get Device Count";
+    case  FunctionGroupGetDevKeyForInd:
+      return "Group Get Dev Key For Index";
+
+    case  FunctionZoneGetGroupIdForInd:
+      return "Zone Get Group ID For Index";
+
+    case  FunctionDeviceCallScene:
+      return "Device Call Scene";
+    case  FunctionDeviceSaveScene:
+      return "Device Save Scene";
+    case  FunctionDeviceUndoScene:
+      return "Device Undo Scene";
+
+    case FunctionDeviceIncreaseValue:
+      return "Function Device Increase Value";
+    case FunctionDeviceDecreaseValue:
+      return "Function Device Decrease Value";
+    case FunctionDeviceStartDimInc:
+      return "Function Device Start Dim Inc";
+    case FunctionDeviceStartDimDec:
+      return "Function Device Start Dim Dec";
+    case FunctionDeviceEndDim:
+      return "Function Device End Dim";
+
+    case  FunctionGroupCallScene:
+      return "Group Call Scene";
+    case  FunctionGroupSaveScene:
+      return "Group Save Scene";
+    case  FunctionGroupUndoScene:
+      return "Group Undo Scene";
+
+    case FunctionGroupIncreaseValue:
+      return "Function Group Increase Value";
+    case FunctionGroupDecreaseValue:
+      return "Function Group Decrease Value";
+    case FunctionGroupStartDimInc:
+      return "Function Group Start Dim Inc";
+    case FunctionGroupStartDimDec:
+      return "Function Group Start Dim Dec";
+    case FunctionGroupEndDim:
+      return "Function Group End Dim";
+
+
+    case FunctionDeviceSetZoneID:
+      return "Device Set ZoneID";
+
+    case  FunctionDeviceGetOnOff:
+      return "Function Device Get On Off";
+    case  FunctionDeviceGetParameterValue:
+      return "Function Device Get Parameter Value";
+    case  FunctionDeviceGetDSID:
+      return "Function Device Get DSID";
+    case FunctionDeviceGetGroups:
+      return "Function Device Get Groups";
+    case FunctionDeviceGetSensorValue:
+      return "Function Device Get Sensor Value";
+
+    case FunctionDSMeterGetDSID:
+      return "Function DSMeter Get DSID";
+
+    case FunctionDSMeterGetPowerConsumption:
+      return "Function DSMeter Get PowerConsumption";
+    case FunctionDSMeterGetEnergyMeterValue:
+      return "Function DSMeter Get Energy-Meter Value";
+    case FunctionDSMeterGetEnergyLevel:
+      return "Function DSMeter Get Energy-Level";
+    case FunctionDSMeterSetEnergyLevel:
+      return "Function DSMeter Set Energy-Level";
+
+    case FunctionGetTypeRequest:
+      return "Function Get Type";
+
+    case FunctionMeterSynchronisation:
+      return "Function Meter Synchronization";
+
+    case FunctionDeviceGetFunctionID:
+      return "Function Device Get Function ID";
+    case FunctionDSLinkConfigWrite:
+      return "Function dSLink Config Write";
+    case FunctionDSLinkConfigRead:
+      return "Function dSLink Config Read";
+    case FunctionDSLinkSendDevice:
+      return "Function dSLink Send Device";
+    case FunctionDSLinkSendGroup:
+      return "Function dSLink Send Group";
+    case FunctionDSLinkReceive:
+      return "Function dSLink Receive";
+    case EventDSLinkInterrupt:
+      return "Function DSLink Interrupt";
+
+
+    case FunctionZoneAddDevice:
+      return "Function Zone Add Device";
+    case FunctionZoneRemoveDevice:
+      return "Function Zone Remove Device";
+    case FunctionDeviceAddToGroup:
+      return "Function Device Add To Group";
+    case EventNewDS485Device:
+      return "Event New DS485 Device";
+    case EventLostDS485Device:
+      return "Event Lost DS485 Device";
+    case EventDeviceReceivedTelegramShort:
+      return "Event Telegram Short";
+    case EventDeviceReceivedTelegramLong:
+      return "Event Telegram Long";
+    case EventDeviceReady:
+      return "Event Device Ready";
+    }
+    return "";
+  } // functionIDToString
+
+
+} // namespace dss
diff --git a/core/ds485/businterfacehandler.h b/core/ds485/businterfacehandler.h
new file mode 100644
index 0000000..13f1ad9
--- /dev/null
+++ b/core/ds485/businterfacehandler.h
@@ -0,0 +1,66 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef BUSINTERFACEHANDLER_H_
+#define BUSINTERFACEHANDLER_H_
+
+#include "core/thread.h"
+#include "core/subsystem.h"
+#include "core/syncevent.h"
+#include "core/ds485/ds485.h"
+
+namespace dss {
+
+  class ModelMaintenance;
+  class FrameBucketBase;
+  class ModelEvent;
+
+  typedef std::vector<boost::shared_ptr<DS485CommandFrame> > CommandFrameSharedPtrVector;
+
+  class BusInterfaceHandler : public Thread,
+                              public Subsystem,
+                              public IDS485FrameCollector {
+  public:
+    BusInterfaceHandler(DSS* _pDSS, ModelMaintenance& _modelMaintenance);
+    virtual void execute();
+    virtual void initialize();
+
+    void addFrameBucket(FrameBucketBase* _bucket);
+    void removeFrameBucket(FrameBucketBase* _bucket);
+
+    virtual void collectFrame(boost::shared_ptr<DS485CommandFrame> _frame);
+  protected:
+    virtual void doStart();
+  private:
+    void raiseModelEvent(ModelEvent* _pEvent);
+  private:
+    ModelMaintenance& m_ModelMaintenance;
+    Mutex m_IncomingFramesGuard;
+    Mutex m_FrameBucketsGuard;
+    SyncEvent m_PacketHere;
+    CommandFrameSharedPtrVector m_IncomingFrames;
+    std::vector<FrameBucketBase*> m_FrameBuckets;
+  };
+
+
+} //  namespace dss
+#endif /* BUSINTERFACEHANDLER_H_ */
diff --git a/core/ds485/ds485.cpp b/core/ds485/ds485.cpp
index 7629266..50841ec 100644
--- a/core/ds485/ds485.cpp
+++ b/core/ds485/ds485.cpp
@@ -158,7 +158,8 @@ namespace dss {
   DS485Controller::DS485Controller()
   : Thread("DS485Controller"),
     m_State(csInitial),
-    m_RS485DeviceName("/dev/ttyUSB0")
+    m_RS485DeviceName("/dev/ttyUSB0"),
+    m_pBusReadyCallback(NULL)
   {
     m_DSID.upper = DSIDHeader;
     m_DSID.lower = 0xDEADBEEF;
@@ -495,7 +496,6 @@ namespace dss {
 //            std::cout << ".";
 //            flush(std::cout);
             time(&tokenReceivedAt);
-            m_TokenEvent.broadcast();
             m_TokenCounter++;
             lastSentWasToken = true;
           } else {
@@ -608,8 +608,6 @@ namespace dss {
     (*frame) = *_frame;
     frame->setFrameSource(fsWire);
     distributeFrame(frame);
-    // Signal our listeners
-    m_CommandFrameEvent.signal();
   } // addToReceivedQueue
 
   void DS485Controller::doChangeState(aControllerState _newState) {
@@ -619,8 +617,11 @@ namespace dss {
       if(m_State == csInitial) {
         m_NextStationID = 0xFF;
         m_StationID = 0xFF;
+      } else if((m_State == csSlave) || (m_State == csMaster)) {
+        if(m_pBusReadyCallback != NULL) {
+          m_pBusReadyCallback->busReady();
+        }
       }
-      m_ControllerEvent.signal();
     }
   } // doChangeState
 
@@ -634,10 +635,6 @@ namespace dss {
     m_PendingFramesGuard.unlock();
   } // enqueueFrame
 
-  bool DS485Controller::waitForEvent(const int _timeoutMS) {
-    return m_ControllerEvent.waitFor(_timeoutMS);
-  } // waitForEvent
-
   aControllerState DS485Controller::getState() const {
     return m_State;
   } // getState
@@ -646,14 +643,6 @@ namespace dss {
     return m_StateString;
   } // getStateAsString
 
-  void DS485Controller::waitForCommandFrame() {
-    m_CommandFrameEvent.waitFor();
-  } // waitForCommandFrame
-
-  void DS485Controller::waitForToken() {
-    m_TokenEvent.waitFor();
-  } // waitForToken
-
 
   //================================================== DS485FrameReader
 
diff --git a/core/ds485/ds485.h b/core/ds485/ds485.h
index 0f539b2..9e5f839 100644
--- a/core/ds485/ds485.h
+++ b/core/ds485/ds485.h
@@ -26,7 +26,6 @@
 #include "core/thread.h"
 #include "unix/serialcom.h"
 #include "core/ds485types.h"
-#include "core/syncevent.h"
 
 #include <vector>
 #include <string>
@@ -210,6 +209,12 @@ namespace dss {
     int getNumberOfCRCErrors() const { return m_NumberOfCRCErrors; }
   }; // FrameReader
 
+  class BusReadyCallbackInterface {
+  public:
+    virtual ~BusReadyCallbackInterface() {}
+    virtual void busReady() = 0;
+  };
+
   class DS485Controller : public Thread,
                           public DS485FrameProvider {
   private:
@@ -224,10 +229,8 @@ namespace dss {
     boost::ptr_vector<DS485CommandFrame> m_PendingFrames;
     Mutex m_PendingFramesGuard;
     boost::shared_ptr<SerialCom> m_SerialCom;
-    SyncEvent m_ControllerEvent;
-    SyncEvent m_CommandFrameEvent;
-    SyncEvent m_TokenEvent;
     dsid_t m_DSID;
+    BusReadyCallbackInterface* m_pBusReadyCallback;
   private:
     DS485Frame* getFrameFromWire();
     bool putFrameOnWire(const DS485Frame* _pFrame, bool _freeFrame = true);
@@ -247,9 +250,6 @@ namespace dss {
     const std::string& getRS485DeviceName() const { return m_RS485DeviceName; }
 
     void enqueueFrame(DS485CommandFrame& _frame);
-    bool waitForEvent(const int _timeoutMS);
-    void waitForCommandFrame();
-    void waitForToken();
 
     aControllerState getState() const;
     int getTokenCount() const { return m_TokenCounter; };
@@ -263,6 +263,8 @@ namespace dss {
     int getStationID() const { return m_StationID; }
 
     void setDSID(const dsid_t& _value) { m_DSID = _value; }
+
+    void setBusReadyCallback(BusReadyCallbackInterface* _value) { m_pBusReadyCallback = _value; }
   }; // DS485Controller
 
   class IDS485FrameCollector {
diff --git a/core/ds485/ds485busrequestdispatcher.h b/core/ds485/ds485busrequestdispatcher.h
index 0fcd132..272aeaf 100644
--- a/core/ds485/ds485busrequestdispatcher.h
+++ b/core/ds485/ds485busrequestdispatcher.h
@@ -27,16 +27,16 @@
 
 namespace dss {
 
-  class DS485Interface;
+  class FrameSenderInterface;
   
   class DS485BusRequestDispatcher : public BusRequestDispatcher {
   public:
     virtual void dispatchRequest(boost::shared_ptr<BusRequest> _pRequest);
-    void setProxy(DS485Interface* _pInterface) {
+    void setFrameSender(FrameSenderInterface* _pInterface) {
       m_pInterface = _pInterface;
     }
   private:
-    DS485Interface* m_pInterface;
+    FrameSenderInterface* m_pInterface;
   }; // DS485BusRequestDispatcher
 
 } // namespace dss
diff --git a/core/ds485/ds485proxy.cpp b/core/ds485/ds485proxy.cpp
index c1ec7c4..29d2437 100644
--- a/core/ds485/ds485proxy.cpp
+++ b/core/ds485/ds485proxy.cpp
@@ -31,7 +31,10 @@
 
 #include "core/model/modelevent.h"
 #include "core/model/device.h"
-#include "core/model/apartment.h"
+#include "core/model/modelmaintenance.h"
+
+#include "core/ds485/framebucketcollector.h"
+#include "core/ds485/businterfacehandler.h"
 
 #ifdef WITH_SIM
 #include "core/sim/dssim.h"
@@ -43,13 +46,12 @@ namespace dss {
 
   const char* FunctionIDToString(const int _functionID); // internal forward declaration
 
-  DS485Proxy::DS485Proxy(DSS* _pDSS, Apartment* _pApartment)
-  : Thread("DS485Proxy"),
-    Subsystem(_pDSS, "DS485Proxy"),
-    m_pApartment(_pApartment),
+  DS485Proxy::DS485Proxy(DSS* _pDSS, ModelMaintenance* _pModelMaintenance)
+  : Subsystem(_pDSS, "DS485Proxy"),
+    m_pModelMaintenance(_pModelMaintenance),
     m_InitializeDS485Controller(true)
   {
-    assert(_pApartment != NULL);
+    assert(_pModelMaintenance != NULL);
     if(_pDSS != NULL) {
       _pDSS->getPropertySystem().createProperty(getConfigPropertyBasePath() + "rs485devicename")
             ->linkToProxy(PropertyProxyMemberFunction<DS485Controller, std::string>(m_DS485Controller, &DS485Controller::getRS485DeviceName, &DS485Controller::setRS485DeviceName));
@@ -75,13 +77,19 @@ namespace dss {
   } // ctor
 
   bool DS485Proxy::isReady() {
-	  return isRunning()
+    bool simReady =
 #ifdef WITH_SIM
-	         &&  DSS::getInstance()->getSimulation().isReady() // allow the simulation to run on it's own
+             DSS::getInstance()->getSimulation().isReady(); // allow the simulation to run on it's own
+#else
+             true;
 #endif
-	         && ((m_DS485Controller.getState() == csSlave) ||
-	             (m_DS485Controller.getState() == csDesignatedMaster) ||
-	             (m_DS485Controller.getState() == csError)); 
+    bool selfReady = m_pBusInterfaceHandler != NULL ? m_pBusInterfaceHandler->isRunning() : true;
+    bool controllerReady =
+        ((m_DS485Controller.getState() == csSlave) ||
+        (m_DS485Controller.getState() == csDesignatedMaster) ||
+        (m_DS485Controller.getState() == csError));
+
+	  return simReady && selfReady && controllerReady;
   } // isReady
 
   uint16_t DS485Proxy::deviceGetParameterValue(devid_t _id, uint8_t _dsMeterID, int _paramID) {
@@ -107,9 +115,9 @@ namespace dss {
     frame.getPayload().add<devid_t>(_id);
 
     uint16_t result;
-    boost::shared_ptr<ReceivedFrame> resFrame = receiveSingleFrame(frame, FunctionDeviceGetFunctionID);
+    boost::shared_ptr<DS485CommandFrame> resFrame = receiveSingleFrame(frame, FunctionDeviceGetFunctionID);
     if(resFrame.get() != NULL) {
-      PayloadDissector pd(resFrame->getFrame()->getPayload());
+      PayloadDissector pd(resFrame->getPayload());
       pd.get<uint8_t>(); // skip the function id
       if(pd.get<uint16_t>() == 0x0001) {
         result = pd.get<uint16_t>();
@@ -156,12 +164,14 @@ namespace dss {
     boost::shared_ptr<DS485CommandFrame> pFrame(new DS485CommandFrame);
     *pFrame = _frame;
     // relay the frame to update our state
-    collectFrame(pFrame);
+    if(m_pBusInterfaceHandler != NULL) {
+      m_pBusInterfaceHandler->collectFrame(pFrame);
+    }
   } // sendFrame
 
   boost::shared_ptr<FrameBucketCollector> DS485Proxy::sendFrameAndInstallBucket(DS485CommandFrame& _frame, const int _functionID) {
     int sourceID = _frame.getHeader().isBroadcast() ? -1 :  _frame.getHeader().getDestination();
-    boost::shared_ptr<FrameBucketCollector> result(new FrameBucketCollector(this, _functionID, sourceID), FrameBucketBase::removeFromProxyAndDelete);
+    boost::shared_ptr<FrameBucketCollector> result(new FrameBucketCollector(&getDSS().getBusInterfaceHandler(), _functionID, sourceID), FrameBucketBase::removeFromProxyAndDelete);
     result->addToProxy();
     sendFrame(_frame);
     return result;
@@ -291,16 +301,16 @@ namespace dss {
 
     std::vector<DSMeterSpec_t> result;
     while(true) {
-      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+      boost::shared_ptr<DS485CommandFrame> recFrame = bucket->popFrame();
       if(recFrame == NULL) {
         break;
       }
-      int source = recFrame->getFrame()->getHeader().getSource();
+      int source = recFrame->getHeader().getSource();
       if(resultFrom[source]) {
         log(std::string("already received result from ") + intToString(source));
         continue;
       }
-      DSMeterSpec_t spec = dsMeterSpecFromFrame(recFrame->getFrame());
+      DSMeterSpec_t spec = dsMeterSpecFromFrame(recFrame);
       result.push_back(spec);
     }
 
@@ -315,13 +325,13 @@ namespace dss {
     cmdFrame.getPayload().add<uint8_t>(FunctionGetTypeRequest);
     log("Proxy: getDSMeterSpec");
 
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionGetTypeRequest);
+    boost::shared_ptr<DS485CommandFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionGetTypeRequest);
 
     if(recFrame == NULL) {
       throw DS485ApiError("No frame received");
     }
 
-    DSMeterSpec_t result = dsMeterSpecFromFrame(recFrame->getFrame());
+    DSMeterSpec_t result = dsMeterSpecFromFrame(recFrame);
 
     return result;
   } // getDSMeterSpec
@@ -432,12 +442,12 @@ namespace dss {
     bucket->waitForFrame(1000);
 
     while(true) {
-      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+      boost::shared_ptr<DS485CommandFrame> recFrame = bucket->popFrame();
       if(recFrame == NULL) {
         break;
       }
 
-      PayloadDissector pd(recFrame->getFrame()->getPayload());
+      PayloadDissector pd(recFrame->getPayload());
       pd.get<uint8_t>(); // discard the function id
       pd.get<uint16_t>(); // function result
 
@@ -573,12 +583,12 @@ namespace dss {
     cmdFrame.getPayload().add<uint16_t>(_deviceID);
     log("Proxy: GetDSIDOfDevice");
 
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDeviceGetDSID);
+    boost::shared_ptr<DS485CommandFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDeviceGetDSID);
     if(recFrame == NULL) {
       throw DS485ApiError("No frame received");
     }
 
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    PayloadDissector pd(recFrame->getPayload());
     pd.get<uint8_t>(); // discard the function id
     int16_t res = int16_t(pd.get<uint16_t>());
     checkResultCode(res);
@@ -592,13 +602,13 @@ namespace dss {
     cmdFrame.getPayload().add<uint8_t>(FunctionDSMeterGetDSID);
     log(std::string("Proxy: GetDSIDOfDSMeter ") + intToString(_dsMeterID));
 
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDSMeterGetDSID);
+    boost::shared_ptr<DS485CommandFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDSMeterGetDSID);
     if(recFrame == NULL) {
       log("GetDSIDOfDSMeter: received no result from " + intToString(_dsMeterID), lsError);
       throw DS485ApiError("No frame received");
     }
 
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    PayloadDissector pd(recFrame->getPayload());
     pd.get<uint8_t>(); // discard the function id
     return pd.get<dsid_t>();
   } // getDSIDOfDSMeter
@@ -627,15 +637,15 @@ namespace dss {
     cmdFrame.getPayload().add<uint8_t>(FunctionDSMeterGetPowerConsumption);
     log(std::string("Proxy: GetPowerConsumption ") + intToString(_dsMeterID));
 
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDSMeterGetPowerConsumption);
+    boost::shared_ptr<DS485CommandFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDSMeterGetPowerConsumption);
     if(recFrame == NULL) {
       log("DS485Proxy::getPowerConsumption: received no results", lsError);
       throw DS485ApiError("No frame received");
     }
-    if(recFrame->getFrame()->getHeader().getSource() != _dsMeterID) {
+    if(recFrame->getHeader().getSource() != _dsMeterID) {
       log("GetPowerConsumption: received result from wrong source");
     }
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    PayloadDissector pd(recFrame->getPayload());
     pd.get<uint8_t>(); // discard the function id
     return pd.get<uint32_t>();
   } // getPowerConsumption
@@ -647,12 +657,12 @@ namespace dss {
     cmdFrame.getPayload().add<uint8_t>(FunctionDSMeterGetEnergyMeterValue);
     log(std::string("Proxy: GetEnergyMeterValue ") + intToString(_dsMeterID));
 
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDSMeterGetEnergyMeterValue);
+    boost::shared_ptr<DS485CommandFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDSMeterGetEnergyMeterValue);
     if(recFrame == NULL) {
       log("DS485Proxy::getEnergyMeterValue: received no results", lsError);
       throw DS485ApiError("No frame received");
     }
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    PayloadDissector pd(recFrame->getPayload());
     pd.get<uint8_t>(); // discard the function id
     return pd.get<uint32_t>();
   } // getEnergyMeterValue
@@ -667,12 +677,12 @@ namespace dss {
 
     bucket->waitForFrame(1000);
 
-    boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+    boost::shared_ptr<DS485CommandFrame> recFrame = bucket->popFrame();
     if(recFrame == NULL) {
       throw DS485ApiError("No frame received");
     }
 
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    PayloadDissector pd(recFrame->getPayload());
     pd.get<uint8_t>(); // discard the function id
     _lower = pd.get<uint16_t>();
     _upper = pd.get<uint16_t>();
@@ -692,7 +702,7 @@ namespace dss {
 
     boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionDeviceGetSensorValue);
     bucket->waitForFrame(2000);
-    boost::shared_ptr<ReceivedFrame> recFrame;
+    boost::shared_ptr<DS485CommandFrame> recFrame;
     if(bucket->isEmpty()) {
       log(std::string("received no ack for request getSensorValue"));
       throw DS485ApiError("no Ack for sensorValue");
@@ -704,7 +714,7 @@ namespace dss {
         recFrame= bucket->popFrame();
     // first frame is only request ack;
 
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    PayloadDissector pd(recFrame->getPayload());
     pd.get<uint8_t>(); // discard functionID
     checkResultCode((int)pd.get<uint16_t>()); // check first ack
 
@@ -716,7 +726,7 @@ namespace dss {
     recFrame = bucket->popFrame();
 
     if(recFrame.get() != NULL) {
-        PayloadDissector pd(recFrame->getFrame()->getPayload());
+        PayloadDissector pd(recFrame->getPayload());
         pd.get<uint8_t>(); // discard functionID
         pd.get<uint16_t>();
         pd.get<uint16_t>();
@@ -741,12 +751,12 @@ namespace dss {
     if((_flags & DSLinkSendWriteOnly) == 0) {
       boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionDSLinkReceive);
       bucket->waitForFrame(10000);
-      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+      boost::shared_ptr<DS485CommandFrame> recFrame = bucket->popFrame();
       if(recFrame == NULL) {
         log("dsLinkSend: No packet received", lsError);
         throw DS485ApiError("No frame received");
       }
-      PayloadDissector pd(recFrame->getFrame()->getPayload());
+      PayloadDissector pd(recFrame->getPayload());
       pd.get<uint8_t>(); // discard the function id
       pd.get<uint16_t>(); // garbage
       devid_t devAddress = pd.get<uint16_t>(); // device address
@@ -782,20 +792,20 @@ namespace dss {
 
   } // removeUserGroup
 
-  boost::shared_ptr<ReceivedFrame> DS485Proxy::receiveSingleFrame(DS485CommandFrame& _frame, uint8_t _functionID) {
+  boost::shared_ptr<DS485CommandFrame> DS485Proxy::receiveSingleFrame(DS485CommandFrame& _frame, uint8_t _functionID) {
     boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(_frame, _functionID);
     bucket->waitForFrame(1000);
 
     if(bucket->isEmpty()) {
       log(std::string("received no results for request (") + FunctionIDToString(_functionID) + ")");
-      return boost::shared_ptr<ReceivedFrame>();
+      return boost::shared_ptr<DS485CommandFrame>();
     } else if(bucket->getFrameCount() > 1) {
       log(std::string("received multiple results (") + intToString(bucket->getFrameCount()) + ") for request (" + FunctionIDToString(_functionID) + ")");
       // TODO: check
       return bucket->popFrame();
     }
 
-    boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+    boost::shared_ptr<DS485CommandFrame> recFrame = bucket->popFrame();
 
     if(recFrame.get() != NULL) {
       return recFrame;
@@ -805,10 +815,10 @@ namespace dss {
   } // receiveSingleFrame
 
   uint8_t DS485Proxy::receiveSingleResult(DS485CommandFrame& _frame, const uint8_t _functionID) {
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(_frame, _functionID);
+    boost::shared_ptr<DS485CommandFrame> recFrame = receiveSingleFrame(_frame, _functionID);
 
     if(recFrame.get() != NULL) {
-      PayloadDissector pd(recFrame->getFrame()->getPayload());
+      PayloadDissector pd(recFrame->getPayload());
       uint8_t functionID = pd.get<uint8_t>();
       if(functionID != _functionID) {
         log("function ids are different", lsFatal);
@@ -821,10 +831,10 @@ namespace dss {
   } // receiveSingleResult
 
   uint16_t DS485Proxy::receiveSingleResult16(DS485CommandFrame& _frame, const uint8_t _functionID) {
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(_frame, _functionID);
+    boost::shared_ptr<DS485CommandFrame> recFrame = receiveSingleFrame(_frame, _functionID);
 
     if(recFrame.get() != NULL) {
-      PayloadDissector pd(recFrame->getFrame()->getPayload());
+      PayloadDissector pd(recFrame->getPayload());
       uint8_t functionID = pd.get<uint8_t>();
       if(functionID != _functionID) {
         log("function ids are different");
@@ -843,531 +853,31 @@ namespace dss {
 
   void DS485Proxy::initialize() {
     Subsystem::initialize();
-    m_DS485Controller.addFrameCollector(this);
+    if(m_pBusInterfaceHandler != NULL) {
+      m_DS485Controller.addFrameCollector(m_pBusInterfaceHandler);
 #ifdef WITH_SIM
-    if(DSS::hasInstance()) {
-      getDSS().getSimulation().addFrameCollector(this);
-    }
+      if(DSS::hasInstance()) {
+        getDSS().getSimulation().addFrameCollector(m_pBusInterfaceHandler);
+      }
 #endif
+    }
   }
 
   void DS485Proxy::doStart() {
     if(m_InitializeDS485Controller) {
       try {
         m_DS485Controller.setDSID(dsid_t::fromString(getDSS().getPropertySystem().getStringValue(getConfigPropertyBasePath() + "dsid")));
-        m_DS485Controller.run();
+        m_DS485Controller.setBusReadyCallback(this);
       } catch (const std::runtime_error& _ex) {
         log(std::string("Caught exception while starting DS485Controller: ") + _ex.what(), lsFatal);
       }
     }
-    // call Thread::run()
-    run();
   } // doStart
 
-  void DS485Proxy::waitForProxyEvent() {
-    m_ProxyEvent.waitFor();
-  } // waitForProxyEvent
-
-  void DS485Proxy::signalEvent() {
-    m_ProxyEvent.signal();
-  } // signalEvent
-
-  const char* FunctionIDToString(const int _functionID) {
-    switch(_functionID) {
-    case  FunctionDSMeterAddZone:
-      return "DSMeter Add Zone";
-    case  FunctionDSMeterRemoveZone:
-      return "DSMeter Remove Zone";
-    case  FunctionDSMeterRemoveAllZones:
-      return "DSMeter Remove All Zones";
-    case  FunctionDSMeterCountDevInZone:
-      return "DSMeter Count Dev In Zone";
-    case  FunctionDSMeterDevKeyInZone:
-      return "DSMeter Dev Key In Zone";
-    case  FunctionDSMeterGetGroupsSize:
-      return "DSMeter Get Groups Size";
-    case  FunctionDSMeterGetZonesSize:
-      return "DSMeter Get Zones Size";
-    case  FunctionDSMeterGetZoneIdForInd:
-      return "DSMeter Get Zone Id For Index";
-    case  FunctionDSMeterAddToGroup:
-      return "DSMeter Add To Group";
-    case  FunctionDSMeterRemoveFromGroup:
-      return "DSMeter Remove From Group";
-    case  FunctionGroupAddDeviceToGroup:
-      return "Group Add Device";
-    case  FunctionGroupRemoveDeviceFromGroup:
-      return "Group Remove Device";
-    case  FunctionGroupGetDeviceCount:
-      return "Group Get Device Count";
-    case  FunctionGroupGetDevKeyForInd:
-      return "Group Get Dev Key For Index";
-
-    case  FunctionZoneGetGroupIdForInd:
-      return "Zone Get Group ID For Index";
-
-    case  FunctionDeviceCallScene:
-      return "Device Call Scene";
-    case  FunctionDeviceSaveScene:
-      return "Device Save Scene";
-    case  FunctionDeviceUndoScene:
-      return "Device Undo Scene";
-
-    case FunctionDeviceIncreaseValue:
-    	return "Function Device Increase Value";
-    case FunctionDeviceDecreaseValue:
-    	return "Function Device Decrease Value";
-    case FunctionDeviceStartDimInc:
-    	return "Function Device Start Dim Inc";
-    case FunctionDeviceStartDimDec:
-    	return "Function Device Start Dim Dec";
-    case FunctionDeviceEndDim:
-    	return "Function Device End Dim";
-
-    case  FunctionGroupCallScene:
-      return "Group Call Scene";
-    case  FunctionGroupSaveScene:
-      return "Group Save Scene";
-    case  FunctionGroupUndoScene:
-      return "Group Undo Scene";
-
-    case FunctionGroupIncreaseValue:
-    	return "Function Group Increase Value";
-    case FunctionGroupDecreaseValue:
-    	return "Function Group Decrease Value";
-    case FunctionGroupStartDimInc:
-    	return "Function Group Start Dim Inc";
-    case FunctionGroupStartDimDec:
-    	return "Function Group Start Dim Dec";
-    case FunctionGroupEndDim:
-    	return "Function Group End Dim";
-
-
-    case FunctionDeviceSetZoneID:
-    	return "Device Set ZoneID";
-
-    case  FunctionDeviceGetOnOff:
-      return "Function Device Get On Off";
-    case  FunctionDeviceGetParameterValue:
-      return "Function Device Get Parameter Value";
-    case  FunctionDeviceGetDSID:
-      return "Function Device Get DSID";
-    case FunctionDeviceGetGroups:
-      return "Function Device Get Groups";
-    case FunctionDeviceGetSensorValue:
-      return "Function Device Get Sensor Value";
-
-    case FunctionDSMeterGetDSID:
-      return "Function DSMeter Get DSID";
-
-    case FunctionDSMeterGetPowerConsumption:
-    	return "Function DSMeter Get PowerConsumption";
-    case FunctionDSMeterGetEnergyMeterValue:
-      return "Function DSMeter Get Energy-Meter Value";
-    case FunctionDSMeterGetEnergyLevel:
-      return "Function DSMeter Get Energy-Level";
-    case FunctionDSMeterSetEnergyLevel:
-      return "Function DSMeter Set Energy-Level";
-
-    case FunctionGetTypeRequest:
-      return "Function Get Type";
-
-    case FunctionMeterSynchronisation:
-      return "Function Meter Synchronization";
-
-    case FunctionDeviceGetFunctionID:
-      return "Function Device Get Function ID";
-    case FunctionDSLinkConfigWrite:
-      return "Function dSLink Config Write";
-    case FunctionDSLinkConfigRead:
-      return "Function dSLink Config Read";
-    case FunctionDSLinkSendDevice:
-      return "Function dSLink Send Device";
-    case FunctionDSLinkSendGroup:
-      return "Function dSLink Send Group";
-    case FunctionDSLinkReceive:
-      return "Function dSLink Receive";
-    case EventDSLinkInterrupt:
-      return "Function DSLink Interrupt";
-      
-
-    case FunctionZoneAddDevice:
-      return "Function Zone Add Device";
-    case FunctionZoneRemoveDevice:
-      return "Function Zone Remove Device";
-    case FunctionDeviceAddToGroup:
-      return "Function Device Add To Group";
-    case EventNewDS485Device:
-      return "Event New DS485 Device";
-    case EventLostDS485Device:
-      return "Event Lost DS485 Device";
-    case EventDeviceReceivedTelegramShort:
-      return "Event Telegram Short";
-    case EventDeviceReceivedTelegramLong:
-      return "Event Telegram Long";
-    case EventDeviceReady:
-      return "Event Device Ready";    
-    }
-    return "";
-  } // functionIDToString
-
-  void DS485Proxy::raiseModelEvent(ModelEvent* _pEvent) {
-    m_pApartment->addModelEvent(_pEvent);
-  } // raiseModelEvent
-
-  void DS485Proxy::execute() {
-    signalEvent();
-    
-    aControllerState lastState = m_DS485Controller.getState();
-
-    while(!m_Terminated) {
-      aControllerState currentState = m_DS485Controller.getState();
-      if(currentState != lastState) {
-        if((currentState == csSlave) || (currentState == csMaster)) {
-          ModelEvent* pEvent = new ModelEvent(ModelEvent::etBusReady);
-          raiseModelEvent(pEvent);
-        }
-        lastState = currentState;
-      }
-      if(!m_IncomingFrames.empty() || m_PacketHere.waitFor(50)) {
-        while(!m_IncomingFrames.empty()) {
-          m_IncomingFramesGuard.lock();
-          // process packets and put them into a functionID-hash
-          boost::shared_ptr<DS485CommandFrame> frame = m_IncomingFrames.front();
-          m_IncomingFrames.erase(m_IncomingFrames.begin());
-          m_IncomingFramesGuard.unlock();
-          log("R");
-          
-          const std::vector<unsigned char>& ch = frame->getPayload().toChar();
-          if(ch.size() < 1) {
-            log("received Command Frame w/o function identifier", lsFatal);
-            continue;
-          }
-
-          uint8_t functionID = ch.front();
-          if((frame->getCommand() == CommandRequest || frame->getCommand() == CommandEvent) && functionID != FunctionDSLinkReceive) {
-            std::string functionIDStr = FunctionIDToString(functionID);
-            if(functionIDStr.empty()) {
-              functionIDStr = "Unknown function id: " + intToString(functionID, true);
-            }
-            std::ostringstream sstream;
-            sstream << "Got request: " << functionIDStr << " from " << int(frame->getHeader().getSource()) << " ";
-            if(frame->getFrameSource() == fsWire) {
-              sstream << "over the wire ";
-            } else {
-              sstream << "from the dss ";
-            }
-
-            PayloadDissector pdDump(frame->getPayload());
-            while(!pdDump.isEmpty()) {
-              uint8_t data = pdDump.get<uint8_t>();
-              sstream << "(0x" << std::hex << (unsigned int)data << ", " << std::dec << (int)data << "d)";
-            }
-            sstream << std::dec;
-            log(sstream.str());
-
-
-            PayloadDissector pd(frame->getPayload());
-
-#ifdef WITH_SIM
-            if(frame->getFrameSource() == fsWire) {
-              getDSS().getSimulation().process(*frame.get());
-            }
-#endif
-            if(functionID == FunctionZoneAddDevice) {
-              log("New device");
-              pd.get<uint8_t>(); // function id
-              int modID = frame->getHeader().getSource();
-              int zoneID = pd.get<uint16_t>();
-              int devID = pd.get<uint16_t>();
-              pd.get<uint16_t>(); // version
-              int functionID = pd.get<uint16_t>();
-
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etNewDevice);
-              pEvent->addParameter(modID);
-              pEvent->addParameter(zoneID);
-              pEvent->addParameter(devID);
-              pEvent->addParameter(functionID);
-              raiseModelEvent(pEvent);
-            } else if(functionID == FunctionGroupCallScene) {
-              pd.get<uint8_t>(); // function id
-              uint16_t zoneID = pd.get<uint16_t>();
-              uint16_t groupID = pd.get<uint16_t>();
-              uint16_t sceneID = pd.get<uint16_t>();
-              if(frame->getCommand() == CommandRequest) {
-                boost::shared_ptr<Event> sceneEvent(new Event("callScene"));
-                sceneEvent->setProperty("sceneID", intToString(sceneID & 0x00ff));
-                sceneEvent->setProperty("groupID", intToString(groupID));
-                sceneEvent->setProperty("zoneID", intToString(zoneID));
-                if(DSS::hasInstance()) {
-                  getDSS().getEventQueue().pushEvent(sceneEvent);
-                }
-              }
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etCallSceneGroup);
-              pEvent->addParameter(zoneID);
-              pEvent->addParameter(groupID);
-              pEvent->addParameter(sceneID);
-              raiseModelEvent(pEvent);
-            } else if(functionID == FunctionDeviceCallScene) {
-              pd.get<uint8_t>(); // functionID
-              uint16_t devID = pd.get<uint16_t>();
-              uint16_t sceneID = pd.get<uint16_t>();
-              int modID = frame->getHeader().getDestination();
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etCallSceneDevice);
-              pEvent->addParameter(modID);
-              pEvent->addParameter(devID);
-              pEvent->addParameter(sceneID);
-              raiseModelEvent(pEvent);
-            } else if(functionID == EventDSLinkInterrupt) {
-              pd.get<uint8_t>(); // functionID
-              uint16_t devID = pd.get<uint16_t>();
-              uint16_t priority = pd.get<uint16_t>();
-              int modID = frame->getHeader().getSource();
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etDSLinkInterrupt);
-              pEvent->addParameter(modID);
-              pEvent->addParameter(devID);
-              pEvent->addParameter(priority);
-              raiseModelEvent(pEvent);
-            } else if(functionID == EventDeviceReceivedTelegramShort) {
-              pd.get<uint8_t>(); // function id
-              uint16_t p1 = pd.get<uint16_t>();
-              uint16_t p2 = pd.get<uint16_t>();
-              uint16_t p3 = pd.get<uint16_t>();
-              uint16_t address = p1 & 0x007F;
-              uint16_t buttonNumber = p2 & 0x000F;
-              uint16_t kind = p3 & 0x000F;
-              boost::shared_ptr<Event> buttonEvt(new Event("buttonPressed"));
-              buttonEvt->setProperty("address", intToString(address));
-              buttonEvt->setProperty("buttonNumber", intToString(buttonNumber));
-              buttonEvt->setProperty("kind", intToString(kind));
-              getDSS().getEventQueue().pushEvent(buttonEvt);
-            } else if(functionID == EventDeviceReceivedTelegramLong) {
-              pd.get<uint8_t>(); // function id
-              pd.get<uint16_t>();
-              uint16_t p2 = pd.get<uint16_t>();
-              uint16_t p3 = pd.get<uint16_t>();
-              uint16_t p4 = pd.get<uint16_t>();
-              uint16_t address = ((p3&0x0f00) | (p4&0x00f0) | (p4&0x000f))>>2;
-              uint16_t subqualifier = ((p4 & 0xf000)>>12);
-              uint8_t mainqualifier = (p4&0x0f00)>>8;
-              uint16_t data = ((p2 &0x0f00)<< 4)&0xf000;
-              data |= ((p3&0x00f0) << 4) &0x0f00;
-              data |= ((p3 &0x000f)<<4)&0x00f0;
-              data |= ((p3&0xf000)>> 12) &0x000f;
-              boost::shared_ptr<Event> telEvt(new Event("deviceReceivedTelegram"));
-              telEvt->setProperty("data", intToString(data));
-              telEvt->setProperty("address", intToString(address));
-              telEvt->setProperty("subqualifier", intToString(subqualifier));
-              telEvt->setProperty("mainqualifier", intToString(mainqualifier));
-              getDSS().getEventQueue().pushEvent(telEvt);
-            } else if(functionID == EventNewDS485Device) {
-              pd.get<uint8_t>(); // functionID
-              int modID = pd.get<uint16_t>();
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etNewDSMeter);
-              pEvent->addParameter(modID);
-              raiseModelEvent(pEvent);
-            } else if(functionID == EventLostDS485Device) {
-              pd.get<uint8_t>(); // functionID
-              int modID = pd.get<uint16_t>();
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etLostDSMeter);
-              pEvent->addParameter(modID);
-              raiseModelEvent(pEvent);
-            } else if(functionID == EventDeviceReady) {
-              int modID = frame->getHeader().getDestination();
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etDSMeterReady);
-              pEvent->addParameter(modID);
-              raiseModelEvent(pEvent);
-            }
-          } else {
-            std::ostringstream sstream;
-            sstream << "Response: ";
-            PayloadDissector pd(frame->getPayload());
-            while(!pd.isEmpty()) {
-              uint8_t data = pd.get<uint8_t>();
-              sstream << "(0x" << std::hex << (unsigned int)data << ", " << std::dec << (int)data << "d)";
-            }
-            sstream << std::dec;
-            sstream << " from " << int(frame->getHeader().getSource());
-            log(sstream.str());
-
-            log(std::string("Response for: ") + FunctionIDToString(functionID));
-            boost::shared_ptr<ReceivedFrame> rf(new ReceivedFrame(m_DS485Controller.getTokenCount(), frame));
-
-            PayloadDissector pd2(frame->getPayload());
-            pd2.get<uint8_t>();
-            if (functionID == FunctionDSMeterGetPowerConsumption) {   
-              /* hard optimized */
-              //getDSS().getApartment().getDSMeterByBusID((int)(frame->getHeader().getSource())).setPowerConsumption(pd2.get<uint32_t>());
-                int modID = frame->getHeader().getSource();
-                ModelEvent* pEvent = new ModelEvent(ModelEvent::etPowerConsumption);
-                pEvent->addParameter(modID);
-                pEvent->addParameter(pd2.get<uint32_t>());
-                raiseModelEvent(pEvent);
-            } else if (functionID == FunctionDSMeterGetEnergyMeterValue) {
-              /* hard optimized */
-              //getDSS().getApartment().getDSMeterByBusID((int)(frame->getHeader().getSource())).setEnergyMeterValue(pd2.get<uint32_t>());
-                int modID = frame->getHeader().getSource();
-                ModelEvent* pEvent = new ModelEvent(ModelEvent::etEnergyMeterValue);
-                pEvent->addParameter(modID);
-                pEvent->addParameter(pd2.get<uint32_t>());
-                raiseModelEvent(pEvent);
-            } else if (functionID == FunctionDSMeterGetDSID) {
-              int sourceID = frame->getHeader().getSource();
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etDS485DeviceDiscovered);
-              pEvent->addParameter(sourceID);
-              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
-              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
-              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
-              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
-              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
-              pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
-              raiseModelEvent(pEvent);
-            }
-
-            bool bucketFound = false;
-            // search for a bucket to put the frame in
-            m_FrameBucketsGuard.lock();
-            foreach(FrameBucketBase* bucket, m_FrameBuckets) {
-              if(bucket->getFunctionID() == functionID) {
-                if((bucket->getSourceID() == -1) || (bucket->getSourceID() == frame->getHeader().getSource())) {
-                  if(bucket->addFrame(rf)) {
-                    bucketFound = true;
-                  }
-                }
-              }
-            }
-            m_FrameBucketsGuard.unlock();
-            if(!bucketFound) {
-              log("No bucket found for " + intToString(frame->getHeader().getSource()));
-            }
-
-          }
-        }
-      }
-    }
-  } // execute
-
-  void DS485Proxy::collectFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
-    uint8_t commandID = _frame->getCommand();
-    if(commandID != CommandResponse && commandID != CommandRequest && commandID != CommandEvent) {
-      log("discarded non response/request/command frame", lsInfo);
-      log(std::string("frame type ") + commandToString(commandID));
-    } else {
-      m_IncomingFramesGuard.lock();
-      m_IncomingFrames.push_back(_frame);
-      m_IncomingFramesGuard.unlock();
-      m_PacketHere.signal();
-    }
-  } // collectFrame
-
-  void DS485Proxy::addFrameBucket(FrameBucketBase* _bucket) {
-    m_FrameBucketsGuard.lock();
-    m_FrameBuckets.push_back(_bucket);
-    m_FrameBucketsGuard.unlock();
-  } // addFrameBucket
-
-  void DS485Proxy::removeFrameBucket(FrameBucketBase* _bucket) {
-    m_FrameBucketsGuard.lock();
-    std::vector<FrameBucketBase*>::iterator pos = find(m_FrameBuckets.begin(), m_FrameBuckets.end(), _bucket);
-    if(pos != m_FrameBuckets.end()) {
-      m_FrameBuckets.erase(pos);
-    }
-    m_FrameBucketsGuard.unlock();
-  } // removeFrameBucket
-
-  //================================================== receivedFrame
-
-  ReceivedFrame::ReceivedFrame(const int _receivedAt, boost::shared_ptr<DS485CommandFrame> _frame)
-  : m_ReceivedAtToken(_receivedAt),
-    m_Frame(_frame)
-  {
-  } // ctor
-
-
-  //================================================== FrameBucketBase
-
-  FrameBucketBase::FrameBucketBase(DS485Proxy* _proxy, int _functionID, int _sourceID)
-  : m_pProxy(_proxy),
-    m_FunctionID(_functionID),
-    m_SourceID(_sourceID)
-  {
-    assert(m_pProxy != NULL);
-  } // ctor
-
-  void FrameBucketBase::addToProxy() {
-    Logger::getInstance()->log("Bucket: Registering for fid: " + intToString(m_FunctionID) + " sid: " + intToString(m_SourceID));
-    m_pProxy->addFrameBucket(this);
-  } // addToProxy
-
-  void FrameBucketBase::removeFromProxyAndDelete(FrameBucketBase* _obj) {
-    _obj->removeFromProxy();
-    delete _obj;
-  } // remove_from_proxy_and_delete
-
-  void FrameBucketBase::removeFromProxy() {
-    Logger::getInstance()->log("Bucket: Removing for fid: " + intToString(m_FunctionID) + " sid: " + intToString(m_SourceID));
-    m_pProxy->removeFrameBucket(this);
-  } // removeFromProxy
-
-
-  //================================================== FrameBucket
-
-  FrameBucketCollector::FrameBucketCollector(DS485Proxy* _proxy, int _functionID, int _sourceID)
-  : FrameBucketBase(_proxy, _functionID, _sourceID),
-    m_SingleFrame(false)
-  { } // ctor
-
-  bool FrameBucketCollector::addFrame(boost::shared_ptr<ReceivedFrame> _frame) {
-    bool result = false;
-    m_FramesMutex.lock();
-    if(!m_SingleFrame || m_Frames.empty()) {
-      m_Frames.push_back(_frame);
-      result = true;
-    }
-    m_FramesMutex.unlock();
-
-    if(result) {
-      m_PacketHere.signal();
-    }
-    return result;
-  } // addFrame
-
-  boost::shared_ptr<ReceivedFrame> FrameBucketCollector::popFrame() {
-    boost::shared_ptr<ReceivedFrame> result;
-
-    m_FramesMutex.lock();
-    if(!m_Frames.empty()) {
-      result = m_Frames.front();
-      m_Frames.pop_front();
-    }
-    m_FramesMutex.unlock();
-    return result;
-  } // popFrame
-
-  void FrameBucketCollector::waitForFrames(int _timeoutMS) {
-    sleepMS(_timeoutMS);
-  } // waitForFrames
-
-  bool FrameBucketCollector::waitForFrame(int _timeoutMS) {
-    m_SingleFrame = true;
-    if(m_Frames.empty()) {
-      Logger::getInstance()->log("FrameBucket::waitForFrame: Waiting for frame");
-      if(m_PacketHere.waitFor(_timeoutMS)) {
-        Logger::getInstance()->log("FrameBucket::waitForFrame: Got frame");
-      } else {
-        Logger::getInstance()->log("FrameBucket::waitForFrame: No frame received");
-        return false;
-      }
-    }
-    return true;
-  } // waitForFrame
-
-  int FrameBucketCollector::getFrameCount() const {
-    return m_Frames.size();
-  } // getFrameCount
+  void DS485Proxy::busReady() {
+    ModelEvent* pEvent = new ModelEvent(ModelEvent::etBusReady);
+    m_pModelMaintenance->addModelEvent(pEvent);
+  } // busReady
 
-  bool FrameBucketCollector::isEmpty() const {
-    return m_Frames.empty();
-  } // isEmpty
 
-}
+} // namespace dss
diff --git a/core/ds485/ds485proxy.h b/core/ds485/ds485proxy.h
index d8d8e3f..40ad94e 100644
--- a/core/ds485/ds485proxy.h
+++ b/core/ds485/ds485proxy.h
@@ -29,7 +29,6 @@
 
 #include "core/ds485types.h"
 #include "ds485.h"
-#include "core/syncevent.h"
 #include "core/DS485Interface.h"
 #include "core/subsystem.h"
 #include "core/mutex.h"
@@ -55,141 +54,61 @@ using namespace stdext;
 
 namespace dss {
 
-  class DS485Proxy;
-  class Apartment;
   class ModelEvent;
+  class FrameBucketBase;
+  class FrameBucketCollector;
+  class BusInterfaceHandler;
+  class ModelMaintenance;
 
-  /** A ReceivedFrame stores a boost::shared_ptr to the frame as well as the token-counter
-   *  of its arrival.
-   */
-  class ReceivedFrame {
-  private:
-    int m_ReceivedAtToken;
-    boost::shared_ptr<DS485CommandFrame> m_Frame;
-  public:
-    ReceivedFrame(const int _receivedAt, boost::shared_ptr<DS485CommandFrame> _frame);
-    boost::shared_ptr<DS485CommandFrame> getFrame() { return m_Frame; };
-
-    /** Returns the arrival time in (owned) tokens */
-    int getReceivedAt() const { return m_ReceivedAtToken; };
-  }; // ReceivedFrame
-
-
-  /** A frame bucket gets notified on every frame that matches any given
-   *  function-/source-id pair.
-   *  If \a m_SourceID is -1 every source matches. */
-  class FrameBucketBase {
-  public:
-    FrameBucketBase(DS485Proxy* _proxy, int _functionID, int _sourceID);
-    virtual ~FrameBucketBase() {}
-
-    int getFunctionID() const { return m_FunctionID; }
-    int getSourceID() const { return m_SourceID; }
-
-    virtual bool addFrame(boost::shared_ptr<ReceivedFrame> _frame) = 0;
-
-    /** Registers the bucket at m_pProxy */
-    void addToProxy();
-    /** Removes the bucket from m_pProxy */
-    void removeFromProxy();
-    /** Static function to be used from a boost::shared_ptr as a deleter. */
-    static void removeFromProxyAndDelete(FrameBucketBase* _obj);
-  private:
-    DS485Proxy* m_pProxy;
-    int m_FunctionID;
-    int m_SourceID;
-  }; // FrameBucketBase
-
-
-  /** FrameBucketCollector holds its received frames in a queue.
-    */
-  class FrameBucketCollector : public FrameBucketBase {
-  private:
-    std::deque<boost::shared_ptr<ReceivedFrame> > m_Frames;
-    SyncEvent m_PacketHere;
-    Mutex m_FramesMutex;
-    bool m_SingleFrame;
-  public:
-    FrameBucketCollector(DS485Proxy* _proxy, int _functionID, int _sourceID);
-    virtual ~FrameBucketCollector() { }
-
-    /** Adds a ReceivedFrame to the frames queue */
-    virtual bool addFrame(boost::shared_ptr<ReceivedFrame> _frame);
-    /** Returns the least recently received item int the queue.
-     * The pointer will contain NULL if isEmpty() returns true. */
-    boost::shared_ptr<ReceivedFrame> popFrame();
-
-    /** Waits for frames to arrive for \a _timeoutMS */
-    void waitForFrames(int _timeoutMS);
-    /** Waits for a frame to arrive in \a _timeoutMS.
-     * If a frame arrives earlier, the function returns */
-    bool waitForFrame(int _timeoutMS);
-
-    int getFrameCount() const;
-    bool isEmpty() const;
-  }; // FrameBucketCollector
-
-
-  typedef std::vector<boost::shared_ptr<DS485CommandFrame> > CommandFrameSharedPtrVector;
-
-  class DS485Proxy : public    Thread,
-                     public    Subsystem,
+  class DS485Proxy : public    Subsystem,
                      public    DS485Interface,
                      public    DeviceBusInterface,
                      public    StructureQueryBusInterface,
-                     public    IDS485FrameCollector {
+                     public    MeteringBusInterface,
+                     public    StructureModifyingBusInterface,
+                     public    FrameSenderInterface,
+                     private   BusReadyCallbackInterface {
   private:
 #ifdef WITH_SIM
     bool isSimAddress(const uint8_t _addr);
 #endif
 
     /** Returns a single frame or NULL if none should arrive within the timeout (1000ms) */
-    boost::shared_ptr<ReceivedFrame> receiveSingleFrame(DS485CommandFrame& _frame, uint8_t _functionID);
+    boost::shared_ptr<DS485CommandFrame> receiveSingleFrame(DS485CommandFrame& _frame, uint8_t _functionID);
     uint8_t receiveSingleResult(DS485CommandFrame& _frame, const uint8_t _functionID);
     uint16_t receiveSingleResult16(DS485CommandFrame& _frame, const uint8_t _functionID);
 
-    std::vector<FrameBucketBase*> m_FrameBuckets;
-
-    void signalEvent();
-
+    BusInterfaceHandler* m_pBusInterfaceHandler;
     DS485Controller m_DS485Controller;
-    SyncEvent m_ProxyEvent;
-    Apartment* m_pApartment;
+    ModelMaintenance* m_pModelMaintenance;
 
-    SyncEvent m_PacketHere;
-    Mutex m_IncomingFramesGuard;
-    Mutex m_FrameBucketsGuard;
-    CommandFrameSharedPtrVector m_IncomingFrames;
     bool m_InitializeDS485Controller;
 
     DSMeterSpec_t dsMeterSpecFromFrame(boost::shared_ptr<DS485CommandFrame> _frame);
     void checkResultCode(const int _resultCode);
-    void raiseModelEvent(ModelEvent* _pEvent);
+    virtual void busReady();
   protected:
     virtual void doStart();
   public:
-    DS485Proxy(DSS* _pDSS, Apartment* _pApartment);
+    DS485Proxy(DSS* _pDSS, ModelMaintenance* _pModelMaintenance);
     virtual ~DS485Proxy() {};
 
+    void setBusInterfaceHandler(BusInterfaceHandler* _value) { m_pBusInterfaceHandler = _value; }
+
     virtual DeviceBusInterface* getDeviceBusInterface() { return this; }
     virtual StructureQueryBusInterface* getStructureQueryBusInterface() { return this; }
+    virtual MeteringBusInterface* getMeteringBusInterface() { return this; }
+    virtual StructureModifyingBusInterface* getStructureModifyingBusInterface() { return this; }
+    virtual FrameSenderInterface* getFrameSenderInterface() { return this; }
 
     virtual bool isReady();
     void setInitializeDS485Controller(const bool _value) { m_InitializeDS485Controller = _value; }
-    virtual void execute();
 
     virtual void sendFrame(DS485CommandFrame& _frame);
     boost::shared_ptr<FrameBucketCollector> sendFrameAndInstallBucket(DS485CommandFrame& _frame, const int _functionID);
-    void installBucket(boost::shared_ptr<FrameBucketBase> _bucket);
 
     //------------------------------------------------ Handling
     virtual void initialize();
-    void waitForProxyEvent();
-
-    virtual void collectFrame(boost::shared_ptr<DS485CommandFrame> _frame);
-
-    void addFrameBucket(FrameBucketBase* _bucket);
-    void removeFrameBucket(FrameBucketBase* _bucket);
 
     //------------------------------------------------ Specialized Commands (system)
     virtual std::vector<DSMeterSpec_t> getDSMeters();
@@ -235,8 +154,6 @@ namespace dss {
 
     void setValueDevice(const Device& _device, const uint16_t _value, const uint16_t _parameterID, const int _size);
     virtual int getSensorValue(const Device& _device, const int _sensorID);
-    //------------------------------------------------ Helpers
-    DS485Controller& getController() { return m_DS485Controller; }
   }; // DS485Proxy
 
 } // namespace dss
diff --git a/core/ds485/framebucketbase.cpp b/core/ds485/framebucketbase.cpp
new file mode 100644
index 0000000..3400035
--- /dev/null
+++ b/core/ds485/framebucketbase.cpp
@@ -0,0 +1,59 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "framebucketbase.h"
+
+#include <cassert>
+
+#include "core/base.h"
+#include "core/logger.h"
+#include "businterfacehandler.h"
+
+namespace dss {
+
+  //================================================== FrameBucketBase
+
+  FrameBucketBase::FrameBucketBase(BusInterfaceHandler* _proxy, int _functionID, int _sourceID)
+  : m_pProxy(_proxy),
+    m_FunctionID(_functionID),
+    m_SourceID(_sourceID)
+  {
+    assert(m_pProxy != NULL);
+  } // ctor
+
+  void FrameBucketBase::addToProxy() {
+    Logger::getInstance()->log("Bucket: Registering for fid: " + intToString(m_FunctionID) + " sid: " + intToString(m_SourceID));
+    m_pProxy->addFrameBucket(this);
+  } // addToProxy
+
+  void FrameBucketBase::removeFromProxyAndDelete(FrameBucketBase* _obj) {
+    _obj->removeFromProxy();
+    delete _obj;
+  } // remove_from_proxy_and_delete
+
+  void FrameBucketBase::removeFromProxy() {
+    Logger::getInstance()->log("Bucket: Removing for fid: " + intToString(m_FunctionID) + " sid: " + intToString(m_SourceID));
+    m_pProxy->removeFrameBucket(this);
+  } // removeFromProxy
+
+
+} // namespace dss
diff --git a/core/ds485/framebucketbase.h b/core/ds485/framebucketbase.h
new file mode 100644
index 0000000..ee707a3
--- /dev/null
+++ b/core/ds485/framebucketbase.h
@@ -0,0 +1,60 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef FRAMEBUCKETBASE_H_
+#define FRAMEBUCKETBASE_H_
+
+#include <boost/shared_ptr.hpp>
+
+namespace dss {
+
+  class BusInterfaceHandler;
+  class DS485CommandFrame;
+
+  /** A frame bucket gets notified on every frame that matches any given
+   *  function-/source-id pair.
+   *  If \a m_SourceID is -1 every source matches. */
+  class FrameBucketBase {
+  public:
+    FrameBucketBase(BusInterfaceHandler* _proxy, int _functionID, int _sourceID);
+    virtual ~FrameBucketBase() {}
+
+    int getFunctionID() const { return m_FunctionID; }
+    int getSourceID() const { return m_SourceID; }
+
+    virtual bool addFrame(boost::shared_ptr<DS485CommandFrame> _frame) = 0;
+
+    /** Registers the bucket at m_pProxy */
+    void addToProxy();
+    /** Removes the bucket from m_pProxy */
+    void removeFromProxy();
+    /** Static function to be used from a boost::shared_ptr as a deleter. */
+    static void removeFromProxyAndDelete(FrameBucketBase* _obj);
+  private:
+    BusInterfaceHandler* m_pProxy;
+    int m_FunctionID;
+    int m_SourceID;
+  }; // FrameBucketBase
+
+} // namespace dss
+
+#endif /* FRAMEBUCKETBASE_H_ */
diff --git a/core/ds485/framebucketcollector.cpp b/core/ds485/framebucketcollector.cpp
new file mode 100644
index 0000000..a0e3d63
--- /dev/null
+++ b/core/ds485/framebucketcollector.cpp
@@ -0,0 +1,91 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "framebucketcollector.h"
+
+#include "core/logger.h"
+#include "core/base.h"
+
+namespace dss {
+
+  //================================================== FrameBucketCollector
+
+  FrameBucketCollector::FrameBucketCollector(BusInterfaceHandler* _proxy, int _functionID, int _sourceID)
+  : FrameBucketBase(_proxy, _functionID, _sourceID),
+    m_SingleFrame(false)
+  { } // ctor
+
+  bool FrameBucketCollector::addFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
+    bool result = false;
+    m_FramesMutex.lock();
+    if(!m_SingleFrame || m_Frames.empty()) {
+      m_Frames.push_back(_frame);
+      result = true;
+    }
+    m_FramesMutex.unlock();
+
+    if(result) {
+      m_PacketHere.signal();
+    }
+    return result;
+  } // addFrame
+
+  boost::shared_ptr<DS485CommandFrame> FrameBucketCollector::popFrame() {
+    boost::shared_ptr<DS485CommandFrame> result;
+
+    m_FramesMutex.lock();
+    if(!m_Frames.empty()) {
+      result = m_Frames.front();
+      m_Frames.pop_front();
+    }
+    m_FramesMutex.unlock();
+    return result;
+  } // popFrame
+
+  void FrameBucketCollector::waitForFrames(int _timeoutMS) {
+    sleepMS(_timeoutMS);
+  } // waitForFrames
+
+  bool FrameBucketCollector::waitForFrame(int _timeoutMS) {
+    m_SingleFrame = true;
+    if(m_Frames.empty()) {
+      Logger::getInstance()->log("FrameBucket::waitForFrame: Waiting for frame");
+      if(m_PacketHere.waitFor(_timeoutMS)) {
+        Logger::getInstance()->log("FrameBucket::waitForFrame: Got frame");
+      } else {
+        Logger::getInstance()->log("FrameBucket::waitForFrame: No frame received");
+        return false;
+      }
+    }
+    return true;
+  } // waitForFrame
+
+  int FrameBucketCollector::getFrameCount() const {
+    return m_Frames.size();
+  } // getFrameCount
+
+  bool FrameBucketCollector::isEmpty() const {
+    return m_Frames.empty();
+  } // isEmpty
+
+
+} // namespace dss
diff --git a/core/ds485/framebucketcollector.h b/core/ds485/framebucketcollector.h
new file mode 100644
index 0000000..74654f9
--- /dev/null
+++ b/core/ds485/framebucketcollector.h
@@ -0,0 +1,67 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef FRAMEBUCKETCOLLECTOR_H_
+#define FRAMEBUCKETCOLLECTOR_H_
+
+#include <deque>
+
+#include <boost/shared_ptr.hpp>
+
+#include "framebucketbase.h"
+#include "core/mutex.h"
+#include "core/syncevent.h"
+
+namespace dss {
+
+  /** FrameBucketCollector holds its received frames in a queue.
+    */
+  class FrameBucketCollector : public FrameBucketBase {
+  private:
+    std::deque<boost::shared_ptr<DS485CommandFrame> > m_Frames;
+    SyncEvent m_PacketHere;
+    Mutex m_FramesMutex;
+    bool m_SingleFrame;
+  public:
+    FrameBucketCollector(BusInterfaceHandler* _proxy, int _functionID, int _sourceID);
+    virtual ~FrameBucketCollector() { }
+
+    /** Adds a DS485CommandFrame to the frames queue */
+    virtual bool addFrame(boost::shared_ptr<DS485CommandFrame> _frame);
+    /** Returns the least recently received item int the queue.
+     * The pointer will contain NULL if isEmpty() returns true. */
+    boost::shared_ptr<DS485CommandFrame> popFrame();
+
+    /** Waits for frames to arrive for \a _timeoutMS */
+    void waitForFrames(int _timeoutMS);
+    /** Waits for a frame to arrive in \a _timeoutMS.
+     * If a frame arrives earlier, the function returns */
+    bool waitForFrame(int _timeoutMS);
+
+    int getFrameCount() const;
+    bool isEmpty() const;
+  }; // FrameBucketCollector
+
+} // namespace dss
+
+#endif /* FRAMEBUCKETCOLLECTOR_H_ */
diff --git a/core/ds485client.cpp b/core/ds485client.cpp
index 44ca06f..66b4ce3 100644
--- a/core/ds485client.cpp
+++ b/core/ds485client.cpp
@@ -25,6 +25,7 @@
 #include "core/dss.h"
 #include "core/foreach.h"
 #include "core/ds485/ds485proxy.h"
+#include "core/ds485/framebucketcollector.h"
 
 namespace dss {
 
@@ -42,15 +43,15 @@ namespace dss {
 
   class FrameBucketCallback : public FrameBucketBase {
   public:
-    FrameBucketCallback(DS485Proxy* _proxy, int _functionID, int _sourceID, DS485Client::FrameCallback_t _callback)
+    FrameBucketCallback(BusInterfaceHandler* _proxy, int _functionID, int _sourceID, DS485Client::FrameCallback_t _callback)
     : FrameBucketBase(_proxy, _functionID, _sourceID),
       m_callBack(_callback)
     {
       assert(_callback != NULL);
     } // ctor
 
-    virtual bool addFrame(boost::shared_ptr<ReceivedFrame> _frame) {
-      m_callBack(_frame->getFrame());
+    virtual bool addFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
+      m_callBack(_frame);
       return false;
     } // addFrame
   private:
@@ -69,7 +70,7 @@ namespace dss {
   } // dtor
 
   void DS485Client::sendFrameDiscardResult(DS485CommandFrame& _frame) {
-    DSS::getInstance()->getDS485Interface().sendFrame(_frame);
+    DSS::getInstance()->getDS485Interface().getFrameSenderInterface()->sendFrame(_frame);
   } // sendFrameDiscardResult
 
   boost::shared_ptr<DS485CommandFrame> DS485Client::sendFrameSingleResult(DS485CommandFrame& _frame, int _functionID, int _timeoutMS) {
@@ -79,7 +80,7 @@ namespace dss {
     boost::shared_ptr<DS485CommandFrame> result;
     boost::shared_ptr<FrameBucketCollector> bucket = proxy->sendFrameAndInstallBucket(_frame, _functionID);
     if(bucket->waitForFrame(_timeoutMS)) {
-      result = bucket->popFrame()->getFrame();
+      result = bucket->popFrame();
     }
     return result;
   } // sendFrameSingleResult
@@ -92,9 +93,9 @@ namespace dss {
     bucket->waitForFrame(_timeoutMS);
 
     std::vector<boost::shared_ptr<DS485CommandFrame> > result;
-    boost::shared_ptr<ReceivedFrame> frame;
+    boost::shared_ptr<DS485CommandFrame> frame;
     while((frame = bucket->popFrame()) != NULL) {
-      result.push_back(frame->getFrame());
+      result.push_back(frame);
     }
     return result;
   } // sendFrameMultipleResults
@@ -102,10 +103,9 @@ namespace dss {
   void DS485Client::subscribeTo(int _functionID, int _source, FrameCallback_t _callback) {
     assert(_callback != NULL);
 
-    DS485Proxy* proxy = dynamic_cast<DS485Proxy*>(&DSS::getInstance()->getDS485Interface());
-    assert(proxy != NULL);
+    BusInterfaceHandler* handler = &DSS::getInstance()->getBusInterfaceHandler();
 
-    boost::shared_ptr<FrameBucketBase> bucket(new FrameBucketCallback(proxy, _functionID, _source, _callback), FrameBucketBase::removeFromProxyAndDelete);
+    boost::shared_ptr<FrameBucketBase> bucket(new FrameBucketCallback(handler, _functionID, _source, _callback), FrameBucketBase::removeFromProxyAndDelete);
     bucket->addToProxy();
     m_pImpl->buckets.push_back(bucket);
   } // subscribeTo
diff --git a/core/dss.cpp b/core/dss.cpp
index 2068678..eb1dba6 100644
--- a/core/dss.cpp
+++ b/core/dss.cpp
@@ -35,8 +35,10 @@
 #include "scripting/modeljs.h"
 #include "eventinterpreterplugins.h"
 #include "core/ds485/ds485proxy.h"
+#include "core/ds485/businterfacehandler.h"
 #include "core/ds485/ds485busrequestdispatcher.h"
 #include "core/model/apartment.h"
+#include "core/model/modelmaintenance.h"
 
 #include "core/web/webserver.h"
 #ifdef WITH_BONJOUR
@@ -156,18 +158,25 @@ const char* WebrootDirectory = "data/webroot";
   bool DSS::initialize(const vector<std::string>& _properties) {
     m_State = ssCreatingSubsystems;
 
-    m_pApartment = boost::shared_ptr<Apartment>(new Apartment(this, NULL));
-    m_Subsystems.push_back(m_pApartment.get());
+    m_pApartment = boost::shared_ptr<Apartment>(new Apartment(this));
 
-    m_pDS485Interface = boost::shared_ptr<DS485Proxy>(new DS485Proxy(this, m_pApartment.get()));
+    m_pModelMaintenance = boost::shared_ptr<ModelMaintenance>(new ModelMaintenance(this));
+    m_Subsystems.push_back(m_pModelMaintenance.get());
+    m_pModelMaintenance->setApartment(m_pApartment.get());
+
+    m_pDS485Interface = boost::shared_ptr<DS485Proxy>(new DS485Proxy(this, m_pModelMaintenance.get()));
     m_Subsystems.push_back(dynamic_cast<DS485Proxy*>(m_pDS485Interface.get()));
 
     m_pBusDispatcher = boost::shared_ptr<DS485BusRequestDispatcher>(new DS485BusRequestDispatcher());
-    m_pBusDispatcher->setProxy(m_pDS485Interface.get());
+    m_pBusDispatcher->setFrameSender(m_pDS485Interface->getFrameSenderInterface());
     
     m_pApartment->setDS485Interface(m_pDS485Interface.get());
     m_pApartment->setBusRequestDispatcher(m_pBusDispatcher.get());
 
+    m_pBusInterfaceHandler = boost::shared_ptr<BusInterfaceHandler>(new BusInterfaceHandler(this, getModelMaintenance()));
+    m_Subsystems.push_back(m_pBusInterfaceHandler.get());
+    dynamic_cast<DS485Proxy*>(m_pDS485Interface.get())->setBusInterfaceHandler(m_pBusInterfaceHandler.get());
+
     m_pWebServer = boost::shared_ptr<WebServer>(new WebServer(this));
     m_Subsystems.push_back(m_pWebServer.get());
 
diff --git a/core/dss.h b/core/dss.h
index a7ce7db..6ff40bf 100644
--- a/core/dss.h
+++ b/core/dss.h
@@ -47,6 +47,8 @@ namespace dss {
   class Apartment;
   class WebServices;
   class DS485BusRequestDispatcher;
+  class BusInterfaceHandler;
+  class ModelMaintenance;
 #ifdef WITH_SIM
   class DSSim;
 #endif
@@ -83,6 +85,8 @@ namespace dss {
     boost::shared_ptr<Metering> m_pMetering;
     boost::shared_ptr<FakeMeter> m_pFakeMeter;
     boost::shared_ptr<DS485BusRequestDispatcher> m_pBusDispatcher;
+    boost::shared_ptr<BusInterfaceHandler> m_pBusInterfaceHandler;
+    boost::shared_ptr<ModelMaintenance> m_pModelMaintenance;
     std::string m_dataDirectory;
     std::string m_configDirectory;
     std::string m_webrootDirectory;
@@ -127,6 +131,8 @@ namespace dss {
     PropertySystem& getPropertySystem() { return *m_pPropertySystem; }
     WebServer& getWebServer() { return *m_pWebServer; }
     EventInterpreter& getEventInterpreter() { return *m_pEventInterpreter; }
+    BusInterfaceHandler& getBusInterfaceHandler() { return *m_pBusInterfaceHandler; }
+    ModelMaintenance& getModelMaintenance() { return *m_pModelMaintenance; }
 
     const std::string& getDataDirectory() const { return m_dataDirectory; }
     const std::string& getConfigDirectory() const { return m_configDirectory; }
diff --git a/core/metering/fake_meter.cpp b/core/metering/fake_meter.cpp
index 1cbe0df..fb60d1e 100644
--- a/core/metering/fake_meter.cpp
+++ b/core/metering/fake_meter.cpp
@@ -28,6 +28,7 @@
 #include "core/foreach.h"
 #include "core/model/apartment.h"
 #include "core/model/modulator.h"
+#include "core/model/modelmaintenance.h"
 
 #include <cmath>
 
@@ -67,7 +68,7 @@ namespace dss {
   }
 
   void FakeMeter::execute() {
-    while(getDSS().getApartment().isInitializing()) {
+    while(getDSS().getModelMaintenance().isInitializing()) {
       sleepSeconds(1);
     }
     SeriesWriter<CurrentValue> writer;
diff --git a/core/metering/metering.cpp b/core/metering/metering.cpp
index d98d8c9..ddfb8ca 100644
--- a/core/metering/metering.cpp
+++ b/core/metering/metering.cpp
@@ -30,6 +30,8 @@
 #include "core/foreach.h"
 #include "core/model/modulator.h"
 #include "core/model/apartment.h"
+#include "core/model/modelmaintenance.h"
+
 
 #include <boost/filesystem.hpp>
 
@@ -191,7 +193,7 @@ namespace dss {
 
   void Metering::execute() {
     // check dsMeters periodically
-    while(DSS::getInstance()->getApartment().isInitializing()) {
+    while(DSS::getInstance()->getModelMaintenance().isInitializing()) {
       sleepSeconds(1);
     }
     while(!m_Terminated) {
diff --git a/core/model/CMakeLists.txt b/core/model/CMakeLists.txt
index 1673177..db8b775 100644
--- a/core/model/CMakeLists.txt
+++ b/core/model/CMakeLists.txt
@@ -2,4 +2,5 @@ add_library(model apartment.cpp group.cpp devicecontainer.cpp set.cpp
 	modulator.cpp device.cpp nonaddressablemodelitem.cpp
 	addressablemodelitem.cpp physicalmodelitem.cpp deviceinterface.cpp
 	devicereference.cpp zone.cpp modelevent.cpp scenehelper.cpp
-	busscanner.cpp busrequest.cpp modelpersistence.cpp)
+	busscanner.cpp busrequest.cpp modelpersistence.cpp
+	modelmaintenance.cpp)
diff --git a/core/model/apartment.cpp b/core/model/apartment.cpp
index de2cf56..6d4223e 100644
--- a/core/model/apartment.cpp
+++ b/core/model/apartment.cpp
@@ -22,10 +22,6 @@
 
 #include "apartment.h"
 
-#include <fstream>
-
-#include <boost/filesystem.hpp>
-
 #include "core/DS485Interface.h"
 #include "core/ds485const.h"
 #include "core/dss.h"
@@ -53,14 +49,20 @@ namespace dss {
 
   //================================================== Apartment
 
-  Apartment::Apartment(DSS* _pDSS, DS485Interface* _pDS485Interface)
-  : Subsystem(_pDSS, "Apartment"),
-    Thread("Apartment"),
-    m_IsInitializing(true),
-    m_pPropertyNode(),
-    m_pDS485Interface(_pDS485Interface),
-    m_pBusRequestDispatcher(NULL)
-  { } // ctor
+  Apartment::Apartment(DSS* _pDSS)
+  : m_pDS485Interface(NULL),
+    m_pBusRequestDispatcher(NULL),
+    m_pModelMaintenance(NULL)
+  {
+    if(_pDSS != NULL) {
+      m_pPropertyNode = DSS::getInstance()->getPropertySystem().createProperty("/apartment");
+    }
+    // create default (broadcast) zone
+    Zone* zoneZero = new Zone(0);
+    addDefaultGroupsToZone(*zoneZero);
+    m_Zones.push_back(zoneZero);
+    zoneZero->setIsPresent(true);
+  } // ctor
 
   Apartment::~Apartment() {
     scrubVector(m_Devices);
@@ -68,23 +70,6 @@ namespace dss {
     scrubVector(m_DSMeters);
   } // dtor
 
-  void Apartment::initialize() {
-    Subsystem::initialize();
-    // create default zone
-    Zone* zoneZero = new Zone(0);
-    addDefaultGroupsToZone(*zoneZero);
-    m_Zones.push_back(zoneZero);
-    zoneZero->setIsPresent(true);
-    if(DSS::hasInstance()) {
-      m_pPropertyNode = DSS::getInstance()->getPropertySystem().createProperty("/apartment");
-      DSS::getInstance()->getPropertySystem().setStringValue(getConfigPropertyBasePath() + "configfile", getDSS().getDataDirectory() + "apartment.xml", true, false);
-    }
-  } // initialize
-
-  void Apartment::doStart() {
-    run();
-  } // start
-
   void Apartment::addDefaultGroupsToZone(Zone& _zone) {
     int zoneID = _zone.getID();
 
@@ -123,30 +108,6 @@ namespace dss {
     _zone.addGroup(grp);
   } // addDefaultGroupsToZone
 
-  void Apartment::dsMeterReady(int _dsMeterBusID) {
-    log("DSMeter with id: " + intToString(_dsMeterBusID) + " is ready", lsInfo);
-    try {
-      try {
-        DSMeter& mod = getDSMeterByBusID(_dsMeterBusID);
-        BusScanner scanner(*m_pDS485Interface->getStructureQueryBusInterface(), *this);
-        if(scanner.scanDSMeter(mod)) {
-          boost::shared_ptr<Event> dsMeterReadyEvent(new Event("dsMeter_ready"));
-          dsMeterReadyEvent->setProperty("dsMeter", mod.getDSID().toString());
-          raiseEvent(dsMeterReadyEvent);
-        }
-      } catch(DS485ApiError& e) {
-        log(std::string("Exception caught while scanning dsMeter " + intToString(_dsMeterBusID) + " : ") + e.what(), lsFatal);
-
-        ModelEvent* pEvent = new ModelEvent(ModelEvent::etDSMeterReady);
-        pEvent->addParameter(_dsMeterBusID);
-        addModelEvent(pEvent);
-      }
-    } catch(ItemNotFoundException& e) {
-      log("No dsMeter for bus-id (" + intToString(_dsMeterBusID) + ") found, re-discovering devices");
-      discoverDS485Devices();
-    }
-  } // dsMeterReady
-
   void Apartment::setPowerConsumption(int _dsMeterBusID, unsigned long _value) {
     getDSMeterByBusID(_dsMeterBusID).setPowerConsumption(_value);
   } // powerConsumption
@@ -155,230 +116,6 @@ namespace dss {
     getDSMeterByBusID(_dsMeterBusID).setEnergyMeterValue(_value);
   } // energyMeterValue
 
-  void Apartment::discoverDS485Devices() {
-    // temporary mark all dsMeters as absent
-    foreach(DSMeter* pDSMeter, m_DSMeters) {
-      pDSMeter->setIsPresent(false);
-    }
-
-    // Request the dsid of all dsMeters
-    DS485CommandFrame requestFrame;
-    requestFrame.getHeader().setBroadcast(true);
-    requestFrame.getHeader().setDestination(0);
-    requestFrame.setCommand(CommandRequest);
-    requestFrame.getPayload().add<uint8_t>(FunctionDSMeterGetDSID);
-    if(DSS::hasInstance()) {
-      DSS::getInstance()->getDS485Interface().sendFrame(requestFrame);
-    }
-  } // discoverDS485Devices
-
-  void Apartment::writeConfiguration() {
-    if(DSS::hasInstance()) {
-      ModelPersistence persistence(*this);
-      persistence.writeConfigurationToXML(DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile"));
-    }
-  } // writeConfiguration
-
-  void Apartment::handleModelEvents() {
-    if(!m_ModelEvents.empty()) {
-      ModelEvent& event = m_ModelEvents.front();
-      switch(event.getEventType()) {
-      case ModelEvent::etNewDevice:
-        if(event.getParameterCount() != 4) {
-          log("Expected exactly 4 parameter for ModelEvent::etNewDevice");
-        } else {
-          onAddDevice(event.getParameter(0), event.getParameter(1), event.getParameter(2), event.getParameter(3));
-        }
-        break;
-      case ModelEvent::etCallSceneDevice:
-        if(event.getParameterCount() != 3) {
-          log("Expected exactly 3 parameter for ModelEvent::etCallSceneDevice");
-        } else {
-          onDeviceCallScene(event.getParameter(0), event.getParameter(1), event.getParameter(2));
-        }
-        break;
-      case ModelEvent::etCallSceneGroup:
-        if(event.getParameterCount() != 3) {
-          log("Expected exactly 3 parameter for ModelEvent::etCallSceneGroup");
-        } else {
-          onGroupCallScene(event.getParameter(0), event.getParameter(1), event.getParameter(2));
-        }
-        break;
-      case ModelEvent::etModelDirty:
-        writeConfiguration();
-        break;
-      case ModelEvent::etDSLinkInterrupt:
-        if(event.getParameterCount() != 3) {
-          log("Expected exactly 3 parameter for ModelEvent::etDSLinkInterrupt");
-        } else {
-          onDSLinkInterrupt(event.getParameter(0), event.getParameter(1), event.getParameter(2));
-        }
-        break;
-      case ModelEvent::etNewDSMeter:
-        discoverDS485Devices();
-        break;
-      case ModelEvent::etLostDSMeter:
-        discoverDS485Devices();
-        break;
-      case ModelEvent::etDSMeterReady:
-        if(event.getParameterCount() != 1) {
-          log("Expected exactly 1 parameter for ModelEvent::etDSMeterReady");
-        } else {
-          try{
-            DSMeter& mod = getDSMeterByBusID(event.getParameter(0));
-            mod.setIsPresent(true);
-            mod.setIsValid(false);
-          } catch(ItemNotFoundException& e) {
-            log("dSM is ready, but it is not yet known, re-discovering devices");
-            discoverDS485Devices();
-          }
-        }
-        break;
-      case ModelEvent::etBusReady:
-        log("Got bus ready event.", lsInfo);
-        discoverDS485Devices();
-        break;
-      case ModelEvent::etPowerConsumption:
-        if(event.getParameterCount() != 2) {
-          log("Expected exactly 2 parameter for ModelEvent::etPowerConsumption");
-        } else {
-          setPowerConsumption(event.getParameter(0), event.getParameter(1));
-        }
-        break;
-      case ModelEvent::etEnergyMeterValue:
-        if(event.getParameterCount() != 2) {
-          log("Expected exactly 2 parameter for ModelEvent::etEnergyMeterValue");
-        } else {
-          setEnergyMeterValue(event.getParameter(0), event.getParameter(1));
-        }
-        break;
-      case ModelEvent::etDS485DeviceDiscovered:
-        if(event.getParameterCount() != 7) {
-          log("Expected exactly 7 parameter for ModelEvent::etDS485DeviceDiscovered");
-        } else {
-          int busID = event.getParameter(0);
-          uint64_t dsidUpper = (uint64_t(event.getParameter(1)) & 0x00ffff) << 48;
-          dsidUpper |= (uint64_t(event.getParameter(2)) & 0x00ffff) << 32;
-          dsidUpper |= (uint64_t(event.getParameter(3))  & 0x00ffff) << 16;
-          dsidUpper |= (uint64_t(event.getParameter(4)) & 0x00ffff);
-          dsid_t newDSID(dsidUpper,
-                         ((uint32_t(event.getParameter(5)) & 0x00ffff) << 16) | (uint32_t(event.getParameter(6)) & 0x00ffff));
-          log ("Discovered device with busID: " + intToString(busID) + " and dsid: " + newDSID.toString());
-          try{
-             getDSMeterByDSID(newDSID).setBusID(busID);
-             log ("dSM present");
-             getDSMeterByDSID(newDSID).setIsPresent(true);
-          } catch(ItemNotFoundException& e) {
-             log ("dSM not present");
-             DSMeter& dsMeter = allocateDSMeter(newDSID);
-             dsMeter.setBusID(busID);
-             dsMeter.setIsPresent(true);
-             dsMeter.setIsValid(false);
-             ModelEvent* pEvent = new ModelEvent(ModelEvent::etDSMeterReady);
-             pEvent->addParameter(busID);
-             addModelEvent(pEvent);
-          }
-        }
-        break;
-      default:
-        assert(false);
-        break;
-      }
-
-      m_ModelEventsMutex.lock();
-      m_ModelEvents.erase(m_ModelEvents.begin());
-      m_ModelEventsMutex.unlock();
-    } else {
-      m_NewModelEvent.waitFor(1000);
-      bool hadToUpdate = false;
-      foreach(DSMeter* pDSMeter, m_DSMeters) {
-        if(pDSMeter->isPresent()) {
-          if(!pDSMeter->isValid()) {
-            dsMeterReady(pDSMeter->getBusID());
-            hadToUpdate = true;
-            break;
-          }
-        }
-      }
-
-      // If we didn't have to update for one cycle, assume that we're done
-      if(!hadToUpdate && m_IsInitializing) {
-        log("******** Finished loading model from dSM(s)...", lsInfo);
-        m_IsInitializing = false;
-
-        {
-          boost::shared_ptr<Event> readyEvent(new Event("model_ready"));
-          raiseEvent(readyEvent);
-        }
-      }
-    }
-  } // handleModelEvents
-
-  void Apartment::readConfiguration() {
-    if(DSS::hasInstance()) {
-      std::string configFileName = DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile");
-      ModelPersistence persistence(*this);
-      persistence.readConfigurationFromXML(configFileName);
-    }
-  } // readConfiguration
-
-  void Apartment::raiseEvent(boost::shared_ptr<Event> _pEvent) {
-    if(DSS::hasInstance()) {
-      getDSS().getEventQueue().pushEvent(_pEvent);
-    }
-  } // raiseEvent
-
-  void Apartment::waitForInterface() {
-    if(DSS::hasInstance()) {
-      DS485Interface& interface = DSS::getInstance()->getDS485Interface();
-
-      log("Apartment::execute: Waiting for interface to get ready", lsInfo);
-
-      while(!interface.isReady() && !m_Terminated) {
-        sleepMS(1000);
-      }
-    }
-
-    boost::shared_ptr<Event> readyEvent(new Event("interface_ready"));
-    raiseEvent(readyEvent);
-  } // waitForInterface
-
-  void Apartment::execute() {
-    {
-      boost::shared_ptr<Event> runningEvent(new Event("running"));
-      raiseEvent(runningEvent);
-    }
-
-    // load devices/dsMeters/etc. from a config-file
-    readConfiguration();
-
-    {
-      boost::shared_ptr<Event> configReadEvent(new Event("config_read"));
-      raiseEvent(configReadEvent);
-    }
-
-    waitForInterface();
-
-    log("Apartment::execute: Interface is ready, enumerating model", lsInfo);
-    discoverDS485Devices();
-
-    while(!m_Terminated) {
-      handleModelEvents();
-    }
-  } // run
-
-  void Apartment::addModelEvent(ModelEvent* _pEvent) {
-    // filter out dirty events, as this will rewrite apartment.xml
-    if(m_IsInitializing && (_pEvent->getEventType() == ModelEvent::etModelDirty)) {
-      delete _pEvent;
-    } else {
-      m_ModelEventsMutex.lock();
-      m_ModelEvents.push_back(_pEvent);
-      m_ModelEventsMutex.unlock();
-      m_NewModelEvent.signal();
-    }
-  } // addModelEvent
-
   Device& Apartment::getDeviceByDSID(const dsid_t _dsid) const {
     foreach(Device* dev, m_Devices) {
       if(dev->getDSID() == _dsid) {
@@ -578,204 +315,6 @@ namespace dss {
     }
   } // removeDSMeter
 
-  class SetLastCalledSceneAction : public IDeviceAction {
-  protected:
-    int m_SceneID;
-  public:
-    SetLastCalledSceneAction(const int _sceneID)
-    : m_SceneID(_sceneID) {}
-    virtual ~SetLastCalledSceneAction() {}
-
-    virtual bool perform(Device& _device) {
-      _device.setLastCalledScene(m_SceneID);
-      return true;
-    }
-  };
-
-  void Apartment::onGroupCallScene(const int _zoneID, const int _groupID, const int _sceneID) {
-    try {
-      if(_sceneID < 0 || _sceneID > MaxSceneNumber) {
-        log("onGroupCallScene: Scene number is out of bounds. zoneID: " + intToString(_zoneID) + " groupID: " + intToString(_groupID) + " scene: " + intToString(_sceneID), lsError);
-        return;
-      }
-      Zone& zone = getZone(_zoneID);
-      Group* group = zone.getGroup(_groupID);
-      if(group != NULL) {
-        log("OnGroupCallScene: group-id '" + intToString(_groupID) + "' in Zone '" + intToString(_zoneID) + "' scene: " + intToString(_sceneID));
-        if(SceneHelper::rememberScene(_sceneID & 0x00ff)) {
-          Set s = zone.getDevices().getByGroup(_groupID);
-          SetLastCalledSceneAction act(_sceneID & 0x00ff);
-          s.perform(act);
-
-          std::vector<Zone*> zonesToUpdate;
-          if(_zoneID == 0) {
-            zonesToUpdate = m_Zones;
-          } else {
-            zonesToUpdate.push_back(&zone);
-          }
-          foreach(Zone* pZone, zonesToUpdate) {
-            if(_groupID == 0) {
-              foreach(Group* pGroup, pZone->getGroups()) {
-                pGroup->setLastCalledScene(_sceneID & 0x00ff);
-              }
-            } else {
-              Group* pGroup = pZone->getGroup(_groupID);
-              if(pGroup != NULL) {
-                pGroup->setLastCalledScene(_sceneID & 0x00ff);
-              }
-            }
-          }
-        }
-      } else {
-        log("OnGroupCallScene: Could not find group with id '" + intToString(_groupID) + "' in Zone '" + intToString(_zoneID) + "'", lsError);
-      }
-    } catch(ItemNotFoundException& e) {
-      log("OnGroupCallScene: Could not find zone with id '" + intToString(_zoneID) + "'", lsError);
-    }
-
-  } // onGroupCallScene
-
-  void Apartment::onDeviceCallScene(const int _dsMeterID, const int _deviceID, const int _sceneID) {
-    try {
-      if(_sceneID < 0 || _sceneID > MaxSceneNumber) {
-        log("onDeviceCallScene: _sceneID is out of bounds. dsMeter-id '" + intToString(_dsMeterID) + "' for device '" + intToString(_deviceID) + "' scene: " + intToString(_sceneID), lsError);
-        return;
-      }
-      DSMeter& mod = getDSMeterByBusID(_dsMeterID);
-      try {
-        log("OnDeviceCallScene: dsMeter-id '" + intToString(_dsMeterID) + "' for device '" + intToString(_deviceID) + "' scene: " + intToString(_sceneID));
-        DeviceReference devRef = mod.getDevices().getByBusID(_deviceID, _dsMeterID);
-        if(SceneHelper::rememberScene(_sceneID & 0x00ff)) {
-          devRef.getDevice().setLastCalledScene(_sceneID & 0x00ff);
-        }
-      } catch(ItemNotFoundException& e) {
-        log("OnDeviceCallScene: Could not find device with bus-id '" + intToString(_deviceID) + "' on dsMeter '" + intToString(_dsMeterID) + "' scene:" + intToString(_sceneID), lsError);
-      }
-    } catch(ItemNotFoundException& e) {
-      log("OnDeviceCallScene: Could not find dsMeter with bus-id '" + intToString(_dsMeterID) + "'", lsError);
-    }
-  } // onDeviceCallScene
-
-  void Apartment::onAddDevice(const int _modID, const int _zoneID, const int _devID, const int _functionID) {
-    // get full dsid
-    log("New Device found");
-    log("  DSMeter: " + intToString(_modID));
-    log("  Zone:      " + intToString(_zoneID));
-    log("  BusID:     " + intToString(_devID));
-    log("  FID:       " + intToString(_functionID));
-
-    dsid_t dsid = getDSS().getDS485Interface().getStructureQueryBusInterface()->getDSIDOfDevice(_modID, _devID);
-    Device& dev = allocateDevice(dsid);
-    DeviceReference devRef(dev, this);
-
-    log("  DSID:      " + dsid.toString());
-
-    // remove from old dsMeter
-    try {
-      DSMeter& oldDSMeter = getDSMeterByBusID(dev.getDSMeterID());
-      oldDSMeter.removeDevice(devRef);
-    } catch(std::runtime_error&) {
-    }
-
-    // remove from old zone
-    if(dev.getZoneID() != 0) {
-      try {
-        Zone& oldZone = getZone(dev.getZoneID());
-        oldZone.removeDevice(devRef);
-        // TODO: check if the zone is empty on the dsMeter and remove it in that case
-      } catch(std::runtime_error&) {
-      }
-    }
-
-    // update device
-    dev.setDSMeterID(_modID);
-    dev.setZoneID(_zoneID);
-    dev.setShortAddress(_devID);
-    dev.setFunctionID(_functionID);
-    dev.setIsPresent(true);
-
-    // add to new dsMeter
-    DSMeter& dsMeter = getDSMeterByBusID(_modID);
-    dsMeter.addDevice(devRef);
-
-    // add to new zone
-    Zone& newZone = allocateZone(_zoneID);
-    newZone.addToDSMeter(dsMeter);
-    newZone.addDevice(devRef);
-
-    // get groups of device
-    dev.resetGroups();
-    std::vector<int> groups = m_pDS485Interface->getStructureQueryBusInterface()->getGroupsOfDevice(_modID, _devID);
-    foreach(int iGroup, groups) {
-      log("  Adding to Group: " + intToString(iGroup));
-      dev.addToGroup(iGroup);
-    }
-
-    {
-      boost::shared_ptr<Event> readyEvent(new Event("new_device"));
-      readyEvent->setProperty("device", dsid.toString());
-      readyEvent->setProperty("zone", intToString(_zoneID));
-      raiseEvent(readyEvent);
-    }
-  } // onAddDevice
-
-  void Apartment::onDSLinkInterrupt(const int _modID, const int _devID, const int _priority) {
-    // get full dsid
-    log("dSLinkInterrupt:");
-    log("  DSMeter: " + intToString(_modID));
-    log("  DevID:     " + intToString(_devID));
-    log("  Priority:  " + intToString(_priority));
-
-    try {
-      DSMeter& dsMeter = getDSMeterByBusID(_modID);
-      try {
-        Device& device = getDeviceByShortAddress(dsMeter, _devID);
-        PropertyNodePtr deviceNode = device.getPropertyNode();
-        if(deviceNode == NULL) {
-          return;
-        }
-        PropertyNodePtr modeNode = deviceNode->getProperty("interrupt/mode");
-        if(modeNode == NULL) {
-          return;
-        }
-        std::string mode = modeNode->getStringValue();
-        if(mode == "ignore") {
-          log("ignoring interrupt");
-        } else if(mode == "raise_event") {
-          log("raising interrupt as event");
-          std::string eventName = "dslink_interrupt";
-          PropertyNodePtr eventNameNode = deviceNode->getProperty("interrupt/event/name");
-          if(eventNameNode == NULL) {
-            log("no node called 'interrupt/event' found, assuming name is 'dslink_interrupt'");
-          } else {
-            eventName = eventNameNode->getAsString();
-          }
-
-          // create event to be raised
-          DeviceReference devRef(device, this);
-          boost::shared_ptr<Event> evt(new Event(eventName, &devRef));
-          evt->setProperty("device", device.getDSID().toString());
-          std::string priorityString = "unknown";
-          if(_priority == 0) {
-            priorityString = "normal";
-          } else if(_priority == 1) {
-            priorityString = "high";
-          }
-          evt->setProperty("priority", priorityString);
-          raiseEvent(evt);
-        } else {
-          log("unknown interrupt mode '" + mode + "'", lsError);
-        }
-      } catch (ItemNotFoundException& ex) {
-        log("Apartment::onDSLinkInterrupt: Unknown device with ID " + intToString(_devID), lsFatal);
-        return;
-      }
-    } catch(ItemNotFoundException& ex) {
-      log("Apartment::onDSLinkInterrupt: Unknown DSMeter with ID " + intToString(_modID), lsFatal);
-      return;
-    }
-  } // onDSLinkInterrupt
-
   void Apartment::dispatchRequest(boost::shared_ptr<BusRequest> _pRequest) {
     if(m_pBusRequestDispatcher != NULL) {
       m_pBusRequestDispatcher->dispatchRequest(_pRequest);
diff --git a/core/model/apartment.h b/core/model/apartment.h
index c8018cf..dcfa358 100644
--- a/core/model/apartment.h
+++ b/core/model/apartment.h
@@ -38,19 +38,18 @@
 #include "core/thread.h"
 #include "core/syncevent.h"
 #include "core/DS485Interface.h"
-#include "modelpersistence.h"
 
 namespace dss {
-
+  class PropertyNode;
+  typedef boost::shared_ptr<PropertyNode> PropertyNodePtr;
   class Zone;
   class DSMeter;
   class Device;
   class Group;
   class Event;
-  class PropertyNode;
-  typedef boost::shared_ptr<PropertyNode> PropertyNodePtr;
   class BusRequestDispatcher;
   class BusRequest;
+  class ModelMaintenance;
 
   /** Represents an Apartment
     * This is the root of the datamodel of the dss. The Apartment is responsible for delivering
@@ -58,44 +57,23 @@ namespace dss {
     */
   class Apartment : public boost::noncopyable,
                     public DeviceContainer,
-                    public Subsystem,
-                    public LockableObject,
-                    public Thread
+                    public LockableObject
   {
   private:
     std::vector<Zone*> m_Zones;
     std::vector<DSMeter*> m_DSMeters;
     std::vector<Device*> m_Devices;
-    bool m_IsInitializing;
-
-    PropertyNodePtr m_pPropertyNode;
 
-    boost::ptr_vector<ModelEvent> m_ModelEvents;
-    Mutex m_ModelEventsMutex;
-    SyncEvent m_NewModelEvent;
     DS485Interface* m_pDS485Interface;
     BusRequestDispatcher* m_pBusRequestDispatcher;
+    PropertyNodePtr m_pPropertyNode;
+    ModelMaintenance* m_pModelMaintenance;
   private:
     void addDefaultGroupsToZone(Zone& _zone);
-    void handleModelEvents();
-    void dsMeterReady(int _dsMeterBusID);
-    void setPowerConsumption(int _dsMeterBusID, unsigned long _value);
-    void setEnergyMeterValue(int _dsMeterBusID, unsigned long _value);
-    void discoverDS485Devices();
-
-    void raiseEvent(boost::shared_ptr<Event> _pEvent);
-    void waitForInterface();
-
-    void readConfiguration();
-    void writeConfiguration();
-  protected:
-    virtual void doStart();
   public:
-    Apartment(DSS* _pDSS, DS485Interface* _pDS485Interface);
+    Apartment(DSS* _pDSS);
     virtual ~Apartment();
 
-    virtual void initialize();
-
     /** Returns a set containing all devices of the set */
     virtual Set getDevices() const;
 
@@ -146,39 +124,20 @@ namespace dss {
     /** Allocates a group */
     UserGroup& allocateGroup(const int _id);
 
-    /** Returns wheter the apartment is still initializing or already running. */
-    bool isInitializing() const { return m_IsInitializing; }
-
     void removeZone(int _zoneID);
     void removeDevice(dsid_t _device);
     void removeDSMeter(dsid_t _dsMeter);
   public:
-
-    /** Returns the root-node for the apartment tree */
-    PropertyNodePtr getPropertyNode() { return m_pPropertyNode; }
-
-    /** Adds a model event to the queue.
-     * The ownership of the event will reside with the Apartment. ModelEvents arriving while initializing will be discarded.
-     */
-    void addModelEvent(ModelEvent* _pEvent);
-
-    /** Called by the DS485Proxy if a group-call-scene frame was intercepted.
-     *  Updates the state of all devices contained in the group. */
-    void onGroupCallScene(const int _zoneID, const int _groupID, const int _sceneID);
-    /** Called by the DS485Proxy if a device-call-scene frame was intercepted.
-     *  Updates the state of the device. */
-    void onDeviceCallScene(const int _dsMeterID, const int _deviceID, const int _sceneID);
-    /** Called by the DS485Proxy if an add-device frame was intercepted.
-     *  Adds the device to the model. */
-    void onAddDevice(const int _modID, const int _zoneID, const int _devID, const int _functionID);
-    void onDSLinkInterrupt(const int _modID, const int _devID, const int _priority);
-    /** Starts the event-processing */
-    virtual void execute();
-  public:
     void setDS485Interface(DS485Interface* _value) { m_pDS485Interface = _value; }
     DeviceBusInterface* getDeviceBusInterface();
     void setBusRequestDispatcher(BusRequestDispatcher* _value) { m_pBusRequestDispatcher = _value; }
     void dispatchRequest(boost::shared_ptr<BusRequest> _pRequest);
+    /** Returns the root-node for the apartment tree */
+    PropertyNodePtr getPropertyNode() { return m_pPropertyNode; }
+    void setModelMaintenance(ModelMaintenance* _value) { m_pModelMaintenance = _value; }
+    ModelMaintenance* getModelMaintenance() { return m_pModelMaintenance; }
+    void setPowerConsumption(int _dsMeterBusID, unsigned long _value);
+    void setEnergyMeterValue(int _dsMeterBusID, unsigned long _value);
   }; // Apartment
   
   /** Exception that will be thrown if a given item could not be found */
diff --git a/core/model/busscanner.cpp b/core/model/busscanner.cpp
index 865b871..30710dd 100644
--- a/core/model/busscanner.cpp
+++ b/core/model/busscanner.cpp
@@ -33,12 +33,14 @@
 #include "group.h"
 #include "apartment.h"
 #include "zone.h"
+#include "modelmaintenance.h"
 
 namespace dss {
   
-  BusScanner::BusScanner(StructureQueryBusInterface& _interface, Apartment& _apartment)
+  BusScanner::BusScanner(StructureQueryBusInterface& _interface, Apartment& _apartment, ModelMaintenance& _maintenance)
   : m_Apartment(_apartment),
-    m_Interface(_interface)
+    m_Interface(_interface),
+    m_Maintenance(_maintenance)
   {
   }
 
@@ -173,7 +175,7 @@ namespace dss {
           if(lastCalledScene < 0 || lastCalledScene > MaxSceneNumber) {
             log("scanDSMeter: _sceneID is out of bounds. zoneID: " + intToString(zoneID) + " groupID: " + intToString(groupID) + " scene: " + intToString(lastCalledScene), lsError);
           } else {
-            m_Apartment.onGroupCallScene(zoneID, groupID, lastCalledScene);
+            m_Maintenance.onGroupCallScene(zoneID, groupID, lastCalledScene);
           }
         } catch(DS485ApiError& error) {
           log(std::string("scanDSMeter: Error getting last called scene '") + error.what() + "'", lsError);
diff --git a/core/model/busscanner.h b/core/model/busscanner.h
index 71a9a88..fffb130 100644
--- a/core/model/busscanner.h
+++ b/core/model/busscanner.h
@@ -30,16 +30,18 @@ namespace dss {
   class StructureQueryBusInterface;
   class Apartment;
   class DSMeter;
+  class ModelMaintenance;
   
   class BusScanner {
   public:
-    BusScanner(StructureQueryBusInterface& _interface, Apartment& _apartment);
+    BusScanner(StructureQueryBusInterface& _interface, Apartment& _apartment, ModelMaintenance& _maintenance);
     bool scanDSMeter(DSMeter& _dsMeter);
   private:
     void log(const std::string& _line, aLogSeverity _severity = lsDebug);
   private:
     Apartment& m_Apartment;
     StructureQueryBusInterface& m_Interface;
+    ModelMaintenance& m_Maintenance;
   };
 
 } // namespace dss
diff --git a/core/model/device.cpp b/core/model/device.cpp
index 493fa72..8c144a1 100644
--- a/core/model/device.cpp
+++ b/core/model/device.cpp
@@ -28,6 +28,7 @@
 #include "core/model/scenehelper.h"
 #include "core/model/modelevent.h"
 #include "core/model/apartment.h"
+#include "core/model/modelmaintenance.h"
 
 namespace dss {
 
@@ -125,8 +126,10 @@ namespace dss {
   } // setName
 
   void Device::dirty() {
-    if(m_pApartment != NULL) {
-      m_pApartment->addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
+    if((m_pApartment != NULL) && (m_pApartment->getModelMaintenance() != NULL)) {
+      m_pApartment->getModelMaintenance()->addModelEvent(
+          new ModelEvent(ModelEvent::etModelDirty)
+      );
     }
   } // dirty
 
diff --git a/core/model/devicecontainer.cpp b/core/model/devicecontainer.cpp
index aa2049a..d993c35 100644
--- a/core/model/devicecontainer.cpp
+++ b/core/model/devicecontainer.cpp
@@ -25,6 +25,7 @@
 #include "core/dss.h"
 #include "modelevent.h"
 #include "apartment.h"
+#include "modelmaintenance.h"
 
 namespace dss {
 
@@ -34,7 +35,7 @@ namespace dss {
     if(m_Name != _name) {
       m_Name = _name;
       if(DSS::hasInstance()) {
-        DSS::getInstance()->getApartment().addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
+        DSS::getInstance()->getModelMaintenance().addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
       }
     }
   }
diff --git a/core/model/modelmaintenance.cpp b/core/model/modelmaintenance.cpp
new file mode 100644
index 0000000..a636021
--- /dev/null
+++ b/core/model/modelmaintenance.cpp
@@ -0,0 +1,522 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "modelmaintenance.h"
+
+#include <stdexcept>
+
+#include "core/foreach.h"
+#include "core/base.h"
+#include "core/dss.h"
+#include "core/event.h"
+#include "core/DS485Interface.h"
+#include "core/propertysystem.h"
+#include "core/ds485const.h"
+
+#include "apartment.h"
+#include "zone.h"
+#include "device.h"
+#include "devicereference.h"
+#include "modulator.h"
+#include "set.h"
+#include "modelpersistence.h"
+#include "busscanner.h"
+#include "scenehelper.h"
+
+namespace dss {
+
+  ModelMaintenance::ModelMaintenance(DSS* _pDSS)
+  : Subsystem(_pDSS, "Apartment"),
+    Thread("Apartment"),
+    m_IsInitializing(true)
+  { }
+
+  void ModelMaintenance::initialize() {
+    Subsystem::initialize();
+    if(m_pApartment == NULL) {
+      throw std::runtime_error("Need apartment to work...");
+    }
+    if(DSS::hasInstance()) {
+      DSS::getInstance()->getPropertySystem().setStringValue(getConfigPropertyBasePath() + "configfile", getDSS().getDataDirectory() + "apartment.xml", true, false);
+    }
+  } // initialize
+
+  void ModelMaintenance::doStart() {
+    run();
+  } // start
+
+  void ModelMaintenance::waitForInterface() {
+    if(DSS::hasInstance()) {
+      DS485Interface& interface = DSS::getInstance()->getDS485Interface();
+
+      log("Apartment::execute: Waiting for interface to get ready", lsInfo);
+
+      while(!interface.isReady() && !m_Terminated) {
+        sleepMS(1000);
+      }
+    }
+
+    boost::shared_ptr<Event> readyEvent(new Event("interface_ready"));
+    raiseEvent(readyEvent);
+  } // waitForInterface
+
+  void ModelMaintenance::execute() {
+    {
+      boost::shared_ptr<Event> runningEvent(new Event("running"));
+      raiseEvent(runningEvent);
+    }
+
+    // load devices/dsMeters/etc. from a config-file
+    readConfiguration();
+
+    {
+      boost::shared_ptr<Event> configReadEvent(new Event("config_read"));
+      raiseEvent(configReadEvent);
+    }
+
+    waitForInterface();
+
+    log("Apartment::execute: Interface is ready, enumerating model", lsInfo);
+    discoverDS485Devices();
+
+    while(!m_Terminated) {
+      handleModelEvents();
+    }
+  } // execute
+
+
+  void ModelMaintenance::discoverDS485Devices() {
+    // temporary mark all dsMeters as absent
+    foreach(DSMeter* pDSMeter, m_pApartment->getDSMeters()) {
+      pDSMeter->setIsPresent(false);
+    }
+
+    // Request the dsid of all dsMeters
+    DS485CommandFrame requestFrame;
+    requestFrame.getHeader().setBroadcast(true);
+    requestFrame.getHeader().setDestination(0);
+    requestFrame.setCommand(CommandRequest);
+    requestFrame.getPayload().add<uint8_t>(FunctionDSMeterGetDSID);
+    if(DSS::hasInstance()) {
+      getDSS().getDS485Interface().getFrameSenderInterface()->sendFrame(requestFrame);
+    }
+  } // discoverDS485Devices
+
+  void ModelMaintenance::writeConfiguration() {
+    if(DSS::hasInstance()) {
+      ModelPersistence persistence(*m_pApartment);
+      persistence.writeConfigurationToXML(DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile"));
+    }
+  } // writeConfiguration
+
+  void ModelMaintenance::handleModelEvents() {
+    if(!m_ModelEvents.empty()) {
+      ModelEvent& event = m_ModelEvents.front();
+      switch(event.getEventType()) {
+      case ModelEvent::etNewDevice:
+        if(event.getParameterCount() != 4) {
+          log("Expected exactly 4 parameter for ModelEvent::etNewDevice");
+        } else {
+          onAddDevice(event.getParameter(0), event.getParameter(1), event.getParameter(2), event.getParameter(3));
+        }
+        break;
+      case ModelEvent::etCallSceneDevice:
+        if(event.getParameterCount() != 3) {
+          log("Expected exactly 3 parameter for ModelEvent::etCallSceneDevice");
+        } else {
+          onDeviceCallScene(event.getParameter(0), event.getParameter(1), event.getParameter(2));
+        }
+        break;
+      case ModelEvent::etCallSceneGroup:
+        if(event.getParameterCount() != 3) {
+          log("Expected exactly 3 parameter for ModelEvent::etCallSceneGroup");
+        } else {
+          onGroupCallScene(event.getParameter(0), event.getParameter(1), event.getParameter(2));
+        }
+        break;
+      case ModelEvent::etModelDirty:
+        writeConfiguration();
+        break;
+      case ModelEvent::etDSLinkInterrupt:
+        if(event.getParameterCount() != 3) {
+          log("Expected exactly 3 parameter for ModelEvent::etDSLinkInterrupt");
+        } else {
+          onDSLinkInterrupt(event.getParameter(0), event.getParameter(1), event.getParameter(2));
+        }
+        break;
+      case ModelEvent::etNewDSMeter:
+        discoverDS485Devices();
+        break;
+      case ModelEvent::etLostDSMeter:
+        discoverDS485Devices();
+        break;
+      case ModelEvent::etDSMeterReady:
+        if(event.getParameterCount() != 1) {
+          log("Expected exactly 1 parameter for ModelEvent::etDSMeterReady");
+        } else {
+          try{
+            DSMeter& mod = m_pApartment->getDSMeterByBusID(event.getParameter(0));
+            mod.setIsPresent(true);
+            mod.setIsValid(false);
+          } catch(ItemNotFoundException& e) {
+            log("dSM is ready, but it is not yet known, re-discovering devices");
+            discoverDS485Devices();
+          }
+        }
+        break;
+      case ModelEvent::etBusReady:
+        log("Got bus ready event.", lsInfo);
+        discoverDS485Devices();
+        break;
+      case ModelEvent::etPowerConsumption:
+        if(event.getParameterCount() != 2) {
+          log("Expected exactly 2 parameter for ModelEvent::etPowerConsumption");
+        } else {
+          m_pApartment->setPowerConsumption(event.getParameter(0), event.getParameter(1));
+        }
+        break;
+      case ModelEvent::etEnergyMeterValue:
+        if(event.getParameterCount() != 2) {
+          log("Expected exactly 2 parameter for ModelEvent::etEnergyMeterValue");
+        } else {
+          m_pApartment->setEnergyMeterValue(event.getParameter(0), event.getParameter(1));
+        }
+        break;
+      case ModelEvent::etDS485DeviceDiscovered:
+        if(event.getParameterCount() != 7) {
+          log("Expected exactly 7 parameter for ModelEvent::etDS485DeviceDiscovered");
+        } else {
+          int busID = event.getParameter(0);
+          uint64_t dsidUpper = (uint64_t(event.getParameter(1)) & 0x00ffff) << 48;
+          dsidUpper |= (uint64_t(event.getParameter(2)) & 0x00ffff) << 32;
+          dsidUpper |= (uint64_t(event.getParameter(3))  & 0x00ffff) << 16;
+          dsidUpper |= (uint64_t(event.getParameter(4)) & 0x00ffff);
+          dsid_t newDSID(dsidUpper,
+                         ((uint32_t(event.getParameter(5)) & 0x00ffff) << 16) | (uint32_t(event.getParameter(6)) & 0x00ffff));
+          log ("Discovered device with busID: " + intToString(busID) + " and dsid: " + newDSID.toString());
+          try{
+             m_pApartment->getDSMeterByDSID(newDSID).setBusID(busID);
+             log ("dSM present");
+             m_pApartment->getDSMeterByDSID(newDSID).setIsPresent(true);
+          } catch(ItemNotFoundException& e) {
+             log ("dSM not present");
+             DSMeter& dsMeter = m_pApartment->allocateDSMeter(newDSID);
+             dsMeter.setBusID(busID);
+             dsMeter.setIsPresent(true);
+             dsMeter.setIsValid(false);
+             ModelEvent* pEvent = new ModelEvent(ModelEvent::etDSMeterReady);
+             pEvent->addParameter(busID);
+             addModelEvent(pEvent);
+          }
+        }
+        break;
+      default:
+        assert(false);
+        break;
+      }
+
+      m_ModelEventsMutex.lock();
+      m_ModelEvents.erase(m_ModelEvents.begin());
+      m_ModelEventsMutex.unlock();
+    } else {
+      m_NewModelEvent.waitFor(1000);
+      bool hadToUpdate = false;
+      foreach(DSMeter* pDSMeter, m_pApartment->getDSMeters()) {
+        if(pDSMeter->isPresent()) {
+          if(!pDSMeter->isValid()) {
+            dsMeterReady(pDSMeter->getBusID());
+            hadToUpdate = true;
+            break;
+          }
+        }
+      }
+
+      // If we didn't have to update for one cycle, assume that we're done
+      if(!hadToUpdate && m_IsInitializing) {
+        log("******** Finished loading model from dSM(s)...", lsInfo);
+        m_IsInitializing = false;
+
+        {
+          boost::shared_ptr<Event> readyEvent(new Event("model_ready"));
+          raiseEvent(readyEvent);
+        }
+      }
+    }
+  } // handleModelEvents
+
+  void ModelMaintenance::dsMeterReady(int _dsMeterBusID) {
+    log("DSMeter with id: " + intToString(_dsMeterBusID) + " is ready", lsInfo);
+    try {
+      try {
+        DSMeter& mod = m_pApartment->getDSMeterByBusID(_dsMeterBusID);
+        BusScanner scanner(*getDSS().getDS485Interface().getStructureQueryBusInterface(), *m_pApartment, *this);
+        if(scanner.scanDSMeter(mod)) {
+          boost::shared_ptr<Event> dsMeterReadyEvent(new Event("dsMeter_ready"));
+          dsMeterReadyEvent->setProperty("dsMeter", mod.getDSID().toString());
+          raiseEvent(dsMeterReadyEvent);
+        }
+      } catch(DS485ApiError& e) {
+        log(std::string("Exception caught while scanning dsMeter " + intToString(_dsMeterBusID) + " : ") + e.what(), lsFatal);
+
+        ModelEvent* pEvent = new ModelEvent(ModelEvent::etDSMeterReady);
+        pEvent->addParameter(_dsMeterBusID);
+        addModelEvent(pEvent);
+      }
+    } catch(ItemNotFoundException& e) {
+      log("No dsMeter for bus-id (" + intToString(_dsMeterBusID) + ") found, re-discovering devices");
+      discoverDS485Devices();
+    }
+  } // dsMeterReady
+
+  void ModelMaintenance::addModelEvent(ModelEvent* _pEvent) {
+    // filter out dirty events, as this will rewrite apartment.xml
+    if(m_IsInitializing && (_pEvent->getEventType() == ModelEvent::etModelDirty)) {
+      delete _pEvent;
+    } else {
+      m_ModelEventsMutex.lock();
+      m_ModelEvents.push_back(_pEvent);
+      m_ModelEventsMutex.unlock();
+      m_NewModelEvent.signal();
+    }
+  } // addModelEvent
+
+  void ModelMaintenance::readConfiguration() {
+    if(DSS::hasInstance()) {
+      std::string configFileName = DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile");
+      ModelPersistence persistence(*m_pApartment);
+      persistence.readConfigurationFromXML(configFileName);
+    }
+  } // readConfiguration
+
+  void ModelMaintenance::raiseEvent(boost::shared_ptr<Event> _pEvent) {
+    if(DSS::hasInstance()) {
+      getDSS().getEventQueue().pushEvent(_pEvent);
+    }
+  } // raiseEvent
+
+  class SetLastCalledSceneAction : public IDeviceAction {
+  protected:
+    int m_SceneID;
+  public:
+    SetLastCalledSceneAction(const int _sceneID)
+    : m_SceneID(_sceneID) {}
+    virtual ~SetLastCalledSceneAction() {}
+
+    virtual bool perform(Device& _device) {
+      _device.setLastCalledScene(m_SceneID);
+      return true;
+    }
+  };
+
+  void ModelMaintenance::onGroupCallScene(const int _zoneID, const int _groupID, const int _sceneID) {
+    try {
+      if(_sceneID < 0 || _sceneID > MaxSceneNumber) {
+        log("onGroupCallScene: Scene number is out of bounds. zoneID: " + intToString(_zoneID) + " groupID: " + intToString(_groupID) + " scene: " + intToString(_sceneID), lsError);
+        return;
+      }
+      Zone& zone = m_pApartment->getZone(_zoneID);
+      Group* group = zone.getGroup(_groupID);
+      if(group != NULL) {
+        log("OnGroupCallScene: group-id '" + intToString(_groupID) + "' in Zone '" + intToString(_zoneID) + "' scene: " + intToString(_sceneID));
+        if(SceneHelper::rememberScene(_sceneID & 0x00ff)) {
+          Set s = zone.getDevices().getByGroup(_groupID);
+          SetLastCalledSceneAction act(_sceneID & 0x00ff);
+          s.perform(act);
+
+          std::vector<Zone*> zonesToUpdate;
+          if(_zoneID == 0) {
+            zonesToUpdate = m_pApartment->getZones();
+          } else {
+            zonesToUpdate.push_back(&zone);
+          }
+          foreach(Zone* pZone, zonesToUpdate) {
+            if(_groupID == 0) {
+              foreach(Group* pGroup, pZone->getGroups()) {
+                pGroup->setLastCalledScene(_sceneID & 0x00ff);
+              }
+            } else {
+              Group* pGroup = pZone->getGroup(_groupID);
+              if(pGroup != NULL) {
+                pGroup->setLastCalledScene(_sceneID & 0x00ff);
+              }
+            }
+          }
+        }
+      } else {
+        log("OnGroupCallScene: Could not find group with id '" + intToString(_groupID) + "' in Zone '" + intToString(_zoneID) + "'", lsError);
+      }
+    } catch(ItemNotFoundException& e) {
+      log("OnGroupCallScene: Could not find zone with id '" + intToString(_zoneID) + "'", lsError);
+    }
+
+  } // onGroupCallScene
+
+  void ModelMaintenance::onDeviceCallScene(const int _dsMeterID, const int _deviceID, const int _sceneID) {
+    try {
+      if(_sceneID < 0 || _sceneID > MaxSceneNumber) {
+        log("onDeviceCallScene: _sceneID is out of bounds. dsMeter-id '" + intToString(_dsMeterID) + "' for device '" + intToString(_deviceID) + "' scene: " + intToString(_sceneID), lsError);
+        return;
+      }
+      DSMeter& mod = m_pApartment->getDSMeterByBusID(_dsMeterID);
+      try {
+        log("OnDeviceCallScene: dsMeter-id '" + intToString(_dsMeterID) + "' for device '" + intToString(_deviceID) + "' scene: " + intToString(_sceneID));
+        DeviceReference devRef = mod.getDevices().getByBusID(_deviceID, _dsMeterID);
+        if(SceneHelper::rememberScene(_sceneID & 0x00ff)) {
+          devRef.getDevice().setLastCalledScene(_sceneID & 0x00ff);
+        }
+      } catch(ItemNotFoundException& e) {
+        log("OnDeviceCallScene: Could not find device with bus-id '" + intToString(_deviceID) + "' on dsMeter '" + intToString(_dsMeterID) + "' scene:" + intToString(_sceneID), lsError);
+      }
+    } catch(ItemNotFoundException& e) {
+      log("OnDeviceCallScene: Could not find dsMeter with bus-id '" + intToString(_dsMeterID) + "'", lsError);
+    }
+  } // onDeviceCallScene
+
+  void ModelMaintenance::onAddDevice(const int _modID, const int _zoneID, const int _devID, const int _functionID) {
+    // get full dsid
+    log("New Device found");
+    log("  DSMeter: " + intToString(_modID));
+    log("  Zone:      " + intToString(_zoneID));
+    log("  BusID:     " + intToString(_devID));
+    log("  FID:       " + intToString(_functionID));
+
+    dsid_t dsid = getDSS().getDS485Interface().getStructureQueryBusInterface()->getDSIDOfDevice(_modID, _devID);
+    Device& dev = m_pApartment->allocateDevice(dsid);
+    DeviceReference devRef(dev, m_pApartment);
+
+    log("  DSID:      " + dsid.toString());
+
+    // remove from old dsMeter
+    try {
+      DSMeter& oldDSMeter = m_pApartment->getDSMeterByBusID(dev.getDSMeterID());
+      oldDSMeter.removeDevice(devRef);
+    } catch(std::runtime_error&) {
+    }
+
+    // remove from old zone
+    if(dev.getZoneID() != 0) {
+      try {
+        Zone& oldZone = m_pApartment->getZone(dev.getZoneID());
+        oldZone.removeDevice(devRef);
+        // TODO: check if the zone is empty on the dsMeter and remove it in that case
+      } catch(std::runtime_error&) {
+      }
+    }
+
+    // update device
+    dev.setDSMeterID(_modID);
+    dev.setZoneID(_zoneID);
+    dev.setShortAddress(_devID);
+    dev.setFunctionID(_functionID);
+    dev.setIsPresent(true);
+
+    // add to new dsMeter
+    DSMeter& dsMeter = m_pApartment->getDSMeterByBusID(_modID);
+    dsMeter.addDevice(devRef);
+
+    // add to new zone
+    Zone& newZone = m_pApartment->allocateZone(_zoneID);
+    newZone.addToDSMeter(dsMeter);
+    newZone.addDevice(devRef);
+
+    // get groups of device
+    dev.resetGroups();
+    std::vector<int> groups = getDSS().getDS485Interface().getStructureQueryBusInterface()->getGroupsOfDevice(_modID, _devID);
+    foreach(int iGroup, groups) {
+      log("  Adding to Group: " + intToString(iGroup));
+      dev.addToGroup(iGroup);
+    }
+
+    {
+      boost::shared_ptr<Event> readyEvent(new Event("new_device"));
+      readyEvent->setProperty("device", dsid.toString());
+      readyEvent->setProperty("zone", intToString(_zoneID));
+      raiseEvent(readyEvent);
+    }
+  } // onAddDevice
+
+  void ModelMaintenance::onDSLinkInterrupt(const int _modID, const int _devID, const int _priority) {
+    // get full dsid
+    log("dSLinkInterrupt:");
+    log("  DSMeter: " + intToString(_modID));
+    log("  DevID:     " + intToString(_devID));
+    log("  Priority:  " + intToString(_priority));
+
+    try {
+      DSMeter& dsMeter = m_pApartment->getDSMeterByBusID(_modID);
+      try {
+        Device& device = m_pApartment->getDeviceByShortAddress(dsMeter, _devID);
+        PropertyNodePtr deviceNode = device.getPropertyNode();
+        if(deviceNode == NULL) {
+          return;
+        }
+        PropertyNodePtr modeNode = deviceNode->getProperty("interrupt/mode");
+        if(modeNode == NULL) {
+          return;
+        }
+        std::string mode = modeNode->getStringValue();
+        if(mode == "ignore") {
+          log("ignoring interrupt");
+        } else if(mode == "raise_event") {
+          log("raising interrupt as event");
+          std::string eventName = "dslink_interrupt";
+          PropertyNodePtr eventNameNode = deviceNode->getProperty("interrupt/event/name");
+          if(eventNameNode == NULL) {
+            log("no node called 'interrupt/event' found, assuming name is 'dslink_interrupt'");
+          } else {
+            eventName = eventNameNode->getAsString();
+          }
+
+          // create event to be raised
+          DeviceReference devRef(device, m_pApartment);
+          boost::shared_ptr<Event> evt(new Event(eventName, &devRef));
+          evt->setProperty("device", device.getDSID().toString());
+          std::string priorityString = "unknown";
+          if(_priority == 0) {
+            priorityString = "normal";
+          } else if(_priority == 1) {
+            priorityString = "high";
+          }
+          evt->setProperty("priority", priorityString);
+          raiseEvent(evt);
+        } else {
+          log("unknown interrupt mode '" + mode + "'", lsError);
+        }
+      } catch (ItemNotFoundException& ex) {
+        log("Apartment::onDSLinkInterrupt: Unknown device with ID " + intToString(_devID), lsFatal);
+        return;
+      }
+    } catch(ItemNotFoundException& ex) {
+      log("Apartment::onDSLinkInterrupt: Unknown DSMeter with ID " + intToString(_modID), lsFatal);
+      return;
+    }
+  } // onDSLinkInterrupt
+
+  void ModelMaintenance::setApartment(Apartment* _value) {
+    m_pApartment = _value;
+    if(m_pApartment != NULL) {
+      m_pApartment->setModelMaintenance(this);
+    }
+  } // setApartment
+
+} // namespace dss
diff --git a/core/model/modelmaintenance.h b/core/model/modelmaintenance.h
new file mode 100644
index 0000000..7a40567
--- /dev/null
+++ b/core/model/modelmaintenance.h
@@ -0,0 +1,94 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef MODELMAINTENANCE_H_
+#define MODELMAINTENANCE_H_
+
+#include <boost/shared_ptr.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+
+#include "core/subsystem.h"
+#include "core/thread.h"
+#include "core/syncevent.h"
+
+namespace dss {
+  class PropertyNode;
+  typedef boost::shared_ptr<PropertyNode> PropertyNodePtr;
+  class Apartment;
+  class ModelEvent;
+  class Event;
+
+
+  class ModelMaintenance : public Subsystem,
+                           public Thread {
+  public:
+    ModelMaintenance(DSS* _pDSS);
+    virtual ~ModelMaintenance() {}
+
+    virtual void initialize();
+
+    /** Adds a model event to the queue.
+     * The ownership of the event will reside with the Apartment. ModelEvents arriving while initializing will be discarded.
+     */
+    void addModelEvent(ModelEvent* _pEvent);
+
+    /** Called by the DS485Proxy if a group-call-scene frame was intercepted.
+     *  Updates the state of all devices contained in the group. */
+    void onGroupCallScene(const int _zoneID, const int _groupID, const int _sceneID);
+    /** Called by the DS485Proxy if a device-call-scene frame was intercepted.
+     *  Updates the state of the device. */
+    void onDeviceCallScene(const int _dsMeterID, const int _deviceID, const int _sceneID);
+    /** Called by the DS485Proxy if an add-device frame was intercepted.
+     *  Adds the device to the model. */
+    void onAddDevice(const int _modID, const int _zoneID, const int _devID, const int _functionID);
+    void onDSLinkInterrupt(const int _modID, const int _devID, const int _priority);
+    /** Starts the event-processing */
+    virtual void execute();
+
+    bool isInitializing() const { return m_IsInitializing; }
+    void setApartment(Apartment* _value);
+  protected:
+    virtual void doStart();
+  private:
+    void handleModelEvents();
+    void dsMeterReady(int _dsMeterBusID);
+    void discoverDS485Devices();
+    void waitForInterface();
+
+    void readConfiguration();
+    void writeConfiguration();
+
+    void raiseEvent(boost::shared_ptr<Event> _pEvent);
+  private:
+    bool m_IsInitializing;
+
+    PropertyNodePtr m_pPropertyNode;
+
+    boost::ptr_vector<ModelEvent> m_ModelEvents;
+    Mutex m_ModelEventsMutex;
+    SyncEvent m_NewModelEvent;
+    Apartment* m_pApartment;
+  }; // ModelMaintenance
+
+}
+
+#endif /* MODELMAINTENANCE_H_ */
diff --git a/core/model/modelpersistence.cpp b/core/model/modelpersistence.cpp
index bbfa0d4..4a5b0e8 100644
--- a/core/model/modelpersistence.cpp
+++ b/core/model/modelpersistence.cpp
@@ -81,7 +81,7 @@ namespace dss {
           std::string nodeName = curNode->localName();
           if(nodeName == "devices") {
             loadDevices(curNode);
-          } else if(nodeName == "dsMeters") {
+          } else if(nodeName == "modulators") {
             loadDSMeters(curNode);
           } else if(nodeName == "zones") {
             loadZones(curNode);
@@ -97,7 +97,7 @@ namespace dss {
           curNode = curNode->nextSibling();
         }
       } else {
-        m_Apartment.log("Config file has the wrong version");
+        Logger::getInstance()->log("Config file has the wrong version");
       }
     }
   } // readConfigurationFromXML
@@ -139,7 +139,7 @@ namespace dss {
   void ModelPersistence::loadDSMeters(Node* _node) {
     Node* curNode = _node->firstChild();
     while(curNode != NULL) {
-      if(curNode->localName() == "dsMeter") {
+      if(curNode->localName() == "modulators") {
         Element* elem = dynamic_cast<Element*>(curNode);
         if((elem != NULL) && elem->hasAttribute("id")) {
           dsid_t id = dsid_t::fromString(elem->getAttribute("id"));
@@ -212,7 +212,7 @@ namespace dss {
   } // zoneToXML
 
   void dsMeterToXML(const DSMeter* _pDSMeter, AutoPtr<Element>& _parentNode, AutoPtr<Document>& _pDocument) {
-    AutoPtr<Element> pDSMeterNode = _pDocument->createElement("dsMeter");
+    AutoPtr<Element> pDSMeterNode = _pDocument->createElement("modulator");
     pDSMeterNode->setAttribute("id", _pDSMeter->getDSID().toString());
     if(!_pDSMeter->getName().empty()) {
       AutoPtr<Element> pNameNode = _pDocument->createElement("name");
@@ -224,7 +224,7 @@ namespace dss {
   } // dsMeterToXML
 
   void ModelPersistence::writeConfigurationToXML(const std::string& _fileName) {
-    m_Apartment.log("Writing apartment config to '" + _fileName + "'", lsInfo);
+    Logger::getInstance()->log("Writing apartment config to '" + _fileName + "'", lsInfo);
     AutoPtr<Document> pDoc = new Document;
 
     AutoPtr<ProcessingInstruction> pXMLHeader = pDoc->createProcessingInstruction("xml", "version='1.0' encoding='utf-8'");
@@ -277,7 +277,7 @@ namespace dss {
       // move it to the desired location
       rename(tmpOut.c_str(), _fileName.c_str());
     } else {
-      m_Apartment.log("Could not open file '" + tmpOut + "' for writing", lsFatal);
+      Logger::getInstance()->log("Could not open file '" + tmpOut + "' for writing", lsFatal);
     }
   } // writeConfigurationToXML
 
diff --git a/core/model/modulator.cpp b/core/model/modulator.cpp
index 03804c2..fc76ad4 100644
--- a/core/model/modulator.cpp
+++ b/core/model/modulator.cpp
@@ -74,7 +74,7 @@ namespace dss {
   unsigned long DSMeter::getPowerConsumption() {
     DateTime now;
     if(!now.addSeconds(-1).before(m_PowerConsumptionAge)) {
-      m_PowerConsumption =  DSS::getInstance()->getDS485Interface().getPowerConsumption(m_BusID);
+      m_PowerConsumption =  DSS::getInstance()->getDS485Interface().getMeteringBusInterface()->getPowerConsumption(m_BusID);
       m_PowerConsumptionAge = now;
     }
     return m_PowerConsumption;
@@ -83,7 +83,7 @@ namespace dss {
   unsigned long DSMeter::getEnergyMeterValue() {
     DateTime now;
     if(!now.addSeconds(-1).before(m_EnergyMeterValueAge)) {
-      m_EnergyMeterValue = DSS::getInstance()->getDS485Interface().getEnergyMeterValue(m_BusID);
+      m_EnergyMeterValue = DSS::getInstance()->getDS485Interface().getMeteringBusInterface()->getEnergyMeterValue(m_BusID);
       m_EnergyMeterValueAge = now;
     }
     return m_EnergyMeterValue;
@@ -91,16 +91,14 @@ namespace dss {
 
 
   /** set the consumption in mW */
-  void DSMeter::setPowerConsumption(unsigned long _value)
-  {
+  void DSMeter::setPowerConsumption(unsigned long _value) {
     DateTime now;
     m_PowerConsumptionAge = now;
     m_PowerConsumption = _value;
   }
 
   /** set the meter value in Wh */
-  void DSMeter::setEnergyMeterValue(unsigned long _value)
-  {
+  void DSMeter::setEnergyMeterValue(unsigned long _value)  {
     DateTime now;
     m_EnergyMeterValueAge = now;
     m_EnergyMeterValue = _value;
diff --git a/core/sim/dssim.cpp b/core/sim/dssim.cpp
index bdb0103..e696f51 100644
--- a/core/sim/dssim.cpp
+++ b/core/sim/dssim.cpp
@@ -154,7 +154,7 @@ namespace dss {
         if(rootNode->hasAttribute("version") && (strToInt(rootNode->getAttribute("version")) == theConfigFileVersion)) {
           Node* curNode = rootNode->firstChild();
           while(curNode != NULL) {
-            if(curNode->localName() == "dsMeter") {
+            if(curNode->localName() == "modulator") {
               DSDSMeterSim* dsMeter = NULL;
               try {
                 dsMeter = new DSDSMeterSim(this);
diff --git a/core/structuremanipulator.h b/core/structuremanipulator.h
index 3315595..30fe524 100644
--- a/core/structuremanipulator.h
+++ b/core/structuremanipulator.h
@@ -26,7 +26,7 @@
 namespace dss {
 
   class Apartment;
-  class DS485Interface;
+  class StructureModifyingBusInterface;
   class DSMeter;
   class Device;
   class Zone;
@@ -34,9 +34,9 @@ namespace dss {
   class StructureManipulator {
   private:
     Apartment& m_Apartment;
-    DS485Interface& m_Interface;
+    StructureModifyingBusInterface& m_Interface;
   public:
-    StructureManipulator(DS485Interface& _interface, Apartment& _apartment)
+    StructureManipulator(StructureModifyingBusInterface& _interface, Apartment& _apartment)
     : m_Apartment(_apartment), m_Interface(_interface)
     { } // ctor
 
diff --git a/core/web/webrequests.cpp b/core/web/webrequests.cpp
index 3d9be8b..b997e72 100644
--- a/core/web/webrequests.cpp
+++ b/core/web/webrequests.cpp
@@ -30,6 +30,7 @@
 
 #include "core/event.h"
 #include "core/ds485/ds485proxy.h"
+#include "core/ds485/framebucketcollector.h"
 #include "core/sim/dssim.h"
 #include "core/propertysystem.h"
 #include "core/foreach.h"
@@ -42,6 +43,7 @@
 #include "core/model/group.h"
 #include "core/model/modulator.h"
 #include "core/model/modelevent.h"
+#include "core/model/modelmaintenance.h"
 
 #include "core/metering/metering.h"
 #include "core/metering/series.h"
@@ -969,7 +971,7 @@ namespace dss {
   //=========================================== StructureRequestHandler
 
   std::string StructureRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
-    StructureManipulator manipulator(getDSS().getDS485Interface(), getDSS().getApartment());
+    StructureManipulator manipulator(*getDSS().getDS485Interface().getStructureModifyingBusInterface(), getDSS().getApartment());
     if(_request.getMethod() == "zoneAddDevice") {
       std::string devidStr = _request.getParameter("devid");
       if(!devidStr.empty()) {
@@ -1029,7 +1031,7 @@ namespace dss {
             return ResultToJSON(false, "Cannot delete a non-empty zone");
           }
           getDSS().getApartment().removeZone(zoneID);
-          getDSS().getApartment().addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
+          getDSS().getModelMaintenance().addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
           return JSONOk();
         } catch(ItemNotFoundException&) {
           return ResultToJSON(false, "Could not find zone");
@@ -1226,11 +1228,11 @@ namespace dss {
           boost::shared_ptr<FrameBucketCollector> bucket = proxy->sendFrameAndInstallBucket(*frame, FunctionDeviceGetTransmissionQuality);
           bucket->waitForFrame(2000);
 
-          boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+          boost::shared_ptr<DS485CommandFrame> recFrame = bucket->popFrame();
           if(recFrame == NULL) {
             return ResultToJSON(false, "No result received");
           }
-          PayloadDissector pd(recFrame->getFrame()->getPayload());
+          PayloadDissector pd(recFrame->getPayload());
           pd.get<uint8_t>();
           int errC = int(pd.get<uint16_t>());
           if(errC < 0) {
diff --git a/tests/busrequesttests.cpp b/tests/busrequesttests.cpp
index 7f65032..43ef57a 100644
--- a/tests/busrequesttests.cpp
+++ b/tests/busrequesttests.cpp
@@ -48,8 +48,7 @@ private:
 };
 
 BOOST_AUTO_TEST_CASE(testRequestReachesDispatcher) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
   Device& d1 = apt.allocateDevice(dsid_t(0,1));
   TestDispatcher dispatcher;
   apt.setBusRequestDispatcher(&dispatcher);
diff --git a/tests/eventtests.cpp b/tests/eventtests.cpp
index 12a22d3..bb5a63f 100644
--- a/tests/eventtests.cpp
+++ b/tests/eventtests.cpp
@@ -29,6 +29,7 @@
 #include "core/setbuilder.h"
 #include "core/sim/dssim.h"
 #include "core/model/apartment.h"
+#include "core/model/modelmaintenance.h"
 #include "core/model/device.h"
 #include "core/model/devicereference.h"
 #include "core/model/zone.h"
@@ -181,8 +182,7 @@ BOOST_AUTO_TEST_CASE(testSubscriptionXML) {
 
 
 BOOST_AUTO_TEST_CASE(testSetBuilder) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   SetBuilder setBuilder(apt);
 
@@ -220,12 +220,12 @@ BOOST_AUTO_TEST_CASE(testDS485Events) {
   queue.setEventRunner(&runner);
   runner.setEventQueue(&queue);
 
-  Apartment apt(NULL, NULL);
+  Apartment apt(NULL);
+  ModelMaintenance maintenance(NULL);
   DSDSMeterSim modSim(NULL);
-  DS485Proxy proxy(NULL, &apt);
+  DS485Proxy proxy(NULL, &maintenance);
   apt.setDS485Interface(&proxy);
 
-  apt.initialize();
   proxy.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
diff --git a/tests/modeljstests.cpp b/tests/modeljstests.cpp
index ea2ca62..3d3711d 100644
--- a/tests/modeljstests.cpp
+++ b/tests/modeljstests.cpp
@@ -40,7 +40,7 @@ using namespace dss;
 BOOST_AUTO_TEST_SUITE(ModelJS)
 
 BOOST_AUTO_TEST_CASE(testBasics) {
-  Apartment apt(NULL, NULL);
+  Apartment apt(NULL);
   apt.setName("my apartment");
 
 
@@ -61,8 +61,7 @@ BOOST_AUTO_TEST_CASE(testBasics) {
 } // testBasics
 
 BOOST_AUTO_TEST_CASE(testSets) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
@@ -141,8 +140,7 @@ BOOST_AUTO_TEST_CASE(testSets) {
 } // testSets
 
 BOOST_AUTO_TEST_CASE(testDevices) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
@@ -166,8 +164,7 @@ BOOST_AUTO_TEST_CASE(testDevices) {
 } // testDevices
 
 BOOST_AUTO_TEST_CASE(testEvents) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev = apt.allocateDevice(dsid_t(0,1));
   dev.setShortAddress(1);
@@ -201,8 +198,7 @@ BOOST_AUTO_TEST_CASE(testEvents) {
 } // testEvents
 
 BOOST_AUTO_TEST_CASE(testSubscriptions) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev = apt.allocateDevice(dsid_t(0,1));
   dev.setShortAddress(1);
diff --git a/tests/modeltests.cpp b/tests/modeltests.cpp
index 0f19452..ec94f23 100644
--- a/tests/modeltests.cpp
+++ b/tests/modeltests.cpp
@@ -24,6 +24,8 @@
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 
+#include <boost/scoped_ptr.hpp>
+
 #include "core/model/device.h"
 #include "core/model/apartment.h"
 #include "core/model/modulator.h"
@@ -31,19 +33,20 @@
 #include "core/model/zone.h"
 #include "core/model/set.h"
 #include "core/setbuilder.h"
-#include "core/ds485const.h"
-#include "core/ds485/ds485proxy.h"
 #include "core/sim/dssim.h"
 #include "core/dss.h"
+#include "core/ds485const.h"
+#include "core/ds485/ds485proxy.h"
 #include "core/ds485/ds485busrequestdispatcher.h"
+#include "core/ds485/businterfacehandler.h"
+#include "core/model/modelmaintenance.h"
 
 using namespace dss;
 
 BOOST_AUTO_TEST_SUITE(Model)
 
 BOOST_AUTO_TEST_CASE(testApartmentAllocateDeviceReturnsTheSameDeviceForDSID) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
@@ -57,8 +60,7 @@ BOOST_AUTO_TEST_CASE(testApartmentAllocateDeviceReturnsTheSameDeviceForDSID) {
 } // testApartmentAllocateDeviceReturnsTheSameDeviceForDSID
 
 BOOST_AUTO_TEST_CASE(testSetGetByBusID) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
@@ -89,8 +91,7 @@ BOOST_AUTO_TEST_CASE(testSetGetByBusID) {
 } // testSetGetByBusID
 
 BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByShortAddress) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   DSMeter& mod = apt.allocateDSMeter(dsid_t(0,2));
   mod.setBusID(1);
@@ -104,8 +105,7 @@ BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByShortAddress) {
 } // testApartmentGetDeviceByShortAddress
 
 BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByName) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setName("dev1");
@@ -114,8 +114,7 @@ BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByName) {
 } // testApartmentGetDeviceByName
 
 BOOST_AUTO_TEST_CASE(testApartmentGetDSMeterByName) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   DSMeter& mod = apt.allocateDSMeter(dsid_t(0,2));
   mod.setName("mod1");
@@ -124,8 +123,7 @@ BOOST_AUTO_TEST_CASE(testApartmentGetDSMeterByName) {
 } // testApartmentGetDSMeterByName
 
 BOOST_AUTO_TEST_CASE(testApartmentGetDSMeterByBusID) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   DSMeter& mod = apt.allocateDSMeter(dsid_t(0,2));
   mod.setBusID(1);
@@ -134,8 +132,7 @@ BOOST_AUTO_TEST_CASE(testApartmentGetDSMeterByBusID) {
 } // testApartmentGetDSMeterByBusID
 
 BOOST_AUTO_TEST_CASE(testZoneMoving) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
@@ -204,8 +201,7 @@ BOOST_AUTO_TEST_CASE(testZoneMoving) {
 } // testZoneMoving
 
 BOOST_AUTO_TEST_CASE(testSet) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
@@ -282,8 +278,7 @@ BOOST_AUTO_TEST_CASE(testSet) {
 } // testSet
 
 BOOST_AUTO_TEST_CASE(testSetBuilder) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
@@ -397,8 +392,7 @@ BOOST_AUTO_TEST_CASE(testSetBuilder) {
 } // testSetBuilder
 
 BOOST_AUTO_TEST_CASE(testRemoval) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
@@ -444,20 +438,25 @@ BOOST_AUTO_TEST_CASE(testRemoval) {
 } // testRemoval
 
 BOOST_AUTO_TEST_CASE(testCallScenePropagation) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  Apartment apt(NULL);
 
   DSDSMeterSim modSim(NULL);
-  DS485Proxy proxy(NULL, &apt);
   DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
+  ModelMaintenance maintenance(NULL);
+  maintenance.setApartment(&apt);
+  maintenance.initialize();
+  DS485Proxy proxy(NULL, &maintenance);
+  dispatcher.setFrameSender(proxy.getFrameSenderInterface());
+  BusInterfaceHandler busHandler(NULL, maintenance);
+  proxy.setBusInterfaceHandler(&busHandler);
   proxy.setInitializeDS485Controller(false);
   proxy.initialize();
   apt.setBusRequestDispatcher(&dispatcher);
+  busHandler.initialize();
 
-  proxy.start();
-  apt.start();
-  while(apt.isInitializing()) {
+  busHandler.start();
+  maintenance.start();
+  while(maintenance.isInitializing()) {
     sleepMS(100);
   }
 
@@ -481,751 +480,383 @@ BOOST_AUTO_TEST_CASE(testCallScenePropagation) {
   sleepMS(500);
   BOOST_CHECK_EQUAL(Scene2, dev1.getLastCalledScene());
   BOOST_CHECK_EQUAL(Scene2, dev2.getLastCalledScene());
-  proxy.terminate();
-  apt.terminate();
+  busHandler.terminate();
+  maintenance.terminate();
   sleepMS(1500);
   DSS::teardown();
 } // testCallScenePropagation
 
 
-  /** Interface to be implemented by any implementation of the DS485 interface */
-  class DS485InterfaceTest : public DS485Interface,
-                             public DeviceBusInterface,
-                             public StructureQueryBusInterface {
-  public:
-    /** Returns true when the interface is ready to transmit user generated DS485Packets */
-    virtual bool isReady() { return true; }
-    
-    int getLastFunctionID() const { return m_LastFunctionID; }
-    void setLastFunctionID(const int _value) { m_LastFunctionID = _value; }
-    int getParameter1() const { return m_Parameter1; }
-    int getParameter2() const { return m_Parameter2; }
-    int getParameter3() const { return m_Parameter3; }
-    virtual void sendFrame(DS485CommandFrame& _frame) {
-      PayloadDissector pd(_frame.getPayload());
-      m_LastFunctionID = pd.get<uint8_t>();
-      if(!pd.isEmpty()) {
-        m_Parameter1 = pd.get<uint16_t>();
-      } else {
-        m_Parameter1 = 0xffff;
-      }
-      if(!pd.isEmpty()) {
-        m_Parameter2 = pd.get<uint16_t>();
-      } else {
-        m_Parameter2 = 0xffff;
-      } 
-      if(!pd.isEmpty()) {
-        m_Parameter3 = pd.get<uint16_t>();
-      } else {
-        m_Parameter3 = 0xffff;
-      }
+class FrameSenderTester : public FrameSenderInterface {
+public:
+  int getLastFunctionID() const { return m_LastFunctionID; }
+  void setLastFunctionID(const int _value) { m_LastFunctionID = _value; }
+  int getParameter1() const { return m_Parameter1; }
+  int getParameter2() const { return m_Parameter2; }
+  int getParameter3() const { return m_Parameter3; }
+  virtual void sendFrame(DS485CommandFrame& _frame) {
+    PayloadDissector pd(_frame.getPayload());
+    m_LastFunctionID = pd.get<uint8_t>();
+    if(!pd.isEmpty()) {
+      m_Parameter1 = pd.get<uint16_t>();
+    } else {
+      m_Parameter1 = 0xffff;
     }
+    if(!pd.isEmpty()) {
+      m_Parameter2 = pd.get<uint16_t>();
+    } else {
+      m_Parameter2 = 0xffff;
+    }
+    if(!pd.isEmpty()) {
+      m_Parameter3 = pd.get<uint16_t>();
+    } else {
+      m_Parameter3 = 0xffff;
+    }
+  }
+private:
+  int m_LastFunctionID;
+  uint16_t m_Parameter1;
+  uint16_t m_Parameter2;
+  uint16_t m_Parameter3;
+}; // FrameSenderTester
+
+class TestModelFixture {
+public:
+  TestModelFixture() {
+    m_pApartment.reset(new Apartment(NULL));
+    m_pFrameSender.reset(new FrameSenderTester());
+    m_pDispatcher.reset(new DS485BusRequestDispatcher());
+    m_pDispatcher->setFrameSender(m_pFrameSender.get());
+    m_pApartment->setBusRequestDispatcher(m_pDispatcher.get());
+    m_pFrameSender->setLastFunctionID(-1);
+  }
 
-    virtual DeviceBusInterface* getDeviceBusInterface() { return this; }
-    virtual StructureQueryBusInterface* getStructureQueryBusInterface() { return this; }
-
-
-    //------------------------------------------------ Specialized Commands (system)
-    /** Returns an std::vector containing the dsMeter-spec of all dsMeters present. */
-    virtual std::vector<DSMeterSpec_t> getDSMeters() { return std::vector<DSMeterSpec_t>(); }
-
-    /** Returns the dsMeter-spec for a dsMeter */
-    virtual DSMeterSpec_t getDSMeterSpec(const int _dsMeterID) { return DSMeterSpec_t(); }
-
-    /** Returns a std::vector conatining the zone-ids of the specified dsMeter */
-    virtual std::vector<int> getZones(const int _dsMeterID) { return std::vector<int>(); }
-    /** Returns the count of the zones of the specified dsMeter */
-    virtual int getZoneCount(const int _dsMeterID) { return 0; }
-    /** Returns the bus-ids of the devices present in the given zone of the specified dsMeter */
-    virtual std::vector<int> getDevicesInZone(const int _dsMeterID, const int _zoneID) { return std::vector<int>(); }
-    /** Returns the count of devices present in the given zone of the specified dsMeter */
-    virtual int getDevicesCountInZone(const int _dsMeterID, const int _zoneID) { return 0; }
-
-    /** Adds the given device to the specified zone. */
-    virtual void setZoneID(const int _dsMeterID, const devid_t _deviceID, const int _zoneID) {}
-
-    /** Creates a new Zone on the given dsMeter */
-    virtual void createZone(const int _dsMeterID, const int _zoneID) {}
-
-    /** Removes the zone \a _zoneID on the dsMeter \a _dsMeterID */
-    virtual void removeZone(const int _dsMeterID, const int _zoneID) {}
-
-    /** Returns the count of groups present in the given zone of the specifid dsMeter */
-    virtual int getGroupCount(const int _dsMeterID, const int _zoneID) { return 0; }
-    /** Returns the a std::vector containing the group-ids of the given zone on the specified dsMeter */
-    virtual std::vector<int> getGroups(const int _dsMeterID, const int _zoneID) { return std::vector<int>(); }
-    /** Returns the count of devices present in the given group */
-    virtual int getDevicesInGroupCount(const int _dsMeterID, const int _zoneID, const int _groupID) { return 0; }
-    /** Returns a std::vector containing the bus-ids of the devices present in the given group */
-    virtual std::vector<int> getDevicesInGroup(const int _dsMeterID, const int _zoneID, const int _groupID) { return std::vector<int>(); }
-
-    virtual std::vector<int> getGroupsOfDevice(const int _dsMeterID, const int _deviceID) { return std::vector<int>(); }
-
-    /** Adds a device to a given group */
-    virtual void addToGroup(const int _dsMeterID, const int _groupID, const int _deviceID) {}
-    /** Removes a device from a given group */
-    virtual void removeFromGroup(const int _dsMeterID, const int _groupID, const int _deviceID) {}
-
-    /** Adds a user group */
-    virtual int addUserGroup(const int _dsMeterID) { return 0; }
-    /** Removes a user group */
-    virtual void removeUserGroup(const int _dsMeterID, const int _groupID) {}
-
-    /** Returns the DSID of a given device */
-    virtual dsid_t getDSIDOfDevice(const int _dsMeterID, const int _deviceID) { return NullDSID; }
-    /** Returns the DSID of a given dsMeter */
-    virtual dsid_t getDSIDOfDSMeter(const int _dsMeterID) { return NullDSID; }
-
-    virtual int getLastCalledScene(const int _dsMeterID, const int _zoneID, const int _groupID) { return 0;}
-
-    //------------------------------------------------ Metering
-
-    /** Returns the current power-consumption in mW */
-    virtual unsigned long getPowerConsumption(const int _dsMeterID) { return 0; }
-
-    /** Returns the meter value in Wh */
-    virtual unsigned long getEnergyMeterValue(const int _dsMeterID) { return 0; }
-
-    virtual bool getEnergyBorder(const int _dsMeterID, int& _lower, int& _upper) { _lower = 0; _upper = 0; return false; }
-
-    //------------------------------------------------ UDI
-    virtual uint8_t dSLinkSend(const int _dsMeterID, devid_t _devAdr, uint8_t _value, uint8_t _flags) { return 0; }
-
-    //------------------------------------------------ Device    
-    virtual uint16_t deviceGetParameterValue(devid_t _id, uint8_t _dsMeterID, int _paramID) { return 0; }
-    virtual uint16_t deviceGetFunctionID(devid_t _id, uint8_t _dsMeterID) { return 0; }
-
-    //------------------------------------------------ Device manipulation
-    virtual void setValueDevice(const Device& _device, const uint16_t _value, const uint16_t _parameterID, const int _size) {}
-    virtual int getSensorValue(const Device& _device, const int _sensorID) { return 0; }
-  private:
-    int m_LastFunctionID;
-    uint16_t m_Parameter1;
-    uint16_t m_Parameter2;
-    uint16_t m_Parameter3;
-  };
-
-
-BOOST_AUTO_TEST_CASE(testTurnOnDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
+  boost::scoped_ptr<Apartment> m_pApartment;
+  boost::scoped_ptr<FrameSenderTester> m_pFrameSender;
+  boost::scoped_ptr<DS485BusRequestDispatcher> m_pDispatcher;
+};
 
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testTurnOnDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.turnOn();
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(SceneMax, proxy.getParameter2());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(SceneMax, m_pFrameSender->getParameter2());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.turnOn();
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(SceneMax, proxy.getParameter2());
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(SceneMax, m_pFrameSender->getParameter2());
 }
 
-BOOST_AUTO_TEST_CASE(testTurnOnGroup) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Group& group = apt.getGroup(1);
+BOOST_FIXTURE_TEST_CASE(testTurnOnGroup, TestModelFixture) {
+  Group& group = m_pApartment->getGroup(1);
   group.turnOn();
-  BOOST_CHECK_EQUAL(FunctionGroupCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter1()); // zone 0
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter2()); // group 1
-  BOOST_CHECK_EQUAL(SceneMax, proxy.getParameter3());
-  proxy.setLastFunctionID(-1);
+  BOOST_CHECK_EQUAL(FunctionGroupCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter1()); // zone 0
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter2()); // group 1
+  BOOST_CHECK_EQUAL(SceneMax, m_pFrameSender->getParameter3());
 }
 
-BOOST_AUTO_TEST_CASE(testTurnOffDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testTurnOffDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.turnOff();
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(SceneMin, proxy.getParameter2());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(SceneMin, m_pFrameSender->getParameter2());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.turnOff();
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(SceneMin, proxy.getParameter2());
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(SceneMin, m_pFrameSender->getParameter2());
 }
 
-BOOST_AUTO_TEST_CASE(testTurnOffGroup) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Group& group = apt.getGroup(1);
+BOOST_FIXTURE_TEST_CASE(testTurnOffGroup, TestModelFixture) {
+  Group& group = m_pApartment->getGroup(1);
   group.turnOff();
-  BOOST_CHECK_EQUAL(FunctionGroupCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter1()); // zone 0
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter2()); // group 1
-  BOOST_CHECK_EQUAL(SceneMin, proxy.getParameter3());
+  BOOST_CHECK_EQUAL(FunctionGroupCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter1()); // zone 0
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter2()); // group 1
+  BOOST_CHECK_EQUAL(SceneMin, m_pFrameSender->getParameter3());
 }
 
-BOOST_AUTO_TEST_CASE(testEnableDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testEnableDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.enable();
-  BOOST_CHECK_EQUAL(FunctionDeviceEnable, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceEnable, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.enable();
-  BOOST_CHECK_EQUAL(FunctionDeviceEnable, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceEnable, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
-BOOST_AUTO_TEST_CASE(testDisableDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testDisableDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.disable();
-  BOOST_CHECK_EQUAL(FunctionDeviceDisable, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceDisable, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.disable();
-  BOOST_CHECK_EQUAL(FunctionDeviceDisable, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceDisable, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
-BOOST_AUTO_TEST_CASE(testIncreaseValueDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testIncreaseValueDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.increaseValue();
-  BOOST_CHECK_EQUAL(FunctionDeviceIncreaseValue, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceIncreaseValue, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.increaseValue();
-  BOOST_CHECK_EQUAL(FunctionDeviceIncreaseValue, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceIncreaseValue, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
-BOOST_AUTO_TEST_CASE(testDecreaseValueDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testDecreaseValueDevice, TestModelFixture) {
+  m_pFrameSender->setLastFunctionID(-1);
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.decreaseValue();
-  BOOST_CHECK_EQUAL(FunctionDeviceDecreaseValue, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceDecreaseValue, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.decreaseValue();
-  BOOST_CHECK_EQUAL(FunctionDeviceDecreaseValue, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceDecreaseValue, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
-BOOST_AUTO_TEST_CASE(testDecreaseValueZone) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  Zone& zone = apt.allocateZone(1);
-
-  proxy.setLastFunctionID(-1);
+BOOST_FIXTURE_TEST_CASE(testDecreaseValueZone, TestModelFixture) {
+  Zone& zone = m_pApartment->allocateZone(1);
   zone.decreaseValue();
-  BOOST_CHECK_EQUAL(FunctionGroupDecreaseValue, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1()); // zone id
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter2()); // group id (broadcast)
+  BOOST_CHECK_EQUAL(FunctionGroupDecreaseValue, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1()); // zone id
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter2()); // group id (broadcast)
 }
 
-BOOST_AUTO_TEST_CASE(testIncreaseValueZone) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  Zone& zone = apt.allocateZone(1);
-
-  proxy.setLastFunctionID(-1);
+BOOST_FIXTURE_TEST_CASE(testIncreaseValueZone, TestModelFixture) {
+  Zone& zone = m_pApartment->allocateZone(1);
   zone.increaseValue();
-  BOOST_CHECK_EQUAL(FunctionGroupIncreaseValue, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1()); // zone id
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter2()); // group id (broadcast)
+  BOOST_CHECK_EQUAL(FunctionGroupIncreaseValue, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1()); // zone id
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter2()); // group id (broadcast)
 }
 
-BOOST_AUTO_TEST_CASE(testStartDimUp) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testStartDimUp, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.startDim(true);
-  BOOST_CHECK_EQUAL(FunctionDeviceStartDimInc, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceStartDimInc, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.startDim(true);
-  BOOST_CHECK_EQUAL(FunctionDeviceStartDimInc, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceStartDimInc, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
-BOOST_AUTO_TEST_CASE(testStartDimDown) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testStartDimDown, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.startDim(false);
-  BOOST_CHECK_EQUAL(FunctionDeviceStartDimDec, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceStartDimDec, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.startDim(false);
-  BOOST_CHECK_EQUAL(FunctionDeviceStartDimDec, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceStartDimDec, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
-BOOST_AUTO_TEST_CASE(testEndDim) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testEndDim, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.endDim();
-  BOOST_CHECK_EQUAL(FunctionDeviceEndDim, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceEndDim, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.endDim();
-  BOOST_CHECK_EQUAL(FunctionDeviceEndDim, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceEndDim, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
-BOOST_AUTO_TEST_CASE(testCallSceneDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testCallSceneDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.callScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.callScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
 }
 
-BOOST_AUTO_TEST_CASE(testSaveSceneDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testSaveSceneDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.saveScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceSaveScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceSaveScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.saveScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceSaveScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
+  BOOST_CHECK_EQUAL(FunctionDeviceSaveScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
 }
 
-BOOST_AUTO_TEST_CASE(testUndoSceneDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testUndoSceneDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.undoScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceUndoScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceUndoScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.undoScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceUndoScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
+  BOOST_CHECK_EQUAL(FunctionDeviceUndoScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
 }
 
-BOOST_AUTO_TEST_CASE(testCallSceneGroup) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Group& group = apt.getGroup(1);
+BOOST_FIXTURE_TEST_CASE(testCallSceneGroup, TestModelFixture) {
+  Group& group = m_pApartment->getGroup(1);
   group.callScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionGroupCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter1()); // zone 0
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter2()); // group 1
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter3());
+  BOOST_CHECK_EQUAL(FunctionGroupCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter1()); // zone 0
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter2()); // group 1
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter3());
 }
 
-BOOST_AUTO_TEST_CASE(testSaveSceneGroup) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Group& group = apt.getGroup(1);
+BOOST_FIXTURE_TEST_CASE(testSaveSceneGroup, TestModelFixture) {
+  Group& group = m_pApartment->getGroup(1);
   group.saveScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionGroupSaveScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter1()); // zone 0
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter2()); // group 1
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter3());
+  BOOST_CHECK_EQUAL(FunctionGroupSaveScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter1()); // zone 0
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter2()); // group 1
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter3());
 }
 
-BOOST_AUTO_TEST_CASE(testUndoSceneGroup) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Group& group = apt.getGroup(1);
+BOOST_FIXTURE_TEST_CASE(testUndoSceneGroup, TestModelFixture) {
+  Group& group = m_pApartment->getGroup(1);
   group.undoScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionGroupUndoScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter1()); // zone 0
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter2()); // group 1
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter3());
+  BOOST_CHECK_EQUAL(FunctionGroupUndoScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter1()); // zone 0
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter2()); // group 1
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter3());
 }
 
-BOOST_AUTO_TEST_CASE(testCallSceneZone) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Zone& zone = apt.allocateZone(1);
+BOOST_FIXTURE_TEST_CASE(testCallSceneZone, TestModelFixture) {
+  Zone& zone = m_pApartment->allocateZone(1);
   zone.callScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionGroupCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1()); // zone 1
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter2()); // group 0
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter3());
+  BOOST_CHECK_EQUAL(FunctionGroupCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1()); // zone 1
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter2()); // group 0
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter3());
 }
 
-BOOST_AUTO_TEST_CASE(testSaveSceneZone) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Zone& zone = apt.allocateZone(1);
+BOOST_FIXTURE_TEST_CASE(testSaveSceneZone, TestModelFixture) {
+  Zone& zone = m_pApartment->allocateZone(1);
   zone.saveScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionGroupSaveScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1()); // zone 1
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter2()); // group 0
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter3());
+  BOOST_CHECK_EQUAL(FunctionGroupSaveScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1()); // zone 1
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter2()); // group 0
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter3());
 }
 
-BOOST_AUTO_TEST_CASE(testUndoSceneZone) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Zone& zone = apt.allocateZone(1);
+BOOST_FIXTURE_TEST_CASE(testUndoSceneZone, TestModelFixture) {
+  Zone& zone = m_pApartment->allocateZone(1);
   zone.undoScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionGroupUndoScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1()); // zone 1
-  BOOST_CHECK_EQUAL(0x0, proxy.getParameter2()); // group 0
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter3());
+  BOOST_CHECK_EQUAL(FunctionGroupUndoScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1()); // zone 1
+  BOOST_CHECK_EQUAL(0x0, m_pFrameSender->getParameter2()); // group 0
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter3());
 }
 
-BOOST_AUTO_TEST_CASE(callUndoSceneSet) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-  proxy.setLastFunctionID(-1);
-
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(callUndoSceneSet, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
-  Device& dev2 = apt.allocateDevice(dsid_t(0,2));
+  Device& dev2 = m_pApartment->allocateDevice(dsid_t(0,2));
   dev2.setShortAddress(2);
   Set set;
   set.addDevice(dev1);
   set.callScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
-  proxy.setLastFunctionID(-1);
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
+  m_pFrameSender->setLastFunctionID(-1);
 }
 
-BOOST_AUTO_TEST_CASE(testSaveSceneSet) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-  proxy.setLastFunctionID(-1);
-
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testSaveSceneSet, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
-  Device& dev2 = apt.allocateDevice(dsid_t(0,2));
+  Device& dev2 = m_pApartment->allocateDevice(dsid_t(0,2));
   dev2.setShortAddress(2);
   Set set;
   set.addDevice(dev1);
   set.saveScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceSaveScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
-  proxy.setLastFunctionID(-1);
+  BOOST_CHECK_EQUAL(FunctionDeviceSaveScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
+  m_pFrameSender->setLastFunctionID(-1);
 }
 
-BOOST_AUTO_TEST_CASE(testUndoSceneSet) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-  proxy.setLastFunctionID(-1);
-
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testUndoSceneSet, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
-  Device& dev2 = apt.allocateDevice(dsid_t(0,2));
+  Device& dev2 = m_pApartment->allocateDevice(dsid_t(0,2));
   dev2.setShortAddress(2);
   Set set;
   set.addDevice(dev1);
   set.undoScene(Scene1);
-  BOOST_CHECK_EQUAL(FunctionDeviceUndoScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
-  proxy.setLastFunctionID(-1);
+  BOOST_CHECK_EQUAL(FunctionDeviceUndoScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, m_pFrameSender->getParameter2());
+  m_pFrameSender->setLastFunctionID(-1);
 }
 
-BOOST_AUTO_TEST_CASE(testNextSceneDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testNextSceneDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.nextScene();
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.nextScene();
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
-BOOST_AUTO_TEST_CASE(testPreviousSceneDevice) {
-  Apartment apt(NULL, NULL);
-  apt.initialize();
-
-  DSDSMeterSim modSim(NULL);
-  DS485InterfaceTest proxy;
-  DS485BusRequestDispatcher dispatcher;
-  dispatcher.setProxy(&proxy);
-  apt.setDS485Interface(&proxy);
-  apt.setBusRequestDispatcher(&dispatcher);
-
-  proxy.setLastFunctionID(-1);
-  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+BOOST_FIXTURE_TEST_CASE(testPreviousSceneDevice, TestModelFixture) {
+  Device& dev1 = m_pApartment->allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
   dev1.previousScene();
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
-  proxy.setLastFunctionID(-1);
-  DeviceReference devRef1(dev1, &apt);
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
+  m_pFrameSender->setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, m_pApartment.get());
   devRef1.previousScene();
-  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
-  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, m_pFrameSender->getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, m_pFrameSender->getParameter1());
 }
 
 BOOST_AUTO_TEST_SUITE_END()


hooks/post-receive
-- 
digitalSTROM Server


More information about the dss-commits mailing list