[dss-commits] digitalSTROM Server branch, master, updated. 3af125e4b69fba9346d85be13f15d0daf29ff287

git version control dss-commits at forum.digitalstrom.org
Mon Jan 4 02:38:52 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  3af125e4b69fba9346d85be13f15d0daf29ff287 (commit)
       via  596b1cba95e3e947b3d0a7a4a212dbb229561ff7 (commit)
       via  9981077d3b3fe39eb6d9f5e678420c2dbf1dd26e (commit)
       via  8c7044ae325aedf1892d207e0278f82c97069315 (commit)
       via  71fad5cbba3e1b772beede92317305a3f0cb4e0b (commit)
       via  74c25b3374a035cc2f2291b6bdf31dfc08d43acf (commit)
       via  aec33bafed919a961deb329856a14b65887c4696 (commit)
       via  73ab1b6887ab4be48aa7010a6b93d20c6ad840de (commit)
       via  aa06c1e2af5ea782aaf4a90e9a6531cedf365663 (commit)
       via  f4bc6616ba5fc6133e58c11d9391b716952c2cf7 (commit)
       via  427fa6108cefcd76896534981af70b10e4ce42a3 (commit)
       via  a300cf6a15c9e1a9e5542f92e3342e14bca300ed (commit)
       via  2df5527faba08c3cd5afe221a8c28d346c801a3b (commit)
       via  26b7a559365023a5281ae9e389455ddab2d80302 (commit)
       via  c51056feffab7b93ab7895edcf9fd2ed92be3ecb (commit)
       via  3bd05b2323855577ca06daa00334cf447f71e4f7 (commit)
       via  022eacd4240d059675a0289165c7c26724e18416 (commit)
       via  e63f129ae2dbc7cd03c00c97ed66eecaf58fa8b3 (commit)
       via  5ce9a6fc29aebab66ed724829275e8ae1538c952 (commit)
       via  a167f925d7c8383a4bb3a9d6a75ab34404f8ae5b (commit)
       via  b9a0cb6addde4b2284f4799057e33b21f0dcddf2 (commit)
       via  83ff84727fb2011c7e86dd84de4f53d761d652d5 (commit)
       via  db42b09760f226469244e7e5c7f1771b515fccec (commit)
       via  4a65dc262018eab39143ade8b67510917a87a537 (commit)
       via  d5c0c8591e79d94cf9a1e1058e95fdf20f679e3c (commit)
       via  d9c251b8f26c0c5c1311e55e44920eee6b74bede (commit)
       via  69acc037120fbac68756870369ab4ce366e56ce0 (commit)
       via  21973f8908632bd4f0dabad0a160a69f30f71a55 (commit)
       via  a96147b0a1491f41fc6a8bdea9fe1abb7761b2eb (commit)
       via  714a7fbd1aa1d2a31fb2a0f0f43c60b9159e7a21 (commit)
       via  ceec51de15527a6eecc32a71e916b622bc3cc617 (commit)
       via  8f84d7a66b8a861fcad168485621cd9f5668d8de (commit)
       via  0b1ee5b3116d9b542e36ace3c83a6a7f2093d83b (commit)
      from  e66d9ae3b6cb709f6cc7aa3b49213bfa4adbad03 (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 3af125e4b69fba9346d85be13f15d0daf29ff287
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Mon Jan 4 02:33:46 2010 +0100

    Moved webrequests to core/web/webrequests.h

commit 596b1cba95e3e947b3d0a7a4a212dbb229561ff7
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Mon Jan 4 01:54:48 2010 +0100

    Added handlers instead of members for web-requests

commit 9981077d3b3fe39eb6d9f5e678420c2dbf1dd26e
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sun Jan 3 15:18:20 2010 +0100

    Moved webserver.* to core/web/

commit 8c7044ae325aedf1892d207e0278f82c97069315
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sun Jan 3 01:27:45 2010 +0100

    Split model.h into core/model/*

commit 71fad5cbba3e1b772beede92317305a3f0cb4e0b
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 22:33:40 2010 +0100

    Split up DS485Interface

commit 74c25b3374a035cc2f2291b6bdf31dfc08d43acf
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 19:28:19 2010 +0100

    Externalized scanModulator to BusScanner

commit aec33bafed919a961deb329856a14b65887c4696
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 18:21:23 2010 +0100

    Moved unix/ds485* to core/ds485/*

commit 73ab1b6887ab4be48aa7010a6b93d20c6ad840de
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 18:10:49 2010 +0100

    Make the dSS work again in non-test conditions

commit aa06c1e2af5ea782aaf4a90e9a6531cedf365663
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 17:50:51 2010 +0100

    Set value has no parameter

commit f4bc6616ba5fc6133e58c11d9391b716952c2cf7
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 17:06:55 2010 +0100

    Use BusRequests for dimming

commit 427fa6108cefcd76896534981af70b10e4ce42a3
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 16:40:14 2010 +0100

    Dimming is only possible on the main-value

commit a300cf6a15c9e1a9e5542f92e3342e14bca300ed
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 16:24:04 2010 +0100

    Remove commands made obsolete by BusRequests

commit 2df5527faba08c3cd5afe221a8c28d346c801a3b
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 16:12:55 2010 +0100

    Implemented Set::splitIntoAddressableItems()
    
    Aka. "Set-Optimizer"

commit 26b7a559365023a5281ae9e389455ddab2d80302
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 14:28:32 2010 +0100

    Make the zone a NonAddressableModelItem

commit c51056feffab7b93ab7895edcf9fd2ed92be3ecb
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 13:45:32 2010 +0100

    Use bus-request for increase/decrease

commit 3bd05b2323855577ca06daa00334cf447f71e4f7
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 13:31:52 2010 +0100

    Actually return something for device disable/enable

commit 022eacd4240d059675a0289165c7c26724e18416
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 13:25:35 2010 +0100

    Adjusted documentation of increase value

commit e63f129ae2dbc7cd03c00c97ed66eecaf58fa8b3
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 13:20:25 2010 +0100

    Get on/off is never used => removed

commit 5ce9a6fc29aebab66ed724829275e8ae1538c952
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Jan 2 13:09:38 2010 +0100

    Increase value always acts on the main value

commit a167f925d7c8383a4bb3a9d6a75ab34404f8ae5b
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Jan 1 23:32:11 2010 +0100

    Use the broadcast group of the zone to control it

commit b9a0cb6addde4b2284f4799057e33b21f0dcddf2
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Jan 1 22:47:29 2010 +0100

    TurnOn/Off mapped to callScene(Min/Max)

commit 83ff84727fb2011c7e86dd84de4f53d761d652d5
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Jan 1 22:37:23 2010 +0100

    Use busrequest to enable/disable device

commit db42b09760f226469244e7e5c7f1771b515fccec
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Jan 1 22:36:55 2010 +0100

    Only devices can be enabled/disabled

commit 4a65dc262018eab39143ade8b67510917a87a537
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Jan 1 21:26:17 2010 +0100

    Use AddressableModelItem as parent for group/device

commit d5c0c8591e79d94cf9a1e1058e95fdf20f679e3c
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Thu Dec 31 20:32:32 2009 +0100

    Use busrequests for device.*Scene

commit d9c251b8f26c0c5c1311e55e44920eee6b74bede
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Mon Dec 21 17:57:07 2009 +0100

    Clarified coment on MPL

commit 69acc037120fbac68756870369ab4ce366e56ce0
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Mon Dec 21 15:10:04 2009 +0100

    Improved test coverage of model.*

commit 21973f8908632bd4f0dabad0a160a69f30f71a55
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Dec 19 22:37:18 2009 +0100

    Improved test coverage for base and properties

commit a96147b0a1491f41fc6a8bdea9fe1abb7761b2eb
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Dec 19 22:36:28 2009 +0100

    Removed unused functions

commit 714a7fbd1aa1d2a31fb2a0f0f43c60b9159e7a21
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Dec 19 22:35:32 2009 +0100

    Ignore files ending with ~

commit ceec51de15527a6eecc32a71e916b622bc3cc617
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Sat Dec 19 22:34:16 2009 +0100

    Use Poco::XML for xml parsing
    
    Removed xmlwrapper, which is now obsolete.

commit 8f84d7a66b8a861fcad168485621cd9f5668d8de
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Thu Dec 17 22:14:47 2009 +0100

    Compile on gcc 4.4.1/xulrunner

commit 0b1ee5b3116d9b542e36ace3c83a6a7f2093d83b
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Thu Dec 17 22:13:39 2009 +0100

    Use xulrunners mozjs if nothing else is available

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

Changes:
diff --git a/.gitignore b/.gitignore
index 1c0415d..5cfac8a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ doc/json_api.xml
 data/webroot/js/lib/
 Debug/
 data/webroot/js/dss-setup-interface.js
+*~
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6f24bcd..a156111 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,6 +31,8 @@ ADD_CUSTOM_TARGET(build_info.h ALL
 )
 ADD_DEFINITIONS(-DHAVE_BUILD_INFO_H)
 
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
 SET(REQUIRED_LIBS)
 
 INCLUDE (${CMAKE_ROOT}/Modules/FindLibXml2.cmake)
@@ -103,6 +105,16 @@ CHECK_INCLUDE_FILES(js/jsapi.h HAVE_JS_JSAPI_H)
 FIND_LIBRARY(MOZJS mozjs)
 IF(${MOZJS} MATCHES "MOZJS-NOTFOUND")
   FIND_LIBRARY(MOZJS js)
+  IF(${MOZJS} MATCHES "MOZJS-NOTFOUND")
+    # try finding xulrunner
+    INCLUDE(FindPkgConfig)
+    pkg_search_module(MOZJS REQUIRED libxul-unstable)
+    SET(MOZJS ${MOZJS_LIBRARIES})
+    INCLUDE_DIRECTORIES(${MOZJS_INCLUDE_DIRS})
+    SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${MOZJS_INCLUDE_DIRS})
+    CHECK_INCLUDE_FILES(jsapi.h HAVE_JSAPI_H)
+    LINK_DIRECTORIES(${MOZJS_LIBRARY_DIRS})
+  ENDIF(${MOZJS} MATCHES "MOZJS-NOTFOUND")
 ENDIF(${MOZJS} MATCHES "MOZJS-NOTFOUND")
 
 # check for gsoap headers and library
@@ -140,7 +152,6 @@ ENDIF(${POCOXML} MATCHES "POCOXML-NOTFOUND")
 CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
                ${CMAKE_CURRENT_BINARY_DIR}/config.h)
 ADD_DEFINITIONS(-DHAVE_CONFIG_H)
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 
 ADD_SUBDIRECTORY(core)
 ADD_SUBDIRECTORY(unix)
@@ -183,7 +194,7 @@ INSTALL(FILES
        )
 
 
-TARGET_LINK_LIBRARIES(dss ${TEST_LIB} ${BOOST_TEST_LIB} core unix webservices pthread
+TARGET_LINK_LIBRARIES(dss ${TEST_LIB} ${BOOST_TEST_LIB} core ds485 model unix webservices pthread
 	mongoose ${REQUIRED_LIBS})
 
 
diff --git a/config.h.in b/config.h.in
index 57e64dc..59b920f 100644
--- a/config.h.in
+++ b/config.h.in
@@ -7,6 +7,7 @@
 #cmakedefine HAVE_STDINT
 #cmakedefine HAVE_MOZJS_JSAPI_H
 #cmakedefine HAVE_JS_JSAPI_H
+#cmakedefine HAVE_JSAPI_H
 #cmakedefine HAVE_LIBICAL_ICAL_H
 #cmakedefine HAVE_ICAL_H
 #cmakedefine HAVE_DNS_SD
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 28ad672..0454d5a 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -6,8 +6,11 @@ ENDIF(WITH_GCOV)
 file(GLOB files *.cpp)
 
 add_library(core ${files} scripting/modeljs.cpp sim/dssim.cpp sim/dsidsim.cpp
-sim/dsid_js.cpp sim/dsid_plugin.cpp
+sim/dsid_js.cpp sim/dsid_plugin.cpp web/webserverapi.cpp web/webrequests.cpp 
 metering/metering.cpp metering/series.cpp metering/seriespersistence.cpp
 metering/fake_meter.cpp vfs/vfs.cpp web/restful.cpp web/restfulapiwriter.cpp
-web/webserverplugin.cpp)
+web/webserverplugin.cpp web/webserver.cpp)
 
+
+add_subdirectory(ds485)
+add_subdirectory(model)
\ No newline at end of file
diff --git a/core/DS485Interface.h b/core/DS485Interface.h
index ddefdaa..67db413 100644
--- a/core/DS485Interface.h
+++ b/core/DS485Interface.h
@@ -23,8 +23,7 @@
 #define DS485INTERFACE_H_
 
 #include "ds485types.h"
-#include "unix/ds485.h"
-#include "model.h"
+#include "core/ds485/ds485.h"
 #include "base.h"
 
 #include <string>
@@ -33,41 +32,24 @@
 
 namespace dss {
 
-	/** Commands to be transmitted either to a set, group or a single device. */
-	typedef enum {
-	  cmdTurnOn,
-	  cmdTurnOff,
-	  cmdStartDimUp,
-	  cmdStartDimDown,
-	  cmdStopDim,
-	  cmdCallScene,
-	  cmdSaveScene,
-	  cmdUndoScene,
-	  cmdIncreaseValue,
-	  cmdDecreaseValue,
-	  cmdEnable,
-	  cmdDisable,
-	  cmdIncreaseParam,
-	  cmdDecreaseParam,
-	  cmdGetOnOff,
-	  cmdGetValue,
-	  cmdSetValue,
-	  cmdGetFunctionID
-	} DS485Command;
-
+  class Device;
+  
 	typedef boost::tuple<int, int, int, std::string, int> ModulatorSpec_t; // bus-id, sw-version, hw-version, name, device-id
 
-  /** Interface to be implemented by any implementation of the DS485 interface */
-  class DS485Interface {
+  class DeviceBusInterface {
   public:
-    virtual ~DS485Interface() {};
+    //------------------------------------------------ UDI
+    virtual uint8_t dSLinkSend(const int _modulatorID, devid_t _devAdr, uint8_t _value, uint8_t _flags) = 0;
 
-    /** Returns true when the interface is ready to transmit user generated DS485Packets */
-    virtual bool isReady() = 0;
+    //------------------------------------------------ Device manipulation
+    virtual uint16_t deviceGetParameterValue(devid_t _id, uint8_t _modulatorID, int _paramID) = 0;
 
-    virtual void sendFrame(DS485CommandFrame& _frame) = 0;
+    virtual void setValueDevice(const Device& _device, const uint16_t _value, const uint16_t _parameterID, const int _size) = 0;
+    virtual int getSensorValue(const Device& _device, const int _sensorID) = 0;
+  }; // DeviceBusInterface
 
-    //------------------------------------------------ Specialized Commands (system)
+  class StructureQueryBusInterface {
+  public:
     /** Returns an std::vector containing the modulator-spec of all modulators present. */
     virtual std::vector<ModulatorSpec_t> getModulators() = 0;
 
@@ -83,15 +65,6 @@ namespace dss {
     /** Returns the count of devices present in the given zone of the specified modulator */
     virtual int getDevicesCountInZone(const int _modulatorID, const int _zoneID) = 0;
 
-    /** Adds the given device to the specified zone. */
-    virtual void setZoneID(const int _modulatorID, const devid_t _deviceID, const int _zoneID) = 0;
-
-    /** Creates a new Zone on the given modulator */
-    virtual void createZone(const int _modulatorID, const int _zoneID) = 0;
-
-    /** Removes the zone \a _zoneID on the modulator \a _modulatorID */
-    virtual void removeZone(const int _modulatorID, const int _zoneID) = 0;
-
     /** Returns the count of groups present in the given zone of the specifid modulator */
     virtual int getGroupCount(const int _modulatorID, const int _zoneID) = 0;
     /** Returns the a std::vector containing the group-ids of the given zone on the specified modulator */
@@ -103,6 +76,41 @@ namespace dss {
 
     virtual std::vector<int> getGroupsOfDevice(const int _modulatorID, const int _deviceID) = 0;
 
+    /** Returns the DSID of a given device */
+    virtual dsid_t getDSIDOfDevice(const int _modulatorID, const int _deviceID) = 0;
+    /** Returns the DSID of a given modulator */
+    virtual dsid_t getDSIDOfModulator(const int _modulatorID) = 0;
+
+    virtual int getLastCalledScene(const int _modulatorID, const int _zoneID, const int _groupID) = 0;
+
+    virtual uint16_t deviceGetFunctionID(devid_t _id, uint8_t _modulatorID) = 0;
+    virtual bool getEnergyBorder(const int _modulatorID, int& _lower, int& _upper) = 0;
+  }; // StructureQueryBusInterface
+  
+  /** Interface to be implemented by any implementation of the DS485 interface */
+  class DS485Interface {
+  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 _modulatorID, const devid_t _deviceID, const int _zoneID) = 0;
+
+    /** Creates a new Zone on the given modulator */
+    virtual void createZone(const int _modulatorID, const int _zoneID) = 0;
+
+    /** Removes the zone \a _zoneID on the modulator \a _modulatorID */
+    virtual void removeZone(const int _modulatorID, const int _zoneID) = 0;
+
     /** Adds a device to a given group */
     virtual void addToGroup(const int _modulatorID, const int _groupID, const int _deviceID) = 0;
     /** Removes a device from a given group */
@@ -113,37 +121,13 @@ namespace dss {
     /** Removes a user group */
     virtual void removeUserGroup(const int _modulatorID, const int _groupID) = 0;
 
-    /** Returns the DSID of a given device */
-    virtual dsid_t getDSIDOfDevice(const int _modulatorID, const int _deviceID) = 0;
-    /** Returns the DSID of a given modulator */
-    virtual dsid_t getDSIDOfModulator(const int _modulatorID) = 0;
-
-    virtual int getLastCalledScene(const int _modulatorID, const int _zoneID, const int _groupID) = 0;
 
     //------------------------------------------------ Metering
-
     /** Returns the current power-consumption in mW */
     virtual unsigned long getPowerConsumption(const int _modulatorID) = 0;
 
     /** Returns the meter value in Wh */
     virtual unsigned long getEnergyMeterValue(const int _modulatorID) = 0;
-
-    virtual bool getEnergyBorder(const int _modulatorID, int& _lower, int& _upper) = 0;
-
-    //------------------------------------------------ UDI
-    //virtual void dSLinkConfigWrite(devid_t _devAdr, uint8_t _index, uint8_t _value) = 0;
-    //virtual bool dSLinkConfigRead(devid_t _devAdr, uint8_t _index, uint8_t& value) = 0;
-    virtual uint8_t dSLinkSend(const int _modulatorID, devid_t _devAdr, uint8_t _value, uint8_t _flags) = 0;
-
-    //------------------------------------------------ Device manipulation
-    virtual std::vector<int> sendCommand(DS485Command _cmd, const Set& _set, int _param = -1) = 0;
-    virtual std::vector<int> sendCommand(DS485Command _cmd, const Device& _device, int _param = -1) = 0;
-    virtual std::vector<int> sendCommand(DS485Command _cmd, devid_t _id, uint8_t _modulatorID, int _param = -1) = 0;
-    virtual std::vector<int> sendCommand(DS485Command _cmd, const Zone& _zone, Group& _group, int _param = -1) = 0;
-    virtual std::vector<int> sendCommand(DS485Command _cmd, const Zone& _zone, uint8_t _groupID, int _param = -1) = 0;
-    
-    virtual void setValueDevice(const Device& _device, const uint16_t _value, const uint16_t _parameterID, const int _size) = 0;
-    virtual int getSensorValue(const Device& _device, const int _sensorID) = 0;
   };
 
   class DS485ApiError : public DSSException {
diff --git a/core/base.cpp b/core/base.cpp
index c45f140..4f926e4 100644
--- a/core/base.cpp
+++ b/core/base.cpp
@@ -228,71 +228,6 @@ namespace dss {
     return sstream.str();
   } // join
 
-
-#define                 P_CCITT  0x8408
-//#define                 P_CCITT     0x1021
-  static int              crc_tabccitt_init       = false;
-  static unsigned short   crc_tabccitt[256];
-  static void             init_crcccitt_tab( void );
-
-  unsigned short update_crc_ccitt( unsigned short crc, char c ) {
-
-    unsigned short tmp, short_c;
-
-    short_c  = 0x00ff & (unsigned short) c;
-
-    if ( ! crc_tabccitt_init ) init_crcccitt_tab();
-
-    tmp = (crc >> 8) ^ short_c;
-    crc = (crc << 8) ^ crc_tabccitt[tmp];
-
-    return crc;
-
-  }  /* update_crc_ccitt */
-
-  static void init_crcccitt_tab( void ) {
-
-    int i, j;
-    unsigned short crc, c;
-
-    for (i=0; i<256; i++) {
-
-      crc = 0;
-      c   = ((unsigned short) i) << 8;
-
-      for (j=0; j<8; j++) {
-
-        if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ P_CCITT;
-        else                      crc =   crc << 1;
-
-        c = c << 1;
-      }
-
-      crc_tabccitt[i] = crc;
-    }
-
-    crc_tabccitt_init = true;
-
-  }  /* init_crcccitt_tab */
-  /*
-  uint16_t CRC16(uint16_t _crc, unsigned const char _data) {
-    const uint16_t CRC_CCIT_16 = 0x1021;
-    uint16_t crcResult = _crc;
-
-    uint16_t tmp = (uint16_t)_data << 8;
-    for(int iBit = 0; iBit < 8; iBit++) {
-      if(tmp & 0x8000 == 0) {
-        crcResult <<= 1;
-      } else {
-        crcResult = (crcResult << 1)^CRC_CCIT_16;
-      }
-      tmp <<= 1;
-
-    }
-    return crcResult;
-  }
-  */
-
   uint16_t update_crc(uint16_t _crc, const unsigned char& c) {
 	int i;
     uint16_t result = _crc ^ c;
diff --git a/core/base.h b/core/base.h
index 737ddf6..f833c86 100644
--- a/core/base.h
+++ b/core/base.h
@@ -119,50 +119,6 @@ namespace dss {
     const HashMapConstStringString& getContainer() const { return m_Container; }
   };
 
-  template <typename resCls>
-  class ResourceHolder {
-  protected:
-    resCls* m_Resource;
-
-    resCls* release() {
-      resCls* result = m_Resource;
-      m_Resource = NULL;
-      return result;
-    }
-  public:
-    explicit ResourceHolder(resCls* _resource = NULL) : m_Resource(_resource) {}
-
-    ResourceHolder(ResourceHolder<resCls>& _other)
-    : m_Resource(_other.release())
-    {
-    }
-
-    ResourceHolder<resCls>& operator=(ResourceHolder<resCls>& _rhs) {
-      m_Resource = _rhs.release();
-      return *this;
-    }
-
-  }; // ResourceHolder
-
-  class Finalizable {
-  public:
-    virtual void finalize() = 0;
-    virtual ~Finalizable() {}
-  }; // Finalizable
-
-  class Finalizer {
-  private:
-    Finalizable& m_Finalizable;
-  public:
-    Finalizer(Finalizable& _finalizable)
-    : m_Finalizable(_finalizable)
-    {}
-
-    virtual ~Finalizer() {
-      m_Finalizable.finalize();
-    }
-  };
-
   template<class t>
   void scrubVector(std::vector<t*>& _vector) {
     while(!_vector.empty()) {
diff --git a/core/bonjour.cpp b/core/bonjour.cpp
index a37054d..b8ba330 100644
--- a/core/bonjour.cpp
+++ b/core/bonjour.cpp
@@ -23,7 +23,6 @@
 #include "bonjour.h"
 #include "core/propertysystem.h"
 #include "core/dss.h"
-#include "core/model.h"
 #include "core/base.h"
 
 #include <arpa/inet.h>
diff --git a/core/busrequestdispatcher.cpp b/core/busrequestdispatcher.cpp
new file mode 100644
index 0000000..1eebd51
--- /dev/null
+++ b/core/busrequestdispatcher.cpp
@@ -0,0 +1,21 @@
+/*
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "busrequestdispatcher.h"
+
diff --git a/core/busrequestdispatcher.h b/core/busrequestdispatcher.h
new file mode 100644
index 0000000..538b353
--- /dev/null
+++ b/core/busrequestdispatcher.h
@@ -0,0 +1,36 @@
+/*
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef BUSREQUESTDISPATCHER_H
+#define BUSREQUESTDISPATCHER_H
+
+#include <boost/shared_ptr.hpp>
+
+namespace dss {
+
+  class BusRequest;
+
+  class BusRequestDispatcher {
+  public:
+    virtual void dispatchRequest(boost::shared_ptr<BusRequest> _pRequest) = 0;
+  }; // BusRequestDispatcher
+
+} // namespace dss
+
+#endif // BUSREQUESTDISPATCHER_H
diff --git a/core/ds485/CMakeLists.txt b/core/ds485/CMakeLists.txt
new file mode 100644
index 0000000..9c7d8c6
--- /dev/null
+++ b/core/ds485/CMakeLists.txt
@@ -0,0 +1 @@
+add_library(ds485 ds485busrequestdispatcher.cpp ds485.cpp ds485proxy.cpp)
\ No newline at end of file
diff --git a/core/ds485/ds485.cpp b/core/ds485/ds485.cpp
new file mode 100644
index 0000000..990e46c
--- /dev/null
+++ b/core/ds485/ds485.cpp
@@ -0,0 +1,1009 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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 "ds485.h"
+
+#include "core/base.h"
+#include "core/logger.h"
+#include "core/ds485const.h"
+#include "core/dss.h"
+#include "core/propertysystem.h"
+
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <ctime>
+#include <sys/time.h>
+
+#include <boost/scoped_ptr.hpp>
+
+namespace dss {
+
+  const unsigned char FrameStart = 0xFD;
+  const unsigned char EscapeCharacter = 0xFC;
+
+  const char* controllerStateToString(const aControllerState _state);
+
+  //================================================== DS485Payload
+
+  template<>
+  void DS485Payload::add(uint8_t _data) {
+    m_Data.push_back(_data);
+  } // add<uint8_t>
+
+  template<>
+  void DS485Payload::add(devid_t _data) {
+    m_Data.push_back((_data >> 0) & 0x00FF);
+    m_Data.push_back((_data >> 8) & 0x00FF);
+  } // add<devid_t>
+
+  template<>
+  void DS485Payload::add(bool _data) {
+    m_Data.push_back(_data);
+  } // add<bool>
+
+  template<>
+  void DS485Payload::add(uint32_t _data) {
+    add<uint16_t>((_data >>  0) & 0x0000FFFF);
+    add<uint16_t>((_data >> 16) & 0x0000FFFF);
+  }
+
+  template<>
+  void DS485Payload::add(dsid_t _data) {
+    // 0x11223344 55667788
+    for(int iByte = 0; iByte < 8; iByte++) {
+      add<uint8_t>((_data.upper >> ((8 - iByte - 1) * 8)) & 0x00000000000000FF);
+    }
+    add<uint8_t>((_data.lower >> 24) & 0x000000FF);
+    add<uint8_t>((_data.lower >> 16) & 0x000000FF);
+    add<uint8_t>((_data.lower >>  8) & 0x000000FF);
+    add<uint8_t>((_data.lower >>  0) & 0x000000FF);
+  } // add<dsid_t>
+
+  int DS485Payload::size() const {
+    return m_Data.size();
+  } // size
+
+  const std::vector<unsigned char>& DS485Payload::toChar() const {
+    return m_Data;
+  } // getData
+
+
+  //================================================== DS485Header
+
+  std::vector<unsigned char> DS485Header::toChar() const {
+    std::vector<unsigned char> result;
+    result.push_back(FrameStart);
+    unsigned char tmp = (m_Destination << 2) | ((m_Broadcast & 0x01) << 1) | (m_Type & 0x01);
+    result.push_back(tmp);
+    tmp = ((m_Source & 0x3F) << 2) | (m_Counter & 0x03);
+    result.push_back(tmp);
+
+    return result;
+  } // toChar
+
+  void DS485Header::fromChar(const unsigned char* _data, const int _len) {
+    if(_len < 3) {
+      throw std::invalid_argument("_len must be > 3");
+    }
+    setDestination((_data[1] >> 2) & 0x3F);
+    setBroadcast((_data[1] & 0x02) == 0x02);
+    setSource((_data[2] >> 2) & 0x3F);
+    setCounter(_data[2] & 0x03);
+  } // fromChar
+
+
+  //================================================== DS485Frame
+
+  std::vector<unsigned char> DS485Frame::toChar() const {
+    std::vector<unsigned char> result = m_Header.toChar();
+    return result;
+  } // toChar
+
+  DS485Payload& DS485Frame::getPayload() {
+    return m_Payload;
+  } // getPayload
+
+  const DS485Payload& DS485Frame::getPayload() const {
+    return m_Payload;
+  } // getPayload
+
+
+  //================================================== DS485CommandFrame
+
+  DS485CommandFrame::DS485CommandFrame()
+  : m_Length(0xFF)
+  {
+    getHeader().setType(1);
+  } // ctor
+
+  std::vector<unsigned char> DS485CommandFrame::toChar() const {
+    std::vector<unsigned char> result = DS485Frame::toChar();
+    unsigned char tmp;
+    if(m_Length == 0xFF) {
+      tmp = (m_Command << 4) | (getPayload().size() & 0x0F);
+    } else {
+      tmp = (m_Command << 4) | (m_Length & 0x0F);
+    }
+    result.push_back(tmp);
+
+    const std::vector<unsigned char>& payload = getPayload().toChar();
+    result.insert(result.end(), payload.begin(), payload.end());
+    return result;
+  } // toChar
+
+
+  //================================================== DS485Controller
+
+  DS485Controller::DS485Controller()
+  : Thread("DS485Controller"),
+    m_State(csInitial),
+    m_RS485DeviceName("/dev/ttyUSB0")
+  {
+    m_DSID.upper = DSIDHeader;
+    m_DSID.lower = 0xDEADBEEF;
+  } // ctor
+
+  DS485Controller::~DS485Controller() {
+  } // dtor
+
+  void DS485Controller::setRS485DeviceName(const std::string& _value) {
+    m_RS485DeviceName = _value;
+    if(isRunning()) {
+      Logger::getInstance()->log("DS485Controller::setRS485DeviceName: Called too late. Value updated but it won't have any effect.", lsError);
+    }
+  } // setRS485DeviceName
+
+  DS485Frame* DS485Controller::getFrameFromWire() {
+    DS485Frame* result = m_FrameReader.getFrame(200);
+    if(result != NULL) {
+      DS485CommandFrame* cmdFrame = dynamic_cast<DS485CommandFrame*>(result);
+      if(cmdFrame != NULL) {
+        //Logger::getInstance()->log("Command received");
+        //Logger::getInstance()->log(string("command: ") + CommandToString(cmdFrame->getCommand()));
+        //Logger::getInstance()->log(string("length:  ") + intToString((cmdFrame->getLength())));
+        //Logger::getInstance()->log(string("msg nr:  ") + intToString(cmdFrame->getHeader().getCounter()));
+      } else {
+        //std::cout << "+";
+        //flush(std::cout);
+        //Logger::getInstance()->log("token received");
+      }
+    }
+    return result;
+  } // getFrameFromWire
+
+  inline void DS485Controller::putCharOnWire(const unsigned char _ch) {
+    if((_ch == FrameStart) || (_ch == EscapeCharacter)) {
+      m_SerialCom->putChar(0xFC);
+      // mask out the msb
+      m_SerialCom->putChar(_ch & 0x7F);
+    } else {
+      m_SerialCom->putChar(_ch);
+    }
+  } // putCharOnWire
+
+  bool DS485Controller::putFrameOnWire(const DS485Frame* _pFrame, bool _freeFrame) {
+    std::vector<unsigned char> chars = _pFrame->toChar();
+    uint16_t crc = 0x0000;
+
+    unsigned int numChars = chars.size();
+    for(unsigned int iChar = 0; iChar < numChars; iChar++) {
+      unsigned char c = chars[iChar];
+      crc = update_crc(crc, c);
+      // escape if it's a reserved character and not the first (frame start)
+      if(iChar != 0) {
+        putCharOnWire(c);
+      } else {
+        m_SerialCom->putChar(c);
+      }
+    }
+
+    if(dynamic_cast<const DS485CommandFrame*>(_pFrame) != NULL) {
+      // send crc
+      unsigned char c = static_cast<unsigned char>(crc & 0xFF);
+      putCharOnWire(c);
+      c = static_cast<unsigned char>((crc >> 8) & 0xFF);
+      putCharOnWire(c);
+    }
+    if(_freeFrame) {
+      delete _pFrame;
+    }
+    return true;
+  } // putFrameOnWire
+
+  bool DS485Controller::resetSerialLine() {
+    m_SerialCom.reset(new SerialCom());
+    try {
+      Logger::getInstance()->log("DS485Controller::execute: Opening '" + m_RS485DeviceName + "' as serial device", lsInfo);
+      m_SerialCom->open(m_RS485DeviceName.c_str());
+      m_FrameReader.setSerialCom(m_SerialCom);
+      return true;
+    } catch(const std::runtime_error& _ex) {
+      Logger::getInstance()->log(std::string("Caught exception while opening serial port: ") + _ex.what(), lsFatal);
+      return false;
+    }
+  } // resetSerialLine
+
+  void DS485Controller::execute() {
+    if(!resetSerialLine()) {
+      doChangeState(csError);
+      return;
+    }
+    doChangeState(csInitial);
+    m_TokenCounter = 0;
+    m_NextStationID = 0xFF;
+    m_StationID = 0xFF;
+    time_t responseSentAt;
+    time_t tokenReceivedAt;
+    m_DSID = dsid_t::fromString(DSS::getInstance()->getPropertySystem().getStringValue("/system/dsid"));
+
+    // prepare token frame
+    boost::scoped_ptr<DS485Frame> token(new DS485Frame());
+    // prepare solicit successor response frame
+    boost::scoped_ptr<DS485CommandFrame> solicitSuccessorResponseFrame(new DS485CommandFrame());
+    solicitSuccessorResponseFrame->getHeader().setDestination(0);
+    solicitSuccessorResponseFrame->getHeader().setSource(0x3F);
+    solicitSuccessorResponseFrame->setCommand(CommandSolicitSuccessorResponse);
+    solicitSuccessorResponseFrame->getPayload().add(m_DSID);
+
+    int senseTimeMS = 0;
+    int numberOfJoinPacketsToWait = -1;
+    bool lastSentWasToken = false;
+    int comErrorSleepTimeScaler = 1;
+    int missedFramesCounter = 0;
+
+    while(!m_Terminated) {
+
+      if(m_State == csInitial) {
+        senseTimeMS = (rand() % 1000) + 2500;
+        numberOfJoinPacketsToWait = -1;
+        m_TokenCounter = 0;
+        lastSentWasToken = false;
+        doChangeState(csSensing);
+        continue;
+      } else if(m_State == csCommError) {
+        sleepMS(comErrorSleepTimeScaler++ * 500);
+        comErrorSleepTimeScaler = std::min(comErrorSleepTimeScaler, 60);
+        if(resetSerialLine()) {
+          doChangeState(csInitial);
+        }
+        continue;
+      } else if(m_State == csSensing) {
+        try {
+          if(m_FrameReader.senseTraffic(senseTimeMS)) {
+            Logger::getInstance()->log("Sensed traffic on the line, changing to csSlaveWaitingToJoin");
+            // wait some time for the first frame and skip it...
+            delete m_FrameReader.getFrame(1000);
+            doChangeState(csSlaveWaitingToJoin);
+          } else {
+            Logger::getInstance()->log("No traffic on line, I'll be your master today");
+            doChangeState(csDesignatedMaster);
+          }
+          comErrorSleepTimeScaler = 1;
+        } catch(const std::runtime_error&) {
+          doChangeState(csCommError);
+        }
+        continue;
+      }
+
+      boost::scoped_ptr<DS485Frame> frame;
+      try {
+        frame.reset(getFrameFromWire());
+      } catch(const std::runtime_error&) {
+        doChangeState(csCommError);
+        continue;
+      }
+      if(frame == NULL) {
+        if(m_State != csDesignatedMaster) {
+          std::cout << "§";
+          missedFramesCounter++;
+          if(missedFramesCounter == 50) {
+            missedFramesCounter = 0;
+            std::cout << "haven't received any frames for 50 iterations, restarting..." << std::endl;
+            doChangeState(csInitial);
+          }
+        } else {
+          sleepMS(1000);
+        }
+        // resend token after timeout
+        if(lastSentWasToken) {
+          putFrameOnWire(token.get(), false);
+          lastSentWasToken = false;
+          std::cout << "t(#)";
+        }
+        flush(std::cout);
+      } else {
+        DS485Header& header = frame->getHeader();
+
+        if (header.getSource() == m_StationID) {
+          continue;
+        }
+
+        DS485CommandFrame* cmdFrame = dynamic_cast<DS485CommandFrame*>(frame.get());
+        lastSentWasToken = false;
+        missedFramesCounter = 0;
+
+        // discard packets which are not addressed to us
+        if(!header.isBroadcast() &&
+           (header.getDestination() != m_StationID) &&
+              (m_State == csSlave ||
+               m_State == csMaster)
+          )
+        {
+/*
+          Logger::getInstance()->log("packet not for me, discarding");
+          std::cout << "dest: " << (int)header.getDestination() << std::endl;
+          std::cout << "src:  " << (int)header.getSource() << std::endl;
+          if(cmdFrame != NULL) {
+            std::cout << "cmd:  " << CommandToString(cmdFrame->getCommand()) << std::endl;
+          }
+*/
+          continue;
+        }
+
+        // handle cases in which we're obliged to act on disregarding our current state
+        if(cmdFrame != NULL) {
+          if(cmdFrame->getCommand() == CommandGetAddressRequest) {
+            if(header.getDestination() == m_StationID) {
+              DS485CommandFrame* frameToSend = new DS485CommandFrame();
+              frameToSend->getHeader().setDestination(header.getSource());
+              frameToSend->getHeader().setSource(m_StationID);
+              frameToSend->setCommand(CommandGetAddressResponse);
+              putFrameOnWire(frameToSend);
+              if(header.isBroadcast()) {
+                std::cerr << "Get address request with bc-flag set" << std::endl;
+              } else {
+                std::cout << "sent response to get address thingie" << std::endl;
+              }
+              continue;
+            }
+          }
+        }
+
+        switch(m_State) {
+        case csInitial:
+          break;
+        case csSensing:
+          break;
+        case csSlaveWaitingToJoin:
+          {
+            if(cmdFrame != NULL) {
+              if(cmdFrame->getCommand() == CommandSolicitSuccessorRequestLong) {
+                // if it's the first of it's kind, determine how many we've got to skip
+                if(numberOfJoinPacketsToWait == -1) {
+                  if(cmdFrame->getCommand() == CommandSolicitSuccessorRequest) {
+                    numberOfJoinPacketsToWait = rand() % 10 + 10;
+                  } else {
+                    // don’t wait forever if we’re in slow-joining mode
+                    numberOfJoinPacketsToWait = rand() % 10;
+                  }
+                  std::cout << "** Waiting for " << numberOfJoinPacketsToWait << std::endl;
+                } else {
+                  numberOfJoinPacketsToWait--;
+                  if(numberOfJoinPacketsToWait == 0) {
+                    m_StationID = 0x3F;
+                    putFrameOnWire(solicitSuccessorResponseFrame.get(), false);
+                    //std::cout << "******* FRAME AWAY ******" << std::endl;
+                    doChangeState(csSlaveJoining);
+                    time(&responseSentAt);
+                  }
+                  //std::cout << numberOfJoinPacketsToWait << std::endl;
+                }
+              }
+            }
+          }
+          break;
+        case csSlaveJoining:
+          if(cmdFrame != NULL) {
+            if(cmdFrame->getCommand() == CommandSetDeviceAddressRequest) {
+              m_StationID = cmdFrame->getPayload().toChar().at(0);
+              DS485CommandFrame* frameToSend = new DS485CommandFrame();
+              frameToSend->getHeader().setDestination(0);
+              frameToSend->getHeader().setSource(m_StationID);
+              frameToSend->setCommand(CommandSetDeviceAddressResponse);
+              putFrameOnWire(frameToSend);
+              std::cout << "### new address " << m_StationID << "\n";
+            } else if(cmdFrame->getCommand() == CommandSetSuccessorAddressRequest) {
+              if(header.getDestination() == m_StationID) {
+                handleSetSuccessor(cmdFrame);
+              }
+            } else {
+              // check if our response has timed-out
+              time_t now;
+              time(&now);
+              if((now - responseSentAt) > 5) {
+                doChangeState(csInitial);
+                Logger::getInstance()->log("DS485: startup timeout", lsError);
+              }
+            }
+            if((m_StationID != 0x3F) && (m_NextStationID != 0xFF)) {
+              Logger::getInstance()->log("DS485: joined network", lsInfo);
+              token->getHeader().setDestination(m_NextStationID);
+              token->getHeader().setSource(m_StationID);
+              doChangeState(csSlaveWaitingForFirstToken);
+              time(&tokenReceivedAt);
+            }
+          }
+          break;
+        case csBroadcastingDSID:
+          break;
+        case csMaster:
+          break;
+        case csSlave:
+          if(cmdFrame == NULL) {
+//            std::cout << "+";
+            // it's a token
+            if(!m_PendingFrames.empty() && (m_TokenCounter > 10)) {
+
+              // send frame
+              m_PendingFramesGuard.lock();
+              DS485CommandFrame& frameToSend = m_PendingFrames.front();
+              putFrameOnWire(&frameToSend, false);
+              std::cout << "p%" << (int)frameToSend.getCommand() << "%e" << std::endl;
+
+              // if not a broadcast, wait for ack, etc
+              if(frameToSend.getHeader().isBroadcast()) {
+                m_PendingFrames.erase(m_PendingFrames.begin());
+              } else {
+                boost::shared_ptr<DS485Frame> ackFrame(m_FrameReader.getFrame(50));
+
+                DS485CommandFrame* cmdAckFrame = dynamic_cast<DS485CommandFrame*>(ackFrame.get());
+                if (cmdAckFrame->getHeader().getSource() == m_StationID) {
+                  ackFrame.reset( m_FrameReader.getFrame(50) );
+                }
+
+                cmdAckFrame = dynamic_cast<DS485CommandFrame*>(ackFrame.get());
+                if(cmdAckFrame != NULL) {
+                  if(cmdAckFrame->getCommand() == CommandAck) {
+                    m_PendingFrames.erase(m_PendingFrames.begin());
+                    std::cout << "\ngot ack" << std::endl;
+                  } else if(cmdAckFrame->getCommand() == CommandBusy) {
+                    std::cout << "\nmodulator is busy" << std::endl;
+                  } else {
+                    m_PendingFrames.erase(m_PendingFrames.begin());
+                    std::cout << "\n&&&&got other" << std::endl;
+                    addToReceivedQueue(cmdAckFrame);
+                  }
+                } else {
+                  m_PendingFrames.erase(m_PendingFrames.begin());
+                  std::cout << "no ack received" << std::endl;
+                }
+              }
+            }
+            m_PendingFramesGuard.unlock();
+            putFrameOnWire(token.get(), false);
+//            std::cout << ".";
+//            flush(std::cout);
+            time(&tokenReceivedAt);
+            m_TokenEvent.broadcast();
+            m_TokenCounter++;
+            lastSentWasToken = true;
+          } else {
+
+            // Handle token timeout
+            time_t now;
+            time(&now);
+            if((now - tokenReceivedAt) > 15) {
+              std::cerr << "restarting" << std::endl;
+              doChangeState(csInitial);
+              continue;
+            }
+            std::cout << "f*" << (int)cmdFrame->getCommand() << "*";
+
+            bool keep = false;
+
+            if(cmdFrame->getCommand() == CommandResponse) {
+              if(!cmdFrame->getHeader().isBroadcast()) {
+                // send ack if it's a response and not a broadcasted one
+                DS485CommandFrame* ack = new DS485CommandFrame();
+                ack->getHeader().setSource(m_StationID);
+                ack->getHeader().setDestination(cmdFrame->getHeader().getSource());
+                ack->setCommand(CommandAck);
+                putFrameOnWire(ack);
+                std::cout << "a(res)";
+              } else {
+                std::cout << "b";
+              }
+              keep = true;
+            } else if(cmdFrame->getCommand() == CommandRequest || cmdFrame->getCommand() == CommandEvent) {
+              if(!cmdFrame->getHeader().isBroadcast()) {
+                DS485CommandFrame* ack = new DS485CommandFrame();
+                ack->getHeader().setSource(m_StationID);
+                ack->getHeader().setDestination(cmdFrame->getHeader().getSource());
+                ack->setCommand(CommandAck);
+                putFrameOnWire(ack);
+                std::cout << "a(req)";
+              }
+              keep = true;
+            } else if(cmdFrame->getCommand() == CommandSolicitSuccessorRequest) {
+              std::cout << "SSRS -> reset" << std::endl;
+              flush(std::cout);
+              doChangeState(csInitial);
+            } else if(cmdFrame->getCommand() == CommandSetSuccessorAddressRequest) {
+              if(header.getDestination() == m_StationID) {
+                handleSetSuccessor(cmdFrame);
+                token->getHeader().setDestination(m_NextStationID);
+              }
+            } else {
+              std::cout << "&&&&&&&&&& unknown frame id: " << (int)cmdFrame->getCommand() << std::endl;
+            }
+            if(keep) {
+              // put in into the received queue
+              addToReceivedQueue(cmdFrame);
+              std::cout << "k";
+            }
+            flush(std::cout);
+          }
+          break;
+        case csSlaveWaitingForFirstToken:
+          {
+            if(cmdFrame == NULL) {
+              if(header.getDestination() == m_StationID) {
+                putFrameOnWire(token.get(), false);
+                m_TokenCounter = 0;
+                doChangeState(csSlave);
+                time(&tokenReceivedAt);
+                std::cout << "DS485: Got first TOKEN" << std::endl;
+                flush(std::cout);
+              }
+            }
+            // Handle timeout
+            time_t now;
+            time(&now);
+            if((now - tokenReceivedAt) > 15) {
+              std::cerr << "DS485: Wait for token timeout, restarting" << std::endl;
+              doChangeState(csInitial);
+              continue;
+            }
+          }
+          break;
+        case csDesignatedMaster:
+          sleepMS(10000);
+          doChangeState(csInitial);
+          break;
+        default:
+          throw std::runtime_error("invalid value for m_State");
+        }
+      }
+    }
+  } // execute
+
+  void DS485Controller::handleSetSuccessor(DS485CommandFrame* _frame) {
+    m_NextStationID = _frame->getPayload().toChar().at(0);
+    DS485CommandFrame* frameToSend = new DS485CommandFrame();
+    frameToSend->getHeader().setDestination(0);
+    frameToSend->getHeader().setSource(m_StationID);
+    frameToSend->setCommand(CommandSetSuccessorAddressResponse);
+    putFrameOnWire(frameToSend);
+    std::cout << "### successor " << m_NextStationID << "\n";
+  } // handleSetSuccessor
+
+  // TODO: look into boost::weak_ptr
+  void DS485Controller::addToReceivedQueue(DS485CommandFrame* _frame) {
+    if(_frame == NULL) {
+      Logger::getInstance()->log("DS485Controller::addToReceivedQueue: _frame is NULL", lsFatal);
+      return;
+    }
+    boost::shared_ptr<DS485CommandFrame> frame(new DS485CommandFrame());
+    (*frame) = *_frame;
+    frame->setFrameSource(fsWire);
+    distributeFrame(frame);
+    // Signal our listeners
+    m_CommandFrameEvent.signal();
+  } // addToReceivedQueue
+
+  void DS485Controller::doChangeState(aControllerState _newState) {
+    if(_newState != m_State) {
+      m_State = _newState;
+      m_StateString = controllerStateToString(m_State);
+      if(m_State == csInitial) {
+        m_NextStationID = 0xFF;
+        m_StationID = 0xFF;
+      }
+      m_ControllerEvent.signal();
+    }
+  } // doChangeState
+
+  void DS485Controller::enqueueFrame(DS485CommandFrame& _frame) {
+    //Logger::getInstance()->log("Frame queued");
+    DS485CommandFrame* frame = new DS485CommandFrame();
+    *frame = _frame;
+    frame->getHeader().setSource(m_StationID);
+    m_PendingFramesGuard.lock();
+    m_PendingFrames.push_back(frame);
+    m_PendingFramesGuard.unlock();
+  } // enqueueFrame
+
+  bool DS485Controller::waitForEvent(const int _timeoutMS) {
+    return m_ControllerEvent.waitFor(_timeoutMS);
+  } // waitForEvent
+
+  aControllerState DS485Controller::getState() const {
+    return m_State;
+  } // getState
+
+  const std::string& DS485Controller::getStateAsString() const {
+    return m_StateString;
+  } // getStateAsString
+
+  void DS485Controller::waitForCommandFrame() {
+    m_CommandFrameEvent.waitFor();
+  } // waitForCommandFrame
+
+  void DS485Controller::waitForToken() {
+    m_TokenEvent.waitFor();
+  } // waitForToken
+
+
+  //================================================== DS485FrameReader
+
+  DS485FrameReader::DS485FrameReader() {
+    m_ValidBytes = 0;
+    m_State = rsSynchronizing;
+    m_MessageLength = -1;
+
+    m_EscapeNext = false;
+    m_IsEscaped = false;
+
+    m_NumberOfFramesReceived = 0;
+    m_NumberOfIncompleteFramesReceived = 0;
+    m_NumberOfCRCErrors = 0;
+  } // ctor
+
+  DS485FrameReader::~DS485FrameReader() {
+  } // dtor
+
+  void DS485FrameReader::setSerialCom(boost::shared_ptr<SerialComBase> _serialCom) {
+    m_SerialCom = _serialCom;
+  } // setHandle
+
+  bool DS485FrameReader::getCharTimeout(char& _charOut, const int _timeoutMS) {
+    return m_SerialCom->getCharTimeout(_charOut, _timeoutMS);
+  } // getCharTimeout
+
+  bool DS485FrameReader::senseTraffic(const int _timeoutMS) {
+    char tmp;
+    return getCharTimeout(tmp, _timeoutMS);
+  } // senseTraffic
+
+  const int TheHeaderSize = 3;
+  const int TheFrameHeaderSize = TheHeaderSize + 1;
+  const int TheCRCSize = 2;
+
+  DS485Frame* DS485FrameReader::getFrame(const int _timeoutMS) {
+    struct timeval timeStarted;
+    gettimeofday(&timeStarted, 0);
+    while(true) {
+      struct timeval now;
+      gettimeofday(&now, 0);
+      int diffMS = (now.tv_sec - timeStarted.tv_sec) * 1000 + (now.tv_usec - timeStarted.tv_usec) / 1000;
+      if(diffMS > _timeoutMS) {
+        flush(std::cout);
+        if(m_State == rsSynchronizing || m_ValidBytes == 0) {
+          break;
+        }
+        m_NumberOfIncompleteFramesReceived++;
+        return NULL;
+      }
+
+      char currentChar;
+      if(getCharTimeout(currentChar, 1)) {
+
+        if((unsigned char)currentChar == EscapeCharacter) {
+          m_EscapeNext = true;
+          continue;
+        }
+
+        if((unsigned char)currentChar == FrameStart) {
+          m_State = rsSynchronizing;
+          m_ValidBytes = 0;
+        }
+
+        if(m_EscapeNext) {
+          currentChar |= 0x80;
+          m_EscapeNext = false;
+          m_IsEscaped = true;
+        } else {
+          m_IsEscaped = false;
+        }
+
+        // store in our receive buffer
+        m_ReceiveBuffer[m_ValidBytes++] = currentChar;
+
+        if(m_ValidBytes == TheReceiveBufferSizeBytes) {
+          Logger::getInstance()->log("receive buffer overflowing, resyncing", lsInfo);
+          m_State = rsSynchronizing;
+          m_ValidBytes = 0;
+        }
+
+        switch(m_State) {
+          case rsSynchronizing:
+          {
+            if(((unsigned char)currentChar == FrameStart) && !m_IsEscaped) {
+              m_State = rsReadingHeader;
+            } else {
+              std::cout << "?";
+            }
+            break;
+          }
+
+          case rsReadingHeader:
+          {
+            if(m_ValidBytes < 1) {
+              Logger::getInstance()->log("in state rsReadingPacket with validBytes < 1, going back to sync", lsError);
+            }
+
+            // attempt to parse the header
+            if(m_ValidBytes == TheHeaderSize) {
+              if((m_ReceiveBuffer[1] & 0x02) == 0x02) {
+                //Logger::getInstance()->log("Packet is a broadcast");
+              } else {
+                //Logger::getInstance()->log("*Packet is adressed");
+              }
+              // check if it's a token or not
+              if((m_ReceiveBuffer[1] & 0x01) == 0x01) {
+                //Logger::getInstance()->log("Packet is a Frame");
+                m_State = rsReadingPacket;
+                m_MessageLength = -1;
+              } else {
+                //Logger::getInstance()->log("Packet is a Token");
+                DS485Frame* frame = new DS485Frame();
+                frame->getHeader().fromChar(m_ReceiveBuffer, m_ValidBytes);
+                m_NumberOfFramesReceived++;
+
+                //std::cout << "-";
+                //flush(std::cout);
+                m_State = rsSynchronizing;
+                return frame;
+              }
+            }
+            break;
+          }
+
+          case rsReadingPacket:
+          {
+            if(m_MessageLength == -1 && m_ValidBytes >= TheFrameHeaderSize) {
+              // the length does not include the size of the headers
+              m_MessageLength = m_ReceiveBuffer[3] & 0x0F;
+            }
+            if(m_ValidBytes == (m_MessageLength + TheFrameHeaderSize)) {
+              //Logger::getInstance()->log("frame received");
+              m_State = rsReadingCRC;
+            }
+            break;
+          }
+
+          case rsReadingCRC:
+          {
+            if(m_ValidBytes == (m_MessageLength + TheFrameHeaderSize + TheCRCSize)) {
+              uint16_t dataCRC = crc16(m_ReceiveBuffer, m_ValidBytes);
+              if(dataCRC != 0) {
+                Logger::getInstance()->log("*********** crc mismatch.", lsError);
+                m_NumberOfCRCErrors++;
+              } else {
+                //Logger::getInstance()->log("received packet, crc ok");
+                //std::cout << "#";
+                m_NumberOfFramesReceived++;
+              }
+              DS485CommandFrame* frame = new DS485CommandFrame();
+              frame->getHeader().fromChar(m_ReceiveBuffer, m_ValidBytes);
+              frame->setLength(m_ReceiveBuffer[3] & 0x0F);
+              frame->setCommand(m_ReceiveBuffer[3] >> 4 & 0x0F);
+              for(int iByte = 0; iByte < m_MessageLength; iByte++) {
+                frame->getPayload().add<uint8_t>(static_cast<uint8_t>(m_ReceiveBuffer[iByte + 4]));
+              }
+              //std::cout << "*" << frame->getCommand() << "*";
+              //flush(std::cout);
+
+              // the show must go on...
+              m_MessageLength = -1;
+              m_State = rsSynchronizing;
+              return frame;
+            }
+          }
+        }
+      }
+    }
+    return NULL;
+  } // getFrame
+
+  //================================================== DS485FrameProvider
+
+  void DS485FrameProvider::addFrameCollector(IDS485FrameCollector* _collector) {
+    m_FrameCollectors.push_back(_collector);
+  } // addFrameCollector
+
+  void DS485FrameProvider::removeFrameCollector(IDS485FrameCollector* _collector) {
+    std::vector<IDS485FrameCollector*>::iterator iCollector = find(m_FrameCollectors.begin(), m_FrameCollectors.end(), _collector);
+    if(iCollector != m_FrameCollectors.end()) {
+      m_FrameCollectors.erase(iCollector);
+    }
+  } // removeFrameCollector
+
+  void DS485FrameProvider::distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
+    for(std::vector<IDS485FrameCollector*>::iterator iCollector = m_FrameCollectors.begin(), e = m_FrameCollectors.end();
+        iCollector != e; ++iCollector)
+    {
+      (*iCollector)->collectFrame(_frame);
+    }
+  } // distributeFrame
+
+  void DS485FrameProvider::distributeFrame(DS485CommandFrame* _pFrame) {
+    boost::shared_ptr<DS485CommandFrame> tempRef(_pFrame);
+    distributeFrame(tempRef);
+  } // distributeFrame
+
+
+  //================================================== PayloadDissector
+
+  template<>
+  uint8_t PayloadDissector::get() {
+    uint8_t result = m_Payload.back();
+    m_Payload.pop_back();
+    return result;
+  }
+
+  template<>
+  uint32_t PayloadDissector::get() {
+    uint32_t result;
+    result = (get<uint8_t>() <<  0) |
+             (get<uint8_t>() <<  8) |
+             (get<uint8_t>() << 16) |
+             (get<uint8_t>() << 24);
+    return result;
+  }
+
+  template<>
+  dsid_t PayloadDissector::get() {
+    dsid_t result;
+    result.upper = 0;
+    for(int iByte = 0; iByte < 8; iByte++) {
+      result.upper |= ((uint64_t)get<uint8_t>() << ((8 - iByte - 1) * 8));
+    }
+    result.lower  = (get<uint8_t>() << 24);
+    result.lower |= (get<uint8_t>() << 16);
+    result.lower |= (get<uint8_t>() <<  8);
+    result.lower |= (get<uint8_t>() <<  0);
+
+    return result;
+  }
+
+  template<>
+  uint16_t PayloadDissector::get() {
+    uint16_t result;
+    result = (get<uint8_t>() << 0)  |
+             (get<uint8_t>() << 8);
+    return result;
+  }
+
+  //================================================== DS485FrameSniffer
+#ifndef __APPLE__
+  DS485FrameSniffer::DS485FrameSniffer(const std::string& _deviceName)
+  {
+     m_SerialCom.reset(new SerialCom());
+     m_SerialCom->open(_deviceName.c_str());
+     m_FrameReader.setSerialCom(m_SerialCom);
+  }
+
+  void DS485FrameSniffer::run() {
+    struct timespec lastFrame;
+    struct timespec thisFrame;
+    clock_gettime(CLOCK_REALTIME, &lastFrame);
+    while(true) {
+      boost::scoped_ptr<DS485Frame> frame(m_FrameReader.getFrame(500));
+      if(frame.get() != NULL){
+        clock_gettime(CLOCK_REALTIME, &thisFrame);
+        if(frame.get() != NULL) {
+
+          double diffMS = ((thisFrame.tv_sec*1000.0 + thisFrame.tv_nsec/1000.0/1000.0) -
+                           (lastFrame.tv_sec*1000.0 + lastFrame.tv_nsec/1000.0/1000.0));
+
+          std::cout << "+" << diffMS << "\n";
+
+          DS485CommandFrame* cmdFrame = dynamic_cast<DS485CommandFrame*>(frame.get());
+          if(cmdFrame != NULL) {
+            uint8_t cmd = cmdFrame->getCommand();
+            std::cout << "Command Frame: " << commandToString(cmd) <<  " " << "(" <<  (int)cmd << ") " << (int)frame->getHeader().getSource() << " -> " << (int)frame->getHeader().getDestination()  << "\n";
+
+            if(cmd == CommandRequest || cmd == CommandResponse) {
+              PayloadDissector pd(cmdFrame->getPayload());
+              std::cout << (int)pd.get<uint8_t>() << "\n";
+            }
+          } else {
+            std::cout << "token " << (int)frame->getHeader().getSource() << " -> " << (int)frame->getHeader().getDestination()  << "\n";
+          }
+          std::cout << "seq: " << (int)frame->getHeader().getCounter() << std::endl;
+
+          lastFrame = thisFrame;
+        }
+      }
+    }
+  }
+#endif
+
+  //================================================== Global helpers
+
+  const char* commandToString(const uint8_t _command) {
+    switch(_command) {
+    case CommandSolicitSuccessorRequestLong:
+      return "solicit successor request long";
+    case CommandSolicitSuccessorRequest:
+      return "solicit successor request";
+    case CommandSolicitSuccessorResponse:
+      return "solicit successor response";
+    case CommandGetAddressRequest:
+      return "get address request";
+    case CommandGetAddressResponse:
+      return "get address response";
+    case CommandSetDeviceAddressRequest:
+      return "set device address request";
+    case CommandSetDeviceAddressResponse:
+      return "set device address response";
+    case CommandSetSuccessorAddressRequest:
+      return "set successor address request";
+    case CommandSetSuccessorAddressResponse:
+      return "set successor address response";
+    case CommandRequest:
+      return "request";
+    case CommandResponse:
+      return "response";
+    case CommandAck:
+      return "ack";
+    case CommandBusy:
+      return "busy";
+    default:
+      return "(unknown)";
+    }
+  } // commandToString
+
+  const char* controllerStateToString(const aControllerState _state) {
+    switch(_state) {
+    case csInitial:
+      return "initial";
+    case csSensing:
+      return "sensing";
+    case csDesignatedMaster:
+      return "designated master";
+    case csBroadcastingDSID:
+      return "broadcasting DSID";
+    case csMaster:
+      return "master";
+    case csSlaveWaitingToJoin:
+      return "slave waiting to join";
+    case csSlaveJoining:
+      return "slave joining";
+    case csSlave:
+      return "slave";
+    case csSlaveWaitingForFirstToken:
+      return "slave waiting for first token";
+    case csError:
+      return "error";
+    case csCommError:
+      return "comm error";
+    default:
+      return "(unknown)";
+    }
+  } // controllerStateToString
+
+  const dsid_t NullDSID(0,0);
+
+}
diff --git a/core/ds485/ds485.h b/core/ds485/ds485.h
new file mode 100644
index 0000000..9dca45d
--- /dev/null
+++ b/core/ds485/ds485.h
@@ -0,0 +1,307 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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 _DS485_H_INCLUDED
+#define _DS485_H_INCLUDED
+
+#include "core/thread.h"
+#include "unix/serialcom.h"
+#include "core/ds485types.h"
+#include "core/syncevent.h"
+
+#include <vector>
+#include <string>
+
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace dss {
+
+  /** Stores the payload of a DS485Frame */
+  class DS485Payload {
+  private:
+    std::vector<unsigned char> m_Data;
+  public:
+    /** Adds \a _data to the payload. */
+    template<class t>
+    void add(t _data);
+
+    /** Returns the size of the payload added.*/
+    int size() const;
+
+    /** Returns a const reference of the data */
+    const std::vector<unsigned char>& toChar() const;
+  }; // DS485Payload
+
+  /** Wrapper for a DS485 header. */
+  class DS485Header {
+  private:
+    uint8_t m_Type;
+    uint8_t m_Counter;
+    uint8_t m_Source;
+    bool m_Broadcast;
+    uint8_t m_Destination;
+  public:
+    DS485Header()
+    : m_Type(0x00),
+      m_Counter(0x00),
+      m_Source(0xff),
+      m_Broadcast(false),
+      m_Destination(0xff)
+    {};
+
+    /** Returns the destination of the frame.
+     * @note This field may not contain any useful information if isBroadcast
+     * returns \c true */
+    uint8_t getDestination() const { return m_Destination; };
+    /** Returns whether the the frame is a broadcast or not. */
+    bool isBroadcast() const { return m_Broadcast; };
+    /** Returns the source of the frame */
+    uint8_t getSource() const { return m_Source; };
+    /** Returns the counter of the frame.
+     * The use of this field is mostly for debugging purposes. Implementors
+     * should increase it every packet they send to detect dropped frames. */
+    uint8_t getCounter() const { return m_Counter; };
+    uint8_t getType() const { return m_Type; };
+
+    void setDestination(const uint8_t _value) { m_Destination = _value; };
+    void setBroadcast(const bool _value) { m_Broadcast = _value; };
+    void setSource(const uint8_t _value) { m_Source = _value; };
+    void setCounter(const uint8_t _value) { m_Counter = _value; };
+    void setType(const uint8_t _value) { m_Type = _value; };
+
+    std::vector<unsigned char> toChar() const;
+    void fromChar(const unsigned char* _data, const int _len);
+  };
+
+  typedef enum {
+    fsWire,
+    fsDSS
+  } aFrameSource;
+
+  class DS485Frame {
+  private:
+    DS485Header m_Header;
+    DS485Payload m_Payload;
+    aFrameSource m_FrameSource;
+  public:
+    DS485Frame()
+    : m_FrameSource(fsDSS)
+    {}
+    virtual ~DS485Frame() {}
+
+    DS485Header& getHeader() { return m_Header; }
+
+    DS485Payload& getPayload();
+    const DS485Payload& getPayload() const;
+
+    aFrameSource getFrameSource() const { return m_FrameSource; }
+    void setFrameSource(aFrameSource _value) { m_FrameSource = _value; }
+
+    virtual std::vector<unsigned char> toChar() const;
+  }; // DS485Frame
+
+  class DS485CommandFrame : public DS485Frame {
+  private:
+    uint8_t m_Command;
+    uint8_t m_Length;
+  public:
+    DS485CommandFrame();
+    virtual ~DS485CommandFrame() {};
+
+    uint8_t getCommand() const { return m_Command; };
+    uint8_t getLength() const { return m_Length; };
+
+    void setCommand(const uint8_t _value) { m_Command = _value; };
+    void setLength(const uint8_t _value) { m_Length = _value; };
+
+    virtual std::vector<unsigned char> toChar() const;
+  };
+
+  class IDS485FrameCollector;
+
+  /** A frame provider receives frames from somewhere */
+  class DS485FrameProvider {
+  private:
+    std::vector<IDS485FrameCollector*> m_FrameCollectors;
+  protected:
+    /** Distributes the frame to the collectors */
+    void distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame);
+    /** Distributes the frame to the collectors.
+     * NOTE: the ownership of the frame is transfered to the frame provider
+     */
+    void distributeFrame(DS485CommandFrame* _pFrame);
+  public:
+    void addFrameCollector(IDS485FrameCollector* _collector);
+    void removeFrameCollector(IDS485FrameCollector* _collector);
+  };
+
+  typedef enum {
+    csInitial,
+    csSensing,
+    csDesignatedMaster,
+    csBroadcastingDSID,
+    csMaster,
+    csSlaveWaitingToJoin,
+    csSlaveJoining,
+    csSlave,
+    csSlaveWaitingForFirstToken,
+    csError,
+    csCommError
+  } aControllerState;
+
+  typedef enum {
+    rsSynchronizing,
+    rsReadingHeader,
+    rsReadingPacket,
+    rsReadingCRC
+  } aReaderState;
+
+  const int TheReceiveBufferSizeBytes = 50;
+
+  class DS485FrameReader {
+  private:
+    // receive functions's state
+    int m_ValidBytes;
+    unsigned char m_ReceiveBuffer[TheReceiveBufferSizeBytes];
+    aReaderState m_State;
+    int m_MessageLength;
+
+    bool m_EscapeNext;
+    bool m_IsEscaped;
+    int m_NumberOfFramesReceived;
+    int m_NumberOfIncompleteFramesReceived;
+    int m_NumberOfCRCErrors;
+  private:
+    int m_Handle;
+    boost::shared_ptr<SerialComBase> m_SerialCom;
+  private:
+    bool getCharTimeout(char& _charOut, const int _timeoutMS);
+  public:
+    DS485FrameReader();
+    virtual ~DS485FrameReader();
+
+    void setSerialCom(boost::shared_ptr<SerialComBase> _serialCom);
+
+    DS485Frame* getFrame(const int _timeoutMS);
+    bool senseTraffic(const int _timeoutMS);
+
+    int getNumberOfFramesReceived() const { return m_NumberOfFramesReceived; }
+    int getNumberOfIncompleteFramesReceived() const { return m_NumberOfIncompleteFramesReceived; }
+    int getNumberOfCRCErrors() const { return m_NumberOfCRCErrors; }
+  }; // FrameReader
+
+  class DS485Controller : public Thread,
+                          public DS485FrameProvider {
+  private:
+    aControllerState m_State;
+    DS485FrameReader m_FrameReader;
+    std::string m_RS485DeviceName;
+    std::string m_StateString;
+    int m_StationID;
+    int m_NextStationID;
+    int m_TokenCounter;
+
+    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;
+  private:
+    DS485Frame* getFrameFromWire();
+    bool putFrameOnWire(const DS485Frame* _pFrame, bool _freeFrame = true);
+
+    inline void putCharOnWire(const unsigned char _ch);
+
+    void doChangeState(aControllerState _newState);
+    void addToReceivedQueue(DS485CommandFrame* _frame);
+    bool resetSerialLine();
+
+    void handleSetSuccessor(DS485CommandFrame* _frame);
+  public:
+    DS485Controller();
+    virtual ~DS485Controller();
+
+    void setRS485DeviceName(const std::string& _value);
+    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; };
+
+    const std::string& getStateAsString() const;
+
+    const DS485FrameReader& getFrameReader() const { return m_FrameReader; }
+
+    virtual void execute();
+
+    int getStationID() const { return m_StationID; }
+
+    void setDSID(const dsid_t& _value) { m_DSID = _value; }
+  }; // DS485Controller
+
+  class IDS485FrameCollector {
+  public:
+    virtual void collectFrame(boost::shared_ptr<DS485CommandFrame> _frame) = 0;
+    virtual ~IDS485FrameCollector() {};
+  }; // DS485FrameCollector
+
+  class DS485FrameSniffer {
+  private:
+    DS485FrameReader m_FrameReader;
+    boost::shared_ptr<SerialCom> m_SerialCom;
+  public:
+    DS485FrameSniffer(const std::string& _deviceName);
+
+    void run();
+  }; // IDS485FrameSniffer
+
+  class PayloadDissector {
+  private:
+    std::vector<unsigned char> m_Payload;
+  public:
+    PayloadDissector(DS485Payload& _payload) {
+      const std::vector<unsigned char>& payload =_payload.toChar();
+      m_Payload.insert(m_Payload.begin(), payload.rbegin(), payload.rend());
+    }
+
+    bool isEmpty() { return m_Payload.empty(); };
+
+    template<class t>
+    t get();
+  }; // PayloadDissector
+
+  const char* commandToString(const uint8_t _command);
+
+  const uint32_t SimulationPrefix = 0xFFC00000;
+  inline bool isSimulationDSID(const dsid_t _dsid) {
+    return (_dsid.lower & SimulationPrefix) == SimulationPrefix;
+  }
+
+}
+
+#endif
diff --git a/core/ds485/ds485busrequestdispatcher.cpp b/core/ds485/ds485busrequestdispatcher.cpp
new file mode 100644
index 0000000..a2d78e1
--- /dev/null
+++ b/core/ds485/ds485busrequestdispatcher.cpp
@@ -0,0 +1,49 @@
+/*
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "ds485busrequestdispatcher.h"
+#include "core/model/busrequest.h"
+#include "core/ds485/ds485.h"
+#include "core/foreach.h"
+#include "core/ds485const.h"
+#include "core/DS485Interface.h"
+
+namespace dss {
+
+  void DS485BusRequestDispatcher::dispatchRequest(boost::shared_ptr<BusRequest> _pRequest) {
+    PacketBuilderHintsBase* hints = _pRequest->getBuilderHints();
+    boost::shared_ptr<DS485CommandFrame> frame(new DS485CommandFrame());
+    frame->getHeader().setBroadcast(hints->isBroadcast());
+    frame->getHeader().setDestination(hints->getTarget());
+    frame->setCommand(CommandRequest);
+    frame->getPayload().add<uint8_t>(hints->getFunctionID());
+    if(hints->getNumberAddressParameter() == 2) {
+      frame->getPayload().add<uint16_t>(hints->getAddressParameter(0));
+      frame->getPayload().add<uint16_t>(hints->getAddressParameter(1));
+    } else {
+      frame->getPayload().add<uint16_t>(hints->getAddressParameter(0));
+    }
+    int numParam = hints->getNumberOfParameter();
+    for(int iParam = 0; iParam < numParam; iParam++) {
+      frame->getPayload().add<uint16_t>(hints->getParameter(iParam));
+    }
+    m_pInterface->sendFrame(*frame);
+  }
+} // namespace dss
+
diff --git a/core/ds485/ds485busrequestdispatcher.h b/core/ds485/ds485busrequestdispatcher.h
new file mode 100644
index 0000000..a049c45
--- /dev/null
+++ b/core/ds485/ds485busrequestdispatcher.h
@@ -0,0 +1,41 @@
+/*
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DS485BUSREQUESTDISPATCHER_H
+#define DS485BUSREQUESTDISPATCHER_H
+
+#include "core/busrequestdispatcher.h"
+
+namespace dss {
+
+  class DS485Interface;
+  
+  class DS485BusRequestDispatcher : public BusRequestDispatcher {
+  public:
+    virtual void dispatchRequest(boost::shared_ptr<BusRequest> _pRequest);
+    void setProxy(DS485Interface* _pInterface) {
+      m_pInterface = _pInterface;
+    }
+  private:
+    DS485Interface* m_pInterface;
+  }; // DS485BusRequestDispatcher
+
+} // namespace dss
+
+#endif // DS485BUSREQUESTDISPATCHER_H
diff --git a/core/ds485/ds485proxy.cpp b/core/ds485/ds485proxy.cpp
new file mode 100644
index 0000000..b5b2677
--- /dev/null
+++ b/core/ds485/ds485proxy.cpp
@@ -0,0 +1,1372 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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 "ds485proxy.h"
+
+#include "core/dss.h"
+#include "core/logger.h"
+#include "core/ds485const.h"
+#include "core/event.h"
+#include "core/propertysystem.h"
+#include "core/foreach.h"
+
+#include "core/model/modelevent.h"
+#include "core/model/device.h"
+#include "core/model/apartment.h"
+
+#ifdef WITH_SIM
+#include "core/sim/dssim.h"
+#endif
+
+#include <sstream>
+
+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),
+    m_InitializeDS485Controller(true)
+  {
+    assert(_pApartment != NULL);
+    if(_pDSS != NULL) {
+      _pDSS->getPropertySystem().createProperty(getConfigPropertyBasePath() + "rs485devicename")
+            ->linkToProxy(PropertyProxyMemberFunction<DS485Controller, std::string>(m_DS485Controller, &DS485Controller::getRS485DeviceName, &DS485Controller::setRS485DeviceName));
+
+      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "tokensReceived")
+            ->linkToProxy(PropertyProxyMemberFunction<DS485Controller, int>(m_DS485Controller, &DS485Controller::getTokenCount));
+
+      const DS485FrameReader& reader = m_DS485Controller.getFrameReader();
+      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "framesReceived")
+            ->linkToProxy(PropertyProxyMemberFunction<DS485FrameReader, int>(reader, &DS485FrameReader::getNumberOfFramesReceived));
+
+      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "incompleteFramesReceived")
+            ->linkToProxy(PropertyProxyMemberFunction<DS485FrameReader, int>(reader, &DS485FrameReader::getNumberOfIncompleteFramesReceived));
+
+      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "crcErrors")
+            ->linkToProxy(PropertyProxyMemberFunction<DS485FrameReader, int>(reader, &DS485FrameReader::getNumberOfCRCErrors));
+
+      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "state")
+            ->linkToProxy(PropertyProxyMemberFunction<DS485Controller, std::string>(m_DS485Controller, &DS485Controller::getStateAsString));
+
+      _pDSS->getPropertySystem().setStringValue("/system/dsid", "3504175FE0000000DEADBEEF", true, false);
+    }
+  } // ctor
+
+  bool DS485Proxy::isReady() {
+	  return isRunning()
+#ifdef WITH_SIM
+	         &&  DSS::getInstance()->getSimulation().isReady() // allow the simulation to run on it's own
+#endif
+	         && ((m_DS485Controller.getState() == csSlave) ||
+	             (m_DS485Controller.getState() == csDesignatedMaster) ||
+	             (m_DS485Controller.getState() == csError)); 
+  } // isReady
+
+  uint16_t DS485Proxy::deviceGetParameterValue(devid_t _id, uint8_t _modulatorID, int _paramID) {
+    DS485CommandFrame frame;
+    frame.getHeader().setDestination(_modulatorID);
+    frame.getHeader().setBroadcast(false);
+    frame.getHeader().setType(1);
+    frame.setCommand(CommandRequest);
+    frame.getPayload().add<uint8_t>(FunctionDeviceGetParameterValue);
+    frame.getPayload().add<uint16_t>(_id);
+    frame.getPayload().add<uint16_t>(_paramID);
+    uint8_t res = receiveSingleResult(frame, FunctionDeviceGetParameterValue);
+    return res;
+  } // deviceGetParameterValue
+
+  uint16_t DS485Proxy::deviceGetFunctionID(devid_t _id, uint8_t _modulatorID) {
+    DS485CommandFrame frame;
+    frame.getHeader().setDestination(_modulatorID);
+    frame.getHeader().setBroadcast(false);
+    frame.getHeader().setType(1);
+    frame.setCommand(CommandRequest);
+    frame.getPayload().add<uint8_t>(FunctionDeviceGetFunctionID);
+    frame.getPayload().add<devid_t>(_id);
+
+    uint16_t result;
+    boost::shared_ptr<ReceivedFrame> resFrame = receiveSingleFrame(frame, FunctionDeviceGetFunctionID);
+    if(resFrame.get() != NULL) {
+      PayloadDissector pd(resFrame->getFrame()->getPayload());
+      pd.get<uint8_t>(); // skip the function id
+      if(pd.get<uint16_t>() == 0x0001) {
+        result = pd.get<uint16_t>();
+        checkResultCode(result);
+      }
+    }
+    return result;
+  } // deviceGetFunctionID
+
+  void DS485Proxy::sendFrame(DS485CommandFrame& _frame) {
+    _frame.setFrameSource(fsDSS);
+    bool broadcast = _frame.getHeader().isBroadcast();
+#ifdef WITH_SIM
+    bool sim = isSimAddress(_frame.getHeader().getDestination());
+    if(broadcast || sim) {
+      log("Sending packet to sim");
+      if(DSS::hasInstance()) {
+        getDSS().getSimulation().process(_frame);
+      }
+    }
+#else
+    bool sim = false;
+#endif
+    if(broadcast || !sim) {
+      if((m_DS485Controller.getState() == csSlave) || (m_DS485Controller.getState() == csMaster)) {
+        log("Sending packet to hardware");
+       	m_DS485Controller.enqueueFrame(_frame);
+      }
+    }
+    std::ostringstream sstream;
+    sstream << "Frame content: ";
+    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 << " to " << int(_frame.getHeader().getDestination());
+    if(broadcast) {
+      sstream << " as broadcast";
+    }
+    log(sstream.str());
+
+    boost::shared_ptr<DS485CommandFrame> pFrame(new DS485CommandFrame);
+    *pFrame = _frame;
+    // relay the frame to update our state
+    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);
+    result->addToProxy();
+    sendFrame(_frame);
+    return result;
+  } // sendFrameAndInstallBucket
+
+#ifdef WITH_SIM
+  bool DS485Proxy::isSimAddress(const uint8_t _addr) {
+    if(DSS::hasInstance()) {
+      return getDSS().getSimulation().isSimAddress(_addr);
+    } else {
+      return true;
+    }
+  } // isSimAddress
+#endif
+
+  void DS485Proxy::checkResultCode(const int _resultCode) {
+    if(_resultCode < 0) {
+      std::string message = "Unknown Error";
+      switch(_resultCode) {
+      case kDS485NoIDForIndexFound:
+        message = "No ID for index found";
+        break;
+      case kDS485ZoneNotFound:
+        message = "Zone not found";
+        break;
+      case kDS485IndexOutOfBounds:
+        message = "Index out of bounds";
+        break;
+      case kDS485GroupIDOutOfBounds:
+        message = "Group ID out of bounds";
+        break;
+      case kDS485ZoneCannotBeDeleted:
+        message = "Zone can not be deleted";
+        break;
+      case kDS485OutOfMemory:
+        message = "dSM is out of memory";
+        break;
+      case kDS485RoomAlreadyExists:
+        message = "Room already exists";
+        break;
+      case kDS485InvalidDeviceID:
+        message = "Invalid device id";
+        break;
+      case kDS485CannotRemoveFromStandardGroup:
+        message = "Cannot remove device from standard group";
+        break;
+      case kDS485CannotDeleteStandardGroup:
+        message = "Cannot delete standard group";
+        break;
+      case kDS485DSIDIsNull:
+        message = "DSID is null";
+        break;
+      case kDS485ReservedRoomNumber:
+        message = "Room number is reserved";
+        break;
+      case kDS485DeviceNotFound:
+        message = "Device not found";
+        break;
+      case kDS485GroupNotFound:
+        message = "Group not found";
+        break;
+      }
+      throw DS485ApiError(message);
+    }
+  } // checkResultCode
+
+  void DS485Proxy::setValueDevice(const Device& _device, const uint16_t _value, const uint16_t _parameterID, const int _size) {
+    DS485CommandFrame frame;
+    frame.getHeader().setDestination(_device.getModulatorID());
+    frame.getHeader().setBroadcast(false);
+    frame.getHeader().setType(1);
+    frame.setCommand(CommandRequest);
+    frame.getPayload().add<uint8_t>(FunctionDeviceSetParameterValue);
+    frame.getPayload().add<uint16_t>(_device.getShortAddress());
+    frame.getPayload().add<uint16_t>(_parameterID);
+    frame.getPayload().add<uint16_t>(_size - 1);
+    frame.getPayload().add<uint16_t>(_value);
+    sendFrame(frame);
+  } // setValueDevice
+  
+  ModulatorSpec_t DS485Proxy::modulatorSpecFromFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
+    int source = _frame->getHeader().getSource();
+
+    PayloadDissector pd(_frame->getPayload());
+    pd.get<uint8_t>();
+    uint16_t devID = pd.get<uint16_t>();
+    devID =  devID >> 8;
+    if(devID == 0) {
+      log("Found dSS");
+    } else if(devID == 1) {
+      log("Found dSM");
+    } else {
+      log(std::string("Found unknown device (") + intToString(devID, true) + ")");
+    }
+    uint16_t hwVersion = (pd.get<uint8_t>() << 8) | pd.get<uint8_t>();
+    uint16_t swVersion = (pd.get<uint8_t>() << 8) | pd.get<uint8_t>();
+
+    log(std::string("  HW-Version: ") + intToString(hwVersion >> 8) + "." + intToString(hwVersion & 0x00FF));
+    log(std::string("  SW-Version: ") + intToString(swVersion >> 8) + "." + intToString(swVersion & 0x00FF));
+
+    std::string name;
+    for(int i = 0; i < 6; i++) {
+      char c = char(pd.get<uint8_t>());
+      if(c != '\0') {
+        name += c;
+      }
+    }
+    log(std::string("  Name:      \"") + name + "\"");
+
+    // bus-id, sw-version, hw-version, name, device-id
+    ModulatorSpec_t spec(source, swVersion, hwVersion, name, devID);
+    return spec;
+  } // modulatorSpecFromFrame
+
+  std::vector<ModulatorSpec_t> DS485Proxy::getModulators() {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(0);
+    cmdFrame.getHeader().setBroadcast(true);
+    cmdFrame.setCommand(CommandRequest);
+    log("Proxy: GetModulators");
+
+    cmdFrame.getPayload().add<uint8_t>(FunctionGetTypeRequest);
+    boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionGetTypeRequest);
+    bucket->waitForFrames(1000);
+
+    std::map<int, bool> resultFrom;
+
+    std::vector<ModulatorSpec_t> result;
+    while(true) {
+      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+      if(recFrame == NULL) {
+        break;
+      }
+      int source = recFrame->getFrame()->getHeader().getSource();
+      if(resultFrom[source]) {
+        log(std::string("already received result from ") + intToString(source));
+        continue;
+      }
+      ModulatorSpec_t spec = modulatorSpecFromFrame(recFrame->getFrame());
+      result.push_back(spec);
+    }
+
+    return result;
+  } // getModulators
+
+  ModulatorSpec_t DS485Proxy::getModulatorSpec(const int _modulatorID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.getHeader().setBroadcast(false);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionGetTypeRequest);
+    log("Proxy: getModulatorSpec");
+
+    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionGetTypeRequest);
+
+    if(recFrame == NULL) {
+      throw DS485ApiError("No frame received");
+    }
+
+    ModulatorSpec_t result = modulatorSpecFromFrame(recFrame->getFrame());
+
+    return result;
+  } // getModulatorSpec
+
+  int DS485Proxy::getGroupCount(const int _modulatorID, const int _zoneID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetGroupsSize);
+    cmdFrame.getPayload().add<uint16_t>(_zoneID);
+    int8_t res = int8_t(receiveSingleResult(cmdFrame, FunctionModulatorGetGroupsSize));
+    if(res < 0) {
+      log("GetGroupCount: Negative group count received '" + intToString(res) +
+          " on modulator " + intToString(_modulatorID) +
+          " with zone " + intToString(_zoneID));
+    }
+    checkResultCode(res);
+    // Every modulator should provide all standard-groups
+    if(res < GroupIDStandardMax) {
+      res = GroupIDStandardMax;
+    }
+    return res;
+  } // getGroupCount
+
+  std::vector<int> DS485Proxy::getGroups(const int _modulatorID, const int _zoneID) {
+    std::vector<int> result;
+
+    int numGroups = getGroupCount(_modulatorID, _zoneID);
+    log(std::string("Modulator has ") + intToString(numGroups) + " groups");
+    for(int iGroup = 0; iGroup < numGroups; iGroup++) {
+      DS485CommandFrame cmdFrame;
+      cmdFrame.getHeader().setDestination(_modulatorID);
+      cmdFrame.setCommand(CommandRequest);
+      cmdFrame.getPayload().add<uint8_t>(FunctionZoneGetGroupIdForInd);
+      cmdFrame.getPayload().add<uint16_t>(_zoneID);
+      cmdFrame.getPayload().add<uint16_t>(iGroup);
+
+      int8_t res = int8_t(receiveSingleResult(cmdFrame, FunctionZoneGetGroupIdForInd));
+      if(res < 0) {
+        log("GetGroups: Negative index received '" + intToString(res) + "' for index " + intToString(iGroup), lsFatal);
+      } else {
+        result.push_back(res);
+      }
+      //checkResultCode(res);
+    }
+
+    return result;
+  } // getGroups
+
+  int DS485Proxy::getDevicesInGroupCount(const int _modulatorID, const int _zoneID, const int _groupID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionGroupGetDeviceCount);
+    cmdFrame.getPayload().add<uint16_t>(_zoneID);
+    cmdFrame.getPayload().add<uint16_t>(_groupID);
+
+    int16_t res = int16_t(receiveSingleResult16(cmdFrame, FunctionGroupGetDeviceCount));
+    if(res < 0) {
+      log("GetDevicesInGroupCount: Negative count received '" + intToString(res) +
+          "' on modulator " + intToString(_modulatorID) +
+          " with zoneID " + intToString(_zoneID) + " in group " + intToString(_groupID));
+    }
+    checkResultCode(res);
+
+    return res;
+  } // getDevicesInGroupCount
+
+  std::vector<int> DS485Proxy::getDevicesInGroup(const int _modulatorID, const int _zoneID, const int _groupID) {
+    std::vector<int> result;
+
+    int numDevices = getDevicesInGroupCount(_modulatorID, _zoneID, _groupID);
+    for(int iDevice = 0; iDevice < numDevices; iDevice++) {
+      DS485CommandFrame cmdFrame;
+      cmdFrame.getHeader().setDestination(_modulatorID);
+      cmdFrame.setCommand(CommandRequest);
+      cmdFrame.getPayload().add<uint8_t>(FunctionGroupGetDevKeyForInd);
+      cmdFrame.getPayload().add<uint16_t>(_zoneID);
+      cmdFrame.getPayload().add<uint16_t>(_groupID);
+      cmdFrame.getPayload().add<uint16_t>(iDevice);
+      int16_t res = int16_t(receiveSingleResult16(cmdFrame, FunctionGroupGetDevKeyForInd));
+      if(res < 0) {
+        log("GetDevicesInGroup: Negative device id received '" + intToString(res) + "' for index " + intToString(iDevice), lsFatal);
+      } else {
+        result.push_back(res);
+      }
+      try {
+        checkResultCode(res);
+      } catch(DS485ApiError& err) {
+        log(std::string("Error reported back by dSM: ") + err.what(), lsFatal);
+      }
+    }
+
+    return result;
+  } // getDevicesInGroup
+
+  std::vector<int> DS485Proxy::getGroupsOfDevice(const int _modulatorID, const int _deviceID) {
+    std::vector<int> result;
+
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionDeviceGetGroups);
+    cmdFrame.getPayload().add<uint16_t>(_deviceID);
+
+    boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionDeviceGetGroups);
+
+    bucket->waitForFrame(1000);
+
+    while(true) {
+      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+      if(recFrame == NULL) {
+        break;
+      }
+
+      PayloadDissector pd(recFrame->getFrame()->getPayload());
+      pd.get<uint8_t>(); // discard the function id
+      pd.get<uint16_t>(); // function result
+
+      for(int iByte = 0; iByte < 8; iByte++) {
+        uint8_t byte = pd.get<uint8_t>();
+        for(int iBit = 0; iBit < 8; iBit++) {
+          if(byte & (1 << iBit)) {
+            result.push_back((iByte * 8 + iBit) + 1);
+          }
+        }
+      }
+    }
+    return result;
+  } // getGroupsOfDevice
+
+  std::vector<int> DS485Proxy::getZones(const int _modulatorID) {
+    std::vector<int> result;
+
+    int numZones = getZoneCount(_modulatorID);
+    log(std::string("Modulator has ") + intToString(numZones) + " zones");
+    for(int iZone = 0; iZone < numZones; iZone++) {
+      DS485CommandFrame cmdFrame;
+      cmdFrame.getHeader().setDestination(_modulatorID);
+      cmdFrame.setCommand(CommandRequest);
+      cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetZoneIdForInd);
+      cmdFrame.getPayload().add<uint16_t>(iZone);
+      log("GetZoneID");
+      int16_t tempResult = int16_t(receiveSingleResult16(cmdFrame, FunctionModulatorGetZoneIdForInd));
+      // TODO: The following line is a workaround as described in #246
+      if((tempResult < 0) && (tempResult > -20)) {
+        log("GetZones: Negative zone id " + intToString(tempResult) + " received. Modulator: " + intToString(_modulatorID) + " index: " + intToString(iZone), lsError);
+        // TODO: take this line outside the if-clause after the dSM-API has been reworked
+        checkResultCode(tempResult);
+      } else {
+        result.push_back(tempResult);
+      }
+      log("received ZoneID: " + uintToString((unsigned int)tempResult));
+    }
+    return result;
+  } // getZones
+
+  int DS485Proxy::getZoneCount(const int _modulatorID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetZonesSize);
+    log("GetZoneCount");
+
+    int8_t result = int8_t(
+        receiveSingleResult(cmdFrame, FunctionModulatorGetZonesSize));
+    checkResultCode(result);
+    return result;
+  } // getZoneCount
+
+  int DS485Proxy::getDevicesCountInZone(const int _modulatorID, const int _zoneID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorCountDevInZone);
+    cmdFrame.getPayload().add<uint16_t>(_zoneID);
+    log("GetDevicesCountInZone");
+
+    log(intToString(_modulatorID) + " " + intToString(_zoneID));
+
+    int16_t result = int16_t(receiveSingleResult16(cmdFrame, FunctionModulatorCountDevInZone));
+    if(result < 0) {
+      log("GetDevicesCountInZone: negative count '" + intToString(result) + "'", lsError);
+    }
+    checkResultCode(result);
+
+    return result;
+  } // getDevicesCountInZone
+
+  std::vector<int> DS485Proxy::getDevicesInZone(const int _modulatorID, const int _zoneID) {
+    std::vector<int> result;
+
+    int numDevices = getDevicesCountInZone(_modulatorID, _zoneID);
+    log(std::string("Found ") + intToString(numDevices) + " in zone.");
+    for(int iDevice = 0; iDevice < numDevices; iDevice++) {
+      DS485CommandFrame cmdFrame;
+      cmdFrame.getHeader().setDestination(_modulatorID);
+      cmdFrame.setCommand(CommandRequest);
+      cmdFrame.getPayload().add<uint8_t>(FunctionModulatorDevKeyInZone);
+      cmdFrame.getPayload().add<uint16_t>(_zoneID);
+      cmdFrame.getPayload().add<uint16_t>(iDevice);
+
+      uint16_t devID = receiveSingleResult16(cmdFrame, FunctionModulatorDevKeyInZone);
+      checkResultCode(int16_t(devID));
+      result.push_back(devID);
+    }
+    return result;
+  } // getDevicesInZone
+
+  void DS485Proxy::setZoneID(const int _modulatorID, const devid_t _deviceID, const int _zoneID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionDeviceSetZoneID);
+    cmdFrame.getPayload().add<devid_t>(_deviceID);
+    cmdFrame.getPayload().add<uint16_t>(_zoneID);
+
+    int16_t res = int16_t(receiveSingleResult(cmdFrame, FunctionDeviceSetZoneID));
+    checkResultCode(res);
+  } // setZoneID
+
+  void DS485Proxy::createZone(const int _modulatorID, const int _zoneID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorAddZone);
+    cmdFrame.getPayload().add<uint16_t>(_zoneID);
+
+    int16_t res = int16_t(receiveSingleResult(cmdFrame, FunctionModulatorAddZone));
+    checkResultCode(res);
+  } // createZone
+
+  void DS485Proxy::removeZone(const int _modulatorID, const int _zoneID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorRemoveZone);
+    cmdFrame.getPayload().add<uint16_t>(_zoneID);
+
+    int16_t res = int16_t(receiveSingleResult(cmdFrame, FunctionModulatorAddZone));
+    checkResultCode(res);
+  } // removeZone
+
+  dsid_t DS485Proxy::getDSIDOfDevice(const int _modulatorID, const int _deviceID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionDeviceGetDSID);
+    cmdFrame.getPayload().add<uint16_t>(_deviceID);
+    log("Proxy: GetDSIDOfDevice");
+
+    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDeviceGetDSID);
+    if(recFrame == NULL) {
+      throw DS485ApiError("No frame received");
+    }
+
+    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    pd.get<uint8_t>(); // discard the function id
+    int16_t res = int16_t(pd.get<uint16_t>());
+    checkResultCode(res);
+    return pd.get<dsid_t>();
+  } // getDSIDOfDevice
+
+  dsid_t DS485Proxy::getDSIDOfModulator(const int _modulatorID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetDSID);
+    log(std::string("Proxy: GetDSIDOfModulator ") + intToString(_modulatorID));
+
+    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionModulatorGetDSID);
+    if(recFrame == NULL) {
+      log("GetDSIDOfModulator: received no result from " + intToString(_modulatorID), lsError);
+      throw DS485ApiError("No frame received");
+    }
+
+    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    pd.get<uint8_t>(); // discard the function id
+    return pd.get<dsid_t>();
+  } // getDSIDOfModulator
+
+  int DS485Proxy::getLastCalledScene(const int _modulatorID, const int _zoneID, const int _groupID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionGroupGetLastCalledScene);
+    log(std::string("Proxy: GetLastCalledScene ") + intToString(_modulatorID));
+    cmdFrame.getPayload().add<uint16_t>(_zoneID);
+    cmdFrame.getPayload().add<uint16_t>(_groupID);
+
+    int16_t res = int16_t(receiveSingleResult16(cmdFrame, FunctionGroupGetLastCalledScene));
+    if(res < 0) {
+      log("DS485Proxy::getLastCalledScene: negative result received: " + intToString(res));
+    }
+    checkResultCode(res);
+    return res;
+  } // getLastCalledScene
+
+  unsigned long DS485Proxy::getPowerConsumption(const int _modulatorID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetPowerConsumption);
+    log(std::string("Proxy: GetPowerConsumption ") + intToString(_modulatorID));
+
+    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionModulatorGetPowerConsumption);
+    if(recFrame == NULL) {
+      log("DS485Proxy::getPowerConsumption: received no results", lsError);
+      throw DS485ApiError("No frame received");
+    }
+    if(recFrame->getFrame()->getHeader().getSource() != _modulatorID) {
+      log("GetPowerConsumption: received result from wrong source");
+    }
+    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    pd.get<uint8_t>(); // discard the function id
+    return pd.get<uint32_t>();
+  } // getPowerConsumption
+
+  unsigned long DS485Proxy::getEnergyMeterValue(const int _modulatorID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetEnergyMeterValue);
+    log(std::string("Proxy: GetEnergyMeterValue ") + intToString(_modulatorID));
+
+    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionModulatorGetEnergyMeterValue);
+    if(recFrame == NULL) {
+      log("DS485Proxy::getEnergyMeterValue: received no results", lsError);
+      throw DS485ApiError("No frame received");
+    }
+    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    pd.get<uint8_t>(); // discard the function id
+    return pd.get<uint32_t>();
+  } // getEnergyMeterValue
+
+  bool DS485Proxy::getEnergyBorder(const int _modulatorID, int& _lower, int& _upper) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetEnergyLevel);
+
+    boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionModulatorGetEnergyLevel);
+
+    bucket->waitForFrame(1000);
+
+    boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+    if(recFrame == NULL) {
+      throw DS485ApiError("No frame received");
+    }
+
+    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    pd.get<uint8_t>(); // discard the function id
+    _lower = pd.get<uint16_t>();
+    _upper = pd.get<uint16_t>();
+    return true;
+  } // getEnergyBorder
+
+  int DS485Proxy::getSensorValue(const Device& _device, const int _sensorID) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_device.getModulatorID());
+    cmdFrame.getHeader().setBroadcast(false);
+    cmdFrame.getHeader().setType(1);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionDeviceGetSensorValue);
+    cmdFrame.getPayload().add<uint16_t>(_device.getShortAddress());
+    cmdFrame.getPayload().add<uint16_t>(_sensorID);
+    log("GetSensorValue");
+
+    boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionDeviceGetSensorValue);
+    bucket->waitForFrame(2000);
+    boost::shared_ptr<ReceivedFrame> recFrame;
+    if(bucket->isEmpty()) {
+      log(std::string("received no ack for request getSensorValue"));
+      throw DS485ApiError("no Ack for sensorValue");
+    } else if(bucket->getFrameCount() == 1) {
+        // first frame received, wait for the next frame
+      recFrame= bucket->popFrame();
+      bucket->waitForFrame(2000);
+    } else
+        recFrame= bucket->popFrame();
+    // first frame is only request ack;
+
+    PayloadDissector pd(recFrame->getFrame()->getPayload());
+    pd.get<uint8_t>(); // discard functionID
+    checkResultCode((int)pd.get<uint16_t>()); // check first ack
+
+    if(bucket->isEmpty()) {
+        // no next frame after additional waiting.
+        throw DS485ApiError("no Answer for sensorValue");
+    }
+
+    recFrame = bucket->popFrame();
+
+    if(recFrame.get() != NULL) {
+        PayloadDissector pd(recFrame->getFrame()->getPayload());
+        pd.get<uint8_t>(); // discard functionID
+        pd.get<uint16_t>();
+        pd.get<uint16_t>();
+        checkResultCode((int)pd.get<uint16_t>()); // check sensorvalue
+        int result = int(pd.get<uint16_t>());
+        log(std::string("result ") + intToString(result));
+        return result;
+    } else {
+      throw std::runtime_error("received frame is NULL but bucket->isEmpty() returns false");
+    }
+  } // getSensorValue
+
+  uint8_t DS485Proxy::dSLinkSend(const int _modulatorID, devid_t _devAdr, uint8_t _value, uint8_t _flags) {
+    DS485CommandFrame cmdFrame;
+    cmdFrame.getHeader().setDestination(_modulatorID);
+    cmdFrame.setCommand(CommandRequest);
+    cmdFrame.getPayload().add<uint8_t>(FunctionDSLinkSendDevice);
+    cmdFrame.getPayload().add<uint16_t>(_devAdr);
+    cmdFrame.getPayload().add<uint16_t>(_value);
+    cmdFrame.getPayload().add<uint16_t>(_flags);
+
+    if((_flags & DSLinkSendWriteOnly) == 0) {
+      boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionDSLinkReceive);
+      bucket->waitForFrame(10000);
+      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+      if(recFrame == NULL) {
+        log("dsLinkSend: No packet received", lsError);
+        throw DS485ApiError("No frame received");
+      }
+      PayloadDissector pd(recFrame->getFrame()->getPayload());
+      pd.get<uint8_t>(); // discard the function id
+      pd.get<uint16_t>(); // garbage
+      devid_t devAddress = pd.get<uint16_t>(); // device address
+      if(devAddress != _devAdr) {
+        std::string errStr =
+            "dSLinkSend: Received answer for wrong device expected: "+
+            intToString(_devAdr, true) +
+            " got: " + intToString(devAddress, true);
+        log(errStr, lsError);
+        throw DS485ApiError(errStr);
+      }
+      return pd.get<uint16_t>();
+    } else {
+      sendFrame(cmdFrame);
+      log("dsLinkSend: Not waiting for response (writeOnly is set)");
+      return 0;
+    }
+  } // dsLinkSend
+
+  void DS485Proxy::addToGroup(const int _modulatorID, const int _groupID, const int _deviceID) {
+
+  } // addToGroup
+
+  void DS485Proxy::removeFromGroup(const int _modulatorID, const int _groupID, const int _deviceID) {
+
+  } // removeFromGroup
+
+  int DS485Proxy::addUserGroup(const int _modulatorID) {
+    return 0;
+  } // addUserGroup
+
+  void DS485Proxy::removeUserGroup(const int _modulatorID, const int _groupID) {
+
+  } // removeUserGroup
+
+  boost::shared_ptr<ReceivedFrame> 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>();
+    } 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();
+
+    if(recFrame.get() != NULL) {
+      return recFrame;
+    } else {
+      throw std::runtime_error("received frame is NULL but bucket->isEmpty() returns false");
+    }
+  } // receiveSingleFrame
+
+  uint8_t DS485Proxy::receiveSingleResult(DS485CommandFrame& _frame, const uint8_t _functionID) {
+    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(_frame, _functionID);
+
+    if(recFrame.get() != NULL) {
+      PayloadDissector pd(recFrame->getFrame()->getPayload());
+      uint8_t functionID = pd.get<uint8_t>();
+      if(functionID != _functionID) {
+        log("function ids are different", lsFatal);
+      }
+      uint8_t result = pd.get<uint8_t>();
+      return result;
+    } else {
+      return 0;
+    }
+  } // receiveSingleResult
+
+  uint16_t DS485Proxy::receiveSingleResult16(DS485CommandFrame& _frame, const uint8_t _functionID) {
+    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(_frame, _functionID);
+
+    if(recFrame.get() != NULL) {
+      PayloadDissector pd(recFrame->getFrame()->getPayload());
+      uint8_t functionID = pd.get<uint8_t>();
+      if(functionID != _functionID) {
+        log("function ids are different");
+      }
+      uint16_t result = pd.get<uint8_t>();
+      if(!pd.isEmpty()) {
+        result |= (pd.get<uint8_t>() << 8);
+      } else {
+        log("receiveSingleResult16: only received half of the data (8bit)", lsFatal);
+      }
+      return result;
+    } else {
+      return 0;
+    }
+  } // receiveSingleResult16
+
+  void DS485Proxy::initialize() {
+    Subsystem::initialize();
+    m_DS485Controller.addFrameCollector(this);
+#ifdef WITH_SIM
+    if(DSS::hasInstance()) {
+      getDSS().getSimulation().addFrameCollector(this);
+    }
+#endif
+  }
+
+  void DS485Proxy::doStart() {
+    if(m_InitializeDS485Controller) {
+      try {
+        m_DS485Controller.setDSID(dsid_t::fromString(getDSS().getPropertySystem().getStringValue(getConfigPropertyBasePath() + "dsid")));
+        m_DS485Controller.run();
+      } 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  FunctionModulatorAddZone:
+      return "Modulator Add Zone";
+    case  FunctionModulatorRemoveZone:
+      return "Modulator Remove Zone";
+    case  FunctionModulatorRemoveAllZones:
+      return "Modulator Remove All Zones";
+    case  FunctionModulatorCountDevInZone:
+      return "Modulator Count Dev In Zone";
+    case  FunctionModulatorDevKeyInZone:
+      return "Modulator Dev Key In Zone";
+    case  FunctionModulatorGetGroupsSize:
+      return "Modulator Get Groups Size";
+    case  FunctionModulatorGetZonesSize:
+      return "Modulator Get Zones Size";
+    case  FunctionModulatorGetZoneIdForInd:
+      return "Modulator Get Zone Id For Index";
+    case  FunctionModulatorAddToGroup:
+      return "Modulator Add To Group";
+    case  FunctionModulatorRemoveFromGroup:
+      return "Modulator 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 FunctionModulatorGetDSID:
+      return "Function Modulator Get DSID";
+
+    case FunctionModulatorGetPowerConsumption:
+    	return "Function Modulator Get PowerConsumption";
+    case FunctionModulatorGetEnergyMeterValue:
+      return "Function Modulator Get Energy-Meter Value";
+    case FunctionModulatorGetEnergyLevel:
+      return "Function Modulator Get Energy-Level";
+    case FunctionModulatorSetEnergyLevel:
+      return "Function Modulator 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::etNewModulator);
+              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::etLostModulator);
+              pEvent->addParameter(modID);
+              raiseModelEvent(pEvent);
+            } else if(functionID == EventDeviceReady) {
+              int modID = frame->getHeader().getDestination();
+              ModelEvent* pEvent = new ModelEvent(ModelEvent::etModulatorReady);
+              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 == FunctionModulatorGetPowerConsumption) {   
+              /* hard optimized */
+              //getDSS().getApartment().getModulatorByBusID((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 == FunctionModulatorGetEnergyMeterValue) {
+              /* hard optimized */
+              //getDSS().getApartment().getModulatorByBusID((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 == FunctionModulatorGetDSID) {
+              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
+
+  bool FrameBucketCollector::isEmpty() const {
+    return m_Frames.empty();
+  } // isEmpty
+
+}
diff --git a/core/ds485/ds485proxy.h b/core/ds485/ds485proxy.h
new file mode 100644
index 0000000..811db19
--- /dev/null
+++ b/core/ds485/ds485proxy.h
@@ -0,0 +1,243 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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 _DS485_PROXY_H_INCLUDED
+#define _DS485_PROXY_H_INCLUDED
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "core/ds485types.h"
+#include "ds485.h"
+#include "core/syncevent.h"
+#include "core/DS485Interface.h"
+#include "core/subsystem.h"
+#include "core/mutex.h"
+
+#include <map>
+#include <vector>
+
+#ifndef WIN32
+  #include <ext/hash_map>
+#else
+  #include <hash_map>
+#endif
+
+#ifndef WIN32
+using namespace __gnu_cxx;
+#else
+using namespace stdext;
+#endif
+
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/ptr_container/ptr_map.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace dss {
+
+  class DS485Proxy;
+  class Apartment;
+  class ModelEvent;
+
+  /** 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,
+                     public    DS485Interface,
+                     public    DeviceBusInterface,
+                     public    StructureQueryBusInterface,
+                     public    IDS485FrameCollector {
+  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);
+    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();
+
+    DS485Controller m_DS485Controller;
+    SyncEvent m_ProxyEvent;
+    Apartment* m_pApartment;
+
+    SyncEvent m_PacketHere;
+    Mutex m_IncomingFramesGuard;
+    Mutex m_FrameBucketsGuard;
+    CommandFrameSharedPtrVector m_IncomingFrames;
+    bool m_InitializeDS485Controller;
+
+    ModulatorSpec_t modulatorSpecFromFrame(boost::shared_ptr<DS485CommandFrame> _frame);
+    void checkResultCode(const int _resultCode);
+    void raiseModelEvent(ModelEvent* _pEvent);
+  protected:
+    virtual void doStart();
+  public:
+    DS485Proxy(DSS* _pDSS, Apartment* _pApartment);
+    virtual ~DS485Proxy() {};
+
+    virtual DeviceBusInterface* getDeviceBusInterface() { return this; }
+    virtual StructureQueryBusInterface* getStructureQueryBusInterface() { 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<ModulatorSpec_t> getModulators();
+    virtual ModulatorSpec_t getModulatorSpec(const int _modulatorID);
+
+    virtual std::vector<int> getZones(const int _modulatorID);
+    virtual int getZoneCount(const int _modulatorID);
+    virtual std::vector<int> getDevicesInZone(const int _modulatorID, const int _zoneID);
+    virtual int getDevicesCountInZone(const int _modulatorID, const int _zoneID);
+
+    virtual void setZoneID(const int _modulatorID, const devid_t _deviceID, const int _zoneID);
+    virtual void createZone(const int _modulatorID, const int _zoneID);
+    virtual void removeZone(const int _modulatorID, const int _zoneID);
+
+    virtual int getGroupCount(const int _modulatorID, const int _zoneID);
+    virtual std::vector<int> getGroups(const int _modulatorID, const int _zoneID);
+    virtual int getDevicesInGroupCount(const int _modulatorID, const int _zoneID, const int _groupID);
+    virtual std::vector<int> getDevicesInGroup(const int _modulatorID, const int _zoneID, const int _groupID);
+
+    virtual std::vector<int> getGroupsOfDevice(const int _modulatorID, const int _deviceID);
+
+    virtual void addToGroup(const int _modulatorID, const int _groupID, const int _deviceID);
+    virtual void removeFromGroup(const int _modulatorID, const int _groupID, const int _deviceID);
+
+    virtual int addUserGroup(const int _modulatorID);
+    virtual void removeUserGroup(const int _modulatorID, const int _groupID);
+
+    virtual dsid_t getDSIDOfDevice(const int _modulatorID, const int _deviceID);
+    virtual dsid_t getDSIDOfModulator(const int _modulatorID);
+
+    virtual int getLastCalledScene(const int _modulatorID, const int _zoneID, const int _groupID);
+
+    virtual unsigned long getPowerConsumption(const int _modulatorID);
+    virtual unsigned long getEnergyMeterValue(const int _modulatorID);
+    virtual bool getEnergyBorder(const int _modulatorID, int& _lower, int& _upper);
+
+    //------------------------------------------------ UDI
+    virtual uint8_t dSLinkSend(const int _modulatorID, devid_t _devAdr, uint8_t _value, uint8_t _flags);
+
+    //------------------------------------------------ Device
+    virtual uint16_t deviceGetParameterValue(devid_t _id, uint8_t _modulatorID, int _paramID);
+    virtual uint16_t deviceGetFunctionID(devid_t _id, uint8_t _modulatorID);
+
+    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
+
+#endif
diff --git a/core/ds485client.cpp b/core/ds485client.cpp
index 13c1064..89f2390 100644
--- a/core/ds485client.cpp
+++ b/core/ds485client.cpp
@@ -23,7 +23,7 @@
 
 #include "core/dss.h"
 #include "core/foreach.h"
-#include "unix/ds485proxy.h"
+#include "core/ds485/ds485proxy.h"
 
 namespace dss {
 
diff --git a/core/ds485const.h b/core/ds485const.h
index 9b50bf8..5a1fab4 100644
--- a/core/ds485const.h
+++ b/core/ds485const.h
@@ -83,7 +83,8 @@ namespace dss {
   const uint8_t FunctionDeviceStartDimInc = 0x45;
   const uint8_t FunctionDeviceStartDimDec = 0x46;
   const uint8_t FunctionDeviceEndDim = 0x47;
-
+  const uint8_t FunctionDeviceDisable = 0x48;
+  const uint8_t FunctionDeviceEnable = 0x49;
 
   const uint8_t FunctionDeviceSetParameterValue = 0x4B;
   const uint8_t FunctionDeviceIncreaseValue  = 0x4C;
diff --git a/core/dss.cpp b/core/dss.cpp
index 2ea5540..67fb9f6 100644
--- a/core/dss.cpp
+++ b/core/dss.cpp
@@ -33,11 +33,11 @@
 #include "propertysystem.h"
 #include "scripting/modeljs.h"
 #include "eventinterpreterplugins.h"
-#ifdef __GNUC__
-#include "../unix/ds485proxy.h"
-#endif
+#include "core/ds485/ds485proxy.h"
+#include "core/ds485/ds485busrequestdispatcher.h"
+#include "core/model/apartment.h"
 
-#include "webserver.h"
+#include "core/web/webserver.h"
 #ifdef WITH_BONJOUR
   #include "bonjour.h"
 #endif
@@ -155,12 +155,18 @@ 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));
+    m_pApartment = boost::shared_ptr<Apartment>(new Apartment(this, NULL));
     m_Subsystems.push_back(m_pApartment.get());
 
     m_pDS485Interface = boost::shared_ptr<DS485Proxy>(new DS485Proxy(this, m_pApartment.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_pApartment->setDS485Interface(m_pDS485Interface.get());
+    m_pApartment->setBusRequestDispatcher(m_pBusDispatcher.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 298a8a4..00fc97c 100644
--- a/core/dss.h
+++ b/core/dss.h
@@ -45,6 +45,7 @@ namespace dss {
   class EventInterpreter;
   class Apartment;
   class WebServices;
+  class DS485BusRequestDispatcher;
 #ifdef WITH_SIM
   class DSSim;
 #endif
@@ -80,6 +81,7 @@ namespace dss {
     boost::shared_ptr<EventQueue> m_pEventQueue;
     boost::shared_ptr<Metering> m_pMetering;
     boost::shared_ptr<FakeMeter> m_pFakeMeter;
+    boost::shared_ptr<DS485BusRequestDispatcher> m_pBusDispatcher;
     std::string m_dataDirectory;
     std::string m_configDirectory;
     std::string m_webrootDirectory;
diff --git a/core/event.cpp b/core/event.cpp
index 3cf3ad3..e34af80 100644
--- a/core/event.cpp
+++ b/core/event.cpp
@@ -22,19 +22,41 @@
 
 #include "event.h"
 
-#include "base.h"
 #include "logger.h"
-#include "xmlwrapper.h"
 #include "dss.h"
 #include "propertysystem.h"
 
 #include "foreach.h"
+#include "core/model/apartment.h"
+#include "core/model/device.h"
+#include "core/model/devicereference.h"
+#include "core/model/set.h"
 
 #include <set>
 #include <iostream>
 
 #include <boost/filesystem.hpp>
 
+#include <Poco/DOM/Document.h>
+#include <Poco/DOM/Element.h>
+#include <Poco/DOM/Node.h>
+#include <Poco/DOM/Attr.h>
+#include <Poco/DOM/Text.h>
+#include <Poco/DOM/AutoPtr.h>
+#include <Poco/DOM/DOMParser.h>
+#include <Poco/SAX/InputSource.h>
+#include <Poco/SAX/SAXException.h>
+
+using Poco::XML::Document;
+using Poco::XML::Element;
+using Poco::XML::Attr;
+using Poco::XML::Text;
+using Poco::XML::ProcessingInstruction;
+using Poco::XML::AutoPtr;
+using Poco::XML::DOMParser;
+using Poco::XML::InputSource;
+using Poco::XML::Node;
+
 using std::set;
 using std::cout;
 
@@ -218,7 +240,7 @@ namespace dss {
             Logger::getInstance()->log("EventInterpreter:  Parameter '" + iParam->first + "' = '" + iParam->second + "'");
           }
 
-          for(vector< boost::shared_ptr<EventSubscription> >::iterator ipSubscription = m_Subscriptions.begin(), e = m_Subscriptions.end();
+          for(std::vector< boost::shared_ptr<EventSubscription> >::iterator ipSubscription = m_Subscriptions.begin(), e = m_Subscriptions.end();
               ipSubscription != e; ++ipSubscription)
           {
             if((*ipSubscription)->matches(*toProcess)) {
@@ -249,7 +271,7 @@ namespace dss {
   } // execute
 
   EventInterpreterPlugin* EventInterpreter::getPluginByName(const std::string& _name) {
-    for(vector<EventInterpreterPlugin*>::iterator ipPlugin = m_Plugins.begin(), e = m_Plugins.end();
+    for(std::vector<EventInterpreterPlugin*>::iterator ipPlugin = m_Plugins.begin(), e = m_Plugins.end();
         ipPlugin != e; ++ipPlugin)
     {
       if((*ipPlugin)->getName() == _name) {
@@ -266,7 +288,7 @@ namespace dss {
   } // subscribe
 
   void EventInterpreter::unsubscribe(const std::string& _subscriptionID) {
-    for(vector< boost::shared_ptr<EventSubscription> >::iterator ipSubscription = m_Subscriptions.begin(), e = m_Subscriptions.end();
+    for(std::vector< boost::shared_ptr<EventSubscription> >::iterator ipSubscription = m_Subscriptions.begin(), e = m_Subscriptions.end();
         ipSubscription != e; ++ipSubscription)
     {
       if((*ipSubscription)->getID() == _subscriptionID) {
@@ -278,7 +300,7 @@ namespace dss {
 
   boost::shared_ptr<EventSubscription> EventInterpreter::subscriptionByID(const std::string& _subscriptionID) {
     boost::shared_ptr<EventSubscription> result;
-    for(vector< boost::shared_ptr<EventSubscription> >::iterator ipSubscription = m_Subscriptions.begin(), e = m_Subscriptions.end();
+    for(std::vector< boost::shared_ptr<EventSubscription> >::iterator ipSubscription = m_Subscriptions.begin(), e = m_Subscriptions.end();
         ipSubscription != e; ++ipSubscription)
     {
       if((*ipSubscription)->getID() == _subscriptionID) {
@@ -299,112 +321,153 @@ namespace dss {
   } // uniqueSubscriptionID
 
   void EventInterpreter::loadFromXML(const std::string& _fileName) {
-    const int apartmentConfigVersion = 1;
+    const int eventConfigVersion = 1;
     Logger::getInstance()->log(std::string("EventInterpreter: Loading subscriptions from '") + _fileName + "'");
 
-    if(boost::filesystem::exists(_fileName)) {
-      XMLDocumentFileReader reader(_fileName);
-
-      XMLNode rootNode = reader.getDocument().getRootNode();
-      if(rootNode.getName() == "subscriptions") {
-        if(strToIntDef(rootNode.getAttributes()["version"], -1) == apartmentConfigVersion) {
-          XMLNodeList nodes = rootNode.getChildren();
-          for(XMLNodeList::iterator iNode = nodes.begin(); iNode != nodes.end(); ++iNode) {
-            std::string nodeName = iNode->getName();
-            if(nodeName == "subscription") {
-              loadSubscription(*iNode);
+    std::ifstream inFile(_fileName.c_str());
+
+    try {
+      InputSource input(inFile);
+      DOMParser parser;
+      AutoPtr<Document> pDoc = parser.parse(&input);
+      Element* rootNode = pDoc->documentElement();
+
+      if(rootNode->localName() == "subscriptions") {
+        if(rootNode->hasAttribute("version") && (strToInt(rootNode->getAttribute("version")) == eventConfigVersion)) {
+          Node* curNode = rootNode->firstChild();
+          while(curNode != NULL) {
+            if(curNode->localName() == "subscription") {
+	            loadSubscription(curNode);
             }
+            curNode = curNode->nextSibling();
           }
         }
+      } else {
+        log(_fileName + " must have a root-node named 'subscriptions'", lsFatal);
       }
+    } catch(Poco::XML::SAXParseException& e) {
+      log("Error parsing file: " + _fileName + ". message: " + e.message(), lsFatal);
     }
   } // loadFromXML
 
-  void EventInterpreter::loadFilter(XMLNode& _node, EventSubscription& _subscription) {
-    std::string matchType = _node.getAttributes()["match"];
-    if(matchType == "all") {
-      _subscription.setFilterOption(EventSubscription::foMatchAll);
-    } else if(matchType == "none") {
-      _subscription.setFilterOption(EventSubscription::foMatchNone);
-    } else if(matchType == "one") {
-      _subscription.setFilterOption(EventSubscription::foMatchOne);
-    } else {
-      Logger::getInstance()->log(std::string("EventInterpreter::loadFilter: Could not determine the match-type (\"") + matchType + "\", reverting to 'all'", lsError);
-    }
-    XMLNodeList nodes = _node.getChildren();
-    for(XMLNodeList::iterator iNode = nodes.begin(); iNode != nodes.end(); ++iNode) {
-      std::string nodeName = iNode->getName();
-      if(nodeName == "property-filter") {
-        EventPropertyFilter* filter = NULL;
-        std::string filterType = iNode->getAttributes()["type"];
-        std::string propertyName = iNode->getAttributes()["property"];
-        if(filterType.empty() || propertyName.empty()) {
-          Logger::getInstance()->log("EventInterpreter::loadFilter: Missing type and/or property-name", lsFatal);
+  void EventInterpreter::loadFilter(Node* _node, EventSubscription& _subscription) {
+    if(_node != NULL) {    
+      Element* elem = dynamic_cast<Element*>(_node);
+      if(elem != NULL) {
+        std::string matchType = elem->getAttribute("match");
+        if(matchType == "all") {
+          _subscription.setFilterOption(EventSubscription::foMatchAll);
+        } else if(matchType == "none") {
+          _subscription.setFilterOption(EventSubscription::foMatchNone);
+        } else if(matchType == "one") {
+          _subscription.setFilterOption(EventSubscription::foMatchOne);
         } else {
-          if(filterType == "exists") {
-            filter = new EventPropertyExistsFilter(propertyName);
-          } else if(filterType == "missing") {
-            filter = new EventPropertyMissingFilter(propertyName);
-          } else if(filterType == "matches") {
-            std::string matchValue = iNode->getAttributes()["value"];
-            filter = new EventPropertyMatchFilter(propertyName, matchValue);
-          } else {
-            Logger::getInstance()->log("Unknown property-filter type", lsError);
-          }
+          log(std::string("loadFilter: Could not determine the match-type (\"") + matchType + "\", reverting to 'all'", lsError);
+          _subscription.setFilterOption(EventSubscription::foMatchAll);
         }
-        if(filter != NULL) {
-          _subscription.addPropertyFilter(filter);
+      }
+
+      Node* curNode = _node->firstChild();
+      while(curNode != NULL) {
+        std::string nodeName = curNode->localName();
+        if(nodeName == "property-filter") {
+          loadPropertyFilter(curNode, _subscription);
         }
+        curNode = curNode->nextSibling();
       }
     }
   } // loadFilter
 
-  void EventInterpreter::loadSubscription(XMLNode& _node) {
-    std::string evtName = _node.getAttributes()["event-name"];
-    std::string handlerName = _node.getAttributes()["handler-name"];
-
-    if(evtName.size() == 0) {
-      Logger::getInstance()->log("EventInterpreter::loadSubscription: empty event-name, skipping this subscription", lsWarning);
-      return;
+  void EventInterpreter::loadPropertyFilter(Node* _pNode, EventSubscription& _subscription) {
+    Element* elem = dynamic_cast<Element*>(_pNode);
+    if(elem != NULL) {
+      EventPropertyFilter* filter = NULL;
+      std::string filterType;
+      if(elem->hasAttribute("type")) {
+        filterType = elem->getAttribute("type");
+      }
+      std::string propertyName;
+      if(elem->hasAttribute("property")) {
+        propertyName = elem->getAttribute("property");
+      }
+      if(filterType.empty() || propertyName.empty()) {
+        Logger::getInstance()->log("EventInterpreter::loadProperty: Missing type and/or property-name", lsFatal);
+      } else {
+        if(filterType == "exists") {
+          filter = new EventPropertyExistsFilter(propertyName);
+        } else if(filterType == "missing") {
+          filter = new EventPropertyMissingFilter(propertyName);
+        } else if(filterType == "matches") {
+          std::string matchValue;
+          if(elem->hasAttribute("value")) {
+            matchValue = elem->getAttribute("value");
+          }
+          filter = new EventPropertyMatchFilter(propertyName, matchValue);
+        } else {
+          Logger::getInstance()->log("Unknown property-filter type", lsError);
+        }
+      }
+      if(filter != NULL) {
+        _subscription.addPropertyFilter(filter);
+      }
     }
+  } // loadPropertyFilter
+  
+  void EventInterpreter::loadSubscription(Node* _node) {
+    Element* elem = dynamic_cast<Element*>(_node);
+    if(elem != NULL) {    
+      std::string evtName;
+      if(elem->hasAttribute("event-name")) {
+        evtName = elem->getAttribute("event-name");
+      }
+      std::string handlerName;
+      if(elem->hasAttribute("handler-name")) {
+        handlerName = elem->getAttribute("handler-name");
+      }
 
-    if(handlerName.size() == 0) {
-      Logger::getInstance()->log("EventInterpreter::loadSubscription: empty handler-name, skipping this subscription", lsWarning);
-      return;
-    }
+      if(evtName.size() == 0) {
+        Logger::getInstance()->log("EventInterpreter::loadSubscription: empty event-name, skipping this subscription", lsWarning);
+        return;
+      }
 
-    boost::shared_ptr<SubscriptionOptions> opts;
-    bool hadOpts = false;
+      if(handlerName.size() == 0) {
+        Logger::getInstance()->log("EventInterpreter::loadSubscription: empty handler-name, skipping this subscription", lsWarning);
+        return;
+      }
 
-    EventInterpreterPlugin* plugin = getPluginByName(handlerName);
-    if(plugin == NULL) {
-      Logger::getInstance()->log(std::string("EventInterpreter::loadSubscription: could not find plugin for handler-name '") + handlerName + "'", lsWarning);
-      Logger::getInstance()->log(       "EventInterpreter::loadSubscription: Still generating a subscription but w/o inner parameter", lsWarning);
-    } else {
-      opts.reset(plugin->createOptionsFromXML(_node.getChildren()));
-      hadOpts = true;
-    }
-    try {
-      XMLNode& paramNode = _node.getChildByName("parameter");
-      if(opts == NULL) {
-        opts.reset(new SubscriptionOptions());
+      boost::shared_ptr<SubscriptionOptions> opts;
+      bool hadOpts = false;
+
+      EventInterpreterPlugin* plugin = getPluginByName(handlerName);
+      if(plugin == NULL) {
+        Logger::getInstance()->log(std::string("EventInterpreter::loadSubscription: could not find plugin for handler-name '") + handlerName + "'", lsWarning);
+        Logger::getInstance()->log(       "EventInterpreter::loadSubscription: Still generating a subscription but w/o inner parameter", lsWarning);
+      } else {
+        opts.reset(plugin->createOptionsFromXML(_node));
+        hadOpts = true;
       }
-      opts->loadParameterFromXML(paramNode);
-    } catch(std::runtime_error& e) {
-      // only delete options created in the try-part...
-      if(!hadOpts) {
-        opts.reset();
+      try {
+        Element* paramElem = elem->getChildElement("parameter");
+        if(opts == NULL) {
+          opts.reset(new SubscriptionOptions());
+        }
+        opts->loadParameterFromXML(paramElem);
+      } catch(std::runtime_error& e) {
+        // only delete options created in the try-part...
+        if(!hadOpts) {
+          opts.reset();
+        }
       }
-    }
 
-    boost::shared_ptr<EventSubscription> subscription(new EventSubscription(evtName, handlerName, *this, opts));
-    try {
-      XMLNode& filterNode = _node.getChildByName("filter");
-      loadFilter(filterNode, *subscription);
-    } catch(std::runtime_error& e) {
-    }
+      boost::shared_ptr<EventSubscription> subscription(new EventSubscription(evtName, handlerName, *this, opts));
+      try {
+        Element* filterElem = elem->getChildElement("filter");
+        loadFilter(filterElem, *subscription);
+      } catch(std::runtime_error& e) {
+      }
 
-    subscribe(subscription);
+      subscribe(subscription);
+    }
   } // loadSubsription
 
 
@@ -684,20 +747,26 @@ namespace dss {
     m_Parameters.set(_name, _value);
   } // setParameter
 
-  void SubscriptionOptions::loadParameterFromXML(XMLNode& _node) {
-    XMLNodeList nodes = _node.getChildren();
-    for(XMLNodeList::iterator iNode = nodes.begin(); iNode != nodes.end(); ++iNode) {
-      std::string nodeName = iNode->getName();
-      if(nodeName == "parameter") {
-        std::string value;
-        std::string name;
-        if(!iNode->getChildren().empty()) {
-          value = iNode->getChildren()[0].getContent();
-        }
-        name = iNode->getAttributes()["name"];
-        if(!name.empty()) {
-          setParameter(name, value);
+  void SubscriptionOptions::loadParameterFromXML(Node* _node) {
+    if(_node !=  NULL) {
+      Node* curNode = _node->firstChild();
+      while(curNode != NULL) {
+        std::string nodeName = curNode->localName();
+        if(nodeName == "parameter") {
+          Element* elem = dynamic_cast<Element*>(curNode);
+          if(elem != NULL) {
+            std::string value;
+            std::string name;
+            if(curNode->hasChildNodes()) {
+              value = curNode->firstChild()->getNodeValue();
+            }
+            name = elem->getAttribute("name");
+            if(!name.empty()) {
+              setParameter(name, value);
+            }
+          }
         }
+        curNode = curNode->nextSibling();
       }
     }
   } // loadParameterFromXML
@@ -710,10 +779,11 @@ namespace dss {
     m_pInterpreter(_interpreter)
   { } // ctor
 
-  SubscriptionOptions* EventInterpreterPlugin::createOptionsFromXML(XMLNodeList& _nodes) {
+  SubscriptionOptions* EventInterpreterPlugin::createOptionsFromXML(Node* _node) {
     return NULL;
   } // createOptionsFromXML
 
+
   //================================================== EventPropertyFilter
 
   EventPropertyFilter::EventPropertyFilter(const std::string& _propertyName)
diff --git a/core/event.h b/core/event.h
index 77825a1..2d938a1 100644
--- a/core/event.h
+++ b/core/event.h
@@ -23,18 +23,26 @@
 #ifndef EVENT_H_
 #define EVENT_H_
 
-#include "model.h"
+#include "base.h"
+#include "datetools.h"
 #include "thread.h"
 #include "syncevent.h"
 #include "mutex.h"
-#include "xmlwrapper.h"
+#include "subsystem.h"
 
 #include <string>
 #include <queue>
+#include <vector>
 
 #include <boost/shared_ptr.hpp>
 #include <boost/ptr_container/ptr_vector.hpp>
 
+namespace Poco {
+  namespace XML {
+    class Node;
+  }
+}
+
 namespace dss {
 
   //================================================== Forward declarations
@@ -42,6 +50,8 @@ namespace dss {
   class EventInterpreter;
   class ScheduledEvent;
   class EventRunner;
+  class Zone;
+  class DeviceReference;
 
   //================================================== Class definitions
 
@@ -109,7 +119,7 @@ namespace dss {
     void setParameter(const std::string& _name, const std::string& _value);
     bool hasParameter(const std::string& _name) const;
 
-    void loadParameterFromXML(XMLNode& _node);
+    void loadParameterFromXML(Poco::XML::Node* _node);
 
     const Properties& getParameters() const { return m_Parameters; }
   }; // SubscriptionOptions
@@ -221,7 +231,7 @@ namespace dss {
     const std::string& getName() const { return m_Name; }
     virtual void handleEvent(Event& _event, const EventSubscription& _subscription) = 0;
 
-    virtual SubscriptionOptions* createOptionsFromXML(XMLNodeList& _nodes);
+    virtual SubscriptionOptions* createOptionsFromXML(Poco::XML::Node* _node);
   }; // EventInterpreterPlugin
 
 
@@ -281,14 +291,15 @@ namespace dss {
   class EventInterpreter : public Subsystem,
                            public Thread {
   private:
-    vector< boost::shared_ptr<EventSubscription> > m_Subscriptions;
-    vector<EventInterpreterPlugin*> m_Plugins;
+    std::vector< boost::shared_ptr<EventSubscription> > m_Subscriptions;
+    std::vector<EventInterpreterPlugin*> m_Plugins;
     EventQueue* m_Queue;
     EventRunner* m_EventRunner;
     int m_EventsProcessed;
   private:
-    void loadSubscription(XMLNode& _node);
-    void loadFilter(XMLNode& _node, EventSubscription& _subscription);
+    void loadSubscription(Poco::XML::Node* _node);
+    void loadFilter(Poco::XML::Node* _node, EventSubscription& _subscription);
+    void loadPropertyFilter(Poco::XML::Node* _pNode, EventSubscription& _subscription);
     boost::shared_ptr<EventSubscription> subscriptionByID(const std::string& _name);
   protected:
     virtual void doStart();
diff --git a/core/eventinterpreterplugins.cpp b/core/eventinterpreterplugins.cpp
index b7f83f7..2fd2975 100644
--- a/core/eventinterpreterplugins.cpp
+++ b/core/eventinterpreterplugins.cpp
@@ -32,10 +32,18 @@
 #include "dss.h"
 #include "scripting/modeljs.h"
 #include "core/foreach.h"
+#include "core/model/set.h"
+#include "core/model/zone.h"
 
 #include <boost/scoped_ptr.hpp>
 #include <boost/filesystem.hpp>
 
+#include <Poco/DOM/Element.h>
+#include <Poco/DOM/Node.h>
+
+using Poco::XML::Element;
+using Poco::XML::Node;
+
 namespace dss {
 
 
@@ -155,7 +163,6 @@ namespace dss {
 
   class SubscriptionOptionsDS485 : public SubscriptionOptions {
   private:
-    DS485Command m_Command;
     int m_ParameterIndex;
     int m_SceneIndex;
     std::string m_To;
@@ -165,9 +172,6 @@ namespace dss {
     : m_ParameterIndex(-1), m_SceneIndex(-1)
     { }
 
-    void setCommand(const DS485Command _value) { m_Command = _value; }
-    DS485Command getCommand() const { return m_Command; }
-
     void setParameterIndex(const int _value) { m_ParameterIndex = _value; }
     int getParameterIndex() const { return m_ParameterIndex; }
 
@@ -181,88 +185,50 @@ namespace dss {
     int getSceneIndex() const { return m_SceneIndex; }
   };
 
-  std::string EventInterpreterPluginDS485::getParameter(XMLNodeList& _nodes, const std::string& _parameterName) {
-    for(XMLNodeList::iterator iNode = _nodes.begin(), e = _nodes.end();
-        iNode != e; ++iNode)
-    {
-      if(iNode->getName() == "parameter") {
-        if(iNode->getAttributes()["name"] == _parameterName) {
-          XMLNodeList& children = iNode->getChildren();
-          if(!children.empty()) {
-            return children[0].getContent();
+  std::string EventInterpreterPluginDS485::getParameter(Node* _node, const std::string& _parameterName) {
+    Node* curNode = _node->firstChild();
+    while(curNode != NULL) {
+      if(curNode->localName() == "parameter") {
+        Element* elem = dynamic_cast<Element*>(curNode);
+        if(elem->getAttribute("name") == _parameterName) {
+          if(elem->hasChildNodes()) {
+            return elem->firstChild()->getNodeValue();
           }
         }
       }
+      curNode = curNode->nextSibling();
     }
     return "";
   } // getParameter
 
-  SubscriptionOptions* EventInterpreterPluginDS485::createOptionsFromXML(XMLNodeList& _nodes) {
+  SubscriptionOptions* EventInterpreterPluginDS485::createOptionsFromXML(Node* _node) {
     SubscriptionOptionsDS485* result = new SubscriptionOptionsDS485();
-    for(XMLNodeList::iterator iNode = _nodes.begin(), e = _nodes.end();
-        iNode != e; ++iNode)
-    {
-      if(iNode->getName() == "send") {
-        std::string typeName = iNode->getAttributes()["type"];
-        std::string paramName = "";
-        bool needParam = false;
-        if(typeName == "turnOn") {
-          result->setCommand(cmdTurnOn);
-        } else if(typeName == "turnOff") {
-          result->setCommand(cmdTurnOff);
-        } else if(typeName == "dimUp") {
-          result->setCommand(cmdStartDimUp);
-          paramName = "parameter";
-        } else if(typeName == "stopDim") {
-          result->setCommand(cmdStopDim);
-          paramName = "parameter";
-        } else if(typeName == "callScene") {
-          result->setCommand(cmdCallScene);
-          paramName = "scene";
-          needParam = true;
-        } else if(typeName == "saveScene") {
-          result->setCommand(cmdSaveScene);
-          paramName = "scene";
-          needParam = true;
-        } else if(typeName == "undoScene") {
-          result->setCommand(cmdUndoScene);
-          paramName = "scene";
-          needParam = true;
-        } else if(typeName == "increaseValue") {
-          result->setCommand(cmdIncreaseValue);
-          paramName = "parameter";
-        } else if(typeName == "decreaseValue") {
-          result->setCommand(cmdDecreaseValue);
-          paramName = "parameter";
-        } else if(typeName == "enable") {
-          result->setCommand(cmdEnable);
-        } else if(typeName == "disable") {
-          result->setCommand(cmdDisable);
-        } else if(typeName == "increaseParameter") {
-          result->setCommand(cmdIncreaseParam);
-          paramName = "parameter";
-        } else if(typeName == "decreaseParameter") {
-          result->setCommand(cmdDecreaseParam);
-          paramName = "parameter";
-        } else {
-          Logger::getInstance()->log(std::string("unknown command: ") + typeName);
-          delete result;
-          return NULL;
-        }
-
-        if(!paramName.empty()) {
-          std::string paramValue = getParameter(iNode->getChildren(), paramName);
-          if(paramValue.size() == 0 && needParam) {
-            Logger::getInstance()->log(std::string("bus_handler: Needed parameter '") + paramName + "' not found in subscription for type '" + typeName + "'", lsError);
-          }
-
-          if(paramName == "parameter") {
-            result->setParameterIndex(strToIntDef(paramValue, -1));
-          } else if(paramName == "scene") {
-            result->setSceneIndex(strToIntDef(paramValue, -1));
+    
+    Node* curNode = _node->firstChild();
+    while(curNode != NULL) {
+      if(curNode->localName() == "send") {
+        Element* elem = dynamic_cast<Element*>(curNode);
+        if(elem != NULL) {
+          std::string typeName = elem->getAttribute("type");
+          std::string paramName = "";
+          bool needParam = false;
+          // TODO: add functionality back
+
+          if(!paramName.empty()) {
+            std::string paramValue = getParameter(curNode, paramName);
+            if(paramValue.size() == 0 && needParam) {
+              Logger::getInstance()->log(std::string("bus_handler: Needed parameter '") + paramName + "' not found in subscription for type '" + typeName + "'", lsError);
+            }
+
+            if(paramName == "parameter") {
+              result->setParameterIndex(strToIntDef(paramValue, -1));
+            } else if(paramName == "scene") {
+              result->setSceneIndex(strToIntDef(paramValue, -1));
+            }
           }
         }
       }
+      curNode = curNode->nextSibling();
     }
 
     return result;
@@ -271,7 +237,7 @@ namespace dss {
   void EventInterpreterPluginDS485::handleEvent(Event& _event, const EventSubscription& _subscription) {
     const SubscriptionOptionsDS485* options = dynamic_cast<const SubscriptionOptionsDS485*>(&_subscription.getOptions());
     if(options != NULL) {
-      DS485Command cmd = options->getCommand();
+//      DS485Command cmd = options->getCommand();
 
 
       // determine location
@@ -291,18 +257,7 @@ namespace dss {
           to = _event.getRaisedAtZone().getDevices();
         }
       }
-
-      if(cmd == cmdCallScene || cmd == cmdSaveScene || cmd == cmdUndoScene) {
-        m_pInterface->sendCommand(cmd, to, options->getSceneIndex());
-      } else if(cmd == cmdIncreaseParam || cmd == cmdDecreaseParam ||
-                cmd == cmdIncreaseValue || cmd == cmdDecreaseValue ||
-                cmd == cmdStartDimUp || cmd == cmdStartDimDown || cmd == cmdStopDim)
-      {
-        m_pInterface->sendCommand(cmd, to, options->getParameterIndex());
-      } else {
-        Logger::getInstance()->log("EventInterpreterPluginDS485::handleEvent: sending...");
-        m_pInterface->sendCommand(cmd, to, 0);
-      }
+      // TODO: add functionality
     } else {
       Logger::getInstance()->log("EventInterpreterPluginDS485::handleEvent: Options are not of type SubscriptionOptionsDS485, ignoring", lsError);
     }
diff --git a/core/eventinterpreterplugins.h b/core/eventinterpreterplugins.h
index c31c9b1..722160c 100644
--- a/core/eventinterpreterplugins.h
+++ b/core/eventinterpreterplugins.h
@@ -29,6 +29,9 @@
 #include "jshandler.h"
 
 namespace dss {
+
+  class Apartment;
+  
   class EventInterpreterPluginRaiseEvent : public EventInterpreterPlugin {
   private:
     void applyOptionsWithSuffix(const SubscriptionOptions& _options, const std::string& _suffix, boost::shared_ptr<Event> _event);
@@ -56,11 +59,11 @@ namespace dss {
   private:
     DS485Interface* m_pInterface;
     Apartment& m_Apartment;
-    std::string getParameter(XMLNodeList& _nodes, const std::string& _parameterName);
+    std::string getParameter(Poco::XML::Node* _node, const std::string& _parameterName);
   public:
     EventInterpreterPluginDS485(Apartment& _apartment, DS485Interface* _pInterface, EventInterpreter* _pInterpreter);
 
-    virtual SubscriptionOptions* createOptionsFromXML(XMLNodeList& _nodes);
+    virtual SubscriptionOptions* createOptionsFromXML(Poco::XML::Node* _node);
 
     virtual void handleEvent(Event& _event, const EventSubscription& _subscription);
   }; // EventInterpreterPluginDS485
diff --git a/core/jshandler.cpp b/core/jshandler.cpp
index bad10fe..f2e0e07 100644
--- a/core/jshandler.cpp
+++ b/core/jshandler.cpp
@@ -163,7 +163,7 @@ namespace dss {
   JSFunctionSpec global_methods[] = {
     {"print", global_print, 1, 0, 0},
     {"keepContext", global_keepContext, 0, 0, 0},
-    {NULL},
+    JS_FS_END
   };
 
   ScriptContext::ScriptContext(ScriptEnvironment& _env, JSContext* _pContext)
@@ -213,11 +213,6 @@ namespace dss {
   } // removeAttachedObject
 
   template<>
-  jsval ScriptContext::convertTo(const jsval& _val) {
-    return _val;
-  } // convertTo<jsval>
- 
-  template<>
   int ScriptContext::convertTo(const jsval& _val) {
     if(JSVAL_IS_NUMBER(_val)) {
       int result;
@@ -277,8 +272,7 @@ namespace dss {
     return false;
   } // raisePendingExceptions
 
-  template <>
-  jsval ScriptContext::evaluateScript(const std::string& _fileName) {
+  jsval ScriptContext::doEvaluateScript(const std::string& _fileName) {
     AssertLocked(this);
 
     std::ifstream in(_fileName.c_str());
@@ -297,35 +291,34 @@ namespace dss {
       raisePendingExceptions();
       throw ScriptException("Error executing script");
     }
-  } // evaluateScript
+  } // doEvaluateScript
 
   template <>
   void ScriptContext::evaluateScript(const std::string& _script) {
-    evaluateScript<jsval>(_script);
+    doEvaluateScript(_script);
   } // evaluateScript<void>
 
   template <>
   int ScriptContext::evaluateScript(const std::string& _script) {
-    return convertTo<int>(evaluateScript<jsval>(_script));
+    return convertTo<int>(doEvaluateScript(_script));
   } // evaluateScript<int>
 
   template <>
   double ScriptContext::evaluateScript(const std::string& _script) {
-    return convertTo<double>(evaluateScript<jsval>(_script));
+    return convertTo<double>(doEvaluateScript(_script));
   } // evaluateScript<double>
 
   template <>
   std::string ScriptContext::evaluateScript(const std::string& _script) {
-    return convertTo<std::string>(evaluateScript<jsval>(_script));
+    return convertTo<std::string>(doEvaluateScript(_script));
   } // evaluateScript<std::string>
 
   template <>
   bool ScriptContext::evaluateScript(const std::string& _script) {
-    return convertTo<bool>(evaluateScript<jsval>(_script));
+    return convertTo<bool>(doEvaluateScript(_script));
   } // evaluateScript<bool>
 
-  template <>
-  jsval ScriptContext::evaluate(const std::string& _script) {
+  jsval ScriptContext::doEvaluate(const std::string& _script) {
     AssertLocked(this);
 
     const char* filename = "temporary_script";
@@ -338,31 +331,31 @@ namespace dss {
       raisePendingExceptions();
       throw ScriptException("Error executing script");
     }
-  } // evaluate
+  } // doEvaluate
   
   template <>
   void ScriptContext::evaluate(const std::string& _script) {
-    evaluate<jsval>(_script);
+    doEvaluate(_script);
   } // evaluate<void>
 
   template <>
   int ScriptContext::evaluate(const std::string& _script) {
-    return convertTo<int>(evaluate<jsval>(_script));
+    return convertTo<int>(doEvaluate(_script));
   } // evaluate<int>
 
   template <>
   double ScriptContext::evaluate(const std::string& _script) {
-    return convertTo<double>(evaluate<jsval>(_script));
+    return convertTo<double>(doEvaluate(_script));
   } // evaluate<double>
 
   template <>
   std::string ScriptContext::evaluate(const std::string& _script) {
-    return convertTo<std::string>(evaluate<jsval>(_script));
+    return convertTo<std::string>(doEvaluate(_script));
   } // evaluate<std::string>
 
   template <>
   bool ScriptContext::evaluate(const std::string& _script) {
-    return convertTo<bool>(evaluate<jsval>(_script));
+    return convertTo<bool>(doEvaluate(_script));
   } // evaluate<bool>
 
 
@@ -372,11 +365,6 @@ namespace dss {
   //================================================== ScriptFunctionParameterList
 
   template<>
-  void ScriptFunctionParameterList::add(jsval _value) {
-    m_Parameter.push_back(_value);
-  } // add<jsval>
-
-  template<>
   void ScriptFunctionParameterList::add(int _value) {
     m_Parameter.push_back(INT_TO_JSVAL(_value));
   } // add<int>
@@ -388,7 +376,11 @@ namespace dss {
 
   template<>
   void ScriptFunctionParameterList::add(double _value) {
-    m_Parameter.push_back(DOUBLE_TO_JSVAL(_value));
+    jsval val;
+    if(JS_NewNumberValue(m_Context.getJSContext(), _value, &val) == JS_TRUE) {
+      m_Parameter.push_back(val);
+    }
+    throw ScriptException("ScriptFunctionParameterList::add<double>: Could not allocate double value");
   } // add<double>
 
   template<>
@@ -432,8 +424,7 @@ namespace dss {
     m_pObject = JS_NewObject(m_Context.getJSContext(), NULL, NULL, parentObj);
   } // ctor
 
-  template<>
-  jsval ScriptObject::getProperty(const std::string& _name) {
+  jsval ScriptObject::doGetProperty(const std::string& _name) {
     AssertLocked objLock(&m_Context);
     JSBool found;
     if(!JS_HasProperty(m_Context.getJSContext(), m_pObject, _name.c_str(), &found)) {
@@ -449,41 +440,40 @@ namespace dss {
     } else {
       throw ScriptException(std::string("Could not find property ") + _name);
     }
-  } // getProperty<jsval>
+  } // doGetProperty
 
   template<>
   std::string ScriptObject::getProperty(const std::string& _name) {
-    jsval value = getProperty<jsval>(_name);
+    jsval value = doGetProperty(_name);
     return m_Context.convertTo<std::string>(value);
   } // getProperty<string>
 
   template<>
   int ScriptObject::getProperty(const std::string& _name) {
-    jsval value = getProperty<jsval>(_name);
+    jsval value = doGetProperty(_name);
     return m_Context.convertTo<int>(value);
   } // getProperty<string>
 
   template<>
   double ScriptObject::getProperty(const std::string& _name) {
-    jsval value = getProperty<jsval>(_name);
+    jsval value = doGetProperty(_name);
     return m_Context.convertTo<double>(value);
   } // getProperty<double>
 
   template<>
   bool ScriptObject::getProperty(const std::string& _name) {
-    jsval value = getProperty<jsval>(_name);
+    jsval value = doGetProperty(_name);
     return m_Context.convertTo<bool>(value);
   } // getProperty<bool>
 
-  template<>
-  void ScriptObject::setProperty(const std::string& _name, jsval _value) {
+  void ScriptObject::doSetProperty(const std::string& _name, jsval _value) {
     JS_SetProperty(m_Context.getJSContext(), m_pObject, _name.c_str(), &_value);
-  } // setProperty<jsval>
+  } // doSetProperty
 
   template<>
   void ScriptObject::setProperty(const std::string& _name, const std::string& _value) {
     JSString* str = JS_NewStringCopyN(m_Context.getJSContext(), _value.c_str(), _value.size());
-    setProperty(_name, STRING_TO_JSVAL(str));
+    doSetProperty(_name, STRING_TO_JSVAL(str));
   } // setProperty<std::string>
 
   template<>
@@ -498,13 +488,13 @@ namespace dss {
     if(!JS_NewNumberValue(m_Context.getJSContext(), _value, &val)) {
       throw ScriptException("could not allocate number");
     }
-    setProperty(_name, val);
+    doSetProperty(_name, val);
   } // setProperty<int>
 
   template<>
   void ScriptObject::setProperty(const std::string& _name, ScriptObject* _value) {
     assert(_value != NULL);
-    setProperty(_name, OBJECT_TO_JSVAL(_value->m_pObject));
+    doSetProperty(_name, OBJECT_TO_JSVAL(_value->m_pObject));
   } // setProperty<ScriptObject>
 
   bool ScriptObject::is(const std::string& _className) {
@@ -515,8 +505,7 @@ namespace dss {
     return getProperty<std::string>("className");
   } // getClassName
 
-  template<>
-  jsval ScriptObject::callFunctionByName(const std::string& _functionName,
+  jsval ScriptObject::doCallFunctionByName(const std::string& _functionName,
                                          ScriptFunctionParameterList& _parameter) {
     AssertLocked objLock(&m_Context);
     int paramc = _parameter.size();
@@ -533,40 +522,39 @@ namespace dss {
       m_Context.raisePendingExceptions();
       throw ScriptException("Error running function");
     }
-  } // callFunctionByName<jsval>
+  } // doCallFunctionByName
 
   template<>
   void ScriptObject::callFunctionByName(const std::string& _functionName,
                                                 ScriptFunctionParameterList& _parameter) {
-    callFunctionByName<jsval>(_functionName, _parameter);
+    doCallFunctionByName(_functionName, _parameter);
   } // callFunctionByName<void>
 
   template<>
   int ScriptObject::callFunctionByName(const std::string& _functionName,
                                                 ScriptFunctionParameterList& _parameter) {
-    return m_Context.convertTo<int>(callFunctionByName<jsval>(_functionName, _parameter));
+    return m_Context.convertTo<int>(doCallFunctionByName(_functionName, _parameter));
   } // callFunctionByName<int>
 
   template<>
   double ScriptObject::callFunctionByName(const std::string& _functionName,
                                                 ScriptFunctionParameterList& _parameter) {
-    return m_Context.convertTo<double>(callFunctionByName<jsval>(_functionName, _parameter));
+    return m_Context.convertTo<double>(doCallFunctionByName(_functionName, _parameter));
   } // callFunctionByName<double>
 
   template<>
   bool ScriptObject::callFunctionByName(const std::string& _functionName,
                                                 ScriptFunctionParameterList& _parameter) {
-    return m_Context.convertTo<bool>(callFunctionByName<jsval>(_functionName, _parameter));
+    return m_Context.convertTo<bool>(doCallFunctionByName(_functionName, _parameter));
   } // callFunctionByName<bool>
 
   template<>
   std::string ScriptObject::callFunctionByName(const std::string& _functionName,
                                                 ScriptFunctionParameterList& _parameter) {
-    return m_Context.convertTo<std::string>(callFunctionByName<jsval>(_functionName, _parameter));
+    return m_Context.convertTo<std::string>(doCallFunctionByName(_functionName, _parameter));
   } // callFunctionByName<std::string>
 
-  template<>
-  jsval ScriptObject::callFunctionByReference(jsval _function,
+  jsval ScriptObject::doCallFunctionByReference(jsval _function,
                                               ScriptFunctionParameterList& _parameter) {
     AssertLocked objLock(&m_Context);
     int paramc = _parameter.size();
@@ -583,36 +571,36 @@ namespace dss {
       m_Context.raisePendingExceptions();
       throw ScriptException("Error running function");
     }
-  } // callFunctionByReference<jsval>
+  } // doCallFunctionByReference
 
   template<>
   void ScriptObject::callFunctionByReference(jsval _function,
                                              ScriptFunctionParameterList& _parameter) {
-    callFunctionByReference<jsval>(_function, _parameter);
+    doCallFunctionByReference(_function, _parameter);
   } // callFunctionByReference<void>
 
   template<>
   int ScriptObject::callFunctionByReference(jsval _function,
                                             ScriptFunctionParameterList& _parameter) {
-    return m_Context.convertTo<int>(callFunctionByReference<jsval>(_function, _parameter));
+    return m_Context.convertTo<int>(doCallFunctionByReference(_function, _parameter));
   } // callFunctionByReference<int>
 
   template<>
   double ScriptObject::callFunctionByReference(jsval _function,
                                                ScriptFunctionParameterList& _parameter) {
-    return m_Context.convertTo<double>(callFunctionByReference<jsval>(_function, _parameter));
+    return m_Context.convertTo<double>(doCallFunctionByReference(_function, _parameter));
   } // callFunctionByReference<double>
 
   template<>
   bool ScriptObject::callFunctionByReference(jsval _function,
                                              ScriptFunctionParameterList& _parameter) {
-    return m_Context.convertTo<bool>(callFunctionByReference<jsval>(_function, _parameter));
+    return m_Context.convertTo<bool>(doCallFunctionByReference(_function, _parameter));
   } // callFunctionByReference<bool>
 
   template<>
   std::string ScriptObject::callFunctionByReference(jsval _function,
                                                     ScriptFunctionParameterList& _parameter) {
-    return m_Context.convertTo<std::string>(callFunctionByReference<jsval>(_function, _parameter));
+    return m_Context.convertTo<std::string>(doCallFunctionByReference(_function, _parameter));
   } // callFunctionByReference<std::string>
 
 } // namespace dss
diff --git a/core/jshandler.h b/core/jshandler.h
index 1f44770..ce22ac0 100644
--- a/core/jshandler.h
+++ b/core/jshandler.h
@@ -28,12 +28,14 @@
 
 #include <iostream>
 
-#define JS_THREADSAFE
-
-#ifdef HAVE_MOZJS_JSAPI_H
+#if defined(HAVE_JSAPI_H)
+#include <jsapi.h>
+#elif defined(HAVE_MOZJS_JSAPI_H)
 #include <mozjs/jsapi.h>
-#else
+#elif defined(HAVE_JS_JSAPI_H)
 #include <js/jsapi.h>
+#else
+#error Could not find spidermonkey
 #endif
 
 #include <boost/ptr_container/ptr_vector.hpp>
@@ -89,6 +91,7 @@ namespace dss {
     bool m_KeepContext;
     std::vector<ScriptContextAttachedObject*> m_AttachedObjects;
     static void jsErrorHandler(JSContext *ctx, const char *msg, JSErrorReport *er);
+    jsval doEvaluateScript(const std::string& _fileName);
   public:
     ScriptContext(ScriptEnvironment& _env, JSContext* _pContext);
     virtual ~ScriptContext();
@@ -96,6 +99,8 @@ namespace dss {
     /** Evaluates the given script */  
     template <class t>
     t evaluate(const std::string& _script);
+    // FIXME: Workaround a compiler issue that interprets typeof jsval == typeof int
+    jsval doEvaluate(const std::string& _script);
 
     /** Evaluates the given file */
     template <class t>
@@ -189,6 +194,9 @@ namespace dss {
   private:
     JSObject* m_pObject;
     ScriptContext& m_Context;
+    jsval doGetProperty(const std::string& _name);
+    void doSetProperty(const std::string& _name, jsval _value);
+    jsval doCallFunctionByReference(jsval _function, ScriptFunctionParameterList& _parameter);
   public:
     ScriptObject(JSObject* _pObject, ScriptContext& _context);
     ScriptObject(ScriptContext& _context, ScriptObject* _pParent);
@@ -212,6 +220,8 @@ namespace dss {
 
     template<class t>
     t callFunctionByName(const std::string& _functionName, ScriptFunctionParameterList& _parameter);
+    // FIXME: work around a compiler issue (typeof jsval == typeof int)
+    jsval doCallFunctionByName(const std::string& _functionName, ScriptFunctionParameterList& _parameter);
 
     template<class t>
     t callFunctionByReference(jsval _function, ScriptFunctionParameterList& _parameter);
@@ -226,6 +236,38 @@ namespace dss {
     }
   }; // ScriptContextAttachedObject
 
+
+/*
+ * Initializer macro for a JSFunctionSpec array element. This is the original
+ * kind of native function specifier initializer. Use JS_FN ("fast native", see
+ * JSFastNative in jspubtd.h) for all functions that do not need a stack frame
+ * when activated.
+ */
+#ifndef JS_FS
+#define JS_FS(name,call,nargs,flags,extra)                                    \
+    {name, call, nargs, flags, extra}
+#endif
+
+/*
+ * "Fast native" initializer macro for a JSFunctionSpec array element. Use this
+ * in preference to JS_FS if the native in question does not need its own stack
+ * frame when activated.
+ */
+#ifndef JS_FN
+#define JS_FN(name,fastcall,nargs,flags)                                      \
+    JS_FS(name, (JSNative)(fastcall), nargs,                                  \
+          (flags) | JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS, 0)
+#endif
+
+/*
+ * Terminating sentinel initializer to put at the end of a JSFunctionSpec array
+ * that's passed to JS_DefineFunctions or JS_InitClass.
+ */
+#ifndef JS_FS_END
+#define JS_FS_END JS_FS(NULL,NULL,0,0,0)
+#endif
+
+
 } // namespace dss
 
 #endif
diff --git a/core/metering/fake_meter.cpp b/core/metering/fake_meter.cpp
index 08d61b9..63dc148 100644
--- a/core/metering/fake_meter.cpp
+++ b/core/metering/fake_meter.cpp
@@ -24,8 +24,9 @@
 #include "core/dss.h"
 #include "core/propertysystem.h"
 #include "seriespersistence.h"
-#include "core/model.h"
 #include "core/foreach.h"
+#include "core/model/apartment.h"
+#include "core/model/modulator.h"
 
 #include <cmath>
 
diff --git a/core/metering/metering.cpp b/core/metering/metering.cpp
index 7984070..7521023 100644
--- a/core/metering/metering.cpp
+++ b/core/metering/metering.cpp
@@ -27,6 +27,8 @@
 #include "core/propertysystem.h"
 #include "seriespersistence.h"
 #include "core/foreach.h"
+#include "core/model/modulator.h"
+#include "core/model/apartment.h"
 
 #include <boost/filesystem.hpp>
 
@@ -87,7 +89,7 @@ namespace dss {
       Timestamp checkingModulator;
       Timestamp startedLoading;
 #endif
-      vector<boost::shared_ptr<Series<CurrentValue> > > series;
+      std::vector<boost::shared_ptr<Series<CurrentValue> > > series;
       for(int iConfig = 0; iConfig < _config->size(); iConfig++) {
         // Load series from file
         std::string fileName = m_MeteringStorageLocation + (*ipModulator)->getDSID().toString() + "_" + _config->getFilenameSuffix(iConfig) + ".xml";
@@ -117,7 +119,7 @@ namespace dss {
 #endif
 
       // stitch up chain
-      for(vector<boost::shared_ptr<Series<CurrentValue> > >::reverse_iterator iSeries = series.rbegin(), e = series.rend();
+      for(std::vector<boost::shared_ptr<Series<CurrentValue> > >::reverse_iterator iSeries = series.rbegin(), e = series.rend();
           iSeries != e; ++iSeries)
       {
         if(iSeries != series.rbegin()) {
diff --git a/core/model.cpp b/core/model.cpp
deleted file mode 100644
index 7aefe10..0000000
--- a/core/model.cpp
+++ /dev/null
@@ -1,2337 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 "model.h"
-#include "DS485Interface.h"
-
-#include "ds485const.h"
-#include "dss.h"
-#include "logger.h"
-#include "propertysystem.h"
-#include "event.h"
-
-#include "foreach.h"
-
-#include <fstream>
-
-#include <boost/filesystem.hpp>
-
-#include <Poco/DOM/Document.h>
-#include <Poco/DOM/Element.h>
-#include <Poco/DOM/Node.h>
-#include <Poco/DOM/Attr.h>
-#include <Poco/DOM/Text.h>
-#include <Poco/DOM/ProcessingInstruction.h>
-#include <Poco/DOM/AutoPtr.h>
-#include <Poco/DOM/DOMWriter.h>
-#include <Poco/DOM/DOMParser.h>
-#include <Poco/XML/XMLWriter.h>
-#include <Poco/SAX/InputSource.h>
-
-using Poco::XML::Document;
-using Poco::XML::Element;
-using Poco::XML::Attr;
-using Poco::XML::Text;
-using Poco::XML::ProcessingInstruction;
-using Poco::XML::AutoPtr;
-using Poco::XML::DOMWriter;
-using Poco::XML::DOMParser;
-using Poco::XML::XMLWriter;
-using Poco::XML::InputSource;
-using Poco::XML::Node;
-
-namespace dss {
-
-
-  //================================================== Device
-
-  const devid_t ShortAddressStaleDevice = 0xFFFF;
-
-  Device::Device(dsid_t _dsid, Apartment* _pApartment)
-  : m_DSID(_dsid),
-    m_ShortAddress(ShortAddressStaleDevice),
-    m_ZoneID(0),
-    m_pApartment(_pApartment),
-    m_FunctionID(0),
-    m_LastCalledScene(SceneOff),
-    m_Consumption(0),
-    m_LastDiscovered(DateTime::NullDate),
-    m_FirstSeen(DateTime::NullDate)
-  { } // ctor
-
-  void Device::publishToPropertyTree() {
-    if(m_pPropertyNode == NULL) {
-      if(m_pApartment->getPropertyNode() != NULL) {
-        m_pPropertyNode = m_pApartment->getPropertyNode()->createProperty("zones/zone0/" + m_DSID.toString());
-//        m_pPropertyNode->createProperty("name")->linkToProxy(PropertyProxyMemberFunction<Device, std::string>(*this, &Device::getName, &Device::setName));
-        m_pPropertyNode->createProperty("name")->linkToProxy(PropertyProxyReference<std::string>(m_Name));
-        m_pPropertyNode->createProperty("ModulatorID")->linkToProxy(PropertyProxyReference<int>(m_ModulatorID, false));
-        m_pPropertyNode->createProperty("ZoneID")->linkToProxy(PropertyProxyReference<int>(m_ZoneID, false));
-        if(m_pPropertyNode->getProperty("interrupt/mode") == NULL) {
-          PropertyNodePtr interruptNode = m_pPropertyNode->createProperty("interrupt");
-          interruptNode->setFlag(PropertyNode::Archive, true);
-          PropertyNodePtr interruptModeNode = interruptNode->createProperty("mode");
-          interruptModeNode->setStringValue("ignore");
-          interruptModeNode->setFlag(PropertyNode::Archive, true);
-        }
-      }
-    }
-  } // publishToPropertyTree
-
-  void Device::turnOn() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdTurnOn, *this);
-  } // turnOn
-
-  void Device::turnOff() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdTurnOff, *this);
-  } // turnOff
-
-  void Device::increaseValue(const int _parameterNr) {
-    if(_parameterNr == -1) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdIncreaseValue, *this);
-    } else {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdIncreaseParam, *this);
-    }
-  } // increaseValue
-
-  void Device::decreaseValue(const int _parameterNr) {
-    if(_parameterNr == -1) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdDecreaseValue, *this);
-    } else {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdDecreaseParam, *this);
-    }
-  } // decreaseValue
-
-  void Device::enable() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdEnable, *this);
-  } // enable
-
-  void Device::disable() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdDisable, *this);
-  } // disable
-
-  void Device::startDim(const bool _directionUp, const int _parameterNr) {
-    if(_directionUp) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdStartDimUp, *this);
-    } else {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdStartDimDown, *this);
-    }
-  } // startDim
-
-  void Device::endDim(const int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdStopDim, *this);
-  } // endDim
-
-  bool Device::isOn() const {
-    return (m_LastCalledScene != SceneOff) &&
-           (m_LastCalledScene != SceneMin) &&
-           (m_LastCalledScene != SceneDeepOff) &&
-           (m_LastCalledScene != SceneStandBy);
-  } // isOn
-
-  int Device::getFunctionID() const {
-    return m_FunctionID;
-  } // getFunctionID
-
-  void Device::setFunctionID(const int _value) {
-    m_FunctionID = _value;
-  } // setFunctionID
-
-  bool Device::hasSwitch() const {
-    return getFunctionID() == FunctionIDSwitch;
-  } // hasSwitch
-
-  void Device::setValue(const double _value, const int _parameterNr) {
-    if(_parameterNr == -1) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdSetValue, *this, static_cast<int>(_value));
-    } else {
-      DSS::getInstance()->getDS485Interface().setValueDevice(*this, (int)_value, _parameterNr, 1);
-    }
-  } // setValue
-
-  void Device::setRawValue(const uint16_t _value, const int _parameterNr, const int _size) {
-    DSS::getInstance()->getDS485Interface().setValueDevice(*this, _value, _parameterNr, _size);
-  } // setRawValue
-
-  double Device::getValue(const int _parameterNr) {
-    vector<int> res = DSS::getInstance()->getDS485Interface().sendCommand(cmdGetValue, *this, _parameterNr);
-    return res.front();
-  } // getValue
-
-  void Device::callScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdCallScene, *this, _sceneNr);
-  } // callScene
-
-  void Device::saveScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdSaveScene, *this, _sceneNr);
-  } // saveScene
-
-  void Device::undoScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdUndoScene, *this, _sceneNr);
-  } // undoScene
-
-  void Device::nextScene() {
-    callScene(SceneHelper::getNextScene(m_LastCalledScene));
-  } // nextScene
-
-  void Device::previousScene() {
-    callScene(SceneHelper::getNextScene(m_LastCalledScene));
-  } // previousScene
-
-  std::string Device::getName() const {
-    return m_Name;
-  } // getName
-
-  void Device::setName(const std::string& _name) {
-    if(m_Name != _name) {
-      m_Name = _name;
-      dirty();
-    }
-  } // setName
-
-  void Device::dirty() {
-    if(m_pApartment != NULL) {
-      m_pApartment->addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
-    }
-  } // dirty
-
-  bool Device::operator==(const Device& _other) const {
-    return _other.m_DSID == m_DSID;
-  } // operator==
-
-  devid_t Device::getShortAddress() const {
-    return m_ShortAddress;
-  } // getShortAddress
-
-  void Device::setShortAddress(const devid_t _shortAddress) {
-    m_ShortAddress = _shortAddress;
-    publishToPropertyTree();
-    m_LastDiscovered = DateTime();
-  } // setShortAddress
-
-  dsid_t Device::getDSID() const {
-    return m_DSID;
-  } // getDSID;
-
-  int Device::getModulatorID() const {
-    return m_ModulatorID;
-  } // getModulatorID
-
-  void Device::setModulatorID(const int _modulatorID) {
-    m_ModulatorID = _modulatorID;
-  } // setModulatorID
-
-  int Device::getZoneID() const {
-  	return m_ZoneID;
-  } // getZoneID
-
-  void Device::setZoneID(const int _value) {
-    if(_value != m_ZoneID) {
-      m_ZoneID = _value;
-      if((m_pPropertyNode != NULL) && (m_pApartment->getPropertyNode() != NULL)) {
-        std::string basePath = "zones/zone" + intToString(m_ZoneID);
-        if(m_pAliasNode == NULL) {
-          PropertyNodePtr node = m_pApartment->getPropertyNode()->getProperty(basePath + "/" + m_DSID.toString());
-          if(node != NULL) {
-            Logger::getInstance()->log("Device::setZoneID: Target node for device " + m_DSID.toString() + " already exists", lsError);
-            if(node->size() > 0) {
-              Logger::getInstance()->log("Device::setZoneID: Target node for device " + m_DSID.toString() + " has children", lsFatal);
-              return;
-            }
-          }
-          m_pAliasNode = m_pApartment->getPropertyNode()->createProperty(basePath + "/" + m_DSID.toString());
-          
-          m_pAliasNode->alias(m_pPropertyNode);
-        } else {
-          PropertyNodePtr base = m_pApartment->getPropertyNode()->getProperty(basePath);
-          if(base == NULL) {
-            throw std::runtime_error("PropertyNode of the new zone does not exist");
-          }
-          base->addChild(m_pAliasNode);
-        }
-      }
-    }
-  } // setZoneID
-
-  int Device:: getGroupIdByIndex(const int _index) const {
-    return m_Groups[_index];
-  } // getGroupIdByIndex
-
-  Group& Device::getGroupByIndex(const int _index) {
-    return m_pApartment->getGroup(getGroupIdByIndex(_index));
-  } // getGroupByIndex
-
-  void Device::addToGroup(const int _groupID) {
-    m_GroupBitmask.set(_groupID-1);
-    if(find(m_Groups.begin(), m_Groups.end(), _groupID) == m_Groups.end()) {
-      m_Groups.push_back(_groupID);
-    } else {
-      Logger::getInstance()->log("Device " + m_DSID.toString() + " (bus: " + intToString(m_ShortAddress) + ", zone: " + intToString(m_ZoneID) + ") is already in group " + intToString(_groupID));
-    }
-  } // addToGroup
-
-  void Device::removeFromGroup(const int _groupID) {
-    m_GroupBitmask.reset(_groupID-1);
-    std::vector<int>::iterator it = find(m_Groups.begin(), m_Groups.end(), _groupID);
-    if(it != m_Groups.end()) {
-      m_Groups.erase(it);
-    }
-  } // removeFromGroup
-
-  void Device::resetGroups() {
-    m_GroupBitmask.reset();
-    m_Groups.clear();
-  } // resetGroups
-
-  int Device::getGroupsCount() const {
-    return m_Groups.size();
-  } // getGroupsCount
-
-  std::bitset<63>& Device::getGroupBitmask() {
-    return m_GroupBitmask;
-  } // getGroupBitmask
-
-  const std::bitset<63>& Device::getGroupBitmask() const {
-    return m_GroupBitmask;
-  } // getGroupBitmask
-
-  bool Device::isInGroup(const int _groupID) const {
-    return (_groupID == 0) || m_GroupBitmask.test(_groupID - 1);
-  } // isInGroup
-
-  Apartment& Device::getApartment() const {
-    return *m_pApartment;
-  } // getApartment
-
-  unsigned long Device::getPowerConsumption() {
-    return m_Consumption;
-  } // getPowerConsumption
-
-  uint8_t Device::dsLinkSend(uint8_t _value, bool _lastByte, bool _writeOnly) {
-    uint8_t flags = 0;
-    if(_lastByte) {
-      flags |= DSLinkSendLastByte;
-    }
-    if(_writeOnly) {
-      flags |= DSLinkSendWriteOnly;
-    }
-    return DSS::getInstance()->getDS485Interface().dSLinkSend(m_ModulatorID, m_ShortAddress, _value, flags);
-  } // dsLinkSend
-
-  int Device::getSensorValue(const int _sensorID) {
-    return DSS::getInstance()->getDS485Interface().getSensorValue(*this,_sensorID);
-  } // getSensorValue
-
-  //================================================== Set
-
-  Set::Set() {
-  } // ctor
-
-  Set::Set(Device& _device) {
-    m_ContainedDevices.push_back(DeviceReference(_device, _device.getApartment()));
-  } // ctor(Device)
-
-  Set::Set(DeviceVector _devices) {
-    m_ContainedDevices = _devices;
-  } // ctor(DeviceVector)
-
-  Set::Set(const Set& _copy) {
-    m_ContainedDevices = _copy.m_ContainedDevices;
-  }
-
-  void Set::turnOn() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdTurnOn, *this);
-  } // turnOn
-
-  void Set::turnOff() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdTurnOff, *this);
-  } // turnOff
-
-  void Set::increaseValue(const int _parameterNr) {
-    if(_parameterNr == -1) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdIncreaseValue, *this);
-    } else {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdIncreaseParam, *this);
-    }
-  } // increaseValue
-
-  void Set::decreaseValue(const int _parameterNr) {
-    if(_parameterNr == -1) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdDecreaseValue, *this);
-    } else {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdDecreaseParam, *this);
-    }
-  } // decreaseValue
-
-  void Set::enable() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdEnable, *this);
-  } // enable
-
-  void Set::disable() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdDisable, *this);
-  } // disable
-
-  void Set::startDim(bool _directionUp, const int _parameterNr) {
-    if(_directionUp) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdStartDimUp, *this);
-    } else {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdStartDimDown, *this);
-    }
-  } // startDim
-
-  void Set::endDim(const int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdStopDim, *this);
-  } // endDim
-
-  void Set::setValue(const double _value, int _parameterNr) {
-    if(_parameterNr == -1) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdSetValue, *this, (int)_value);
-    } else {
-      throw std::runtime_error("Can't set arbitrary parameter on a set");
-    }
-  } // setValue
-
-  void Set::callScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdCallScene, *this, _sceneNr);
-  } // callScene
-
-  void Set::saveScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdSaveScene, *this, _sceneNr);
-  } // saveScene
-
-  void Set::undoScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdUndoScene, *this, _sceneNr);
-  } // undoScene
-
-  void Set::nextScene() {
-    throw std::runtime_error("Not yet implemented");
-  } // nextScene
-
-  void Set::previousScene() {
-    throw std::runtime_error("Not yet implemented");
-  } // previousScene
-
-  void Set::perform(IDeviceAction& _deviceAction) {
-    for(DeviceIterator iDevice = m_ContainedDevices.begin(); iDevice != m_ContainedDevices.end(); ++iDevice) {
-      _deviceAction.perform(iDevice->getDevice());
-    }
-  } // perform
-
-  Set Set::getSubset(const IDeviceSelector& _selector) const {
-    Set result;
-    foreach(DeviceReference iDevice, m_ContainedDevices) {
-      if(_selector.selectDevice(iDevice.getDevice())) {
-        result.addDevice(iDevice);
-      }
-    }
-    return result;
-  } // getSubset
-
-  class ByGroupSelector : public IDeviceSelector {
-  private:
-    const int m_GroupNr;
-  public:
-    ByGroupSelector(const int _groupNr)
-    : m_GroupNr(_groupNr)
-    {}
-
-    virtual ~ByGroupSelector() {}
-
-    virtual bool selectDevice(const Device& _device) const {
-      return _device.isInGroup(m_GroupNr);
-    }
-  };
-
-  Set Set::getByGroup(int _groupNr) const {
-    if(_groupNr != GroupIDBroadcast) {
-      return getSubset(ByGroupSelector(_groupNr));
-    } else {
-      return *this;
-    }
-  } // getByGroup(id)
-
-  Set Set::getByGroup(const Group& _group) const {
-    return getByGroup(_group.getID());
-  } // getByGroup(ref)
-
-  Set Set::getByGroup(const std::string& _name) const {
-    Set result;
-    if(isEmpty()) {
-      return result;
-    } else {
-      Group& g = get(0).getDevice().getApartment().getGroup(_name);
-      return getByGroup(g.getID());
-    }
-  } // getByGroup(name)
-
-  Set Set::getByZone(int _zoneID) const {
-    if(_zoneID != 0) {
-      Set result;
-      foreach(const DeviceReference& dev, m_ContainedDevices) {
-        if(dev.getDevice().getZoneID() == _zoneID) {
-          result.addDevice(dev);
-        }
-      }
-      return result;
-    } else {
-      // return a copy of this set if the broadcast zone was requested
-      return *this;
-    }
-  } // getByZone(id)
-
-  Set Set::getByZone(const std::string& _zoneName) const {
-    Set result;
-    if(isEmpty()) {
-      return result;
-    } else {
-      Zone& zone = get(0).getDevice().getApartment().getZone(_zoneName);
-      return getByZone(zone.getID());
-    }
-  } // getByZone(name)
-
-  Set Set::getByModulator(const int _modulatorID) const {
-    Set result;
-    foreach(const DeviceReference& dev, m_ContainedDevices) {
-      if(dev.getDevice().getModulatorID() == _modulatorID) {
-        result.addDevice(dev);
-      }
-    }
-    return result;
-  } // getByModulator
-
-  Set Set::getByModulator(const Modulator& _modulator) const {
-    return getByModulator(_modulator.getBusID());
-  } // getByModulator
-
-  Set Set::getByFunctionID(const int _functionID) const {
-    Set result;
-    foreach(const DeviceReference& dev, m_ContainedDevices) {
-      if(dev.getDevice().getFunctionID() == _functionID) {
-        result.addDevice(dev);
-      }
-    }
-    return result;
-  } // getByFunctionID
-
-  Set Set::getByPresence(const bool _presence) const {
-    Set result;
-    foreach(const DeviceReference& dev, m_ContainedDevices) {
-      if(dev.getDevice().isPresent()== _presence) {
-        result.addDevice(dev);
-      }
-    }
-    return result;
-  } // getByPresence
-
-  class ByNameSelector : public IDeviceSelector {
-  private:
-    const std::string m_Name;
-  public:
-    ByNameSelector(const std::string& _name) : m_Name(_name) {};
-    virtual ~ByNameSelector() {};
-
-    virtual bool selectDevice(const Device& _device) const {
-      return _device.getName() == m_Name;
-    }
-  };
-
-  DeviceReference Set::getByName(const std::string& _name) const {
-    Set resultSet = getSubset(ByNameSelector(_name));
-    if(resultSet.length() == 0) {
-      throw ItemNotFoundException(_name);
-    }
-    return resultSet.m_ContainedDevices.front();
-  } // getByName
-
-
-  class ByIDSelector : public IDeviceSelector {
-  private:
-    const devid_t m_ID;
-  public:
-    ByIDSelector(const devid_t _id) : m_ID(_id) {}
-    virtual ~ByIDSelector() {};
-
-    virtual bool selectDevice(const Device& _device) const {
-      return _device.getShortAddress() == m_ID;
-    }
-  };
-
-  DeviceReference Set::getByBusID(const devid_t _id) const {
-    Set resultSet = getSubset(ByIDSelector(_id));
-    if(resultSet.length() == 0) {
-      throw ItemNotFoundException(std::string("with busid ") + intToString(_id));
-    }
-    return resultSet.m_ContainedDevices.front();
-  } // getByBusID
-
-  class ByDSIDSelector : public IDeviceSelector {
-  private:
-    const dsid_t m_ID;
-  public:
-    ByDSIDSelector(const dsid_t _id) : m_ID(_id) {}
-    virtual ~ByDSIDSelector() {};
-
-    virtual bool selectDevice(const Device& _device) const {
-      return _device.getDSID() == m_ID;
-    }
-  };
-
-  DeviceReference Set::getByDSID(const dsid_t _dsid) const {
-    Set resultSet = getSubset(ByDSIDSelector(_dsid));
-    if(resultSet.length() == 0) {
-      throw ItemNotFoundException("with dsid " + _dsid.toString());
-    }
-    return resultSet.m_ContainedDevices.front();
-  } // getByDSID
-
-  int Set::length() const {
-    return m_ContainedDevices.size();
-  } // length
-
-  bool Set::isEmpty() const {
-    return length() == 0;
-  } // isEmpty
-
-  Set Set::combine(Set& _other) const {
-    Set resultSet(_other);
-    foreach(const DeviceReference& iDevice, m_ContainedDevices) {
-      if(!resultSet.contains(iDevice)) {
-        resultSet.addDevice(iDevice);
-      }
-    }
-    return resultSet;
-  } // combine
-
-  Set Set::remove(const Set& _other) const {
-    Set resultSet(*this);
-    foreach(const DeviceReference& iDevice, _other.m_ContainedDevices) {
-      resultSet.removeDevice(iDevice);
-    }
-    return resultSet;
-  } // remove
-
-  bool Set::contains(const DeviceReference& _device) const {
-    DeviceVector::const_iterator pos = find(m_ContainedDevices.begin(), m_ContainedDevices.end(), _device);
-    return pos != m_ContainedDevices.end();
-  } // contains
-
-  bool Set::contains(const Device& _device) const {
-    return contains(DeviceReference(_device, _device.getApartment()));
-  } // contains
-
-  void Set::addDevice(const DeviceReference& _device) {
-    if(!contains(_device)) {
-      m_ContainedDevices.push_back(_device);
-    }
-  } // addDevice
-
-  void Set::addDevice(const Device& _device) {
-    addDevice(DeviceReference(_device, _device.getApartment()));
-  } // addDevice
-
-  void Set::removeDevice(const DeviceReference& _device) {
-    DeviceVector::iterator pos = find(m_ContainedDevices.begin(), m_ContainedDevices.end(), _device);
-    if(pos != m_ContainedDevices.end()) {
-      m_ContainedDevices.erase(pos);
-    }
-  } // removeDevice
-
-  void Set::removeDevice(const Device& _device) {
-    removeDevice(DeviceReference(_device, _device.getApartment()));
-  } // removeDevice
-
-  const DeviceReference& Set::get(int _index) const {
-    return m_ContainedDevices.at(_index);
-  } // get
-
-  const DeviceReference& Set::operator[](const int _index) const {
-    return get(_index);
-  } // operator[]
-
-  DeviceReference& Set::get(int _index) {
-    return m_ContainedDevices.at(_index);
-  } // get
-
-  DeviceReference& Set::operator[](const int _index) {
-    return get(_index);
-  } // operator[]
-
-  unsigned long Set::getPowerConsumption() {
-    unsigned long result = 0;
-    foreach(DeviceReference& iDevice, m_ContainedDevices) {
-      result += iDevice.getPowerConsumption();
-    }
-    return result;
-  } // getPowerConsumption
-
-  std::ostream& operator<<(std::ostream& out, const Device& _dt) {
-    out << "Device ID " << _dt.getShortAddress();
-    if(!_dt.getName().empty()) {
-      out << " name: " << _dt.getName();
-    }
-    return out;
-  } // operator<<
-
-  //================================================== Apartment
-
-  Apartment::Apartment(DSS* _pDSS)
-  : Subsystem(_pDSS, "Apartment"),
-    Thread("Apartment"),
-    m_IsInitializing(true),
-    m_pPropertyNode()
-  { } // ctor
-
-  Apartment::~Apartment() {
-    scrubVector(m_Devices);
-    scrubVector(m_Zones);
-    scrubVector(m_Modulators);
-  } // 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();
-
-    Group* grp = new Group(GroupIDBroadcast, zoneID, *this);
-    grp->setName("broadcast");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDYellow, zoneID, *this);
-    grp->setName("yellow");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDGray, zoneID, *this);
-    grp->setName("gray");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDBlue, zoneID, *this);
-    grp->setName("blue");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDCyan, zoneID, *this);
-    grp->setName("cyan");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDRed, zoneID, *this);
-    grp->setName("red");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDViolet, zoneID, *this);
-    grp->setName("magenta");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDGreen, zoneID, *this);
-    grp->setName("green");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDBlack, zoneID, *this);
-    grp->setName("black");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDWhite, zoneID, *this);
-    grp->setName("white");
-    _zone.addGroup(grp);
-    grp = new Group(GroupIDDisplay, zoneID, *this);
-    grp->setName("display");
-    _zone.addGroup(grp);
-  } // addDefaultGroupsToZone
-
-  bool Apartment::scanModulator(Modulator& _modulator) {
-    _modulator.setIsPresent(true);
-    _modulator.setIsValid(false);
-
-    DS485Interface& interface = DSS::getInstance()->getDS485Interface();
-    int modulatorID = _modulator.getBusID();
-
-    log("scanModulator: Start " + intToString(modulatorID) , lsInfo);
-    vector<int> zoneIDs;
-    try {
-      zoneIDs = interface.getZones(modulatorID);
-    } catch(DS485ApiError& e) {
-      log("scanModulator: Error getting ZoneIDs", lsFatal);
-      return false;
-    }
-
-    int levelOrange, levelRed;
-    try {
-      if(interface.getEnergyBorder(modulatorID, levelOrange, levelRed)) {
-        _modulator.setEnergyLevelOrange(levelOrange);
-        _modulator.setEnergyLevelRed(levelRed);
-      }
-    } catch(DS485ApiError& e) {
-      log("scanModulator: Error getting EnergyLevels", lsFatal);
-      return false;
-    }
-
-    try {
-      ModulatorSpec_t spec = interface.getModulatorSpec(modulatorID);
-      _modulator.setSoftwareVersion(spec.get<1>());
-      _modulator.setHardwareVersion(spec.get<2>());
-      _modulator.setHardwareName(spec.get<3>());
-      _modulator.setDeviceType(spec.get<4>());
-    } catch(DS485ApiError& e) {
-      log("scanModulator: Error getting dSMSpecs", lsFatal);
-      return false;
-    }
-
-    bool firstZone = true;
-    foreach(int zoneID, zoneIDs) {
-      log("scanModulator:  Found zone with id: " + intToString(zoneID));
-      Zone& zone = allocateZone(zoneID);
-      zone.addToModulator(_modulator);
-      zone.setIsPresent(true);
-      if(firstZone) {
-        zone.setFirstZoneOnModulator(modulatorID);
-        firstZone = false;
-      }
-      vector<int> devices;
-      try {
-        devices = interface.getDevicesInZone(modulatorID, zoneID);
-      } catch(DS485ApiError& e) {
-        log("scanModulator: Error getting getDevicesInZone", lsFatal);
-        return false;
-      }
-      foreach(int devID, devices) {
-        dsid_t dsid;
-        try {
-          dsid = interface.getDSIDOfDevice(modulatorID, devID);
-        } catch(DS485ApiError& e) {
-            log("scanModulator: Error getting getDSIDOfDevice", lsFatal);
-            return false;
-        }
-
-        vector<int> results;
-        try {
-          results = interface.sendCommand(cmdGetFunctionID, devID, modulatorID);
-        } catch(DS485ApiError& e) {
-          log("scanModulator: Error getting cmdGetFunctionID", lsFatal);
-          return false;
-        }
-        int functionID = 0;
-        if(results.size() == 1) {
-          functionID = results.front();
-        }
-        log("scanModulator:    Found device with id: " + intToString(devID));
-        log("scanModulator:    DSID:        " + dsid.toString());
-        log("scanModulator:    Function ID: " + unsignedLongIntToHexString(functionID));
-        Device& dev = allocateDevice(dsid);
-        dev.setShortAddress(devID);
-        dev.setModulatorID(modulatorID);
-        dev.setZoneID(zoneID);
-        dev.setFunctionID(functionID);
-
-        std::vector<int> groupIdperDevices = interface.getGroupsOfDevice(modulatorID, devID);
-        vector<int> groupIDsPerDevice = interface.getGroupsOfDevice(modulatorID,devID);
-        foreach(int groupID, groupIDsPerDevice) {
-          log(std::string("scanModulator: adding device ") + intToString(devID) + " to group " + intToString(groupID));
-          dev.addToGroup(groupID);
-        }
-
-        DeviceReference devRef(dev, *this);
-        zone.addDevice(devRef);
-        _modulator.addDevice(devRef);
-        dev.setIsPresent(true);
-      }
-      vector<int> groupIDs;
-      try {
-        groupIDs = interface.getGroups(modulatorID, zoneID);
-      } catch(DS485ApiError& e) {
-        log("scanModulator: Error getting getGroups", lsFatal);
-        return false;
-      }
-
-      foreach(int groupID, groupIDs) {
-        if(groupID == 0) {
-          log("scanModulator:    Group ID is zero, bailing out... (modulatorID: "
-              + intToString(modulatorID) + 
-              "zoneID: " + intToString(zoneID) + ")",
-              lsError);
-          continue;
-        }
-        log("scanModulator:    Found group with id: " + intToString(groupID));
-        if(zone.getGroup(groupID) == NULL) {
-          log(" scanModulator:    Adding new group to zone");
-          zone.addGroup(new Group(groupID, zone.getID(), *this));
-        }
-        try {
-          Group& group = getGroup(groupID);
-          group.setIsPresent(true);
-        } catch(ItemNotFoundException&) {
-          Group* pGroup = new Group(groupID, 0, *this);
-          getZone(0).addGroup(pGroup);
-          pGroup->setIsPresent(true);
-          log("scanModulator:     Adding new group to zone 0");
-        }
-
-        // get last called scene for zone, group
-        try {
-          int lastCalledScene = interface.getLastCalledScene(modulatorID, zoneID, groupID);
-          Group* pGroup = zone.getGroup(groupID);
-          assert(pGroup != NULL);
-          log("scanModulator: zoneID: " + intToString(zoneID) + " groupID: " + intToString(groupID) + " lastScene: " + intToString(lastCalledScene));
-          if(lastCalledScene < 0 || lastCalledScene > MaxSceneNumber) {
-            log("scanModulator: _sceneID is out of bounds. zoneID: " + intToString(zoneID) + " groupID: " + intToString(groupID) + " scene: " + intToString(lastCalledScene), lsError);
-          } else {
-            onGroupCallScene(zoneID, groupID, lastCalledScene);
-          }
-        } catch(DS485ApiError& error) {
-          log(std::string("scanModulator: Error getting last called scene '") + error.what() + "'", lsError);
-        }
-      }
-    }
-    _modulator.setIsValid(true);
-    return true;
-
-  } // scanModulator
-
-  void Apartment::modulatorReady(int _modulatorBusID) {
-    log("Modulator with id: " + intToString(_modulatorBusID) + " is ready", lsInfo);
-    try {
-      try {
-        Modulator& mod = getModulatorByBusID(_modulatorBusID);
-        if(scanModulator(mod)) {
-          boost::shared_ptr<Event> modulatorReadyEvent(new Event("modulator_ready"));
-          modulatorReadyEvent->setProperty("modulator", mod.getDSID().toString());
-          raiseEvent(modulatorReadyEvent);
-        }
-      } catch(DS485ApiError& e) {
-        log(std::string("Exception caught while scanning modulator " + intToString(_modulatorBusID) + " : ") + e.what(), lsFatal);
-
-        ModelEvent* pEvent = new ModelEvent(ModelEvent::etModulatorReady);
-        pEvent->addParameter(_modulatorBusID);
-        addModelEvent(pEvent);
-      }
-    } catch(ItemNotFoundException& e) {
-      log("No modulator for bus-id (" + intToString(_modulatorBusID) + ") found, re-discovering devices");
-      discoverDS485Devices();
-    }
-  } // modulatorReady
-
-  void Apartment::setPowerConsumption(int _modulatorBusID, unsigned long _value) {
-    getModulatorByBusID(_modulatorBusID).setPowerConsumption(_value);
-  } // powerConsumption
-
-  void Apartment::setEnergyMeterValue(int _modulatorBusID, unsigned long _value) {
-    getModulatorByBusID(_modulatorBusID).setEnergyMeterValue(_value);
-  } // energyMeterValue
-
-  void Apartment::discoverDS485Devices() {
-    // temporary mark all modulators as absent
-    foreach(Modulator* pModulator, m_Modulators) {
-      pModulator->setIsPresent(false);
-    }
-
-    // Request the dsid of all modulators
-    DS485CommandFrame requestFrame;
-    requestFrame.getHeader().setBroadcast(true);
-    requestFrame.getHeader().setDestination(0);
-    requestFrame.setCommand(CommandRequest);
-    requestFrame.getPayload().add<uint8_t>(FunctionModulatorGetDSID);
-    if(DSS::hasInstance()) {
-      DSS::getInstance()->getDS485Interface().sendFrame(requestFrame);
-    }
-  } // discoverDS485Devices
-
-  void Apartment::writeConfiguration() {
-    if(DSS::hasInstance()) {
-      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::etNewModulator:
-        discoverDS485Devices();
-        break;
-      case ModelEvent::etLostModulator:
-        discoverDS485Devices();
-        break;
-      case ModelEvent::etModulatorReady:
-        if(event.getParameterCount() != 1) {
-          log("Expected exactly 1 parameter for ModelEvent::etModulatorReady");
-        } else {
-          try{
-            Modulator& mod = getModulatorByBusID(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{
-             getModulatorByDSID(newDSID).setBusID(busID);
-             log ("dSM present");
-             getModulatorByDSID(newDSID).setIsPresent(true);
-          } catch(ItemNotFoundException& e) {
-             log ("dSM not present");
-             Modulator& modulator = allocateModulator(newDSID);
-             modulator.setBusID(busID);
-             modulator.setIsPresent(true);
-             modulator.setIsValid(false);
-             ModelEvent* pEvent = new ModelEvent(ModelEvent::etModulatorReady);
-             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(Modulator* pModulator, m_Modulators) {
-        if(pModulator->isPresent()) {
-          if(!pModulator->isValid()) {
-            modulatorReady(pModulator->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");
-      if(!boost::filesystem::exists(configFileName)) {
-        log(std::string("Apartment::execute: Could not open config-file for apartment: '") + configFileName + "'", lsWarning);
-      } else {
-        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/modulators/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
-
-  const int ApartmentConfigVersion = 1;
-
-  void Apartment::readConfigurationFromXML(const std::string& _fileName) {
-    setName("dSS");
-    std::ifstream inFile(_fileName.c_str());
-
-    InputSource input(inFile);
-    DOMParser parser;
-    AutoPtr<Document> pDoc = parser.parse(&input);
-    Element* rootNode = pDoc->documentElement();
-
-    if(rootNode->localName() == "config") {
-      if(rootNode->hasAttribute("version") && (strToInt(rootNode->getAttribute("version")) == ApartmentConfigVersion)) {
-        Node* curNode = rootNode->firstChild();
-        while(curNode != NULL) {
-          std::string nodeName = curNode->localName();
-          if(nodeName == "devices") {
-            loadDevices(curNode);
-          } else if(nodeName == "modulators") {
-            loadModulators(curNode);
-          } else if(nodeName == "zones") {
-            loadZones(curNode);
-          } else if(nodeName == "apartment") {
-            Element* elem = dynamic_cast<Element*>(curNode);
-            if(elem != NULL) {
-              Element* nameElem = elem->getChildElement("name");
-              if(nameElem->hasChildNodes()) {
-                setName(nameElem->firstChild()->nodeValue());
-              }
-            }
-          }
-          curNode = curNode->nextSibling();
-        }
-      } else {
-        log("Config file has the wrong version");
-      }
-    }
-  } // readConfigurationFromXML
-
-  void Apartment::loadDevices(Node* _node) {
-    Node* curNode = _node->firstChild();
-    while(curNode != NULL) {
-      if(curNode->localName() == "device") {
-        Element* elem = dynamic_cast<Element*>(curNode);
-        if((elem != NULL) && elem->hasAttribute("dsid")) {
-          dsid_t dsid = dsid_t::fromString(elem->getAttribute("dsid"));
-          std::string name;
-          Element* nameElem = elem->getChildElement("name");
-          if((nameElem != NULL) && nameElem->hasChildNodes()) {
-            name = nameElem->firstChild()->nodeValue();
-          }
-
-          DateTime firstSeen;
-          if(elem->hasAttribute("firstSeen")) {
-            firstSeen = DateTime(dateFromISOString(elem->getAttribute("firstSeen").c_str()));
-          }
-
-          Device& newDevice = allocateDevice(dsid);
-          if(!name.empty()) {
-            newDevice.setName(name);
-          }
-          newDevice.setFirstSeen(firstSeen);
-          Element* propertiesElem = elem->getChildElement("properties");
-          if(propertiesElem != NULL) {
-            newDevice.publishToPropertyTree();
-            newDevice.getPropertyNode()->loadChildrenFromNode(propertiesElem);
-          }
-        }
-      }
-      curNode = curNode->nextSibling();
-    }
-  } // loadDevices
-
-  void Apartment::loadModulators(Node* _node) {
-    Node* curNode = _node->firstChild();
-    while(curNode != NULL) {
-      if(curNode->localName() == "modulator") {
-        Element* elem = dynamic_cast<Element*>(curNode);
-        if((elem != NULL) && elem->hasAttribute("id")) {
-          dsid_t id = dsid_t::fromString(elem->getAttribute("id"));
-          std::string name;
-          Element* nameElem = elem->getChildElement("name");
-          if((nameElem != NULL) && nameElem->hasChildNodes()) {
-            name = nameElem->firstChild()->nodeValue();
-          }
-          Modulator& newModulator = allocateModulator(id);
-          if(!name.empty()) {
-            newModulator.setName(name);
-          }
-        }
-      }
-      curNode = curNode->nextSibling();
-    }
-  } // loadModulators
-
-  void Apartment::loadZones(Node* _node) {
-    Node* curNode = _node->firstChild();
-    while(curNode != NULL) {
-      if(curNode->localName() == "zone") {
-        Element* elem = dynamic_cast<Element*>(curNode);
-        if((elem != NULL) && elem->hasAttribute("id")) {
-          int id = strToInt(elem->getAttribute("id"));
-          std::string name;
-          Element* nameElem = elem->getChildElement("name");
-          if((nameElem != NULL) && nameElem->hasChildNodes()) {
-            name = nameElem->firstChild()->nodeValue();
-          }
-          Zone& newZone = allocateZone(id);
-          if(!name.empty()) {
-            newZone.setName(name);
-          }
-        }
-      }
-      curNode = curNode->nextSibling();
-    }
-  } // loadZones
-
-  void DeviceToXML(const Device* _pDevice, AutoPtr<Element>& _parentNode, AutoPtr<Document>& _pDocument) {
-    AutoPtr<Element> pDeviceNode = _pDocument->createElement("device");
-    pDeviceNode->setAttribute("dsid", _pDevice->getDSID().toString());
-    if(!_pDevice->getName().empty()) {
-      AutoPtr<Element> pNameNode = _pDocument->createElement("name");
-      AutoPtr<Text> txtNode = _pDocument->createTextNode(_pDevice->getName());
-      pNameNode->appendChild(txtNode);
-      pDeviceNode->appendChild(pNameNode);
-    }    
-    pDeviceNode->setAttribute("firstSeen", _pDevice->getFirstSeen());
-    if(_pDevice->getPropertyNode() != NULL) {
-      AutoPtr<Element> pPropertiesNode = _pDocument->createElement("properties");
-      pDeviceNode->appendChild(pPropertiesNode);
-      _pDevice->getPropertyNode()->saveChildrenAsXML(_pDocument, pPropertiesNode, PropertyNode::Archive);
-    }
-
-    _parentNode->appendChild(pDeviceNode);
-  } // deviceToXML
-
-  void ZoneToXML(const Zone* _pZone, AutoPtr<Element>& _parentNode, AutoPtr<Document>& _pDocument) {
-    AutoPtr<Element> pZoneNode = _pDocument->createElement("zone");
-    pZoneNode->setAttribute("id", intToString(_pZone->getID()));
-    if(!_pZone->getName().empty()) {
-      AutoPtr<Element> pNameNode = _pDocument->createElement("name");
-      AutoPtr<Text> txtNode = _pDocument->createTextNode(_pZone->getName());
-      pNameNode->appendChild(txtNode);
-      pZoneNode->appendChild(pNameNode);
-    }
-    _parentNode->appendChild(pZoneNode);
-  } // zoneToXML
-
-  void ModulatorToXML(const Modulator* _pModulator, AutoPtr<Element>& _parentNode, AutoPtr<Document>& _pDocument) {
-    AutoPtr<Element> pModulatorNode = _pDocument->createElement("modulator");
-    pModulatorNode->setAttribute("id", _pModulator->getDSID().toString());
-    if(!_pModulator->getName().empty()) {
-      AutoPtr<Element> pNameNode = _pDocument->createElement("name");
-      AutoPtr<Text> txtNode = _pDocument->createTextNode(_pModulator->getName());
-      pNameNode->appendChild(txtNode);
-      pModulatorNode->appendChild(pNameNode);
-    }
-    _parentNode->appendChild(pModulatorNode);
-  } // modulatorToXML
-
-  void Apartment::writeConfigurationToXML(const std::string& _fileName) {
-    log("Writing apartment config to '" + _fileName + "'", lsInfo);
-    AutoPtr<Document> pDoc = new Document;
-
-    AutoPtr<ProcessingInstruction> pXMLHeader = pDoc->createProcessingInstruction("xml", "version='1.0' encoding='utf-8'");
-    pDoc->appendChild(pXMLHeader);
-
-    AutoPtr<Element> pRoot = pDoc->createElement("config");
-    pRoot->setAttribute("version", intToString(ApartmentConfigVersion));
-    pDoc->appendChild(pRoot);
-
-    // apartment
-    AutoPtr<Element> pApartment = pDoc->createElement("apartment");
-    pRoot->appendChild(pApartment);
-    AutoPtr<Element> pApartmentName = pDoc->createElement("name");
-    AutoPtr<Text> pApartmentNameText = pDoc->createTextNode(getName());
-    pApartmentName->appendChild(pApartmentNameText);
-    pApartment->appendChild(pApartmentName);
-
-    // devices
-    AutoPtr<Element> pDevices = pDoc->createElement("devices");
-    pRoot->appendChild(pDevices);
-    foreach(Device* pDevice, m_Devices) {
-      DeviceToXML(pDevice, pDevices, pDoc);
-    }
-
-    // zones
-    AutoPtr<Element> pZones = pDoc->createElement("zones");
-    pRoot->appendChild(pZones);
-    foreach(Zone* pZone, m_Zones) {
-      ZoneToXML(pZone, pZones, pDoc);
-    }
-
-    // modulators
-    AutoPtr<Element> pModulators = pDoc->createElement("modulators");
-    pRoot->appendChild(pModulators);
-    foreach(Modulator* pModulator, m_Modulators) {
-      ModulatorToXML(pModulator, pModulators, pDoc);
-    }
-
-    std::string tmpOut = _fileName + ".tmp";
-    std::ofstream ofs(tmpOut.c_str());
-
-    if(ofs) {
-      DOMWriter writer;
-      writer.setNewLine("\n");
-      writer.setOptions(XMLWriter::PRETTY_PRINT);
-      writer.writeNode(ofs, pDoc);
-
-      ofs.close();
-
-      // move it to the desired location
-      rename(tmpOut.c_str(), _fileName.c_str());
-    } else {
-      log("Could not open file '" + tmpOut + "' for writing", lsFatal);
-    }
-  } // writeConfigurationToXML
-
-  Device& Apartment::getDeviceByDSID(const dsid_t _dsid) const {
-    foreach(Device* dev, m_Devices) {
-      if(dev->getDSID() == _dsid) {
-        return *dev;
-      }
-    }
-    throw ItemNotFoundException(_dsid.toString());
-  } // getDeviceByShortAddress const
-
-  Device& Apartment::getDeviceByDSID(const dsid_t _dsid) {
-    foreach(Device* dev, m_Devices) {
-      if(dev->getDSID() == _dsid) {
-        return *dev;
-      }
-    }
-    throw ItemNotFoundException(_dsid.toString());
-  } // getDeviceByShortAddress
-
-  Device& Apartment::getDeviceByShortAddress(const Modulator& _modulator, const devid_t _deviceID) const {
-    foreach(Device* dev, m_Devices) {
-      if((dev->getShortAddress() == _deviceID) &&
-          (_modulator.getBusID() == dev->getModulatorID())) {
-        return *dev;
-      }
-    }
-    throw ItemNotFoundException(intToString(_deviceID));
-  } // getDeviceByShortAddress
-
-  Device& Apartment::getDeviceByName(const std::string& _name) {
-    foreach(Device* dev, m_Devices) {
-      if(dev->getName() == _name) {
-        return *dev;
-      }
-    }
-    throw ItemNotFoundException(_name);
-  } // getDeviceByName
-
-  Set Apartment::getDevices() const {
-    DeviceVector devs;
-    foreach(Device* dev, m_Devices) {
-      devs.push_back(DeviceReference(*dev, *this));
-    }
-
-    return Set(devs);
-  } // getDevices
-
-  Zone& Apartment::getZone(const std::string& _zoneName) {
-    foreach(Zone* zone, m_Zones) {
-      if(zone->getName() == _zoneName) {
-        return *zone;
-      }
-    }
-    throw ItemNotFoundException(_zoneName);
-  } // getZone(name)
-
-  Zone& Apartment::getZone(const int _id) {
-    foreach(Zone* zone, m_Zones) {
-      if(zone->getID() == _id) {
-        return *zone;
-      }
-    }
-    throw ItemNotFoundException(intToString(_id));
-  } // getZone(id)
-
-  vector<Zone*>& Apartment::getZones() {
-    return m_Zones;
-  } // getZones
-
-  Modulator& Apartment::getModulator(const std::string& _modName) {
-    foreach(Modulator* modulator, m_Modulators) {
-      if(modulator->getName() == _modName) {
-        return *modulator;
-      }
-    }
-    throw ItemNotFoundException(_modName);
-  } // getModulator(name)
-
-  Modulator& Apartment::getModulatorByBusID(const int _busId) {
-    foreach(Modulator* modulator, m_Modulators) {
-      if(modulator->getBusID() == _busId) {
-        return *modulator;
-      }
-    }
-    throw ItemNotFoundException(intToString(_busId));
-  } // getModulatorByBusID
-
-  Modulator& Apartment::getModulatorByDSID(const dsid_t _dsid) {
-    foreach(Modulator* modulator, m_Modulators) {
-      if(modulator->getDSID() == _dsid) {
-        return *modulator;
-      }
-    }
-    throw ItemNotFoundException(_dsid.toString());
-  } // getModulatorByDSID
-
-  vector<Modulator*>& Apartment::getModulators() {
-    return m_Modulators;
-  } // getModulators
-
-  // Group queries
-  Group& Apartment::getGroup(const std::string& _name) {
-    Group* pResult = getZone(0).getGroup(_name);
-    if(pResult != NULL) {
-      return *pResult;
-    }
-    throw ItemNotFoundException(_name);
-  } // getGroup(name)
-
-  Group& Apartment::getGroup(const int _id) {
-    Group* pResult = getZone(0).getGroup(_id);
-    if(pResult != NULL) {
-      return *pResult;
-    }
-    throw ItemNotFoundException(intToString(_id));
-  } // getGroup(id)
-
-  Device& Apartment::allocateDevice(const dsid_t _dsid) {
-    // search for existing device
-    foreach(Device* device, m_Devices) {
-      if(device->getDSID() == _dsid) {
-        DeviceReference devRef(*device, *this);
-        getZone(0).addDevice(devRef);
-        return *device;
-      }
-    }
-
-    Device* pResult = new Device(_dsid, this);
-    pResult->setFirstSeen(DateTime());
-    m_Devices.push_back(pResult);
-    DeviceReference devRef(*pResult, *this);
-    getZone(0).addDevice(devRef);
-    return *pResult;
-  } // allocateDevice
-
-  Modulator& Apartment::allocateModulator(const dsid_t _dsid) {
-    foreach(Modulator* modulator, m_Modulators) {
-      if((modulator)->getDSID() == _dsid) {
-        return *modulator;
-      }
-    }
-
-    Modulator* pResult = new Modulator(_dsid);
-    m_Modulators.push_back(pResult);
-    return *pResult;
-  } // allocateModulator
-
-  Zone& Apartment::allocateZone(int _zoneID) {
-    if(getPropertyNode() != NULL) {
-      getPropertyNode()->createProperty("zones/zone" + intToString(_zoneID));
-    }
-
-    foreach(Zone* zone, m_Zones) {
-  		if(zone->getID() == _zoneID) {
-  			return *zone;
-  		}
-  	}
-
-  	Zone* zone = new Zone(_zoneID);
-  	m_Zones.push_back(zone);
-  	addDefaultGroupsToZone(*zone);
-  	return *zone;
-  } // allocateZone
-
-  void Apartment::removeZone(int _zoneID) {
-    for(std::vector<Zone*>::iterator ipZone = m_Zones.begin(), e = m_Zones.end();
-        ipZone != e; ++ipZone) {
-      Zone* pZone = *ipZone;
-      if(pZone->getID() == _zoneID) {
-        m_Zones.erase(ipZone);
-        delete pZone;
-        return;
-      }
-    }
-  } // removeZone
-  
-  void Apartment::removeDevice(dsid_t _device) {
-    for(std::vector<Device*>::iterator ipDevice = m_Devices.begin(), e = m_Devices.end();
-        ipDevice != e; ++ipDevice) {
-      Device* pDevice = *ipDevice;
-      if(pDevice->getDSID() == _device) {
-        m_Devices.erase(ipDevice);
-        delete pDevice;
-        return;
-      }
-    }
-  } // removeDevice
-  
-  void Apartment::removeModulator(dsid_t _modulator) {
-    for(std::vector<Modulator*>::iterator ipModulator = m_Modulators.begin(), e = m_Modulators.end();
-        ipModulator != e; ++ipModulator) {
-      Modulator* pModulator = *ipModulator;
-      if(pModulator->getDSID() == _modulator) {
-        m_Modulators.erase(ipModulator);
-        delete pModulator;
-        return;
-      }
-    }
-  } // removeModulator
-
-  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);
-
-          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 _modulatorID, const int _deviceID, const int _sceneID) {
-    try {
-      if(_sceneID < 0 || _sceneID > MaxSceneNumber) {
-        log("onDeviceCallScene: _sceneID is out of bounds. modulator-id '" + intToString(_modulatorID) + "' for device '" + intToString(_deviceID) + "' scene: " + intToString(_sceneID), lsError);
-        return;
-      }
-      Modulator& mod = getModulatorByBusID(_modulatorID);
-      try {
-        log("OnDeviceCallScene: modulator-id '" + intToString(_modulatorID) + "' for device '" + intToString(_deviceID) + "' scene: " + intToString(_sceneID));
-        DeviceReference devRef = mod.getDevices().getByBusID(_deviceID);
-        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 modulator '" + intToString(_modulatorID) + "' scene:" + intToString(_sceneID), lsError);
-      }
-    } catch(ItemNotFoundException& e) {
-      log("OnDeviceCallScene: Could not find modulator with bus-id '" + intToString(_modulatorID) + "'", 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("  Modulator: " + intToString(_modID));
-    log("  Zone:      " + intToString(_zoneID));
-    log("  BusID:     " + intToString(_devID));
-    log("  FID:       " + intToString(_functionID));
-
-    dsid_t dsid = getDSS().getDS485Interface().getDSIDOfDevice(_modID, _devID);
-    Device& dev = allocateDevice(dsid);
-    DeviceReference devRef(dev, *this);
-
-    log("  DSID:      " + dsid.toString());
-
-    // remove from old modulator
-    try {
-      Modulator& oldModulator = getModulatorByBusID(dev.getModulatorID());
-      oldModulator.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 modulator and remove it in that case
-      } catch(std::runtime_error&) {
-      }
-    }
-
-    // update device
-    dev.setModulatorID(_modID);
-    dev.setZoneID(_zoneID);
-    dev.setShortAddress(_devID);
-    dev.setFunctionID(_functionID);
-    dev.setIsPresent(true);
-
-    // add to new modulator
-    Modulator& modulator = getModulatorByBusID(_modID);
-    modulator.addDevice(devRef);
-
-    // add to new zone
-    Zone& newZone = allocateZone(_zoneID);
-    newZone.addToModulator(modulator);
-    newZone.addDevice(devRef);
-
-    // get groups of device
-    dev.resetGroups();
-    vector<int> groups = getDSS().getDS485Interface().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("  Modulator: " + intToString(_modID));
-    log("  DevID:     " + intToString(_devID));
-    log("  Priority:  " + intToString(_priority));
-
-    try {
-      Modulator& modulator = getModulatorByBusID(_modID);
-      try {
-        Device& device = getDeviceByShortAddress(modulator, _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 Modulator with ID " + intToString(_modID), lsFatal);
-      return;
-    }
-
-  } // onDSLinkInterrupt
-
-  //================================================== Modulator
-
-  Modulator::Modulator(const dsid_t _dsid)
-  : m_DSID(_dsid),
-    m_BusID(0xFF),
-    m_PowerConsumption(0),
-    m_EnergyMeterValue(0),
-    m_IsValid(false)
-  {
-  } // ctor
-
-  Set Modulator::getDevices() const {
-    return m_ConnectedDevices;
-  } // getDevices
-
-  void Modulator::addDevice(const DeviceReference& _device) {
-    if(!contains(m_ConnectedDevices, _device)) {
-  	  m_ConnectedDevices.push_back(_device);
-    } else {
-      Logger::getInstance()->log("Modulator::addDevice: DUPLICATE DEVICE Detected modulator: " + intToString(m_BusID) + " device: " + _device.getDSID().toString(), lsFatal);
-    }
-  } // addDevice
-
-  void Modulator::removeDevice(const DeviceReference& _device) {
-    DeviceIterator pos = find(m_ConnectedDevices.begin(), m_ConnectedDevices.end(), _device);
-    if(pos != m_ConnectedDevices.end()) {
-      m_ConnectedDevices.erase(pos);
-    }
-  } // removeDevice
-
-  dsid_t Modulator::getDSID() const {
-    return m_DSID;
-  } // getDSID
-
-  int Modulator::getBusID() const {
-    return m_BusID;
-  } // getBusID
-
-  void Modulator::setBusID(const int _busID) {
-    m_BusID = _busID;
-  } // setBusID
-
-  unsigned long Modulator::getPowerConsumption() {
-    DateTime now;
-    if(!now.addSeconds(-1).before(m_PowerConsumptionAge)) {
-      m_PowerConsumption =  DSS::getInstance()->getDS485Interface().getPowerConsumption(m_BusID);
-      m_PowerConsumptionAge = now;
-    }
-    return m_PowerConsumption;
-  } // getPowerConsumption
-
-  unsigned long Modulator::getEnergyMeterValue() {
-    DateTime now;
-    if(!now.addSeconds(-1).before(m_EnergyMeterValueAge)) {
-      m_EnergyMeterValue = DSS::getInstance()->getDS485Interface().getEnergyMeterValue(m_BusID);
-      m_EnergyMeterValueAge = now;
-    }
-    return m_EnergyMeterValue;
-  } // getEnergyMeterValue
-
-
-  /** set the consumption in mW */
-  void Modulator::setPowerConsumption(unsigned long _value)
-  {
-    DateTime now;
-    m_PowerConsumptionAge = now;
-    m_PowerConsumption = _value;
-  }
-
-  /** set the meter value in Wh */
-  void Modulator::setEnergyMeterValue(unsigned long _value)
-  {
-    DateTime now;
-    m_EnergyMeterValueAge = now;
-    m_EnergyMeterValue = _value;
-  }
-
-  unsigned long Modulator::getCachedPowerConsumption() {
-    return m_PowerConsumption;
-  } // getPowerConsumption
-
-  unsigned long Modulator::getCachedEnergyMeterValue() {
-    return m_EnergyMeterValue;
-  } // getEnergyMeterValue
-
-  
-  //================================================== Zone
-
-  Zone::~Zone() {
-    scrubVector(m_Groups);
-    // we don't own our modulators
-    m_Modulators.clear();
-  } // dtor
-
-  Set Zone::getDevices() const {
-    return Set(m_Devices);
-  } // getDevices
-
-  void Zone::addDevice(DeviceReference& _device) {
-    const Device& dev = _device.getDevice();
-  	int oldZoneID = dev.getZoneID();
-  	if((oldZoneID != -1) && (oldZoneID != 0)) {
-  		try {
-  		  Zone& oldZone = dev.getApartment().getZone(oldZoneID);
-  		  oldZone.removeDevice(_device);
-  		} catch(std::runtime_error&) {
-  		}
-  	}
-    if(!contains(m_Devices, _device)) {
-      m_Devices.push_back(_device);
-    } else {
-      // don't warn about multiple additions to zone 0
-      if(m_ZoneID != 0) {
-        Logger::getInstance()->log("Zone::addDevice: DUPLICATE DEVICE Detected Zone: " + intToString(m_ZoneID) + " device: " + _device.getDSID().toString(), lsWarning);
-      }
-    }
-    _device.getDevice().setZoneID(m_ZoneID);
-  } // addDevice
-
-  void Zone::addGroup(Group* _group) {
-    if(_group->getZoneID() != m_ZoneID) {
-      throw std::runtime_error("Zone::addGroup: ZoneID of _group does not match own");
-    }
-    m_Groups.push_back(_group);
-  } // addGroup
-
-  void Zone::removeGroup(UserGroup* _group) {
-    std::vector<Group*>::iterator it = find(m_Groups.begin(), m_Groups.end(), _group);
-    if(it != m_Groups.end()) {
-      m_Groups.erase(it);
-    }
-  } // removeGroup
-
-  void Zone::removeDevice(const DeviceReference& _device) {
-    DeviceIterator pos = find(m_Devices.begin(), m_Devices.end(), _device);
-    if(pos != m_Devices.end()) {
-      m_Devices.erase(pos);
-    }
-  } // removeDevice
-
-  Group* Zone::getGroup(const std::string& _name) const {
-    for(vector<Group*>::const_iterator ipGroup = m_Groups.begin(), e = m_Groups.end();
-        ipGroup != e; ++ipGroup)
-    {
-        if((*ipGroup)->getName() == _name) {
-          return *ipGroup;
-        }
-    }
-    return NULL;
-  } // getGroup
-
-  Group* Zone::getGroup(const int _id) const {
-    for(vector<Group*>::const_iterator ipGroup = m_Groups.begin(), e = m_Groups.end();
-        ipGroup != e; ++ipGroup)
-    {
-        if((*ipGroup)->getID() == _id) {
-          return *ipGroup;
-        }
-    }
-    return NULL;
-  } // getGroup
-
-  int Zone::getID() const {
-    return m_ZoneID;
-  } // getID
-
-  void Zone::setZoneID(const int _value) {
-    m_ZoneID = _value;
-  } // setZoneID
-
-  void Zone::addToModulator(const Modulator& _modulator) {
-    // make sure the zone is connected to the modulator
-    if(find(m_Modulators.begin(), m_Modulators.end(), &_modulator) == m_Modulators.end()) {
-      m_Modulators.push_back(&_modulator);
-    }
-  } // addToModulator
-
-  void Zone::removeFromModulator(const Modulator& _modulator) {
-    m_Modulators.erase(find(m_Modulators.begin(), m_Modulators.end(), &_modulator));
-  } // removeFromModulator
-
-  vector<int> Zone::getModulators() const {
-  	vector<int> result;
-  	for(vector<const Modulator*>::const_iterator iModulator = m_Modulators.begin(), e = m_Modulators.end();
-  	    iModulator != e; ++iModulator) {
-  		result.push_back((*iModulator)->getBusID());
-  	}
-  	return result;
-  } // getModulators
-
-  bool Zone::registeredOnModulator(const Modulator& _modulator) const {
-    return find(m_Modulators.begin(), m_Modulators.end(), &_modulator) != m_Modulators.end();
-  } // registeredOnModulator
-
-  void Zone::turnOn() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdTurnOn, *this, GroupIDBroadcast);
-  } // turnOn
-
-  void Zone::turnOff() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdTurnOff, *this, GroupIDBroadcast);
-  } // turnOff
-
-  void Zone::increaseValue(const int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdIncreaseValue, *this, GroupIDBroadcast, _parameterNr);
-  } // increaseValue
-
-  void Zone::decreaseValue(const int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdDecreaseValue, *this, GroupIDBroadcast, _parameterNr);
-  } // decreaseValue
-
-  void Zone::enable() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdEnable, *this, GroupIDBroadcast);
-  } // enable
-
-  void Zone::disable() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdDisable, *this, GroupIDBroadcast);
-  } // disable
-
-  void Zone::startDim(const bool _directionUp, const int _parameterNr) {
-    if(_directionUp) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdStartDimUp, *this, GroupIDBroadcast, _parameterNr);
-    } else {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdStartDimDown, *this, GroupIDBroadcast, _parameterNr);
-    }
-  } // startDim
-
-  void Zone::endDim(const int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdStopDim, *this, GroupIDBroadcast, _parameterNr);
-  } // endDim
-
-  void Zone::setValue(const double _value, const int _parameterNr) {
-    if(_parameterNr == -1) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdSetValue, *this, GroupIDBroadcast, static_cast<int>(_value));
-    } else {
-      throw std::runtime_error("Can't set arbitrary parameter on a zone");
-    }
-  } // setValue
-
-  void Zone::callScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdCallScene, *this, GroupIDBroadcast, _sceneNr);
-  } // callScene
-
-  void Zone::saveScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdSaveScene, *this, GroupIDBroadcast, _sceneNr);
-  } // saveScene
-
-  void Zone::undoScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdUndoScene, *this, GroupIDBroadcast, _sceneNr);
-  } // undoScene
-
-  unsigned long Zone::getPowerConsumption() {
-    return getDevices().getPowerConsumption();
-  } // getPowerConsumption
-
-  void Zone::nextScene() {
-    Group* broadcastGroup = getGroup(0);
-    if(broadcastGroup != NULL) {
-      broadcastGroup->nextScene();
-    }
-  } // nextScene
-
-  void Zone::previousScene() {
-    Group* broadcastGroup = getGroup(0);
-    if(broadcastGroup != NULL) {
-      broadcastGroup->previousScene();
-    }
-  } // previousScene
-
-
-  //============================================= Group
-
-  Group::Group(const int _id, const int _zoneID, Apartment& _apartment)
-  : m_Apartment(_apartment),
-    m_ZoneID(_zoneID),
-    m_GroupID(_id),
-    m_LastCalledScene(SceneOff)
-  {
-  } // ctor
-
-  int Group::getID() const {
-    return m_GroupID;
-  } // getID
-
-  int Group::getZoneID() const {
-    return m_ZoneID;
-  } // getZoneID
-
-  Set Group::getDevices() const {
-    return m_Apartment.getDevices().getByZone(m_ZoneID).getByGroup(m_GroupID);
-  } // getDevices
-
-  void Group::turnOn() {
-    callScene(SceneMax);
-  } // turnOn
-
-  void Group::turnOff() {
-    callScene(SceneMin);
-  } // turnOff
-
-  void Group::increaseValue(const int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdIncreaseValue, m_Apartment.getZone(m_ZoneID), m_GroupID, _parameterNr);
-  } // increaseValue
-
-  void Group::decreaseValue(const int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdDecreaseValue, m_Apartment.getZone(m_ZoneID), m_GroupID, _parameterNr);
-  } // decreaseValue
-
-  void Group::enable() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdEnable, m_Apartment.getZone(m_ZoneID), m_GroupID);
-  } // enable
-
-  void Group::disable() {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdDisable, m_Apartment.getZone(m_ZoneID), m_GroupID);
-  } // disable
-
-  void Group::startDim(bool _directionUp, const int _parameterNr)  {
-    if(_directionUp) {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdStartDimUp, m_Apartment.getZone(m_ZoneID), m_GroupID, _parameterNr);
-    } else {
-      DSS::getInstance()->getDS485Interface().sendCommand(cmdStartDimDown, m_Apartment.getZone(m_ZoneID), m_GroupID, _parameterNr);
-    }
-  } // startDim
-
-  void Group::endDim(const int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdStopDim, m_Apartment.getZone(m_ZoneID), m_GroupID, _parameterNr);
-  } // endDim
-
-  void Group::setValue(const double _value, int _parameterNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdSetValue, m_Apartment.getZone(m_ZoneID), m_GroupID, static_cast<int>(_value));
-  } // setValue
-
-  Group& Group::operator=(const Group& _other) {
-    m_Devices = _other.m_Devices;
-    //m_Apartment = _other.m_Apartment;
-    m_GroupID = _other.m_GroupID;
-    m_ZoneID = _other.m_ZoneID;
-    return *this;
-  } // operator=
-
-  void Group::callScene(const int _sceneNr) {
-    // this might be redundant, but since a set could be
-    // optimized if it contains only one device its safer like that...
-    if(SceneHelper::rememberScene(_sceneNr & 0x00ff)) {
-      m_LastCalledScene = _sceneNr & 0x00ff;
-    }
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdCallScene, m_Apartment.getZone(m_ZoneID), m_GroupID, _sceneNr);
-  } // callScene
-
-  void Group::saveScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdSaveScene, m_Apartment.getZone(m_ZoneID), m_GroupID, _sceneNr);
-  } // saveScene
-
-  void Group::undoScene(const int _sceneNr) {
-    DSS::getInstance()->getDS485Interface().sendCommand(cmdUndoScene, m_Apartment.getZone(m_ZoneID), m_GroupID, _sceneNr);
-  } // undoScene
-
-  unsigned long Group::getPowerConsumption() {
-    return getDevices().getPowerConsumption();
-  } // getPowerConsumption
-
-  void Group::nextScene() {
-    callScene(SceneHelper::getNextScene(m_LastCalledScene));
-  } // nextScene
-
-  void Group::previousScene() {
-    callScene(SceneHelper::getPreviousScene(m_LastCalledScene));
-  } // previousScene
-
-
-  //================================================== DeviceReference
-
-  DeviceReference::DeviceReference(const DeviceReference& _copy)
-  : m_DSID(_copy.m_DSID),
-    m_Apartment(_copy.m_Apartment)
-  {
-  } // ctor(copy)
-
-  DeviceReference::DeviceReference(const dsid_t _dsid, const Apartment& _apartment)
-  : m_DSID(_dsid),
-    m_Apartment(&_apartment)
-  {
-  } // ctor(dsid)
-
-  DeviceReference::DeviceReference(const Device& _device, const Apartment& _apartment)
-  : m_DSID(_device.getDSID()),
-    m_Apartment(&_apartment)
-  {
-  } // ctor(device)
-
-  Device& DeviceReference::getDevice() {
-    return m_Apartment->getDeviceByDSID(m_DSID);
-  } // getDevice
-
-  const Device& DeviceReference::getDevice() const {
-    return m_Apartment->getDeviceByDSID(m_DSID);
-  } // getDevice
-
-  dsid_t DeviceReference::getDSID() const {
-    return m_DSID;
-  } // getID
-
-  std::string DeviceReference::getName() const {
-    return getDevice().getName();
-  } //getName
-
-  void DeviceReference::turnOn() {
-    getDevice().turnOn();
-  } // turnOn
-
-  void DeviceReference::turnOff() {
-    getDevice().turnOff();
-  } // turnOff
-
-  void DeviceReference::increaseValue(const int _parameterNr) {
-    getDevice().increaseValue(_parameterNr);
-  } // increaseValue
-
-  void DeviceReference::decreaseValue(const int _parameterNr) {
-    getDevice().decreaseValue(_parameterNr);
-  } // decreaseValue
-
-  void DeviceReference::enable() {
-    getDevice().enable();
-  } // enable
-
-  void DeviceReference::disable() {
-    getDevice().disable();
-  } // disable
-
-  void DeviceReference::startDim(const bool _directionUp, const int _parameterNr) {
-    getDevice().startDim(_directionUp, _parameterNr);
-  } // startDim
-
-  void DeviceReference::endDim(const int _parameterNr) {
-    getDevice().endDim(_parameterNr);
-  } // endDim
-
-  void DeviceReference::setValue(const double _value, const int _parameterNr) {
-    getDevice().setValue(_value, _parameterNr);
-  } // setValue
-
-  bool DeviceReference::isOn() const {
-    return getDevice().isOn();
-  }
-
-  bool DeviceReference::hasSwitch() const {
-    return getDevice().hasSwitch();
-  }
-
-  void DeviceReference::callScene(const int _sceneNr) {
-    getDevice().callScene(_sceneNr);
-  } // callScene
-
-  void DeviceReference::saveScene(const int _sceneNr) {
-    getDevice().saveScene(_sceneNr);
-  } // saveScene
-
-  void DeviceReference::undoScene(const int _sceneNr) {
-    getDevice().undoScene(_sceneNr);
-  } // undoScene
-
-  unsigned long DeviceReference::getPowerConsumption() {
-    return getDevice().getPowerConsumption();
-  }
-
-  void DeviceReference::nextScene() {
-    getDevice().nextScene();
-  }
-
-  void DeviceReference::previousScene() {
-    getDevice().previousScene();
-  }
-
-  void DeviceContainer::setName(const std::string& _name) {
-    if(m_Name != _name) {
-      m_Name = _name;
-      if(DSS::hasInstance()) {
-        DSS::getInstance()->getApartment().addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
-      }
-    }
-  }
-
-  //================================================== Utils
-
-  unsigned int SceneHelper::getNextScene(const unsigned int _currentScene) {
-    switch(_currentScene) {
-    case ScenePanic:
-    case SceneStandBy:
-    case SceneDeepOff:
-    case SceneOff:
-    case Scene1:
-      return Scene2;
-    case Scene2:
-      return Scene3;
-    case Scene3:
-      return Scene4;
-    case Scene4:
-      return Scene2;
-    default:
-      return Scene1;
-    }
-  } // getNextScene
-
-  unsigned int SceneHelper::getPreviousScene(const unsigned int _currentScene) {
-    switch(_currentScene) {
-    case ScenePanic:
-    case SceneStandBy:
-    case SceneDeepOff:
-    case SceneOff:
-    case Scene1:
-      return Scene4;
-    case Scene2:
-      return Scene4;
-    case Scene3:
-      return Scene2;
-    case Scene4:
-      return Scene3;
-    default:
-      return Scene1;
-    }
-  } // getPreviousScene
-
-  bool SceneHelper::m_Initialized = false;
-  std::bitset<64> SceneHelper::m_ZonesToIgnore;
-
-  void SceneHelper::initialize() {
-    m_Initialized = true;
-    m_ZonesToIgnore.reset();
-    m_ZonesToIgnore.set(SceneInc);
-    m_ZonesToIgnore.set(SceneDec);
-    m_ZonesToIgnore.set(SceneStop);
-    m_ZonesToIgnore.set(SceneBell);
-    m_ZonesToIgnore.set(SceneEnergyOverload);
-    m_ZonesToIgnore.set(SceneEnergyHigh);
-    m_ZonesToIgnore.set(SceneEnergyMiddle);
-    m_ZonesToIgnore.set(SceneEnergyLow);
-    m_ZonesToIgnore.set(SceneEnergyClassA);
-    m_ZonesToIgnore.set(SceneEnergyClassB);
-    m_ZonesToIgnore.set(SceneEnergyClassC);
-    m_ZonesToIgnore.set(SceneEnergyClassD);
-    m_ZonesToIgnore.set(SceneEnergyClassE);
-    m_ZonesToIgnore.set(SceneLocalOff);
-    m_ZonesToIgnore.set(SceneLocalOn);
-  }
-
-  bool SceneHelper::rememberScene(const unsigned int _scene) {
-    if(!m_Initialized) {
-      initialize();
-      assert(m_Initialized);
-    }
-    return !m_ZonesToIgnore.test(_scene);
-  } // rememberScene
-
-}
diff --git a/core/model.h b/core/model.h
deleted file mode 100644
index 4a053fc..0000000
--- a/core/model.h
+++ /dev/null
@@ -1,1010 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 _MODEL_H_INCLUDED
-#define _MODEL_H_INCLUDED
-
-#include <bitset>
-
-#include "base.h"
-#include "datetools.h"
-#include "ds485types.h"
-#include "thread.h"
-#include "subsystem.h"
-#include "mutex.h"
-#include "syncevent.h"
-
-#include <vector>
-#include <string>
-
-#include <boost/utility.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/tuple/tuple.hpp>
-
-namespace Poco {
-  namespace XML {
-    class Node;
-  }
-}
-
-namespace dss {
-
-  class Device;
-  class Set;
-  class DeviceContainer;
-  class Apartment;
-  class Group;
-  class Modulator;
-  class PropertyNode;
-  class Event;
-  typedef boost::shared_ptr<PropertyNode> PropertyNodePtr;
-
-  class PhysicalModelItem {
-  private:
-    bool m_IsPresent;
-  public:
-    PhysicalModelItem()
-    : m_IsPresent(false)
-    { }
-
-    bool isPresent() const { return m_IsPresent; }
-    void setIsPresent(const bool _value) { m_IsPresent = _value; }
-  };
-
-  /** Interface to a single or multiple devices.
-   */
-  class IDeviceInterface {
-  public:
-    /** Turns the device on.
-     *  This will invoke scene "max".
-     */
-    virtual void turnOn() = 0;
-    /** Turns the device off.
-     * This will invoke scene "min"
-     */
-    virtual void turnOff() = 0;
-
-    /** Increases the value of the given parameter by one,
-     * If no parameter gets passed, it will increase the default value of the device(s).
-     */
-    virtual void increaseValue(const int _parameterNr = -1) = 0;
-    /** Decreases the value of the given parameter by one.
-     * If no parameter gets passed, it will decrease the default value of the device(s).
-     */
-    virtual void decreaseValue(const int _parameterNr = -1) = 0;
-
-    /** Enables a previously disabled device.
-     */
-    virtual void enable() = 0;
-    /** Disables a device.
-      * A disabled device may only react to enable().
-      */
-    virtual void disable() = 0;
-
-    /** Starts dimming the given parameter.
-     * If _directionUp is true, the value gets increased over time. Else its getting decreased.
-     */
-    virtual void startDim(bool _directionUp, const int _parameterNr = -1) = 0;
-    /** Stops the dimming */
-    virtual void endDim(const int _parameterNr = -1)= 0;
-    /** Sets the value of the given parameter */
-    virtual void setValue(const double _value, int _parameterNr = -1) = 0;
-
-
-    /** Sets the scene on the device.
-     * The output value will be set according to the scene lookup table in the device.
-     */
-    virtual void callScene(const int _sceneNr) = 0;
-    /** Stores the current output value into the scene lookup table.
-     * The next time scene _sceneNr gets called the output will be set according to the lookup table.
-     */
-    virtual void saveScene(const int _sceneNr) = 0;
-    /** Restores the last set value of _sceneNr
-     */
-    virtual void undoScene(const int _sceneNr) = 0;
-
-    /** Returns the consumption in mW */
-    virtual unsigned long getPowerConsumption() = 0;
-
-    /** Calls the next scene according to the last called scene.
-     * @see dss::SceneHelper::getNextScene
-     */
-    virtual void nextScene() = 0;
-    /** Calls the previos scene according to the last called scene.
-     * @see dss::SceneHelper::getPreviousScene
-     */
-    virtual void previousScene() = 0;
-
-    virtual ~IDeviceInterface() {};
-  };
-
-  /** Internal reference to a device.
-   * A DeviceReference is virtually interchangable with a device. It is used in places
-     where a reference to a device is needed.
-   */
-  class DeviceReference : public IDeviceInterface {
-  private:
-    dsid_t m_DSID;
-    const Apartment* m_Apartment;
-  public:
-    /** Copy constructor */
-    DeviceReference(const DeviceReference& _copy);
-    DeviceReference(const dsid_t _dsid, const Apartment& _apartment);
-    DeviceReference(const Device& _device, const Apartment& _apartment);
-    virtual ~DeviceReference() {};
-
-    /** Returns a reference to the referenced device
-     * @note This accesses the apartment which has to be valid.
-     */
-    Device& getDevice();
-    /** @copydoc getDevice() */
-    const Device& getDevice() const;
-    /** Returns the DSID of the referenced device */
-    dsid_t getDSID() const;
-
-    /** Returns the function id.
-     * @note This will lookup the device */
-    int getFunctionID() const;
-    bool hasSwitch() const;
-
-    /** Compares two device references.
-     * Device references are considered equal if their DSID match. */
-    bool operator==(const DeviceReference& _other) const {
-      return m_DSID == _other.m_DSID;
-    }
-
-    /** Returns the name of the referenced device.
-     * @note This will lookup the device. */
-    std::string getName() const;
-
-    virtual void turnOn();
-    virtual void turnOff();
-
-    virtual void increaseValue(const int _parameterNr = -1);
-    virtual void decreaseValue(const int _parameterNr = -1);
-
-    virtual void enable();
-    virtual void disable();
-
-    /** Returns wheter the device is turned on.
-     * @note The detection is soly based on the last called scene. As soon as we've
-     * got submetering data this should reflect the real state.
-     */
-    virtual bool isOn() const;
-
-    virtual void startDim(const bool _directionUp, const int _parameterNr = -1);
-    virtual void endDim(const int _parameterNr = -1);
-    virtual void setValue(const double _value, const int _parameterNr = -1);
-
-    virtual void callScene(const int _sceneNr);
-    virtual void saveScene(const int _sceneNr);
-    virtual void undoScene(const int _sceneNr);
-
-    virtual void nextScene();
-    virtual void previousScene();
-
-    virtual unsigned long getPowerConsumption();
- }; // DeviceReference
-
-  typedef std::vector<DeviceReference> DeviceVector;
-  typedef DeviceVector::iterator DeviceIterator;
-  typedef DeviceVector::const_iterator DeviceConstIterator;
-  typedef boost::tuple<double, double, double> DeviceLocation;
-
-  /** Represents a dsID */
-  class Device : public IDeviceInterface,
-                 public PhysicalModelItem,
-                 public boost::noncopyable {
-  private:
-    std::string m_Name;
-    dsid_t m_DSID;
-    devid_t m_ShortAddress;
-    int m_ModulatorID;
-    int m_ZoneID;
-    Apartment* m_pApartment;
-    std::bitset<63> m_GroupBitmask;
-    std::vector<int> m_Groups;
-    int m_FunctionID;
-    int m_LastCalledScene;
-    unsigned long m_Consumption;
-    DateTime m_LastDiscovered;
-    DateTime m_FirstSeen;
-
-    PropertyNodePtr m_pPropertyNode;
-    PropertyNodePtr m_pAliasNode;
-  protected:
-    /** Sends the application a note that something has changed.
-     * This will cause the \c apartment.xml to be updated. */
-    void dirty();
-  public:
-    /** Creates and initializes a device. */
-    Device(const dsid_t _dsid, Apartment* _pApartment);
-    virtual ~Device() {};
-
-    virtual void turnOn();
-    virtual void turnOff();
-
-    virtual void increaseValue(const int _parameterNr = -1);
-    virtual void decreaseValue(const int _parameterNr = -1);
-
-    virtual void enable();
-    virtual void disable();
-
-    /** @copydoc DeviceReference::isOn() */
-    virtual bool isOn() const;
-
-    virtual void startDim(const bool _directionUp, const int _parameterNr = -1);
-    virtual void endDim(const int _parameterNr = -1);
-    virtual void setValue(const double _value, const int _parameterNr = -1);
-    void setRawValue(const uint16_t _value, const int _parameterNr, const int _size);
-    /** Returns the value of _parameterNr.
-     * @note not yet implemented */
-    double getValue(const int _parameterNr = -1);
-
-    virtual void callScene(const int _sceneNr);
-    virtual void saveScene(const int _sceneNr);
-    virtual void undoScene(const int _sceneNr);
-
-    virtual void nextScene();
-    virtual void previousScene();
-
-    /** Returns the function ID of the device.
-     * A function ID specifies a certain subset of functionality that
-     * a device implements.
-     */
-    int getFunctionID() const;
-    /** Sets the functionID to \a _value */
-    void setFunctionID(const int _value);
-    bool hasSwitch() const;
-
-    /** Returns the name of the device. */
-    std::string getName() const;
-    /** Sets the name of the device.
-     * @note This will cause the apartment to store
-     * \c apartment.xml
-     */
-    void setName(const std::string& _name);
-
-    /** Returns the group bitmask (1 based) of the device */
-    std::bitset<63>& getGroupBitmask();
-    /** @copydoc getGroupBitmask() */
-    const std::bitset<63>& getGroupBitmask() const;
-
-    /** Returns wheter the device is in group \a _groupID or not. */
-    bool isInGroup(const int _groupID) const;
-    /** Adds the device to group \a _groupID. */
-    void addToGroup(const int _groupID);
-    /** Removes the device from group \a _groupID */
-    void removeFromGroup(const int _groupID);
-
-    /** Returns the group id of the \a _index'th group */
-    int getGroupIdByIndex(const int _index) const;
-    /** Returns \a _index'th group of the device */
-    Group& getGroupByIndex(const int _index);
-    /** Returns the number of groups the device is a member of */
-    int getGroupsCount() const;
-
-    /** Removes the device from all group.
-     * The device will remain in the broadcastgroup though.
-     */
-    void resetGroups();
-
-    /** Returns the last called scene.
-     * At the moment this information is used to determine wheter a device is
-     * turned on or not. */
-    int getLastCalledScene() const { return m_LastCalledScene; }
-    /** Sets the last called scene. */
-    void setLastCalledScene(const int _value) { m_LastCalledScene = _value; }
-
-    /** Returns the short address of the device. This is the address
-     * the device got from the dSM. */
-    devid_t getShortAddress() const;
-    /** Sets the short-address of the device. */
-    void setShortAddress(const devid_t _shortAddress);
-    /** Returns the DSID of the device */
-    dsid_t getDSID() const;
-    /** Returns the id of the modulator the device is connected to */
-    int getModulatorID() const;
-    /** Sets the modulatorID of the device. */
-    void setModulatorID(const int _modulatorID);
-
-    /** Returns the zone ID the device resides in. */
-    int getZoneID() const;
-    /** Sets the zone ID of the device. */
-    void setZoneID(const int _value);
-    /** Returns the apartment the device resides in. */
-    Apartment& getApartment() const;
-    
-    const DateTime& getLastDiscovered() const { return m_LastDiscovered; }
-    const DateTime& getFirstSeen() const { return m_FirstSeen; }
-    void setFirstSeen(const DateTime& _value) { m_FirstSeen = _value; }
-
-    virtual unsigned long getPowerConsumption();
-
-    /** Sends a byte to the device using dsLink. If \a _writeOnly is \c true,
-     * the result of the function is not defined. */
-    uint8_t dsLinkSend(uint8_t _value, bool _lastByte, bool _writeOnly);
-    int getSensorValue(const int _sensorID);
-
-    const PropertyNodePtr& getPropertyNode() const { return m_pPropertyNode; }
-    PropertyNodePtr getPropertyNode() { return m_pPropertyNode; }
-
-    /** Publishes the device to the property tree.
-     * @see DSS::getPropertySystem */
-    void publishToPropertyTree();
-
-    /** Returns wheter two devices are equal.
-     * Devices are considered equal if their DSID are a match.*/
-    bool operator==(const Device& _other) const;
-  }; // Device
-
-  std::ostream& operator<<(std::ostream& out, const Device& _dt);
-
-  /** Abstract interface to select certain Devices from a set */
-  class IDeviceSelector {
-  public:
-    /** The implementor should return true if the device should appear in the
-     * resulting set. */
-    virtual bool selectDevice(const Device& _device) const = 0;
-    virtual ~IDeviceSelector() {}
-  };
-
-  /** Abstract interface to perform an Action on each device of a set */
-  class IDeviceAction {
-  public:
-    /** This action will be performed for every device contained in the set. */
-    virtual bool perform(Device& _device) = 0;
-    virtual ~IDeviceAction() {}
-  };
-
-  /** A set holds an arbitrary list of devices.
-    * A Command sent to an instance of this class will replicate the command to all
-    * contained devices.
-    * Only references to devices will be stored.
-   */
-  class Set : public IDeviceInterface {
-  private:
-    DeviceVector m_ContainedDevices;
-  public:
-    /** Constructor for an empty Set.*/
-    Set();
-    /** Copy constructor. */
-    Set(const Set& _copy);
-    /** Constructor for a set containing only \a _device. */
-    Set(Device& _device);
-    /** Constructor for a set containing only \a _reference. */
-    Set(DeviceReference& _reference);
-    /** Constructor for a set containing \a _devices. */
-    Set(DeviceVector _devices);
-    virtual ~Set() {};
-
-    virtual void turnOn();
-    virtual void turnOff();
-
-    virtual void increaseValue(const int _parameterNr = -1);
-    virtual void decreaseValue(const int _parameterNr = -1);
-
-    virtual void enable();
-    virtual void disable();
-
-    virtual void startDim(bool _directionUp, const int _parameterNr = -1);
-    virtual void endDim(const int _parameterNr = -1);
-    virtual void setValue(const double _value, int _parameterNr = -1);
-
-    virtual void callScene(const int _sceneNr);
-    virtual void saveScene(const int _sceneNr);
-    virtual void undoScene(const int _sceneNr);
-
-    /** Performs the given action on all contained devices */
-    void perform(IDeviceAction& _deviceAction);
-
-    /** Returns a subset selected by the given selector
-     * A device will be included in the resulting set if _selector.selectDevice(...) return true.
-     */
-    Set getSubset(const IDeviceSelector& _selector) const;
-    /** Returns a subset of the devices which are member of the given group
-    * Note that these groups could be spanned over multiple modulators.
-     */
-    Set getByGroup(int _groupNr) const;
-    /** Returns a subset of the devices which are member of the given group
-     * Note that these groups could be spanned over multiple modulators.
-     */
-    Set getByGroup(const Group& _group) const;
-    /** Returns a subset of the devices which are member of the given group
-     * Note that these groups could be spanned over multiple modulators.
-     */
-    Set getByGroup(const std::string& _name) const;
-
-    /** Returns a subset of devices with the given function-id. */
-    Set getByFunctionID(const int _functionID) const;
-
-    /** Returns a subset that contains all devices belonging to Zone \a _zoneID. */
-    Set getByZone(int _zoneID) const;
-
-    /** Returns a subset that contains all devices belonging to Zone \a _zoneName */
-    Set getByZone(const std::string& _zoneName) const;
-
-    /** Returns a subset that contains all devices belonging to Modulator \a _modulatorID */
-    Set getByModulator(const int _modulatorID) const;
-    /** Returns a subset that contains all devices belonging to Modulator \a _modulator */
-    Set getByModulator(const Modulator& _modulator) const;
-
-    /** Returns a subset that contains all devices that have the presence state of \a _present */
-    Set getByPresence(const bool _present) const;
-
-    /** Returns the device indicated by _name
-     */
-    DeviceReference getByName(const std::string& _name) const;
-    /** Returns the device indicated by \a _busid */
-    DeviceReference getByBusID(const devid_t _busid) const;
-
-    /** Returns the device indicated by \a _dsid */
-    DeviceReference getByDSID(const dsid_t _dsid)  const;
-
-    /** Returns the number of devices contained in this set */
-    int length() const;
-    /** Returns true if the set is empty */
-    bool isEmpty() const;
-
-    /** Returns a set that's combined with the set _other.
-     * Duplicates get filtered out.
-     */
-    Set combine(Set& _other) const;
-    /* Returns a set with all device in _other removed */
-    Set remove(const Set& _other) const;
-
-    /** Returns the \a _index'th device */
-    const DeviceReference& get(int _index) const;
-    /** @copydoc get */
-    const DeviceReference& operator[](const int _index) const;
-
-    /** @copydoc get */
-    DeviceReference& get(int _index);
-    /** @copydoc get */
-    DeviceReference& operator[](const int _index);
-
-    /** Returns true if the set contains \a _device */
-    bool contains(const DeviceReference& _device) const;
-    /** Returns true if the set contains \a _device */
-    bool contains(const Device& _device) const;
-
-    /** Adds the device \a _device to the set */
-    void addDevice(const DeviceReference& _device);
-    /** Adds the device \a _device to the set */
-    void addDevice(const Device& _device);
-
-    /** Removes the device \a _device from the set */
-    void removeDevice(const DeviceReference& _device);
-    /** Removes the device \a _device from the set */
-    void removeDevice(const Device& _device);
-
-    virtual void nextScene();
-    virtual void previousScene();
-
-    virtual unsigned long getPowerConsumption();
-  }; // Set
-
-
-  /** A class derived from DeviceContainer can deliver a Set of its Devices */
-  class DeviceContainer {
-  private:
-    std::string m_Name;
-  public:
-    /** Returns a set containing all devices of the container. */
-    virtual Set getDevices() const = 0;
-    /** Returns a subset of the devices contained, selected by \a _selector */
-    virtual Set getDevices(const IDeviceSelector& _selector) const {
-      return getDevices().getSubset(_selector);
-    }
-
-    /** Sets the name of the container. */
-    virtual void setName(const std::string& _name);
-    /** Returns the name of the container */
-    const std::string& getName() const { return m_Name; };
-
-    virtual ~DeviceContainer() {};
-  }; // DeviceContainer
-
-  /** Represents a Modulator */
-  class Modulator : public DeviceContainer,
-                    public PhysicalModelItem {
-  private:
-    dsid_t m_DSID;
-    int m_BusID;
-    DeviceVector m_ConnectedDevices;
-    int m_EnergyLevelOrange;
-    int m_EnergyLevelRed;
-    int m_PowerConsumption;
-    DateTime m_PowerConsumptionAge;
-    int m_EnergyMeterValue;
-    DateTime m_EnergyMeterValueAge;
-    int m_HardwareVersion;
-    int m_SoftwareVersion;
-    std::string m_HardwareName;
-    int m_DeviceType;
-    bool m_IsValid;
-  public:
-    /** Constructs a modulator with the given dsid. */
-    Modulator(const dsid_t _dsid);
-    virtual ~Modulator() {};
-    virtual Set getDevices() const;
-
-    /** Returns the DSID of the Modulator */
-    dsid_t getDSID() const;
-    /** Returns the bus id of the Modulator */
-    int getBusID() const;
-    /** Sets the bus id of the Modulator */
-    void setBusID(const int _busID);
-
-    /** Adds a DeviceReference to the modulators devices list */
-    void addDevice(const DeviceReference& _device);
-
-    /** Removes the device identified by the reference. */
-    void removeDevice(const DeviceReference& _device);
-
-    /** Returns the consumption in mW */
-    unsigned long getPowerConsumption();
-    /** Returns the meter value in Wh */
-    unsigned long getEnergyMeterValue();
-
-
-    /** set the consumption in mW */
-    void setPowerConsumption(unsigned long _value);
-    /** set the meter value in Wh */
-    void setEnergyMeterValue(unsigned long _value);
-
-    /** Returns the last consumption in mW returned from dS485 Bus, but never request it*/
-    unsigned long getCachedPowerConsumption();
-    /** Returns the last meter value in Wh returned from dS485 Bus, but never request it*/
-    unsigned long getCachedEnergyMeterValue();
-    
-    /** Returns the orange energy level */
-    int getEnergyLevelOrange() const { return m_EnergyLevelOrange; }
-    /** Returns the red energy level */
-    int getEnergyLevelRed() const { return m_EnergyLevelRed; }
-    /** Sets the orange energy level.
-     * @note This has no effect on the modulator as of now. */
-    void setEnergyLevelRed(const int _value) { m_EnergyLevelRed = _value; }
-    /** Sets the red energy level.
-     * @note This has no effect on the modulator as of now. */
-    void setEnergyLevelOrange(const int _value) { m_EnergyLevelOrange = _value; }
-
-    int getHardwareVersion() const { return m_HardwareVersion; }
-    void setHardwareVersion(const int _value) { m_HardwareVersion = _value; }
-    int getSoftwareVersion() const { return m_SoftwareVersion; }
-    void setSoftwareVersion(const int _value) { m_SoftwareVersion = _value; }
-    std::string getHardwareName() const { return m_HardwareName; }
-    void setHardwareName(const std::string& _value) { m_HardwareName = _value; }
-    int getDeviceType() { return m_DeviceType; }
-    void setDeviceType(const int _value) { m_DeviceType = _value; }
-
-    /** Returns true if the modulator has been read-out completely. */
-    bool isValid() const { return m_IsValid; }
-    void setIsValid(const bool _value) { m_IsValid = _value; }
-  }; // Modulator
-
-  /** Represents a predefined group */
-  class Group : public DeviceContainer,
-                public IDeviceInterface,
-                public PhysicalModelItem  {
-  protected:
-    DeviceVector m_Devices;
-    Apartment& m_Apartment;
-    int m_ZoneID;
-    int m_GroupID;
-    int m_LastCalledScene;
-  public:
-    /** Constructs a group with the given id belonging to \a _zoneID. */
-    Group(const int _id, const int _zoneID, Apartment& _apartment);
-    virtual ~Group() {};
-    virtual Set getDevices() const;
-
-    /** Returns the id of the group */
-    int getID() const;
-    int getZoneID() const;
-
-    virtual void turnOn();
-    virtual void turnOff();
-
-    virtual void increaseValue(const int _parameterNr = -1);
-    virtual void decreaseValue(const int _parameterNr = -1);
-
-    virtual void enable();
-    virtual void disable();
-
-    virtual void startDim(bool _directionUp, const int _parameterNr = -1);
-    virtual void endDim(const int _parameterNr = -1);
-    virtual void setValue(const double _value, int _parameterNr = -1);
-
-    virtual void callScene(const int _sceneNr);
-    virtual void saveScene(const int _sceneNr);
-    virtual void undoScene(const int _sceneNr);
-
-    virtual void nextScene();
-    virtual void previousScene();
-
-    virtual unsigned long getPowerConsumption();
-
-    /** @copydoc Device::getLastCalledScene */
-    int getLastCalledScene() const { return m_LastCalledScene; }
-    /** @copydoc Device::setLastCalledScene */
-    void setLastCalledScene(const int _value) { m_LastCalledScene = _value; }
-
-    /** Compares a group to another group.
-     * Two groups are considered equal if they belong to the same group and zone. */
-    Group& operator=(const Group& _other);
-  }; // Group
-
-
-  /** Represents a user-defined-group */
-  class UserGroup : public Group {
-  private:
-  public:
-    /** Adds a device to the group.
-     * This will permanently add the device to the group.
-     */
-    virtual void addDevice(const Device& _device);
-    /** Removes a device from the group.
-     * This will permanently remove the device from the group.
-     */
-    virtual void removeDevice(const Device& _device);
-  }; // UserGroup
-
-  /** Represents a Zone.
-   * A Zone houses multiple devices. It can span over multiple modulators.
-   */
-  class Zone : public DeviceContainer,
-               public IDeviceInterface,
-               public PhysicalModelItem,
-               public boost::noncopyable {
-  private:
-    int m_ZoneID;
-    DeviceVector m_Devices;
-    std::vector<const Modulator*> m_Modulators;
-    std::vector<Group*> m_Groups;
-    int m_FirstZoneOnModulator;
-  public:
-  	Zone(const int _id)
-  	: m_ZoneID(_id),
-          m_FirstZoneOnModulator(-1)
-  	{}
-    virtual ~Zone();
-    virtual Set getDevices() const;
-
-    /** Adds the Zone to a modulator. */
-    void addToModulator(const Modulator& _modulator);
-    /** Removes the Zone from a modulator. */
-    void removeFromModulator(const Modulator& _modulator);
-
-    /** Adds a device to the zone.
-     * This will permanently add the device to the zone.
-     */
-    void addDevice(DeviceReference& _device);
-
-    /** Removes a device from the zone.
-     * This will permanently remove the device from the zone.
-     */
-    void removeDevice(const DeviceReference& _device);
-
-    /** Returns the group with the name \a _name */
-    Group* getGroup(const std::string& _name) const;
-    /** Returns the group with the id \a _id */
-    Group* getGroup(const int _id) const;
-
-    /** Adds a group to the zone */
-    void addGroup(Group* _group);
-    /** Removes a group from the zone */
-    void removeGroup(UserGroup* _group);
-
-    /** Returns the zones id */
-    int getID() const;
-    /** Sets the zones id */
-    void setZoneID(const int _value);
-
-    /** Returns the ID of the modulator the zone is the first 
-      * zone on.
-      * @return The modulator id, or -1 
-      */
-    int getFirstZoneOnModulator() { return m_FirstZoneOnModulator; }
-    void setFirstZoneOnModulator(const int _value) { m_FirstZoneOnModulator = _value; }
-
-    /** Returns a list of the modulators the zone is registered with. */
-    std::vector<int> getModulators() const;
-    bool registeredOnModulator(const Modulator& _modulator) const;
-
-    virtual void turnOn();
-    virtual void turnOff();
-
-    virtual void increaseValue(const int _parameterNr = -1);
-    virtual void decreaseValue(const int _parameterNr = -1);
-
-    virtual void enable();
-    virtual void disable();
-
-    virtual void startDim(bool _directionUp, const int _parameterNr = -1);
-    virtual void endDim(const int _parameterNr = -1);
-    virtual void setValue(const double _value, int _parameterNr = -1);
-
-    virtual void callScene(const int _sceneNr);
-    virtual void saveScene(const int _sceneNr);
-    virtual void undoScene(const int _sceneNr);
-
-    virtual void nextScene();
-    virtual void previousScene();
-
-    virtual unsigned long getPowerConsumption();
-    /** Returns a vector of groups present on the zone. */
-    std::vector<Group*> getGroups() { return m_Groups; }
-  }; // Zone
-
-
-  /** A Model event gets processed by the apartment asynchronously.
-   * It consists of multiple integer parameter whose meanig is defined by ModelEvent::EventType
-   */
-  class ModelEvent {
-  public:
-    typedef enum { etCallSceneGroup,  /**< A group has changed the scene. */
-                   etCallSceneDevice, /**< A device has changed the scene (only raised from the simulation at the moment). */
-                   etNewDevice,       /**< A new device has been detected */
-                   etModelDirty,      /**< A parameter that will be stored in \c apartment.xml has been changed. */
-                   etDSLinkInterrupt,  /**< An interrupt has occured */
-                   etNewModulator, /**< A new modulator has joined the bus */
-                   etLostModulator, /**< We've lost a modulator on the bus */
-                   etModulatorReady, /**< A modulator has completed its scanning cycle and is now ready */
-                   etBusReady, /**< The bus transitioned into ready state */
-                   etPowerConsumption, /**< Powerconsumption message happened */
-                   etEnergyMeterValue, /**< Powerconsumption message happened */
-                   etDS485DeviceDiscovered, /**< A new device has been discovered on the bus */
-                 } EventType;
-  private:
-    EventType m_EventType;
-    std::vector<int> m_Parameter;
-  public:
-    /** Constructs a ModelEvent with the given EventType. */
-    ModelEvent(EventType _type)
-    : m_EventType(_type)
-    {}
-
-    /** Adds an integer parameter. */
-    void addParameter(const int _param) { m_Parameter.push_back(_param); }
-    /** Returns the parameter at _index.
-     * @note Check getParameterCount to check the bounds. */
-    int getParameter(const int _index) const { return m_Parameter.at(_index); }
-    /** Returns the parameter count. */
-    int getParameterCount() const { return m_Parameter.size(); }
-    /** Returns the type of the event. */
-    EventType getEventType() { return m_EventType; }
-  };
-
-  /** Represents an Apartment
-    * This is the root of the datamodel of the dss. The Apartment is responsible for delivering
-    * and loading all subitems.
-    */
-  class Apartment : public boost::noncopyable,
-                    public DeviceContainer,
-                    public Subsystem,
-                    public LockableObject,
-                    public Thread
-  {
-  private:
-    std::vector<Zone*> m_Zones;
-    std::vector<Modulator*> m_Modulators;
-    std::vector<Device*> m_Devices;
-    bool m_IsInitializing;
-
-    PropertyNodePtr m_pPropertyNode;
-
-    boost::ptr_vector<ModelEvent> m_ModelEvents;
-    Mutex m_ModelEventsMutex;
-    SyncEvent m_NewModelEvent;
-  private:
-    void loadDevices(Poco::XML::Node* _node);
-    void loadModulators(Poco::XML::Node* _node);
-    void loadZones(Poco::XML::Node* _node);
-
-    void addDefaultGroupsToZone(Zone& _zone);
-    void handleModelEvents();
-    void modulatorReady(int _modulatorBusID);
-    void setPowerConsumption(int _modulatorBusID, unsigned long _value);
-    void setEnergyMeterValue(int _modulatorBusID, unsigned long _value);
-    void discoverDS485Devices();
-
-    void raiseEvent(boost::shared_ptr<Event> _pEvent);
-    void waitForInterface();
-  protected:
-    virtual void doStart();
-  public:
-    Apartment(DSS* _pDSS);
-    virtual ~Apartment();
-
-    virtual void initialize();
-
-    /** Returns a set containing all devices of the set */
-    virtual Set getDevices() const;
-
-    /** Loads the datamodel and marks the contained items as "stale" */
-    void readConfigurationFromXML(const std::string& _fileName);
-    void readConfiguration();
-
-    void writeConfigurationToXML(const std::string& _fileName);
-    void writeConfiguration();
-
-    /** Returns a reference to the device with the DSID \a _dsid */
-    Device& getDeviceByDSID(const dsid_t _dsid) const;
-    /** @copydoc getDeviceByDSID */
-    Device& getDeviceByDSID(const dsid_t _dsid);
-    /** Returns a reference to the device with the name \a _name*/
-    Device& getDeviceByName(const std::string& _name);
-    /** Returns a device by it's short-address and modulator */
-    Device& getDeviceByShortAddress(const Modulator& _modulator, const devid_t _deviceID) const;
-
-    /** Allocates a device and returns a reference to it.
-     *  If there is a stale device with the same dsid, this device gets "activated"
-     */
-    Device& allocateDevice(const dsid_t _dsid);
-
-    /** Returns the Zone by name */
-    Zone& getZone(const std::string& _zoneName);
-    /** Returns the Zone by its id */
-    Zone& getZone(const int _id);
-    /** Returns a vector of all zones */
-    std::vector<Zone*>& getZones();
-
-    /** Allocates a zone and returns a reference to it. Should a zone with
-      * the given _zoneID already exist, a reference to the existing zone will
-      * be returned.
-      * NOTE: Outside code should never call this function
-      */
-    Zone& allocateZone(int _zoneID);
-    
-    Modulator& allocateModulator(const dsid_t _dsid);
-
-    /** Returns a Modulator by name */
-    Modulator& getModulator(const std::string& _modName);
-    /** Returns a Modulator by DSID  */
-    Modulator& getModulatorByDSID(const dsid_t _dsid);
-    /** Returns a Modulator by bus-id */
-    Modulator& getModulatorByBusID(const int _busID);
-    /** Returns a vector of all modulators */
-    std::vector<Modulator*>& getModulators();
-
-    /** Returns a Group by name */
-    Group& getGroup(const std::string& _name);
-    /** Returns a Group by id */
-    Group& getGroup(const int _id);
-
-    /** 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 removeModulator(dsid_t _modulator);
-
-    bool scanModulator(Modulator& _modulator);
-  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 _modulatorID, 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();
-  }; // Apartment
-
-  //============================================= Helper definitions
-  typedef bool (*DeviceSelectorFun)(const Device& _device);
-
-  /** Device selector that works on simple function instead of classes */
-  class DeviceSelector : public IDeviceSelector {
-  private:
-    DeviceSelectorFun m_SelectorFunction;
-  public:
-    DeviceSelector(DeviceSelectorFun& _selectorFun) : m_SelectorFunction(_selectorFun) {}
-    virtual bool selectDevice(const Device& _device) { return m_SelectorFunction(_device); }
-
-    virtual ~DeviceSelector() {}
-  }; // DeviceSelector
-
-  /** Exception that will be thrown if a given item could not be found */
-  class ItemNotFoundException : public DSSException {
-  public:
-    ItemNotFoundException(const std::string& _name) : DSSException(std::string("Could not find item ") + _name) {};
-    ~ItemNotFoundException() throw() {}
-  };
-
-  /** Helper functions for scene management. */
-  class SceneHelper {
-  private:
-    static std::bitset<64> m_ZonesToIgnore;
-    static bool m_Initialized;
-
-    static void initialize();
-  public:
-    /** Returns wheter to remember a scene.
-     * Certain scenes represent events thus they won't have to be remembered.
-     */
-    static bool rememberScene(const unsigned int _sceneID);
-    /** Returns the next scene based on _currentScene.
-     * From off to Scene1 -> Scene2 -> Scene3 -> Scene4 -> Scene1...
-     * \param _currentScene Scene now active.
-     */
-    static unsigned int getNextScene(const unsigned int _currentScene);
-    /** Returns the previous scene based on _currentScene.
-     * From off to Scene1 -> Scene4 -> Scene3 -> Scene2 -> Scene1...
-     * \param _currentScene Scene now active.
-     */
-    static unsigned int getPreviousScene(const unsigned int _currentScene);
-  }; // SceneHelper
-
-}
-
-//#ifdef DOC
-
-#ifndef WIN32
-#include <ext/hash_map>
-#else
-#include <hash_map>
-#endif
-#include <stdexcept>
-
-#ifndef WIN32
-using namespace __gnu_cxx;
-#else
-using namespace stdext;
-#endif
-
-namespace __gnu_cxx
-{
-  template<>
-  struct hash<const dss::Modulator*>  {
-    size_t operator()(const dss::Modulator* x) const  {
-      return x->getDSID().lower;
-    }
-  };
-
-  template<>
-  struct hash<const dss::Zone*>  {
-    size_t operator()(const dss::Zone* x) const  {
-      return x->getID();
-    }
-  };
-}
-
-//#endif // DOC
-#endif // MODEL_H_INCLUDED
diff --git a/core/model/CMakeLists.txt b/core/model/CMakeLists.txt
new file mode 100644
index 0000000..2d00c21
--- /dev/null
+++ b/core/model/CMakeLists.txt
@@ -0,0 +1 @@
+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)
diff --git a/core/model/addressablemodelitem.cpp b/core/model/addressablemodelitem.cpp
new file mode 100644
index 0000000..1a97a41
--- /dev/null
+++ b/core/model/addressablemodelitem.cpp
@@ -0,0 +1,99 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "addressablemodelitem.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include "core/model/busrequest.h"
+#include "core/model/apartment.h"
+
+namespace dss {
+
+  //================================================== AddressableModelItem
+
+  AddressableModelItem::AddressableModelItem(Apartment* _pApartment)
+  : m_pApartment(_pApartment)
+  {} // ctor
+
+
+  void AddressableModelItem::increaseValue() {
+    boost::shared_ptr<IncreaseValueCommandBusRequest> request(new IncreaseValueCommandBusRequest());
+    request->setTarget(this);
+    m_pApartment->dispatchRequest(request);
+  }
+
+  void AddressableModelItem::decreaseValue() {
+    boost::shared_ptr<DecreaseValueCommandBusRequest> request(new DecreaseValueCommandBusRequest());
+    request->setTarget(this);
+    m_pApartment->dispatchRequest(request);
+  }
+
+  void AddressableModelItem::startDim(const bool _directionUp) {
+    boost::shared_ptr<CommandBusRequest> request;
+    if(_directionUp) {
+      request.reset(new StartDimUpCommandBusRequest());
+    } else {
+      request.reset(new StartDimDownCommandBusRequest());
+    }
+    request->setTarget(this);
+    m_pApartment->dispatchRequest(request);
+  } // startDim
+
+  void AddressableModelItem::endDim() {
+    boost::shared_ptr<CommandBusRequest> request(new EndDimCommandBusRequest());
+    request->setTarget(this);
+    m_pApartment->dispatchRequest(request);
+  } // endDim
+
+  void AddressableModelItem::setValue(const double _value) {
+    boost::shared_ptr<SetValueCommandBusRequest> request(new SetValueCommandBusRequest());
+    request->setTarget(this);
+    request->setValue(_value);
+    m_pApartment->dispatchRequest(request);
+  } // setValue
+
+  void AddressableModelItem::callScene(const int _sceneNr) {
+    boost::shared_ptr<CallSceneCommandBusRequest> request(new CallSceneCommandBusRequest());
+    request->setTarget(this);
+    request->setSceneID(_sceneNr);
+    m_pApartment->dispatchRequest(request);
+  } // callScene
+
+  void AddressableModelItem::saveScene(const int _sceneNr) {
+    boost::shared_ptr<SaveSceneCommandBusRequest> request(new SaveSceneCommandBusRequest());
+    request->setTarget(this);
+    request->setSceneID(_sceneNr);
+    m_pApartment->dispatchRequest(request);
+  } // saveScene
+
+  void AddressableModelItem::undoScene(const int _sceneNr) {
+    boost::shared_ptr<UndoSceneCommandBusRequest> request(new UndoSceneCommandBusRequest());
+    request->setTarget(this);
+    request->setSceneID(_sceneNr);
+    m_pApartment->dispatchRequest(request);
+  } // undoScene
+/*
+  void nextScene();
+  void previousScene();
+*/
+  
+} // namespace dss
diff --git a/core/model/addressablemodelitem.h b/core/model/addressablemodelitem.h
new file mode 100644
index 0000000..6cefc5c
--- /dev/null
+++ b/core/model/addressablemodelitem.h
@@ -0,0 +1,59 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 ADDRESSABLEMODELITEM_H
+#define ADDRESSABLEMODELITEM_H
+
+#include "physicalmodelitem.h"
+#include "deviceinterface.h"
+
+namespace dss {
+
+  class Apartment;
+  
+  class AddressableModelItem : public PhysicalModelItem,
+                               public IDeviceInterface {
+  public:
+    AddressableModelItem(Apartment* _pApartment);
+
+    virtual void increaseValue();
+    virtual void decreaseValue();
+
+    virtual void startDim(const bool _directionUp);
+    virtual void endDim();
+
+    virtual void setValue(const double _value);
+
+    virtual void callScene(const int _sceneNr);
+    virtual void saveScene(const int _sceneNr);
+    virtual void undoScene(const int _sceneNr);
+/*
+    virtual void nextScene();
+    virtual void previousScene();
+*/
+  protected:
+    Apartment* m_pApartment;
+  }; // AddressableModelItem
+
+}
+
+#endif // ADDRESSABLEMODELITEM_H
diff --git a/core/model/apartment.cpp b/core/model/apartment.cpp
new file mode 100644
index 0000000..66fdd2d
--- /dev/null
+++ b/core/model/apartment.cpp
@@ -0,0 +1,1035 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "apartment.h"
+
+#include <fstream>
+
+#include <boost/filesystem.hpp>
+
+#include <Poco/DOM/Document.h>
+#include <Poco/DOM/Element.h>
+#include <Poco/DOM/Node.h>
+#include <Poco/DOM/Attr.h>
+#include <Poco/DOM/Text.h>
+#include <Poco/DOM/ProcessingInstruction.h>
+#include <Poco/DOM/AutoPtr.h>
+#include <Poco/DOM/DOMWriter.h>
+#include <Poco/DOM/DOMParser.h>
+#include <Poco/XML/XMLWriter.h>
+#include <Poco/SAX/InputSource.h>
+
+using Poco::XML::Document;
+using Poco::XML::Element;
+using Poco::XML::Attr;
+using Poco::XML::Text;
+using Poco::XML::ProcessingInstruction;
+using Poco::XML::AutoPtr;
+using Poco::XML::DOMWriter;
+using Poco::XML::DOMParser;
+using Poco::XML::XMLWriter;
+using Poco::XML::InputSource;
+using Poco::XML::Node;
+
+#include "core/DS485Interface.h"
+#include "core/ds485const.h"
+#include "core/dss.h"
+#include "core/logger.h"
+#include "core/propertysystem.h"
+#include "core/event.h"
+#include "core/foreach.h"
+
+#include "core/busrequestdispatcher.h"
+#include "core/model/busrequest.h"
+
+#include "core/model/busscanner.h"
+#include "core/model/scenehelper.h"
+#include "core/model/modelevent.h"
+
+#include "core/model/set.h"
+#include "core/model/device.h"
+#include "core/model/set.h"
+#include "core/model/zone.h"
+#include "core/model/group.h"
+#include "core/model/modulator.h"
+
+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() {
+    scrubVector(m_Devices);
+    scrubVector(m_Zones);
+    scrubVector(m_Modulators);
+  } // 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();
+
+    Group* grp = new Group(GroupIDBroadcast, zoneID, *this);
+    grp->setName("broadcast");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDYellow, zoneID, *this);
+    grp->setName("yellow");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDGray, zoneID, *this);
+    grp->setName("gray");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDBlue, zoneID, *this);
+    grp->setName("blue");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDCyan, zoneID, *this);
+    grp->setName("cyan");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDRed, zoneID, *this);
+    grp->setName("red");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDViolet, zoneID, *this);
+    grp->setName("magenta");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDGreen, zoneID, *this);
+    grp->setName("green");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDBlack, zoneID, *this);
+    grp->setName("black");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDWhite, zoneID, *this);
+    grp->setName("white");
+    _zone.addGroup(grp);
+    grp = new Group(GroupIDDisplay, zoneID, *this);
+    grp->setName("display");
+    _zone.addGroup(grp);
+  } // addDefaultGroupsToZone
+
+  void Apartment::modulatorReady(int _modulatorBusID) {
+    log("Modulator with id: " + intToString(_modulatorBusID) + " is ready", lsInfo);
+    try {
+      try {
+        Modulator& mod = getModulatorByBusID(_modulatorBusID);
+        BusScanner scanner(*m_pDS485Interface->getStructureQueryBusInterface(), *this);
+        if(scanner.scanModulator(mod)) {
+          boost::shared_ptr<Event> modulatorReadyEvent(new Event("modulator_ready"));
+          modulatorReadyEvent->setProperty("modulator", mod.getDSID().toString());
+          raiseEvent(modulatorReadyEvent);
+        }
+      } catch(DS485ApiError& e) {
+        log(std::string("Exception caught while scanning modulator " + intToString(_modulatorBusID) + " : ") + e.what(), lsFatal);
+
+        ModelEvent* pEvent = new ModelEvent(ModelEvent::etModulatorReady);
+        pEvent->addParameter(_modulatorBusID);
+        addModelEvent(pEvent);
+      }
+    } catch(ItemNotFoundException& e) {
+      log("No modulator for bus-id (" + intToString(_modulatorBusID) + ") found, re-discovering devices");
+      discoverDS485Devices();
+    }
+  } // modulatorReady
+
+  void Apartment::setPowerConsumption(int _modulatorBusID, unsigned long _value) {
+    getModulatorByBusID(_modulatorBusID).setPowerConsumption(_value);
+  } // powerConsumption
+
+  void Apartment::setEnergyMeterValue(int _modulatorBusID, unsigned long _value) {
+    getModulatorByBusID(_modulatorBusID).setEnergyMeterValue(_value);
+  } // energyMeterValue
+
+  void Apartment::discoverDS485Devices() {
+    // temporary mark all modulators as absent
+    foreach(Modulator* pModulator, m_Modulators) {
+      pModulator->setIsPresent(false);
+    }
+
+    // Request the dsid of all modulators
+    DS485CommandFrame requestFrame;
+    requestFrame.getHeader().setBroadcast(true);
+    requestFrame.getHeader().setDestination(0);
+    requestFrame.setCommand(CommandRequest);
+    requestFrame.getPayload().add<uint8_t>(FunctionModulatorGetDSID);
+    if(DSS::hasInstance()) {
+      DSS::getInstance()->getDS485Interface().sendFrame(requestFrame);
+    }
+  } // discoverDS485Devices
+
+  void Apartment::writeConfiguration() {
+    if(DSS::hasInstance()) {
+      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::etNewModulator:
+        discoverDS485Devices();
+        break;
+      case ModelEvent::etLostModulator:
+        discoverDS485Devices();
+        break;
+      case ModelEvent::etModulatorReady:
+        if(event.getParameterCount() != 1) {
+          log("Expected exactly 1 parameter for ModelEvent::etModulatorReady");
+        } else {
+          try{
+            Modulator& mod = getModulatorByBusID(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{
+             getModulatorByDSID(newDSID).setBusID(busID);
+             log ("dSM present");
+             getModulatorByDSID(newDSID).setIsPresent(true);
+          } catch(ItemNotFoundException& e) {
+             log ("dSM not present");
+             Modulator& modulator = allocateModulator(newDSID);
+             modulator.setBusID(busID);
+             modulator.setIsPresent(true);
+             modulator.setIsValid(false);
+             ModelEvent* pEvent = new ModelEvent(ModelEvent::etModulatorReady);
+             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(Modulator* pModulator, m_Modulators) {
+        if(pModulator->isPresent()) {
+          if(!pModulator->isValid()) {
+            modulatorReady(pModulator->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");
+      if(!boost::filesystem::exists(configFileName)) {
+        log(std::string("Apartment::execute: Could not open config-file for apartment: '") + configFileName + "'", lsWarning);
+      } else {
+        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/modulators/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
+
+  const int ApartmentConfigVersion = 1;
+
+  void Apartment::readConfigurationFromXML(const std::string& _fileName) {
+    setName("dSS");
+    std::ifstream inFile(_fileName.c_str());
+
+    InputSource input(inFile);
+    DOMParser parser;
+    AutoPtr<Document> pDoc = parser.parse(&input);
+    Element* rootNode = pDoc->documentElement();
+
+    if(rootNode->localName() == "config") {
+      if(rootNode->hasAttribute("version") && (strToInt(rootNode->getAttribute("version")) == ApartmentConfigVersion)) {
+        Node* curNode = rootNode->firstChild();
+        while(curNode != NULL) {
+          std::string nodeName = curNode->localName();
+          if(nodeName == "devices") {
+            loadDevices(curNode);
+          } else if(nodeName == "modulators") {
+            loadModulators(curNode);
+          } else if(nodeName == "zones") {
+            loadZones(curNode);
+          } else if(nodeName == "apartment") {
+            Element* elem = dynamic_cast<Element*>(curNode);
+            if(elem != NULL) {
+              Element* nameElem = elem->getChildElement("name");
+              if(nameElem->hasChildNodes()) {
+                setName(nameElem->firstChild()->nodeValue());
+              }
+            }
+          }
+          curNode = curNode->nextSibling();
+        }
+      } else {
+        log("Config file has the wrong version");
+      }
+    }
+  } // readConfigurationFromXML
+
+  void Apartment::loadDevices(Node* _node) {
+    Node* curNode = _node->firstChild();
+    while(curNode != NULL) {
+      if(curNode->localName() == "device") {
+        Element* elem = dynamic_cast<Element*>(curNode);
+        if((elem != NULL) && elem->hasAttribute("dsid")) {
+          dsid_t dsid = dsid_t::fromString(elem->getAttribute("dsid"));
+          std::string name;
+          Element* nameElem = elem->getChildElement("name");
+          if((nameElem != NULL) && nameElem->hasChildNodes()) {
+            name = nameElem->firstChild()->nodeValue();
+          }
+
+          DateTime firstSeen;
+          if(elem->hasAttribute("firstSeen")) {
+            firstSeen = DateTime(dateFromISOString(elem->getAttribute("firstSeen").c_str()));
+          }
+
+          Device& newDevice = allocateDevice(dsid);
+          if(!name.empty()) {
+            newDevice.setName(name);
+          }
+          newDevice.setFirstSeen(firstSeen);
+          Element* propertiesElem = elem->getChildElement("properties");
+          if(propertiesElem != NULL) {
+            newDevice.publishToPropertyTree();
+            newDevice.getPropertyNode()->loadChildrenFromNode(propertiesElem);
+          }
+        }
+      }
+      curNode = curNode->nextSibling();
+    }
+  } // loadDevices
+
+  void Apartment::loadModulators(Node* _node) {
+    Node* curNode = _node->firstChild();
+    while(curNode != NULL) {
+      if(curNode->localName() == "modulator") {
+        Element* elem = dynamic_cast<Element*>(curNode);
+        if((elem != NULL) && elem->hasAttribute("id")) {
+          dsid_t id = dsid_t::fromString(elem->getAttribute("id"));
+          std::string name;
+          Element* nameElem = elem->getChildElement("name");
+          if((nameElem != NULL) && nameElem->hasChildNodes()) {
+            name = nameElem->firstChild()->nodeValue();
+          }
+          Modulator& newModulator = allocateModulator(id);
+          if(!name.empty()) {
+            newModulator.setName(name);
+          }
+        }
+      }
+      curNode = curNode->nextSibling();
+    }
+  } // loadModulators
+
+  void Apartment::loadZones(Node* _node) {
+    Node* curNode = _node->firstChild();
+    while(curNode != NULL) {
+      if(curNode->localName() == "zone") {
+        Element* elem = dynamic_cast<Element*>(curNode);
+        if((elem != NULL) && elem->hasAttribute("id")) {
+          int id = strToInt(elem->getAttribute("id"));
+          std::string name;
+          Element* nameElem = elem->getChildElement("name");
+          if((nameElem != NULL) && nameElem->hasChildNodes()) {
+            name = nameElem->firstChild()->nodeValue();
+          }
+          Zone& newZone = allocateZone(id);
+          if(!name.empty()) {
+            newZone.setName(name);
+          }
+        }
+      }
+      curNode = curNode->nextSibling();
+    }
+  } // loadZones
+
+  void DeviceToXML(const Device* _pDevice, AutoPtr<Element>& _parentNode, AutoPtr<Document>& _pDocument) {
+    AutoPtr<Element> pDeviceNode = _pDocument->createElement("device");
+    pDeviceNode->setAttribute("dsid", _pDevice->getDSID().toString());
+    if(!_pDevice->getName().empty()) {
+      AutoPtr<Element> pNameNode = _pDocument->createElement("name");
+      AutoPtr<Text> txtNode = _pDocument->createTextNode(_pDevice->getName());
+      pNameNode->appendChild(txtNode);
+      pDeviceNode->appendChild(pNameNode);
+    }
+    pDeviceNode->setAttribute("firstSeen", _pDevice->getFirstSeen());
+    if(_pDevice->getPropertyNode() != NULL) {
+      AutoPtr<Element> pPropertiesNode = _pDocument->createElement("properties");
+      pDeviceNode->appendChild(pPropertiesNode);
+      _pDevice->getPropertyNode()->saveChildrenAsXML(_pDocument, pPropertiesNode, PropertyNode::Archive);
+    }
+
+    _parentNode->appendChild(pDeviceNode);
+  } // deviceToXML
+
+  void ZoneToXML(const Zone* _pZone, AutoPtr<Element>& _parentNode, AutoPtr<Document>& _pDocument) {
+    AutoPtr<Element> pZoneNode = _pDocument->createElement("zone");
+    pZoneNode->setAttribute("id", intToString(_pZone->getID()));
+    if(!_pZone->getName().empty()) {
+      AutoPtr<Element> pNameNode = _pDocument->createElement("name");
+      AutoPtr<Text> txtNode = _pDocument->createTextNode(_pZone->getName());
+      pNameNode->appendChild(txtNode);
+      pZoneNode->appendChild(pNameNode);
+    }
+    _parentNode->appendChild(pZoneNode);
+  } // zoneToXML
+
+  void ModulatorToXML(const Modulator* _pModulator, AutoPtr<Element>& _parentNode, AutoPtr<Document>& _pDocument) {
+    AutoPtr<Element> pModulatorNode = _pDocument->createElement("modulator");
+    pModulatorNode->setAttribute("id", _pModulator->getDSID().toString());
+    if(!_pModulator->getName().empty()) {
+      AutoPtr<Element> pNameNode = _pDocument->createElement("name");
+      AutoPtr<Text> txtNode = _pDocument->createTextNode(_pModulator->getName());
+      pNameNode->appendChild(txtNode);
+      pModulatorNode->appendChild(pNameNode);
+    }
+    _parentNode->appendChild(pModulatorNode);
+  } // modulatorToXML
+
+  void Apartment::writeConfigurationToXML(const std::string& _fileName) {
+    log("Writing apartment config to '" + _fileName + "'", lsInfo);
+    AutoPtr<Document> pDoc = new Document;
+
+    AutoPtr<ProcessingInstruction> pXMLHeader = pDoc->createProcessingInstruction("xml", "version='1.0' encoding='utf-8'");
+    pDoc->appendChild(pXMLHeader);
+
+    AutoPtr<Element> pRoot = pDoc->createElement("config");
+    pRoot->setAttribute("version", intToString(ApartmentConfigVersion));
+    pDoc->appendChild(pRoot);
+
+    // apartment
+    AutoPtr<Element> pApartment = pDoc->createElement("apartment");
+    pRoot->appendChild(pApartment);
+    AutoPtr<Element> pApartmentName = pDoc->createElement("name");
+    AutoPtr<Text> pApartmentNameText = pDoc->createTextNode(getName());
+    pApartmentName->appendChild(pApartmentNameText);
+    pApartment->appendChild(pApartmentName);
+
+    // devices
+    AutoPtr<Element> pDevices = pDoc->createElement("devices");
+    pRoot->appendChild(pDevices);
+    foreach(Device* pDevice, m_Devices) {
+      DeviceToXML(pDevice, pDevices, pDoc);
+    }
+
+    // zones
+    AutoPtr<Element> pZones = pDoc->createElement("zones");
+    pRoot->appendChild(pZones);
+    foreach(Zone* pZone, m_Zones) {
+      ZoneToXML(pZone, pZones, pDoc);
+    }
+
+    // modulators
+    AutoPtr<Element> pModulators = pDoc->createElement("modulators");
+    pRoot->appendChild(pModulators);
+    foreach(Modulator* pModulator, m_Modulators) {
+      ModulatorToXML(pModulator, pModulators, pDoc);
+    }
+
+    std::string tmpOut = _fileName + ".tmp";
+    std::ofstream ofs(tmpOut.c_str());
+
+    if(ofs) {
+      DOMWriter writer;
+      writer.setNewLine("\n");
+      writer.setOptions(XMLWriter::PRETTY_PRINT);
+      writer.writeNode(ofs, pDoc);
+
+      ofs.close();
+
+      // move it to the desired location
+      rename(tmpOut.c_str(), _fileName.c_str());
+    } else {
+      log("Could not open file '" + tmpOut + "' for writing", lsFatal);
+    }
+  } // writeConfigurationToXML
+
+  Device& Apartment::getDeviceByDSID(const dsid_t _dsid) const {
+    foreach(Device* dev, m_Devices) {
+      if(dev->getDSID() == _dsid) {
+        return *dev;
+      }
+    }
+    throw ItemNotFoundException(_dsid.toString());
+  } // getDeviceByShortAddress const
+
+  Device& Apartment::getDeviceByDSID(const dsid_t _dsid) {
+    foreach(Device* dev, m_Devices) {
+      if(dev->getDSID() == _dsid) {
+        return *dev;
+      }
+    }
+    throw ItemNotFoundException(_dsid.toString());
+  } // getDeviceByShortAddress
+
+  Device& Apartment::getDeviceByShortAddress(const Modulator& _modulator, const devid_t _deviceID) const {
+    foreach(Device* dev, m_Devices) {
+      if((dev->getShortAddress() == _deviceID) &&
+          (_modulator.getBusID() == dev->getModulatorID())) {
+        return *dev;
+      }
+    }
+    throw ItemNotFoundException(intToString(_deviceID));
+  } // getDeviceByShortAddress
+
+  Device& Apartment::getDeviceByName(const std::string& _name) {
+    foreach(Device* dev, m_Devices) {
+      if(dev->getName() == _name) {
+        return *dev;
+      }
+    }
+    throw ItemNotFoundException(_name);
+  } // getDeviceByName
+
+  Set Apartment::getDevices() const {
+    DeviceVector devs;
+    foreach(Device* dev, m_Devices) {
+      devs.push_back(DeviceReference(*dev, this));
+    }
+
+    return Set(devs);
+  } // getDevices
+
+  Zone& Apartment::getZone(const std::string& _zoneName) {
+    foreach(Zone* zone, m_Zones) {
+      if(zone->getName() == _zoneName) {
+        return *zone;
+      }
+    }
+    throw ItemNotFoundException(_zoneName);
+  } // getZone(name)
+
+  Zone& Apartment::getZone(const int _id) {
+    foreach(Zone* zone, m_Zones) {
+      if(zone->getID() == _id) {
+        return *zone;
+      }
+    }
+    throw ItemNotFoundException(intToString(_id));
+  } // getZone(id)
+
+  std::vector<Zone*>& Apartment::getZones() {
+    return m_Zones;
+  } // getZones
+
+  Modulator& Apartment::getModulator(const std::string& _modName) {
+    foreach(Modulator* modulator, m_Modulators) {
+      if(modulator->getName() == _modName) {
+        return *modulator;
+      }
+    }
+    throw ItemNotFoundException(_modName);
+  } // getModulator(name)
+
+  Modulator& Apartment::getModulatorByBusID(const int _busId) {
+    foreach(Modulator* modulator, m_Modulators) {
+      if(modulator->getBusID() == _busId) {
+        return *modulator;
+      }
+    }
+    throw ItemNotFoundException(intToString(_busId));
+  } // getModulatorByBusID
+
+  Modulator& Apartment::getModulatorByDSID(const dsid_t _dsid) {
+    foreach(Modulator* modulator, m_Modulators) {
+      if(modulator->getDSID() == _dsid) {
+        return *modulator;
+      }
+    }
+    throw ItemNotFoundException(_dsid.toString());
+  } // getModulatorByDSID
+
+  std::vector<Modulator*>& Apartment::getModulators() {
+    return m_Modulators;
+  } // getModulators
+
+  // Group queries
+  Group& Apartment::getGroup(const std::string& _name) {
+    Group* pResult = getZone(0).getGroup(_name);
+    if(pResult != NULL) {
+      return *pResult;
+    }
+    throw ItemNotFoundException(_name);
+  } // getGroup(name)
+
+  Group& Apartment::getGroup(const int _id) {
+    Group* pResult = getZone(0).getGroup(_id);
+    if(pResult != NULL) {
+      return *pResult;
+    }
+    throw ItemNotFoundException(intToString(_id));
+  } // getGroup(id)
+
+  Device& Apartment::allocateDevice(const dsid_t _dsid) {
+    // search for existing device
+    foreach(Device* device, m_Devices) {
+      if(device->getDSID() == _dsid) {
+        DeviceReference devRef(*device, this);
+        getZone(0).addDevice(devRef);
+        return *device;
+      }
+    }
+
+    Device* pResult = new Device(_dsid, this);
+    pResult->setFirstSeen(DateTime());
+    m_Devices.push_back(pResult);
+    DeviceReference devRef(*pResult, this);
+    getZone(0).addDevice(devRef);
+    return *pResult;
+  } // allocateDevice
+
+  Modulator& Apartment::allocateModulator(const dsid_t _dsid) {
+    foreach(Modulator* modulator, m_Modulators) {
+      if((modulator)->getDSID() == _dsid) {
+        return *modulator;
+      }
+    }
+
+    Modulator* pResult = new Modulator(_dsid);
+    m_Modulators.push_back(pResult);
+    return *pResult;
+  } // allocateModulator
+
+  Zone& Apartment::allocateZone(int _zoneID) {
+    if(getPropertyNode() != NULL) {
+      getPropertyNode()->createProperty("zones/zone" + intToString(_zoneID));
+    }
+
+    foreach(Zone* zone, m_Zones) {
+      if(zone->getID() == _zoneID) {
+        return *zone;
+      }
+    }
+
+    Zone* zone = new Zone(_zoneID);
+    m_Zones.push_back(zone);
+    addDefaultGroupsToZone(*zone);
+    return *zone;
+  } // allocateZone
+
+  void Apartment::removeZone(int _zoneID) {
+    for(std::vector<Zone*>::iterator ipZone = m_Zones.begin(), e = m_Zones.end();
+        ipZone != e; ++ipZone) {
+      Zone* pZone = *ipZone;
+      if(pZone->getID() == _zoneID) {
+        m_Zones.erase(ipZone);
+        delete pZone;
+        return;
+      }
+    }
+  } // removeZone
+
+  void Apartment::removeDevice(dsid_t _device) {
+    for(std::vector<Device*>::iterator ipDevice = m_Devices.begin(), e = m_Devices.end();
+        ipDevice != e; ++ipDevice) {
+      Device* pDevice = *ipDevice;
+      if(pDevice->getDSID() == _device) {
+        m_Devices.erase(ipDevice);
+        delete pDevice;
+        return;
+      }
+    }
+  } // removeDevice
+
+  void Apartment::removeModulator(dsid_t _modulator) {
+    for(std::vector<Modulator*>::iterator ipModulator = m_Modulators.begin(), e = m_Modulators.end();
+        ipModulator != e; ++ipModulator) {
+      Modulator* pModulator = *ipModulator;
+      if(pModulator->getDSID() == _modulator) {
+        m_Modulators.erase(ipModulator);
+        delete pModulator;
+        return;
+      }
+    }
+  } // removeModulator
+
+  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 _modulatorID, const int _deviceID, const int _sceneID) {
+    try {
+      if(_sceneID < 0 || _sceneID > MaxSceneNumber) {
+        log("onDeviceCallScene: _sceneID is out of bounds. modulator-id '" + intToString(_modulatorID) + "' for device '" + intToString(_deviceID) + "' scene: " + intToString(_sceneID), lsError);
+        return;
+      }
+      Modulator& mod = getModulatorByBusID(_modulatorID);
+      try {
+        log("OnDeviceCallScene: modulator-id '" + intToString(_modulatorID) + "' for device '" + intToString(_deviceID) + "' scene: " + intToString(_sceneID));
+        DeviceReference devRef = mod.getDevices().getByBusID(_deviceID);
+        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 modulator '" + intToString(_modulatorID) + "' scene:" + intToString(_sceneID), lsError);
+      }
+    } catch(ItemNotFoundException& e) {
+      log("OnDeviceCallScene: Could not find modulator with bus-id '" + intToString(_modulatorID) + "'", 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("  Modulator: " + 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 modulator
+    try {
+      Modulator& oldModulator = getModulatorByBusID(dev.getModulatorID());
+      oldModulator.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 modulator and remove it in that case
+      } catch(std::runtime_error&) {
+      }
+    }
+
+    // update device
+    dev.setModulatorID(_modID);
+    dev.setZoneID(_zoneID);
+    dev.setShortAddress(_devID);
+    dev.setFunctionID(_functionID);
+    dev.setIsPresent(true);
+
+    // add to new modulator
+    Modulator& modulator = getModulatorByBusID(_modID);
+    modulator.addDevice(devRef);
+
+    // add to new zone
+    Zone& newZone = allocateZone(_zoneID);
+    newZone.addToModulator(modulator);
+    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("  Modulator: " + intToString(_modID));
+    log("  DevID:     " + intToString(_devID));
+    log("  Priority:  " + intToString(_priority));
+
+    try {
+      Modulator& modulator = getModulatorByBusID(_modID);
+      try {
+        Device& device = getDeviceByShortAddress(modulator, _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 Modulator with ID " + intToString(_modID), lsFatal);
+      return;
+    }
+  } // onDSLinkInterrupt
+
+  void Apartment::dispatchRequest(boost::shared_ptr<BusRequest> _pRequest) {
+    if(m_pBusRequestDispatcher != NULL) {
+      m_pBusRequestDispatcher->dispatchRequest(_pRequest);
+    } else {
+      throw std::runtime_error("Apartment::dispatchRequest: m_pBusRequestDispatcher is NULL");
+    }
+  } // dispatchRequest
+
+  DeviceBusInterface* Apartment::getDeviceBusInterface() {
+    return m_pDS485Interface->getDeviceBusInterface();
+  } // getDeviceBusInterface
+
+
+} // namespace dss
diff --git a/core/model/apartment.h b/core/model/apartment.h
new file mode 100644
index 0000000..08f9650
--- /dev/null
+++ b/core/model/apartment.h
@@ -0,0 +1,205 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 APARTMENT_H
+#define APARTMENT_H
+
+#include <vector>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+
+#include "devicecontainer.h"
+#include "modeltypes.h"
+#include "modelevent.h"
+#include "group.h"
+#include "core/subsystem.h"
+#include "core/mutex.h"
+#include "core/thread.h"
+#include "core/syncevent.h"
+#include "core/DS485Interface.h"
+
+namespace Poco {
+  namespace XML {
+    class Node;
+  }
+}
+
+namespace dss {
+
+  class Zone;
+  class Modulator;
+  class Device;
+  class Group;
+  class Event;
+  class PropertyNode;
+  typedef boost::shared_ptr<PropertyNode> PropertyNodePtr;
+  class BusRequestDispatcher;
+  class BusRequest;
+
+  /** Represents an Apartment
+    * This is the root of the datamodel of the dss. The Apartment is responsible for delivering
+    * and loading all subitems.
+    */
+  class Apartment : public boost::noncopyable,
+                    public DeviceContainer,
+                    public Subsystem,
+                    public LockableObject,
+                    public Thread
+  {
+  private:
+    std::vector<Zone*> m_Zones;
+    std::vector<Modulator*> m_Modulators;
+    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;
+  private:
+    void loadDevices(Poco::XML::Node* _node);
+    void loadModulators(Poco::XML::Node* _node);
+    void loadZones(Poco::XML::Node* _node);
+
+    void addDefaultGroupsToZone(Zone& _zone);
+    void handleModelEvents();
+    void modulatorReady(int _modulatorBusID);
+    void setPowerConsumption(int _modulatorBusID, unsigned long _value);
+    void setEnergyMeterValue(int _modulatorBusID, unsigned long _value);
+    void discoverDS485Devices();
+
+    void raiseEvent(boost::shared_ptr<Event> _pEvent);
+    void waitForInterface();
+  protected:
+    virtual void doStart();
+  public:
+    Apartment(DSS* _pDSS, DS485Interface* _pDS485Interface);
+    virtual ~Apartment();
+
+    virtual void initialize();
+
+    /** Returns a set containing all devices of the set */
+    virtual Set getDevices() const;
+
+    /** Loads the datamodel and marks the contained items as "stale" */
+    void readConfigurationFromXML(const std::string& _fileName);
+    void readConfiguration();
+
+    void writeConfigurationToXML(const std::string& _fileName);
+    void writeConfiguration();
+
+    /** Returns a reference to the device with the DSID \a _dsid */
+    Device& getDeviceByDSID(const dsid_t _dsid) const;
+    /** @copydoc getDeviceByDSID */
+    Device& getDeviceByDSID(const dsid_t _dsid);
+    /** Returns a reference to the device with the name \a _name*/
+    Device& getDeviceByName(const std::string& _name);
+    /** Returns a device by it's short-address and modulator */
+    Device& getDeviceByShortAddress(const Modulator& _modulator, const devid_t _deviceID) const;
+
+    /** Allocates a device and returns a reference to it.
+     *  If there is a stale device with the same dsid, this device gets "activated"
+     */
+    Device& allocateDevice(const dsid_t _dsid);
+
+    /** Returns the Zone by name */
+    Zone& getZone(const std::string& _zoneName);
+    /** Returns the Zone by its id */
+    Zone& getZone(const int _id);
+    /** Returns a vector of all zones */
+    std::vector<Zone*>& getZones();
+
+    /** Allocates a zone and returns a reference to it. Should a zone with
+      * the given _zoneID already exist, a reference to the existing zone will
+      * be returned.
+      * NOTE: Outside code should never call this function
+      */
+    Zone& allocateZone(int _zoneID);
+
+    Modulator& allocateModulator(const dsid_t _dsid);
+
+    /** Returns a Modulator by name */
+    Modulator& getModulator(const std::string& _modName);
+    /** Returns a Modulator by DSID  */
+    Modulator& getModulatorByDSID(const dsid_t _dsid);
+    /** Returns a Modulator by bus-id */
+    Modulator& getModulatorByBusID(const int _busID);
+    /** Returns a vector of all modulators */
+    std::vector<Modulator*>& getModulators();
+
+    /** Returns a Group by name */
+    Group& getGroup(const std::string& _name);
+    /** Returns a Group by id */
+    Group& getGroup(const int _id);
+
+    /** 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 removeModulator(dsid_t _modulator);
+  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 _modulatorID, 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);
+  }; // Apartment
+  
+  /** Exception that will be thrown if a given item could not be found */
+  class ItemNotFoundException : public DSSException {
+  public:
+    ItemNotFoundException(const std::string& _name) : DSSException(std::string("Could not find item ") + _name) {};
+    ~ItemNotFoundException() throw() {}
+  };
+
+} // namespace dss
+
+#endif // APARTMENT_H
diff --git a/core/model/busrequest.cpp b/core/model/busrequest.cpp
new file mode 100644
index 0000000..05968f2
--- /dev/null
+++ b/core/model/busrequest.cpp
@@ -0,0 +1,286 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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 "busrequest.h"
+#include "core/ds485const.h"
+#include "core/model/device.h"
+#include "core/model/group.h"
+
+#include <cassert>
+
+namespace dss {
+
+  class PacketBuilderHints : public PacketBuilderHintsBase {
+  public:
+    PacketBuilderHints(BusRequest* _pRequest)
+    : m_pRequest(_pRequest)
+    { }
+
+  protected:
+    BusRequest* getRequest() {
+      return m_pRequest;
+    }
+  private:
+     BusRequest* m_pRequest;
+  };
+
+  class DeviceCommandPacketBuilderHints : public PacketBuilderHints {
+  public:
+    DeviceCommandPacketBuilderHints(DeviceCommandBusRequest* _pRequest)
+    : PacketBuilderHints(_pRequest)
+    {}
+    
+    virtual int getNumberAddressParameter() {
+      return 1;
+    }
+
+    virtual int getFunctionID() {
+      return m_FunctionID;
+    }
+
+    virtual int getNumberOfParameter() {
+      return 0;
+    }
+
+    virtual uint16_t getParameter(int _parameter) {
+      return 0;
+    }
+
+    virtual uint16_t getAddressParameter(int _parameter) {
+      if(_parameter == 0) {
+        return getDevice()->getShortAddress();
+      }
+      throw std::runtime_error("getAddressParameter: failed to get address parameter nr. " + intToString(_parameter));
+    }
+
+    virtual uint16_t getTarget() {
+      return getDevice()->getModulatorID();
+    }
+
+    virtual bool isBroadcast() {
+      return false;
+    }
+
+    void setFunctionID(uint16_t _value) {
+      m_FunctionID = _value;
+    }
+  private:
+    Device* getDevice() {
+      return ((DeviceCommandBusRequest*)getRequest())->getTarget();
+    }
+  private:
+    uint16_t m_FunctionID;
+  };
+
+  PacketBuilderHintsBase* EnableDeviceCommandBusRequest::getBuilderHints() {
+    DeviceCommandPacketBuilderHints* result = new DeviceCommandPacketBuilderHints(this);
+    result->setFunctionID(FunctionDeviceEnable);
+    return result;
+  }
+
+  PacketBuilderHintsBase* DisableDeviceCommandBusRequest::getBuilderHints() {
+    DeviceCommandPacketBuilderHints* result = new DeviceCommandPacketBuilderHints(this);
+    result->setFunctionID(FunctionDeviceDisable);
+    return result;
+  }
+  
+  class CommandBusRequestPacketBuilderHints : public PacketBuilderHints {
+  public:
+    
+    CommandBusRequestPacketBuilderHints(CommandBusRequest* _pRequest)
+    : PacketBuilderHints(_pRequest),
+      m_pGroup(NULL),
+      m_pDevice(NULL),
+      m_FunctionIDForGroup(-1),
+      m_FunctionIDForDevice(-1)
+    {
+      determineTypeOfTarget();
+    }
+    
+    virtual int getFunctionID() {
+      if(targetIsGroup()) {
+        return m_FunctionIDForGroup;
+      } else if(targetIsDevice()) {
+        return m_FunctionIDForDevice;
+      } else {
+        assert(false);
+      }
+    }
+
+    virtual bool isBroadcast() {
+      return targetIsGroup();
+    }
+
+    virtual uint16_t getTarget() {
+      if(targetIsDevice()) {
+        return m_pDevice->getModulatorID();
+      }
+      return 0;
+    }
+
+    virtual int getNumberAddressParameter() {
+      if(targetIsDevice()) {
+        return 1;
+      } else if(targetIsGroup()) {
+        return 2;
+      }
+      throw std::runtime_error("getNumberAddressParameter: failed to get address parameter count");
+    }
+
+    virtual uint16_t getAddressParameter(int _parameter) {
+      if(_parameter == 0) {
+        if(targetIsDevice()) {
+          return m_pDevice->getShortAddress();
+        } else if(targetIsGroup()) {
+          return m_pGroup->getZoneID();
+        }
+      } else if(_parameter == 1) {
+        if(targetIsGroup()) {
+          return m_pGroup->getID();
+        }
+      }
+      throw std::runtime_error("getAddressParameter: failed to get address parameter nr. " + intToString(_parameter));
+    }
+
+    void setFunctionIDForDevice(const int _value) {
+      m_FunctionIDForDevice = _value;
+    }
+
+    void setFunctionIDForGroup(const int _value) {
+      m_FunctionIDForGroup = _value;
+    }
+
+    virtual int getNumberOfParameter() {
+      return m_Parameter.size();
+    }
+
+    virtual uint16_t getParameter(int _parameter) {
+      return m_Parameter.at(_parameter);
+    }
+
+    void addParameter(uint16_t _parameter) {
+      m_Parameter.push_back(_parameter);
+    }
+  private:
+    void determineTypeOfTarget() {
+      PhysicalModelItem* pTarget = ((CommandBusRequest*)getRequest())->getTarget();
+      m_pGroup = dynamic_cast<Group*>(pTarget);
+      m_pDevice = dynamic_cast<Device*>(pTarget);
+    }
+
+    bool targetIsGroup() {
+      return m_pGroup != NULL;
+    }
+
+    bool targetIsDevice() {
+      return m_pDevice != NULL;
+    }   
+  private:
+    Group* m_pGroup;
+    Device* m_pDevice;
+    int m_FunctionIDForGroup;
+    int m_FunctionIDForDevice;
+    std::vector<uint16_t> m_Parameter;
+  }; // CommandBusRequestPacketBuilderHints
+  
+  class SceneCommandPacketBuilderHints : public CommandBusRequestPacketBuilderHints {
+  public:
+    SceneCommandPacketBuilderHints(SceneCommandBusRequest* _pRequest)
+    : CommandBusRequestPacketBuilderHints(_pRequest)
+    {
+    }
+
+    virtual int getNumberOfParameter() {
+      return 1;
+    }
+
+    virtual uint16_t getParameter(int _parameter) {
+      if(_parameter == 0) {
+        return dynamic_cast<SceneCommandBusRequest*>(getRequest())->getSceneID();
+      }
+      throw std::out_of_range("_parameter out of range");
+    }
+  };
+  
+  PacketBuilderHintsBase* CallSceneCommandBusRequest::getBuilderHints() {
+    SceneCommandPacketBuilderHints* result = new SceneCommandPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceCallScene);
+    result->setFunctionIDForGroup(FunctionGroupCallScene);
+    return result;
+  } // getBuilderHints
+
+  PacketBuilderHintsBase* SaveSceneCommandBusRequest::getBuilderHints() {
+    SceneCommandPacketBuilderHints* result = new SceneCommandPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceSaveScene);
+    result->setFunctionIDForGroup(FunctionGroupSaveScene);
+    return result;
+  } // getBuilderHints
+
+  PacketBuilderHintsBase* UndoSceneCommandBusRequest::getBuilderHints() {
+    SceneCommandPacketBuilderHints* result = new SceneCommandPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceUndoScene);
+    result->setFunctionIDForGroup(FunctionGroupUndoScene);
+    return result;
+  } // getBuilderHints
+
+  PacketBuilderHintsBase* IncreaseValueCommandBusRequest::getBuilderHints() {
+    CommandBusRequestPacketBuilderHints* result = new CommandBusRequestPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceIncreaseValue);
+    result->setFunctionIDForGroup(FunctionGroupIncreaseValue);
+    return result;
+  } // getBuilderHints
+
+  PacketBuilderHintsBase* DecreaseValueCommandBusRequest::getBuilderHints() {
+    CommandBusRequestPacketBuilderHints* result = new CommandBusRequestPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceDecreaseValue);
+    result->setFunctionIDForGroup(FunctionGroupDecreaseValue);
+    return result;
+  } // getBuilderHints
+
+  PacketBuilderHintsBase* StartDimUpCommandBusRequest::getBuilderHints() {
+    CommandBusRequestPacketBuilderHints* result = new CommandBusRequestPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceStartDimInc);
+    result->setFunctionIDForGroup(FunctionGroupStartDimInc);
+    return result;
+  } // getBuilderHints
+
+  PacketBuilderHintsBase* StartDimDownCommandBusRequest::getBuilderHints() {
+    CommandBusRequestPacketBuilderHints* result = new CommandBusRequestPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceStartDimDec);
+    result->setFunctionIDForGroup(FunctionGroupStartDimDec);
+    return result;
+  } // getBuilderHints
+
+  PacketBuilderHintsBase* EndDimCommandBusRequest::getBuilderHints() {
+    CommandBusRequestPacketBuilderHints* result = new CommandBusRequestPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceEndDim);
+    result->setFunctionIDForGroup(FunctionGroupEndDim);
+    return result;
+  } // getBuilderHints
+
+  PacketBuilderHintsBase* SetValueCommandBusRequest::getBuilderHints() {
+    CommandBusRequestPacketBuilderHints* result = new CommandBusRequestPacketBuilderHints(this);
+    result->setFunctionIDForDevice(FunctionDeviceSetValue);
+    result->setFunctionIDForGroup(FunctionGroupSetValue);
+    result->addParameter(m_Value);
+    return result;
+  } // getBuilderHints
+  
+} // namespace dss
\ No newline at end of file
diff --git a/core/model/busrequest.h b/core/model/busrequest.h
new file mode 100644
index 0000000..5ba8e57
--- /dev/null
+++ b/core/model/busrequest.h
@@ -0,0 +1,129 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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 BUSREQUEST_H
+#define BUSREQUEST_H
+
+#include <stdint.h>
+
+namespace dss {
+  class AddressableModelItem;
+  class Device;
+  
+  class PacketBuilderHintsBase {
+  public:
+    virtual int getFunctionID() = 0;
+    virtual int getNumberAddressParameter() = 0;
+    virtual uint16_t getAddressParameter(int _parameter) = 0;
+    virtual uint16_t getTarget() = 0;
+    virtual bool isBroadcast() = 0;
+    virtual int getNumberOfParameter() = 0;
+    virtual uint16_t getParameter(int _parameter) = 0;
+  };
+
+  class BusRequest {
+  public:
+    virtual PacketBuilderHintsBase* getBuilderHints() = 0;
+  };
+
+  class CommandBusRequest : public BusRequest {
+  public:
+    void setTarget(AddressableModelItem* _value) { m_pTarget = _value; }
+    AddressableModelItem* getTarget() const { return m_pTarget; }
+  private:
+    AddressableModelItem* m_pTarget;
+  };
+
+  class DeviceCommandBusRequest : public BusRequest {
+  public:
+    void setTarget(Device* _value) { m_pTarget = _value; }
+    Device* getTarget() const { return m_pTarget; }
+  private:
+    Device* m_pTarget;
+  };
+  
+  class EnableDeviceCommandBusRequest : public DeviceCommandBusRequest {
+  public:
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+
+  class DisableDeviceCommandBusRequest : public DeviceCommandBusRequest {
+  public:
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+
+  class SceneCommandBusRequest : public CommandBusRequest {
+  public:
+    void setSceneID(const int _value) { m_SceneID = _value; }
+    int getSceneID() const { return m_SceneID; }
+  private:
+    int m_SceneID;
+  };
+
+  class CallSceneCommandBusRequest : public SceneCommandBusRequest {
+  public:
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+
+  class SaveSceneCommandBusRequest : public SceneCommandBusRequest {
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+  
+  class UndoSceneCommandBusRequest : public SceneCommandBusRequest {
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+
+  class IncreaseValueCommandBusRequest : public CommandBusRequest {
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+
+  class DecreaseValueCommandBusRequest : public CommandBusRequest {
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+
+  class StartDimUpCommandBusRequest : public CommandBusRequest {
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+  
+  class StartDimDownCommandBusRequest : public CommandBusRequest {
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+
+  class EndDimCommandBusRequest : public CommandBusRequest {
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  };
+
+  class SetValueCommandBusRequest : public CommandBusRequest {
+  public:
+    void setValue(const int _value) {
+      m_Value = _value;
+    }
+
+    uint16_t getValue() const {
+      return m_Value;
+    }
+  private:
+    virtual PacketBuilderHintsBase* getBuilderHints();
+  private:
+    uint16_t m_Value;
+  };
+}
+
+#endif // BUSREQUEST_H
diff --git a/core/model/busscanner.cpp b/core/model/busscanner.cpp
new file mode 100644
index 0000000..2da9703
--- /dev/null
+++ b/core/model/busscanner.cpp
@@ -0,0 +1,190 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "busscanner.h"
+
+#include <vector>
+
+#include "core/DS485Interface.h"
+#include "core/foreach.h"
+#include "core/ds485const.h"
+
+#include "modulator.h"
+#include "device.h"
+#include "group.h"
+#include "apartment.h"
+#include "zone.h"
+
+namespace dss {
+  
+  BusScanner::BusScanner(StructureQueryBusInterface& _interface, Apartment& _apartment)
+  : m_Apartment(_apartment),
+    m_Interface(_interface)
+  {
+  }
+
+  bool BusScanner::scanModulator(Modulator& _modulator) {
+    _modulator.setIsPresent(true);
+    _modulator.setIsValid(false);
+
+    int modulatorID = _modulator.getBusID();
+
+    log("scanModulator: Start " + intToString(modulatorID) , lsInfo);
+    std::vector<int> zoneIDs;
+    try {
+      zoneIDs = m_Interface.getZones(modulatorID);
+    } catch(DS485ApiError& e) {
+      log("scanModulator: Error getting ZoneIDs", lsFatal);
+      return false;
+    }
+
+    int levelOrange, levelRed;
+    try {
+      if(m_Interface.getEnergyBorder(modulatorID, levelOrange, levelRed)) {
+        _modulator.setEnergyLevelOrange(levelOrange);
+        _modulator.setEnergyLevelRed(levelRed);
+      }
+    } catch(DS485ApiError& e) {
+      log("scanModulator: Error getting EnergyLevels", lsFatal);
+      return false;
+    }
+
+    try {
+      ModulatorSpec_t spec = m_Interface.getModulatorSpec(modulatorID);
+      _modulator.setSoftwareVersion(spec.get<1>());
+      _modulator.setHardwareVersion(spec.get<2>());
+      _modulator.setHardwareName(spec.get<3>());
+      _modulator.setDeviceType(spec.get<4>());
+    } catch(DS485ApiError& e) {
+      log("scanModulator: Error getting dSMSpecs", lsFatal);
+      return false;
+    }
+
+    bool firstZone = true;
+    foreach(int zoneID, zoneIDs) {
+      log("scanModulator:  Found zone with id: " + intToString(zoneID));
+      Zone& zone = m_Apartment.allocateZone(zoneID);
+      zone.addToModulator(_modulator);
+      zone.setIsPresent(true);
+      if(firstZone) {
+        zone.setFirstZoneOnModulator(modulatorID);
+        firstZone = false;
+      }
+      std::vector<int> devices;
+      try {
+        devices = m_Interface.getDevicesInZone(modulatorID, zoneID);
+      } catch(DS485ApiError& e) {
+        log("scanModulator: Error getting getDevicesInZone", lsFatal);
+        return false;
+      }
+      foreach(int devID, devices) {
+        dsid_t dsid;
+        try {
+          dsid = m_Interface.getDSIDOfDevice(modulatorID, devID);
+        } catch(DS485ApiError& e) {
+            log("scanModulator: Error getting getDSIDOfDevice", lsFatal);
+            return false;
+        }
+
+        int functionID = 0;
+        try {
+          functionID = m_Interface.deviceGetFunctionID(devID, modulatorID);
+        } catch(DS485ApiError& e) {
+          log("scanModulator: Error getting cmdGetFunctionID", lsFatal);
+          return false;
+        }
+        log("scanModulator:    Found device with id: " + intToString(devID));
+        log("scanModulator:    DSID:        " + dsid.toString());
+        log("scanModulator:    Function ID: " + unsignedLongIntToHexString(functionID));
+        Device& dev = m_Apartment.allocateDevice(dsid);
+        dev.setShortAddress(devID);
+        dev.setModulatorID(modulatorID);
+        dev.setZoneID(zoneID);
+        dev.setFunctionID(functionID);
+
+        std::vector<int> groupIdperDevices = m_Interface.getGroupsOfDevice(modulatorID, devID);
+        std::vector<int> groupIDsPerDevice = m_Interface.getGroupsOfDevice(modulatorID,devID);
+        foreach(int groupID, groupIDsPerDevice) {
+          log(std::string("scanModulator: adding device ") + intToString(devID) + " to group " + intToString(groupID));
+          dev.addToGroup(groupID);
+        }
+
+        DeviceReference devRef(dev, &m_Apartment);
+        zone.addDevice(devRef);
+        _modulator.addDevice(devRef);
+        dev.setIsPresent(true);
+      }
+      std::vector<int> groupIDs;
+      try {
+        groupIDs = m_Interface.getGroups(modulatorID, zoneID);
+      } catch(DS485ApiError& e) {
+        log("scanModulator: Error getting getGroups", lsFatal);
+        return false;
+      }
+
+      foreach(int groupID, groupIDs) {
+        if(groupID == 0) {
+          log("scanModulator:    Group ID is zero, bailing out... (modulatorID: "
+              + intToString(modulatorID) +
+              "zoneID: " + intToString(zoneID) + ")",
+              lsError);
+          continue;
+        }
+        log("scanModulator:    Found group with id: " + intToString(groupID));
+        if(zone.getGroup(groupID) == NULL) {
+          log(" scanModulator:    Adding new group to zone");
+          zone.addGroup(new Group(groupID, zone.getID(), m_Apartment));
+        }
+        try {
+          Group& group = m_Apartment.getGroup(groupID);
+          group.setIsPresent(true);
+        } catch(ItemNotFoundException&) {
+          Group* pGroup = new Group(groupID, 0, m_Apartment);
+          m_Apartment.getZone(0).addGroup(pGroup);
+          pGroup->setIsPresent(true);
+          log("scanModulator:     Adding new group to zone 0");
+        }
+
+        // get last called scene for zone, group
+        try {
+          int lastCalledScene = m_Interface.getLastCalledScene(modulatorID, zoneID, groupID);
+          Group* pGroup = zone.getGroup(groupID);
+          assert(pGroup != NULL);
+          log("scanModulator: zoneID: " + intToString(zoneID) + " groupID: " + intToString(groupID) + " lastScene: " + intToString(lastCalledScene));
+          if(lastCalledScene < 0 || lastCalledScene > MaxSceneNumber) {
+            log("scanModulator: _sceneID is out of bounds. zoneID: " + intToString(zoneID) + " groupID: " + intToString(groupID) + " scene: " + intToString(lastCalledScene), lsError);
+          } else {
+            m_Apartment.onGroupCallScene(zoneID, groupID, lastCalledScene);
+          }
+        } catch(DS485ApiError& error) {
+          log(std::string("scanModulator: Error getting last called scene '") + error.what() + "'", lsError);
+        }
+      }
+    }
+    _modulator.setIsValid(true);
+    return true;
+
+  } // scanModulator
+
+  void BusScanner::log(const std::string& _line, aLogSeverity _severity) {
+    Logger::getInstance()->log(_line, _severity);
+  }
+}
diff --git a/core/model/busscanner.h b/core/model/busscanner.h
new file mode 100644
index 0000000..cff9fa9
--- /dev/null
+++ b/core/model/busscanner.h
@@ -0,0 +1,46 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 BUSSCANNER_H
+#define BUSSCANNER_H
+
+#include "core/logger.h"
+
+namespace dss {
+
+  class StructureQueryBusInterface;
+  class Apartment;
+  class Modulator;
+  
+  class BusScanner {
+  public:
+    BusScanner(StructureQueryBusInterface& _interface, Apartment& _apartment);
+    bool scanModulator(Modulator& _modulator);
+  private:
+    void log(const std::string& _line, aLogSeverity _severity = lsDebug);
+  private:
+    Apartment& m_Apartment;
+    StructureQueryBusInterface& m_Interface;
+  };
+
+} // namespace dss
+
+#endif // BUSSCANNER_H
diff --git a/core/model/device.cpp b/core/model/device.cpp
new file mode 100644
index 0000000..3813e74
--- /dev/null
+++ b/core/model/device.cpp
@@ -0,0 +1,260 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "device.h"
+
+#include "core/ds485const.h"
+#include "core/model/busrequest.h"
+#include "core/propertysystem.h"
+#include "core/model/scenehelper.h"
+#include "core/model/modelevent.h"
+#include "core/model/apartment.h"
+
+namespace dss {
+
+  //================================================== Device
+
+  const devid_t ShortAddressStaleDevice = 0xFFFF;
+
+  Device::Device(dsid_t _dsid, Apartment* _pApartment)
+  : AddressableModelItem(_pApartment),
+    m_DSID(_dsid),
+    m_ShortAddress(ShortAddressStaleDevice),
+    m_ZoneID(0),
+    m_FunctionID(0),
+    m_LastCalledScene(SceneOff),
+    m_Consumption(0),
+    m_LastDiscovered(DateTime::NullDate),
+    m_FirstSeen(DateTime::NullDate)
+  { } // ctor
+
+  void Device::publishToPropertyTree() {
+    if(m_pPropertyNode == NULL) {
+      if(m_pApartment->getPropertyNode() != NULL) {
+        m_pPropertyNode = m_pApartment->getPropertyNode()->createProperty("zones/zone0/" + m_DSID.toString());
+//        m_pPropertyNode->createProperty("name")->linkToProxy(PropertyProxyMemberFunction<Device, std::string>(*this, &Device::getName, &Device::setName));
+        m_pPropertyNode->createProperty("name")->linkToProxy(PropertyProxyReference<std::string>(m_Name));
+        m_pPropertyNode->createProperty("ModulatorID")->linkToProxy(PropertyProxyReference<int>(m_ModulatorID, false));
+        m_pPropertyNode->createProperty("ZoneID")->linkToProxy(PropertyProxyReference<int>(m_ZoneID, false));
+        if(m_pPropertyNode->getProperty("interrupt/mode") == NULL) {
+          PropertyNodePtr interruptNode = m_pPropertyNode->createProperty("interrupt");
+          interruptNode->setFlag(PropertyNode::Archive, true);
+          PropertyNodePtr interruptModeNode = interruptNode->createProperty("mode");
+          interruptModeNode->setStringValue("ignore");
+          interruptModeNode->setFlag(PropertyNode::Archive, true);
+        }
+      }
+    }
+  } // publishToPropertyTree
+
+  void Device::enable() {
+    boost::shared_ptr<EnableDeviceCommandBusRequest> request(new EnableDeviceCommandBusRequest());
+    request->setTarget(this);
+    m_pApartment->dispatchRequest(request);
+  } // enable
+
+  void Device::disable() {
+    boost::shared_ptr<DisableDeviceCommandBusRequest> request(new DisableDeviceCommandBusRequest());
+    request->setTarget(this);
+    m_pApartment->dispatchRequest(request);
+  } // disable
+
+  bool Device::isOn() const {
+    return (m_LastCalledScene != SceneOff) &&
+           (m_LastCalledScene != SceneMin) &&
+           (m_LastCalledScene != SceneDeepOff) &&
+           (m_LastCalledScene != SceneStandBy);
+  } // isOn
+
+  int Device::getFunctionID() const {
+    return m_FunctionID;
+  } // getFunctionID
+
+  void Device::setFunctionID(const int _value) {
+    m_FunctionID = _value;
+  } // setFunctionID
+
+  bool Device::hasSwitch() const {
+    return getFunctionID() == FunctionIDSwitch;
+  } // hasSwitch
+
+  void Device::setRawValue(const uint16_t _value, const int _parameterNr, const int _size) {
+    m_pApartment->getDeviceBusInterface()->setValueDevice(*this, _value, _parameterNr, _size);
+  } // setRawValue
+
+  double Device::getValue(const int _parameterNr) {
+    return m_pApartment->getDeviceBusInterface()->deviceGetParameterValue(m_ShortAddress, m_ModulatorID,  _parameterNr);
+  } // getValue
+
+  void Device::nextScene() {
+    callScene(SceneHelper::getNextScene(m_LastCalledScene));
+  } // nextScene
+
+  void Device::previousScene() {
+    callScene(SceneHelper::getNextScene(m_LastCalledScene));
+  } // previousScene
+
+  std::string Device::getName() const {
+    return m_Name;
+  } // getName
+
+  void Device::setName(const std::string& _name) {
+    if(m_Name != _name) {
+      m_Name = _name;
+      dirty();
+    }
+  } // setName
+
+  void Device::dirty() {
+    if(m_pApartment != NULL) {
+      m_pApartment->addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
+    }
+  } // dirty
+
+  bool Device::operator==(const Device& _other) const {
+    return _other.m_DSID == m_DSID;
+  } // operator==
+
+  devid_t Device::getShortAddress() const {
+    return m_ShortAddress;
+  } // getShortAddress
+
+  void Device::setShortAddress(const devid_t _shortAddress) {
+    m_ShortAddress = _shortAddress;
+    publishToPropertyTree();
+    m_LastDiscovered = DateTime();
+  } // setShortAddress
+
+  dsid_t Device::getDSID() const {
+    return m_DSID;
+  } // getDSID;
+
+  int Device::getModulatorID() const {
+    return m_ModulatorID;
+  } // getModulatorID
+
+  void Device::setModulatorID(const int _modulatorID) {
+    m_ModulatorID = _modulatorID;
+  } // setModulatorID
+
+  int Device::getZoneID() const {
+    return m_ZoneID;
+  } // getZoneID
+
+  void Device::setZoneID(const int _value) {
+    if(_value != m_ZoneID) {
+      m_ZoneID = _value;
+      if((m_pPropertyNode != NULL) && (m_pApartment->getPropertyNode() != NULL)) {
+        std::string basePath = "zones/zone" + intToString(m_ZoneID);
+        if(m_pAliasNode == NULL) {
+          PropertyNodePtr node = m_pApartment->getPropertyNode()->getProperty(basePath + "/" + m_DSID.toString());
+          if(node != NULL) {
+            Logger::getInstance()->log("Device::setZoneID: Target node for device " + m_DSID.toString() + " already exists", lsError);
+            if(node->size() > 0) {
+              Logger::getInstance()->log("Device::setZoneID: Target node for device " + m_DSID.toString() + " has children", lsFatal);
+              return;
+            }
+          }
+          m_pAliasNode = m_pApartment->getPropertyNode()->createProperty(basePath + "/" + m_DSID.toString());
+
+          m_pAliasNode->alias(m_pPropertyNode);
+        } else {
+          PropertyNodePtr base = m_pApartment->getPropertyNode()->getProperty(basePath);
+          if(base == NULL) {
+            throw std::runtime_error("PropertyNode of the new zone does not exist");
+          }
+          base->addChild(m_pAliasNode);
+        }
+      }
+    }
+  } // setZoneID
+
+  int Device:: getGroupIdByIndex(const int _index) const {
+    return m_Groups[_index];
+  } // getGroupIdByIndex
+
+  Group& Device::getGroupByIndex(const int _index) {
+    return m_pApartment->getGroup(getGroupIdByIndex(_index));
+  } // getGroupByIndex
+
+  void Device::addToGroup(const int _groupID) {
+    m_GroupBitmask.set(_groupID-1);
+    if(find(m_Groups.begin(), m_Groups.end(), _groupID) == m_Groups.end()) {
+      m_Groups.push_back(_groupID);
+    } else {
+      Logger::getInstance()->log("Device " + m_DSID.toString() + " (bus: " + intToString(m_ShortAddress) + ", zone: " + intToString(m_ZoneID) + ") is already in group " + intToString(_groupID));
+    }
+  } // addToGroup
+
+  void Device::removeFromGroup(const int _groupID) {
+    m_GroupBitmask.reset(_groupID-1);
+    std::vector<int>::iterator it = find(m_Groups.begin(), m_Groups.end(), _groupID);
+    if(it != m_Groups.end()) {
+      m_Groups.erase(it);
+    }
+  } // removeFromGroup
+
+  void Device::resetGroups() {
+    m_GroupBitmask.reset();
+    m_Groups.clear();
+  } // resetGroups
+
+  int Device::getGroupsCount() const {
+    return m_Groups.size();
+  } // getGroupsCount
+
+  std::bitset<63>& Device::getGroupBitmask() {
+    return m_GroupBitmask;
+  } // getGroupBitmask
+
+  const std::bitset<63>& Device::getGroupBitmask() const {
+    return m_GroupBitmask;
+  } // getGroupBitmask
+
+  bool Device::isInGroup(const int _groupID) const {
+    return (_groupID == 0) || m_GroupBitmask.test(_groupID - 1);
+  } // isInGroup
+
+  Apartment& Device::getApartment() const {
+    return *m_pApartment;
+  } // getApartment
+
+  unsigned long Device::getPowerConsumption() {
+    return m_Consumption;
+  } // getPowerConsumption
+
+  uint8_t Device::dsLinkSend(uint8_t _value, bool _lastByte, bool _writeOnly) {
+    uint8_t flags = 0;
+    if(_lastByte) {
+      flags |= DSLinkSendLastByte;
+    }
+    if(_writeOnly) {
+      flags |= DSLinkSendWriteOnly;
+    }
+    return m_pApartment->getDeviceBusInterface()->dSLinkSend(m_ModulatorID, m_ShortAddress, _value, flags);
+  } // dsLinkSend
+
+  int Device::getSensorValue(const int _sensorID) {
+    return m_pApartment->getDeviceBusInterface()->getSensorValue(*this,_sensorID);
+  } // getSensorValue
+
+  
+} // namespace dss
diff --git a/core/model/device.h b/core/model/device.h
new file mode 100644
index 0000000..e08393a
--- /dev/null
+++ b/core/model/device.h
@@ -0,0 +1,177 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 DEVICE_H
+#define DEVICE_H
+
+#include <iosfwd>
+#include <bitset>
+
+#include <boost/noncopyable.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "core/ds485types.h"
+#include "core/datetools.h"
+#include "addressablemodelitem.h"
+
+namespace dss {
+
+  class PropertyNode;
+  typedef boost::shared_ptr<PropertyNode> PropertyNodePtr;
+  class Group;
+
+  /** Represents a dsID */
+  class Device : public AddressableModelItem,
+                 public boost::noncopyable {
+  private:
+    std::string m_Name;
+    dsid_t m_DSID;
+    devid_t m_ShortAddress;
+    int m_ModulatorID;
+    int m_ZoneID;
+    std::bitset<63> m_GroupBitmask;
+    std::vector<int> m_Groups;
+    int m_FunctionID;
+    int m_LastCalledScene;
+    unsigned long m_Consumption;
+    DateTime m_LastDiscovered;
+    DateTime m_FirstSeen;
+
+    PropertyNodePtr m_pPropertyNode;
+    PropertyNodePtr m_pAliasNode;
+  protected:
+    /** Sends the application a note that something has changed.
+     * This will cause the \c apartment.xml to be updated. */
+    void dirty();
+  public:
+    /** Creates and initializes a device. */
+    Device(const dsid_t _dsid, Apartment* _pApartment);
+    virtual ~Device() {};
+
+    void enable();
+    void disable();
+
+    /** @copydoc DeviceReference::isOn() */
+    virtual bool isOn() const;
+
+    void setRawValue(const uint16_t _value, const int _parameterNr, const int _size);
+    /** Returns the value of _parameterNr.
+     * @note not yet implemented */
+    double getValue(const int _parameterNr = -1);
+
+    virtual void nextScene();
+    virtual void previousScene();
+
+    /** Returns the function ID of the device.
+     * A function ID specifies a certain subset of functionality that
+     * a device implements.
+     */
+    int getFunctionID() const;
+    /** Sets the functionID to \a _value */
+    void setFunctionID(const int _value);
+    bool hasSwitch() const;
+
+    /** Returns the name of the device. */
+    std::string getName() const;
+    /** Sets the name of the device.
+     * @note This will cause the apartment to store
+     * \c apartment.xml
+     */
+    void setName(const std::string& _name);
+
+    /** Returns the group bitmask (1 based) of the device */
+    std::bitset<63>& getGroupBitmask();
+    /** @copydoc getGroupBitmask() */
+    const std::bitset<63>& getGroupBitmask() const;
+
+    /** Returns wheter the device is in group \a _groupID or not. */
+    bool isInGroup(const int _groupID) const;
+    /** Adds the device to group \a _groupID. */
+    void addToGroup(const int _groupID);
+    /** Removes the device from group \a _groupID */
+    void removeFromGroup(const int _groupID);
+
+    /** Returns the group id of the \a _index'th group */
+    int getGroupIdByIndex(const int _index) const;
+    /** Returns \a _index'th group of the device */
+    Group& getGroupByIndex(const int _index);
+    /** Returns the number of groups the device is a member of */
+    int getGroupsCount() const;
+
+    /** Removes the device from all group.
+     * The device will remain in the broadcastgroup though.
+     */
+    void resetGroups();
+
+    /** Returns the last called scene.
+     * At the moment this information is used to determine wheter a device is
+     * turned on or not. */
+    int getLastCalledScene() const { return m_LastCalledScene; }
+    /** Sets the last called scene. */
+    void setLastCalledScene(const int _value) { m_LastCalledScene = _value; }
+
+    /** Returns the short address of the device. This is the address
+     * the device got from the dSM. */
+    devid_t getShortAddress() const;
+    /** Sets the short-address of the device. */
+    void setShortAddress(const devid_t _shortAddress);
+    /** Returns the DSID of the device */
+    dsid_t getDSID() const;
+    /** Returns the id of the modulator the device is connected to */
+    int getModulatorID() const;
+    /** Sets the modulatorID of the device. */
+    void setModulatorID(const int _modulatorID);
+
+    /** Returns the zone ID the device resides in. */
+    int getZoneID() const;
+    /** Sets the zone ID of the device. */
+    void setZoneID(const int _value);
+    /** Returns the apartment the device resides in. */
+    Apartment& getApartment() const;
+
+    const DateTime& getLastDiscovered() const { return m_LastDiscovered; }
+    const DateTime& getFirstSeen() const { return m_FirstSeen; }
+    void setFirstSeen(const DateTime& _value) { m_FirstSeen = _value; }
+
+    virtual unsigned long getPowerConsumption();
+
+    /** Sends a byte to the device using dsLink. If \a _writeOnly is \c true,
+     * the result of the function is not defined. */
+    uint8_t dsLinkSend(uint8_t _value, bool _lastByte, bool _writeOnly);
+    int getSensorValue(const int _sensorID);
+
+    const PropertyNodePtr& getPropertyNode() const { return m_pPropertyNode; }
+    PropertyNodePtr getPropertyNode() { return m_pPropertyNode; }
+
+    /** Publishes the device to the property tree.
+     * @see DSS::getPropertySystem */
+    void publishToPropertyTree();
+
+    /** Returns wheter two devices are equal.
+     * Devices are considered equal if their DSID are a match.*/
+    bool operator==(const Device& _other) const;
+  }; // Device
+
+  std::ostream& operator<<(std::ostream& out, const Device& _dt);
+
+} // namespace dss
+
+#endif // DEVICE_H
diff --git a/core/model/devicecontainer.cpp b/core/model/devicecontainer.cpp
new file mode 100644
index 0000000..0658f0f
--- /dev/null
+++ b/core/model/devicecontainer.cpp
@@ -0,0 +1,41 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "devicecontainer.h"
+
+#include "core/dss.h"
+#include "modelevent.h"
+#include "apartment.h"
+
+namespace dss {
+
+  //================================================== DeviceContainer
+
+  void DeviceContainer::setName(const std::string& _name) {
+    if(m_Name != _name) {
+      m_Name = _name;
+      if(DSS::hasInstance()) {
+        DSS::getInstance()->getApartment().addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
+      }
+    }
+  }
+
+} // namespace dss
diff --git a/core/model/devicecontainer.h b/core/model/devicecontainer.h
new file mode 100644
index 0000000..85f3e64
--- /dev/null
+++ b/core/model/devicecontainer.h
@@ -0,0 +1,49 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 DEVICECONTAINER_H
+#define DEVICECONTAINER_H
+
+#include <string>
+
+namespace dss {
+
+  class Set;
+
+  /** A class derived from DeviceContainer can deliver a Set of its Devices */
+  class DeviceContainer {
+  private:
+    std::string m_Name;
+  public:
+    /** Returns a set containing all devices of the container. */
+    virtual Set getDevices() const = 0;
+
+    /** Sets the name of the container. */
+    virtual void setName(const std::string& _name);
+    /** Returns the name of the container */
+    const std::string& getName() const { return m_Name; };
+
+    virtual ~DeviceContainer() {};
+  }; // DeviceContainer
+
+} // namespace dss
+
+#endif // DEVICECONTAINER_H
diff --git a/core/model/deviceinterface.cpp b/core/model/deviceinterface.cpp
new file mode 100644
index 0000000..f677f67
--- /dev/null
+++ b/core/model/deviceinterface.cpp
@@ -0,0 +1,35 @@
+/*
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "deviceinterface.h"
+
+#include "core/ds485const.h"
+
+namespace dss {
+  //================================================== IDeviceInterface
+
+  void IDeviceInterface::turnOn() {
+    callScene(SceneMax);
+  }
+
+  void IDeviceInterface::turnOff() {
+    callScene(SceneMin);
+  }
+
+}
\ No newline at end of file
diff --git a/core/model/deviceinterface.h b/core/model/deviceinterface.h
new file mode 100644
index 0000000..ac5c103
--- /dev/null
+++ b/core/model/deviceinterface.h
@@ -0,0 +1,83 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 DEVICEINTERFACE_H
+#define DEVICEINTERFACE_H
+
+namespace dss {
+  
+  /** Interface to a single or multiple devices.
+   */
+  class IDeviceInterface {
+  public:
+    /** Turns the device on.
+     *  This will invoke scene "max".
+     */
+    virtual void turnOn();
+    /** Turns the device off.
+     * This will invoke scene "min"
+     */
+    virtual void turnOff();
+
+    /** Increases the main value (e.g. brightness) */
+    virtual void increaseValue() = 0;
+    /** Decreases the main value (e.g. brightness) */
+    virtual void decreaseValue() = 0;
+
+    /** Starts dimming the given parameter.
+     * If _directionUp is true, the value gets increased over time. Else its getting decreased.
+     */
+    virtual void startDim(const bool _directionUp) = 0;
+    /** Stops the dimming */
+    virtual void endDim() = 0;
+    /** Sets the value of the given parameter */
+    virtual void setValue(const double _value) = 0;
+
+
+    /** Sets the scene on the device.
+     * The output value will be set according to the scene lookup table in the device.
+     */
+    virtual void callScene(const int _sceneNr) = 0;
+    /** Stores the current output value into the scene lookup table.
+     * The next time scene _sceneNr gets called the output will be set according to the lookup table.
+     */
+    virtual void saveScene(const int _sceneNr) = 0;
+    /** Restores the last set value of _sceneNr
+     */
+    virtual void undoScene(const int _sceneNr) = 0;
+
+    /** Returns the consumption in mW */
+    virtual unsigned long getPowerConsumption() = 0;
+
+    /** Calls the next scene according to the last called scene.
+     * @see dss::SceneHelper::getNextScene
+     */
+    virtual void nextScene() = 0;
+    /** Calls the previos scene according to the last called scene.
+     * @see dss::SceneHelper::getPreviousScene
+     */
+    virtual void previousScene() = 0;
+
+    virtual ~IDeviceInterface() {};
+  }; // IDeviceInterface
+
+} // namespace dss
+#endif // DEVICEINTERFACE_H
diff --git a/core/model/devicereference.cpp b/core/model/devicereference.cpp
new file mode 100644
index 0000000..0262058
--- /dev/null
+++ b/core/model/devicereference.cpp
@@ -0,0 +1,125 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "devicereference.h"
+
+#include "device.h"
+#include "apartment.h"
+
+namespace dss {
+
+  //================================================== DeviceReference
+
+  DeviceReference::DeviceReference(const DeviceReference& _copy)
+  : m_DSID(_copy.m_DSID),
+    m_Apartment(_copy.m_Apartment)
+  {
+  } // ctor(copy)
+
+  DeviceReference::DeviceReference(const dsid_t _dsid, const Apartment* _apartment)
+  : m_DSID(_dsid),
+    m_Apartment(_apartment)
+  {
+  } // ctor(dsid)
+
+  DeviceReference::DeviceReference(const Device& _device, const Apartment* _apartment)
+  : m_DSID(_device.getDSID()),
+    m_Apartment(_apartment)
+  {
+  } // ctor(device)
+
+  Device& DeviceReference::getDevice() {
+    return m_Apartment->getDeviceByDSID(m_DSID);
+  } // getDevice
+
+  const Device& DeviceReference::getDevice() const {
+    return m_Apartment->getDeviceByDSID(m_DSID);
+  } // getDevice
+
+  dsid_t DeviceReference::getDSID() const {
+    return m_DSID;
+  } // getID
+
+  std::string DeviceReference::getName() const {
+    return getDevice().getName();
+  } //getName
+
+  void DeviceReference::increaseValue() {
+    getDevice().increaseValue();
+  } // increaseValue
+
+  void DeviceReference::decreaseValue() {
+    getDevice().decreaseValue();
+  } // decreaseValue
+
+  void DeviceReference::enable() {
+    getDevice().enable();
+  } // enable
+
+  void DeviceReference::disable() {
+    getDevice().disable();
+  } // disable
+
+  void DeviceReference::startDim(const bool _directionUp) {
+    getDevice().startDim(_directionUp);
+  } // startDim
+
+  void DeviceReference::endDim() {
+    getDevice().endDim();
+  } // endDim
+
+  void DeviceReference::setValue(const double _value) {
+    getDevice().setValue(_value);
+  } // setValue
+
+  bool DeviceReference::isOn() const {
+    return getDevice().isOn();
+  }
+
+  bool DeviceReference::hasSwitch() const {
+    return getDevice().hasSwitch();
+  }
+
+  void DeviceReference::callScene(const int _sceneNr) {
+    getDevice().callScene(_sceneNr);
+  } // callScene
+
+  void DeviceReference::saveScene(const int _sceneNr) {
+    getDevice().saveScene(_sceneNr);
+  } // saveScene
+
+  void DeviceReference::undoScene(const int _sceneNr) {
+    getDevice().undoScene(_sceneNr);
+  } // undoScene
+
+  unsigned long DeviceReference::getPowerConsumption() {
+    return getDevice().getPowerConsumption();
+  }
+
+  void DeviceReference::nextScene() {
+    getDevice().nextScene();
+  }
+
+  void DeviceReference::previousScene() {
+    getDevice().previousScene();
+  }
+
+} // namespace dss
diff --git a/core/model/devicereference.h b/core/model/devicereference.h
new file mode 100644
index 0000000..7162c83
--- /dev/null
+++ b/core/model/devicereference.h
@@ -0,0 +1,102 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 DEVICEREFERENCE_H
+#define DEVICEREFERENCE_H
+
+#include "core/ds485types.h"
+#include "deviceinterface.h"
+
+namespace dss {
+  
+  class Apartment;
+  class Device;
+  
+    /** Internal reference to a device.
+   * A DeviceReference is virtually interchangable with a device. It is used in places
+     where a reference to a device is needed.
+   */
+  class DeviceReference : public IDeviceInterface {
+  private:
+    dsid_t m_DSID;
+    const Apartment* m_Apartment;
+  public:
+    /** Copy constructor */
+    DeviceReference(const DeviceReference& _copy);
+    DeviceReference(const dsid_t _dsid, const Apartment* _apartment);
+    DeviceReference(const Device& _device, const Apartment* _apartment);
+    virtual ~DeviceReference() {};
+
+    /** Returns a reference to the referenced device
+     * @note This accesses the apartment which has to be valid.
+     */
+    Device& getDevice();
+    /** @copydoc getDevice() */
+    const Device& getDevice() const;
+    /** Returns the DSID of the referenced device */
+    dsid_t getDSID() const;
+
+    /** Returns the function id.
+     * @note This will lookup the device */
+    int getFunctionID() const;
+    bool hasSwitch() const;
+
+    /** Compares two device references.
+     * Device references are considered equal if their DSID match. */
+    bool operator==(const DeviceReference& _other) const {
+      return m_DSID == _other.m_DSID;
+    }
+
+    /** Returns the name of the referenced device.
+     * @note This will lookup the device. */
+    std::string getName() const;
+
+    virtual void setValue(const double _value);
+
+    virtual void increaseValue();
+    virtual void decreaseValue();
+
+    void enable();
+    void disable();
+
+    /** Returns wheter the device is turned on.
+     * @note The detection is soly based on the last called scene. As soon as we've
+     * got submetering data this should reflect the real state.
+     */
+    virtual bool isOn() const;
+
+    virtual void startDim(const bool _directionUp);
+    virtual void endDim();
+
+    virtual void callScene(const int _sceneNr);
+    virtual void saveScene(const int _sceneNr);
+    virtual void undoScene(const int _sceneNr);
+
+    virtual void nextScene();
+    virtual void previousScene();
+
+    virtual unsigned long getPowerConsumption();
+ }; // DeviceReference
+
+} // namespace dss
+
+#endif // DEVICEREFERENCE_H
diff --git a/core/model/group.cpp b/core/model/group.cpp
new file mode 100644
index 0000000..3394011
--- /dev/null
+++ b/core/model/group.cpp
@@ -0,0 +1,80 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "group.h"
+#include "scenehelper.h"
+#include "set.h"
+#include "apartment.h"
+
+#include "core/ds485const.h"
+namespace dss {
+
+    //============================================= Group
+
+  Group::Group(const int _id, const int _zoneID, Apartment& _apartment)
+  : AddressableModelItem(&_apartment),
+    m_ZoneID(_zoneID),
+    m_GroupID(_id),
+    m_LastCalledScene(SceneOff)
+  {
+  } // ctor
+
+  int Group::getID() const {
+    return m_GroupID;
+  } // getID
+
+  int Group::getZoneID() const {
+    return m_ZoneID;
+  } // getZoneID
+
+  Set Group::getDevices() const {
+    return m_pApartment->getDevices().getByZone(m_ZoneID).getByGroup(m_GroupID);
+  } // getDevices
+
+  Group& Group::operator=(const Group& _other) {
+    m_Devices = _other.m_Devices;
+    m_GroupID = _other.m_GroupID;
+    m_ZoneID = _other.m_ZoneID;
+    return *this;
+  } // operator=
+
+  void Group::callScene(const int _sceneNr) {
+    // this might be redundant, but since a set could be
+    // optimized if it contains only one device its safer like that...
+    if(SceneHelper::rememberScene(_sceneNr & 0x00ff)) {
+      m_LastCalledScene = _sceneNr & 0x00ff;
+    }
+    AddressableModelItem::callScene(_sceneNr);
+  } // callScene
+
+  unsigned long Group::getPowerConsumption() {
+    return getDevices().getPowerConsumption();
+  } // getPowerConsumption
+
+  void Group::nextScene() {
+    callScene(SceneHelper::getNextScene(m_LastCalledScene));
+  } // nextScene
+
+  void Group::previousScene() {
+    callScene(SceneHelper::getPreviousScene(m_LastCalledScene));
+  } // previousScene
+
+} // namespace dss
diff --git a/core/model/group.h b/core/model/group.h
new file mode 100644
index 0000000..c50d172
--- /dev/null
+++ b/core/model/group.h
@@ -0,0 +1,83 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 GROUP_H
+#define GROUP_H
+
+#include "modeltypes.h"
+#include "devicecontainer.h"
+#include "addressablemodelitem.h"
+
+namespace dss {
+
+  /** Represents a predefined group */
+  class Group : public DeviceContainer,
+                public AddressableModelItem {
+  protected:
+    DeviceVector m_Devices;
+    int m_ZoneID;
+    int m_GroupID;
+    int m_LastCalledScene;
+  public:
+    /** Constructs a group with the given id belonging to \a _zoneID. */
+    Group(const int _id, const int _zoneID, Apartment& _apartment);
+    virtual ~Group() {};
+    virtual Set getDevices() const;
+
+    /** Returns the id of the group */
+    int getID() const;
+    int getZoneID() const;
+
+    virtual void callScene(const int _sceneNr);
+
+    virtual void nextScene();
+    virtual void previousScene();
+
+    virtual unsigned long getPowerConsumption();
+
+    /** @copydoc Device::getLastCalledScene */
+    int getLastCalledScene() const { return m_LastCalledScene; }
+    /** @copydoc Device::setLastCalledScene */
+    void setLastCalledScene(const int _value) { m_LastCalledScene = _value; }
+
+    /** Compares a group to another group.
+     * Two groups are considered equal if they belong to the same group and zone. */
+    Group& operator=(const Group& _other);
+  }; // Group
+
+
+  /** Represents a user-defined-group */
+  class UserGroup : public Group {
+  private:
+  public:
+    /** Adds a device to the group.
+     * This will permanently add the device to the group.
+     */
+    virtual void addDevice(const Device& _device);
+    /** Removes a device from the group.
+     * This will permanently remove the device from the group.
+     */
+    virtual void removeDevice(const Device& _device);
+  }; // UserGroup
+
+} // namespace dss
+
+#endif // GROUP_H
diff --git a/core/model/modelevent.cpp b/core/model/modelevent.cpp
new file mode 100644
index 0000000..dd345ed
--- /dev/null
+++ b/core/model/modelevent.cpp
@@ -0,0 +1,27 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "modelevent.h"
+
+namespace dss {
+
+} // namespace dss
diff --git a/core/model/modelevent.h b/core/model/modelevent.h
new file mode 100644
index 0000000..744a93f
--- /dev/null
+++ b/core/model/modelevent.h
@@ -0,0 +1,70 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 MODELEVENT_H
+#define MODELEVENT_H
+
+#include <vector>
+
+namespace dss {
+
+  /** A Model event gets processed by the apartment asynchronously.
+   * It consists of multiple integer parameter whose meanig is defined by ModelEvent::EventType
+   */
+  class ModelEvent {
+  public:
+    typedef enum { etCallSceneGroup,  /**< A group has changed the scene. */
+                   etCallSceneDevice, /**< A device has changed the scene (only raised from the simulation at the moment). */
+                   etNewDevice,       /**< A new device has been detected */
+                   etModelDirty,      /**< A parameter that will be stored in \c apartment.xml has been changed. */
+                   etDSLinkInterrupt,  /**< An interrupt has occured */
+                   etNewModulator, /**< A new modulator has joined the bus */
+                   etLostModulator, /**< We've lost a modulator on the bus */
+                   etModulatorReady, /**< A modulator has completed its scanning cycle and is now ready */
+                   etBusReady, /**< The bus transitioned into ready state */
+                   etPowerConsumption, /**< Powerconsumption message happened */
+                   etEnergyMeterValue, /**< Powerconsumption message happened */
+                   etDS485DeviceDiscovered, /**< A new device has been discovered on the bus */
+                 } EventType;
+  private:
+    EventType m_EventType;
+    std::vector<int> m_Parameter;
+  public:
+    /** Constructs a ModelEvent with the given EventType. */
+    ModelEvent(EventType _type)
+    : m_EventType(_type)
+    {}
+
+    /** Adds an integer parameter. */
+    void addParameter(const int _param) { m_Parameter.push_back(_param); }
+    /** Returns the parameter at _index.
+     * @note Check getParameterCount to check the bounds. */
+    int getParameter(const int _index) const { return m_Parameter.at(_index); }
+    /** Returns the parameter count. */
+    int getParameterCount() const { return m_Parameter.size(); }
+    /** Returns the type of the event. */
+    EventType getEventType() { return m_EventType; }
+  }; // ModelEvent
+
+} // namespace dss
+
+#endif // MODELEVENT_H
diff --git a/core/model/modeltypes.h b/core/model/modeltypes.h
new file mode 100644
index 0000000..2f7ffd4
--- /dev/null
+++ b/core/model/modeltypes.h
@@ -0,0 +1,39 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "devicereference.h"
+
+#ifndef MODELTYPES_H
+#define MODELTYPES_H
+
+#include <vector>
+
+#include "devicereference.h"
+
+namespace dss {
+
+  typedef std::vector<DeviceReference> DeviceVector;
+  typedef DeviceVector::iterator DeviceIterator;
+  typedef DeviceVector::const_iterator DeviceConstIterator;
+
+}
+
+#endif
\ No newline at end of file
diff --git a/core/model/modulator.cpp b/core/model/modulator.cpp
new file mode 100644
index 0000000..64a0324
--- /dev/null
+++ b/core/model/modulator.cpp
@@ -0,0 +1,117 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "modulator.h"
+
+#include "core/dss.h"
+#include "core/logger.h"
+#include "core/DS485Interface.h"
+#include "set.h"
+
+namespace dss {
+
+  //================================================== Modulator
+
+  Modulator::Modulator(const dsid_t _dsid)
+  : m_DSID(_dsid),
+    m_BusID(0xFF),
+    m_PowerConsumption(0),
+    m_EnergyMeterValue(0),
+    m_IsValid(false)
+  {
+  } // ctor
+
+  Set Modulator::getDevices() const {
+    return m_ConnectedDevices;
+  } // getDevices
+
+  void Modulator::addDevice(const DeviceReference& _device) {
+    if(!contains(m_ConnectedDevices, _device)) {
+      m_ConnectedDevices.push_back(_device);
+    } else {
+      Logger::getInstance()->log("Modulator::addDevice: DUPLICATE DEVICE Detected modulator: " + intToString(m_BusID) + " device: " + _device.getDSID().toString(), lsFatal);
+    }
+  } // addDevice
+
+  void Modulator::removeDevice(const DeviceReference& _device) {
+    DeviceIterator pos = find(m_ConnectedDevices.begin(), m_ConnectedDevices.end(), _device);
+    if(pos != m_ConnectedDevices.end()) {
+      m_ConnectedDevices.erase(pos);
+    }
+  } // removeDevice
+
+  dsid_t Modulator::getDSID() const {
+    return m_DSID;
+  } // getDSID
+
+  int Modulator::getBusID() const {
+    return m_BusID;
+  } // getBusID
+
+  void Modulator::setBusID(const int _busID) {
+    m_BusID = _busID;
+  } // setBusID
+
+  unsigned long Modulator::getPowerConsumption() {
+    DateTime now;
+    if(!now.addSeconds(-1).before(m_PowerConsumptionAge)) {
+      m_PowerConsumption =  DSS::getInstance()->getDS485Interface().getPowerConsumption(m_BusID);
+      m_PowerConsumptionAge = now;
+    }
+    return m_PowerConsumption;
+  } // getPowerConsumption
+
+  unsigned long Modulator::getEnergyMeterValue() {
+    DateTime now;
+    if(!now.addSeconds(-1).before(m_EnergyMeterValueAge)) {
+      m_EnergyMeterValue = DSS::getInstance()->getDS485Interface().getEnergyMeterValue(m_BusID);
+      m_EnergyMeterValueAge = now;
+    }
+    return m_EnergyMeterValue;
+  } // getEnergyMeterValue
+
+
+  /** set the consumption in mW */
+  void Modulator::setPowerConsumption(unsigned long _value)
+  {
+    DateTime now;
+    m_PowerConsumptionAge = now;
+    m_PowerConsumption = _value;
+  }
+
+  /** set the meter value in Wh */
+  void Modulator::setEnergyMeterValue(unsigned long _value)
+  {
+    DateTime now;
+    m_EnergyMeterValueAge = now;
+    m_EnergyMeterValue = _value;
+  }
+
+  unsigned long Modulator::getCachedPowerConsumption() {
+    return m_PowerConsumption;
+  } // getPowerConsumption
+
+  unsigned long Modulator::getCachedEnergyMeterValue() {
+    return m_EnergyMeterValue;
+  } // getEnergyMeterValue
+
+
+} // namespace dss
diff --git a/core/model/modulator.h b/core/model/modulator.h
new file mode 100644
index 0000000..dd98e08
--- /dev/null
+++ b/core/model/modulator.h
@@ -0,0 +1,118 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 MODULATOR_H
+#define MODULATOR_H
+
+#include <string>
+
+#include "devicecontainer.h"
+#include "physicalmodelitem.h"
+#include "core/ds485types.h"
+#include "core/model/modeltypes.h"
+#include "core/datetools.h"
+
+namespace dss {
+
+  /** Represents a Modulator */
+  class Modulator : public DeviceContainer,
+                    public PhysicalModelItem {
+  private:
+    dsid_t m_DSID;
+    int m_BusID;
+    DeviceVector m_ConnectedDevices;
+    int m_EnergyLevelOrange;
+    int m_EnergyLevelRed;
+    int m_PowerConsumption;
+    DateTime m_PowerConsumptionAge;
+    int m_EnergyMeterValue;
+    DateTime m_EnergyMeterValueAge;
+    int m_HardwareVersion;
+    int m_SoftwareVersion;
+    std::string m_HardwareName;
+    int m_DeviceType;
+    bool m_IsValid;
+  public:
+    /** Constructs a modulator with the given dsid. */
+    Modulator(const dsid_t _dsid);
+    virtual ~Modulator() {};
+    virtual Set getDevices() const;
+
+    /** Returns the DSID of the Modulator */
+    dsid_t getDSID() const;
+    /** Returns the bus id of the Modulator */
+    int getBusID() const;
+    /** Sets the bus id of the Modulator */
+    void setBusID(const int _busID);
+
+    /** Adds a DeviceReference to the modulators devices list */
+    void addDevice(const DeviceReference& _device);
+
+    /** Removes the device identified by the reference. */
+    void removeDevice(const DeviceReference& _device);
+
+    /** Returns the consumption in mW */
+    unsigned long getPowerConsumption();
+    /** Returns the meter value in Wh */
+    unsigned long getEnergyMeterValue();
+
+
+    /** set the consumption in mW */
+    void setPowerConsumption(unsigned long _value);
+    /** set the meter value in Wh */
+    void setEnergyMeterValue(unsigned long _value);
+
+    /** Returns the last consumption in mW returned from dS485 Bus, but never request it*/
+    unsigned long getCachedPowerConsumption();
+    /** Returns the last meter value in Wh returned from dS485 Bus, but never request it*/
+    unsigned long getCachedEnergyMeterValue();
+
+    /** Returns the orange energy level */
+    int getEnergyLevelOrange() const { return m_EnergyLevelOrange; }
+    /** Returns the red energy level */
+    int getEnergyLevelRed() const { return m_EnergyLevelRed; }
+    /** Sets the orange energy level.
+     * @note This has no effect on the modulator as of now. */
+    void setEnergyLevelRed(const int _value) { m_EnergyLevelRed = _value; }
+    /** Sets the red energy level.
+     * @note This has no effect on the modulator as of now. */
+    void setEnergyLevelOrange(const int _value) { m_EnergyLevelOrange = _value; }
+
+    int getHardwareVersion() const { return m_HardwareVersion; }
+    void setHardwareVersion(const int _value) { m_HardwareVersion = _value; }
+    int getSoftwareVersion() const { return m_SoftwareVersion; }
+    void setSoftwareVersion(const int _value) { m_SoftwareVersion = _value; }
+    std::string getHardwareName() const { return m_HardwareName; }
+    void setHardwareName(const std::string& _value) { m_HardwareName = _value; }
+    int getDeviceType() { return m_DeviceType; }
+    void setDeviceType(const int _value) { m_DeviceType = _value; }
+
+    /** Returns true if the modulator has been read-out completely. */
+    bool isValid() const { return m_IsValid; }
+    void setIsValid(const bool _value) { m_IsValid = _value; }
+  }; // Modulator
+
+  
+} // namespace dss
+
+
+#endif // MODULATOR_H
diff --git a/core/model/nonaddressablemodelitem.cpp b/core/model/nonaddressablemodelitem.cpp
new file mode 100644
index 0000000..4a25b4d
--- /dev/null
+++ b/core/model/nonaddressablemodelitem.cpp
@@ -0,0 +1,91 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "nonaddressablemodelitem.h"
+
+#include "core/foreach.h"
+#include "addressablemodelitem.h"
+
+namespace dss {
+
+  //================================================== NonAddressableModelItem
+
+  void NonAddressableModelItem::increaseValue() {
+    std::vector<AddressableModelItem*> items = splitIntoAddressableItems();
+    foreach(AddressableModelItem* item, items) {
+      item->increaseValue();
+    }
+  } // increaseValue
+
+  void NonAddressableModelItem::decreaseValue() {
+    std::vector<AddressableModelItem*> items = splitIntoAddressableItems();
+    foreach(AddressableModelItem* item, items) {
+      item->decreaseValue();
+    }
+  } // decreaseValue
+
+  void NonAddressableModelItem::startDim(const bool _directionUp) {
+    std::vector<AddressableModelItem*> items = splitIntoAddressableItems();
+    foreach(AddressableModelItem* item, items) {
+      item->startDim(_directionUp);
+    }
+  } // startDim
+
+  void NonAddressableModelItem::endDim() {
+    std::vector<AddressableModelItem*> items = splitIntoAddressableItems();
+    foreach(AddressableModelItem* item, items) {
+      item->endDim();
+    }
+  } // endDim
+
+  void NonAddressableModelItem::setValue(const double _value) {
+    std::vector<AddressableModelItem*> items = splitIntoAddressableItems();
+    foreach(AddressableModelItem* item, items) {
+      item->setValue(_value);
+    }
+  } // setValue
+
+  void NonAddressableModelItem::callScene(const int _sceneNr) {
+    std::vector<AddressableModelItem*> items = splitIntoAddressableItems();
+    foreach(AddressableModelItem* item, items) {
+      item->callScene(_sceneNr);
+    }
+  } // callScene
+
+  void NonAddressableModelItem::saveScene(const int _sceneNr) {
+    std::vector<AddressableModelItem*> items = splitIntoAddressableItems();
+    foreach(AddressableModelItem* item, items) {
+      item->saveScene(_sceneNr);
+    }
+  } // saveScene
+
+  void NonAddressableModelItem::undoScene(const int _sceneNr) {
+    std::vector<AddressableModelItem*> items = splitIntoAddressableItems();
+    foreach(AddressableModelItem* item, items) {
+      item->undoScene(_sceneNr);
+    }
+  } // undoScene
+/*
+    virtual void nextScene();
+    virtual void previousScene();
+*/
+
+} // namespace dss
diff --git a/core/model/nonaddressablemodelitem.h b/core/model/nonaddressablemodelitem.h
new file mode 100644
index 0000000..0c1a917
--- /dev/null
+++ b/core/model/nonaddressablemodelitem.h
@@ -0,0 +1,55 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 NONADDRESSABLEMODELITEM_H
+#define NONADDRESSABLEMODELITEM_H
+
+#include <vector>
+
+#include "devicereference.h"
+
+namespace dss {
+
+  class AddressableModelItem;
+  
+  class NonAddressableModelItem : public IDeviceInterface {
+  public:
+    virtual void increaseValue();
+    virtual void decreaseValue();
+
+    virtual void startDim(const bool _directionUp);
+    virtual void endDim();
+
+    virtual void setValue(const double _value);
+
+    virtual void callScene(const int _sceneNr);
+    virtual void saveScene(const int _sceneNr);
+    virtual void undoScene(const int _sceneNr);
+/*
+    virtual void nextScene();
+    virtual void previousScene();
+*/
+  protected:
+    virtual std::vector<AddressableModelItem*> splitIntoAddressableItems() = 0;
+  }; // NonAddressableModelItem
+
+} // namespace dss
+
+#endif // NONADDRESSABLEMODELITEM_H
diff --git a/core/model/physicalmodelitem.cpp b/core/model/physicalmodelitem.cpp
new file mode 100644
index 0000000..d89aa8f
--- /dev/null
+++ b/core/model/physicalmodelitem.cpp
@@ -0,0 +1,23 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "physicalmodelitem.h"
+
diff --git a/core/model/physicalmodelitem.h b/core/model/physicalmodelitem.h
new file mode 100644
index 0000000..66d0083
--- /dev/null
+++ b/core/model/physicalmodelitem.h
@@ -0,0 +1,41 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 PHYSICALMODELITEM_H
+#define PHYSICALMODELITEM_H
+
+namespace dss {
+
+  class PhysicalModelItem {
+  private:
+    bool m_IsPresent;
+  public:
+    PhysicalModelItem()
+    : m_IsPresent(false)
+    { }
+
+    bool isPresent() const { return m_IsPresent; }
+    virtual void setIsPresent(const bool _value) { m_IsPresent = _value; }
+  };
+
+}
+
+#endif // PHYSICALMODELITEM_H
diff --git a/core/model/scenehelper.cpp b/core/model/scenehelper.cpp
new file mode 100644
index 0000000..6128e33
--- /dev/null
+++ b/core/model/scenehelper.cpp
@@ -0,0 +1,102 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "scenehelper.h"
+
+#include <cassert>
+
+#include "core/ds485const.h"
+
+namespace dss {
+
+  //================================================== Utils
+
+  unsigned int SceneHelper::getNextScene(const unsigned int _currentScene) {
+    switch(_currentScene) {
+    case ScenePanic:
+    case SceneStandBy:
+    case SceneDeepOff:
+    case SceneOff:
+    case Scene1:
+      return Scene2;
+    case Scene2:
+      return Scene3;
+    case Scene3:
+      return Scene4;
+    case Scene4:
+      return Scene2;
+    default:
+      return Scene1;
+    }
+  } // getNextScene
+
+  unsigned int SceneHelper::getPreviousScene(const unsigned int _currentScene) {
+    switch(_currentScene) {
+    case ScenePanic:
+    case SceneStandBy:
+    case SceneDeepOff:
+    case SceneOff:
+    case Scene1:
+      return Scene4;
+    case Scene2:
+      return Scene4;
+    case Scene3:
+      return Scene2;
+    case Scene4:
+      return Scene3;
+    default:
+      return Scene1;
+    }
+  } // getPreviousScene
+
+  bool SceneHelper::m_Initialized = false;
+  std::bitset<64> SceneHelper::m_ZonesToIgnore;
+
+  void SceneHelper::initialize() {
+    m_Initialized = true;
+    m_ZonesToIgnore.reset();
+    m_ZonesToIgnore.set(SceneInc);
+    m_ZonesToIgnore.set(SceneDec);
+    m_ZonesToIgnore.set(SceneStop);
+    m_ZonesToIgnore.set(SceneBell);
+    m_ZonesToIgnore.set(SceneEnergyOverload);
+    m_ZonesToIgnore.set(SceneEnergyHigh);
+    m_ZonesToIgnore.set(SceneEnergyMiddle);
+    m_ZonesToIgnore.set(SceneEnergyLow);
+    m_ZonesToIgnore.set(SceneEnergyClassA);
+    m_ZonesToIgnore.set(SceneEnergyClassB);
+    m_ZonesToIgnore.set(SceneEnergyClassC);
+    m_ZonesToIgnore.set(SceneEnergyClassD);
+    m_ZonesToIgnore.set(SceneEnergyClassE);
+    m_ZonesToIgnore.set(SceneLocalOff);
+    m_ZonesToIgnore.set(SceneLocalOn);
+  }
+
+  bool SceneHelper::rememberScene(const unsigned int _scene) {
+    if(!m_Initialized) {
+      initialize();
+      assert(m_Initialized);
+    }
+    return !m_ZonesToIgnore.test(_scene);
+  } // rememberScene
+
+}
diff --git a/core/model/scenehelper.h b/core/model/scenehelper.h
new file mode 100644
index 0000000..54203ed
--- /dev/null
+++ b/core/model/scenehelper.h
@@ -0,0 +1,56 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 SCENEHELPER_H
+#define SCENEHELPER_H
+
+#include <bitset>
+
+namespace dss {
+
+  /** Helper functions for scene management. */
+  class SceneHelper {
+  private:
+    static std::bitset<64> m_ZonesToIgnore;
+    static bool m_Initialized;
+
+    static void initialize();
+  public:
+    /** Returns wheter to remember a scene.
+     * Certain scenes represent events thus they won't have to be remembered.
+     */
+    static bool rememberScene(const unsigned int _sceneID);
+    /** Returns the next scene based on _currentScene.
+     * From off to Scene1 -> Scene2 -> Scene3 -> Scene4 -> Scene1...
+     * \param _currentScene Scene now active.
+     */
+    static unsigned int getNextScene(const unsigned int _currentScene);
+    /** Returns the previous scene based on _currentScene.
+     * From off to Scene1 -> Scene4 -> Scene3 -> Scene2 -> Scene1...
+     * \param _currentScene Scene now active.
+     */
+    static unsigned int getPreviousScene(const unsigned int _currentScene);
+  }; // SceneHelper
+
+} // namespace dss
+
+#endif // SCENEHELPER_H
diff --git a/core/model/set.cpp b/core/model/set.cpp
new file mode 100644
index 0000000..1a2acb5
--- /dev/null
+++ b/core/model/set.cpp
@@ -0,0 +1,505 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "set.h"
+
+#include <stdexcept>
+// hash_map,map used by SetSplitter
+#include <map>
+#ifndef WIN32 
+#include <ext/hash_map>
+#else
+#include <hash_map>
+#endif
+#ifndef WIN32
+using namespace __gnu_cxx;
+#else
+using namespace stdext;
+#endif
+
+#include "core/logger.h"
+#include "core/foreach.h"
+#include "core/ds485const.h"
+
+#include "device.h"
+#include "group.h"
+#include "apartment.h"
+#include "zone.h"
+#include "modulator.h"
+
+namespace dss {
+
+    //================================================== Set
+
+  Set::Set() {
+  } // ctor
+
+  Set::Set(Device& _device) {
+    m_ContainedDevices.push_back(DeviceReference(_device, &_device.getApartment()));
+  } // ctor(Device)
+
+  Set::Set(DeviceVector _devices) {
+    m_ContainedDevices = _devices;
+  } // ctor(DeviceVector)
+
+  Set::Set(const Set& _copy) {
+    m_ContainedDevices = _copy.m_ContainedDevices;
+  }
+
+  void Set::nextScene() {
+    throw std::runtime_error("Not yet implemented");
+  } // nextScene
+
+  void Set::previousScene() {
+    throw std::runtime_error("Not yet implemented");
+  } // previousScene
+
+  void Set::perform(IDeviceAction& _deviceAction) {
+    for(DeviceIterator iDevice = m_ContainedDevices.begin(); iDevice != m_ContainedDevices.end(); ++iDevice) {
+      _deviceAction.perform(iDevice->getDevice());
+    }
+  } // perform
+
+  Set Set::getSubset(const IDeviceSelector& _selector) const {
+    Set result;
+    foreach(DeviceReference iDevice, m_ContainedDevices) {
+      if(_selector.selectDevice(iDevice.getDevice())) {
+        result.addDevice(iDevice);
+      }
+    }
+    return result;
+  } // getSubset
+
+  class ByGroupSelector : public IDeviceSelector {
+  private:
+    const int m_GroupNr;
+  public:
+    ByGroupSelector(const int _groupNr)
+    : m_GroupNr(_groupNr)
+    {}
+
+    virtual ~ByGroupSelector() {}
+
+    virtual bool selectDevice(const Device& _device) const {
+      return _device.isInGroup(m_GroupNr);
+    }
+  };
+
+  Set Set::getByGroup(int _groupNr) const {
+    if(_groupNr != GroupIDBroadcast) {
+      return getSubset(ByGroupSelector(_groupNr));
+    } else {
+      return *this;
+    }
+  } // getByGroup(id)
+
+  Set Set::getByGroup(const Group& _group) const {
+    return getByGroup(_group.getID());
+  } // getByGroup(ref)
+
+  Set Set::getByGroup(const std::string& _name) const {
+    Set result;
+    if(isEmpty()) {
+      return result;
+    } else {
+      Group& g = get(0).getDevice().getApartment().getGroup(_name);
+      return getByGroup(g.getID());
+    }
+  } // getByGroup(name)
+
+  Set Set::getByZone(int _zoneID) const {
+    if(_zoneID != 0) {
+      Set result;
+      foreach(const DeviceReference& dev, m_ContainedDevices) {
+        if(dev.getDevice().getZoneID() == _zoneID) {
+          result.addDevice(dev);
+        }
+      }
+      return result;
+    } else {
+      // return a copy of this set if the broadcast zone was requested
+      return *this;
+    }
+  } // getByZone(id)
+
+  Set Set::getByZone(const std::string& _zoneName) const {
+    Set result;
+    if(isEmpty()) {
+      return result;
+    } else {
+      Zone& zone = get(0).getDevice().getApartment().getZone(_zoneName);
+      return getByZone(zone.getID());
+    }
+  } // getByZone(name)
+
+  Set Set::getByModulator(const int _modulatorID) const {
+    Set result;
+    foreach(const DeviceReference& dev, m_ContainedDevices) {
+      if(dev.getDevice().getModulatorID() == _modulatorID) {
+        result.addDevice(dev);
+      }
+    }
+    return result;
+  } // getByModulator
+
+  Set Set::getByModulator(const Modulator& _modulator) const {
+    return getByModulator(_modulator.getBusID());
+  } // getByModulator
+
+  Set Set::getByFunctionID(const int _functionID) const {
+    Set result;
+    foreach(const DeviceReference& dev, m_ContainedDevices) {
+      if(dev.getDevice().getFunctionID() == _functionID) {
+        result.addDevice(dev);
+      }
+    }
+    return result;
+  } // getByFunctionID
+
+  Set Set::getByPresence(const bool _presence) const {
+    Set result;
+    foreach(const DeviceReference& dev, m_ContainedDevices) {
+      if(dev.getDevice().isPresent()== _presence) {
+        result.addDevice(dev);
+      }
+    }
+    return result;
+  } // getByPresence
+
+  class ByNameSelector : public IDeviceSelector {
+  private:
+    const std::string m_Name;
+  public:
+    ByNameSelector(const std::string& _name) : m_Name(_name) {};
+    virtual ~ByNameSelector() {};
+
+    virtual bool selectDevice(const Device& _device) const {
+      return _device.getName() == m_Name;
+    }
+  };
+
+  DeviceReference Set::getByName(const std::string& _name) const {
+    Set resultSet = getSubset(ByNameSelector(_name));
+    if(resultSet.length() == 0) {
+      throw ItemNotFoundException(_name);
+    }
+    return resultSet.m_ContainedDevices.front();
+  } // getByName
+
+
+  class ByIDSelector : public IDeviceSelector {
+  private:
+    const devid_t m_ID;
+  public:
+    ByIDSelector(const devid_t _id) : m_ID(_id) {}
+    virtual ~ByIDSelector() {};
+
+    virtual bool selectDevice(const Device& _device) const {
+      return _device.getShortAddress() == m_ID;
+    }
+  };
+
+  DeviceReference Set::getByBusID(const devid_t _id) const {
+    Set resultSet = getSubset(ByIDSelector(_id));
+    if(resultSet.length() == 0) {
+      throw ItemNotFoundException(std::string("with busid ") + intToString(_id));
+    }
+    return resultSet.m_ContainedDevices.front();
+  } // getByBusID
+
+  class ByDSIDSelector : public IDeviceSelector {
+  private:
+    const dsid_t m_ID;
+  public:
+    ByDSIDSelector(const dsid_t _id) : m_ID(_id) {}
+    virtual ~ByDSIDSelector() {};
+
+    virtual bool selectDevice(const Device& _device) const {
+      return _device.getDSID() == m_ID;
+    }
+  };
+
+  DeviceReference Set::getByDSID(const dsid_t _dsid) const {
+    Set resultSet = getSubset(ByDSIDSelector(_dsid));
+    if(resultSet.length() == 0) {
+      throw ItemNotFoundException("with dsid " + _dsid.toString());
+    }
+    return resultSet.m_ContainedDevices.front();
+  } // getByDSID
+
+  int Set::length() const {
+    return m_ContainedDevices.size();
+  } // length
+
+  bool Set::isEmpty() const {
+    return length() == 0;
+  } // isEmpty
+
+  Set Set::combine(Set& _other) const {
+    Set resultSet(_other);
+    foreach(const DeviceReference& iDevice, m_ContainedDevices) {
+      if(!resultSet.contains(iDevice)) {
+        resultSet.addDevice(iDevice);
+      }
+    }
+    return resultSet;
+  } // combine
+
+  Set Set::remove(const Set& _other) const {
+    Set resultSet(*this);
+    foreach(const DeviceReference& iDevice, _other.m_ContainedDevices) {
+      resultSet.removeDevice(iDevice);
+    }
+    return resultSet;
+  } // remove
+
+  bool Set::contains(const DeviceReference& _device) const {
+    DeviceVector::const_iterator pos = find(m_ContainedDevices.begin(), m_ContainedDevices.end(), _device);
+    return pos != m_ContainedDevices.end();
+  } // contains
+
+  bool Set::contains(const Device& _device) const {
+    return contains(DeviceReference(_device, &_device.getApartment()));
+  } // contains
+
+  void Set::addDevice(const DeviceReference& _device) {
+    if(!contains(_device)) {
+      m_ContainedDevices.push_back(_device);
+    }
+  } // addDevice
+
+  void Set::addDevice(const Device& _device) {
+    addDevice(DeviceReference(_device, &_device.getApartment()));
+  } // addDevice
+
+  void Set::removeDevice(const DeviceReference& _device) {
+    DeviceVector::iterator pos = find(m_ContainedDevices.begin(), m_ContainedDevices.end(), _device);
+    if(pos != m_ContainedDevices.end()) {
+      m_ContainedDevices.erase(pos);
+    }
+  } // removeDevice
+
+  void Set::removeDevice(const Device& _device) {
+    removeDevice(DeviceReference(_device, &_device.getApartment()));
+  } // removeDevice
+
+  const DeviceReference& Set::get(int _index) const {
+    return m_ContainedDevices.at(_index);
+  } // get
+
+  const DeviceReference& Set::operator[](const int _index) const {
+    return get(_index);
+  } // operator[]
+
+  DeviceReference& Set::get(int _index) {
+    return m_ContainedDevices.at(_index);
+  } // get
+
+  DeviceReference& Set::operator[](const int _index) {
+    return get(_index);
+  } // operator[]
+
+  unsigned long Set::getPowerConsumption() {
+    unsigned long result = 0;
+    foreach(DeviceReference& iDevice, m_ContainedDevices) {
+      result += iDevice.getPowerConsumption();
+    }
+    return result;
+  } // getPowerConsumption
+
+  std::ostream& operator<<(std::ostream& out, const Device& _dt) {
+    out << "Device ID " << _dt.getShortAddress();
+    if(!_dt.getName().empty()) {
+      out << " name: " << _dt.getName();
+    }
+    return out;
+  } // operator<<
+
+  class SetSplitter {
+  public:
+    typedef hash_map<const Zone*, std::pair< std::vector<Group*>, Set> > FittingResult;
+    typedef std::vector<AddressableModelItem*> ModelItemVector;
+
+    static std::vector<AddressableModelItem*> splitUp(Set& _set) {
+      std::vector<AddressableModelItem*> result;
+      if(_set.length() == 1) {
+        log("Optimization: Set contains only one device");
+        result.push_back(&_set.get(0).getDevice());
+      } else if(_set.length() > 0) {
+        Apartment& apt = _set.get(0).getDevice().getApartment();
+        if(_set.length() == apt.getDevices().length()) {
+          log("Optimization: Set contains all devices of apartment");
+          result.push_back(apt.getZone(0).getGroup(0));
+        } else {
+          result = bestFit(_set);
+        }
+
+      }
+      return result;
+    }
+  private:
+    typedef std::pair<std::vector<Group*>, Set> FittingResultPerModulator;
+    typedef std::map<const Zone*, Set> HashMapZoneSet;
+    static const bool OptimizerDebug = false;
+
+    static ModelItemVector bestFit(const Set& _set) {
+      ModelItemVector result;
+      HashMapZoneSet zoneToSet = splitByZone(_set);
+
+      std::back_insert_iterator<ModelItemVector> insertionIterator(result);
+      for(HashMapZoneSet::iterator it = zoneToSet.begin(); it != zoneToSet.end(); ++it) {
+        ModelItemVector resultPart = bestFit(*(it->first), it->second);
+        std::copy(resultPart.begin(), resultPart.end(), insertionIterator);
+      }
+
+      return result;
+    } // bestFit(const Set&)
+
+    /** Returns a hash map that contains all zones and the devices in that zone in a set */
+    static HashMapZoneSet splitByZone(const Set& _set) {
+      HashMapZoneSet result;
+      for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
+        const Device& dev = _set.get(iDevice).getDevice();
+        Zone& zone = dev.getApartment().getZone(dev.getZoneID());
+        result[&zone].addDevice(dev);
+      }
+      return result;
+    } // splitByZone
+
+    /** Tries to find a large group containing all devices and a list of devices to
+        address all items in the set*/
+    static ModelItemVector bestFit(const Zone& _zone, const Set& _set) {
+      Set workingCopy = _set;
+
+      ModelItemVector result;
+
+      if(OptimizerDebug) {
+        Logger::getInstance()->log("Finding fit for zone " + intToString(_zone.getID()));
+      }
+
+      if(_zone.getDevices().length() == _set.length()) {
+        Logger::getInstance()->log(std::string("Optimization: Set contains all devices of zone ") + intToString(_zone.getID()));
+        result.push_back(findGroupContainingAllDevices(_set, _zone));
+      } else {
+        std::vector<Group*> unsuitableGroups;
+        Set workingCopy = _set;
+
+        while(!workingCopy.isEmpty()) {
+          DeviceReference& ref = workingCopy.get(0);
+          workingCopy.removeDevice(ref);
+
+          if(OptimizerDebug) {
+            Logger::getInstance()->log("Working with device " + ref.getDSID().toString());
+          }
+
+          bool foundGroup = false;
+          for(int iGroup = 0; iGroup < ref.getDevice().getGroupsCount(); iGroup++) {
+            Group& g = ref.getDevice().getGroupByIndex(iGroup);
+
+            if(OptimizerDebug) {
+              Logger::getInstance()->log("  Checking Group " + intToString(g.getID()));
+            }
+            // continue if already found unsuitable
+            if(find(unsuitableGroups.begin(), unsuitableGroups.end(), &g) != unsuitableGroups.end()) {
+              if(OptimizerDebug) {
+                Logger::getInstance()->log("  Group discarded before, continuing search");
+              }
+              continue;
+            }
+
+            // see if we've got a fit
+            bool groupFits = true;
+            Set devicesInGroup = _zone.getDevices().getByGroup(g);
+            if(OptimizerDebug) {
+              Logger::getInstance()->log("    Group has " + intToString(devicesInGroup.length()) + " devices");
+            }
+            for(int iDevice = 0; iDevice < devicesInGroup.length(); iDevice++) {
+              if(!_set.contains(devicesInGroup.get(iDevice))) {
+                unsuitableGroups.push_back(&g);
+                groupFits = false;
+                if(OptimizerDebug) {
+                  Logger::getInstance()->log("    Original set does _not_ contain device " + devicesInGroup.get(iDevice).getDevice().getDSID().toString());
+                }
+                break;
+              }
+              if(OptimizerDebug) {
+                Logger::getInstance()->log("    Original set contains device " + devicesInGroup.get(iDevice).getDevice().getDSID().toString());
+              }
+            }
+            if(groupFits) {
+              if(OptimizerDebug) {
+                Logger::getInstance()->log("  Found a fit " + intToString(g.getID()));
+              }
+              foundGroup = true;
+              result.push_back(&g);
+              if(OptimizerDebug) {
+                Logger::getInstance()->log("  Removing devices from working copy");
+              }
+              while(!devicesInGroup.isEmpty()) {
+                workingCopy.removeDevice(devicesInGroup.get(0));
+                devicesInGroup.removeDevice(devicesInGroup.get(0));
+              }
+              if(OptimizerDebug) {
+                Logger::getInstance()->log("  Done. (Removing devices from working copy)");
+              }
+              break;
+            }
+          }
+
+          // if no fitting group found
+          if(!foundGroup) {
+            result.push_back(&ref.getDevice());
+          }
+        }
+      }
+      return result;
+    }
+
+    static Group* findGroupContainingAllDevices(const Set& _set, const Zone& _zone) {
+      std::bitset<63> possibleGroups;
+      possibleGroups.set();
+      for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
+        possibleGroups &= _set[iDevice].getDevice().getGroupBitmask();
+      }
+      if(possibleGroups.any()) {
+        for(unsigned int iGroup = 0; iGroup < possibleGroups.size(); iGroup++) {
+          if(possibleGroups.test(iGroup)) {
+            Logger::getInstance()->log("Sending the command to group " + intToString(iGroup + 1));
+            return _zone.getGroup(iGroup + 1);
+          }
+        }
+        assert(false); // can't come here or we've detected a bug in std::bitvector.any()
+      } else {
+        Logger::getInstance()->log("Sending the command to broadcast group");
+        return _zone.getGroup(GroupIDBroadcast);
+      }
+    }
+  private:
+    static void log(const std::string& _line) {
+      Logger::getInstance()->log(_line);
+    }
+  };
+
+  std::vector<AddressableModelItem*> Set::splitIntoAddressableItems() {
+    return SetSplitter::splitUp(*this);
+  } // splitIntoAddressableItems
+
+} // namespace dss
diff --git a/core/model/set.h b/core/model/set.h
new file mode 100644
index 0000000..b409117
--- /dev/null
+++ b/core/model/set.h
@@ -0,0 +1,166 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 SET_H
+#define SET_H
+
+#include "nonaddressablemodelitem.h"
+#include "modeltypes.h"
+
+namespace dss {
+
+  class Device;
+  class Group;
+  class Modulator;
+  
+  /** Abstract interface to select certain Devices from a set */
+  class IDeviceSelector {
+  public:
+    /** The implementor should return true if the device should appear in the
+     * resulting set. */
+    virtual bool selectDevice(const Device& _device) const = 0;
+    virtual ~IDeviceSelector() {}
+  };
+
+  /** Abstract interface to perform an Action on each device of a set */
+  class IDeviceAction {
+  public:
+    /** This action will be performed for every device contained in the set. */
+    virtual bool perform(Device& _device) = 0;
+    virtual ~IDeviceAction() {}
+  };
+  
+  /** A set holds an arbitrary list of devices.
+    * A Command sent to an instance of this class will replicate the command to all
+    * contained devices.
+    * Only references to devices will be stored.
+   */
+  class Set : public NonAddressableModelItem {
+  private:
+    DeviceVector m_ContainedDevices;
+  public:
+    /** Constructor for an empty Set.*/
+    Set();
+    /** Copy constructor. */
+    Set(const Set& _copy);
+    /** Constructor for a set containing only \a _device. */
+    Set(Device& _device);
+    /** Constructor for a set containing only \a _reference. */
+    Set(DeviceReference& _reference);
+    /** Constructor for a set containing \a _devices. */
+    Set(DeviceVector _devices);
+    virtual ~Set() {};
+
+    /** Performs the given action on all contained devices */
+    void perform(IDeviceAction& _deviceAction);
+
+    /** Returns a subset selected by the given selector
+     * A device will be included in the resulting set if _selector.selectDevice(...) return true.
+     */
+    Set getSubset(const IDeviceSelector& _selector) const;
+    /** Returns a subset of the devices which are member of the given group
+    * Note that these groups could be spanned over multiple modulators.
+     */
+    Set getByGroup(int _groupNr) const;
+    /** Returns a subset of the devices which are member of the given group
+     * Note that these groups could be spanned over multiple modulators.
+     */
+    Set getByGroup(const Group& _group) const;
+    /** Returns a subset of the devices which are member of the given group
+     * Note that these groups could be spanned over multiple modulators.
+     */
+    Set getByGroup(const std::string& _name) const;
+
+    /** Returns a subset of devices with the given function-id. */
+    Set getByFunctionID(const int _functionID) const;
+
+    /** Returns a subset that contains all devices belonging to Zone \a _zoneID. */
+    Set getByZone(int _zoneID) const;
+
+    /** Returns a subset that contains all devices belonging to Zone \a _zoneName */
+    Set getByZone(const std::string& _zoneName) const;
+
+    /** Returns a subset that contains all devices belonging to Modulator \a _modulatorID */
+    Set getByModulator(const int _modulatorID) const;
+    /** Returns a subset that contains all devices belonging to Modulator \a _modulator */
+    Set getByModulator(const Modulator& _modulator) const;
+
+    /** Returns a subset that contains all devices that have the presence state of \a _present */
+    Set getByPresence(const bool _present) const;
+
+    /** Returns the device indicated by _name
+     */
+    DeviceReference getByName(const std::string& _name) const;
+    /** Returns the device indicated by \a _busid */
+    DeviceReference getByBusID(const devid_t _busid) const;
+
+    /** Returns the device indicated by \a _dsid */
+    DeviceReference getByDSID(const dsid_t _dsid)  const;
+
+    /** Returns the number of devices contained in this set */
+    int length() const;
+    /** Returns true if the set is empty */
+    bool isEmpty() const;
+
+    /** Returns a set that's combined with the set _other.
+     * Duplicates get filtered out.
+     */
+    Set combine(Set& _other) const;
+    /* Returns a set with all device in _other removed */
+    Set remove(const Set& _other) const;
+
+    /** Returns the \a _index'th device */
+    const DeviceReference& get(int _index) const;
+    /** @copydoc get */
+    const DeviceReference& operator[](const int _index) const;
+
+    /** @copydoc get */
+    DeviceReference& get(int _index);
+    /** @copydoc get */
+    DeviceReference& operator[](const int _index);
+
+    /** Returns true if the set contains \a _device */
+    bool contains(const DeviceReference& _device) const;
+    /** Returns true if the set contains \a _device */
+    bool contains(const Device& _device) const;
+
+    /** Adds the device \a _device to the set */
+    void addDevice(const DeviceReference& _device);
+    /** Adds the device \a _device to the set */
+    void addDevice(const Device& _device);
+
+    /** Removes the device \a _device from the set */
+    void removeDevice(const DeviceReference& _device);
+    /** Removes the device \a _device from the set */
+    void removeDevice(const Device& _device);
+
+    virtual void nextScene();
+    virtual void previousScene();
+
+    virtual unsigned long getPowerConsumption();
+  protected:
+    virtual std::vector<AddressableModelItem*> splitIntoAddressableItems();
+  }; // Set
+
+  
+} // namespace dss
+
+#endif // SET_H
diff --git a/core/model/zone.cpp b/core/model/zone.cpp
new file mode 100644
index 0000000..0c948eb
--- /dev/null
+++ b/core/model/zone.cpp
@@ -0,0 +1,162 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "zone.h"
+
+#include <vector>
+
+#include "core/base.h"
+#include "core/logger.h"
+#include "core/ds485const.h"
+#include "set.h"
+#include "device.h"
+#include "apartment.h"
+#include "modulator.h"
+
+namespace dss {
+
+  //================================================== Zone
+
+  Zone::~Zone() {
+    scrubVector(m_Groups);
+    // we don't own our modulators
+    m_Modulators.clear();
+  } // dtor
+
+  Set Zone::getDevices() const {
+    return Set(m_Devices);
+  } // getDevices
+
+  void Zone::addDevice(DeviceReference& _device) {
+    const Device& dev = _device.getDevice();
+    int oldZoneID = dev.getZoneID();
+    if((oldZoneID != -1) && (oldZoneID != 0)) {
+      try {
+        Zone& oldZone = dev.getApartment().getZone(oldZoneID);
+        oldZone.removeDevice(_device);
+      } catch(std::runtime_error&) {
+      }
+    }
+    if(!contains(m_Devices, _device)) {
+      m_Devices.push_back(_device);
+    } else {
+      // don't warn about multiple additions to zone 0
+      if(m_ZoneID != 0) {
+        Logger::getInstance()->log("Zone::addDevice: DUPLICATE DEVICE Detected Zone: " + intToString(m_ZoneID) + " device: " + _device.getDSID().toString(), lsWarning);
+      }
+    }
+    _device.getDevice().setZoneID(m_ZoneID);
+  } // addDevice
+
+  void Zone::addGroup(Group* _group) {
+    if(_group->getZoneID() != m_ZoneID) {
+      throw std::runtime_error("Zone::addGroup: ZoneID of _group does not match own");
+    }
+    m_Groups.push_back(_group);
+  } // addGroup
+
+  void Zone::removeGroup(UserGroup* _group) {
+    std::vector<Group*>::iterator it = find(m_Groups.begin(), m_Groups.end(), _group);
+    if(it != m_Groups.end()) {
+      m_Groups.erase(it);
+    }
+  } // removeGroup
+
+  void Zone::removeDevice(const DeviceReference& _device) {
+    DeviceIterator pos = find(m_Devices.begin(), m_Devices.end(), _device);
+    if(pos != m_Devices.end()) {
+      m_Devices.erase(pos);
+    }
+  } // removeDevice
+
+  Group* Zone::getGroup(const std::string& _name) const {
+    for(std::vector<Group*>::const_iterator ipGroup = m_Groups.begin(), e = m_Groups.end();
+        ipGroup != e; ++ipGroup)
+    {
+        if((*ipGroup)->getName() == _name) {
+          return *ipGroup;
+        }
+    }
+    return NULL;
+  } // getGroup
+
+  Group* Zone::getGroup(const int _id) const {
+    for(std::vector<Group*>::const_iterator ipGroup = m_Groups.begin(), e = m_Groups.end();
+        ipGroup != e; ++ipGroup)
+    {
+        if((*ipGroup)->getID() == _id) {
+          return *ipGroup;
+        }
+    }
+    return NULL;
+  } // getGroup
+
+  int Zone::getID() const {
+    return m_ZoneID;
+  } // getID
+
+  void Zone::setZoneID(const int _value) {
+    m_ZoneID = _value;
+  } // setZoneID
+
+  void Zone::addToModulator(const Modulator& _modulator) {
+    // make sure the zone is connected to the modulator
+    if(find(m_Modulators.begin(), m_Modulators.end(), &_modulator) == m_Modulators.end()) {
+      m_Modulators.push_back(&_modulator);
+    }
+  } // addToModulator
+
+  void Zone::removeFromModulator(const Modulator& _modulator) {
+    m_Modulators.erase(find(m_Modulators.begin(), m_Modulators.end(), &_modulator));
+  } // removeFromModulator
+
+  std::vector<int> Zone::getModulators() const {
+    std::vector<int> result;
+    for(std::vector<const Modulator*>::const_iterator iModulator = m_Modulators.begin(), e = m_Modulators.end();
+        iModulator != e; ++iModulator) {
+      result.push_back((*iModulator)->getBusID());
+    }
+    return result;
+  } // getModulators
+
+  bool Zone::registeredOnModulator(const Modulator& _modulator) const {
+    return find(m_Modulators.begin(), m_Modulators.end(), &_modulator) != m_Modulators.end();
+  } // registeredOnModulator
+
+  unsigned long Zone::getPowerConsumption() {
+    return getDevices().getPowerConsumption();
+  } // getPowerConsumption
+
+  void Zone::nextScene() {
+    getGroup(GroupIDBroadcast)->nextScene();
+  } // nextScene
+
+  void Zone::previousScene() {
+    getGroup(GroupIDBroadcast)->previousScene();
+  } // previousScene
+
+  std::vector<AddressableModelItem*> Zone::splitIntoAddressableItems() {
+    std::vector<AddressableModelItem*> result;
+    result.push_back(getGroup(GroupIDBroadcast));
+    return result;
+  } // splitIntoAddressableItems
+  
+} // namespace dss
diff --git a/core/model/zone.h b/core/model/zone.h
new file mode 100644
index 0000000..916f131
--- /dev/null
+++ b/core/model/zone.h
@@ -0,0 +1,116 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 ZONE_H
+#define ZONE_H
+
+#include <vector>
+
+#include <boost/noncopyable.hpp>
+
+#include "modeltypes.h"
+#include "devicecontainer.h"
+#include "nonaddressablemodelitem.h"
+#include "physicalmodelitem.h"
+
+namespace dss {
+  class Modulator;
+  class Group;
+  class UserGroup;
+  class Set;
+  class DeviceReference;
+ 
+    /** Represents a Zone.
+   * A Zone houses multiple devices. It can span over multiple modulators.
+   */
+  class Zone : public DeviceContainer,
+               public NonAddressableModelItem,
+               public PhysicalModelItem,
+               public boost::noncopyable {
+  private:
+    int m_ZoneID;
+    DeviceVector m_Devices;
+    std::vector<const Modulator*> m_Modulators;
+    std::vector<Group*> m_Groups;
+    int m_FirstZoneOnModulator;
+  public:
+    Zone(const int _id)
+    : m_ZoneID(_id),
+          m_FirstZoneOnModulator(-1)
+    {}
+    virtual ~Zone();
+    virtual Set getDevices() const;
+
+    /** Adds the Zone to a modulator. */
+    void addToModulator(const Modulator& _modulator);
+    /** Removes the Zone from a modulator. */
+    void removeFromModulator(const Modulator& _modulator);
+
+    /** Adds a device to the zone.
+     * This will permanently add the device to the zone.
+     */
+    void addDevice(DeviceReference& _device);
+
+    /** Removes a device from the zone.
+     * This will permanently remove the device from the zone.
+     */
+    void removeDevice(const DeviceReference& _device);
+
+    /** Returns the group with the name \a _name */
+    Group* getGroup(const std::string& _name) const;
+    /** Returns the group with the id \a _id */
+    Group* getGroup(const int _id) const;
+
+    /** Adds a group to the zone */
+    void addGroup(Group* _group);
+    /** Removes a group from the zone */
+    void removeGroup(UserGroup* _group);
+
+    /** Returns the zones id */
+    int getID() const;
+    /** Sets the zones id */
+    void setZoneID(const int _value);
+
+    /** Returns the ID of the modulator the zone is the first
+      * zone on.
+      * @return The modulator id, or -1
+      */
+    int getFirstZoneOnModulator() { return m_FirstZoneOnModulator; }
+    void setFirstZoneOnModulator(const int _value) { m_FirstZoneOnModulator = _value; }
+
+    /** Returns a list of the modulators the zone is registered with. */
+    std::vector<int> getModulators() const;
+    bool registeredOnModulator(const Modulator& _modulator) const;
+
+    virtual void nextScene();
+    virtual void previousScene();
+
+    virtual unsigned long getPowerConsumption();
+    /** Returns a vector of groups present on the zone. */
+    std::vector<Group*> getGroups() { return m_Groups; }
+  protected:
+    virtual std::vector<AddressableModelItem*> splitIntoAddressableItems();
+  }; // Zone
+
+
+} // namespace dss
+
+#endif // ZONE_H
diff --git a/core/scripting/modeljs.cpp b/core/scripting/modeljs.cpp
index 0707d13..24b8c12 100644
--- a/core/scripting/modeljs.cpp
+++ b/core/scripting/modeljs.cpp
@@ -28,6 +28,11 @@
 #include "core/logger.h"
 #include "core/propertysystem.h"
 #include "core/DS485Interface.h"
+#include "core/model/device.h"
+#include "core/model/devicereference.h"
+#include "core/model/apartment.h"
+#include "core/model/set.h"
+
 
 namespace dss {
   const std::string ModelScriptcontextExtensionName = "modelextension";
@@ -413,9 +418,9 @@ namespace dss {
     ScriptContext* ctx = static_cast<ScriptContext*>(JS_GetContextPrivate(cx));
 
     ScriptObject self(obj, *ctx);
-    if(self.is("set") || self.is("device")) {
-      IDeviceInterface* intf = static_cast<IDeviceInterface*>(JS_GetPrivate(cx, obj));
-      intf->enable();
+    if(self.is("device")) {
+      DeviceReference* dev = static_cast<DeviceReference*>(JS_GetPrivate(cx, obj));
+      dev->enable();
       *rval = INT_TO_JSVAL(0);
       return JS_TRUE;
     }
@@ -426,9 +431,9 @@ namespace dss {
     ScriptContext* ctx = static_cast<ScriptContext*>(JS_GetContextPrivate(cx));
 
     ScriptObject self(obj, *ctx);
-    if(self.is("set") || self.is("device")) {
-      IDeviceInterface* intf = static_cast<IDeviceInterface*>(JS_GetPrivate(cx, obj));
-      intf->disable();
+    if(self.is("device")) {
+      DeviceReference* dev = static_cast<DeviceReference*>(JS_GetPrivate(cx, obj));
+      dev->disable();
       *rval = INT_TO_JSVAL(0);
       return JS_TRUE;
     }
@@ -441,12 +446,7 @@ namespace dss {
     ScriptObject self(obj, *ctx);
     if(self.is("set") || self.is("device")) {
       IDeviceInterface* intf = static_cast<IDeviceInterface*>(JS_GetPrivate(cx, obj));
-      if(argc == 0) {
-        intf->increaseValue();
-      } else if(argc >= 1) {
-        int parameterNr = ctx->convertTo<int>(argv[0]);
-        intf->increaseValue(parameterNr);
-      }
+      intf->increaseValue();
       *rval = INT_TO_JSVAL(0);
       return JS_TRUE;
     }
@@ -459,12 +459,7 @@ namespace dss {
     ScriptObject self(obj, *ctx);
     if(self.is("set") || self.is("device")) {
       IDeviceInterface* intf = static_cast<IDeviceInterface*>(JS_GetPrivate(cx, obj));
-      if(argc == 0) {
-        intf->decreaseValue();
-      } else if(argc >= 1) {
-        int parameterNr = ctx->convertTo<int>(argv[0]);
-        intf->decreaseValue(parameterNr);
-      }
+      intf->decreaseValue();
       *rval = INT_TO_JSVAL(0);
       return JS_TRUE;
     }
@@ -478,11 +473,8 @@ namespace dss {
     if(self.is("set") || self.is("device")) {
       IDeviceInterface* intf = static_cast<IDeviceInterface*>(JS_GetPrivate(cx, obj));
       bool up = ctx->convertTo<bool>(argv[0]);
-      if(argc == 1) {
+      if(argc >= 1) {
         intf->startDim(up);
-      } else if(argc >= 2) {
-        int parameterNr = ctx->convertTo<int>(argv[1]);
-        intf->startDim(up, parameterNr);
       }
       *rval = INT_TO_JSVAL(0);
       return JS_TRUE;
@@ -496,12 +488,7 @@ namespace dss {
     ScriptObject self(obj, *ctx);
     if(self.is("set") || self.is("device")) {
       IDeviceInterface* intf = static_cast<IDeviceInterface*>(JS_GetPrivate(cx, obj));
-      if(argc == 0) {
-        intf->endDim();
-      } else if(argc >= 1) {
-        int parameterNr = ctx->convertTo<int>(argv[0]);
-        intf->endDim(parameterNr);
-      }
+      intf->endDim();
       *rval = INT_TO_JSVAL(0);
       return JS_TRUE;
     }
@@ -514,12 +501,9 @@ namespace dss {
     ScriptObject self(obj, *ctx);
     if(self.is("set") || self.is("device")) {
       IDeviceInterface* intf = static_cast<IDeviceInterface*>(JS_GetPrivate(cx, obj));
-      double value = ctx->convertTo<double>(argv[0]);
-      if(argc == 1) {
+      if(argc >= 1) {
+        double value = ctx->convertTo<double>(argv[0]);
         intf->setValue(value);
-      } else if(argc >= 2) {
-        int parameterNr = ctx->convertTo<int>(argv[1]);
-        intf->setValue(value, parameterNr);
       }
       *rval = INT_TO_JSVAL(0);
       return JS_TRUE;
@@ -754,7 +738,7 @@ namespace dss {
   };
 
   JSObject* ModelScriptContextExtension::createJSDevice(ScriptContext& _ctx, Device& _dev) {
-    DeviceReference ref(_dev.getDSID(), m_Apartment);
+    DeviceReference ref(_dev.getDSID(), &m_Apartment);
     return createJSDevice(_ctx, ref);
   } // createJSDevice
 
@@ -762,7 +746,7 @@ namespace dss {
     JSObject* result = JS_NewObject(_ctx.getJSContext(), &dev_class, NULL, NULL);
     JS_DefineFunctions(_ctx.getJSContext(), result, device_interface_methods);
     JS_DefineProperties(_ctx.getJSContext(), result, dev_properties);
-    DeviceReference* innerObj = new DeviceReference(_ref.getDSID(), _ref.getDevice().getApartment());
+    DeviceReference* innerObj = new DeviceReference(_ref.getDSID(), &_ref.getDevice().getApartment());
     // make an explicit copy
     *innerObj = _ref;
     JS_SetPrivate(_ctx.getJSContext(), result, innerObj);
diff --git a/core/scripting/modeljs.h b/core/scripting/modeljs.h
index 700da84..18e53da 100644
--- a/core/scripting/modeljs.h
+++ b/core/scripting/modeljs.h
@@ -27,12 +27,15 @@
 #include <boost/ptr_container/ptr_vector.hpp>
 
 #include "core/jshandler.h"
-#include "core/model.h"
 #include "core/event.h"
 #include "core/propertysystem.h"
 
 namespace dss {
 
+  class Set;
+  class Device;
+  class Apartment;
+
   /** This class extends a ScriptContext to contain the JS-API of the Apartment */
   class ModelScriptContextExtension : public ScriptExtension {
   private:
diff --git a/core/setbuilder.cpp b/core/setbuilder.cpp
index 713d050..3051dd1 100644
--- a/core/setbuilder.cpp
+++ b/core/setbuilder.cpp
@@ -20,12 +20,17 @@
 */
 
 #include "setbuilder.h"
-#include "base.h"
 
 #include <vector>
 #include <stdexcept>
 #include <cassert>
 
+#include "base.h"
+#include "core/model/set.h"
+#include "core/model/zone.h"
+#include "core/model/apartment.h"
+#include "core/model/group.h"
+
 using std::vector;
 
 namespace dss {
diff --git a/core/setbuilder.h b/core/setbuilder.h
index b686705..4b44388 100644
--- a/core/setbuilder.h
+++ b/core/setbuilder.h
@@ -23,12 +23,16 @@
 #ifndef SETBUILDER_H_
 #define SETBUILDER_H_
 
-#include "model.h"
-
 #include <string>
 
+#include "core/ds485types.h"
+
 namespace dss {
 
+  class Zone;
+  class Apartment;
+  class Set;
+  
   class SetBuilder {
   private:
     std::string m_SetDescription;
diff --git a/core/sim/dssim.cpp b/core/sim/dssim.cpp
index ad68199..4d814f2 100644
--- a/core/sim/dssim.cpp
+++ b/core/sim/dssim.cpp
@@ -413,7 +413,7 @@ namespace dss {
   } // loadGroups
 
   void DSModulatorSim::addDeviceToGroup(DSIDInterface* _device, int _groupID) {
-    m_DevicesOfGroupInZone[pair<const int, const int>(_device->getZoneID(), _groupID)].push_back(_device);
+    m_DevicesOfGroupInZone[std::pair<const int, const int>(_device->getZoneID(), _groupID)].push_back(_device);
     m_GroupsPerDevice[_device->getShortAddress()].push_back(_groupID);
   } // addDeviceToGroup
 
@@ -443,21 +443,21 @@ namespace dss {
   } // deviceCallScene
 
   void DSModulatorSim::groupCallScene(const int _zoneID, const int _groupID, const int _sceneID) {
-	vector<DSIDInterface*> dsids;
-	m_LastCalledSceneForZoneAndGroup[std::make_pair(_zoneID, _groupID)] = _sceneID;
-	if(_groupID == GroupIDBroadcast) {
-	  if(_zoneID == 0) {
-	    dsids = m_SimulatedDevices;
-	  } else {
-      dsids = m_Zones[_zoneID];
-	  }
-	} else {
-      pair<const int, const int> zonesGroup(_zoneID, _groupID);
+    std::vector<DSIDInterface*> dsids;
+    m_LastCalledSceneForZoneAndGroup[std::make_pair(_zoneID, _groupID)] = _sceneID;
+    if(_groupID == GroupIDBroadcast) {
+      if(_zoneID == 0) {
+        dsids = m_SimulatedDevices;
+      } else {
+        dsids = m_Zones[_zoneID];
+      }
+    } else {
+      std::pair<const int, const int> zonesGroup(_zoneID, _groupID);
       if(m_DevicesOfGroupInZone.find(zonesGroup) != m_DevicesOfGroupInZone.end()) {
         dsids = m_DevicesOfGroupInZone[zonesGroup];
       }
 	}
-    for(vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
+    for(std::vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
         iDSID != e; ++iDSID)
     {
       (*iDSID)->callScene(_sceneID);
@@ -469,10 +469,10 @@ namespace dss {
   } // deviceSaveScene
 
   void DSModulatorSim::groupSaveScene(const int _zoneID, const int _groupID, const int _sceneID) {
-    pair<const int, const int> zonesGroup(_zoneID, _groupID);
+    std::pair<const int, const int> zonesGroup(_zoneID, _groupID);
     if(m_DevicesOfGroupInZone.find(zonesGroup) != m_DevicesOfGroupInZone.end()) {
       std::vector<DSIDInterface*> dsids = m_DevicesOfGroupInZone[zonesGroup];
-      for(vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
+      for(std::vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
           iDSID != e; ++iDSID)
       {
         (*iDSID)->saveScene(_sceneID);
@@ -485,10 +485,10 @@ namespace dss {
   } // deviceUndoScene
 
   void DSModulatorSim::groupUndoScene(const int _zoneID, const int _groupID, const int _sceneID) {
-    pair<const int, const int> zonesGroup(_zoneID, _groupID);
+    std::pair<const int, const int> zonesGroup(_zoneID, _groupID);
     if(m_DevicesOfGroupInZone.find(zonesGroup) != m_DevicesOfGroupInZone.end()) {
       std::vector<DSIDInterface*> dsids = m_DevicesOfGroupInZone[zonesGroup];
-      for(vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
+      for(std::vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
           iDSID != e; ++iDSID)
       {
         (*iDSID)->undoScene(_sceneID);
@@ -497,10 +497,10 @@ namespace dss {
   } // groupUndoScene
 
   void DSModulatorSim::groupStartDim(const int _zoneID, const int _groupID, bool _up, int _parameterNr) {
-    pair<const int, const int> zonesGroup(_zoneID, _groupID);
+    std::pair<const int, const int> zonesGroup(_zoneID, _groupID);
     if(m_DevicesOfGroupInZone.find(zonesGroup) != m_DevicesOfGroupInZone.end()) {
       std::vector<DSIDInterface*> dsids = m_DevicesOfGroupInZone[zonesGroup];
-      for(vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
+      for(std::vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
           iDSID != e; ++iDSID)
       {
         (*iDSID)->startDim(_up, _parameterNr);
@@ -509,10 +509,10 @@ namespace dss {
   } // groupStartDim
 
   void DSModulatorSim::groupEndDim(const int _zoneID, const int _groupID, const int _parameterNr) {
-    pair<const int, const int> zonesGroup(_zoneID, _groupID);
+    std::pair<const int, const int> zonesGroup(_zoneID, _groupID);
     if(m_DevicesOfGroupInZone.find(zonesGroup) != m_DevicesOfGroupInZone.end()) {
       std::vector<DSIDInterface*> dsids = m_DevicesOfGroupInZone[zonesGroup];
-      for(vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
+      for(std::vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
           iDSID != e; ++iDSID)
       {
         (*iDSID)->endDim(_parameterNr);
@@ -521,10 +521,10 @@ namespace dss {
   } // groupEndDim
 
   void DSModulatorSim::groupDecValue(const int _zoneID, const int _groupID, const int _parameterNr) {
-    pair<const int, const int> zonesGroup(_zoneID, _groupID);
+    std::pair<const int, const int> zonesGroup(_zoneID, _groupID);
     if(m_DevicesOfGroupInZone.find(zonesGroup) != m_DevicesOfGroupInZone.end()) {
       std::vector<DSIDInterface*> dsids = m_DevicesOfGroupInZone[zonesGroup];
-      for(vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
+      for(std::vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
           iDSID != e; ++iDSID)
       {
         (*iDSID)->decreaseValue(_parameterNr);
@@ -533,10 +533,10 @@ namespace dss {
   } // groupDecValue
 
   void DSModulatorSim::groupIncValue(const int _zoneID, const int _groupID, const int _parameterNr) {
-    pair<const int, const int> zonesGroup(_zoneID, _groupID);
+    std::pair<const int, const int> zonesGroup(_zoneID, _groupID);
     if(m_DevicesOfGroupInZone.find(zonesGroup) != m_DevicesOfGroupInZone.end()) {
       std::vector<DSIDInterface*> dsids = m_DevicesOfGroupInZone[zonesGroup];
-      for(vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
+      for(std::vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
           iDSID != e; ++iDSID)
       {
         (*iDSID)->increaseValue(_parameterNr);
@@ -545,10 +545,10 @@ namespace dss {
   } // groupIncValue
 
   void DSModulatorSim::groupSetValue(const int _zoneID, const int _groupID, const int _value) {
-    pair<const int, const int> zonesGroup(_zoneID, _groupID);
+    std::pair<const int, const int> zonesGroup(_zoneID, _groupID);
     if(m_DevicesOfGroupInZone.find(zonesGroup) != m_DevicesOfGroupInZone.end()) {
       std::vector<DSIDInterface*> dsids = m_DevicesOfGroupInZone[zonesGroup];
-      for(vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
+      for(std::vector<DSIDInterface*>::iterator iDSID = dsids.begin(), e = dsids.end();
           iDSID != e; ++iDSID)
       {
         (*iDSID)->setValue(_value);
@@ -770,7 +770,7 @@ namespace dss {
                 response = createResponse(cmdFrame, cmdNr);
                 int zoneID = pd.get<uint16_t>();
                 int groupID = pd.get<uint16_t>();
-                int result = m_DevicesOfGroupInZone[pair<const int, const int>(zoneID, groupID)].size();
+                int result = m_DevicesOfGroupInZone[std::pair<const int, const int>(zoneID, groupID)].size();
                 response->getPayload().add<uint16_t>(result);
                 distributeFrame(response);
               }
@@ -781,7 +781,7 @@ namespace dss {
                 int zoneID = pd.get<uint16_t>();
                 int groupID = pd.get<uint16_t>();
                 int index = pd.get<uint16_t>();
-                int result = m_DevicesOfGroupInZone[pair<const int, const int>(zoneID, groupID)].at(index)->getShortAddress();
+                int result = m_DevicesOfGroupInZone[std::pair<const int, const int>(zoneID, groupID)].at(index)->getShortAddress();
                 response->getPayload().add<uint16_t>(result);
                 distributeFrame(response);
               }
@@ -1030,7 +1030,7 @@ namespace dss {
   } // createResponse
 
   DSIDInterface& DSModulatorSim::lookupDevice(const devid_t _shortAddress) {
-    for(vector<DSIDInterface*>::iterator ipSimDev = m_SimulatedDevices.begin(); ipSimDev != m_SimulatedDevices.end(); ++ipSimDev) {
+    for(std::vector<DSIDInterface*>::iterator ipSimDev = m_SimulatedDevices.begin(); ipSimDev != m_SimulatedDevices.end(); ++ipSimDev) {
       if((*ipSimDev)->getShortAddress() == _shortAddress)  {
         return **ipSimDev;
       }
@@ -1043,7 +1043,7 @@ namespace dss {
   } // getID
 
   DSIDInterface* DSModulatorSim::getSimulatedDevice(const dsid_t _dsid) {
-    for(vector<DSIDInterface*>::iterator iDSID = m_SimulatedDevices.begin(), e = m_SimulatedDevices.end();
+    for(std::vector<DSIDInterface*>::iterator iDSID = m_SimulatedDevices.begin(), e = m_SimulatedDevices.end();
         iDSID != e; ++iDSID)
     {
       if((*iDSID)->getDSID() == _dsid) {
diff --git a/core/sim/dssim.h b/core/sim/dssim.h
index a4b9a11..0345e21 100644
--- a/core/sim/dssim.h
+++ b/core/sim/dssim.h
@@ -24,7 +24,7 @@
 
 #include "core/ds485types.h"
 #include "core/ds485const.h"
-#include "unix/ds485.h"
+#include "core/ds485/ds485.h"
 #include "core/subsystem.h"
 
 #include <map>
diff --git a/core/structuremanipulator.cpp b/core/structuremanipulator.cpp
index 712af64..567bcab 100644
--- a/core/structuremanipulator.cpp
+++ b/core/structuremanipulator.cpp
@@ -7,8 +7,13 @@
 
 #include "structuremanipulator.h"
 
-#include "model.h"
 #include "DS485Interface.h"
+#include "mutex.h"
+#include "core/model/device.h"
+#include "core/model/apartment.h"
+#include "core/model/modulator.h"
+#include "core/model/zone.h"
+#include "core/model/set.h"
 
 #include <stdexcept>
 
@@ -36,7 +41,7 @@ namespace dss {
     }
     m_Interface.setZoneID(targetModulator.getBusID(), _device.getShortAddress(), _zone.getID());
     _device.setZoneID(_zone.getID());
-    DeviceReference ref(_device, m_Apartment);
+    DeviceReference ref(_device, &m_Apartment);
     _zone.addDevice(ref);
 
     // check if we can remove the zone from the modulator
diff --git a/core/web/restful.cpp b/core/web/restful.cpp
index 7f360a7..eb0b2e0 100644
--- a/core/web/restful.cpp
+++ b/core/web/restful.cpp
@@ -22,3 +22,27 @@
 */
 
 #include "restful.h"
+
+#include "core/foreach.h"
+
+namespace dss {
+
+  bool RestfulAPI::hasClass(const std::string& _name) {
+    foreach(RestfulClass& cls, m_Classes) {
+      if(cls.getName() == _name) {
+        return true;
+      }
+    }
+    return false;
+  } // hasClass
+
+  bool RestfulClass::hasMethod(const std::string& _name) {
+    foreach(RestfulMethod& method, m_Methods) {
+      if(method.getName() == _name) {
+        return true;
+      }
+    }
+    return false;
+  } // hasMethod
+  
+} // namespace dss
diff --git a/core/web/restful.h b/core/web/restful.h
index b1ba65f..9f5b149 100644
--- a/core/web/restful.h
+++ b/core/web/restful.h
@@ -139,6 +139,7 @@ namespace dss {
     const boost::ptr_vector<RestfulMethod>& getStaticMethods() const { return m_StaticMethods; }
     const std::string& getDocumentationShort() const { return m_DocumentationShort; }
     const std::string& getDocumentationLong() const { return m_DocumentationLong; }
+    bool hasMethod(const std::string& _name);
   }; // RestfulClass
 
   class RestfulAPI {
@@ -154,6 +155,8 @@ namespace dss {
     }
 
     const boost::ptr_vector<RestfulClass>& getClasses() const { return m_Classes; }
+
+    bool hasClass(const std::string& _name);
   }; // RestfulAPI
 
   class RestfulParameterType {
@@ -193,8 +196,47 @@ namespace dss {
   }; // RestfulParameterTypeInteger
 
   class RestfulRequest {
+  public:
+    RestfulRequest(const std::string& _request, const HashMapConstStringString& _parameter)
+    : m_Parameter(_parameter)
+    {
+      splitIntoMethodAndClass(_request);
+    }
+
+    const std::string& getClass() const {
+      return m_Class;
+    } // getClass
+
+    const std::string& getMethod() const {
+      return m_Method;
+    } // getMethod
+
+    const std::string& getParameter(const std::string& _name) const {
+      HashMapConstStringString::const_iterator iEntry = m_Parameter.find(_name);
+      if(iEntry != m_Parameter.end()) {
+        return iEntry->second;
+      } else {
+        return "";
+      }
+    } // getParameter
   private:
-  }; // RestfulRequest
+    void splitIntoMethodAndClass(const std::string& _request) {
+      size_t pos = _request.find('/');
+      m_Class = _request.substr(0, pos);
+      m_Method = _request.substr(pos+1, std::string::npos);
+    } // splitIntoMethodAndClass
+  private:
+    std::string m_Class;
+    std::string m_Method;
+    HashMapConstStringString m_Parameter;
+  };
+
+  class Session;
+  
+  class RestfulRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session) = 0;
+  };
 
 } // namespace dss
 
diff --git a/core/web/webrequests.cpp b/core/web/webrequests.cpp
new file mode 100644
index 0000000..496b6f2
--- /dev/null
+++ b/core/web/webrequests.cpp
@@ -0,0 +1,1409 @@
+/*
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "webrequests.h"
+
+#include <sstream>
+#include <vector>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem.hpp>
+
+#include "core/event.h"
+#include "core/ds485/ds485proxy.h"
+#include "core/sim/dssim.h"
+#include "core/propertysystem.h"
+#include "core/foreach.h"
+
+#include "core/model/apartment.h"
+#include "core/model/set.h"
+#include "core/model/device.h"
+#include "core/model/devicereference.h"
+#include "core/model/zone.h"
+#include "core/model/group.h"
+#include "core/model/modulator.h"
+#include "core/model/modelevent.h"
+
+#include "core/metering/metering.h"
+#include "core/metering/series.h"
+#include "core/metering/seriespersistence.h"
+#include "core/setbuilder.h"
+#include "core/structuremanipulator.h"
+
+
+namespace dss {
+
+  //=========================================== Globals
+
+  std::string ToJSONValue(const int& _value) {
+    return intToString(_value);
+  } // toJSONValue(int)
+
+  std::string ToJSONValue(const double& _value) {
+    return doubleToString(_value);
+  } // toJSONValue(double)
+
+  std::string ToJSONValue(const bool& _value) {
+    if(_value) {
+      return "true";
+    } else {
+      return "false";
+    }
+  } // toJSONValue(bool)
+
+  std::string ToJSONValue(const std::string& _value) {
+    return std::string("\"") + _value + '"';
+  } // toJSONValue(const std::string&)
+
+  std::string ToJSONValue(const char* _value) {
+    return ToJSONValue(std::string(_value));
+  } // toJSONValue(const char*)
+
+  std::string ResultToJSON(const bool _ok, const std::string& _message = "") {
+    std::ostringstream sstream;
+    sstream << "{ " << ToJSONValue("ok") << ":" << ToJSONValue(_ok);
+    if(!_message.empty()) {
+      sstream << ", " << ToJSONValue("message") << ":" << ToJSONValue(_message);
+    }
+    sstream << "}";
+    if(!_ok) {
+      Logger::getInstance()->log("JSON call failed: '" + _message + "'");
+    }
+    return sstream.str();
+  } // resultToJSON
+
+  std::string JSONOk(const std::string& _innerResult = "") {
+    std::ostringstream sstream;
+    sstream << "{ " << ToJSONValue("ok") << ":" << ToJSONValue(true);
+    if(!_innerResult.empty()) {
+      sstream << ", " << ToJSONValue("result")<<  ": " << _innerResult;
+    }
+    sstream << " }";
+    return sstream.str();
+  }
+
+  std::string ToJSONValue(const DeviceReference& _device) {
+    std::ostringstream sstream;
+    sstream << "{ \"id\": \"" << _device.getDSID().toString() << "\""
+            << ", \"isSwitch\": " << ToJSONValue(_device.hasSwitch())
+            << ", \"name\": " << ToJSONValue(_device.getDevice().getName())
+            << ", \"fid\": " << ToJSONValue(_device.getDevice().getFunctionID())
+            << ", \"circuitID\":" << ToJSONValue(_device.getDevice().getModulatorID())
+            << ", \"busID\":"  << ToJSONValue(_device.getDevice().getShortAddress())
+            << ", \"isPresent\":"  << ToJSONValue(_device.getDevice().isPresent())
+            << ", \"lastDiscovered\":"  << ToJSONValue(int(_device.getDevice().getLastDiscovered().secondsSinceEpoch()))
+            << ", \"firstSeen\":"  << ToJSONValue(int(_device.getDevice().getFirstSeen().secondsSinceEpoch()))
+            << ", \"on\": " << ToJSONValue(_device.isOn()) << " }";
+    return sstream.str();
+  } // toJSONValue(DeviceReference)
+
+  std::string ToJSONValue(const Set& _set, const std::string& _arrayName) {
+    std::ostringstream sstream;
+    sstream << ToJSONValue(_arrayName) << ":[";
+    bool firstDevice = true;
+    for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
+      const DeviceReference& d = _set.get(iDevice);
+      if(firstDevice) {
+        firstDevice = false;
+      } else {
+        sstream << ",";
+      }
+      sstream << ToJSONValue(d);
+    }
+    sstream << "]";
+    return sstream.str();
+  } // toJSONValue(Set,Name)
+
+  std::string ToJSONValue(const Group& _group) {
+    std::ostringstream sstream;
+    sstream << "{ " << ToJSONValue("id") << ": " << ToJSONValue(_group.getID()) << ",";
+    sstream << ToJSONValue("name") << ": " << ToJSONValue(_group.getName()) << ", ";
+    sstream << ToJSONValue("isPresent") << ": " << ToJSONValue(_group.isPresent()) << ", ";
+    sstream << ToJSONValue("devices") << ": [";
+    Set devices = _group.getDevices();
+    bool first = true;
+    for(int iDevice = 0; iDevice < devices.length(); iDevice++) {
+      if(!first) {
+        sstream << " , ";
+      } else {
+        first = false;
+      }
+      sstream << " { " << ToJSONValue("id") << ": " << ToJSONValue(devices[iDevice].getDSID().toString()) << " }";
+    }
+    sstream << "]} ";
+    return sstream.str();
+  } // toJSONValue(Group)
+
+  std::string ToJSONValue(Zone& _zone, bool _includeDevices = true) {
+    std::ostringstream sstream;
+    sstream << "{ \"id\": " << _zone.getID() << ",";
+    std::string name = _zone.getName();
+    if(name.size() == 0) {
+      name = std::string("Zone ") + intToString(_zone.getID());
+    }
+    sstream << ToJSONValue("name") << ": " << ToJSONValue(name) << ", ";
+    sstream << ToJSONValue("isPresent") << ": " << ToJSONValue(_zone.isPresent());
+    if(_zone.getFirstZoneOnModulator() != -1) {
+      sstream << ", " << ToJSONValue("firstZoneOnModulator")
+              << ": " << ToJSONValue(_zone.getFirstZoneOnModulator());
+    }
+
+    if(_includeDevices) {
+      sstream << ", ";
+      Set devices = _zone.getDevices();
+      sstream << ToJSONValue(devices, "devices");
+      sstream << "," << ToJSONValue("groups") << ": [";
+      bool first = true;
+      foreach(Group* pGroup, _zone.getGroups()) {
+        if(!first) {
+          sstream << ",";
+        }
+        first = false;
+        sstream  << ToJSONValue(*pGroup);
+      }
+      sstream << "] ";
+    }
+
+    sstream << "} ";
+    return sstream.str();
+  } // toJSONValue(Zone)
+
+  std::string ToJSONValue(Apartment& _apartment) {
+    std::ostringstream sstream;
+    sstream << "{ \"apartment\": { \"zones\": [";
+    vector<Zone*>& zones = _apartment.getZones();
+    bool first = true;
+    for(vector<Zone*>::iterator ipZone = zones.begin(), e = zones.end();
+        ipZone != e; ++ipZone)
+    {
+      Zone* pZone = *ipZone;
+      if(!first) {
+        sstream << ", ";
+      } else {
+        first = false;
+      }
+      sstream << ToJSONValue(*pZone);
+    }
+    sstream << "]} }";
+    return sstream.str();
+  } // toJSONValue(Apartment)
+
+  Set GetUnassignedDevices() {
+    Apartment& apt = DSS::getInstance()->getApartment();
+    Set devices = apt.getZone(0).getDevices();
+
+    vector<Zone*>& zones = apt.getZones();
+    for(vector<Zone*>::iterator ipZone = zones.begin(), e = zones.end();
+        ipZone != e; ++ipZone)
+    {
+      Zone* pZone = *ipZone;
+      if(pZone->getID() == 0) {
+        // zone 0 holds all devices, so we're going to skip it
+        continue;
+      }
+
+      devices = devices.remove(pZone->getDevices());
+    }
+
+    return devices;
+  } // getUnassignedDevices
+
+  template<class t>
+  std::string ToJSONArray(const vector<t>& _v);
+
+  template<>
+  std::string ToJSONArray(const vector<int>& _v) {
+    std::ostringstream arr;
+    arr << "[";
+    bool first = true;
+    vector<int>::const_iterator iV;
+    vector<int>::const_iterator e;
+    for(iV = _v.begin(), e = _v.end();
+        iV != e; ++iV)
+    {
+      if(!first) {
+        arr << ",";
+      }
+      arr << ToJSONValue(*iV);
+      first = false;
+    }
+    arr << "]";
+    return arr.str();
+  } // toJSONArray<int>
+  
+  //=========================================== DeviceInterfaceRequestHandler
+
+  std::string DeviceInterfaceRequestHandler::handleDeviceInterfaceRequest(const RestfulRequest& _request, IDeviceInterface* _interface) {
+    bool ok = true;
+    std::string errorString;
+    assert(_interface != NULL);
+    if(_request.getMethod() == "turnOn") {
+      _interface->turnOn();
+    } else if(_request.getMethod() == "turnOff") {
+      _interface->turnOff();
+    } else if(_request.getMethod() == "increaseValue") {
+      _interface->increaseValue();
+    } else if(_request.getMethod() == "decreaseValue") {
+      _interface->decreaseValue();
+    } else if(_request.getMethod() == "startDim") {
+      std::string direction = _request.getParameter("direction");
+      if(direction == "up") {
+        _interface->startDim(true);
+      } else {
+        _interface->startDim(false);
+      }
+    } else if(_request.getMethod() == "endDim") {
+      _interface->endDim();
+    } else if(_request.getMethod() == "setValue") {
+      std::string valueStr = _request.getParameter("value");
+      int value = strToIntDef(valueStr, -1);
+      if(value == -1) {
+        errorString = "invalid or missing parameter value: '" + valueStr + "'";
+        ok = false;
+      } else {
+        _interface->setValue(value);
+      }
+    } else if(_request.getMethod() == "callScene") {
+      std::string sceneStr = _request.getParameter("sceneNr");
+      int sceneID = strToIntDef(sceneStr, -1);
+      if(sceneID != -1) {
+        _interface->callScene(sceneID);
+      } else {
+        errorString = "invalid sceneNr: '" + sceneStr + "'";
+        ok = false;
+      }
+    } else if(_request.getMethod() == "saveScene") {
+      std::string sceneStr = _request.getParameter("sceneNr");
+      int sceneID = strToIntDef(sceneStr, -1);
+      if(sceneID != -1) {
+        _interface->saveScene(sceneID);
+      } else {
+        errorString = "invalid sceneNr: '" + sceneStr + "'";
+        ok = false;
+      }
+    } else if(_request.getMethod() == "undoScene") {
+      std::string sceneStr = _request.getParameter("sceneNr");
+      int sceneID = strToIntDef(sceneStr, -1);
+      if(sceneID != -1) {
+        _interface->undoScene(sceneID);
+      } else {
+        errorString = "invalid sceneNr: '" + sceneStr + "'";
+        ok = false;
+      }
+    } else if(_request.getMethod() == "getConsumption") {
+      return "{ " + ToJSONValue("consumption") + ": " +  uintToString(_interface->getPowerConsumption()) +"}";
+    }
+    return ResultToJSON(ok, errorString);
+  } // handleRequest
+
+  bool DeviceInterfaceRequestHandler::isDeviceInterfaceCall(const RestfulRequest& _request) {
+    return endsWith(_request.getMethod(), "turnOn")
+        || endsWith(_request.getMethod(), "turnOff")
+        || endsWith(_request.getMethod(), "increaseValue")
+        || endsWith(_request.getMethod(), "decreaseValue")
+        || endsWith(_request.getMethod(), "startDim")
+        || endsWith(_request.getMethod(), "endDim")
+        || endsWith(_request.getMethod(), "setValue")
+        || endsWith(_request.getMethod(), "callScene")
+        || endsWith(_request.getMethod(), "saveScene")
+        || endsWith(_request.getMethod(), "undoScene")
+        || endsWith(_request.getMethod(), "getConsumption");
+  } // isDeviceInterfaceCall
+
+
+  //=========================================== ApartmentRequestHandler
+  
+  std::string ApartmentRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    bool ok = true;
+    std::string errorMessage;
+    if(_request.getMethod() == "getConsumption") {
+      int accumulatedConsumption = 0;
+      foreach(Modulator* pModulator, getDSS().getApartment().getModulators()) {
+        accumulatedConsumption += pModulator->getPowerConsumption();
+      }
+      return "{ " + ToJSONValue("consumption") + ": " +  uintToString(accumulatedConsumption) +"}";
+    } else if(isDeviceInterfaceCall(_request)) {
+      IDeviceInterface* interface = NULL;
+      std::string groupName = _request.getParameter("groupName");
+      std::string groupIDString = _request.getParameter("groupID");
+      if(!groupName.empty()) {
+        try {
+          Group& grp = getDSS().getApartment().getGroup(groupName);
+          interface = &grp;
+        } catch(std::runtime_error& e) {
+          errorMessage = "Could not find group with name '" + groupName + "'";
+          ok = false;
+        }
+      } else if(!groupIDString.empty()) {
+        try {
+          int groupID = strToIntDef(groupIDString, -1);
+          if(groupID != -1) {
+            Group& grp = getDSS().getApartment().getGroup(groupID);
+            interface = &grp;
+          } else {
+            errorMessage = "Could not parse group id '" + groupIDString + "'";
+            ok = false;
+          }
+        } catch(std::runtime_error& e) {
+          errorMessage = "Could not find group with ID '" + groupIDString + "'";
+          ok = false;
+        }
+      }
+      if(ok) {
+        if(interface == NULL) {
+          interface = &getDSS().getApartment().getGroup(GroupIDBroadcast);
+        }
+        return handleDeviceInterfaceRequest(_request, interface);
+      } else {
+        std::ostringstream sstream;
+        sstream << "{ ok: " << ToJSONValue(ok) << ", message: " << ToJSONValue(errorMessage) << " }";
+        return sstream.str();
+      }
+    } else {
+      std::string result;
+      if(_request.getMethod() == "getStructure") {
+        result = ToJSONValue(getDSS().getApartment());
+      } else if(_request.getMethod() == "getDevices") {
+        Set devices;
+        if(_request.getParameter("unassigned").empty()) {
+          devices = getDSS().getApartment().getDevices();
+        } else {
+          devices = GetUnassignedDevices();
+        }
+
+        result = "{" + ToJSONValue(devices, "devices") + "}";
+/* TODO: re-enable
+      } else if(_request.getMethod() == "login") {
+        int token = m_LastSessionID;
+        m_Sessions[token] = Session(token);
+        return "{" + ToJSONValue("token") + ": " + ToJSONValue(token) + "}";
+*/
+      } else if(_request.getMethod() == "getCircuits") {
+        std::ostringstream sstream;
+        sstream << "{ " << ToJSONValue("circuits") << ": [";
+        bool first = true;
+        vector<Modulator*>& modulators = getDSS().getApartment().getModulators();
+        foreach(Modulator* modulator, modulators) {
+          if(!first) {
+            sstream << ",";
+          }
+          first = false;
+          sstream << "{ " << ToJSONValue("name") << ": " << ToJSONValue(modulator->getName());
+          sstream << ", " << ToJSONValue("dsid") << ": " << ToJSONValue(modulator->getDSID().toString());
+          sstream << ", " << ToJSONValue("busid") << ": " << ToJSONValue(modulator->getBusID());
+          sstream << ", " << ToJSONValue("hwVersion") << ": " << ToJSONValue(modulator->getHardwareVersion());
+          sstream << ", " << ToJSONValue("swVersion") << ": " << ToJSONValue(modulator->getSoftwareVersion());
+          sstream << ", " << ToJSONValue("hwName") << ": " << ToJSONValue(modulator->getHardwareName());
+          sstream << ", " << ToJSONValue("deviceType") << ": " << ToJSONValue(modulator->getDeviceType());
+          sstream << ", " << ToJSONValue("isPresent") << ": " << ToJSONValue(modulator->isPresent());
+          sstream << "}";
+        }
+        sstream << "]}";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "getName") {
+        std::ostringstream sstream;
+        sstream << "{" << ToJSONValue("name") << ":" << ToJSONValue(getDSS().getApartment().getName()) << "}";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "setName") {
+        getDSS().getApartment().setName(_request.getParameter("newName"));
+        result = ResultToJSON(true);
+      } else if(_request.getMethod() == "rescan") {
+        std::vector<Modulator*> mods = getDSS().getApartment().getModulators();
+        foreach(Modulator* pModulator, mods) {
+          pModulator->setIsValid(false);
+        }
+        result = ResultToJSON(true);
+      } else {
+        throw std::runtime_error("Unhandled function");
+      }
+      return result;
+    }
+  } // handleApartmentCall
+
+
+  //=========================================== ZoneRequestHandler
+
+  std::string ZoneRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    bool ok = true;
+    std::string errorMessage;
+    std::string zoneName = _request.getParameter("name");
+    std::string zoneIDString = _request.getParameter("id");
+    Zone* pZone = NULL;
+    if(!zoneIDString.empty()) {
+      int zoneID = strToIntDef(zoneIDString, -1);
+      if(zoneID != -1) {
+        try {
+          Zone& zone = getDSS().getApartment().getZone(zoneID);
+          pZone = &zone;
+        } catch(std::runtime_error& e) {
+          ok = false;
+          errorMessage = "Could not find zone with id '" + zoneIDString + "'";
+        }
+      } else {
+        ok = false;
+        errorMessage = "Could not parse id '" + zoneIDString + "'";
+      }
+    } else if(!zoneName.empty()) {
+      try {
+        Zone& zone = getDSS().getApartment().getZone(zoneName);
+        pZone = &zone;
+      } catch(std::runtime_error& e) {
+        ok = false;
+        errorMessage = "Could not find zone named '" + zoneName + "'";
+      }
+    } else {
+      ok = false;
+      errorMessage = "Need parameter name or id to identify zone";
+    }
+    if(ok) {
+      Group* pGroup = NULL;
+      std::string groupName = _request.getParameter("groupName");
+      std::string groupIDString = _request.getParameter("groupID");
+      if(!groupName.empty()) {
+        try {
+          pGroup = pZone->getGroup(groupName);
+          if(pGroup == NULL) {
+            // TODO: this might better be done by the zone
+            throw std::runtime_error("dummy");
+          }
+        } catch(std::runtime_error& e) {
+          errorMessage = "Could not find group with name '" + groupName + "'";
+          ok = false;
+        }
+      } else if(!groupIDString.empty()) {
+        try {
+          int groupID = strToIntDef(groupIDString, -1);
+          if(groupID != -1) {
+            pGroup = pZone->getGroup(groupID);
+            if(pGroup == NULL) {
+              // TODO: this might better be done by the zone
+              throw std::runtime_error("dummy");
+            }
+          } else {
+            errorMessage = "Could not parse group id '" + groupIDString + "'";
+            ok = false;
+          }
+        } catch(std::runtime_error& e) {
+          errorMessage = "Could not find group with ID '" + groupIDString + "'";
+          ok = false;
+        }
+      }
+      if(ok) {
+        if(isDeviceInterfaceCall(_request)) {
+          IDeviceInterface* interface = NULL;
+          if(pGroup != NULL) {
+            interface = pGroup;
+          }
+          if(ok) {
+            if(interface == NULL) {
+              interface = pZone;
+            }
+            return handleDeviceInterfaceRequest(_request, interface);
+          }
+        } else if(_request.getMethod() == "getLastCalledScene") {
+          int lastScene = 0;
+          if(pGroup != NULL) {
+            lastScene = pGroup->getLastCalledScene();
+          } else if(pZone != NULL) {
+            lastScene = pZone->getGroup(0)->getLastCalledScene();
+          } else {
+            // should never reach here because ok, would be false
+            assert(false);
+          }
+          std::ostringstream sstream;
+          sstream << "{" << ToJSONValue("scene") << ":" << ToJSONValue(lastScene) << "}";
+          return JSONOk(sstream.str());
+        } else if(_request.getMethod() == "getName") {
+          std::ostringstream sstream;
+          sstream << "{" << ToJSONValue("name") << ":" << ToJSONValue(pZone->getName()) << "}";
+          return JSONOk(sstream.str());
+        } else if(_request.getMethod() == "setName") {
+          pZone->setName(_request.getParameter("newName"));
+          return ResultToJSON(true);
+        } else {
+          throw std::runtime_error("Unhandled function");
+        }
+      }
+    }
+    if(!ok) {
+      return ResultToJSON(ok, errorMessage);
+    } else {
+      return "";
+    }
+  } // handleRequest
+
+
+  //=========================================== DeviceRequestHandler
+
+  std::string DeviceRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    bool ok = true;
+    std::string errorMessage;
+    std::string deviceName = _request.getParameter("name");
+    std::string deviceDSIDString = _request.getParameter("dsid");
+    Device* pDevice = NULL;
+    if(!deviceDSIDString.empty()) {
+      dsid_t deviceDSID = dsid_t::fromString(deviceDSIDString);
+      if(!(deviceDSID == NullDSID)) {
+        try {
+          Device& device = getDSS().getApartment().getDeviceByDSID(deviceDSID);
+          pDevice = &device;
+        } catch(std::runtime_error& e) {
+          ok = false;
+          errorMessage = "Could not find device with dsid '" + deviceDSIDString + "'";
+        }
+      } else {
+        ok = false;
+        errorMessage = "Could not parse dsid '" + deviceDSIDString + "'";
+      }
+    } else if(!deviceName.empty()) {
+      try {
+        Device& device = getDSS().getApartment().getDeviceByName(deviceName);
+        pDevice = &device;
+      } catch(std::runtime_error&  e) {
+        ok = false;
+        errorMessage = "Could not find device named '" + deviceName + "'";
+      }
+    } else {
+      ok = false;
+      errorMessage = "Need parameter name or dsid to identify device";
+    }
+    if(ok) {
+      if(isDeviceInterfaceCall(_request)) {
+        return handleDeviceInterfaceRequest(_request, pDevice);
+      } else if(_request.getMethod() == "getGroups") {
+        int numGroups = pDevice->getGroupsCount();
+        std::ostringstream sstream;
+        sstream << "{ " << ToJSONValue("groups") << ": [";
+        bool first = true;
+        for(int iGroup = 0; iGroup < numGroups; iGroup++) {
+          if(!first) {
+            sstream << ", ";
+          }
+          first = false;
+          try {
+            Group& group = pDevice->getGroupByIndex(iGroup);
+            sstream << "{ " << ToJSONValue("id") << ":" << group.getID();
+            if(!group.getName().empty()) {
+              sstream << ", " << ToJSONValue("name") << ":" << ToJSONValue(group.getName());
+            }
+          } catch(std::runtime_error&) {
+            Logger::getInstance()->log("DeviceRequestHandler: Group only present at device level");
+          }
+          sstream << "}";
+        }
+        sstream << "]}";
+        return sstream.str();
+      } else if(_request.getMethod() == "getState") {
+        std::ostringstream sstream;
+        sstream << "{ " << ToJSONValue("isOn") << ":" << ToJSONValue(pDevice->isOn()) << " }";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "getName") {
+        std::ostringstream sstream;
+        sstream << "{ " << ToJSONValue("name") << ":" << ToJSONValue(pDevice->getName()) << " }";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "setName") {
+        pDevice->setName(_request.getParameter("newName"));
+        return ResultToJSON(true);
+      } else if(_request.getMethod() == "enable") {
+        pDevice->enable();
+        return ResultToJSON(true);
+      } else if(_request.getMethod() == "disable") {
+        pDevice->disable();
+        return ResultToJSON(true);
+      } else if(_request.getMethod() == "setRawValue") {
+        int value = strToIntDef(_request.getParameter("value"), -1);
+        if(value == -1) {
+          return ResultToJSON(false, "Invalid or missing parameter 'value'");
+        }
+        int parameterID = strToIntDef(_request.getParameter("parameterID"), -1);
+        if(parameterID == -1) {
+          return ResultToJSON(false, "Invalid or missing parameter 'parameterID'");
+        }
+        int size = strToIntDef(_request.getParameter("size"), -1);
+        if(size == -1) {
+          return ResultToJSON(false, "Invalid or missing parameter 'size'");
+        }
+
+        pDevice->setRawValue(value, parameterID, size);
+        return JSONOk();
+      } else {
+        throw std::runtime_error("Unhandled function");
+      }
+    } else {
+      return ResultToJSON(ok, errorMessage);
+    }
+  } // handleRequest
+
+
+  //=========================================== CircuitRequestHandler
+
+  std::string CircuitRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    std::string idString = _request.getParameter("id");
+    if(idString.empty()) {
+      return ResultToJSON(false, "missing parameter id");
+    }
+    dsid_t dsid = dsid_t::fromString(idString);
+    if(dsid == NullDSID) {
+      return ResultToJSON(false, "could not parse dsid");
+    }
+    try {
+      Modulator& modulator = getDSS().getApartment().getModulatorByDSID(dsid);
+      if(_request.getMethod() == "getName") {
+        return JSONOk("{ " + ToJSONValue("name") + ": " + ToJSONValue(modulator.getName()) + "}");
+      } else if(_request.getMethod() == "setName") {
+        modulator.setName(_request.getParameter("newName"));
+        return ResultToJSON(true);
+      } else if(_request.getMethod() == "getEnergyBorder") {
+        std::ostringstream sstream;
+        sstream << "{" << ToJSONValue("orange") << ":" << ToJSONValue(modulator.getEnergyLevelOrange());
+        sstream << "," << ToJSONValue("red") << ":" << ToJSONValue(modulator.getEnergyLevelRed());
+        sstream << "}";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "getConsumption") {
+        return JSONOk("{ " + ToJSONValue("consumption") + ": " +  uintToString(modulator.getPowerConsumption()) +"}");
+      } else if(_request.getMethod() == "getEnergyMeterValue") {
+        return JSONOk("{ " + ToJSONValue("metervalue") + ": " +  uintToString(modulator.getEnergyMeterValue()) +"}");
+      } else if(_request.getMethod() == "rescan") {
+        modulator.setIsValid(false);
+        return ResultToJSON(true);
+      } else {
+        throw std::runtime_error("Unhandled function");
+      }
+    } catch(std::runtime_error&) {
+      return ResultToJSON(false, "could not find modulator with given dsid");
+    }
+    return "";
+  } // handleRequest
+
+
+  //=========================================== SetRequestHandler
+
+  std::string SetRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    if(_request.getMethod() == "fromApartment") {
+      return JSONOk("{'self': '.'}");
+    } else {
+      std::string self = trim(_request.getParameter("self"));
+      if(self.empty()) {
+        return ResultToJSON(false, "missing parameter 'self'");
+      }
+
+      if(_request.getMethod() == "byZone") {
+        std::string additionalPart;
+        if(self != ".") {
+          additionalPart = ".";
+        }
+        if(!_request.getParameter("zoneID").empty()) {
+          additionalPart += "zone(" + _request.getParameter("zoneID") + ")";
+        } else if(!_request.getParameter("zoneName").empty()) {
+          additionalPart += _request.getParameter("zoneName");
+        } else {
+          return ResultToJSON(false, "missing either zoneID or zoneName");
+        }
+
+        std::ostringstream sstream;
+        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "byGroup") {
+        std::string additionalPart;
+        if(self != ".") {
+          additionalPart = ".";
+        }
+        if(!_request.getParameter("groupID").empty()) {
+          additionalPart += "group(" + _request.getParameter("groupID") + ")";
+        } else if(!_request.getParameter("groupName").empty()) {
+          additionalPart += _request.getParameter("groupName");
+        } else {
+          return ResultToJSON(false, "missing either groupID or groupName");
+        }
+
+        std::ostringstream sstream;
+        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "byDSID") {
+        std::string additionalPart;
+        if(self != ".") {
+          additionalPart = ".";
+        }
+        if(!_request.getParameter("dsid").empty()) {
+          additionalPart += "dsid(" + _request.getParameter("dsid") + ")";
+        } else {
+          return ResultToJSON(false, "missing parameter dsid");
+        }
+
+        std::ostringstream sstream;
+        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "getDevices") {
+        SetBuilder builder(getDSS().getApartment());
+        Set set = builder.buildSet(self, NULL);
+        return JSONOk("{" + ToJSONValue(set, "devices") + "}");
+      } else if(_request.getMethod() == "add") {
+        std::string other = _request.getParameter("other");
+        if(other.empty()) {
+          return ResultToJSON(false, "missing parameter other");
+        }
+        std::string additionalPart;
+        if(self != ".") {
+          additionalPart = ".";
+        }
+        additionalPart += "add(" + other + ")";
+
+        std::ostringstream sstream;
+        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
+        return JSONOk(sstream.str());
+      } else if(_request.getMethod() == "subtract") {
+        std::string other = _request.getParameter("other");
+        if(other.empty()) {
+          return ResultToJSON(false, "missing parameter other");
+        }
+        std::string additionalPart;
+        if(self != ".") {
+          additionalPart = ".";
+        }
+        additionalPart += "subtract(" + other + ")";
+
+        std::ostringstream sstream;
+        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
+        return JSONOk(sstream.str());
+      } else if(isDeviceInterfaceCall(_request)) {
+        SetBuilder builder(getDSS().getApartment());
+        Set set = builder.buildSet(self, NULL);
+        return handleDeviceInterfaceRequest(_request, &set);
+      } else {
+        throw std::runtime_error("Unhandled function");
+      }
+
+    }
+    return "";
+  } // handleRequest
+
+
+  //=========================================== PropertyRequestHandler
+
+  std::string PropertyRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    std::string propName = _request.getParameter("path");
+    if(propName.empty()) {
+      return ResultToJSON(false, "Need parameter \'path\' for property operations");
+    }
+    PropertyNodePtr node = getDSS().getPropertySystem().getProperty(propName);
+
+    if(_request.getMethod() == "getString") {
+      if(node == NULL) {
+        return ResultToJSON(false, "Could not find node named '" + propName + "'");
+      }
+      try {
+        std::ostringstream sstream;
+        sstream << "{ " << ToJSONValue("value") << ": " << ToJSONValue(node->getStringValue()) << "}";
+        return JSONOk(sstream.str());
+      } catch(PropertyTypeMismatch& ex) {
+        return ResultToJSON(false, std::string("Error getting property: '") + ex.what() + "'");
+      }
+    } else if(_request.getMethod() == "getInteger") {
+      if(node == NULL) {
+        return ResultToJSON(false, "Could not find node named '" + propName + "'");
+      }
+      try {
+        std::ostringstream sstream;
+        sstream << "{ " << ToJSONValue("value") << ": " << ToJSONValue(node->getIntegerValue()) << "}";
+        return JSONOk(sstream.str());
+      } catch(PropertyTypeMismatch& ex) {
+        return ResultToJSON(false, std::string("Error getting property: '") + ex.what() + "'");
+      }
+    } else if(_request.getMethod() == "getBoolean") {
+      if(node == NULL) {
+        return ResultToJSON(false, "Could not find node named '" + propName + "'");
+      }
+      try {
+        std::ostringstream sstream;
+        sstream << "{ " << ToJSONValue("value") << ": " << ToJSONValue(node->getBoolValue()) << "}";
+        return JSONOk(sstream.str());
+      } catch(PropertyTypeMismatch& ex) {
+        return ResultToJSON(false, std::string("Error getting property: '") + ex.what() + "'");
+      }
+    } else if(_request.getMethod() == "setString") {
+      std::string value = _request.getParameter("value");
+      if(node == NULL) {
+        node = getDSS().getPropertySystem().createProperty(propName);
+      }
+      try {
+        node->setStringValue(value);
+      } catch(PropertyTypeMismatch& ex) {
+        return ResultToJSON(false, std::string("Error setting property: '") + ex.what() + "'");
+      }
+      return JSONOk();
+    } else if(_request.getMethod() == "setBoolean") {
+      std::string strValue = _request.getParameter("value");
+      bool value;
+      if(strValue == "true") {
+        value = true;
+      } else if(strValue == "false") {
+        value = false;
+      } else {
+        return ResultToJSON(false, "Expected 'true' or 'false' for parameter 'value' but got: '" + strValue + "'");
+      }
+      if(node == NULL) {
+        node = getDSS().getPropertySystem().createProperty(propName);
+      }
+      try {
+        node->setBooleanValue(value);
+      } catch(PropertyTypeMismatch& ex) {
+        return ResultToJSON(false, std::string("Error setting property: '") + ex.what() + "'");
+      }
+      return JSONOk();
+    } else if(_request.getMethod() == "setInteger") {
+      std::string strValue = _request.getParameter("value");
+      int value;
+      try {
+        value = strToInt(strValue);
+      } catch(...) {
+        return ResultToJSON(false, "Could not convert parameter 'value' to std::string. Got: '" + strValue + "'");
+      }
+      if(node == NULL) {
+        node = getDSS().getPropertySystem().createProperty(propName);
+      }
+      try {
+        node->setIntegerValue(value);
+      } catch(PropertyTypeMismatch& ex) {
+        return ResultToJSON(false, std::string("Error setting property: '") + ex.what() + "'");
+      }
+      return JSONOk();
+    } else if(_request.getMethod() == "getChildren") {
+      if(node == NULL) {
+        return ResultToJSON(false, "Could not find node named '" + propName + "'");
+      }
+      std::ostringstream sstream;
+      sstream << "[";
+      bool first = true;
+      for(int iChild = 0; iChild < node->getChildCount(); iChild++) {
+        if(!first) {
+          sstream << ",";
+        }
+        first = false;
+        PropertyNodePtr cnode = node->getChild(iChild);
+        sstream << "{" << ToJSONValue("name") << ":" << ToJSONValue(cnode->getName());
+        sstream << "," << ToJSONValue("type") << ":" << ToJSONValue(getValueTypeAsString(cnode->getValueType()));
+        sstream << "}";
+      }
+      sstream << "]";
+      return JSONOk(sstream.str());
+    } else if(_request.getMethod() == "getType") {
+      if(node == NULL) {
+        return ResultToJSON(false, "Could not find node named '" + propName + "'");
+      }
+      std::ostringstream sstream;
+      sstream << ":" << ToJSONValue("type") << ":" << ToJSONValue(getValueTypeAsString(node->getValueType())) << "}";
+      return JSONOk(sstream.str());
+    } else {
+      throw std::runtime_error("Unhandled function");
+    }
+    return "";
+  } // handleRequest
+
+
+  //=========================================== EventRequestHandler
+
+  std::string EventRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    if(_request.getMethod() == "raise") {
+      std::string name = _request.getParameter("name");
+      std::string location = _request.getParameter("location");
+      std::string context = _request.getParameter("context");
+      std::string parameter = _request.getParameter("parameter");
+
+      boost::shared_ptr<Event> evt(new Event(name));
+      if(!context.empty()) {
+        evt->setContext(context);
+      }
+      if(!location.empty()) {
+        evt->setLocation(location);
+      }
+      std::vector<std::string> params = dss::splitString(parameter, ';');
+      for(std::vector<std::string>::iterator iParam = params.begin(), e = params.end();
+          iParam != e; ++iParam)
+      {
+        std::vector<std::string> nameValue = dss::splitString(*iParam, '=');
+        if(nameValue.size() == 2) {
+          dss::Logger::getInstance()->log("WebServer::handleEventCall: Got parameter '" + nameValue[0] + "'='" + nameValue[1] + "'");
+          evt->setProperty(nameValue[0], nameValue[1]);
+        } else {
+          dss::Logger::getInstance()->log(std::string("Invalid parameter found WebServer::handleEventCall: ") + *iParam );
+        }
+      }
+
+      getDSS().getEventQueue().pushEvent(evt);
+      return ResultToJSON(true);
+    } else {
+      throw std::runtime_error("Unhandled function");
+    }
+  } // handleRequest
+  
+
+  //=========================================== SystemRequestHandler
+
+  std::string SystemRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    if(_request.getMethod() == "version") {
+      return ResultToJSON(true, DSS::getInstance()->versionString());
+    }
+    throw std::runtime_error("Unhandled function");
+  } // handleRequest
+
+
+  //=========================================== StructureRequestHandler
+
+  std::string StructureRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    StructureManipulator manipulator(getDSS().getDS485Interface(), getDSS().getApartment());
+    if(_request.getMethod() == "zoneAddDevice") {
+      std::string devidStr = _request.getParameter("devid");
+      if(!devidStr.empty()) {
+        dsid_t devid = dsid::fromString(devidStr);
+
+        Device& dev = DSS::getInstance()->getApartment().getDeviceByDSID(devid);
+        if(!dev.isPresent()) {
+          return ResultToJSON(false, "cannot add nonexisting device to a zone");
+        }
+
+        std::string zoneIDStr = _request.getParameter("zone");
+        if(!zoneIDStr.empty()) {
+          try {
+            int zoneID = strToInt(zoneIDStr);
+            DeviceReference devRef(dev, &DSS::getInstance()->getApartment());
+            try {
+              Zone& zone = getDSS().getApartment().getZone(zoneID);
+              manipulator.addDeviceToZone(dev, zone);
+            } catch(ItemNotFoundException&) {
+              return ResultToJSON(false, "Could not find zone");
+            }
+          } catch(std::runtime_error& err) {
+            return ResultToJSON(false, err.what());
+          }
+        }
+        return ResultToJSON(true);
+      } else {
+        return ResultToJSON(false, "Need parameter devid");
+      }
+    } else if(_request.getMethod() == "addZone") {
+      int zoneID = -1;
+
+      std::string zoneIDStr = _request.getParameter("zoneID");
+      if(!zoneIDStr.empty()) {
+        zoneID = strToIntDef(zoneIDStr, -1);
+      }
+      if(zoneID != -1) {
+        getDSS().getApartment().allocateZone(zoneID);
+      } else {
+        return ResultToJSON(false, "could not find zone");
+      }
+      return ResultToJSON(true, "");
+    } else if(_request.getMethod() == "removeZone") {
+      int zoneID = -1;
+
+      std::string zoneIDStr = _request.getParameter("zoneID");
+      if(!zoneIDStr.empty()) {
+        zoneID = strToIntDef(zoneIDStr, -1);
+      }
+      if(zoneID != -1) {
+        try {
+          Zone& zone = getDSS().getApartment().getZone(zoneID);
+          if(zone.getFirstZoneOnModulator() != -1) {
+            return ResultToJSON(false, "Cannot delete a primary zone");
+          }
+          if(zone.getDevices().length() > 0) {
+            return ResultToJSON(false, "Cannot delete a non-empty zone");
+          }
+          getDSS().getApartment().removeZone(zoneID);
+          getDSS().getApartment().addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
+          return JSONOk();
+        } catch(ItemNotFoundException&) {
+          return ResultToJSON(false, "Could not find zone");
+        }
+      } else {
+        return ResultToJSON(false, "Missing parameter zoneID");
+      }
+    } else {
+      throw std::runtime_error("Unhandled function");
+    }
+  } // handleRequest
+
+
+  //=========================================== SimRequestHandler
+
+  std::string SimRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    if(_request.getMethod() == "switch") {
+      if(_request.getMethod() == "switch/pressed") {
+        int buttonNr = strToIntDef(_request.getParameter("buttonnr"), -1);
+        if(buttonNr == -1) {
+          return ResultToJSON(false, "Invalid button number");
+        }
+
+        int zoneID = strToIntDef(_request.getParameter("zoneID"), -1);
+        if(zoneID == -1) {
+          return ResultToJSON(false, "Could not parse zoneID");
+        }
+        int groupID = strToIntDef(_request.getParameter("groupID"), -1);
+        if(groupID == -1) {
+          return ResultToJSON(false, "Could not parse groupID");
+        }
+        try {
+          Zone& zone = getDSS().getApartment().getZone(zoneID);
+          Group* pGroup = zone.getGroup(groupID);
+
+          if(pGroup == NULL) {
+            return ResultToJSON(false, "Could not find group");
+          }
+
+          switch(buttonNr) {
+          case 1: // upper-left
+          case 3: // upper-right
+          case 7: // lower-left
+          case 9: // lower-right
+            break;
+          case 2: // up
+            pGroup->increaseValue();
+            break;
+          case 8: // down
+            pGroup->decreaseValue();
+            break;
+          case 4: // left
+            pGroup->previousScene();
+            break;
+          case 6: // right
+            pGroup->nextScene();
+            break;
+          case 5:
+            {
+              if(groupID == GroupIDGreen) {
+                getDSS().getApartment().getGroup(0).callScene(SceneBell);
+              } else if(groupID == GroupIDRed){
+                getDSS().getApartment().getGroup(0).callScene(SceneAlarm);
+              } else {
+                const int lastScene = pGroup->getLastCalledScene();
+                if(lastScene == SceneOff || lastScene == SceneDeepOff ||
+                  lastScene == SceneStandBy || lastScene == ScenePanic)
+                {
+                  pGroup->callScene(Scene1);
+                } else {
+                  pGroup->callScene(SceneOff);
+                }
+              }
+            }
+            break;
+          default:
+            return ResultToJSON(false, "Invalid button nr (range is 1..9)");
+          }
+        } catch(std::runtime_error&) {
+          return ResultToJSON(false, "Could not find zone");
+        }
+      }
+    } else if(_request.getMethod() == "addDevice") {
+      //std::string type = _parameter["type"];
+      //std::string dsidStr = _parameter["dsid"];
+      // TODO: not finished yet ;)
+      return "";
+    }
+    throw std::runtime_error("Unhandled function");
+  } // handleRequest
+
+
+  //=========================================== DebugRequestHandler
+
+  std::string DebugRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    if(_request.getMethod() == "sendFrame") {
+      int destination = strToIntDef(_request.getParameter("destination"),0) & 0x3F;
+      bool broadcast = _request.getParameter("broadcast") == "true";
+      int counter = strToIntDef(_request.getParameter("counter"), 0x00) & 0x03;
+      int command = strToIntDef(_request.getParameter("command"), 0x09 /* request */) & 0x00FF;
+      int length = strToIntDef(_request.getParameter("length"), 0x00) & 0x0F;
+
+      std::cout
+          << "sending frame: "
+          << "\ndest:    " << destination
+          << "\nbcst:    " << broadcast
+          << "\ncntr:    " << counter
+          << "\ncmd :    " << command
+          << "\nlen :    " << length << std::endl;
+
+      DS485CommandFrame* frame = new DS485CommandFrame();
+      frame->getHeader().setBroadcast(broadcast);
+      frame->getHeader().setDestination(destination);
+      frame->getHeader().setCounter(counter);
+      frame->setCommand(command);
+      for(int iByte = 0; iByte < length; iByte++) {
+        uint8_t byte = strToIntDef(_request.getParameter(std::string("payload_") + intToString(iByte+1)), 0xFF);
+        std::cout << "b" << std::dec << iByte << ": " << std::hex << (int)byte << "\n";
+        frame->getPayload().add<uint8_t>(byte);
+      }
+      std::cout << std::dec << "done" << std::endl;
+      DS485Interface* intf = &DSS::getInstance()->getDS485Interface();
+      DS485Proxy* proxy = dynamic_cast<DS485Proxy*>(intf);
+      if(proxy != NULL) {
+        proxy->sendFrame(*frame);
+      } else {
+        delete frame;
+      }
+      return ResultToJSON(true);
+    } else if(_request.getMethod() == "dSLinkSend") {
+      std::string deviceDSIDString =_request.getParameter("dsid");
+      Device* pDevice = NULL;
+      if(!deviceDSIDString.empty()) {
+        dsid_t deviceDSID = dsid_t::fromString(deviceDSIDString);
+        if(!(deviceDSID == NullDSID)) {
+          try {
+            Device& device = getDSS().getApartment().getDeviceByDSID(deviceDSID);
+            pDevice = &device;
+          } catch(std::runtime_error& e) {
+            return ResultToJSON(false ,"Could not find device with dsid '" + deviceDSIDString + "'");
+          }
+        } else {
+          return ResultToJSON(false, "Could not parse dsid '" + deviceDSIDString + "'");
+        }
+      } else {
+        return ResultToJSON(false, "Missing parameter 'dsid'");
+      }
+
+      int iValue = strToIntDef(_request.getParameter("value"), -1);
+      if(iValue == -1) {
+        return ResultToJSON(false, "Missing parameter 'value'");
+      }
+      if(iValue < 0 || iValue > 0x00ff) {
+        return ResultToJSON(false, "Parameter 'value' is out of range (0-0xff)");
+      }
+      bool writeOnly = false;
+      bool lastValue = false;
+      if(_request.getParameter("writeOnly") == "true") {
+        writeOnly = true;
+      }
+      if(_request.getParameter("lastValue") == "true") {
+        lastValue = true;
+      }
+      uint8_t result;
+      try {
+        result = pDevice->dsLinkSend(iValue, lastValue, writeOnly);
+      } catch(std::runtime_error& e) {
+        return ResultToJSON(false, std::string("Error: ") + e.what());
+      }
+      if(writeOnly) {
+        return ResultToJSON(true);
+      } else {
+        std::ostringstream sstream;
+        sstream << "{" << ToJSONValue("value") << ":" << ToJSONValue(result) << "}";
+        return JSONOk(sstream.str());
+      }
+    } else if(_request.getMethod() == "pingDevice") {
+      std::string deviceDSIDString = _request.getParameter("dsid");
+      if(deviceDSIDString.empty()) {
+        return ResultToJSON(false, "Missing parameter 'dsid'");
+      }
+      try {
+        dsid_t deviceDSID = dsid_t::fromString(deviceDSIDString);
+        Device& device = getDSS().getApartment().getDeviceByDSID(deviceDSID);
+        DS485CommandFrame* frame = new DS485CommandFrame();
+        frame->getHeader().setBroadcast(true);
+        frame->getHeader().setDestination(device.getModulatorID());
+        frame->setCommand(CommandRequest);
+        frame->getPayload().add<uint8_t>(FunctionDeviceGetTransmissionQuality);
+        frame->getPayload().add<uint16_t>(device.getShortAddress());
+        DS485Interface* intf = &DSS::getInstance()->getDS485Interface();
+        DS485Proxy* proxy = dynamic_cast<DS485Proxy*>(intf);
+        if(proxy != NULL) {
+          boost::shared_ptr<FrameBucketCollector> bucket = proxy->sendFrameAndInstallBucket(*frame, FunctionDeviceGetTransmissionQuality);
+          bucket->waitForFrame(2000);
+
+          boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
+          if(recFrame == NULL) {
+            return ResultToJSON(false, "No result received");
+          }
+          PayloadDissector pd(recFrame->getFrame()->getPayload());
+          pd.get<uint8_t>();
+          int errC = int(pd.get<uint16_t>());
+          if(errC < 0) {
+            return ResultToJSON(false, "dSM reported error-code: " + intToString(errC));
+          }
+          pd.get<uint16_t>(); // device address
+          int qualityHK = pd.get<uint16_t>();
+          int qualityRK = pd.get<uint16_t>();
+          std::ostringstream sstream;
+          sstream << "{" << ToJSONValue("qualityHK") << ":" << ToJSONValue(qualityHK) << ",";
+          sstream << ToJSONValue("qualityRK") << ":" << ToJSONValue(qualityRK) << "}";
+          return JSONOk(sstream.str());
+        } else {
+          delete frame;
+          return ResultToJSON(false, "Proxy has a wrong type or is null");
+        }
+      } catch(ItemNotFoundException&) {
+        return ResultToJSON(false ,"Could not find device with dsid '" + deviceDSIDString + "'");
+      } catch(std::invalid_argument&) {
+        return ResultToJSON(false, "Could not parse dsid '" + deviceDSIDString + "'");
+      }
+    } else if(_request.getMethod() == "resetZone") {
+      std::string zoneIDStr = _request.getParameter("zoneID");
+      int zoneID;
+      try {
+        zoneID = strToInt(zoneIDStr);
+      } catch(std::runtime_error&) {
+        return ResultToJSON(false, "Could not parse Zone ID");
+      }
+      DS485CommandFrame* frame = new DS485CommandFrame();
+      frame->getHeader().setBroadcast(true);
+      frame->getHeader().setDestination(0);
+      frame->setCommand(CommandRequest);
+      frame->getPayload().add<uint8_t>(FunctionZoneRemoveAllDevicesFromZone);
+      frame->getPayload().add<uint8_t>(zoneID);
+      DS485Interface* intf = &DSS::getInstance()->getDS485Interface();
+      DS485Proxy* proxy = dynamic_cast<DS485Proxy*>(intf);
+      if(proxy != NULL) {
+        proxy->sendFrame(*frame);
+        return ResultToJSON(true, "Please restart your dSMs");
+      } else {
+        delete frame;
+        return ResultToJSON(false, "Proxy has a wrong type or is null");
+      }
+    }
+    throw std::runtime_error("Unhandled function");
+  } // handleRequest
+
+
+  //=========================================== MeteringRequestHandler
+
+  std::string MeteringRequestHandler::handleRequest(const RestfulRequest& _request, Session* _session) {
+    if(_request.getMethod() == "getResolutions") {
+      std::vector<boost::shared_ptr<MeteringConfigChain> > meteringConfig = getDSS().getMetering().getConfig();
+      std::ostringstream sstream;
+      sstream << "{" << ToJSONValue("resolutions") << ":" << "[";
+      for(unsigned int iConfig = 0; iConfig < meteringConfig.size(); iConfig++) {
+        boost::shared_ptr<MeteringConfigChain> cConfig = meteringConfig[iConfig];
+        for(int jConfig = 0; jConfig < cConfig->size(); jConfig++) {
+          sstream << "{" << ToJSONValue("type") << ":" << (cConfig->isEnergy() ? ToJSONValue("energy") : ToJSONValue("consumption") ) << ","
+                  << ToJSONValue("unit") << ":" << ToJSONValue(cConfig->getUnit()) << ","
+                  << ToJSONValue("resolution") << ":" << ToJSONValue(cConfig->getResolution(jConfig)) << "}";
+          if(jConfig < cConfig->size() && iConfig < meteringConfig.size()) {
+            sstream << ",";
+          }
+        }
+      }
+      sstream << "]"  << "}";
+      return JSONOk(sstream.str());
+    } else if(_request.getMethod() == "getSeries") {
+      std::ostringstream sstream;
+      sstream << "{ " << ToJSONValue("series") << ": [";
+      bool first = true;
+      vector<Modulator*>& modulators = getDSS().getApartment().getModulators();
+      foreach(Modulator* modulator, modulators) {
+        if(!first) {
+          sstream << ",";
+        }
+        first = false;
+        sstream << "{ " << ToJSONValue("dsid") << ": " << ToJSONValue(modulator->getDSID().toString());
+        sstream << ", " << ToJSONValue("type") << ": " << ToJSONValue("energy");
+        sstream << "},";
+        sstream << "{ " << ToJSONValue("dsid") << ": " << ToJSONValue(modulator->getDSID().toString());
+        sstream << ", " << ToJSONValue("type") << ": " << ToJSONValue("consumption");
+        sstream << "}";
+      }
+      sstream << "]}";
+      return JSONOk(sstream.str());
+    } else if(_request.getMethod() == "getValues") { //?dsid=;n=,resolution=,type=
+      std::string errorMessage;
+      std::string deviceDSIDString = _request.getParameter("dsid");
+      std::string resolutionString = _request.getParameter("resolution");
+      std::string typeString = _request.getParameter("type");
+      std::string fileSuffix;
+      std::string storageLocation;
+      std::string seriesPath;
+      int resolution;
+      bool energy;
+      if(!deviceDSIDString.empty()) {
+        dsid_t deviceDSID = dsid_t::fromString(deviceDSIDString);
+        if(!(deviceDSID == NullDSID)) {
+          try {
+            getDSS().getApartment().getModulatorByDSID(deviceDSID);
+          } catch(std::runtime_error& e) {
+            return ResultToJSON(false, "Could not find device with dsid '" + deviceDSIDString + "'");
+          }
+        } else {
+        return ResultToJSON(false, "Could not parse dsid '" + deviceDSIDString + "'");
+        }
+      } else {
+        return ResultToJSON(false, "Could not parse dsid '" + deviceDSIDString + "'");
+      }
+      resolution = strToIntDef(resolutionString, -1);
+      if(resolution == -1) {
+        return ResultToJSON(false, "Need could not parse resolution '" + resolutionString + "'");
+      }
+      if(typeString.empty()) {
+        return ResultToJSON(false, "Need a type, 'energy' or 'consumption'");
+      } else {
+        if(typeString == "consumption") {
+          energy = false;
+        } else if(typeString == "energy") {
+          energy = true;
+        } else {
+          return ResultToJSON(false, "Invalide type '" + typeString + "'");
+        }
+      }
+      if(!resolutionString.empty()) {
+        std::vector<boost::shared_ptr<MeteringConfigChain> > meteringConfig = getDSS().getMetering().getConfig();
+        storageLocation = getDSS().getMetering().getStorageLocation();
+        for(unsigned int iConfig = 0; iConfig < meteringConfig.size(); iConfig++) {
+          boost::shared_ptr<MeteringConfigChain> cConfig = meteringConfig[iConfig];
+          for(int jConfig = 0; jConfig < cConfig->size(); jConfig++) {
+            if(cConfig->isEnergy() == energy && cConfig->getResolution(jConfig) == resolution) {
+              fileSuffix = cConfig->getFilenameSuffix(jConfig);
+            }
+          }
+        }
+        if(fileSuffix.empty()) {
+          return ResultToJSON(false, "No data for '" + typeString + "' and resolution '" + resolutionString + "'");
+        } else {
+          seriesPath = storageLocation + deviceDSIDString + "_" + fileSuffix + ".xml";
+          log("_Trying to load series from " + seriesPath);
+          if(boost::filesystem::exists(seriesPath)) {
+            SeriesReader<CurrentValue> reader;
+            boost::shared_ptr<Series<CurrentValue> > s = boost::shared_ptr<Series<CurrentValue> >(reader.readFromXML(seriesPath));
+            std::deque<CurrentValue>* values = s->getExpandedValues();
+            bool first = true;
+            std::ostringstream sstream;
+            sstream << "{ " ;
+            sstream << ToJSONValue("dsmid") << ":" << ToJSONValue(deviceDSIDString) << ",";
+            sstream << ToJSONValue("type") << ":" << ToJSONValue(typeString) << ",";
+            sstream << ToJSONValue("resolution") << ":" << ToJSONValue(resolutionString) << ",";
+            sstream << ToJSONValue("values") << ": [";
+            for(std::deque<CurrentValue>::iterator iValue = values->begin(), e = values->end(); iValue != e; iValue++)
+            {
+              if(!first) {
+                sstream << ",";
+              }
+              first = false;
+              sstream << "[" << iValue->getTimeStamp().secondsSinceEpoch()  << "," << iValue->getValue() << "]";
+            }
+            sstream << "]}";
+            delete values;
+            return JSONOk(sstream.str());
+          } else {
+            return ResultToJSON(false, "No data-file for '" + typeString + "' and resolution '" + resolutionString + "'");
+          }
+        }
+      } else {
+        return ResultToJSON(false, "Could not parse resolution '" + resolutionString + "'");
+      }
+    } else if(_request.getMethod() == "getAggregatedValues") { //?set=;n=,resolution=;type=
+      // TODO: implement
+    }
+    throw std::runtime_error("Unhandled function");
+  } // handleRequest
+
+} // namespace dss
diff --git a/core/web/webrequests.h b/core/web/webrequests.h
new file mode 100644
index 0000000..21ded0d
--- /dev/null
+++ b/core/web/webrequests.h
@@ -0,0 +1,116 @@
+/*
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef WEBREQUESTS_H
+#define WEBREQUESTS_H
+
+#include "core/web/restful.h"
+
+#include <string>
+
+#include "core/logger.h"
+#include "core/dss.h"
+
+namespace dss {
+
+  class IDeviceInterface;
+  
+  class WebServerRequestHandler : public RestfulRequestHandler {
+  protected:
+    DSS& getDSS() {
+      return *DSS::getInstance();
+    }
+
+    void log(const std::string& _line, aLogSeverity _severity = lsDebug) {
+      Logger::getInstance()->log("RequestHandler: " + _line, _severity);
+    }
+  }; // WebServerRequestHandler
+
+  class DeviceInterfaceRequestHandler : public WebServerRequestHandler {
+  public:
+    std::string handleDeviceInterfaceRequest(const RestfulRequest& _request, IDeviceInterface* _interface);
+
+  protected:
+    bool isDeviceInterfaceCall(const RestfulRequest& _request);
+  };
+
+  class ApartmentRequestHandler : public DeviceInterfaceRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  };
+
+  class ZoneRequestHandler : public DeviceInterfaceRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // ZoneRequestHandler
+
+  class DeviceRequestHandler : public DeviceInterfaceRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // DeviceRequestHandler
+
+  class CircuitRequestHandler : public WebServerRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // CircuitRequestHandler
+
+  class SetRequestHandler : public DeviceInterfaceRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // SetRequestHandler
+
+  class PropertyRequestHandler : public WebServerRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // PropertyRequestHandler
+
+  class EventRequestHandler : public WebServerRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // EventRequestHandler
+
+  class SystemRequestHandler : public WebServerRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // SystemRequestHandler
+
+  class StructureRequestHandler : public WebServerRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // StructureRequestHandler
+
+  class SimRequestHandler : public WebServerRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // SimRequestHandler
+
+  class DebugRequestHandler : public WebServerRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // DebugRequestHandler
+
+  class MeteringRequestHandler : public WebServerRequestHandler {
+  public:
+    virtual std::string handleRequest(const RestfulRequest& _request, Session* _session);
+  }; // MeteringRequestHandler
+
+
+}
+
+#endif // WEBREQUESTS_H
diff --git a/core/web/webserver.cpp b/core/web/webserver.cpp
new file mode 100644
index 0000000..49ffde7
--- /dev/null
+++ b/core/web/webserver.cpp
@@ -0,0 +1,350 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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 "webserver.h"
+
+#include <iostream>
+#include <sstream>
+
+#include "core/logger.h"
+#include "core/dss.h"
+#include "core/propertysystem.h"
+#include "core/web/restful.h"
+#include "core/web/restfulapiwriter.h"
+#include "core/web/webrequests.h"
+#include "core/web/webserverplugin.h"
+
+#include "webserverapi.h"
+
+namespace dss {
+  //============================================= WebServer
+
+  WebServer::WebServer(DSS* _pDSS)
+    : Subsystem(_pDSS, "WebServer"), m_mgContext(0)
+  {
+  } // ctor
+
+  WebServer::~WebServer() {
+    if (m_mgContext) {
+      mg_stop(m_mgContext);
+    }
+  } // dtor
+
+  void WebServer::initialize() {
+    Subsystem::initialize();
+
+    log("Starting Webserver...");
+    m_mgContext = mg_start();
+
+    getDSS().getPropertySystem().setStringValue(getConfigPropertyBasePath() + "webroot", getDSS().getWebrootDirectory(), true, false);
+    getDSS().getPropertySystem().setStringValue(getConfigPropertyBasePath() + "ports", "8080", true, false);
+
+    setupAPI();
+    instantiateHandlers();
+  } // initialize
+
+  void WebServer::loadPlugins() {
+    PropertyNodePtr pluginsNode = getDSS().getPropertySystem().getProperty(getConfigPropertyBasePath() + "plugins");
+    if(pluginsNode != NULL) {
+      log("Found plugins node, trying to loading plugins", lsInfo);
+      pluginsNode->foreachChildOf(*this, &WebServer::loadPlugin);
+    }
+  } // loadPlugins
+
+  void WebServer::loadPlugin(PropertyNode& _node) {
+    PropertyNodePtr pFileNode = _node.getProperty("file");
+    PropertyNodePtr pURINode = _node.getProperty("uri");
+
+    if(pFileNode == NULL) {
+      log("loadPlugin: Missing subnode name 'file' on node " + _node.getDisplayName(), lsError);
+      return;
+    }
+    if(pURINode == NULL) {
+      log("loadPlugin: Missing subnode 'uri on node " + _node.getDisplayName(), lsError);
+    }
+    WebServerPlugin* plugin = new WebServerPlugin(pURINode->getStringValue(), pFileNode->getStringValue());
+    try {
+      plugin->load();
+    } catch(std::runtime_error& e) {
+      delete plugin;
+      plugin = NULL;
+      log(std::string("Caught exception while loading: ") + e.what(), lsError);
+      return;
+    }
+    m_Plugins.push_back(plugin);
+
+    log("Registering " + pFileNode->getStringValue() + " for URI '" + pURINode->getStringValue() + "'");
+    mg_set_uri_callback(m_mgContext, pURINode->getStringValue().c_str(), &httpPluginCallback, plugin);
+  } // loadPlugin
+
+  void WebServer::setupAPI() {
+    RestfulAPI api = WebServerAPI::createRestfulAPI();
+    RestfulAPIWriter::writeToXML(api, "doc/json_api.xml");
+  } // setupAPI
+
+  void WebServer::doStart() {
+    std::string ports = DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "ports");
+    log("Webserver: Listening on port(s) " + ports);
+    mg_set_option(m_mgContext, "ports", ports.c_str());
+
+    std::string aliases = std::string("/=") + DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "webroot");
+    log("Webserver: Configured aliases: " + aliases);
+    mg_set_option(m_mgContext, "aliases", aliases.c_str());
+
+    mg_set_uri_callback(m_mgContext, "/browse/*", &httpBrowseProperties, NULL);
+    mg_set_uri_callback(m_mgContext, "/json/*", &jsonHandler, NULL);
+    mg_set_uri_callback(m_mgContext, "/download/*", &downloadHandler, NULL);
+
+    loadPlugins();
+
+    log("Webserver started", lsInfo);
+  } // start
+
+  const char* httpCodeToMessage(const int _code) {
+    if(_code == 400) {
+      return "Bad Request";
+    } else if(_code == 401) {
+      return "Unauthorized\r\nWWW-Authenticate: Basic realm=\"dSS\"";
+    } else if(_code == 403) {
+      return "Forbidden";
+    } else if(_code == 500) {
+      return "Internal Server Error";
+    } else {
+      return "OK";
+    }
+  }
+
+  void WebServer::emitHTTPHeader(int _code, struct mg_connection* _connection, const std::string& _contentType) {
+    std::ostringstream sstream;
+    sstream << "HTTP/1.1 " << _code << ' ' << httpCodeToMessage(_code) << "\r\n";
+    sstream << "Content-Type: " << _contentType << "; charset=utf-8\r\n\r\n";
+    std::string tmp = sstream.str();
+    mg_write(_connection, tmp.c_str(), tmp.length());
+  } // emitHTTPHeader
+
+  HashMapConstStringString parseParameter(const char* _params) {
+    HashMapConstStringString result;
+    if(_params != NULL) {
+      std::vector<std::string> paramList = splitString(_params, '&');
+      for(std::vector<std::string>::iterator iParam = paramList.begin(); iParam != paramList.end(); ++iParam) {
+        std::vector<std::string> nameValue = splitString(*iParam, '=');
+        if(nameValue.size() != 2) {
+          result[*iParam] = "";
+        } else {
+          result[urlDecode(nameValue.at(0))] = urlDecode(nameValue.at(1));
+        }
+      }
+    }
+    return result;
+  } // parseParameter
+
+  const char* kHandlerApartment = "apartment";
+  const char* kHandlerZone = "zone";
+  const char* kHandlerDevice = "device";
+  const char* kHandlerCircuit = "circuit";
+  const char* kHandlerSet = "set";
+  const char* kHandlerProperty = "property";
+  const char* kHandlerEvent = "event";
+  const char* kHandlerSystem = "system";
+  const char* kHandlerStructure = "structure";
+  const char* kHandlerSim = "sim";
+  const char* kHandlerDebug = "debug";
+  const char* kHandlerMetering = "metering";
+
+  void WebServer::instantiateHandlers() {
+    m_Handlers[kHandlerApartment] = new ApartmentRequestHandler();
+    m_Handlers[kHandlerZone] = new ZoneRequestHandler();
+    m_Handlers[kHandlerDevice] = new DeviceRequestHandler();
+    m_Handlers[kHandlerCircuit] = new CircuitRequestHandler();
+    m_Handlers[kHandlerSet] = new SetRequestHandler();
+    m_Handlers[kHandlerProperty] = new PropertyRequestHandler();
+    m_Handlers[kHandlerEvent] = new EventRequestHandler();
+    m_Handlers[kHandlerSystem] = new SystemRequestHandler();
+    m_Handlers[kHandlerStructure] = new StructureRequestHandler();
+    m_Handlers[kHandlerSim] = new SimRequestHandler();
+    m_Handlers[kHandlerDebug] = new DebugRequestHandler();
+    m_Handlers[kHandlerMetering] = new MeteringRequestHandler();
+  } // instantiateHandlers
+  
+  void WebServer::httpPluginCallback(struct mg_connection* _connection,
+                                     const struct mg_request_info* _info,
+                                     void* _userData) {
+    if(_userData != NULL) {
+      WebServerPlugin* plugin = static_cast<WebServerPlugin*>(_userData);
+      WebServer& self = DSS::getInstance()->getWebServer();
+
+      std::string uri = _info->uri;
+      self.log("Plugin: Processing call to " + uri);
+
+      self.pluginCalled(_connection, _info, *plugin, uri);
+    }
+  } // httpPluginCallback
+
+  void WebServer::pluginCalled(struct mg_connection* _connection,
+                               const struct mg_request_info* _info,
+                               WebServerPlugin& plugin,
+                               const std::string& _uri) {
+    HashMapConstStringString paramMap = parseParameter(_info->query_string);
+
+    std::string result;
+    if(plugin.handleRequest(_uri, paramMap, getDSS(), result)) {
+      emitHTTPHeader(200, _connection, "text/plain");
+      mg_write(_connection, result.c_str(), result.length());
+    } else {
+      emitHTTPHeader(500, _connection, "text/plain");
+      mg_printf(_connection, "error");
+    }
+  } // pluginCalled
+
+  void WebServer::jsonHandler(struct mg_connection* _connection,
+                              const struct mg_request_info* _info,
+                              void* _userData) {
+    const std::string urlid = "/json/";
+    std::string uri = _info->uri;
+
+    HashMapConstStringString paramMap = parseParameter(_info->query_string);
+
+    std::string method = uri.substr(uri.find(urlid) + urlid.size());
+
+    RestfulRequest request(method, paramMap);
+
+    WebServer& self = DSS::getInstance()->getWebServer();
+    self.log("Processing call to " + method);
+
+    Session* session = NULL;
+    std::string tokenStr = paramMap["token"];
+    if(!tokenStr.empty()) {
+      int token = strToIntDef(tokenStr, -1);
+      if(token != -1) {
+        SessionByID::iterator iEntry = self.m_Sessions.find(token);
+        if(iEntry != self.m_Sessions.end()) {
+          if(iEntry->second->isStillValid()) {
+            Session& s = *iEntry->second;
+            session = &s;
+          }
+        }
+      }
+    }
+
+    std::string result;
+    if(self.m_Handlers[request.getClass()] != NULL) {
+      result = self.m_Handlers[request.getClass()]->handleRequest(request, session);
+      emitHTTPHeader(200, _connection, "application/json");
+    } else {
+      emitHTTPHeader(404, _connection, "application/json");
+      std::ostringstream sstream;
+      sstream << "{" << "\"ok\"" << ":" << "false" << ",";
+      sstream << "\"message\"" << ":" << "\"Call to unknown function\"";
+      sstream << "}";
+      result = sstream.str();
+      self.log("Unknown function '" + method + "'", lsError);
+    }
+    mg_write(_connection, result.c_str(), result.length());
+  } // jsonHandler
+
+  void WebServer::downloadHandler(struct mg_connection* _connection,
+                                  const struct mg_request_info* _info, 
+                                  void* _userData) {
+    const std::string kURLID = "/download/";
+    std::string uri = _info->uri;
+
+    std::string givenFileName = uri.substr(uri.find(kURLID) + kURLID.size());
+
+    WebServer& self = DSS::getInstance()->getWebServer();
+    self.log("Processing call to download/" + givenFileName);
+
+    // TODO: make the files-node readonly as this might pose a security threat
+    //       (you could download any file on the disk if you add it as a subnode
+    //        of files)
+    PropertyNodePtr filesNode = self.getDSS().getPropertySystem().getProperty(
+                                    self.getConfigPropertyBasePath() + "files"
+                                );
+    std::string fileName;
+    if(filesNode != NULL) {
+      PropertyNodePtr fileNode = filesNode->getProperty(givenFileName);
+      if(fileNode != NULL) {
+        fileName = fileNode->getStringValue();
+      }
+    }
+    self.log("Using local file: " + fileName);
+    struct mgstat st;
+    if(mg_stat(fileName.c_str(), &st) != 0) {
+      self.log("Not found");
+      memset(&st, '\0', sizeof(st));
+    }
+    mg_send_file(_connection, fileName.c_str(), &st);
+  } // downloadHandler
+
+  void WebServer::httpBrowseProperties(struct mg_connection* _connection,
+                                       const struct mg_request_info* _info,
+                                       void* _userData) {
+    emitHTTPHeader(200, _connection);
+
+    const std::string urlid = "/browse";
+    std::string uri = _info->uri;
+    HashMapConstStringString paramMap = parseParameter(_info->query_string);
+
+    std::string path = uri.substr(uri.find(urlid) + urlid.size());
+    if(path.empty()) {
+      path = "/";
+    }
+    mg_printf(_connection, "<html><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><body>");
+
+    std::ostringstream stream;
+    stream << "<h1>" << path << "</h1>";
+    stream << "<ul>";
+    PropertyNodePtr node = DSS::getInstance()->getPropertySystem().getProperty(path);
+    if(node != NULL) {
+      for(int iNode = 0; iNode < node->getChildCount(); iNode++) {
+        PropertyNodePtr cnode = node->getChild(iNode);
+
+        stream << "<li>";
+        if(cnode->getChildCount() != 0) {
+          stream << "<a href=\"/browse" << path << "/" << cnode->getDisplayName() << "\">" << cnode->getDisplayName() << "</a>";
+        } else {
+          stream << cnode->getDisplayName();
+        }
+        stream << " : ";
+        stream << getValueTypeAsString(cnode->getValueType()) << " : ";
+        switch(cnode->getValueType()) {
+        case vTypeBoolean:
+          stream << cnode->getBoolValue();
+          break;
+        case vTypeInteger:
+          stream << cnode->getIntegerValue();
+          break;
+        case vTypeNone:
+          break;
+        case vTypeString:
+          stream << cnode->getStringValue();
+          break;
+        default:
+          stream << "unknown value";
+        }
+      }
+    }
+
+    stream << "</ul></body></html>";
+    std::string tmp = stream.str();
+    mg_write(_connection, tmp.c_str(), tmp.length());
+  } // httpBrowseProperties
+
+}
diff --git a/core/web/webserver.h b/core/web/webserver.h
new file mode 100644
index 0000000..8f03cc3
--- /dev/null
+++ b/core/web/webserver.h
@@ -0,0 +1,89 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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 WEBSERVER_H_
+#define WEBSERVER_H_
+
+#include <mongoose/mongoose.h>
+
+#include "core/base.h"
+#include "core/subsystem.h"
+#include "core/session.h"
+
+#include <string>
+
+#include <boost/ptr_container/ptr_map.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+
+namespace dss {
+
+  class IDeviceInterface;
+  class PropertyNode;
+  class WebServerPlugin;
+  class RestfulRequestHandler;
+
+  typedef boost::ptr_map<const int, Session> SessionByID;
+
+  class WebServer : public Subsystem {
+  private:
+    struct mg_context* m_mgContext;
+    int m_LastSessionID;
+    SessionByID m_Sessions;
+    boost::ptr_vector<WebServerPlugin> m_Plugins;
+    __gnu_cxx::hash_map<const std::string, RestfulRequestHandler*> m_Handlers;
+  private:
+    void setupAPI();
+    void loadPlugin(PropertyNode& _node);
+    void loadPlugins();
+    void instantiateHandlers();
+  protected:
+    void pluginCalled(struct mg_connection* _connection,
+                      const struct mg_request_info* _info,
+                      WebServerPlugin& plugin, 
+                      const std::string& _uri);
+
+    static void httpPluginCallback(struct mg_connection* _connection,
+                                   const struct mg_request_info* _info, 
+                                   void* _userData);
+    static void httpBrowseProperties(struct mg_connection* _connection,
+                                   const struct mg_request_info* _info, 
+                                   void* _userData);
+    static void jsonHandler(struct mg_connection* _connection,
+                            const struct mg_request_info* _info, 
+                            void* _userData);
+    static void downloadHandler(struct mg_connection* _connection,
+                            const struct mg_request_info* _info, 
+                            void* _userData);
+
+      static void emitHTTPHeader(int _code, struct mg_connection* _connection, const std::string& _contentType = "text/html");
+  protected:
+    virtual void doStart();
+  public:
+    WebServer(DSS* _pDSS);
+    ~WebServer();
+
+    virtual void initialize();
+
+  }; // WebServer
+
+}
+
+#endif /*WEBSERVER_H_*/
diff --git a/core/web/webserverapi.cpp b/core/web/webserverapi.cpp
new file mode 100644
index 0000000..3777640
--- /dev/null
+++ b/core/web/webserverapi.cpp
@@ -0,0 +1,339 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 "webserverapi.h"
+
+#include "restful.h"
+
+namespace dss {
+ 
+  RestfulAPI WebServerAPI::createRestfulAPI() {
+    RestfulAPI api;
+    RestfulClass& clsApartment = api.addClass("apartment")
+       .withDocumentation("A wrapper for global functions as well as adressing all devices connected to the dSS");
+    clsApartment.addMethod("getName")
+      .withDocumentation("Returns the name of the apartment");
+    clsApartment.addMethod("setName")
+      .withParameter("newName", "string", true)
+      .withDocumentation("Sets the name of the apartment to newName");
+    clsApartment.addMethod("turnOn")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Turns on all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("turnOff")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Turns off all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("increaseValue")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Increases the main value on all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("decreaseValue")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Decreases the main value on all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("enable")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Enables all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("disable")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Disables all devices of the apartment.", "A disabled device will react only to an enable call. If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("startDim")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("direction", "string", false)
+      .withDocumentation("Starts dimming the devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("endDim")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Stops dimming the devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("setValue")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("value", "integer", true)
+      .withDocumentation("Sets the output value of all devices of the apartment to value.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("callScene")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Calls the scene sceneNr on all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("saveScene")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Saves the current output value to sceneNr.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("undoScene")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Undos setting the value of sceneNr.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("getConsumption")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Returns the consumption of all devices in the apartment in mW.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsApartment.addMethod("getStructure")
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Returns an object containing the structure of the apartment.");
+    clsApartment.addMethod("getDevices")
+      .withParameter("unassigned", "boolean", false)
+      .withDocumentation("Returns the list of devices in the apartment.", "If unassigned is true, only devices that are not assigned to a zone get returned");
+    clsApartment.addStaticMethod("login")
+      .withDocumentation("Returns a session token");
+    clsApartment.addMethod("getCircuits")
+      .withDocumentation("Returns a list of the circuits present in the apartment");
+    clsApartment.addMethod("rescan")
+      .withDocumentation("Rescans all circuits of the apartment");
+
+    RestfulClass& clsZone = api.addClass("zone")
+        .withInstanceParameter("id", "integer", false)
+        .withInstanceParameter("name", "string", false)
+        .requireOneOf("id", "name");
+    clsZone.addMethod("getName")
+      .withDocumentation("Returns the name of the zone.");
+    clsZone.addMethod("setName")
+      .withParameter("newName", "string", true)
+      .withDocumentation("Sets the name of the zone to newName.");
+    clsZone.addMethod("turnOn")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Turns on all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("turnOff")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Turns off all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("increaseValue")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Increases the main value of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("decreaseValue")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Decreases the main value of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("enable")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Enables all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("disable")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Disables all devices in the zone.", "Disabled devices will react only to a enable call. If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("startDim")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("direction", "string", false)
+      .withDocumentation("Starts dimming the main value of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("endDim")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Stops dimming of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("setValue")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("value", "integer", true)
+      .withDocumentation("Sets the output value of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("callScene")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Sets the scene sceneNr on all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("saveScene")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Saves the current output value to sceneNr of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("undoScene")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Undos the setting of a scene value.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+    clsZone.addMethod("getConsumption")
+      .withParameter("groupID", "integer", false)
+      .withParameter("groupName", "string", false)
+      .withDocumentation("Returns the consumption of all devices in the zone in mW.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
+
+    RestfulClass& clsDevice = api.addClass("device")
+        .withInstanceParameter("dsid", "integer", false)
+        .withInstanceParameter("name", "string", false)
+        .requireOneOf("dsid", "name");
+    clsDevice.addMethod("getName")
+       .withDocumentation("Returns the name of the device");
+    clsDevice.addMethod("setName")
+      .withParameter("newName", "string", true)
+      .withDocumentation("Sets the name of the device to newName");
+    clsDevice.addMethod("getGroups")
+      .withDocumentation("Returns an array of groups the device is in");
+    clsDevice.addMethod("getState")
+      .withDocumentation("Returns the state of the device");
+    clsDevice.addMethod("getLocation")
+      .withDocumentation("Returns the location of the device.");
+    clsDevice.addMethod("setLocation")
+      .withParameter("x", "double", false)
+      .withParameter("y", "double", false)
+      .withParameter("z", "double", false)
+      .withDocumentation("Sets the location of the device.");
+    clsDevice.addMethod("turnOn")
+      .withDocumentation("Turns on the device.", "This will call SceneMax on the device.");
+    clsDevice.addMethod("turnOff")
+      .withDocumentation("Turns off the device.", "This will call SceneMin on the device.");
+    clsDevice.addMethod("increaseValue")
+      .withDocumentation("Increases the default value of the device.");
+    clsDevice.addMethod("decreaseValue")
+      .withDocumentation("Decreases the default value of the device.");
+    clsDevice.addMethod("enable")
+      .withDocumentation("Enables the device.");
+    clsDevice.addMethod("disable")
+      .withDocumentation("Disables the device.", "A disabled device will only react to enable calls.");
+    clsDevice.addMethod("startDim")
+      .withParameter("direction", "string", false)
+      .withDocumentation("Starts dimming the device.", "If direction equals 'up' it will dim up, otherwise down.");
+    clsDevice.addMethod("endDim")
+      .withDocumentation("Stops dimming.");
+    clsDevice.addMethod("setValue")
+      .withParameter("value", "double", true)
+      .withDocumentation("Sets the output value of the device to value");
+    clsDevice.addMethod("setRawValue")
+      .withParameter("value", "integer", true)
+      .withParameter("parameterID", "integer", true)
+      .withParameter("size", "integer", true)
+      .withDocumentation("Sets the value of register parameterID to value");
+    clsDevice.addMethod("callScene")
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Calls scene sceneNr on the device.");
+    clsDevice.addMethod("saveScene")
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Saves the current outputvalue to sceneNr.");
+    clsDevice.addMethod("undoScene")
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Undos saving the scene value for sceneNr");
+    clsDevice.addMethod("getConsumption")
+      .withDocumentation("Returns the consumption of the device in mW.", "Note that this works only for simulated devices at the moment.");
+
+
+    RestfulClass& clsCircuit = api.addClass("circuit")
+       .withInstanceParameter("id", "dsid", true);
+    clsCircuit.addMethod("getName")
+       .withDocumentation("Returns the name of the circuit.");
+    clsCircuit.addMethod("setName")
+       .withParameter("newName", "string", true)
+       .withDocumentation("Sets the name of the circuit to newName.");
+    clsCircuit.addMethod("getEnergyBorder")
+       .withDocumentation("Returns the energy borders (orange, red).");
+    clsCircuit.addMethod("getConsumption")
+       .withDocumentation("Returns the consumption of all connected devices in mW");
+    clsCircuit.addMethod("getEnergyMeterValue")
+       .withDocumentation("Returns the meter-value in Wh");
+    clsCircuit.addMethod("rescan")
+       .withDocumentation("Rescans the circuit");
+
+    RestfulClass& clsProp = api.addClass("property")
+        .withInstanceParameter("path", "string", true);
+    clsProp.addMethod("getString")
+        .withDocumentation("Returns the std::string value of the property", "This will fail if the property is not of type 'string'.");
+    clsProp.addMethod("getInteger")
+        .withDocumentation("Returns the integer value of the property", "This will fail if the property is not of type 'integer'.");
+    clsProp.addMethod("getBoolean")
+        .withDocumentation("Returns the boolean value of the property", "This will fail if the property is not of type 'boolean'.");
+    clsProp.addMethod("setString")
+        .withParameter("value", "string", true)
+        .withDocumentation("Sets the std::string value of the property", "This will fail if the property is not of type 'string'.");
+    clsProp.addMethod("setInteger")
+        .withParameter("value", "integer", true)
+        .withDocumentation("Sets the integer value of the property", "This will fail if the property is not of type 'integer'.");
+    clsProp.addMethod("setBoolean")
+        .withParameter("value", "boolean", true)
+        .withDocumentation("Sets the boolean value of the property", "This will fail if the property is not of type 'boolean'.");
+    clsProp.addMethod("getChildren")
+        .withParameter("value", "string", true)
+        .withDocumentation("Returns an array of the nodes children");
+    clsProp.addMethod("setString")
+        .withDocumentation("Returns the type of the node");
+
+    RestfulClass& clsEvent = api.addClass("event");
+    clsEvent.addMethod("raise")
+       .withParameter("name", "string", true)
+       .withParameter("context", "string", false)
+       .withParameter("location", "string", false)
+       .withDocumentation("Raises an event", "The context describes the source of the event. The location, if provided, defines where any action that is taken "
+           "by any subscription should happen.");
+
+    RestfulClass& clsSystem = api.addClass("system");
+    clsSystem.addMethod("version")
+      .withDocumentation("Returns the dss version",
+                         "This method returns the version std::string of the dss");
+
+    RestfulClass& clsSet = api.addClass("set")
+        .withInstanceParameter("self", "string", false);
+    clsSet.addMethod("fromApartment")
+        .withDocumentation("Creates a set that contains all devices of the apartment");
+    clsSet.addMethod("byZone")
+        .withParameter("zoneID", "integer", false)
+        .withParameter("zoneName", "string", false)
+        .withDocumentation("Restricts the set to the given zone");
+    clsSet.addMethod("byGroup")
+        .withParameter("groupID", "integer", false)
+        .withParameter("groupName", "integer", false)
+        .withDocumentation("Restricts the set to the given group");
+    clsSet.addMethod("byDSID")
+        .withParameter("dsid", "dsid", true)
+        .withDocumentation("Restricts the set to the given dsid");
+    clsSet.addMethod("add")
+        .withParameter("other", "string", true)
+        .withDocumentation("Combines the set self with other");
+    clsSet.addMethod("subtract")
+        .withParameter("other", "string", true)
+        .withDocumentation("Subtracts the set self from other");
+    clsSet.addMethod("turnOn")
+        .withDocumentation("Turns on all devices of the set.");
+    clsSet.addMethod("turnOff")
+        .withDocumentation("Turns off all devices of the set.");
+    clsSet.addMethod("increaseValue")
+        .withDocumentation("Increases the main value on all devices of the set.");
+    clsSet.addMethod("decreaseValue")
+        .withDocumentation("Decreases the main value on all devices of the set.");
+    clsSet.addMethod("enable")
+        .withDocumentation("Enables all devices of the set.");
+    clsSet.addMethod("disable")
+        .withDocumentation("Disables all devices of the set.", "A disabled device will react only to an enable call.");
+    clsSet.addMethod("startDim")
+      .withParameter("direction", "string", false)
+      .withDocumentation("Starts dimming the devices of the set.");
+    clsSet.addMethod("endDim")
+      .withDocumentation("Stops dimming the devices of the set.");
+    clsSet.addMethod("setValue")
+      .withParameter("value", "integer", true)
+      .withDocumentation("Sets the output value of all devices of the set to value.");
+    clsSet.addMethod("callScene")
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Calls the scene sceneNr on all devices of the set.");
+    clsSet.addMethod("saveScene")
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Saves the current output value to sceneNr.");
+    clsSet.addMethod("undoScene")
+      .withParameter("sceneNr", "integer", true)
+      .withDocumentation("Undoes setting the value of sceneNr.");
+    clsApartment.addMethod("getConsumption")
+      .withDocumentation("Returns the consumption of all devices in the set in mW.");
+    return api;
+  } // createRestfulAPI
+
+} // namespace dss
diff --git a/core/web/webserverapi.h b/core/web/webserverapi.h
new file mode 100644
index 0000000..dadd857
--- /dev/null
+++ b/core/web/webserverapi.h
@@ -0,0 +1,34 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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 WEBSERVERAPI_H
+#define WEBSERVERAPI_H
+
+namespace dss {
+
+  class RestfulAPI;
+  
+  class WebServerAPI {
+  public:
+    static RestfulAPI createRestfulAPI();
+  };
+}
+#endif // WEBSERVERAPI_H
diff --git a/core/webserver.cpp b/core/webserver.cpp
deleted file mode 100644
index 870c42c..0000000
--- a/core/webserver.cpp
+++ /dev/null
@@ -1,2014 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 "webserver.h"
-#include "logger.h"
-#include "model.h"
-#include "dss.h"
-#include "event.h"
-#include "unix/ds485proxy.h"
-#include "sim/dssim.h"
-#include "propertysystem.h"
-#include "foreach.h"
-#include "core/web/restful.h"
-#include "core/web/restfulapiwriter.h"
-#include "metering/metering.h"
-#include "metering/series.h"
-#include "metering/seriespersistence.h"
-#include "web/webserverplugin.h"
-#include "core/setbuilder.h"
-#include "core/structuremanipulator.h"
-
-#include <iostream>
-#include <sstream>
-
-#include <boost/shared_ptr.hpp>
-#include <boost/filesystem.hpp>
-
-namespace dss {
-  //============================================= WebServer
-
-  WebServer::WebServer(DSS* _pDSS)
-    : Subsystem(_pDSS, "WebServer"), m_mgContext(0)
-  {
-  } // ctor
-
-  WebServer::~WebServer() {
-    if (m_mgContext) {
-      mg_stop(m_mgContext);
-    }
-  } // dtor
-
-  void WebServer::initialize() {
-    Subsystem::initialize();
-
-    log("Starting Webserver...");
-    m_mgContext = mg_start();
-
-    getDSS().getPropertySystem().setStringValue(getConfigPropertyBasePath() + "webroot", getDSS().getWebrootDirectory(), true, false);
-    getDSS().getPropertySystem().setStringValue(getConfigPropertyBasePath() + "ports", "8080", true, false);
-
-    setupAPI();
-  } // initialize
-
-  void WebServer::loadPlugins() {
-    PropertyNodePtr pluginsNode = getDSS().getPropertySystem().getProperty(getConfigPropertyBasePath() + "plugins");
-    if(pluginsNode != NULL) {
-      log("Found plugins node, trying to loading plugins", lsInfo);
-      pluginsNode->foreachChildOf(*this, &WebServer::loadPlugin);
-    }
-  } // loadPlugins
-
-  void WebServer::loadPlugin(PropertyNode& _node) {
-    PropertyNodePtr pFileNode = _node.getProperty("file");
-    PropertyNodePtr pURINode = _node.getProperty("uri");
-
-    if(pFileNode == NULL) {
-      log("loadPlugin: Missing subnode name 'file' on node " + _node.getDisplayName(), lsError);
-      return;
-    }
-    if(pURINode == NULL) {
-      log("loadPlugin: Missing subnode 'uri on node " + _node.getDisplayName(), lsError);
-    }
-    WebServerPlugin* plugin = new WebServerPlugin(pURINode->getStringValue(), pFileNode->getStringValue());
-    try {
-      plugin->load();
-    } catch(std::runtime_error& e) {
-      delete plugin;
-      plugin = NULL;
-      log(std::string("Caught exception while loading: ") + e.what(), lsError);
-      return;
-    }
-    m_Plugins.push_back(plugin);
-
-    log("Registering " + pFileNode->getStringValue() + " for URI '" + pURINode->getStringValue() + "'");
-    mg_set_uri_callback(m_mgContext, pURINode->getStringValue().c_str(), &httpPluginCallback, plugin);
-  } // loadPlugin
-
-  void WebServer::setupAPI() {
-    RestfulAPI api;
-    RestfulClass& clsApartment = api.addClass("apartment")
-       .withDocumentation("A wrapper for global functions as well as adressing all devices connected to the dSS");
-    clsApartment.addMethod("getName")
-      .withDocumentation("Returns the name of the apartment");
-    clsApartment.addMethod("setName")
-      .withParameter("newName", "string", true)
-      .withDocumentation("Sets the name of the apartment to newName");
-    clsApartment.addMethod("turnOn")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Turns on all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("turnOff")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Turns off all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("increaseValue")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Increases the main value on all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("decreaseValue")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Decreases the main value on all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("enable")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Enables all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("disable")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Disables all devices of the apartment.", "A disabled device will react only to an enable call. If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("startDim")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("direction", "string", false)
-      .withDocumentation("Starts dimming the devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("endDim")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Stops dimming the devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("setValue")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("value", "integer", true)
-      .withDocumentation("Sets the output value of all devices of the apartment to value.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("callScene")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Calls the scene sceneNr on all devices of the apartment.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("saveScene")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Saves the current output value to sceneNr.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("undoScene")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Undos setting the value of sceneNr.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("getConsumption")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Returns the consumption of all devices in the apartment in mW.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsApartment.addMethod("getStructure")
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Returns an object containing the structure of the apartment.");
-    clsApartment.addMethod("getDevices")
-      .withParameter("unassigned", "boolean", false)
-      .withDocumentation("Returns the list of devices in the apartment.", "If unassigned is true, only devices that are not assigned to a zone get returned");
-    clsApartment.addStaticMethod("login")
-      .withDocumentation("Returns a session token");
-    clsApartment.addMethod("getCircuits")
-      .withDocumentation("Returns a list of the circuits present in the apartment");
-    clsApartment.addMethod("rescan")
-      .withDocumentation("Rescans all circuits of the apartment");
-
-    RestfulClass& clsZone = api.addClass("zone")
-        .withInstanceParameter("id", "integer", false)
-        .withInstanceParameter("name", "string", false)
-        .requireOneOf("id", "name");
-    clsZone.addMethod("getName")
-      .withDocumentation("Returns the name of the zone.");
-    clsZone.addMethod("setName")
-      .withParameter("newName", "string", true)
-      .withDocumentation("Sets the name of the zone to newName.");
-    clsZone.addMethod("turnOn")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Turns on all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("turnOff")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Turns off all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("increaseValue")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Increases the main value of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("decreaseValue")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Decreases the main value of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("enable")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Enables all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("disable")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Disables all devices in the zone.", "Disabled devices will react only to a enable call. If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("startDim")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("direction", "string", false)
-      .withDocumentation("Starts dimming the main value of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("endDim")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Stops dimming of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("setValue")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("value", "integer", true)
-      .withDocumentation("Sets the output value of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("callScene")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Sets the scene sceneNr on all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("saveScene")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Saves the current output value to sceneNr of all devices in the zone.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("undoScene")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Undos the setting of a scene value.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-    clsZone.addMethod("getConsumption")
-      .withParameter("groupID", "integer", false)
-      .withParameter("groupName", "string", false)
-      .withDocumentation("Returns the consumption of all devices in the zone in mW.", "If groupID or groupName are specified, only devices contained in this group will be addressed");
-
-    RestfulClass& clsDevice = api.addClass("device")
-        .withInstanceParameter("dsid", "integer", false)
-        .withInstanceParameter("name", "string", false)
-        .requireOneOf("dsid", "name");
-    clsDevice.addMethod("getName")
-       .withDocumentation("Returns the name of the device");
-    clsDevice.addMethod("setName")
-      .withParameter("newName", "string", true)
-      .withDocumentation("Sets the name of the device to newName");
-    clsDevice.addMethod("getGroups")
-      .withDocumentation("Returns an array of groups the device is in");
-    clsDevice.addMethod("getState")
-      .withDocumentation("Returns the state of the device");
-    clsDevice.addMethod("getLocation")
-      .withDocumentation("Returns the location of the device.");
-    clsDevice.addMethod("setLocation")
-      .withParameter("x", "double", false)
-      .withParameter("y", "double", false)
-      .withParameter("z", "double", false)
-      .withDocumentation("Sets the location of the device.");
-    clsDevice.addMethod("turnOn")
-      .withDocumentation("Turns on the device.", "This will call SceneMax on the device.");
-    clsDevice.addMethod("turnOff")
-      .withDocumentation("Turns off the device.", "This will call SceneMin on the device.");
-    clsDevice.addMethod("increaseValue")
-      .withDocumentation("Increases the default value of the device.");
-    clsDevice.addMethod("decreaseValue")
-      .withDocumentation("Decreases the default value of the device.");
-    clsDevice.addMethod("enable")
-      .withDocumentation("Enables the device.");
-    clsDevice.addMethod("disable")
-      .withDocumentation("Disables the device.", "A disabled device will only react to enable calls.");
-    clsDevice.addMethod("startDim")
-      .withParameter("direction", "string", false)
-      .withDocumentation("Starts dimming the device.", "If direction equals 'up' it will dim up, otherwise down.");
-    clsDevice.addMethod("endDim")
-      .withDocumentation("Stops dimming.");
-    clsDevice.addMethod("setValue")
-      .withParameter("value", "double", true)
-      .withDocumentation("Sets the output value of the device to value");
-    clsDevice.addMethod("setRawValue")
-      .withParameter("value", "integer", true)
-      .withParameter("parameterID", "integer", true)
-      .withParameter("size", "integer", true)
-      .withDocumentation("Sets the value of register parameterID to value");
-    clsDevice.addMethod("callScene")
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Calls scene sceneNr on the device.");
-    clsDevice.addMethod("saveScene")
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Saves the current outputvalue to sceneNr.");
-    clsDevice.addMethod("undoScene")
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Undos saving the scene value for sceneNr");
-    clsDevice.addMethod("getConsumption")
-      .withDocumentation("Returns the consumption of the device in mW.", "Note that this works only for simulated devices at the moment.");
-
-
-    RestfulClass& clsCircuit = api.addClass("circuit")
-       .withInstanceParameter("id", "dsid", true);
-    clsCircuit.addMethod("getName")
-       .withDocumentation("Returns the name of the circuit.");
-    clsCircuit.addMethod("setName")
-       .withParameter("newName", "string", true)
-       .withDocumentation("Sets the name of the circuit to newName.");
-    clsCircuit.addMethod("getEnergyBorder")
-       .withDocumentation("Returns the energy borders (orange, red).");
-    clsCircuit.addMethod("getConsumption")
-       .withDocumentation("Returns the consumption of all connected devices in mW");
-    clsCircuit.addMethod("getEnergyMeterValue")
-       .withDocumentation("Returns the meter-value in Wh");
-    clsCircuit.addMethod("rescan")
-       .withDocumentation("Rescans the circuit");
-
-    RestfulClass& clsProp = api.addClass("property")
-        .withInstanceParameter("path", "string", true);
-    clsProp.addMethod("getString")
-        .withDocumentation("Returns the std::string value of the property", "This will fail if the property is not of type 'string'.");
-    clsProp.addMethod("getInteger")
-        .withDocumentation("Returns the integer value of the property", "This will fail if the property is not of type 'integer'.");
-    clsProp.addMethod("getBoolean")
-        .withDocumentation("Returns the boolean value of the property", "This will fail if the property is not of type 'boolean'.");
-    clsProp.addMethod("setString")
-        .withParameter("value", "string", true)
-        .withDocumentation("Sets the std::string value of the property", "This will fail if the property is not of type 'string'.");
-    clsProp.addMethod("setInteger")
-        .withParameter("value", "integer", true)
-        .withDocumentation("Sets the integer value of the property", "This will fail if the property is not of type 'integer'.");
-    clsProp.addMethod("setBoolean")
-        .withParameter("value", "boolean", true)
-        .withDocumentation("Sets the boolean value of the property", "This will fail if the property is not of type 'boolean'.");
-    clsProp.addMethod("getChildren")
-        .withParameter("value", "string", true)
-        .withDocumentation("Returns an array of the nodes children");
-    clsProp.addMethod("setString")
-        .withDocumentation("Returns the type of the node");
-
-    RestfulClass& clsEvent = api.addClass("event");
-    clsEvent.addMethod("raise")
-       .withParameter("name", "string", true)
-       .withParameter("context", "string", false)
-       .withParameter("location", "string", false)
-       .withDocumentation("Raises an event", "The context describes the source of the event. The location, if provided, defines where any action that is taken "
-           "by any subscription should happen.");
-    
-    RestfulClass& clsSystem = api.addClass("system");
-    clsSystem.addMethod("version")
-      .withDocumentation("Returns the dss version", 
-                         "This method returns the version std::string of the dss");
-
-    RestfulClass& clsSet = api.addClass("set")
-        .withInstanceParameter("self", "string", false);
-    clsSet.addMethod("fromApartment")
-        .withDocumentation("Creates a set that contains all devices of the apartment");
-    clsSet.addMethod("byZone")
-        .withParameter("zoneID", "integer", false)
-        .withParameter("zoneName", "string", false)
-        .withDocumentation("Restricts the set to the given zone");
-    clsSet.addMethod("byGroup")
-        .withParameter("groupID", "integer", false)
-        .withParameter("groupName", "integer", false)
-        .withDocumentation("Restricts the set to the given group");
-    clsSet.addMethod("byDSID")
-        .withParameter("dsid", "dsid", true)
-        .withDocumentation("Restricts the set to the given dsid");
-    clsSet.addMethod("add")
-        .withParameter("other", "string", true)
-        .withDocumentation("Combines the set self with other");
-    clsSet.addMethod("subtract")
-        .withParameter("other", "string", true)
-        .withDocumentation("Subtracts the set self from other");
-    clsSet.addMethod("turnOn")
-        .withDocumentation("Turns on all devices of the set.");
-    clsSet.addMethod("turnOff")
-        .withDocumentation("Turns off all devices of the set.");
-    clsSet.addMethod("increaseValue")
-        .withDocumentation("Increases the main value on all devices of the set.");
-    clsSet.addMethod("decreaseValue")
-        .withDocumentation("Decreases the main value on all devices of the set.");
-    clsSet.addMethod("enable")
-        .withDocumentation("Enables all devices of the set.");
-    clsSet.addMethod("disable")
-        .withDocumentation("Disables all devices of the set.", "A disabled device will react only to an enable call.");
-    clsSet.addMethod("startDim")
-      .withParameter("direction", "string", false)
-      .withDocumentation("Starts dimming the devices of the set.");
-    clsSet.addMethod("endDim")
-      .withDocumentation("Stops dimming the devices of the set.");
-    clsSet.addMethod("setValue")
-      .withParameter("value", "integer", true)
-      .withDocumentation("Sets the output value of all devices of the set to value.");
-    clsSet.addMethod("callScene")
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Calls the scene sceneNr on all devices of the set.");
-    clsSet.addMethod("saveScene")
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Saves the current output value to sceneNr.");
-    clsSet.addMethod("undoScene")
-      .withParameter("sceneNr", "integer", true)
-      .withDocumentation("Undoes setting the value of sceneNr.");
-    clsApartment.addMethod("getConsumption")
-      .withDocumentation("Returns the consumption of all devices in the set in mW.");
-
-    RestfulAPIWriter::writeToXML(api, "doc/json_api.xml");
-  } // setupAPI
-
-  void WebServer::doStart() {
-    std::string ports = DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "ports");
-    log("Webserver: Listening on port(s) " + ports);
-    mg_set_option(m_mgContext, "ports", ports.c_str());
-
-    std::string aliases = std::string("/=") + DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "webroot");
-    log("Webserver: Configured aliases: " + aliases);
-    mg_set_option(m_mgContext, "aliases", aliases.c_str());
-
-    mg_set_uri_callback(m_mgContext, "/browse/*", &httpBrowseProperties, NULL);
-    mg_set_uri_callback(m_mgContext, "/json/*", &jsonHandler, NULL);
-    mg_set_uri_callback(m_mgContext, "/download/*", &downloadHandler, NULL);
-
-    loadPlugins();
-
-    log("Webserver started", lsInfo);
-  } // start
-
-  const char* httpCodeToMessage(const int _code) {
-    if(_code == 400) {
-      return "Bad Request";
-    } else if(_code == 401) {
-      return "Unauthorized\r\nWWW-Authenticate: Basic realm=\"dSS\"";
-    } else if(_code == 403) {
-      return "Forbidden";
-    } else if(_code == 500) {
-      return "Internal Server Error";
-    } else {
-      return "OK";
-    }
-  }
-
-  void WebServer::emitHTTPHeader(int _code, struct mg_connection* _connection, const std::string& _contentType) {
-    std::ostringstream sstream;
-    sstream << "HTTP/1.1 " << _code << ' ' << httpCodeToMessage(_code) << "\r\n";
-    sstream << "Content-Type: " << _contentType << "; charset=utf-8\r\n\r\n";
-    std::string tmp = sstream.str();
-    mg_write(_connection, tmp.c_str(), tmp.length());
-  } // emitHTTPHeader
-
-  HashMapConstStringString parseParameter(const char* _params) {
-    HashMapConstStringString result;
-    if(_params != NULL) {
-      vector<std::string> paramList = splitString(_params, '&');
-      for(vector<std::string>::iterator iParam = paramList.begin(); iParam != paramList.end(); ++iParam) {
-        vector<std::string> nameValue = splitString(*iParam, '=');
-        if(nameValue.size() != 2) {
-          result[*iParam] = "";
-        } else {
-          result[urlDecode(nameValue.at(0))] = urlDecode(nameValue.at(1));
-        }
-      }
-    }
-    return result;
-  } // parseParameter
-
-  std::string ToJSONValue(const int& _value) {
-    return intToString(_value);
-  } // toJSONValue(int)
-
-  std::string ToJSONValue(const double& _value) {
-    return doubleToString(_value);
-  } // toJSONValue(double)
-
-  std::string ToJSONValue(const bool& _value) {
-    if(_value) {
-      return "true";
-    } else {
-      return "false";
-    }
-  } // toJSONValue(bool)
-
-  std::string ToJSONValue(const std::string& _value) {
-    return std::string("\"") + _value + '"';
-  } // toJSONValue(const std::string&)
-
-  std::string ToJSONValue(const char* _value) {
-    return ToJSONValue(std::string(_value));
-  } // toJSONValue(const char*)
-
-  std::string WebServer::ResultToJSON(const bool _ok, const std::string& _message) {
-    std::ostringstream sstream;
-    sstream << "{ " << ToJSONValue("ok") << ":" << ToJSONValue(_ok);
-    if(!_message.empty()) {
-      sstream << ", " << ToJSONValue("message") << ":" << ToJSONValue(_message);
-    }
-    sstream << "}";
-    if(!_ok) {
-      log("JSON call failed: '" + _message + "'");
-    }
-    return sstream.str();
-  } // resultToJSON
-
-  std::string JSONOk(const std::string& _innerResult = "") {
-    std::ostringstream sstream;
-    sstream << "{ " << ToJSONValue("ok") << ":" << ToJSONValue(true);
-    if(!_innerResult.empty()) {
-      sstream << ", " << ToJSONValue("result")<<  ": " << _innerResult;
-    }
-    sstream << " }";
-    return sstream.str();
-  }
-
-  std::string ToJSONValue(const DeviceReference& _device) {
-    std::ostringstream sstream;
-    sstream << "{ \"id\": \"" << _device.getDSID().toString() << "\""
-            << ", \"isSwitch\": " << ToJSONValue(_device.hasSwitch())
-            << ", \"name\": " << ToJSONValue(_device.getDevice().getName())
-            << ", \"fid\": " << ToJSONValue(_device.getDevice().getFunctionID())
-            << ", \"circuitID\":" << ToJSONValue(_device.getDevice().getModulatorID())
-            << ", \"busID\":"  << ToJSONValue(_device.getDevice().getShortAddress())
-            << ", \"isPresent\":"  << ToJSONValue(_device.getDevice().isPresent())
-            << ", \"lastDiscovered\":"  << ToJSONValue(int(_device.getDevice().getLastDiscovered().secondsSinceEpoch()))
-            << ", \"firstSeen\":"  << ToJSONValue(int(_device.getDevice().getFirstSeen().secondsSinceEpoch()))
-            << ", \"on\": " << ToJSONValue(_device.isOn()) << " }";
-    return sstream.str();
-  } // toJSONValue(DeviceReference)
-
-  std::string ToJSONValue(const Set& _set, const std::string& _arrayName) {
-    std::ostringstream sstream;
-    sstream << ToJSONValue(_arrayName) << ":[";
-    bool firstDevice = true;
-    for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
-      const DeviceReference& d = _set.get(iDevice);
-      if(firstDevice) {
-        firstDevice = false;
-      } else {
-        sstream << ",";
-      }
-      sstream << ToJSONValue(d);
-    }
-    sstream << "]";
-    return sstream.str();
-  } // toJSONValue(Set,Name)
-
-  std::string ToJSONValue(const Group& _group) {
-    std::ostringstream sstream;
-    sstream << "{ " << ToJSONValue("id") << ": " << ToJSONValue(_group.getID()) << ",";
-    sstream << ToJSONValue("name") << ": " << ToJSONValue(_group.getName()) << ", ";
-    sstream << ToJSONValue("isPresent") << ": " << ToJSONValue(_group.isPresent()) << ", ";
-    sstream << ToJSONValue("devices") << ": [";
-    Set devices = _group.getDevices();
-    bool first = true;
-    for(int iDevice = 0; iDevice < devices.length(); iDevice++) {
-      if(!first) {
-        sstream << " , ";
-      } else {
-        first = false;
-      }
-      sstream << " { " << ToJSONValue("id") << ": " << ToJSONValue(devices[iDevice].getDSID().toString()) << " }";
-    }
-    sstream << "]} ";
-    return sstream.str();
-  } // toJSONValue(Group)
-
-  std::string ToJSONValue(Zone& _zone, bool _includeDevices = true) {
-    std::ostringstream sstream;
-    sstream << "{ \"id\": " << _zone.getID() << ",";
-    std::string name = _zone.getName();
-    if(name.size() == 0) {
-      name = std::string("Zone ") + intToString(_zone.getID());
-    }
-    sstream << ToJSONValue("name") << ": " << ToJSONValue(name) << ", ";
-    sstream << ToJSONValue("isPresent") << ": " << ToJSONValue(_zone.isPresent());
-    if(_zone.getFirstZoneOnModulator() != -1) {
-      sstream << ", " << ToJSONValue("firstZoneOnModulator") 
-              << ": " << ToJSONValue(_zone.getFirstZoneOnModulator());
-    }
-
-    if(_includeDevices) {
-      sstream << ", ";
-      Set devices = _zone.getDevices();
-      sstream << ToJSONValue(devices, "devices");
-      sstream << "," << ToJSONValue("groups") << ": [";
-      bool first = true;
-      foreach(Group* pGroup, _zone.getGroups()) {
-        if(!first) {
-          sstream << ",";
-        }
-        first = false;
-        sstream  << ToJSONValue(*pGroup);
-      }
-      sstream << "] ";
-    }
-
-    sstream << "} ";
-    return sstream.str();
-  } // toJSONValue(Zone)
-
-  std::string ToJSONValue(Apartment& _apartment) {
-  	std::ostringstream sstream;
-  	sstream << "{ \"apartment\": { \"zones\": [";
-	  vector<Zone*>& zones = _apartment.getZones();
-	  bool first = true;
-	  for(vector<Zone*>::iterator ipZone = zones.begin(), e = zones.end();
-	      ipZone != e; ++ipZone)
-	  {
-	  	Zone* pZone = *ipZone;
-	  	if(!first) {
-	  	  sstream << ", ";
-	  	} else {
-	  		first = false;
-	  	}
-	  	sstream << ToJSONValue(*pZone);
-	  }
-    sstream << "]} }";
-	  return sstream.str();
-  } // toJSONValue(Apartment)
-
-  Set GetUnassignedDevices() {
-    Apartment& apt = DSS::getInstance()->getApartment();
-    Set devices = apt.getZone(0).getDevices();
-
-    vector<Zone*>& zones = apt.getZones();
-    for(vector<Zone*>::iterator ipZone = zones.begin(), e = zones.end();
-        ipZone != e; ++ipZone)
-    {
-      Zone* pZone = *ipZone;
-      if(pZone->getID() == 0) {
-        // zone 0 holds all devices, so we're going to skip it
-        continue;
-      }
-
-      devices = devices.remove(pZone->getDevices());
-    }
-
-    return devices;
-  } // getUnassignedDevices
-
-  template<class t>
-  std::string ToJSONArray(const vector<t>& _v);
-
-  template<>
-  std::string ToJSONArray(const vector<int>& _v) {
-    std::ostringstream arr;
-    arr << "[";
-    bool first = true;
-    vector<int>::const_iterator iV;
-    vector<int>::const_iterator e;
-    for(iV = _v.begin(), e = _v.end();
-        iV != e; ++iV)
-    {
-      if(!first) {
-        arr << ",";
-      }
-      arr << ToJSONValue(*iV);
-      first = false;
-    }
-    arr << "]";
-    return arr.str();
-  } // toJSONArray<int>
-
-  std::string WebServer::callDeviceInterface(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, IDeviceInterface* _interface, Session* _session) {
-    bool ok = true;
-    std::string errorString;
-    assert(_interface != NULL);
-    if(endsWith(_method, "/turnOn")) {
-      _interface->turnOn();
-    } else if(endsWith(_method, "/turnOff")) {
-      _interface->turnOff();
-    } else if(endsWith(_method, "/increaseValue")) {
-      _interface->increaseValue();
-    } else if(endsWith(_method, "/decreaseValue")) {
-      _interface->decreaseValue();
-    } else if(endsWith(_method, "/enable")) {
-      _interface->enable();
-    } else if(endsWith(_method, "/disable")) {
-      _interface->disable();
-    } else if(endsWith(_method, "/startDim")) {
-      std::string direction = _parameter["direction"];
-      if(direction == "up") {
-        _interface->startDim(true);
-      } else {
-        _interface->startDim(false);
-      }
-    } else if(endsWith(_method, "/endDim")) {
-      _interface->endDim();
-    } else if(endsWith(_method, "/setValue")) {
-      int value = strToIntDef(_parameter["value"], -1);
-      if(value == -1) {
-        errorString = "invalid or missing parameter value: '" + _parameter["value"] + "'";
-        ok = false;
-      } else {
-        _interface->setValue(value);
-      }
-    } else if(endsWith(_method, "/callScene")) {
-      std::string sceneStr = _parameter["sceneNr"];
-      int sceneID = strToIntDef(sceneStr, -1);
-      if(sceneID != -1) {
-        _interface->callScene(sceneID);
-      } else {
-        errorString = "invalid sceneNr: '" + sceneStr + "'";
-        ok = false;
-      }
-    } else if(endsWith(_method, "/saveScene")) {
-      std::string sceneStr = _parameter["sceneNr"];
-      int sceneID = strToIntDef(sceneStr, -1);
-      if(sceneID != -1) {
-        _interface->saveScene(sceneID);
-      } else {
-        errorString = "invalid sceneNr: '" + sceneStr + "'";
-        ok = false;
-      }
-    } else if(endsWith(_method, "/undoScene")) {
-      std::string sceneStr = _parameter["sceneNr"];
-      int sceneID = strToIntDef(sceneStr, -1);
-      if(sceneID != -1) {
-        _interface->undoScene(sceneID);
-      } else {
-        errorString = "invalid sceneNr: '" + sceneStr + "'";
-        ok = false;
-      }
-    } else if(endsWith(_method, "/getConsumption")) {
-      return "{ " + ToJSONValue("consumption") + ": " +  uintToString(_interface->getPowerConsumption()) +"}";
-    }
-    return ResultToJSON(ok, errorString);
-  } // callDeviceInterface
-
-  bool WebServer::isDeviceInterfaceCall(const std::string& _method) {
-    return endsWith(_method, "/turnOn")
-        || endsWith(_method, "/turnOff")
-        || endsWith(_method, "/increaseValue")
-        || endsWith(_method, "/decreaseValue")
-        || endsWith(_method, "/enable")
-        || endsWith(_method, "/disable")
-        || endsWith(_method, "/startDim")
-        || endsWith(_method, "/endDim")
-        || endsWith(_method, "/setValue")
-        || endsWith(_method, "/callScene")
-        || endsWith(_method, "/saveScene")
-        || endsWith(_method, "/undoScene")
-        || endsWith(_method, "/getConsumption");
-  } // isDeviceInterfaceCall
-
-  std::string WebServer::handleApartmentCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    bool ok = true;
-    std::string errorMessage;
-    _handled = true;
-    if(endsWith(_method, "/getConsumption")) {
-      int accumulatedConsumption = 0;
-      foreach(Modulator* pModulator, getDSS().getApartment().getModulators()) {
-        accumulatedConsumption += pModulator->getPowerConsumption();
-      }
-      return "{ " + ToJSONValue("consumption") + ": " +  uintToString(accumulatedConsumption) +"}";
-    } else if(isDeviceInterfaceCall(_method)) {
-      IDeviceInterface* interface = NULL;
-      std::string groupName = _parameter["groupName"];
-      std::string groupIDString = _parameter["groupID"];
-      if(!groupName.empty()) {
-        try {
-          Group& grp = getDSS().getApartment().getGroup(groupName);
-          interface = &grp;
-        } catch(std::runtime_error& e) {
-          errorMessage = "Could not find group with name '" + groupName + "'";
-          ok = false;
-        }
-      } else if(!groupIDString.empty()) {
-        try {
-          int groupID = strToIntDef(groupIDString, -1);
-          if(groupID != -1) {
-            Group& grp = getDSS().getApartment().getGroup(groupID);
-            interface = &grp;
-          } else {
-            errorMessage = "Could not parse group id '" + groupIDString + "'";
-            ok = false;
-          }
-        } catch(std::runtime_error& e) {
-          errorMessage = "Could not find group with ID '" + groupIDString + "'";
-          ok = false;
-        }
-      }
-      if(ok) {
-        if(interface == NULL) {
-          interface = &getDSS().getApartment().getGroup(GroupIDBroadcast);
-        }
-        return callDeviceInterface(_method, _parameter, _connection, interface, _session);
-      } else {
-        std::ostringstream sstream;
-        sstream << "{ ok: " << ToJSONValue(ok) << ", message: " << ToJSONValue(errorMessage) << " }";
-        return sstream.str();
-      }
-    } else {
-      std::string result;
-      if(endsWith(_method, "/getStructure")) {
-        result = ToJSONValue(getDSS().getApartment());
-      } else if(endsWith(_method, "/getDevices")) {
-        Set devices;
-        if(_parameter["unassigned"].empty()) {
-          devices = getDSS().getApartment().getDevices();
-        } else {
-          devices = GetUnassignedDevices();
-        }
-
-        result = "{" + ToJSONValue(devices, "devices") + "}";
-      } else if(endsWith(_method, "/login")) {
-        int token = m_LastSessionID;
-        m_Sessions[token] = Session(token);
-        return "{" + ToJSONValue("token") + ": " + ToJSONValue(token) + "}";
-      } else if(endsWith(_method, "/getCircuits")) {
-        std::ostringstream sstream;
-        sstream << "{ " << ToJSONValue("circuits") << ": [";
-        bool first = true;
-        vector<Modulator*>& modulators = getDSS().getApartment().getModulators();
-        foreach(Modulator* modulator, modulators) {
-          if(!first) {
-            sstream << ",";
-          }
-          first = false;
-          sstream << "{ " << ToJSONValue("name") << ": " << ToJSONValue(modulator->getName());
-          sstream << ", " << ToJSONValue("dsid") << ": " << ToJSONValue(modulator->getDSID().toString());
-          sstream << ", " << ToJSONValue("busid") << ": " << ToJSONValue(modulator->getBusID());
-          sstream << ", " << ToJSONValue("hwVersion") << ": " << ToJSONValue(modulator->getHardwareVersion());
-          sstream << ", " << ToJSONValue("swVersion") << ": " << ToJSONValue(modulator->getSoftwareVersion());
-          sstream << ", " << ToJSONValue("hwName") << ": " << ToJSONValue(modulator->getHardwareName());
-          sstream << ", " << ToJSONValue("deviceType") << ": " << ToJSONValue(modulator->getDeviceType());
-          sstream << ", " << ToJSONValue("isPresent") << ": " << ToJSONValue(modulator->isPresent());
-          sstream << "}";
-        }
-        sstream << "]}";
-        return JSONOk(sstream.str());
-      } else if(endsWith(_method, "/getName")) {
-        std::ostringstream sstream;
-        sstream << "{" << ToJSONValue("name") << ":" << ToJSONValue(getDSS().getApartment().getName()) << "}";
-        return JSONOk(sstream.str());
-      } else if(endsWith(_method, "/setName")) {
-        getDSS().getApartment().setName(_parameter["newName"]);
-        result = ResultToJSON(true);
-      } else if(endsWith(_method, "/rescan")) {
-        std::vector<Modulator*> mods = getDSS().getApartment().getModulators();
-        foreach(Modulator* pModulator, mods) {
-          pModulator->setIsValid(false);
-        }
-        result = ResultToJSON(true);
-      } else {
-        _handled = false;
-      }
-      return result;
-    }
-  } // handleApartmentCall
-
-  std::string WebServer::handleZoneCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    bool ok = true;
-    std::string errorMessage;
-    _handled = true;
-    std::string zoneName = _parameter["name"];
-    std::string zoneIDString = _parameter["id"];
-    Zone* pZone = NULL;
-    if(!zoneIDString.empty()) {
-      int zoneID = strToIntDef(zoneIDString, -1);
-      if(zoneID != -1) {
-        try {
-          Zone& zone = getDSS().getApartment().getZone(zoneID);
-          pZone = &zone;
-        } catch(std::runtime_error& e) {
-          ok = false;
-          errorMessage = "Could not find zone with id '" + zoneIDString + "'";
-        }
-      } else {
-        ok = false;
-        errorMessage = "Could not parse id '" + zoneIDString + "'";
-      }
-    } else if(!zoneName.empty()) {
-      try {
-        Zone& zone = getDSS().getApartment().getZone(zoneName);
-        pZone = &zone;
-      } catch(std::runtime_error& e) {
-        ok = false;
-        errorMessage = "Could not find zone named '" + zoneName + "'";
-      }
-    } else {
-      ok = false;
-      errorMessage = "Need parameter name or id to identify zone";
-    }
-    if(ok) {
-      Group* pGroup = NULL;
-      std::string groupName = _parameter["groupName"];
-      std::string groupIDString = _parameter["groupID"];
-      if(!groupName.empty()) {
-        try {
-          pGroup = pZone->getGroup(groupName);
-          if(pGroup == NULL) {
-            // TODO: this might better be done by the zone
-            throw std::runtime_error("dummy");
-          }
-        } catch(std::runtime_error& e) {
-          errorMessage = "Could not find group with name '" + groupName + "'";
-          ok = false;
-        }
-      } else if(!groupIDString.empty()) {
-        try {
-          int groupID = strToIntDef(groupIDString, -1);
-          if(groupID != -1) {
-            pGroup = pZone->getGroup(groupID);
-            if(pGroup == NULL) {
-              // TODO: this might better be done by the zone
-              throw std::runtime_error("dummy");
-            }
-          } else {
-            errorMessage = "Could not parse group id '" + groupIDString + "'";
-            ok = false;
-          }
-        } catch(std::runtime_error& e) {
-          errorMessage = "Could not find group with ID '" + groupIDString + "'";
-          ok = false;
-        }
-      }
-      if(ok) {
-        if(isDeviceInterfaceCall(_method)) {
-          IDeviceInterface* interface = NULL;
-          if(pGroup != NULL) {
-            interface = pGroup;
-          }
-          if(ok) {
-            if(interface == NULL) {
-              interface = pZone;
-            }
-            return callDeviceInterface(_method, _parameter, _connection, interface, _session);
-          }
-        } else if(endsWith(_method, "/getLastCalledScene")) {
-          int lastScene = 0;
-          if(pGroup != NULL) {
-            lastScene = pGroup->getLastCalledScene();
-          } else if(pZone != NULL) {
-            lastScene = pZone->getGroup(0)->getLastCalledScene();
-          } else {
-            // should never reach here because ok, would be false
-            assert(false);
-          }
-          std::ostringstream sstream;
-          sstream << "{" << ToJSONValue("scene") << ":" << ToJSONValue(lastScene) << "}";
-          return JSONOk(sstream.str());
-        } else if(endsWith(_method, "/getName")) {
-          std::ostringstream sstream;
-          sstream << "{" << ToJSONValue("name") << ":" << ToJSONValue(pZone->getName()) << "}";
-          return JSONOk(sstream.str());
-        } else if(endsWith(_method, "/setName")) {
-          pZone->setName(_parameter["newName"]);
-          return ResultToJSON(true);
-        } else {
-          _handled = false;
-          return "";
-        }
-      }
-    }
-    if(!ok) {
-      return ResultToJSON(ok, errorMessage);
-    } else {
-      return "";
-    }
-  } // handleZoneCall
-
-  std::string WebServer::handleDeviceCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    bool ok = true;
-    std::string errorMessage;
-    _handled = true;
-    std::string deviceName = _parameter["name"];
-    std::string deviceDSIDString = _parameter["dsid"];
-    Device* pDevice = NULL;
-    if(!deviceDSIDString.empty()) {
-      dsid_t deviceDSID = dsid_t::fromString(deviceDSIDString);
-      if(!(deviceDSID == NullDSID)) {
-        try {
-          Device& device = getDSS().getApartment().getDeviceByDSID(deviceDSID);
-          pDevice = &device;
-        } catch(std::runtime_error& e) {
-          ok = false;
-          errorMessage = "Could not find device with dsid '" + deviceDSIDString + "'";
-        }
-      } else {
-        ok = false;
-        errorMessage = "Could not parse dsid '" + deviceDSIDString + "'";
-      }
-    } else if(!deviceName.empty()) {
-      try {
-        Device& device = getDSS().getApartment().getDeviceByName(deviceName);
-        pDevice = &device;
-      } catch(std::runtime_error&  e) {
-        ok = false;
-        errorMessage = "Could not find device named '" + deviceName + "'";
-      }
-    } else {
-      ok = false;
-      errorMessage = "Need parameter name or dsid to identify device";
-    }
-    if(ok) {
-      if(isDeviceInterfaceCall(_method)) {
-        return callDeviceInterface(_method, _parameter, _connection, pDevice, _session);
-      } else if(beginsWith(_method, "device/getGroups")) {
-        int numGroups = pDevice->getGroupsCount();
-        std::ostringstream sstream;
-        sstream << "{ " << ToJSONValue("groups") << ": [";
-        bool first = true;
-        for(int iGroup = 0; iGroup < numGroups; iGroup++) {
-          if(!first) {
-            sstream << ", ";
-          }
-          first = false;
-          try {
-            Group& group = pDevice->getGroupByIndex(iGroup);
-            sstream << "{ " << ToJSONValue("id") << ":" << group.getID();
-            if(!group.getName().empty()) {
-              sstream << ", " << ToJSONValue("name") << ":" << ToJSONValue(group.getName());
-            }
-          } catch(std::runtime_error&) {
-            log("Group only present at device level");
-          }
-          sstream << "}";
-        }
-        sstream << "]}";
-        return sstream.str();
-      } else if(beginsWith(_method, "device/getState")) {
-        std::ostringstream sstream;
-        sstream << "{ " << ToJSONValue("isOn") << ":" << ToJSONValue(pDevice->isOn()) << " }";
-        return JSONOk(sstream.str());
-      } else if(beginsWith(_method, "device/getName")) {
-        std::ostringstream sstream;
-        sstream << "{ " << ToJSONValue("name") << ":" << ToJSONValue(pDevice->getName()) << " }";
-        return JSONOk(sstream.str());
-      } else if(beginsWith(_method, "device/setName")) {
-        pDevice->setName(_parameter["newName"]);
-        return ResultToJSON(true);
-      } else if(beginsWith(_method, "device/setRawValue")) {
-        int value = strToIntDef(_parameter["value"], -1);
-        if(value == -1) {
-          return ResultToJSON(false, "Invalid or missing parameter 'value'");
-        }
-        int parameterID = strToIntDef(_parameter["parameterID"], -1);
-        if(parameterID == -1) {
-          return ResultToJSON(false, "Invalid or missing parameter 'parameterID'");
-        }
-        int size = strToIntDef(_parameter["size"], -1);
-        if(size == -1) {
-          return ResultToJSON(false, "Invalid or missing parameter 'size'");
-        }
-
-        pDevice->setRawValue(value, parameterID, size);
-        return JSONOk();
-      } else {
-        _handled = false;
-        return "";
-      }
-    } else {
-      return ResultToJSON(ok, errorMessage);
-    }
-  } // handleDeviceCall
-
-  std::string WebServer::handleCircuitCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    _handled = true;
-    std::string idString = _parameter["id"];
-    if(idString.empty()) {
-      return ResultToJSON(false, "missing parameter id");
-    }
-    dsid_t dsid = dsid_t::fromString(idString);
-    if(dsid == NullDSID) {
-      return ResultToJSON(false, "could not parse dsid");
-    }
-    try {
-      Modulator& modulator = getDSS().getApartment().getModulatorByDSID(dsid);
-      if(endsWith(_method, "circuit/getName")) {
-        return JSONOk("{ " + ToJSONValue("name") + ": " + ToJSONValue(modulator.getName()) + "}");
-      } else if(endsWith(_method, "circuit/setName")) {
-        modulator.setName(_parameter["newName"]);
-        return ResultToJSON(true);
-      } else if(endsWith(_method, "circuit/getEnergyBorder")) {
-        std::ostringstream sstream;
-        sstream << "{" << ToJSONValue("orange") << ":" << ToJSONValue(modulator.getEnergyLevelOrange());
-        sstream << "," << ToJSONValue("red") << ":" << ToJSONValue(modulator.getEnergyLevelRed());
-        sstream << "}";
-        return JSONOk(sstream.str());
-      } else if(endsWith(_method, "/getConsumption")) {
-        return JSONOk("{ " + ToJSONValue("consumption") + ": " +  uintToString(modulator.getPowerConsumption()) +"}");
-      } else if(endsWith(_method, "/getEnergyMeterValue")) {
-        return JSONOk("{ " + ToJSONValue("metervalue") + ": " +  uintToString(modulator.getEnergyMeterValue()) +"}");
-      } else if(endsWith(_method, "/rescan")) {
-        try {
-          getDSS().getApartment().scanModulator(modulator);
-          return ResultToJSON(true);
-        } catch(std::runtime_error& err) {
-          return ResultToJSON(false, err.what());
-        }
-      } else {
-        _handled = false;
-      }
-    } catch(std::runtime_error&) {
-      return ResultToJSON(false, "could not find modulator with given dsid");
-    }
-    return "";
-  } // handleCircuitCall
-
-
-  std::string WebServer::handleSetCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    _handled = true;
-    if(endsWith(_method, "/fromApartment")) {
-      _handled = true;
-      return JSONOk("{'self': '.'}");
-    } else {
-      std::string self = trim(_parameter["self"]);
-      if(self.empty()) {
-        return ResultToJSON(false, "missing parameter 'self'");
-      }
-
-      if(endsWith(_method, "/byZone")) {
-        std::string additionalPart;
-        if(self != ".") {
-          additionalPart = ".";
-        }
-        if(!_parameter["zoneID"].empty()) {
-          additionalPart += "zone(" + _parameter["zoneID"] + ")";
-        } else if(!_parameter["zoneName"].empty()) {
-          additionalPart += _parameter["zoneName"];
-        } else {
-          return ResultToJSON(false, "missing either zoneID or zoneName");
-        }
-
-        std::ostringstream sstream;
-        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
-        return JSONOk(sstream.str());
-      } else if(endsWith(_method, "/byGroup")) {
-        std::string additionalPart;
-        if(self != ".") {
-          additionalPart = ".";
-        }
-        if(!_parameter["groupID"].empty()) {
-          additionalPart += "group(" + _parameter["groupID"] + ")";
-        } else if(!_parameter["groupName"].empty()) {
-          additionalPart += _parameter["groupName"];
-        } else {
-          return ResultToJSON(false, "missing either groupID or groupName");
-        }
-
-        std::ostringstream sstream;
-        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
-        return JSONOk(sstream.str());
-      } else if(endsWith(_method, "/byDSID")) {
-        std::string additionalPart;
-        if(self != ".") {
-          additionalPart = ".";
-        }
-        if(!_parameter["dsid"].empty()) {
-          additionalPart += "dsid(" + _parameter["dsid"] + ")";
-        } else {
-          return ResultToJSON(false, "missing parameter dsid");
-        }
-
-        std::ostringstream sstream;
-        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
-        return JSONOk(sstream.str());
-      } else if(endsWith(_method, "/getDevices")) {
-        SetBuilder builder(getDSS().getApartment());
-        Set set = builder.buildSet(self, NULL);
-        return JSONOk("{" + ToJSONValue(set, "devices") + "}");
-      } else if(endsWith(_method, "/add")) {
-        std::string other = _parameter["other"];
-        if(other.empty()) {
-          return ResultToJSON(false, "missing parameter other");
-        }
-        std::string additionalPart;
-        if(self != ".") {
-          additionalPart = ".";
-        }
-        additionalPart += "add(" + other + ")";
-
-        std::ostringstream sstream;
-        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
-        return JSONOk(sstream.str());
-      } else if(endsWith(_method, "/subtract")) {
-        std::string other = _parameter["other"];
-        if(other.empty()) {
-          return ResultToJSON(false, "missing parameter other");
-        }
-        std::string additionalPart;
-        if(self != ".") {
-          additionalPart = ".";
-        }
-        additionalPart += "subtract(" + other + ")";
-
-        std::ostringstream sstream;
-        sstream << "{" << ToJSONValue("self") << ":" << ToJSONValue(self + additionalPart) << "}";
-        return JSONOk(sstream.str());
-      } else if(isDeviceInterfaceCall(_method)) {
-        SetBuilder builder(getDSS().getApartment());
-        Set set = builder.buildSet(self, NULL);
-        return callDeviceInterface(_method, _parameter, _connection, &set, _session);
-      } else {
-        _handled = false;
-      }
-
-    }
-    return "";
-  } // handleSetCall
-
-  std::string WebServer::handlePropertyCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    _handled = true;
-    std::string propName = _parameter["path"];
-    if(propName.empty()) {
-      return ResultToJSON(false, "Need parameter \'path\' for property operations");
-    }
-    PropertyNodePtr node = getDSS().getPropertySystem().getProperty(propName);
-
-    if(endsWith(_method, "/getString")) {
-      if(node == NULL) {
-        return ResultToJSON(false, "Could not find node named '" + propName + "'");
-      }
-      try {
-        std::ostringstream sstream;
-        sstream << "{ " << ToJSONValue("value") << ": " << ToJSONValue(node->getStringValue()) << "}";
-        return JSONOk(sstream.str());
-      } catch(PropertyTypeMismatch& ex) {
-        return ResultToJSON(false, std::string("Error getting property: '") + ex.what() + "'");
-      }
-    } else if(endsWith(_method, "/getInteger")) {
-      if(node == NULL) {
-        return ResultToJSON(false, "Could not find node named '" + propName + "'");
-      }
-      try {
-        std::ostringstream sstream;
-        sstream << "{ " << ToJSONValue("value") << ": " << ToJSONValue(node->getIntegerValue()) << "}";
-        return JSONOk(sstream.str());
-      } catch(PropertyTypeMismatch& ex) {
-        return ResultToJSON(false, std::string("Error getting property: '") + ex.what() + "'");
-      }
-    } else if(endsWith(_method, "/getBoolean")) {
-      if(node == NULL) {
-        return ResultToJSON(false, "Could not find node named '" + propName + "'");
-      }
-      try {
-        std::ostringstream sstream;
-        sstream << "{ " << ToJSONValue("value") << ": " << ToJSONValue(node->getBoolValue()) << "}";
-        return JSONOk(sstream.str());
-      } catch(PropertyTypeMismatch& ex) {
-        return ResultToJSON(false, std::string("Error getting property: '") + ex.what() + "'");
-      }
-    } else if(endsWith(_method, "/setString")) {
-      std::string value = _parameter["value"];
-      if(node == NULL) {
-        node = getDSS().getPropertySystem().createProperty(propName);
-      }
-      try {
-        node->setStringValue(value);
-      } catch(PropertyTypeMismatch& ex) {
-        return ResultToJSON(false, std::string("Error setting property: '") + ex.what() + "'");
-      }
-      return JSONOk();
-    } else if(endsWith(_method, "/setBoolean")) {
-      std::string strValue = _parameter["value"];
-      bool value;
-      if(strValue == "true") {
-        value = true;
-      } else if(strValue == "false") {
-        value = false;
-      } else {
-        return ResultToJSON(false, "Expected 'true' or 'false' for parameter 'value' but got: '" + strValue + "'");
-      }
-      if(node == NULL) {
-        node = getDSS().getPropertySystem().createProperty(propName);
-      }
-      try {
-        node->setBooleanValue(value);
-      } catch(PropertyTypeMismatch& ex) {
-        return ResultToJSON(false, std::string("Error setting property: '") + ex.what() + "'");
-      }
-      return JSONOk();
-    } else if(endsWith(_method, "/setInteger")) {
-      std::string strValue = _parameter["value"];
-      int value;
-      try {
-        value = strToInt(strValue);
-      } catch(...) {
-        return ResultToJSON(false, "Could not convert parameter 'value' to std::string. Got: '" + strValue + "'");
-      }
-      if(node == NULL) {
-        node = getDSS().getPropertySystem().createProperty(propName);
-      }
-      try {
-        node->setIntegerValue(value);
-      } catch(PropertyTypeMismatch& ex) {
-        return ResultToJSON(false, std::string("Error setting property: '") + ex.what() + "'");
-      }
-      return JSONOk();
-    } else if(endsWith(_method, "/getChildren")) {
-      if(node == NULL) {
-        return ResultToJSON(false, "Could not find node named '" + propName + "'");
-      }
-      std::ostringstream sstream;
-      sstream << "[";
-      bool first = true;
-      for(int iChild = 0; iChild < node->getChildCount(); iChild++) {
-        if(!first) {
-          sstream << ",";
-        }
-        first = false;
-        PropertyNodePtr cnode = node->getChild(iChild);
-        sstream << "{" << ToJSONValue("name") << ":" << ToJSONValue(cnode->getName());
-        sstream << "," << ToJSONValue("type") << ":" << ToJSONValue(getValueTypeAsString(cnode->getValueType()));
-        sstream << "}";
-      }
-      sstream << "]";
-      return JSONOk(sstream.str());
-    } else if(endsWith(_method, "/getType")) {
-      if(node == NULL) {
-        return ResultToJSON(false, "Could not find node named '" + propName + "'");
-      }
-      std::ostringstream sstream;
-      sstream << ":" << ToJSONValue("type") << ":" << ToJSONValue(getValueTypeAsString(node->getValueType())) << "}";
-      return JSONOk(sstream.str());
-    } else {
-      _handled = false;
-    }
-    return "";
-  } // handlePropertyCall
-
-  std::string WebServer::handleEventCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    _handled = true;
-    std::string result;
-    if(endsWith(_method, "/raise")) {
-      std::string name = _parameter["name"];
-      std::string location = _parameter["location"];
-      std::string context = _parameter["context"];
-      std::string parameter = _parameter["parameter"];
-
-      boost::shared_ptr<Event> evt(new Event(name));
-      if(!context.empty()) {
-        evt->setContext(context);
-      }
-      if(!location.empty()) {
-        evt->setLocation(location);
-      }
-      std::vector<std::string> params = dss::splitString(parameter, ';');
-      for(std::vector<std::string>::iterator iParam = params.begin(), e = params.end();
-          iParam != e; ++iParam)
-      {
-        std::vector<std::string> nameValue = dss::splitString(*iParam, '=');
-        if(nameValue.size() == 2) {
-          dss::Logger::getInstance()->log("WebServer::handleEventCall: Got parameter '" + nameValue[0] + "'='" + nameValue[1] + "'");
-          evt->setProperty(nameValue[0], nameValue[1]);
-        } else {
-          dss::Logger::getInstance()->log(std::string("Invalid parameter found WebServer::handleEventCall: ") + *iParam );
-        }
-      }
-      
-      getDSS().getEventQueue().pushEvent(evt);
-      return ResultToJSON(true);
-    } else {
-      _handled = false;
-    }
-    return result;
-  } // handleEventCall
-
-  std::string WebServer::handleSystemCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    _handled = true;
-    if(endsWith(_method, "/version")) {
-      return ResultToJSON(true, DSS::getInstance()->versionString());
-    } else {
-      _handled = false;
-      return std::string();
-    }
-  } // handleEventCall
-
-  std::string WebServer::handleStructureCall(const std::string& _method,
-                                        HashMapConstStringString& _parameter,
-                                        struct mg_connection* _connection,
-                                        bool& _handled,
-                                        Session* _session) {
-    _handled = true;
-    StructureManipulator manipulator(getDSS().getDS485Interface(), getDSS().getApartment());
-    if(endsWith(_method, "structure/zoneAddDevice")) {
-      std::string devidStr = _parameter["devid"];
-      if(!devidStr.empty()) {
-        dsid_t devid = dsid::fromString(devidStr);
-
-        Device& dev = DSS::getInstance()->getApartment().getDeviceByDSID(devid);
-        if(!dev.isPresent()) {
-          return ResultToJSON(false, "cannot add nonexisting device to a zone");
-        }
-
-        std::string zoneIDStr = _parameter["zone"];
-        if(!zoneIDStr.empty()) {
-          try {
-            int zoneID = strToInt(zoneIDStr);
-            DeviceReference devRef(dev, DSS::getInstance()->getApartment());
-            try {
-              Zone& zone = getDSS().getApartment().getZone(zoneID);
-              manipulator.addDeviceToZone(dev, zone);
-            } catch(ItemNotFoundException&) {
-              return ResultToJSON(false, "Could not find zone");
-            }
-          } catch(std::runtime_error& err) {
-            return ResultToJSON(false, err.what());
-          }
-        }
-        return ResultToJSON(true);
-      } else {
-        return ResultToJSON(false, "Need parameter devid");
-      }
-    } else if(endsWith(_method, "structure/addZone")) {
-      int zoneID = -1;
-
-      std::string zoneIDStr = _parameter["zoneID"];
-      if(!zoneIDStr.empty()) {
-        zoneID = strToIntDef(zoneIDStr, -1);
-      }
-      if(zoneID != -1) {
-        getDSS().getApartment().allocateZone(zoneID);
-      } else {
-        return ResultToJSON(false, "could not find zone");
-      }
-      return ResultToJSON(true, "");
-    } else if(endsWith(_method, "structure/removeZone")) {
-      int zoneID = -1;
-      
-      std::string zoneIDStr = _parameter["zoneID"];
-      if(!zoneIDStr.empty()) {
-        zoneID = strToIntDef(zoneIDStr, -1);
-      }
-      if(zoneID != -1) {
-        try {
-          Zone& zone = getDSS().getApartment().getZone(zoneID);
-          if(zone.getFirstZoneOnModulator() != -1) {
-            return ResultToJSON(false, "Cannot delete a primary zone");
-          }
-          if(zone.getDevices().length() > 0) {
-            return ResultToJSON(false, "Cannot delete a non-empty zone");
-          }
-          getDSS().getApartment().removeZone(zoneID);
-          getDSS().getApartment().addModelEvent(new ModelEvent(ModelEvent::etModelDirty));
-          return JSONOk();
-        } catch(ItemNotFoundException&) {
-          return ResultToJSON(false, "Could not find zone");
-        }
-      } else {
-        return ResultToJSON(false, "Missing parameter zoneID");
-      }
-    } else {
-      _handled = false;
-      return "";
-    }
-  } // handleStructureCall
-
-  std::string WebServer::handleSimCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    _handled = true;
-    if(beginsWith(_method, "sim/switch")) {
-      if(endsWith(_method, "/switch/pressed")) {
-        int buttonNr = strToIntDef(_parameter["buttonnr"], -1);
-        if(buttonNr == -1) {
-          return ResultToJSON(false, "Invalid button number");
-        }
-
-        int zoneID = strToIntDef(_parameter["zoneID"], -1);
-        if(zoneID == -1) {
-          return ResultToJSON(false, "Could not parse zoneID");
-        }
-        int groupID = strToIntDef(_parameter["groupID"], -1);
-        if(groupID == -1) {
-          return ResultToJSON(false, "Could not parse groupID");
-        }
-        try {
-          Zone& zone = getDSS().getApartment().getZone(zoneID);
-          Group* pGroup = zone.getGroup(groupID);
-
-          if(pGroup == NULL) {
-            return ResultToJSON(false, "Could not find group");
-          }
-
-          switch(buttonNr) {
-          case 1: // upper-left
-          case 3: // upper-right
-          case 7: // lower-left
-          case 9: // lower-right
-            break;
-          case 2: // up
-            pGroup->increaseValue();
-            break;
-          case 8: // down
-            pGroup->decreaseValue();
-            break;
-          case 4: // left
-            pGroup->previousScene();
-            break;
-          case 6: // right
-            pGroup->nextScene();
-            break;
-          case 5:
-            {
-              if(groupID == GroupIDGreen) {
-                getDSS().getApartment().getGroup(0).callScene(SceneBell);
-              } else if(groupID == GroupIDRed){
-                getDSS().getApartment().getGroup(0).callScene(SceneAlarm);
-              } else {
-                const int lastScene = pGroup->getLastCalledScene();
-                if(lastScene == SceneOff || lastScene == SceneDeepOff ||
-                   lastScene == SceneStandBy || lastScene == ScenePanic)
-                {
-                  pGroup->callScene(Scene1);
-                } else {
-                  pGroup->callScene(SceneOff);
-                }
-              }
-            }
-            break;
-          default:
-            return ResultToJSON(false, "Invalid button nr (range is 1..9)");
-          }
-        } catch(std::runtime_error&) {
-          return ResultToJSON(false, "Could not find zone");
-        }
-      } else {
-        _handled = false;
-        return "";
-      }
-    } else if(beginsWith(_method, "sim/addDevice")) {
-      std::string type = _parameter["type"];
-      std::string dsidStr = _parameter["dsid"];
-      // TODO: not finished yet ;)
-    } else {
-      _handled = false;
-    }
-    return "";
-  } // handleSimCall
-
-  std::string WebServer::handleDebugCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    _handled = true;
-    if(endsWith(_method, "/sendFrame")) {
-      int destination = strToIntDef(_parameter["destination"],0) & 0x3F;
-      bool broadcast = _parameter["broadcast"] == "true";
-      int counter = strToIntDef(_parameter["counter"], 0x00) & 0x03;
-      int command = strToIntDef(_parameter["command"], 0x09 /* request */) & 0x00FF;
-      int length = strToIntDef(_parameter["length"], 0x00) & 0x0F;
-
-      std::cout
-           << "sending frame: "
-           << "\ndest:    " << destination
-           << "\nbcst:    " << broadcast
-           << "\ncntr:    " << counter
-           << "\ncmd :    " << command
-           << "\nlen :    " << length << std::endl;
-
-      DS485CommandFrame* frame = new DS485CommandFrame();
-      frame->getHeader().setBroadcast(broadcast);
-      frame->getHeader().setDestination(destination);
-      frame->getHeader().setCounter(counter);
-      frame->setCommand(command);
-      for(int iByte = 0; iByte < length; iByte++) {
-        uint8_t byte = strToIntDef(_parameter[std::string("payload_") + intToString(iByte+1)], 0xFF);
-        std::cout << "b" << std::dec << iByte << ": " << std::hex << (int)byte << "\n";
-        frame->getPayload().add<uint8_t>(byte);
-      }
-      std::cout << std::dec << "done" << std::endl;
-      DS485Interface* intf = &DSS::getInstance()->getDS485Interface();
-      DS485Proxy* proxy = dynamic_cast<DS485Proxy*>(intf);
-      if(proxy != NULL) {
-        proxy->sendFrame(*frame);
-      } else {
-        delete frame;
-      }
-      return ResultToJSON(true);
-    } else if(endsWith(_method, "debug/dSLinkSend")) {
-      std::string deviceDSIDString = _parameter["dsid"];
-      Device* pDevice = NULL;
-      if(!deviceDSIDString.empty()) {
-        dsid_t deviceDSID = dsid_t::fromString(deviceDSIDString);
-        if(!(deviceDSID == NullDSID)) {
-          try {
-            Device& device = getDSS().getApartment().getDeviceByDSID(deviceDSID);
-            pDevice = &device;
-          } catch(std::runtime_error& e) {
-            return ResultToJSON(false ,"Could not find device with dsid '" + deviceDSIDString + "'");
-          }
-        } else {
-          return ResultToJSON(false, "Could not parse dsid '" + deviceDSIDString + "'");
-        }
-      } else {
-        return ResultToJSON(false, "Missing parameter 'dsid'");
-      }
-
-      int iValue = strToIntDef(_parameter["value"], -1);
-      if(iValue == -1) {
-        return ResultToJSON(false, "Missing parameter 'value'");
-      }
-      if(iValue < 0 || iValue > 0x00ff) {
-        return ResultToJSON(false, "Parameter 'value' is out of range (0-0xff)");
-      }
-      bool writeOnly = false;
-      bool lastValue = false;
-      if(_parameter["writeOnly"] == "true") {
-        writeOnly = true;
-      }
-      if(_parameter["lastValue"] == "true") {
-        lastValue = true;
-      }
-      uint8_t result;
-      try {
-        result = pDevice->dsLinkSend(iValue, lastValue, writeOnly);
-      } catch(std::runtime_error& e) {
-        return ResultToJSON(false, std::string("Error: ") + e.what());
-      }
-      if(writeOnly) {
-        return ResultToJSON(true);
-      } else {
-        std::ostringstream sstream;
-        sstream << "{" << ToJSONValue("value") << ":" << ToJSONValue(result) << "}";
-        return JSONOk(sstream.str());
-      }
-    } else if(endsWith(_method, "debug/pingDevice")) {
-      std::string deviceDSIDString = _parameter["dsid"];
-      if(deviceDSIDString.empty()) {
-        return ResultToJSON(false, "Missing parameter 'dsid'");
-      }
-      try {
-        dsid_t deviceDSID = dsid_t::fromString(deviceDSIDString);
-        Device& device = getDSS().getApartment().getDeviceByDSID(deviceDSID);
-        DS485CommandFrame* frame = new DS485CommandFrame();
-        frame->getHeader().setBroadcast(true);
-        frame->getHeader().setDestination(device.getModulatorID());
-        frame->setCommand(CommandRequest);
-        frame->getPayload().add<uint8_t>(FunctionDeviceGetTransmissionQuality);
-        frame->getPayload().add<uint16_t>(device.getShortAddress());
-        DS485Interface* intf = &DSS::getInstance()->getDS485Interface();
-        DS485Proxy* proxy = dynamic_cast<DS485Proxy*>(intf);
-        if(proxy != NULL) {
-          boost::shared_ptr<FrameBucketCollector> bucket = proxy->sendFrameAndInstallBucket(*frame, FunctionDeviceGetTransmissionQuality);
-          bucket->waitForFrame(2000);
-
-          boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
-          if(recFrame == NULL) {
-            return ResultToJSON(false, "No result received");
-          }
-          PayloadDissector pd(recFrame->getFrame()->getPayload());
-          pd.get<uint8_t>();
-          int errC = int(pd.get<uint16_t>());
-          if(errC < 0) {
-            return ResultToJSON(false, "dSM reported error-code: " + intToString(errC));
-          }
-          pd.get<uint16_t>(); // device address
-          int qualityHK = pd.get<uint16_t>();
-          int qualityRK = pd.get<uint16_t>();
-          std::ostringstream sstream;
-          sstream << "{" << ToJSONValue("qualityHK") << ":" << ToJSONValue(qualityHK) << ",";
-          sstream << ToJSONValue("qualityRK") << ":" << ToJSONValue(qualityRK) << "}";
-          return JSONOk(sstream.str());
-        } else {
-          delete frame;
-          return ResultToJSON(false, "Proxy has a wrong type or is null");
-        }              
-      } catch(ItemNotFoundException&) {
-        return ResultToJSON(false ,"Could not find device with dsid '" + deviceDSIDString + "'");
-      } catch(std::invalid_argument&) {
-        return ResultToJSON(false, "Could not parse dsid '" + deviceDSIDString + "'");
-      }
-    } else if(endsWith(_method, "debug/resetZone")) {
-      std::string zoneIDStr = _parameter["zoneID"];
-      int zoneID;
-      try {
-        zoneID = strToInt(zoneIDStr);
-      } catch(std::runtime_error&) {
-        return ResultToJSON(false, "Could not parse Zone ID");
-      }
-      DS485CommandFrame* frame = new DS485CommandFrame();
-      frame->getHeader().setBroadcast(true);
-      frame->getHeader().setDestination(0);
-      frame->setCommand(CommandRequest);
-      frame->getPayload().add<uint8_t>(FunctionZoneRemoveAllDevicesFromZone);
-      frame->getPayload().add<uint8_t>(zoneID);
-      DS485Interface* intf = &DSS::getInstance()->getDS485Interface();
-      DS485Proxy* proxy = dynamic_cast<DS485Proxy*>(intf);
-      if(proxy != NULL) {
-        proxy->sendFrame(*frame);
-        return ResultToJSON(true, "Please restart your dSMs");
-      } else {
-        delete frame;
-        return ResultToJSON(false, "Proxy has a wrong type or is null");
-      }
-    } else {
-      _handled = false;
-      return "";
-    }
-  } // handleDebugCall
-
-  std::string WebServer::handleMeteringCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session) {
-    if(endsWith(_method, "/getResolutions")) {
-      _handled = true;
-      std::vector<boost::shared_ptr<MeteringConfigChain> > meteringConfig = getDSS().getMetering().getConfig();
-      std::ostringstream sstream;
-      sstream << "{" << ToJSONValue("resolutions") << ":" << "[";
-      for(unsigned int iConfig = 0; iConfig < meteringConfig.size(); iConfig++) {
-        boost::shared_ptr<MeteringConfigChain> cConfig = meteringConfig[iConfig];
-        for(int jConfig = 0; jConfig < cConfig->size(); jConfig++) {
-          sstream << "{" << ToJSONValue("type") << ":" << (cConfig->isEnergy() ? ToJSONValue("energy") : ToJSONValue("consumption") ) << ","
-                  << ToJSONValue("unit") << ":" << ToJSONValue(cConfig->getUnit()) << ","
-                  << ToJSONValue("resolution") << ":" << ToJSONValue(cConfig->getResolution(jConfig)) << "}";
-          if(jConfig < cConfig->size() && iConfig < meteringConfig.size()) {
-            sstream << ",";
-          }
-        }
-      }
-      sstream << "]"  << "}";
-      return JSONOk(sstream.str());
-    } else if(endsWith(_method, "/getSeries")) {
-      _handled = true;
-      std::ostringstream sstream;
-      sstream << "{ " << ToJSONValue("series") << ": [";
-      bool first = true;
-      vector<Modulator*>& modulators = getDSS().getApartment().getModulators();
-      foreach(Modulator* modulator, modulators) {
-        if(!first) {
-          sstream << ",";
-        }
-        first = false;
-        sstream << "{ " << ToJSONValue("dsid") << ": " << ToJSONValue(modulator->getDSID().toString());
-        sstream << ", " << ToJSONValue("type") << ": " << ToJSONValue("energy");
-        sstream << "},";
-        sstream << "{ " << ToJSONValue("dsid") << ": " << ToJSONValue(modulator->getDSID().toString());
-        sstream << ", " << ToJSONValue("type") << ": " << ToJSONValue("consumption");
-        sstream << "}";
-      }
-      sstream << "]}";
-      return JSONOk(sstream.str());
-    } else if(endsWith(_method, "/getValues")) { //?dsid=;n=,resolution=,type=
-      _handled = true;
-      std::string errorMessage;
-      std::string deviceDSIDString = _parameter["dsid"];
-      std::string resolutionString = _parameter["resolution"];
-      std::string typeString = _parameter["type"];
-      std::string fileSuffix;
-      std::string storageLocation;
-      std::string seriesPath;
-      int resolution;
-      bool energy;
-      if(!deviceDSIDString.empty()) {
-        dsid_t deviceDSID = dsid_t::fromString(deviceDSIDString);
-        if(!(deviceDSID == NullDSID)) {
-          try {
-            getDSS().getApartment().getModulatorByDSID(deviceDSID);
-          } catch(std::runtime_error& e) {
-            return ResultToJSON(false, "Could not find device with dsid '" + deviceDSIDString + "'");
-          }
-        } else {
-         return ResultToJSON(false, "Could not parse dsid '" + deviceDSIDString + "'");
-        }
-      } else {
-        return ResultToJSON(false, "Could not parse dsid '" + deviceDSIDString + "'");
-      }
-      resolution = strToIntDef(resolutionString, -1);
-      if(resolution == -1) {
-        return ResultToJSON(false, "Need could not parse resolution '" + resolutionString + "'");
-      }
-      if(typeString.empty()) {
-        return ResultToJSON(false, "Need a type, 'energy' or 'consumption'");
-      } else {
-        if(typeString == "consumption") {
-          energy = false;
-        } else if(typeString == "energy") {
-          energy = true;
-        } else {
-          return ResultToJSON(false, "Invalide type '" + typeString + "'");
-        }
-      }
-      if(!resolutionString.empty()) {
-        std::vector<boost::shared_ptr<MeteringConfigChain> > meteringConfig = getDSS().getMetering().getConfig();
-        storageLocation = getDSS().getMetering().getStorageLocation();
-        for(unsigned int iConfig = 0; iConfig < meteringConfig.size(); iConfig++) {
-          boost::shared_ptr<MeteringConfigChain> cConfig = meteringConfig[iConfig];
-          for(int jConfig = 0; jConfig < cConfig->size(); jConfig++) {
-            if(cConfig->isEnergy() == energy && cConfig->getResolution(jConfig) == resolution) {
-              fileSuffix = cConfig->getFilenameSuffix(jConfig);
-            }
-          }
-        }
-        if(fileSuffix.empty()) {
-          return ResultToJSON(false, "No data for '" + typeString + "' and resolution '" + resolutionString + "'");
-        } else {
-          seriesPath = storageLocation + deviceDSIDString + "_" + fileSuffix + ".xml";
-          log("_Trying to load series from " + seriesPath);
-          if(boost::filesystem::exists(seriesPath)) {
-            SeriesReader<CurrentValue> reader;
-            boost::shared_ptr<Series<CurrentValue> > s = boost::shared_ptr<Series<CurrentValue> >(reader.readFromXML(seriesPath));
-            std::deque<CurrentValue>* values = s->getExpandedValues();
-            bool first = true;
-            std::ostringstream sstream;
-            sstream << "{ " ;
-            sstream << ToJSONValue("dsmid") << ":" << ToJSONValue(deviceDSIDString) << ",";
-            sstream << ToJSONValue("type") << ":" << ToJSONValue(typeString) << ",";
-            sstream << ToJSONValue("resolution") << ":" << ToJSONValue(resolutionString) << ",";
-            sstream << ToJSONValue("values") << ": [";
-            for(std::deque<CurrentValue>::iterator iValue = values->begin(), e = values->end(); iValue != e; iValue++)
-            {
-              if(!first) {
-                sstream << ",";
-              }
-              first = false;
-              sstream << "[" << iValue->getTimeStamp().secondsSinceEpoch()  << "," << iValue->getValue() << "]";
-            }
-            sstream << "]}";
-            delete values;
-            return JSONOk(sstream.str());
-          } else {
-            return ResultToJSON(false, "No data-file for '" + typeString + "' and resolution '" + resolutionString + "'");
-          }
-        }
-      } else {
-        return ResultToJSON(false, "Could not parse resolution '" + resolutionString + "'");
-      }
-    } else if(endsWith(_method, "/getAggregatedValues")) { //?set=;n=,resolution=;type=
-      _handled = false;
-      return "";
-    }
-    _handled = false;
-    return "";
-  } // handleMeteringCall
-
-  void WebServer::httpPluginCallback(struct mg_connection* _connection,
-                                     const struct mg_request_info* _info,
-                                     void* _userData) {
-    if(_userData != NULL) {
-      WebServerPlugin* plugin = static_cast<WebServerPlugin*>(_userData);
-      WebServer& self = DSS::getInstance()->getWebServer();
-
-      std::string uri = _info->uri;
-      self.log("Plugin: Processing call to " + uri);
-
-      self.pluginCalled(_connection, _info, *plugin, uri);
-    }
-  } // httpPluginCallback
-
-  void WebServer::pluginCalled(struct mg_connection* _connection,
-                               const struct mg_request_info* _info,
-                               WebServerPlugin& plugin,
-                               const std::string& _uri) {
-    HashMapConstStringString paramMap = parseParameter(_info->query_string);
-
-    std::string result;
-    if(plugin.handleRequest(_uri, paramMap, getDSS(), result)) {
-      emitHTTPHeader(200, _connection, "text/plain");
-      mg_write(_connection, result.c_str(), result.length());
-    } else {
-      emitHTTPHeader(500, _connection, "text/plain");
-      mg_printf(_connection, "error");
-    }
-  } // pluginCalled
-
-  void WebServer::jsonHandler(struct mg_connection* _connection,
-                              const struct mg_request_info* _info,
-                              void* _userData) {
-    const std::string urlid = "/json/";
-    std::string uri = _info->uri;
-
-    HashMapConstStringString paramMap = parseParameter(_info->query_string);
-
-    std::string method = uri.substr(uri.find(urlid) + urlid.size());
-
-    WebServer& self = DSS::getInstance()->getWebServer();
-    self.log("Processing call to " + method);
-
-    Session* session = NULL;
-    std::string tokenStr = paramMap["token"];
-    if(!tokenStr.empty()) {
-      int token = strToIntDef(tokenStr, -1);
-      if(token != -1) {
-        SessionByID::iterator iEntry = self.m_Sessions.find(token);
-        if(iEntry != self.m_Sessions.end()) {
-          if(iEntry->second->isStillValid()) {
-            Session& s = *iEntry->second;
-            session = &s;
-          }
-        }
-      }
-    }
-
-    std::string result;
-    bool handled = false;
-    if(beginsWith(method, "apartment/")) {
-      result = self.handleApartmentCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "zone/")) {
-      result = self.handleZoneCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "device/")) {
-      result = self.handleDeviceCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "circuit/")) {
-      result = self.handleCircuitCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "set/")) {
-      result = self.handleSetCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "property/")) {
-      result = self.handlePropertyCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "event/")) {
-      result = self.handleEventCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "system/")) {
-      result = self.handleSystemCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "structure/")) {
-      result = self.handleStructureCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "sim/")) {
-      result = self.handleSimCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "debug/")) {
-      result = self.handleDebugCall(method, paramMap, _connection, handled, session);
-    } else if(beginsWith(method, "metering/")) {
-      result = self.handleMeteringCall(method, paramMap, _connection, handled, session);
-    }
-
-    if(!handled) {
-      emitHTTPHeader(404, _connection, "application/json");
-      std::ostringstream sstream;
-      sstream << "{" << ToJSONValue("ok") << ":" << ToJSONValue(false) << ",";
-      sstream << ToJSONValue("message") << ":" << ToJSONValue("Call to unknown function");
-      sstream << "}";
-      result = sstream.str();
-      self.log("Unknown function '" + method + "'", lsError);
-    } else {
-      emitHTTPHeader(200, _connection, "application/json");
-    }
-    mg_write(_connection, result.c_str(), result.length());
-  } // jsonHandler
-
-  void WebServer::downloadHandler(struct mg_connection* _connection,
-                                  const struct mg_request_info* _info, 
-                                  void* _userData) {
-    const std::string kURLID = "/download/";
-    std::string uri = _info->uri;
-
-    std::string givenFileName = uri.substr(uri.find(kURLID) + kURLID.size());
-
-    WebServer& self = DSS::getInstance()->getWebServer();
-    self.log("Processing call to download/" + givenFileName);
-
-    // TODO: make the files-node readonly as this might pose a security threat
-    //       (you could download any file on the disk if you add it as a subnode
-    //        of files)
-    PropertyNodePtr filesNode = self.getDSS().getPropertySystem().getProperty(
-                                    self.getConfigPropertyBasePath() + "files"
-                                );
-    std::string fileName;
-    if(filesNode != NULL) {
-      PropertyNodePtr fileNode = filesNode->getProperty(givenFileName);
-      if(fileNode != NULL) {
-        fileName = fileNode->getStringValue();
-      }
-    }
-    self.log("Using local file: " + fileName);
-    struct mgstat st;
-    if(mg_stat(fileName.c_str(), &st) != 0) {
-      self.log("Not found");
-      memset(&st, '\0', sizeof(st));
-    }
-    mg_send_file(_connection, fileName.c_str(), &st);
-  } // downloadHandler
-
-  void WebServer::httpBrowseProperties(struct mg_connection* _connection,
-                                       const struct mg_request_info* _info,
-                                       void* _userData) {
-    emitHTTPHeader(200, _connection);
-
-    const std::string urlid = "/browse";
-    std::string uri = _info->uri;
-    HashMapConstStringString paramMap = parseParameter(_info->query_string);
-
-    std::string path = uri.substr(uri.find(urlid) + urlid.size());
-    if(path.empty()) {
-      path = "/";
-    }
-    mg_printf(_connection, "<html><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><body>");
-
-    std::ostringstream stream;
-    stream << "<h1>" << path << "</h1>";
-    stream << "<ul>";
-    PropertyNodePtr node = DSS::getInstance()->getPropertySystem().getProperty(path);
-    if(node != NULL) {
-      for(int iNode = 0; iNode < node->getChildCount(); iNode++) {
-        PropertyNodePtr cnode = node->getChild(iNode);
-
-        stream << "<li>";
-        if(cnode->getChildCount() != 0) {
-          stream << "<a href=\"/browse" << path << "/" << cnode->getDisplayName() << "\">" << cnode->getDisplayName() << "</a>";
-        } else {
-          stream << cnode->getDisplayName();
-        }
-        stream << " : ";
-        stream << getValueTypeAsString(cnode->getValueType()) << " : ";
-        switch(cnode->getValueType()) {
-        case vTypeBoolean:
-          stream << cnode->getBoolValue();
-          break;
-        case vTypeInteger:
-          stream << cnode->getIntegerValue();
-          break;
-        case vTypeNone:
-          break;
-        case vTypeString:
-          stream << cnode->getStringValue();
-          break;
-        default:
-          stream << "unknown value";
-        }
-      }
-    }
-
-    stream << "</ul></body></html>";
-    std::string tmp = stream.str();
-    mg_write(_connection, tmp.c_str(), tmp.length());
-  } // httpBrowseProperties
-
-}
diff --git a/core/webserver.h b/core/webserver.h
deleted file mode 100644
index c01ff17..0000000
--- a/core/webserver.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 WEBSERVER_H_
-#define WEBSERVER_H_
-
-#include <mongoose/mongoose.h>
-
-#include "base.h"
-#include "subsystem.h"
-#include "session.h"
-
-#include <string>
-
-#include <boost/ptr_container/ptr_map.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
-
-namespace dss {
-
-  class IDeviceInterface;
-  class PropertyNode;
-  class WebServerPlugin;
-
-  typedef boost::ptr_map<const int, Session> SessionByID;
-
-  class WebServer : public Subsystem {
-  private:
-    struct mg_context* m_mgContext;
-    int m_LastSessionID;
-    SessionByID m_Sessions;
-    boost::ptr_vector<WebServerPlugin> m_Plugins;
-  private:
-    void setupAPI();
-    void loadPlugin(PropertyNode& _node);
-    void loadPlugins();
-    std::string ResultToJSON(const bool _ok, const std::string& _message = "");
-  protected:
-    bool isDeviceInterfaceCall(const std::string& _method);
-    std::string callDeviceInterface(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, IDeviceInterface* _interface, Session* _session);
-
-    std::string handleApartmentCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleZoneCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleDeviceCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleSetCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handlePropertyCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleEventCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleSystemCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleCircuitCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleStructureCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleSimCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleDebugCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    std::string handleMeteringCall(const std::string& _method, HashMapConstStringString& _parameter, struct mg_connection* _connection, bool& _handled, Session* _session);
-    void pluginCalled(struct mg_connection* _connection, 
-                      const struct mg_request_info* _info,
-                      WebServerPlugin& plugin, 
-                      const std::string& _uri);
-
-    static void httpPluginCallback(struct mg_connection* _connection,
-                                   const struct mg_request_info* _info, 
-                                   void* _userData);
-    static void httpBrowseProperties(struct mg_connection* _connection,
-                                   const struct mg_request_info* _info, 
-                                   void* _userData);
-    static void jsonHandler(struct mg_connection* _connection,
-                            const struct mg_request_info* _info, 
-                            void* _userData);
-    static void downloadHandler(struct mg_connection* _connection,
-                            const struct mg_request_info* _info, 
-                            void* _userData);
-
-      static void emitHTTPHeader(int _code, struct mg_connection* _connection, const std::string& _contentType = "text/html");
-  protected:
-    virtual void doStart();
-  public:
-    WebServer(DSS* _pDSS);
-    ~WebServer();
-
-    virtual void initialize();
-
-  }; // WebServer
-
-}
-
-#endif /*WEBSERVER_H_*/
diff --git a/core/xmlwrapper.cpp b/core/xmlwrapper.cpp
deleted file mode 100644
index 4d33dfa..0000000
--- a/core/xmlwrapper.cpp
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 "xmlwrapper.h"
-
-#include <fstream>
-
-#include <boost/filesystem.hpp>
-
-namespace dss {
-  //============================================= XMLNode
-
-  XMLNode::XMLNode()
-  {
-    initialize();
-  } // ctor()
-
-  XMLNode::XMLNode(const XMLNode& _other)
-  {
-    initialize();
-    copyFrom(_other);
-  } // ctor(copy)
-
-  XMLNode::XMLNode(xmlNode* _node)
-  {
-    initialize();
-    m_pNode = _node;
-    assertHasNode("XMLNode::ctor(xmlNode*): Node must not be NULL");
-  } // ctor(xmlNode*)
-
-  void XMLNode::initialize() {
-    m_pNode = NULL;
-    m_AttributesRead = false;
-    m_ChildrenRead = false;
-  } // initialize
-
-  void XMLNode::copyFrom(const XMLNode& _other) {
-    m_pNode = _other.m_pNode;
-    m_Children = _other.m_Children;
-    m_ChildrenRead = _other.m_ChildrenRead;
-    if(_other.m_Attributes.size() > 0) {
-      m_Attributes = _other.m_Attributes;
-    } else {
-      m_Attributes.clear();
-    }
-    m_AttributesRead = _other.m_AttributesRead;
-  } // copyFrom
-
-  const std::string XMLNode::getName() {
-    assertHasNode("Can't get name without node");
-#ifdef USE_LIBXML
-    const char* name = (const char*)m_pNode->name;
-#else
-    const char* name = m_pNode->pName;
-#endif
-    return name;
-  }
-
-  const std::string XMLNode::getContent() {
-    assertHasNode("Can't get content without node");
-#ifdef USE_LIBXML
-    const char* content = (const char*)m_pNode->content;
-#else
-    const char* content = (const char*)m_pNode->pValue;
-#endif
-    return content;
-  }
-
-  void XMLNode::assertHasNode(const std::string& _reason) {
-    if(m_pNode == NULL) {
-      throw XMLException(_reason);
-    }
-  }
-
-  XMLNodeList& XMLNode::getChildren() {
-    assertHasNode("Can't return children without node");
-
-    if(!m_ChildrenRead) {
-#ifdef USE_LIBXML
-      xmlNode* child = m_pNode->children;
-      while(child != NULL) {
-        XMLNode childObj(child);
-        m_Children.push_back(childObj);
-        child = child->next;
-      }
-#else
-      lstSeek(m_pNode->subElementList, 0);
-      PElement elem = static_cast<PElement>(lstGet(m_pNode->subElementList));
-      while(elem != NULL) {
-        XMLNode childObj(elem);
-        m_Children.push_back(childObj);
-
-        lstNext(m_pNode->subElementList);
-        elem = static_cast<PElement>(lstGet(m_pNode->subElementList));
-      }
-#endif
-      m_ChildrenRead = true;
-    }
-    return m_Children;
-  }
-
-  XMLNode& XMLNode::getChildByName(const std::string& _name) {
-    XMLNodeList& children = getChildren();
-    for(XMLNodeList::iterator it = children.begin(); it != children.end(); ++it) {
-      if(it->getName() == _name) {
-        return *it;
-      }
-    }
-    throw XMLException("Could not find node");
-  } // getChildByName
-
-  bool XMLNode::hasChildWithName(const std::string& _name) {
-    XMLNodeList& children = getChildren();
-    for(XMLNodeList::iterator it = children.begin(); it != children.end(); ++it) {
-      if(it->getName() == _name) {
-        return true;
-      }
-    }
-    return false;
-  } // hasChildWithName
-
-  XMLNode& XMLNode::addChildNode(const std::string& _name, const std::string& _content) {
-    assertHasNode("Need a node to append a child to");
-
-    if(_name.size() == 0) {
-      throw XMLException("XMLNode::addChildNode: parameter _name must not be empty");
-    }
-   /* XMLNode result(xmlNewChild(m_pNode, NULL, _name.c_str(), _content.c_str()));
-    m_Children.push_back(result);
-    return m_Children[m_Children.size()];
-    */
-    throw XMLException("XMLNode::addChildNode: parameter _name must not be empty");
-  } // addChildNode
-
-  HashMapConstStringString& XMLNode::getAttributes() {
-    assertHasNode("Can't return children without node");
-
-    if(!m_AttributesRead) {
-#ifdef USE_LIBXML
-      xmlAttr* currAttr = m_pNode->properties;
-      while(currAttr != NULL) {
-        if(currAttr->type == XML_ATTRIBUTE_NODE) {
-          const char* name = (const char*)currAttr->name;
-          const char* value = (const char*)currAttr->children->content;
-
-          m_Attributes[name] = value;
-        }
-        currAttr = currAttr->next;
-      }
-#else
-      lstSeek(m_pNode->attributeList, 0);
-      PAttribute attr = static_cast<PAttribute>(lstGet(m_pNode->attributeList));
-      while(attr != NULL) {
-        const char* name = attr->pName;
-        const char* value = attr->pValue;
-
-        m_Attributes[name] = value;
-        lstNext(m_pNode->attributeList);
-        attr = static_cast<PAttribute>(lstGet(m_pNode->attributeList));
-      }
-#endif
-      m_AttributesRead = true;
-    }
-    return m_Attributes;
-  }
-
-  //============================================= XMLDocument
-
-  XMLDocument::XMLDocument(xmlDoc* _pDocument)
-  : ResourceHolder<xmlDoc>(_pDocument)
-  {
-    if(m_Resource != NULL) {
-#ifdef USE_LIBXML
-      m_RootNode = XMLNode(xmlDocGetRootElement(m_Resource));
-#else
-      lstSeek(_pDocument, 0);
-      m_RootNode = XMLNode(static_cast<PElement>(lstGet(_pDocument)));
-#endif
-    }
-  } // ctor(xmlDoc*)
-
-  XMLDocument::XMLDocument(XMLDocument& _other)
-  : ResourceHolder<xmlDoc>(_other),
-  m_RootNode(_other.m_RootNode)
-  {
-  } // ctor(copy)
-
-  XMLDocument::~XMLDocument() {
-    if(m_Resource != NULL) {
-#ifdef USE_LIBXML
-      xmlFreeDoc(m_Resource);
-#else
-      lstDeinit(m_Resource);
-#endif
-      m_Resource = NULL;
-    }
-  }
-
-  XMLNode& XMLDocument::getRootNode() {
-    return m_RootNode;
-  } // getRootNode
-
-
-  void XMLDocument::saveToFile(const std::string& _fileName) {
-    FILE* out = fopen(_fileName.c_str(), "w");
-    if(out == NULL) {
-      throw XMLException(std::string("XMLDocumen::saveToFile: Could not open file ") + _fileName);
-    }
-#ifdef USE_LIBXML
-    if(xmlDocDump(out, m_Resource) < 0) {
-      throw XMLException(std::string("XMLDocumen::saveToFile: xmlDocDump failed for file:") + _fileName);
-    }
-#endif
-  }
-
-  //============================================= XMLDocumentFileReader
-
-  XMLDocumentFileReader::XMLDocumentFileReader(const std::string& _uri)
-  : m_URI(_uri)
-  {
-  }
-
-  XMLDocumentReader::~XMLDocumentReader() {
-  }
-
-  XMLDocument& XMLDocumentFileReader::getDocument() {
-    if(!boost::filesystem::exists(m_URI.c_str())) {
-      throw XMLException(std::string("XMLDocumentFileReader::getDocument: File '") + m_URI + "' does not exist");
-    }
-
-#ifdef USE_LIBXML
-    xmlDoc* doc = xmlParseFile(m_URI.c_str());
-    if(doc == NULL) {
-      throw XMLException(std::string("Could not parse file: ") + m_URI);
-    }
-
-    XMLDocument docObj(doc);
-    m_Document = docObj;
-#else
-    ifstream f(m_URI.c_str());
-    std::string str((istreambuf_iterator<char>(f)), istreambuf_iterator<char>());
-
-    PScanner scanner;
-    scanner = scnInit();
-    scanner->buf = str.c_str();
-    scanner->bufLength = str.size();
-    xmlDoc* doc = xmlParseXML(scanner);
-    XMLDocument docObj(doc);
-    m_Document = docObj;
-#endif
-    return m_Document;
-  }
-
-}
diff --git a/core/xmlwrapper.h b/core/xmlwrapper.h
deleted file mode 100644
index 6be7fb3..0000000
--- a/core/xmlwrapper.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 _XML_WRAPPER_H_INCLUDED
-#define _XML_WRAPPER_H_INCLUDED
-
-#include "base.h"
-
-#ifndef USE_LIBXML
-  #include "xml/list.h"
-  #include "xml/xmlparser.h"
-#else
-#include <libxml/tree.h>
-#endif
-
-namespace dss {
-
-  class XMLNode;
-
-  typedef std::vector<XMLNode> XMLNodeList;
-
-  class XMLNode {
-  private:
-    bool m_ChildrenRead;
-    bool m_AttributesRead;
-  protected:
-    xmlNode* m_pNode;
-    XMLNodeList m_Children;
-    HashMapConstStringString m_Attributes;
-
-    void assertHasNode(const std::string& _reason);
-    void initialize();
-    void copyFrom(const XMLNode& _other);
-  public:
-    XMLNode();
-    XMLNode(const XMLNode& _other);
-    XMLNode(xmlNode* _node);
-    XMLNode& operator=(const XMLNode& _rhs) {
-      copyFrom(_rhs);
-      return *this;
-    }
-
-    const std::string getName();
-    const std::string getContent();
-
-    void setContent(const std::string& _value);
-    void setName(const std::string& _value);
-
-    XMLNode& addTextNode();
-    XMLNode& addChildNode(const std::string& _name, const std::string& _content = "");
-
-    XMLNode& getChildByName(const std::string& _name);
-    bool hasChildWithName(const std::string& _name);
-
-    XMLNodeList& getChildren();
-    HashMapConstStringString& getAttributes();
-  }; // XMLNode
-
-  class XMLDocument : ResourceHolder<xmlDoc> {
-  private:
-    XMLNode m_RootNode;
-  public:
-    explicit XMLDocument(xmlDoc* _pDocument = NULL);
-    XMLDocument(XMLDocument& _other);
-    ~XMLDocument();
-
-    void saveToFile(const std::string& _fileName);
-
-    XMLNode& getRootNode();
-  }; // XMLDocument
-
-  class XMLDocumentReader {
-  protected:
-    XMLDocument m_Document;
-  public:
-    virtual ~XMLDocumentReader();
-    virtual XMLDocument& getDocument() = 0;
-  }; // XMLReader
-
-  class XMLDocumentFileReader : public XMLDocumentReader {
-  private:
-    const std::string m_URI;
-  public:
-    XMLDocumentFileReader(const std::string& _uri);
-    virtual ~XMLDocumentFileReader() {}
-
-    virtual XMLDocument& getDocument();
-  };
-
-  class XMLDocumentMemoryReader : public XMLDocumentReader {
-  private:
-    const std::string m_XMLData;
-  public:
-    XMLDocumentMemoryReader(const char* _xmlData);
-    virtual ~XMLDocumentMemoryReader() {}
-    virtual XMLDocument& getDocument();
-  }; // XMLDocumentMemoryReaders
-
-  class XMLException : public DSSException {
-  public:
-    XMLException( const std::string& _message )
-    : DSSException(_message)
-    { }
-  }; // XMLException
-
-
-}
-
-#endif
diff --git a/examples/plugins/ds485Client/webserver_plugin_ds485client.cpp b/examples/plugins/ds485Client/webserver_plugin_ds485client.cpp
index 4d3ec08..c6821d4 100644
--- a/examples/plugins/ds485Client/webserver_plugin_ds485client.cpp
+++ b/examples/plugins/ds485Client/webserver_plugin_ds485client.cpp
@@ -5,7 +5,6 @@
 #include "core/base.h"
 #include "core/datetools.h" 
 #include "core/dss.h" 
-#include "core/model.h" 
 #include "core/ds485client.h" 
 #include "unix/ds485.h" 
 #include "core/ds485const.h" 
diff --git a/examples/plugins/iPhone_plugin/iPhone_plugin.cpp b/examples/plugins/iPhone_plugin/iPhone_plugin.cpp
index fc2bc24..516853a 100644
--- a/examples/plugins/iPhone_plugin/iPhone_plugin.cpp
+++ b/examples/plugins/iPhone_plugin/iPhone_plugin.cpp
@@ -7,7 +7,6 @@
 #include "core/base.h"
 #include "core/datetools.h" 
 #include "core/dss.h" 
-#include "core/model.h" 
 #include "core/ds485client.h" 
 #include "unix/ds485.h" 
 #include "core/ds485const.h" 
diff --git a/main.cpp b/main.cpp
index 1e1e952..e97fc5b 100644
--- a/main.cpp
+++ b/main.cpp
@@ -30,7 +30,7 @@
 #include "core/dss.h"
 #include "core/logger.h"
 #include "core/ds485client.h"
-#include "unix/ds485.h"
+#include "core/ds485/ds485.h"
 #ifdef WITH_TESTS
 #include "tests/tests.h"
 #endif
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 3c075fa..3721a49 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,14 +1,14 @@
 add_library(tests basetests.cpp  datetoolstests.cpp  ds485tests.cpp
 	eventtests.cpp  modeljstests.cpp  modeltests.cpp
-	propertysystemtests.cpp  scriptstest.cpp  seriestests.cpp tests.cpp)
+	propertysystemtests.cpp  scriptstest.cpp  seriestests.cpp tests.cpp busrequesttests.cpp restfulapitests.cpp)
 
 add_executable( dsstests EXCLUDE_FROM_ALL testrunner.cpp ../namespaces.cpp
 	basetests.cpp  datetoolstests.cpp  ds485tests.cpp
         eventtests.cpp  modeljstests.cpp  modeltests.cpp
-        propertysystemtests.cpp  scriptstest.cpp
-	seriestests.cpp jshandlertests.cpp)
+        propertysystemtests.cpp  scriptstest.cpp busrequesttests.cpp
+	seriestests.cpp jshandlertests.cpp restfulapitests.cpp)
 
-target_link_libraries(dsstests ${BOOST_TEST_LIB} core unix webservices 
+target_link_libraries(dsstests ${BOOST_TEST_LIB} core ds485 unix webservices model
 	pthread mongoose ${REQUIRED_LIBS})
 
 add_custom_target( test
diff --git a/tests/basetests.cpp b/tests/basetests.cpp
index 7290ffe..106f610 100644
--- a/tests/basetests.cpp
+++ b/tests/basetests.cpp
@@ -60,16 +60,46 @@ BOOST_AUTO_TEST_CASE(testUrlDecode) {
                        urlDecode("sourceid=1&schedule=FREQ%3DMINUTELY%3BINTERVAL%3D1&start=20080520T080000Z"));
 } // teturlDecode
 
-BOOST_AUTO_TEST_CASE(testConversions) {
+BOOST_AUTO_TEST_CASE(testStrToInt) {
   BOOST_CHECK_EQUAL(1, strToInt("1"));
   BOOST_CHECK_EQUAL(1, strToInt("0x1"));
   BOOST_CHECK_EQUAL(10, strToInt("0xa"));
 
+  BOOST_CHECK_THROW(strToInt("asdf"), std::invalid_argument);
+  BOOST_CHECK_THROW(strToInt(""), std::invalid_argument);
+  BOOST_CHECK_THROW(strToInt(" "), std::invalid_argument);
+} // testStrToInt
+
+BOOST_AUTO_TEST_CASE(testStrToIntDef) {
   BOOST_CHECK_EQUAL(-1, strToIntDef("", -1));
   BOOST_CHECK_EQUAL(-1, strToIntDef(" ", -1));
   BOOST_CHECK_EQUAL(-1, strToIntDef("gfdfg", -1));
   BOOST_CHECK_EQUAL(1, strToIntDef("1", -1));
-} // testConversions
+} // testStrToIntDef
+
+BOOST_AUTO_TEST_CASE(testStrToUInt) {
+  BOOST_CHECK_EQUAL(7, strToUInt("7"));
+
+  BOOST_CHECK_THROW(strToUInt("asdf"), std::invalid_argument);
+  BOOST_CHECK_THROW(strToUInt(""), std::invalid_argument);
+  BOOST_CHECK_THROW(strToUInt(" "), std::invalid_argument);
+}
+
+BOOST_AUTO_TEST_CASE(testStrToDouble) {
+  BOOST_CHECK_EQUAL(0.0, strToDouble("0.0"));
+  BOOST_CHECK_EQUAL(-1.0, strToDouble("asdf", -1.0));
+  BOOST_CHECK_EQUAL(1.0, strToDouble("1.00", -1.0));
+  BOOST_CHECK_THROW(strToDouble("asdf"), std::invalid_argument);
+} // testStrToDouble
+
+BOOST_AUTO_TEST_CASE(testUintToString) {
+  BOOST_CHECK_EQUAL("0", uintToString(0));
+  BOOST_CHECK_EQUAL("2222", uintToString(2222));
+} // testUintToString
+
+BOOST_AUTO_TEST_CASE(testUnsignedLongIntToHexString) {
+  BOOST_CHECK_EQUAL("42", unsignedLongIntToHexString(0x42));
+} // testUnsignedLongIntToHexString
 
 BOOST_AUTO_TEST_CASE(testTrim) {
   // reductions to zero-std::string
@@ -137,9 +167,43 @@ BOOST_AUTO_TEST_CASE(testSplitString) {
   BOOST_CHECK_EQUAL((size_t)2, result.size());
   BOOST_CHECK_EQUAL(std::string("a"), result[0]);
   BOOST_CHECK_EQUAL(std::string("b"), result[1]);
-
 } // testSplitString
 
+BOOST_AUTO_TEST_CASE(testJoinOneElement) {
+  std::vector<std::string> vec;
+  vec.push_back("test");
+  BOOST_CHECK_EQUAL("test", join(vec, ","));
+}
+
+BOOST_AUTO_TEST_CASE(testJoinNoElement) {
+  std::vector<std::string> vec;
+  BOOST_CHECK_EQUAL("", join(vec, ","));
+}
+
+BOOST_AUTO_TEST_CASE(testJoinMoreElements) {
+  std::vector<std::string> vec;
+  vec.push_back("test");
+  vec.push_back("test2");
+  vec.push_back("test3");
+  BOOST_CHECK_EQUAL("test,test2,test3", join(vec, ","));
+}
+
+BOOST_AUTO_TEST_CASE(testProperties) {
+  Properties props;
+  BOOST_CHECK(!props.has("key"));
+  props.set("key", "value");
+  BOOST_CHECK(props.has("key"));
+  BOOST_CHECK_EQUAL("value", props.get("key"));
+  
+  BOOST_CHECK_THROW(props.get("nonexisting"), std::runtime_error);
+  BOOST_CHECK_EQUAL("default", props.get("nonexisting", "default"));
+  
+  BOOST_CHECK_EQUAL(true, props.unset("key"));
+  BOOST_CHECK(!props.has("key"));
+  
+  BOOST_CHECK_EQUAL(false, props.unset("key"));
+}
+
 BOOST_AUTO_TEST_CASE(testISODate) {
   char c = 'C';
   struct tm inst;
diff --git a/tests/busrequesttests.cpp b/tests/busrequesttests.cpp
new file mode 100644
index 0000000..81eae02
--- /dev/null
+++ b/tests/busrequesttests.cpp
@@ -0,0 +1,64 @@
+/*
+    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
+
+    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/>.
+*/
+
+#define BOOST_TEST_NO_MAIN
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+#include "core/model/busrequest.h"
+#include "core/ds485const.h"
+#include "core/busrequestdispatcher.h"
+#include "core/model/apartment.h"
+#include "core/model/device.h"
+
+using namespace dss;
+
+BOOST_AUTO_TEST_SUITE(BusRequests)
+
+class TestDispatcher : public dss::BusRequestDispatcher {
+public:
+  int requestCount() { return m_Requests.size(); }
+  boost::shared_ptr<BusRequest> getBusRequest(int _count) {
+    return m_Requests.at(_count);
+  }
+
+  virtual void dispatchRequest(boost::shared_ptr<BusRequest> _pRequest) {
+    m_Requests.push_back(_pRequest);
+  }
+private:
+  std::vector<boost::shared_ptr<BusRequest> > m_Requests;
+};
+
+BOOST_AUTO_TEST_CASE(testRequestReachesDispatcher) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+  Device& d1 = apt.allocateDevice(dsid_t(0,1));
+  TestDispatcher dispatcher;
+  apt.setBusRequestDispatcher(&dispatcher);
+  boost::shared_ptr<CallSceneCommandBusRequest> request(new CallSceneCommandBusRequest());
+  request->setTarget(&d1);
+  request->setSceneID(SceneOff);
+  
+  BOOST_CHECK_EQUAL(0, dispatcher.requestCount());
+  apt.dispatchRequest(request);
+  BOOST_CHECK_EQUAL(1, dispatcher.requestCount());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/datetoolstests.cpp b/tests/datetoolstests.cpp
index d669e0f..4b7865d 100644
--- a/tests/datetoolstests.cpp
+++ b/tests/datetoolstests.cpp
@@ -172,6 +172,7 @@ BOOST_AUTO_TEST_CASE(testDynamicSchedule) {
   BOOST_CHECK_EQUAL(when.addMinute(10), v[2]);
 } // testDynamicSchedule
 
+#if defined(HAVE_LIBICAL_ICAL_H) || defined(HAVE_ICAL_H)
 BOOST_AUTO_TEST_CASE(testDynamicScheduleICal) {
   ICalSchedule sched("FREQ=MINUTELY;INTERVAL=2", "20080505T080000Z");
 
@@ -184,6 +185,7 @@ BOOST_AUTO_TEST_CASE(testDynamicScheduleICal) {
   DateTime nextRecurr = sched.getNextOccurence(startPlusOneSec);
   BOOST_CHECK_EQUAL(startTime.addMinute(2), nextRecurr);
 } // testDynamicScheduleICal
+#endif
 
 BOOST_AUTO_TEST_SUITE_END()
 
diff --git a/tests/ds485tests.cpp b/tests/ds485tests.cpp
index a908297..f0182f0 100644
--- a/tests/ds485tests.cpp
+++ b/tests/ds485tests.cpp
@@ -25,7 +25,7 @@
 
 #include <boost/scoped_ptr.hpp>
 
-#include "../unix/ds485.h"
+#include "core/ds485/ds485.h"
 
 using namespace dss;
 
diff --git a/tests/eventtests.cpp b/tests/eventtests.cpp
index b11e485..f1ff4a7 100644
--- a/tests/eventtests.cpp
+++ b/tests/eventtests.cpp
@@ -23,11 +23,17 @@
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 
-#include "../core/event.h"
-#include "../core/eventinterpreterplugins.h"
-#include "../core/setbuilder.h"
-#include "../core/sim/dssim.h"
-#include "../unix/ds485proxy.h"
+#include "core/event.h"
+#include "core/eventinterpreterplugins.h"
+#include "core/setbuilder.h"
+#include "core/sim/dssim.h"
+#include "core/model/apartment.h"
+#include "core/model/device.h"
+#include "core/model/devicereference.h"
+#include "core/model/zone.h"
+#include "core/model/group.h"
+#include "core/model/set.h"
+#include "core/ds485/ds485proxy.h"
 
 using namespace dss;
 
@@ -105,6 +111,7 @@ BOOST_AUTO_TEST_CASE(testEmptySubscriptionXML) {
   EventQueue queue;
   EventInterpreter interpreter(NULL);
   interpreter.setEventQueue(&queue);
+  interpreter.initialize();
 
   BOOST_CHECK_EQUAL(interpreter.getNumberOfSubscriptions(), 0);
 
@@ -115,6 +122,7 @@ BOOST_AUTO_TEST_CASE(testEmptySubscriptionXML) {
 
 BOOST_AUTO_TEST_CASE(testNonExistingXML) {
   EventInterpreter interpreter(NULL);
+  interpreter.initialize();
 
   BOOST_CHECK_EQUAL(interpreter.getNumberOfSubscriptions(), 0);
 
@@ -172,7 +180,7 @@ BOOST_AUTO_TEST_CASE(testSubscriptionXML) {
 
 
 BOOST_AUTO_TEST_CASE(testSetBuilder) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   SetBuilder setBuilder(apt);
@@ -211,11 +219,12 @@ BOOST_AUTO_TEST_CASE(testDS485Events) {
   queue.setEventRunner(&runner);
   runner.setEventQueue(&queue);
 
-  Apartment apt(NULL);
-  apt.initialize();
-
+  Apartment apt(NULL, NULL);
   DSModulatorSim modSim(NULL);
   DS485Proxy proxy(NULL, &apt);
+  apt.setDS485Interface(&proxy);
+
+  apt.initialize();
   proxy.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
diff --git a/tests/jshandlertests.cpp b/tests/jshandlertests.cpp
index d89549e..84db43a 100644
--- a/tests/jshandlertests.cpp
+++ b/tests/jshandlertests.cpp
@@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE(testCallingFunctions) {
   env->initialize();
 
   boost::scoped_ptr<ScriptContext> ctx(env->getContext());
-  jsval res = ctx->evaluate<jsval>("dev = { func: function(a,b,c) { return { e: a, f: b, g: c }; } }; dev");
+  jsval res = ctx->doEvaluate("dev = { func: function(a,b,c) { return { e: a, f: b, g: c }; } }; dev");
 
   BOOST_ASSERT(JSVAL_IS_OBJECT(res));
 
@@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(testCallingFunctions) {
   list.add<int>(1);
   list.add<bool>(false);
 
-  res = obj.callFunctionByName<jsval>("func", list);
+  res = obj.doCallFunctionByName("func", list);
 
   BOOST_ASSERT(JSVAL_IS_OBJECT(res));
   ScriptObject resObj(JSVAL_TO_OBJECT(res), *ctx);
@@ -76,4 +76,22 @@ BOOST_AUTO_TEST_CASE(testCallingFunctions) {
   BOOST_CHECK_EQUAL(resObj.getProperty<bool>("g"), false);
 }
 
+BOOST_AUTO_TEST_CASE(testLongerScript) {
+  boost::scoped_ptr<ScriptEnvironment> env(new ScriptEnvironment());
+  env->initialize();
+
+  boost::scoped_ptr<ScriptContext> ctx(env->getContext());
+  ctx->evaluate<void>("print('dummy.js, running');\n"
+                      "\n"
+                      "var pi = 3.14;\n"
+                      "var r = 5;\n"
+                      "var x = 1984;\n"
+                      "\n"
+                      "var area = pi * r * r;\n"
+                      "var division = x / r;\n"
+                      "\n"
+                      "print('area: ' + area);\n"
+                      "print('divison: ' + division);");
+} // testLongerScript
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/modeljstests.cpp b/tests/modeljstests.cpp
index cbd31a3..5c197ee 100644
--- a/tests/modeljstests.cpp
+++ b/tests/modeljstests.cpp
@@ -27,6 +27,8 @@
 #include "core/event.h"
 #include "core/eventinterpreterplugins.h"
 #include "core/propertysystem.h"
+#include "core/model/apartment.h"
+#include "core/model/device.h"
 
 #include <boost/scoped_ptr.hpp>
 #include <memory>
@@ -37,7 +39,7 @@ using namespace dss;
 BOOST_AUTO_TEST_SUITE(ModelJS)
 
 BOOST_AUTO_TEST_CASE(testBasics) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.setName("my apartment");
 
 
@@ -58,7 +60,7 @@ BOOST_AUTO_TEST_CASE(testBasics) {
 } // testBasics
 
 BOOST_AUTO_TEST_CASE(testSets) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
@@ -138,7 +140,7 @@ BOOST_AUTO_TEST_CASE(testSets) {
 } // testSets
 
 BOOST_AUTO_TEST_CASE(testDevices) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
@@ -163,7 +165,7 @@ BOOST_AUTO_TEST_CASE(testDevices) {
 } // testDevices
 
 BOOST_AUTO_TEST_CASE(testEvents) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev = apt.allocateDevice(dsid_t(0,1));
@@ -198,7 +200,7 @@ BOOST_AUTO_TEST_CASE(testEvents) {
 } // testEvents
 
 BOOST_AUTO_TEST_CASE(testSubscriptions) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev = apt.allocateDevice(dsid_t(0,1));
diff --git a/tests/modeltests.cpp b/tests/modeltests.cpp
index 5d9a389..d79dcc1 100644
--- a/tests/modeltests.cpp
+++ b/tests/modeltests.cpp
@@ -23,19 +23,25 @@
 #define BOOST_TEST_DYN_LINK
 #include <boost/test/unit_test.hpp>
 
-#include "core/model.h"
+#include "core/model/device.h"
+#include "core/model/apartment.h"
+#include "core/model/modulator.h"
+#include "core/model/devicereference.h"
+#include "core/model/zone.h"
+#include "core/model/set.h"
 #include "core/setbuilder.h"
 #include "core/ds485const.h"
-#include "unix/ds485proxy.h"
+#include "core/ds485/ds485proxy.h"
 #include "core/sim/dssim.h"
 #include "core/dss.h"
+#include "core/ds485/ds485busrequestdispatcher.h"
 
 using namespace dss;
 
 BOOST_AUTO_TEST_SUITE(Model)
 
 BOOST_AUTO_TEST_CASE(testApartmentAllocateDeviceReturnsTheSameDeviceForDSID) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
@@ -50,7 +56,7 @@ BOOST_AUTO_TEST_CASE(testApartmentAllocateDeviceReturnsTheSameDeviceForDSID) {
 } // testApartmentAllocateDeviceReturnsTheSameDeviceForDSID
 
 BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByShortAddress) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Modulator& mod = apt.allocateModulator(dsid_t(0,2));
@@ -65,7 +71,7 @@ BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByShortAddress) {
 } // testApartmentGetDeviceByShortAddress
 
 BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByName) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
@@ -75,7 +81,7 @@ BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByName) {
 } // testApartmentGetDeviceByName
 
 BOOST_AUTO_TEST_CASE(testApartmentGetModulatorByName) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Modulator& mod = apt.allocateModulator(dsid_t(0,2));
@@ -85,7 +91,7 @@ BOOST_AUTO_TEST_CASE(testApartmentGetModulatorByName) {
 } // testApartmentGetModulatorByName
 
 BOOST_AUTO_TEST_CASE(testApartmentGetModulatorByBusID) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Modulator& mod = apt.allocateModulator(dsid_t(0,2));
@@ -95,21 +101,21 @@ BOOST_AUTO_TEST_CASE(testApartmentGetModulatorByBusID) {
 } // testApartmentGetModulatorByBusID
 
 BOOST_AUTO_TEST_CASE(testZoneMoving) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setShortAddress(1);
-  DeviceReference devRef1(dev1, apt);
+  DeviceReference devRef1(dev1, &apt);
   Device& dev2 = apt.allocateDevice(dsid_t(0,2));
   dev2.setShortAddress(2);
-  DeviceReference devRef2(dev2, apt);
+  DeviceReference devRef2(dev2, &apt);
   Device& dev3 = apt.allocateDevice(dsid_t(0,3));
   dev3.setShortAddress(3);
-  DeviceReference devRef3(dev3, apt);
+  DeviceReference devRef3(dev3, &apt);
   Device& dev4 = apt.allocateDevice(dsid_t(0,4));
   dev4.setShortAddress(4);
-  DeviceReference devRef4(dev4, apt);
+  DeviceReference devRef4(dev4, &apt);
 
   Zone& zone1 = apt.allocateZone(1);
   zone1.addDevice(devRef1);
@@ -161,7 +167,7 @@ BOOST_AUTO_TEST_CASE(testZoneMoving) {
 } // testZoneMoving
 
 BOOST_AUTO_TEST_CASE(testSet) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
@@ -243,7 +249,7 @@ BOOST_AUTO_TEST_CASE(testSet) {
 } // testSet
 
 BOOST_AUTO_TEST_CASE(testSetBuilder) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
@@ -358,7 +364,7 @@ BOOST_AUTO_TEST_CASE(testSetBuilder) {
 } // testSetBuilder
 
 BOOST_AUTO_TEST_CASE(testRemoval) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
@@ -405,13 +411,16 @@ BOOST_AUTO_TEST_CASE(testRemoval) {
 } // testRemoval
 
 BOOST_AUTO_TEST_CASE(testCallScenePropagation) {
-  Apartment apt(NULL);
+  Apartment apt(NULL, NULL);
   apt.initialize();
 
   DSModulatorSim modSim(NULL);
   DS485Proxy proxy(NULL, &apt);
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
   proxy.setInitializeDS485Controller(false);
   proxy.initialize();
+  apt.setBusRequestDispatcher(&dispatcher);
 
   proxy.start();
   apt.start();
@@ -425,18 +434,17 @@ BOOST_AUTO_TEST_CASE(testCallScenePropagation) {
   dev1.setName("dev1");
   dev1.setShortAddress(1);
   dev1.setModulatorID(76);
-  DeviceReference devRef1(dev1, apt);
+  DeviceReference devRef1(dev1, &apt);
   mod.addDevice(devRef1);
   Device& dev2 = apt.allocateDevice(dsid_t(0,2));
   dev2.setName("dev2");
   dev2.setShortAddress(2);
   dev2.setModulatorID(76);
 
-//  dev1.callScene(Scene1);
-  proxy.sendCommand(cmdCallScene, dev1, Scene1);
+  dev1.callScene(Scene1);
   sleepMS(500);
   BOOST_CHECK_EQUAL(Scene1, dev1.getLastCalledScene());
-  proxy.sendCommand(cmdCallScene, apt.getZone(0), apt.getGroup(0), Scene2);
+  apt.getZone(0).callScene(Scene2);
   sleepMS(500);
   BOOST_CHECK_EQUAL(Scene2, dev1.getLastCalledScene());
   BOOST_CHECK_EQUAL(Scene2, dev2.getLastCalledScene());
@@ -446,4 +454,745 @@ BOOST_AUTO_TEST_CASE(testCallScenePropagation) {
   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;
+      }
+    }
+
+    virtual DeviceBusInterface* getDeviceBusInterface() { return this; }
+    virtual StructureQueryBusInterface* getStructureQueryBusInterface() { return this; }
+
+
+    //------------------------------------------------ Specialized Commands (system)
+    /** Returns an std::vector containing the modulator-spec of all modulators present. */
+    virtual std::vector<ModulatorSpec_t> getModulators() { return std::vector<ModulatorSpec_t>(); }
+
+    /** Returns the modulator-spec for a modulator */
+    virtual ModulatorSpec_t getModulatorSpec(const int _modulatorID) { return ModulatorSpec_t(); }
+
+    /** Returns a std::vector conatining the zone-ids of the specified modulator */
+    virtual std::vector<int> getZones(const int _modulatorID) { return std::vector<int>(); }
+    /** Returns the count of the zones of the specified modulator */
+    virtual int getZoneCount(const int _modulatorID) { return 0; }
+    /** Returns the bus-ids of the devices present in the given zone of the specified modulator */
+    virtual std::vector<int> getDevicesInZone(const int _modulatorID, const int _zoneID) { return std::vector<int>(); }
+    /** Returns the count of devices present in the given zone of the specified modulator */
+    virtual int getDevicesCountInZone(const int _modulatorID, const int _zoneID) { return 0; }
+
+    /** Adds the given device to the specified zone. */
+    virtual void setZoneID(const int _modulatorID, const devid_t _deviceID, const int _zoneID) {}
+
+    /** Creates a new Zone on the given modulator */
+    virtual void createZone(const int _modulatorID, const int _zoneID) {}
+
+    /** Removes the zone \a _zoneID on the modulator \a _modulatorID */
+    virtual void removeZone(const int _modulatorID, const int _zoneID) {}
+
+    /** Returns the count of groups present in the given zone of the specifid modulator */
+    virtual int getGroupCount(const int _modulatorID, const int _zoneID) { return 0; }
+    /** Returns the a std::vector containing the group-ids of the given zone on the specified modulator */
+    virtual std::vector<int> getGroups(const int _modulatorID, const int _zoneID) { return std::vector<int>(); }
+    /** Returns the count of devices present in the given group */
+    virtual int getDevicesInGroupCount(const int _modulatorID, 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 _modulatorID, const int _zoneID, const int _groupID) { return std::vector<int>(); }
+
+    virtual std::vector<int> getGroupsOfDevice(const int _modulatorID, const int _deviceID) { return std::vector<int>(); }
+
+    /** Adds a device to a given group */
+    virtual void addToGroup(const int _modulatorID, const int _groupID, const int _deviceID) {}
+    /** Removes a device from a given group */
+    virtual void removeFromGroup(const int _modulatorID, const int _groupID, const int _deviceID) {}
+
+    /** Adds a user group */
+    virtual int addUserGroup(const int _modulatorID) { return 0; }
+    /** Removes a user group */
+    virtual void removeUserGroup(const int _modulatorID, const int _groupID) {}
+
+    /** Returns the DSID of a given device */
+    virtual dsid_t getDSIDOfDevice(const int _modulatorID, const int _deviceID) { return NullDSID; }
+    /** Returns the DSID of a given modulator */
+    virtual dsid_t getDSIDOfModulator(const int _modulatorID) { return NullDSID; }
+
+    virtual int getLastCalledScene(const int _modulatorID, const int _zoneID, const int _groupID) { return 0;}
+
+    //------------------------------------------------ Metering
+
+    /** Returns the current power-consumption in mW */
+    virtual unsigned long getPowerConsumption(const int _modulatorID) { return 0; }
+
+    /** Returns the meter value in Wh */
+    virtual unsigned long getEnergyMeterValue(const int _modulatorID) { return 0; }
+
+    virtual bool getEnergyBorder(const int _modulatorID, int& _lower, int& _upper) { _lower = 0; _upper = 0; return false; }
+
+    //------------------------------------------------ UDI
+    virtual uint8_t dSLinkSend(const int _modulatorID, devid_t _devAdr, uint8_t _value, uint8_t _flags) { return 0; }
+
+    //------------------------------------------------ Device    
+    virtual uint16_t deviceGetParameterValue(devid_t _id, uint8_t _modulatorID, int _paramID) { return 0; }
+    virtual uint16_t deviceGetFunctionID(devid_t _id, uint8_t _modulatorID) { 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();
+
+  DSModulatorSim 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));
+  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);
+  devRef1.turnOn();
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(SceneMax, proxy.getParameter2());
+}
+
+BOOST_AUTO_TEST_CASE(testTurnOnGroup) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  proxy.setLastFunctionID(-1);
+  Group& group = apt.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_AUTO_TEST_CASE(testTurnOffDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  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);
+  devRef1.turnOff();
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(SceneMin, proxy.getParameter2());
+}
+
+BOOST_AUTO_TEST_CASE(testTurnOffGroup) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  proxy.setLastFunctionID(-1);
+  Group& group = apt.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_AUTO_TEST_CASE(testEnableDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  dev1.enable();
+  BOOST_CHECK_EQUAL(FunctionDeviceEnable, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  proxy.setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, &apt);
+  devRef1.enable();
+  BOOST_CHECK_EQUAL(FunctionDeviceEnable, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
+BOOST_AUTO_TEST_CASE(testDisableDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  dev1.disable();
+  BOOST_CHECK_EQUAL(FunctionDeviceDisable, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  proxy.setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, &apt);
+  devRef1.disable();
+  BOOST_CHECK_EQUAL(FunctionDeviceDisable, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
+BOOST_AUTO_TEST_CASE(testIncreaseValueDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  dev1.increaseValue();
+  BOOST_CHECK_EQUAL(FunctionDeviceIncreaseValue, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  proxy.setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, &apt);
+  devRef1.increaseValue();
+  BOOST_CHECK_EQUAL(FunctionDeviceIncreaseValue, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
+BOOST_AUTO_TEST_CASE(testDecreaseValueDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  dev1.decreaseValue();
+  BOOST_CHECK_EQUAL(FunctionDeviceDecreaseValue, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  proxy.setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, &apt);
+  devRef1.decreaseValue();
+  BOOST_CHECK_EQUAL(FunctionDeviceDecreaseValue, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
+BOOST_AUTO_TEST_CASE(testDecreaseValueZone) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  Zone& zone = apt.allocateZone(1);
+
+  proxy.setLastFunctionID(-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_AUTO_TEST_CASE(testIncreaseValueZone) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  Zone& zone = apt.allocateZone(1);
+
+  proxy.setLastFunctionID(-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_AUTO_TEST_CASE(testStartDimUp) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  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);
+  devRef1.startDim(true);
+  BOOST_CHECK_EQUAL(FunctionDeviceStartDimInc, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
+BOOST_AUTO_TEST_CASE(testStartDimDown) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  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);
+  devRef1.startDim(false);
+  BOOST_CHECK_EQUAL(FunctionDeviceStartDimDec, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
+BOOST_AUTO_TEST_CASE(testEndDim) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  dev1.endDim();
+  BOOST_CHECK_EQUAL(FunctionDeviceEndDim, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  proxy.setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, &apt);
+  devRef1.endDim();
+  BOOST_CHECK_EQUAL(FunctionDeviceEndDim, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
+BOOST_AUTO_TEST_CASE(testCallSceneDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  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);
+  devRef1.callScene(Scene1);
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
+}
+
+BOOST_AUTO_TEST_CASE(testSaveSceneDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  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);
+  devRef1.saveScene(Scene1);
+  BOOST_CHECK_EQUAL(FunctionDeviceSaveScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
+}
+
+BOOST_AUTO_TEST_CASE(testUndoSceneDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  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);
+  devRef1.undoScene(Scene1);
+  BOOST_CHECK_EQUAL(FunctionDeviceUndoScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  BOOST_CHECK_EQUAL(Scene1, proxy.getParameter2());
+}
+
+BOOST_AUTO_TEST_CASE(testCallSceneGroup) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  proxy.setLastFunctionID(-1);
+  Group& group = apt.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_AUTO_TEST_CASE(testSaveSceneGroup) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  proxy.setLastFunctionID(-1);
+  Group& group = apt.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_AUTO_TEST_CASE(testUndoSceneGroup) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  proxy.setLastFunctionID(-1);
+  Group& group = apt.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_AUTO_TEST_CASE(testCallSceneZone) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  proxy.setLastFunctionID(-1);
+  Zone& zone = apt.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_AUTO_TEST_CASE(testSaveSceneZone) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  proxy.setLastFunctionID(-1);
+  Zone& zone = apt.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_AUTO_TEST_CASE(testUndoSceneZone) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485InterfaceTest proxy;
+  DS485BusRequestDispatcher dispatcher;
+  dispatcher.setProxy(&proxy);
+  apt.setDS485Interface(&proxy);
+  apt.setBusRequestDispatcher(&dispatcher);
+
+  proxy.setLastFunctionID(-1);
+  Zone& zone = apt.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_AUTO_TEST_CASE(callUndoSceneSet) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  Device& dev2 = apt.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_AUTO_TEST_CASE(testSaveSceneSet) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  Device& dev2 = apt.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_AUTO_TEST_CASE(testUndoSceneSet) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  Device& dev2 = apt.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_AUTO_TEST_CASE(testNextSceneDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  dev1.nextScene();
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  proxy.setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, &apt);
+  devRef1.nextScene();
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
+BOOST_AUTO_TEST_CASE(testPreviousSceneDevice) {
+  Apartment apt(NULL, NULL);
+  apt.initialize();
+
+  DSModulatorSim 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));
+  dev1.setShortAddress(1);
+  dev1.previousScene();
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+  proxy.setLastFunctionID(-1);
+  DeviceReference devRef1(dev1, &apt);
+  devRef1.previousScene();
+  BOOST_CHECK_EQUAL(FunctionDeviceCallScene, proxy.getLastFunctionID());
+  BOOST_CHECK_EQUAL(0x1, proxy.getParameter1());
+}
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/propertysystemtests.cpp b/tests/propertysystemtests.cpp
index 988ddea..f1fd6f6 100644
--- a/tests/propertysystemtests.cpp
+++ b/tests/propertysystemtests.cpp
@@ -35,26 +35,46 @@ int testGetter() {
   return 2;
 }
 
+template<class t>
 class PropTest {
 private:
-  int m_Value;
+  t m_Value;
 public:
-  PropTest(const int _value) :
+  PropTest(const t _value) :
     m_Value(_value) {
   }
 
-  void setValue(int _value) {
+  void setValue(t _value) {
     m_Value = _value;
 #ifdef VERBOSE_TESTS
     cout << "PropTest::setValue new value: " << _value << endl;
 #endif
   }
 
-  int getValue() const {
+  t getValue() const {
     return m_Value;
   }
 };
 
+class PropTestString {
+private:
+  std::string m_Value;
+public:
+  PropTestString(const std::string& _value) :
+    m_Value(_value) {
+  }
+
+  void setValue(const std::string& _value) {
+    m_Value = _value;
+#ifdef VERBOSE_TESTS
+    cout << "PropTestString::setValue new value: " << _value << endl;
+#endif
+  }
+
+  const std::string& getValue() const {
+    return m_Value;
+  }
+};
 
 #include "../core/propertysystem.h"
 
@@ -62,6 +82,70 @@ using namespace dss;
 
 BOOST_AUTO_TEST_SUITE(PropertySystemTests)
 
+BOOST_AUTO_TEST_CASE(testBoolProxy) {
+  PropertySystem propSys;
+  PropertyNodePtr prop = propSys.createProperty("/value");
+  
+  PropTest<bool> t(true);
+  PropertyProxyMemberFunction<class PropTest<bool>, bool> 
+    proxy(t, &PropTest<bool>::getValue, &PropTest<bool>::setValue);
+  prop->linkToProxy(proxy);
+  
+  BOOST_CHECK_EQUAL(true, proxy.getValue());
+  BOOST_CHECK_EQUAL(true, prop->getBoolValue());
+
+  prop->setBooleanValue(false);
+  BOOST_CHECK_EQUAL(false, proxy.getValue());
+  BOOST_CHECK_EQUAL(false, prop->getBoolValue());
+} // testBoolProxy
+
+BOOST_AUTO_TEST_CASE(testIntProxy) {
+  PropertySystem propSys;
+  PropertyNodePtr prop = propSys.createProperty("/value");
+  
+  PropTest<int> t(7);
+  PropertyProxyMemberFunction<class PropTest<int>, int> 
+    proxy(t, &PropTest<int>::getValue, &PropTest<int>::setValue);
+  prop->linkToProxy(proxy);
+
+  BOOST_CHECK_EQUAL(7, proxy.getValue());
+  BOOST_CHECK_EQUAL(7, prop->getIntegerValue());
+
+  prop->setIntegerValue(false);
+  BOOST_CHECK_EQUAL(false, proxy.getValue());
+  BOOST_CHECK_EQUAL(false, prop->getIntegerValue());
+} // testIntProxy
+
+BOOST_AUTO_TEST_CASE(testStringProxy) {
+  PropertySystem propSys;
+  PropertyNodePtr prop = propSys.createProperty("/value");
+  
+  PropTestString t("initial");
+  PropertyProxyMemberFunction<class PropTestString, std::string> 
+    proxy(t, &PropTestString::getValue, &PropTestString::setValue);
+  prop->linkToProxy(proxy);
+
+  BOOST_CHECK_EQUAL("initial", proxy.getValue());
+  BOOST_CHECK_EQUAL("initial", prop->getStringValue());
+
+  prop->setStringValue("testValue");
+  BOOST_CHECK_EQUAL("testValue", proxy.getValue());
+  BOOST_CHECK_EQUAL("testValue", prop->getStringValue());
+} // testStringProxy
+
+
+BOOST_AUTO_TEST_CASE(testPropertyNodeSize) {
+  PropertySystem propSys;
+  BOOST_CHECK_EQUAL(0, propSys.getRootNode()->size());
+
+  PropertyNodePtr prop = propSys.createProperty("/node");
+  
+  BOOST_CHECK_EQUAL(1, propSys.getRootNode()->size());
+  propSys.getRootNode()->removeChild(prop);
+
+  BOOST_CHECK_EQUAL(0, propSys.getRootNode()->size());
+} // testPropertyNodeSize
+
 BOOST_AUTO_TEST_CASE(testPropertySystem) {
   boost::scoped_ptr<PropertySystem> propSys(new PropertySystem());
   PropertyNodePtr propND1 = propSys->createProperty("/config");
@@ -140,17 +224,17 @@ BOOST_AUTO_TEST_CASE(testPropertySystem) {
   propND1->unlinkProxy();
 
   // test pointer to member, readonly
-  PropTest t(2);
-  PropertyProxyMemberFunction<class PropTest, int> to(t, &PropTest::getValue);
+  PropTest<int> t(2);
+  PropertyProxyMemberFunction<class PropTest<int>, int> to(t, &PropTest<int>::getValue);
   propND1->linkToProxy(to);
   BOOST_CHECK_EQUAL(2, propND1->getIntegerValue());
   propND1->setIntegerValue(5);
   BOOST_CHECK_EQUAL(2, propND1->getIntegerValue());
   propND1->unlinkProxy();
 
-  PropertyProxyMemberFunction<class PropTest, int> to2(t,
-                                                       &PropTest::getValue,
-                                                       &PropTest::setValue);
+  PropertyProxyMemberFunction<class PropTest<int>, int> to2(t,
+                                                       &PropTest<int>::getValue,
+                                                       &PropTest<int>::setValue);
   propND1->linkToProxy(to2);
   BOOST_CHECK_EQUAL(2, propND1->getIntegerValue());
   propND1->setIntegerValue(5);
@@ -273,4 +357,32 @@ BOOST_AUTO_TEST_CASE(testFlags) {
   BOOST_CHECK(node->hasFlag(PropertyNode::Archive));
 } // testFlags
 
+BOOST_AUTO_TEST_CASE(testPropertyNodeGetAsString) {
+  PropertySystem propSys;
+  
+  PropertyNodePtr intNode = propSys.createProperty("/int");
+  intNode->setIntegerValue(1);
+  BOOST_CHECK_EQUAL("1", intNode->getAsString());
+
+  PropertyNodePtr boolNode = propSys.createProperty("/bool");
+  boolNode->setBooleanValue(true);
+  BOOST_CHECK_EQUAL("true", boolNode->getAsString());
+  boolNode->setBooleanValue(false);
+  BOOST_CHECK_EQUAL("false", boolNode->getAsString());
+  
+  PropertyNodePtr stringNode = propSys.createProperty("/string");
+  stringNode->setStringValue("test");
+  BOOST_CHECK_EQUAL("test", stringNode->getAsString());
+  
+  PropertyNodePtr noneNode = propSys.createProperty("/none");
+  BOOST_CHECK_EQUAL("", noneNode->getAsString());  
+} // testPropertyNodeGetAsString
+
+BOOST_AUTO_TEST_CASE(testValueTypeFromAndToString) {
+  BOOST_CHECK_EQUAL(vTypeBoolean, getValueTypeFromString(getValueTypeAsString(vTypeBoolean)));
+  BOOST_CHECK_EQUAL(vTypeInteger, getValueTypeFromString(getValueTypeAsString(vTypeInteger)));
+  BOOST_CHECK_EQUAL(vTypeString, getValueTypeFromString(getValueTypeAsString(vTypeString)));
+  BOOST_CHECK_EQUAL(vTypeNone, getValueTypeFromString(getValueTypeAsString(vTypeNone)));
+} // testValueTypeFromAndToString
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/restfulapitests.cpp b/tests/restfulapitests.cpp
new file mode 100644
index 0000000..fa1cdb2
--- /dev/null
+++ b/tests/restfulapitests.cpp
@@ -0,0 +1,58 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+    Copyright (c) 2010 futureLAB AG, Winterthur, Switzerland
+
+    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/>.
+
+*/
+
+#define BOOST_TEST_NO_MAIN
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+
+#include "core/web/restful.h"
+
+using namespace dss;
+
+BOOST_AUTO_TEST_SUITE(RestfulAPITests)
+
+BOOST_AUTO_TEST_CASE(testDeclaring) {
+    RestfulAPI api;
+    BOOST_CHECK(!api.hasClass("apartment"));
+    
+    RestfulClass& clsApartment = api.addClass("apartment")
+       .withDocumentation("A wrapper for global functions as well as adressing all devices connected to the dSS");
+
+    BOOST_CHECK(api.hasClass("apartment"));
+    BOOST_CHECK(!clsApartment.hasMethod("getName"));
+
+     clsApartment.addMethod("getName")
+      .withDocumentation("Returns the name of the apartment");
+
+    BOOST_CHECK(clsApartment.hasMethod("getName"));
+}
+
+BOOST_AUTO_TEST_CASE(testRestfulRequest) {
+  HashMapConstStringString params;
+  std::string method = "test/method";
+
+  RestfulRequest req(method, params);
+
+  BOOST_CHECK_EQUAL(req.getClass(), "test");
+  BOOST_CHECK_EQUAL(req.getMethod(), "method");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/seriestests.cpp b/tests/seriestests.cpp
index 991ea38..ca43596 100644
--- a/tests/seriestests.cpp
+++ b/tests/seriestests.cpp
@@ -33,7 +33,7 @@ using namespace dss;
 
 BOOST_AUTO_TEST_SUITE(SeriesTests)
 
-// calculates N + (N-1) + (N-2) from N to N-limit
+// calculates N + (N-1) + (N-2) + ... from N to N-limit
 // we could use the following formula but using MTP is way cooler ;-)
 // N * (N-1)/2 - (N-limit)*(N-limit - 1)/2
 template <int N, int limit>
diff --git a/unix/ds485.cpp b/unix/ds485.cpp
deleted file mode 100644
index 990e46c..0000000
--- a/unix/ds485.cpp
+++ /dev/null
@@ -1,1009 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 "ds485.h"
-
-#include "core/base.h"
-#include "core/logger.h"
-#include "core/ds485const.h"
-#include "core/dss.h"
-#include "core/propertysystem.h"
-
-#include <stdexcept>
-#include <sstream>
-#include <iostream>
-
-#include <ctime>
-#include <sys/time.h>
-
-#include <boost/scoped_ptr.hpp>
-
-namespace dss {
-
-  const unsigned char FrameStart = 0xFD;
-  const unsigned char EscapeCharacter = 0xFC;
-
-  const char* controllerStateToString(const aControllerState _state);
-
-  //================================================== DS485Payload
-
-  template<>
-  void DS485Payload::add(uint8_t _data) {
-    m_Data.push_back(_data);
-  } // add<uint8_t>
-
-  template<>
-  void DS485Payload::add(devid_t _data) {
-    m_Data.push_back((_data >> 0) & 0x00FF);
-    m_Data.push_back((_data >> 8) & 0x00FF);
-  } // add<devid_t>
-
-  template<>
-  void DS485Payload::add(bool _data) {
-    m_Data.push_back(_data);
-  } // add<bool>
-
-  template<>
-  void DS485Payload::add(uint32_t _data) {
-    add<uint16_t>((_data >>  0) & 0x0000FFFF);
-    add<uint16_t>((_data >> 16) & 0x0000FFFF);
-  }
-
-  template<>
-  void DS485Payload::add(dsid_t _data) {
-    // 0x11223344 55667788
-    for(int iByte = 0; iByte < 8; iByte++) {
-      add<uint8_t>((_data.upper >> ((8 - iByte - 1) * 8)) & 0x00000000000000FF);
-    }
-    add<uint8_t>((_data.lower >> 24) & 0x000000FF);
-    add<uint8_t>((_data.lower >> 16) & 0x000000FF);
-    add<uint8_t>((_data.lower >>  8) & 0x000000FF);
-    add<uint8_t>((_data.lower >>  0) & 0x000000FF);
-  } // add<dsid_t>
-
-  int DS485Payload::size() const {
-    return m_Data.size();
-  } // size
-
-  const std::vector<unsigned char>& DS485Payload::toChar() const {
-    return m_Data;
-  } // getData
-
-
-  //================================================== DS485Header
-
-  std::vector<unsigned char> DS485Header::toChar() const {
-    std::vector<unsigned char> result;
-    result.push_back(FrameStart);
-    unsigned char tmp = (m_Destination << 2) | ((m_Broadcast & 0x01) << 1) | (m_Type & 0x01);
-    result.push_back(tmp);
-    tmp = ((m_Source & 0x3F) << 2) | (m_Counter & 0x03);
-    result.push_back(tmp);
-
-    return result;
-  } // toChar
-
-  void DS485Header::fromChar(const unsigned char* _data, const int _len) {
-    if(_len < 3) {
-      throw std::invalid_argument("_len must be > 3");
-    }
-    setDestination((_data[1] >> 2) & 0x3F);
-    setBroadcast((_data[1] & 0x02) == 0x02);
-    setSource((_data[2] >> 2) & 0x3F);
-    setCounter(_data[2] & 0x03);
-  } // fromChar
-
-
-  //================================================== DS485Frame
-
-  std::vector<unsigned char> DS485Frame::toChar() const {
-    std::vector<unsigned char> result = m_Header.toChar();
-    return result;
-  } // toChar
-
-  DS485Payload& DS485Frame::getPayload() {
-    return m_Payload;
-  } // getPayload
-
-  const DS485Payload& DS485Frame::getPayload() const {
-    return m_Payload;
-  } // getPayload
-
-
-  //================================================== DS485CommandFrame
-
-  DS485CommandFrame::DS485CommandFrame()
-  : m_Length(0xFF)
-  {
-    getHeader().setType(1);
-  } // ctor
-
-  std::vector<unsigned char> DS485CommandFrame::toChar() const {
-    std::vector<unsigned char> result = DS485Frame::toChar();
-    unsigned char tmp;
-    if(m_Length == 0xFF) {
-      tmp = (m_Command << 4) | (getPayload().size() & 0x0F);
-    } else {
-      tmp = (m_Command << 4) | (m_Length & 0x0F);
-    }
-    result.push_back(tmp);
-
-    const std::vector<unsigned char>& payload = getPayload().toChar();
-    result.insert(result.end(), payload.begin(), payload.end());
-    return result;
-  } // toChar
-
-
-  //================================================== DS485Controller
-
-  DS485Controller::DS485Controller()
-  : Thread("DS485Controller"),
-    m_State(csInitial),
-    m_RS485DeviceName("/dev/ttyUSB0")
-  {
-    m_DSID.upper = DSIDHeader;
-    m_DSID.lower = 0xDEADBEEF;
-  } // ctor
-
-  DS485Controller::~DS485Controller() {
-  } // dtor
-
-  void DS485Controller::setRS485DeviceName(const std::string& _value) {
-    m_RS485DeviceName = _value;
-    if(isRunning()) {
-      Logger::getInstance()->log("DS485Controller::setRS485DeviceName: Called too late. Value updated but it won't have any effect.", lsError);
-    }
-  } // setRS485DeviceName
-
-  DS485Frame* DS485Controller::getFrameFromWire() {
-    DS485Frame* result = m_FrameReader.getFrame(200);
-    if(result != NULL) {
-      DS485CommandFrame* cmdFrame = dynamic_cast<DS485CommandFrame*>(result);
-      if(cmdFrame != NULL) {
-        //Logger::getInstance()->log("Command received");
-        //Logger::getInstance()->log(string("command: ") + CommandToString(cmdFrame->getCommand()));
-        //Logger::getInstance()->log(string("length:  ") + intToString((cmdFrame->getLength())));
-        //Logger::getInstance()->log(string("msg nr:  ") + intToString(cmdFrame->getHeader().getCounter()));
-      } else {
-        //std::cout << "+";
-        //flush(std::cout);
-        //Logger::getInstance()->log("token received");
-      }
-    }
-    return result;
-  } // getFrameFromWire
-
-  inline void DS485Controller::putCharOnWire(const unsigned char _ch) {
-    if((_ch == FrameStart) || (_ch == EscapeCharacter)) {
-      m_SerialCom->putChar(0xFC);
-      // mask out the msb
-      m_SerialCom->putChar(_ch & 0x7F);
-    } else {
-      m_SerialCom->putChar(_ch);
-    }
-  } // putCharOnWire
-
-  bool DS485Controller::putFrameOnWire(const DS485Frame* _pFrame, bool _freeFrame) {
-    std::vector<unsigned char> chars = _pFrame->toChar();
-    uint16_t crc = 0x0000;
-
-    unsigned int numChars = chars.size();
-    for(unsigned int iChar = 0; iChar < numChars; iChar++) {
-      unsigned char c = chars[iChar];
-      crc = update_crc(crc, c);
-      // escape if it's a reserved character and not the first (frame start)
-      if(iChar != 0) {
-        putCharOnWire(c);
-      } else {
-        m_SerialCom->putChar(c);
-      }
-    }
-
-    if(dynamic_cast<const DS485CommandFrame*>(_pFrame) != NULL) {
-      // send crc
-      unsigned char c = static_cast<unsigned char>(crc & 0xFF);
-      putCharOnWire(c);
-      c = static_cast<unsigned char>((crc >> 8) & 0xFF);
-      putCharOnWire(c);
-    }
-    if(_freeFrame) {
-      delete _pFrame;
-    }
-    return true;
-  } // putFrameOnWire
-
-  bool DS485Controller::resetSerialLine() {
-    m_SerialCom.reset(new SerialCom());
-    try {
-      Logger::getInstance()->log("DS485Controller::execute: Opening '" + m_RS485DeviceName + "' as serial device", lsInfo);
-      m_SerialCom->open(m_RS485DeviceName.c_str());
-      m_FrameReader.setSerialCom(m_SerialCom);
-      return true;
-    } catch(const std::runtime_error& _ex) {
-      Logger::getInstance()->log(std::string("Caught exception while opening serial port: ") + _ex.what(), lsFatal);
-      return false;
-    }
-  } // resetSerialLine
-
-  void DS485Controller::execute() {
-    if(!resetSerialLine()) {
-      doChangeState(csError);
-      return;
-    }
-    doChangeState(csInitial);
-    m_TokenCounter = 0;
-    m_NextStationID = 0xFF;
-    m_StationID = 0xFF;
-    time_t responseSentAt;
-    time_t tokenReceivedAt;
-    m_DSID = dsid_t::fromString(DSS::getInstance()->getPropertySystem().getStringValue("/system/dsid"));
-
-    // prepare token frame
-    boost::scoped_ptr<DS485Frame> token(new DS485Frame());
-    // prepare solicit successor response frame
-    boost::scoped_ptr<DS485CommandFrame> solicitSuccessorResponseFrame(new DS485CommandFrame());
-    solicitSuccessorResponseFrame->getHeader().setDestination(0);
-    solicitSuccessorResponseFrame->getHeader().setSource(0x3F);
-    solicitSuccessorResponseFrame->setCommand(CommandSolicitSuccessorResponse);
-    solicitSuccessorResponseFrame->getPayload().add(m_DSID);
-
-    int senseTimeMS = 0;
-    int numberOfJoinPacketsToWait = -1;
-    bool lastSentWasToken = false;
-    int comErrorSleepTimeScaler = 1;
-    int missedFramesCounter = 0;
-
-    while(!m_Terminated) {
-
-      if(m_State == csInitial) {
-        senseTimeMS = (rand() % 1000) + 2500;
-        numberOfJoinPacketsToWait = -1;
-        m_TokenCounter = 0;
-        lastSentWasToken = false;
-        doChangeState(csSensing);
-        continue;
-      } else if(m_State == csCommError) {
-        sleepMS(comErrorSleepTimeScaler++ * 500);
-        comErrorSleepTimeScaler = std::min(comErrorSleepTimeScaler, 60);
-        if(resetSerialLine()) {
-          doChangeState(csInitial);
-        }
-        continue;
-      } else if(m_State == csSensing) {
-        try {
-          if(m_FrameReader.senseTraffic(senseTimeMS)) {
-            Logger::getInstance()->log("Sensed traffic on the line, changing to csSlaveWaitingToJoin");
-            // wait some time for the first frame and skip it...
-            delete m_FrameReader.getFrame(1000);
-            doChangeState(csSlaveWaitingToJoin);
-          } else {
-            Logger::getInstance()->log("No traffic on line, I'll be your master today");
-            doChangeState(csDesignatedMaster);
-          }
-          comErrorSleepTimeScaler = 1;
-        } catch(const std::runtime_error&) {
-          doChangeState(csCommError);
-        }
-        continue;
-      }
-
-      boost::scoped_ptr<DS485Frame> frame;
-      try {
-        frame.reset(getFrameFromWire());
-      } catch(const std::runtime_error&) {
-        doChangeState(csCommError);
-        continue;
-      }
-      if(frame == NULL) {
-        if(m_State != csDesignatedMaster) {
-          std::cout << "§";
-          missedFramesCounter++;
-          if(missedFramesCounter == 50) {
-            missedFramesCounter = 0;
-            std::cout << "haven't received any frames for 50 iterations, restarting..." << std::endl;
-            doChangeState(csInitial);
-          }
-        } else {
-          sleepMS(1000);
-        }
-        // resend token after timeout
-        if(lastSentWasToken) {
-          putFrameOnWire(token.get(), false);
-          lastSentWasToken = false;
-          std::cout << "t(#)";
-        }
-        flush(std::cout);
-      } else {
-        DS485Header& header = frame->getHeader();
-
-        if (header.getSource() == m_StationID) {
-          continue;
-        }
-
-        DS485CommandFrame* cmdFrame = dynamic_cast<DS485CommandFrame*>(frame.get());
-        lastSentWasToken = false;
-        missedFramesCounter = 0;
-
-        // discard packets which are not addressed to us
-        if(!header.isBroadcast() &&
-           (header.getDestination() != m_StationID) &&
-              (m_State == csSlave ||
-               m_State == csMaster)
-          )
-        {
-/*
-          Logger::getInstance()->log("packet not for me, discarding");
-          std::cout << "dest: " << (int)header.getDestination() << std::endl;
-          std::cout << "src:  " << (int)header.getSource() << std::endl;
-          if(cmdFrame != NULL) {
-            std::cout << "cmd:  " << CommandToString(cmdFrame->getCommand()) << std::endl;
-          }
-*/
-          continue;
-        }
-
-        // handle cases in which we're obliged to act on disregarding our current state
-        if(cmdFrame != NULL) {
-          if(cmdFrame->getCommand() == CommandGetAddressRequest) {
-            if(header.getDestination() == m_StationID) {
-              DS485CommandFrame* frameToSend = new DS485CommandFrame();
-              frameToSend->getHeader().setDestination(header.getSource());
-              frameToSend->getHeader().setSource(m_StationID);
-              frameToSend->setCommand(CommandGetAddressResponse);
-              putFrameOnWire(frameToSend);
-              if(header.isBroadcast()) {
-                std::cerr << "Get address request with bc-flag set" << std::endl;
-              } else {
-                std::cout << "sent response to get address thingie" << std::endl;
-              }
-              continue;
-            }
-          }
-        }
-
-        switch(m_State) {
-        case csInitial:
-          break;
-        case csSensing:
-          break;
-        case csSlaveWaitingToJoin:
-          {
-            if(cmdFrame != NULL) {
-              if(cmdFrame->getCommand() == CommandSolicitSuccessorRequestLong) {
-                // if it's the first of it's kind, determine how many we've got to skip
-                if(numberOfJoinPacketsToWait == -1) {
-                  if(cmdFrame->getCommand() == CommandSolicitSuccessorRequest) {
-                    numberOfJoinPacketsToWait = rand() % 10 + 10;
-                  } else {
-                    // don’t wait forever if we’re in slow-joining mode
-                    numberOfJoinPacketsToWait = rand() % 10;
-                  }
-                  std::cout << "** Waiting for " << numberOfJoinPacketsToWait << std::endl;
-                } else {
-                  numberOfJoinPacketsToWait--;
-                  if(numberOfJoinPacketsToWait == 0) {
-                    m_StationID = 0x3F;
-                    putFrameOnWire(solicitSuccessorResponseFrame.get(), false);
-                    //std::cout << "******* FRAME AWAY ******" << std::endl;
-                    doChangeState(csSlaveJoining);
-                    time(&responseSentAt);
-                  }
-                  //std::cout << numberOfJoinPacketsToWait << std::endl;
-                }
-              }
-            }
-          }
-          break;
-        case csSlaveJoining:
-          if(cmdFrame != NULL) {
-            if(cmdFrame->getCommand() == CommandSetDeviceAddressRequest) {
-              m_StationID = cmdFrame->getPayload().toChar().at(0);
-              DS485CommandFrame* frameToSend = new DS485CommandFrame();
-              frameToSend->getHeader().setDestination(0);
-              frameToSend->getHeader().setSource(m_StationID);
-              frameToSend->setCommand(CommandSetDeviceAddressResponse);
-              putFrameOnWire(frameToSend);
-              std::cout << "### new address " << m_StationID << "\n";
-            } else if(cmdFrame->getCommand() == CommandSetSuccessorAddressRequest) {
-              if(header.getDestination() == m_StationID) {
-                handleSetSuccessor(cmdFrame);
-              }
-            } else {
-              // check if our response has timed-out
-              time_t now;
-              time(&now);
-              if((now - responseSentAt) > 5) {
-                doChangeState(csInitial);
-                Logger::getInstance()->log("DS485: startup timeout", lsError);
-              }
-            }
-            if((m_StationID != 0x3F) && (m_NextStationID != 0xFF)) {
-              Logger::getInstance()->log("DS485: joined network", lsInfo);
-              token->getHeader().setDestination(m_NextStationID);
-              token->getHeader().setSource(m_StationID);
-              doChangeState(csSlaveWaitingForFirstToken);
-              time(&tokenReceivedAt);
-            }
-          }
-          break;
-        case csBroadcastingDSID:
-          break;
-        case csMaster:
-          break;
-        case csSlave:
-          if(cmdFrame == NULL) {
-//            std::cout << "+";
-            // it's a token
-            if(!m_PendingFrames.empty() && (m_TokenCounter > 10)) {
-
-              // send frame
-              m_PendingFramesGuard.lock();
-              DS485CommandFrame& frameToSend = m_PendingFrames.front();
-              putFrameOnWire(&frameToSend, false);
-              std::cout << "p%" << (int)frameToSend.getCommand() << "%e" << std::endl;
-
-              // if not a broadcast, wait for ack, etc
-              if(frameToSend.getHeader().isBroadcast()) {
-                m_PendingFrames.erase(m_PendingFrames.begin());
-              } else {
-                boost::shared_ptr<DS485Frame> ackFrame(m_FrameReader.getFrame(50));
-
-                DS485CommandFrame* cmdAckFrame = dynamic_cast<DS485CommandFrame*>(ackFrame.get());
-                if (cmdAckFrame->getHeader().getSource() == m_StationID) {
-                  ackFrame.reset( m_FrameReader.getFrame(50) );
-                }
-
-                cmdAckFrame = dynamic_cast<DS485CommandFrame*>(ackFrame.get());
-                if(cmdAckFrame != NULL) {
-                  if(cmdAckFrame->getCommand() == CommandAck) {
-                    m_PendingFrames.erase(m_PendingFrames.begin());
-                    std::cout << "\ngot ack" << std::endl;
-                  } else if(cmdAckFrame->getCommand() == CommandBusy) {
-                    std::cout << "\nmodulator is busy" << std::endl;
-                  } else {
-                    m_PendingFrames.erase(m_PendingFrames.begin());
-                    std::cout << "\n&&&&got other" << std::endl;
-                    addToReceivedQueue(cmdAckFrame);
-                  }
-                } else {
-                  m_PendingFrames.erase(m_PendingFrames.begin());
-                  std::cout << "no ack received" << std::endl;
-                }
-              }
-            }
-            m_PendingFramesGuard.unlock();
-            putFrameOnWire(token.get(), false);
-//            std::cout << ".";
-//            flush(std::cout);
-            time(&tokenReceivedAt);
-            m_TokenEvent.broadcast();
-            m_TokenCounter++;
-            lastSentWasToken = true;
-          } else {
-
-            // Handle token timeout
-            time_t now;
-            time(&now);
-            if((now - tokenReceivedAt) > 15) {
-              std::cerr << "restarting" << std::endl;
-              doChangeState(csInitial);
-              continue;
-            }
-            std::cout << "f*" << (int)cmdFrame->getCommand() << "*";
-
-            bool keep = false;
-
-            if(cmdFrame->getCommand() == CommandResponse) {
-              if(!cmdFrame->getHeader().isBroadcast()) {
-                // send ack if it's a response and not a broadcasted one
-                DS485CommandFrame* ack = new DS485CommandFrame();
-                ack->getHeader().setSource(m_StationID);
-                ack->getHeader().setDestination(cmdFrame->getHeader().getSource());
-                ack->setCommand(CommandAck);
-                putFrameOnWire(ack);
-                std::cout << "a(res)";
-              } else {
-                std::cout << "b";
-              }
-              keep = true;
-            } else if(cmdFrame->getCommand() == CommandRequest || cmdFrame->getCommand() == CommandEvent) {
-              if(!cmdFrame->getHeader().isBroadcast()) {
-                DS485CommandFrame* ack = new DS485CommandFrame();
-                ack->getHeader().setSource(m_StationID);
-                ack->getHeader().setDestination(cmdFrame->getHeader().getSource());
-                ack->setCommand(CommandAck);
-                putFrameOnWire(ack);
-                std::cout << "a(req)";
-              }
-              keep = true;
-            } else if(cmdFrame->getCommand() == CommandSolicitSuccessorRequest) {
-              std::cout << "SSRS -> reset" << std::endl;
-              flush(std::cout);
-              doChangeState(csInitial);
-            } else if(cmdFrame->getCommand() == CommandSetSuccessorAddressRequest) {
-              if(header.getDestination() == m_StationID) {
-                handleSetSuccessor(cmdFrame);
-                token->getHeader().setDestination(m_NextStationID);
-              }
-            } else {
-              std::cout << "&&&&&&&&&& unknown frame id: " << (int)cmdFrame->getCommand() << std::endl;
-            }
-            if(keep) {
-              // put in into the received queue
-              addToReceivedQueue(cmdFrame);
-              std::cout << "k";
-            }
-            flush(std::cout);
-          }
-          break;
-        case csSlaveWaitingForFirstToken:
-          {
-            if(cmdFrame == NULL) {
-              if(header.getDestination() == m_StationID) {
-                putFrameOnWire(token.get(), false);
-                m_TokenCounter = 0;
-                doChangeState(csSlave);
-                time(&tokenReceivedAt);
-                std::cout << "DS485: Got first TOKEN" << std::endl;
-                flush(std::cout);
-              }
-            }
-            // Handle timeout
-            time_t now;
-            time(&now);
-            if((now - tokenReceivedAt) > 15) {
-              std::cerr << "DS485: Wait for token timeout, restarting" << std::endl;
-              doChangeState(csInitial);
-              continue;
-            }
-          }
-          break;
-        case csDesignatedMaster:
-          sleepMS(10000);
-          doChangeState(csInitial);
-          break;
-        default:
-          throw std::runtime_error("invalid value for m_State");
-        }
-      }
-    }
-  } // execute
-
-  void DS485Controller::handleSetSuccessor(DS485CommandFrame* _frame) {
-    m_NextStationID = _frame->getPayload().toChar().at(0);
-    DS485CommandFrame* frameToSend = new DS485CommandFrame();
-    frameToSend->getHeader().setDestination(0);
-    frameToSend->getHeader().setSource(m_StationID);
-    frameToSend->setCommand(CommandSetSuccessorAddressResponse);
-    putFrameOnWire(frameToSend);
-    std::cout << "### successor " << m_NextStationID << "\n";
-  } // handleSetSuccessor
-
-  // TODO: look into boost::weak_ptr
-  void DS485Controller::addToReceivedQueue(DS485CommandFrame* _frame) {
-    if(_frame == NULL) {
-      Logger::getInstance()->log("DS485Controller::addToReceivedQueue: _frame is NULL", lsFatal);
-      return;
-    }
-    boost::shared_ptr<DS485CommandFrame> frame(new DS485CommandFrame());
-    (*frame) = *_frame;
-    frame->setFrameSource(fsWire);
-    distributeFrame(frame);
-    // Signal our listeners
-    m_CommandFrameEvent.signal();
-  } // addToReceivedQueue
-
-  void DS485Controller::doChangeState(aControllerState _newState) {
-    if(_newState != m_State) {
-      m_State = _newState;
-      m_StateString = controllerStateToString(m_State);
-      if(m_State == csInitial) {
-        m_NextStationID = 0xFF;
-        m_StationID = 0xFF;
-      }
-      m_ControllerEvent.signal();
-    }
-  } // doChangeState
-
-  void DS485Controller::enqueueFrame(DS485CommandFrame& _frame) {
-    //Logger::getInstance()->log("Frame queued");
-    DS485CommandFrame* frame = new DS485CommandFrame();
-    *frame = _frame;
-    frame->getHeader().setSource(m_StationID);
-    m_PendingFramesGuard.lock();
-    m_PendingFrames.push_back(frame);
-    m_PendingFramesGuard.unlock();
-  } // enqueueFrame
-
-  bool DS485Controller::waitForEvent(const int _timeoutMS) {
-    return m_ControllerEvent.waitFor(_timeoutMS);
-  } // waitForEvent
-
-  aControllerState DS485Controller::getState() const {
-    return m_State;
-  } // getState
-
-  const std::string& DS485Controller::getStateAsString() const {
-    return m_StateString;
-  } // getStateAsString
-
-  void DS485Controller::waitForCommandFrame() {
-    m_CommandFrameEvent.waitFor();
-  } // waitForCommandFrame
-
-  void DS485Controller::waitForToken() {
-    m_TokenEvent.waitFor();
-  } // waitForToken
-
-
-  //================================================== DS485FrameReader
-
-  DS485FrameReader::DS485FrameReader() {
-    m_ValidBytes = 0;
-    m_State = rsSynchronizing;
-    m_MessageLength = -1;
-
-    m_EscapeNext = false;
-    m_IsEscaped = false;
-
-    m_NumberOfFramesReceived = 0;
-    m_NumberOfIncompleteFramesReceived = 0;
-    m_NumberOfCRCErrors = 0;
-  } // ctor
-
-  DS485FrameReader::~DS485FrameReader() {
-  } // dtor
-
-  void DS485FrameReader::setSerialCom(boost::shared_ptr<SerialComBase> _serialCom) {
-    m_SerialCom = _serialCom;
-  } // setHandle
-
-  bool DS485FrameReader::getCharTimeout(char& _charOut, const int _timeoutMS) {
-    return m_SerialCom->getCharTimeout(_charOut, _timeoutMS);
-  } // getCharTimeout
-
-  bool DS485FrameReader::senseTraffic(const int _timeoutMS) {
-    char tmp;
-    return getCharTimeout(tmp, _timeoutMS);
-  } // senseTraffic
-
-  const int TheHeaderSize = 3;
-  const int TheFrameHeaderSize = TheHeaderSize + 1;
-  const int TheCRCSize = 2;
-
-  DS485Frame* DS485FrameReader::getFrame(const int _timeoutMS) {
-    struct timeval timeStarted;
-    gettimeofday(&timeStarted, 0);
-    while(true) {
-      struct timeval now;
-      gettimeofday(&now, 0);
-      int diffMS = (now.tv_sec - timeStarted.tv_sec) * 1000 + (now.tv_usec - timeStarted.tv_usec) / 1000;
-      if(diffMS > _timeoutMS) {
-        flush(std::cout);
-        if(m_State == rsSynchronizing || m_ValidBytes == 0) {
-          break;
-        }
-        m_NumberOfIncompleteFramesReceived++;
-        return NULL;
-      }
-
-      char currentChar;
-      if(getCharTimeout(currentChar, 1)) {
-
-        if((unsigned char)currentChar == EscapeCharacter) {
-          m_EscapeNext = true;
-          continue;
-        }
-
-        if((unsigned char)currentChar == FrameStart) {
-          m_State = rsSynchronizing;
-          m_ValidBytes = 0;
-        }
-
-        if(m_EscapeNext) {
-          currentChar |= 0x80;
-          m_EscapeNext = false;
-          m_IsEscaped = true;
-        } else {
-          m_IsEscaped = false;
-        }
-
-        // store in our receive buffer
-        m_ReceiveBuffer[m_ValidBytes++] = currentChar;
-
-        if(m_ValidBytes == TheReceiveBufferSizeBytes) {
-          Logger::getInstance()->log("receive buffer overflowing, resyncing", lsInfo);
-          m_State = rsSynchronizing;
-          m_ValidBytes = 0;
-        }
-
-        switch(m_State) {
-          case rsSynchronizing:
-          {
-            if(((unsigned char)currentChar == FrameStart) && !m_IsEscaped) {
-              m_State = rsReadingHeader;
-            } else {
-              std::cout << "?";
-            }
-            break;
-          }
-
-          case rsReadingHeader:
-          {
-            if(m_ValidBytes < 1) {
-              Logger::getInstance()->log("in state rsReadingPacket with validBytes < 1, going back to sync", lsError);
-            }
-
-            // attempt to parse the header
-            if(m_ValidBytes == TheHeaderSize) {
-              if((m_ReceiveBuffer[1] & 0x02) == 0x02) {
-                //Logger::getInstance()->log("Packet is a broadcast");
-              } else {
-                //Logger::getInstance()->log("*Packet is adressed");
-              }
-              // check if it's a token or not
-              if((m_ReceiveBuffer[1] & 0x01) == 0x01) {
-                //Logger::getInstance()->log("Packet is a Frame");
-                m_State = rsReadingPacket;
-                m_MessageLength = -1;
-              } else {
-                //Logger::getInstance()->log("Packet is a Token");
-                DS485Frame* frame = new DS485Frame();
-                frame->getHeader().fromChar(m_ReceiveBuffer, m_ValidBytes);
-                m_NumberOfFramesReceived++;
-
-                //std::cout << "-";
-                //flush(std::cout);
-                m_State = rsSynchronizing;
-                return frame;
-              }
-            }
-            break;
-          }
-
-          case rsReadingPacket:
-          {
-            if(m_MessageLength == -1 && m_ValidBytes >= TheFrameHeaderSize) {
-              // the length does not include the size of the headers
-              m_MessageLength = m_ReceiveBuffer[3] & 0x0F;
-            }
-            if(m_ValidBytes == (m_MessageLength + TheFrameHeaderSize)) {
-              //Logger::getInstance()->log("frame received");
-              m_State = rsReadingCRC;
-            }
-            break;
-          }
-
-          case rsReadingCRC:
-          {
-            if(m_ValidBytes == (m_MessageLength + TheFrameHeaderSize + TheCRCSize)) {
-              uint16_t dataCRC = crc16(m_ReceiveBuffer, m_ValidBytes);
-              if(dataCRC != 0) {
-                Logger::getInstance()->log("*********** crc mismatch.", lsError);
-                m_NumberOfCRCErrors++;
-              } else {
-                //Logger::getInstance()->log("received packet, crc ok");
-                //std::cout << "#";
-                m_NumberOfFramesReceived++;
-              }
-              DS485CommandFrame* frame = new DS485CommandFrame();
-              frame->getHeader().fromChar(m_ReceiveBuffer, m_ValidBytes);
-              frame->setLength(m_ReceiveBuffer[3] & 0x0F);
-              frame->setCommand(m_ReceiveBuffer[3] >> 4 & 0x0F);
-              for(int iByte = 0; iByte < m_MessageLength; iByte++) {
-                frame->getPayload().add<uint8_t>(static_cast<uint8_t>(m_ReceiveBuffer[iByte + 4]));
-              }
-              //std::cout << "*" << frame->getCommand() << "*";
-              //flush(std::cout);
-
-              // the show must go on...
-              m_MessageLength = -1;
-              m_State = rsSynchronizing;
-              return frame;
-            }
-          }
-        }
-      }
-    }
-    return NULL;
-  } // getFrame
-
-  //================================================== DS485FrameProvider
-
-  void DS485FrameProvider::addFrameCollector(IDS485FrameCollector* _collector) {
-    m_FrameCollectors.push_back(_collector);
-  } // addFrameCollector
-
-  void DS485FrameProvider::removeFrameCollector(IDS485FrameCollector* _collector) {
-    std::vector<IDS485FrameCollector*>::iterator iCollector = find(m_FrameCollectors.begin(), m_FrameCollectors.end(), _collector);
-    if(iCollector != m_FrameCollectors.end()) {
-      m_FrameCollectors.erase(iCollector);
-    }
-  } // removeFrameCollector
-
-  void DS485FrameProvider::distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
-    for(std::vector<IDS485FrameCollector*>::iterator iCollector = m_FrameCollectors.begin(), e = m_FrameCollectors.end();
-        iCollector != e; ++iCollector)
-    {
-      (*iCollector)->collectFrame(_frame);
-    }
-  } // distributeFrame
-
-  void DS485FrameProvider::distributeFrame(DS485CommandFrame* _pFrame) {
-    boost::shared_ptr<DS485CommandFrame> tempRef(_pFrame);
-    distributeFrame(tempRef);
-  } // distributeFrame
-
-
-  //================================================== PayloadDissector
-
-  template<>
-  uint8_t PayloadDissector::get() {
-    uint8_t result = m_Payload.back();
-    m_Payload.pop_back();
-    return result;
-  }
-
-  template<>
-  uint32_t PayloadDissector::get() {
-    uint32_t result;
-    result = (get<uint8_t>() <<  0) |
-             (get<uint8_t>() <<  8) |
-             (get<uint8_t>() << 16) |
-             (get<uint8_t>() << 24);
-    return result;
-  }
-
-  template<>
-  dsid_t PayloadDissector::get() {
-    dsid_t result;
-    result.upper = 0;
-    for(int iByte = 0; iByte < 8; iByte++) {
-      result.upper |= ((uint64_t)get<uint8_t>() << ((8 - iByte - 1) * 8));
-    }
-    result.lower  = (get<uint8_t>() << 24);
-    result.lower |= (get<uint8_t>() << 16);
-    result.lower |= (get<uint8_t>() <<  8);
-    result.lower |= (get<uint8_t>() <<  0);
-
-    return result;
-  }
-
-  template<>
-  uint16_t PayloadDissector::get() {
-    uint16_t result;
-    result = (get<uint8_t>() << 0)  |
-             (get<uint8_t>() << 8);
-    return result;
-  }
-
-  //================================================== DS485FrameSniffer
-#ifndef __APPLE__
-  DS485FrameSniffer::DS485FrameSniffer(const std::string& _deviceName)
-  {
-     m_SerialCom.reset(new SerialCom());
-     m_SerialCom->open(_deviceName.c_str());
-     m_FrameReader.setSerialCom(m_SerialCom);
-  }
-
-  void DS485FrameSniffer::run() {
-    struct timespec lastFrame;
-    struct timespec thisFrame;
-    clock_gettime(CLOCK_REALTIME, &lastFrame);
-    while(true) {
-      boost::scoped_ptr<DS485Frame> frame(m_FrameReader.getFrame(500));
-      if(frame.get() != NULL){
-        clock_gettime(CLOCK_REALTIME, &thisFrame);
-        if(frame.get() != NULL) {
-
-          double diffMS = ((thisFrame.tv_sec*1000.0 + thisFrame.tv_nsec/1000.0/1000.0) -
-                           (lastFrame.tv_sec*1000.0 + lastFrame.tv_nsec/1000.0/1000.0));
-
-          std::cout << "+" << diffMS << "\n";
-
-          DS485CommandFrame* cmdFrame = dynamic_cast<DS485CommandFrame*>(frame.get());
-          if(cmdFrame != NULL) {
-            uint8_t cmd = cmdFrame->getCommand();
-            std::cout << "Command Frame: " << commandToString(cmd) <<  " " << "(" <<  (int)cmd << ") " << (int)frame->getHeader().getSource() << " -> " << (int)frame->getHeader().getDestination()  << "\n";
-
-            if(cmd == CommandRequest || cmd == CommandResponse) {
-              PayloadDissector pd(cmdFrame->getPayload());
-              std::cout << (int)pd.get<uint8_t>() << "\n";
-            }
-          } else {
-            std::cout << "token " << (int)frame->getHeader().getSource() << " -> " << (int)frame->getHeader().getDestination()  << "\n";
-          }
-          std::cout << "seq: " << (int)frame->getHeader().getCounter() << std::endl;
-
-          lastFrame = thisFrame;
-        }
-      }
-    }
-  }
-#endif
-
-  //================================================== Global helpers
-
-  const char* commandToString(const uint8_t _command) {
-    switch(_command) {
-    case CommandSolicitSuccessorRequestLong:
-      return "solicit successor request long";
-    case CommandSolicitSuccessorRequest:
-      return "solicit successor request";
-    case CommandSolicitSuccessorResponse:
-      return "solicit successor response";
-    case CommandGetAddressRequest:
-      return "get address request";
-    case CommandGetAddressResponse:
-      return "get address response";
-    case CommandSetDeviceAddressRequest:
-      return "set device address request";
-    case CommandSetDeviceAddressResponse:
-      return "set device address response";
-    case CommandSetSuccessorAddressRequest:
-      return "set successor address request";
-    case CommandSetSuccessorAddressResponse:
-      return "set successor address response";
-    case CommandRequest:
-      return "request";
-    case CommandResponse:
-      return "response";
-    case CommandAck:
-      return "ack";
-    case CommandBusy:
-      return "busy";
-    default:
-      return "(unknown)";
-    }
-  } // commandToString
-
-  const char* controllerStateToString(const aControllerState _state) {
-    switch(_state) {
-    case csInitial:
-      return "initial";
-    case csSensing:
-      return "sensing";
-    case csDesignatedMaster:
-      return "designated master";
-    case csBroadcastingDSID:
-      return "broadcasting DSID";
-    case csMaster:
-      return "master";
-    case csSlaveWaitingToJoin:
-      return "slave waiting to join";
-    case csSlaveJoining:
-      return "slave joining";
-    case csSlave:
-      return "slave";
-    case csSlaveWaitingForFirstToken:
-      return "slave waiting for first token";
-    case csError:
-      return "error";
-    case csCommError:
-      return "comm error";
-    default:
-      return "(unknown)";
-    }
-  } // controllerStateToString
-
-  const dsid_t NullDSID(0,0);
-
-}
diff --git a/unix/ds485.h b/unix/ds485.h
deleted file mode 100644
index eb4d199..0000000
--- a/unix/ds485.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 _DS485_H_INCLUDED
-#define _DS485_H_INCLUDED
-
-#include "core/thread.h"
-#include "serialcom.h"
-#include "core/ds485types.h"
-#include "core/syncevent.h"
-
-#include <vector>
-#include <string>
-
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <boost/shared_ptr.hpp>
-
-namespace dss {
-
-  /** Stores the payload of a DS485Frame */
-  class DS485Payload {
-  private:
-    std::vector<unsigned char> m_Data;
-  public:
-    /** Adds \a _data to the payload. */
-    template<class t>
-    void add(t _data);
-
-    /** Returns the size of the payload added.*/
-    int size() const;
-
-    /** Returns a const reference of the data */
-    const std::vector<unsigned char>& toChar() const;
-  }; // DS485Payload
-
-  /** Wrapper for a DS485 header. */
-  class DS485Header {
-  private:
-    uint8_t m_Type;
-    uint8_t m_Counter;
-    uint8_t m_Source;
-    bool m_Broadcast;
-    uint8_t m_Destination;
-  public:
-    DS485Header()
-    : m_Type(0x00),
-      m_Counter(0x00),
-      m_Source(0xff),
-      m_Broadcast(false),
-      m_Destination(0xff)
-    {};
-
-    /** Returns the destination of the frame.
-     * @note This field may not contain any useful information if isBroadcast
-     * returns \c true */
-    uint8_t getDestination() const { return m_Destination; };
-    /** Returns whether the the frame is a broadcast or not. */
-    bool isBroadcast() const { return m_Broadcast; };
-    /** Returns the source of the frame */
-    uint8_t getSource() const { return m_Source; };
-    /** Returns the counter of the frame.
-     * The use of this field is mostly for debugging purposes. Implementors
-     * should increase it every packet they send to detect dropped frames. */
-    uint8_t getCounter() const { return m_Counter; };
-    uint8_t getType() const { return m_Type; };
-
-    void setDestination(const uint8_t _value) { m_Destination = _value; };
-    void setBroadcast(const bool _value) { m_Broadcast = _value; };
-    void setSource(const uint8_t _value) { m_Source = _value; };
-    void setCounter(const uint8_t _value) { m_Counter = _value; };
-    void setType(const uint8_t _value) { m_Type = _value; };
-
-    std::vector<unsigned char> toChar() const;
-    void fromChar(const unsigned char* _data, const int _len);
-  };
-
-  typedef enum {
-    fsWire,
-    fsDSS
-  } aFrameSource;
-
-  class DS485Frame {
-  private:
-    DS485Header m_Header;
-    DS485Payload m_Payload;
-    aFrameSource m_FrameSource;
-  public:
-    DS485Frame()
-    : m_FrameSource(fsDSS)
-    {}
-    virtual ~DS485Frame() {}
-
-    DS485Header& getHeader() { return m_Header; }
-
-    DS485Payload& getPayload();
-    const DS485Payload& getPayload() const;
-
-    aFrameSource getFrameSource() const { return m_FrameSource; }
-    void setFrameSource(aFrameSource _value) { m_FrameSource = _value; }
-
-    virtual std::vector<unsigned char> toChar() const;
-  }; // DS485Frame
-
-  class DS485CommandFrame : public DS485Frame {
-  private:
-    uint8_t m_Command;
-    uint8_t m_Length;
-  public:
-    DS485CommandFrame();
-    virtual ~DS485CommandFrame() {};
-
-    uint8_t getCommand() const { return m_Command; };
-    uint8_t getLength() const { return m_Length; };
-
-    void setCommand(const uint8_t _value) { m_Command = _value; };
-    void setLength(const uint8_t _value) { m_Length = _value; };
-
-    virtual std::vector<unsigned char> toChar() const;
-  };
-
-  class IDS485FrameCollector;
-
-  /** A frame provider receives frames from somewhere */
-  class DS485FrameProvider {
-  private:
-    std::vector<IDS485FrameCollector*> m_FrameCollectors;
-  protected:
-    /** Distributes the frame to the collectors */
-    void distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame);
-    /** Distributes the frame to the collectors.
-     * NOTE: the ownership of the frame is transfered to the frame provider
-     */
-    void distributeFrame(DS485CommandFrame* _pFrame);
-  public:
-    void addFrameCollector(IDS485FrameCollector* _collector);
-    void removeFrameCollector(IDS485FrameCollector* _collector);
-  };
-
-  typedef enum {
-    csInitial,
-    csSensing,
-    csDesignatedMaster,
-    csBroadcastingDSID,
-    csMaster,
-    csSlaveWaitingToJoin,
-    csSlaveJoining,
-    csSlave,
-    csSlaveWaitingForFirstToken,
-    csError,
-    csCommError
-  } aControllerState;
-
-  typedef enum {
-    rsSynchronizing,
-    rsReadingHeader,
-    rsReadingPacket,
-    rsReadingCRC
-  } aReaderState;
-
-  const int TheReceiveBufferSizeBytes = 50;
-
-  class DS485FrameReader {
-  private:
-    // receive functions's state
-    int m_ValidBytes;
-    unsigned char m_ReceiveBuffer[TheReceiveBufferSizeBytes];
-    aReaderState m_State;
-    int m_MessageLength;
-
-    bool m_EscapeNext;
-    bool m_IsEscaped;
-    int m_NumberOfFramesReceived;
-    int m_NumberOfIncompleteFramesReceived;
-    int m_NumberOfCRCErrors;
-  private:
-    int m_Handle;
-    boost::shared_ptr<SerialComBase> m_SerialCom;
-  private:
-    bool getCharTimeout(char& _charOut, const int _timeoutMS);
-  public:
-    DS485FrameReader();
-    virtual ~DS485FrameReader();
-
-    void setSerialCom(boost::shared_ptr<SerialComBase> _serialCom);
-
-    DS485Frame* getFrame(const int _timeoutMS);
-    bool senseTraffic(const int _timeoutMS);
-
-    int getNumberOfFramesReceived() const { return m_NumberOfFramesReceived; }
-    int getNumberOfIncompleteFramesReceived() const { return m_NumberOfIncompleteFramesReceived; }
-    int getNumberOfCRCErrors() const { return m_NumberOfCRCErrors; }
-  }; // FrameReader
-
-  class DS485Controller : public Thread,
-                          public DS485FrameProvider {
-  private:
-    aControllerState m_State;
-    DS485FrameReader m_FrameReader;
-    std::string m_RS485DeviceName;
-    std::string m_StateString;
-    int m_StationID;
-    int m_NextStationID;
-    int m_TokenCounter;
-
-    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;
-  private:
-    DS485Frame* getFrameFromWire();
-    bool putFrameOnWire(const DS485Frame* _pFrame, bool _freeFrame = true);
-
-    inline void putCharOnWire(const unsigned char _ch);
-
-    void doChangeState(aControllerState _newState);
-    void addToReceivedQueue(DS485CommandFrame* _frame);
-    bool resetSerialLine();
-
-    void handleSetSuccessor(DS485CommandFrame* _frame);
-  public:
-    DS485Controller();
-    virtual ~DS485Controller();
-
-    void setRS485DeviceName(const std::string& _value);
-    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; };
-
-    const std::string& getStateAsString() const;
-
-    const DS485FrameReader& getFrameReader() const { return m_FrameReader; }
-
-    virtual void execute();
-
-    int getStationID() const { return m_StationID; }
-
-    void setDSID(const dsid_t& _value) { m_DSID = _value; }
-  }; // DS485Controller
-
-  class IDS485FrameCollector {
-  public:
-    virtual void collectFrame(boost::shared_ptr<DS485CommandFrame> _frame) = 0;
-    virtual ~IDS485FrameCollector() {};
-  }; // DS485FrameCollector
-
-  class DS485FrameSniffer {
-  private:
-    DS485FrameReader m_FrameReader;
-    boost::shared_ptr<SerialCom> m_SerialCom;
-  public:
-    DS485FrameSniffer(const std::string& _deviceName);
-
-    void run();
-  }; // IDS485FrameSniffer
-
-  class PayloadDissector {
-  private:
-    std::vector<unsigned char> m_Payload;
-  public:
-    PayloadDissector(DS485Payload& _payload) {
-      const std::vector<unsigned char>& payload =_payload.toChar();
-      m_Payload.insert(m_Payload.begin(), payload.rbegin(), payload.rend());
-    }
-
-    bool isEmpty() { return m_Payload.empty(); };
-
-    template<class t>
-    t get();
-  }; // PayloadDissector
-
-  const char* commandToString(const uint8_t _command);
-
-  const uint32_t SimulationPrefix = 0xFFC00000;
-  inline bool isSimulationDSID(const dsid_t _dsid) {
-    return (_dsid.lower & SimulationPrefix) == SimulationPrefix;
-  }
-
-}
-
-#endif
diff --git a/unix/ds485proxy.cpp b/unix/ds485proxy.cpp
deleted file mode 100644
index 755d3d5..0000000
--- a/unix/ds485proxy.cpp
+++ /dev/null
@@ -1,1690 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 "ds485proxy.h"
-
-#include "core/model.h"
-#include "core/dss.h"
-#include "core/logger.h"
-#include "core/ds485const.h"
-#include "core/event.h"
-#include "core/propertysystem.h"
-#include "core/foreach.h"
-
-#ifdef WITH_SIM
-#include "core/sim/dssim.h"
-#endif
-
-#include <sstream>
-
-namespace dss {
-
-  const char* FunctionIDToString(const int _functionID); // internal forward declaration
-
-  typedef hash_map<const Modulator*, Set> HashMapModulatorSet;
-
-  HashMapModulatorSet splitByModulator(const Set& _set) {
-    HashMapModulatorSet result;
-    for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
-      const DeviceReference& dev = _set.get(iDevice);
-      Modulator& mod = dev.getDevice().getApartment().getModulatorByBusID(dev.getDevice().getModulatorID());
-      result[&mod].addDevice(dev);
-    }
-    return result;
-  } // splitByModulator
-
-
-  typedef std::map<const Zone*, Set> HashMapZoneSet;
-
-  HashMapZoneSet splitByZone(const Set& _set) {
-    HashMapZoneSet result;
-    for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
-      const DeviceReference& devRef = _set.get(iDevice);
-      const Device& dev = devRef.getDevice();
-      Zone& zone = dev.getApartment().getZone(dev.getZoneID());
-      result[&zone].addDevice(dev);
-    }
-    return result;
-  } // splitByZone
-
-  typedef std::pair<std::vector<Group*>, Set> FittingResultPerModulator;
-
-  const bool OptimizerDebug = true;
-
-  /** Precondition: _set contains only devices of _zone */
-  FittingResultPerModulator bestFit(const Zone& _zone, const Set& _set) {
-    Set workingCopy = _set;
-
-    std::vector<Group*> fittingGroups;
-    Set singleDevices;
-
-    if(OptimizerDebug) {
-      Logger::getInstance()->log("Finding fit for zone " + intToString(_zone.getID()));
-    }
-
-
-    if(_zone.getDevices().length() == _set.length()) {
-      Logger::getInstance()->log(std::string("Optimization: Set contains all devices of zone ") + intToString(_zone.getID()));
-        std::bitset<63> possibleGroups;
-        possibleGroups.set();
-        for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
-          possibleGroups &= _set[iDevice].getDevice().getGroupBitmask();
-      }
-      if(possibleGroups.any()) {
-          for(unsigned int iGroup = 0; iGroup < possibleGroups.size(); iGroup++) {
-            if(possibleGroups.test(iGroup)) {
-              Logger::getInstance()->log("Sending the command to group " + intToString(iGroup + 1));
-              fittingGroups.push_back(_zone.getGroup(iGroup + 1));
-              break;
-            }
-          }
-        } else {
-          Logger::getInstance()->log("Sending the command to broadcast group");
-          fittingGroups.push_back(_zone.getGroup(GroupIDBroadcast));
-        }
-      } else {
-        std::vector<Group*> unsuitableGroups;
-        Set workingCopy = _set;
-
-      while(!workingCopy.isEmpty()) {
-        DeviceReference& ref = workingCopy.get(0);
-        workingCopy.removeDevice(ref);
-
-        if(OptimizerDebug) {
-          Logger::getInstance()->log("Working with device " + ref.getDSID().toString());
-        }
-
-        bool foundGroup = false;
-        for(int iGroup = 0; iGroup < ref.getDevice().getGroupsCount(); iGroup++) {
-        Group& g = ref.getDevice().getGroupByIndex(iGroup);
-
-            if(OptimizerDebug) {
-            Logger::getInstance()->log("  Checking Group " + intToString(g.getID()));
-          }
-        // continue if already found unsuitable
-        if(find(unsuitableGroups.begin(), unsuitableGroups.end(), &g) != unsuitableGroups.end()) {
-              if(OptimizerDebug) {
-              Logger::getInstance()->log("  Group discarded before, continuing search");
-            }
-          continue;
-        }
-
-        // see if we've got a fit
-        bool groupFits = true;
-        Set devicesInGroup = _zone.getDevices().getByGroup(g);
-            if(OptimizerDebug) {
-            Logger::getInstance()->log("    Group has " + intToString(devicesInGroup.length()) + " devices");
-          }
-        for(int iDevice = 0; iDevice < devicesInGroup.length(); iDevice++) {
-          if(!_set.contains(devicesInGroup.get(iDevice))) {
-          unsuitableGroups.push_back(&g);
-          groupFits = false;
-                if(OptimizerDebug) {
-                Logger::getInstance()->log("    Original set does _not_ contain device " + devicesInGroup.get(iDevice).getDevice().getDSID().toString());
-              }
-          break;
-          }
-              if(OptimizerDebug) {
-              Logger::getInstance()->log("    Original set contains device " + devicesInGroup.get(iDevice).getDevice().getDSID().toString());
-            }
-        }
-        if(groupFits) {
-              if(OptimizerDebug) {
-              Logger::getInstance()->log("  Found a fit " + intToString(g.getID()));
-            }
-          foundGroup = true;
-          fittingGroups.push_back(&g);
-              if(OptimizerDebug) {
-              Logger::getInstance()->log("  Removing devices from working copy");
-            }
-          while(!devicesInGroup.isEmpty()) {
-          workingCopy.removeDevice(devicesInGroup.get(0));
-            devicesInGroup.removeDevice(devicesInGroup.get(0));
-          }
-              if(OptimizerDebug) {
-              Logger::getInstance()->log("  Done. (Removing devices from working copy)");
-            }
-          break;
-        }
-      }
-
-		  // if no fitting group found
-		  if(!foundGroup) {
-  	    singleDevices.addDevice(ref);
-		  }
-    }
-  }
-    return FittingResultPerModulator(fittingGroups, singleDevices);
-  }
-
-  FittingResultPerModulator bestFit(const Modulator& _modulator, const Set& _set) {
-    Set workingCopy = _set;
-
-    std::vector<Group*> unsuitableGroups;
-    std::vector<Group*> fittingGroups;
-    Set singleDevices;
-
-    while(!workingCopy.isEmpty()) {
-      DeviceReference& ref = workingCopy.get(0);
-      workingCopy.removeDevice(ref);
-
-      bool foundGroup = false;
-      for(int iGroup = 0; iGroup < ref.getDevice().getGroupsCount(); iGroup++) {
-        Group& g = ref.getDevice().getGroupByIndex(iGroup);
-
-        // continue if already found unsuitable
-        if(find(unsuitableGroups.begin(), unsuitableGroups.end(), &g) != unsuitableGroups.end()) {
-          continue;
-        }
-
-        // see if we've got a fit
-        bool groupFits = true;
-        Set devicesInGroup = _modulator.getDevices().getByGroup(g);
-        for(int iDevice = 0; iDevice < devicesInGroup.length(); iDevice++) {
-          if(!_set.contains(devicesInGroup.get(iDevice))) {
-            unsuitableGroups.push_back(&g);
-            groupFits = false;
-            break;
-          }
-        }
-        if(groupFits) {
-          foundGroup = true;
-          fittingGroups.push_back(&g);
-          while(!devicesInGroup.isEmpty()) {
-            workingCopy.removeDevice(devicesInGroup.get(0));
-          }
-          break;
-        }
-      }
-
-      // if no fitting group found
-      if(!foundGroup) {
-        singleDevices.addDevice(ref);
-      }
-    }
-    return FittingResultPerModulator(fittingGroups, singleDevices);
-  } // bestFit
-
-  DS485Proxy::DS485Proxy(DSS* _pDSS, Apartment* _pApartment)
-  : Thread("DS485Proxy"),
-    Subsystem(_pDSS, "DS485Proxy"),
-    m_pApartment(_pApartment),
-    m_InitializeDS485Controller(true)
-  {
-    assert(_pApartment != NULL);
-    if(_pDSS != NULL) {
-      _pDSS->getPropertySystem().createProperty(getConfigPropertyBasePath() + "rs485devicename")
-            ->linkToProxy(PropertyProxyMemberFunction<DS485Controller, std::string>(m_DS485Controller, &DS485Controller::getRS485DeviceName, &DS485Controller::setRS485DeviceName));
-
-      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "tokensReceived")
-            ->linkToProxy(PropertyProxyMemberFunction<DS485Controller, int>(m_DS485Controller, &DS485Controller::getTokenCount));
-
-      const DS485FrameReader& reader = m_DS485Controller.getFrameReader();
-      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "framesReceived")
-            ->linkToProxy(PropertyProxyMemberFunction<DS485FrameReader, int>(reader, &DS485FrameReader::getNumberOfFramesReceived));
-
-      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "incompleteFramesReceived")
-            ->linkToProxy(PropertyProxyMemberFunction<DS485FrameReader, int>(reader, &DS485FrameReader::getNumberOfIncompleteFramesReceived));
-
-      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "crcErrors")
-            ->linkToProxy(PropertyProxyMemberFunction<DS485FrameReader, int>(reader, &DS485FrameReader::getNumberOfCRCErrors));
-
-      _pDSS->getPropertySystem().createProperty(getPropertyBasePath() + "state")
-            ->linkToProxy(PropertyProxyMemberFunction<DS485Controller, std::string>(m_DS485Controller, &DS485Controller::getStateAsString));
-
-      _pDSS->getPropertySystem().setStringValue("/system/dsid", "3504175FE0000000DEADBEEF", true, false);
-    }
-  } // ctor
-
-  bool DS485Proxy::isReady() {
-	  return isRunning()
-#ifdef WITH_SIM
-	         &&  DSS::getInstance()->getSimulation().isReady() // allow the simulation to run on it's own
-#endif
-	         && ((m_DS485Controller.getState() == csSlave) ||
-	             (m_DS485Controller.getState() == csDesignatedMaster) ||
-	             (m_DS485Controller.getState() == csError)); 
-  } // isReady
-
-  FittingResult DS485Proxy::bestFit(const Set& _set) {
-    FittingResult result;
-    HashMapZoneSet zoneToSet = splitByZone(_set);
-
-    for(HashMapZoneSet::iterator it = zoneToSet.begin(); it != zoneToSet.end(); ++it) {
-      result[it->first] = dss::bestFit(*(it->first), it->second);
-    }
-
-    return result;
-  } // bestFit(const Set&)
-
-  std::vector<int> DS485Proxy::sendCommand(DS485Command _cmd, const Set& _set, int _param) {
-    if(_set.length() == 1) {
-      log("Optimization: Set contains only one device");
-      return sendCommand(_cmd, _set.get(0).getDevice(), _param);
-    } else if(_set.length() > 0) {
-      Apartment& apt = _set.get(0).getDevice().getApartment();
-      if(_set.length() == apt.getDevices().length()) {
-        log("Optimization: Set contains all devices of apartment");
-        return sendCommand(_cmd, apt.getZone(0), apt.getGroup(GroupIDBroadcast), _param);
-      }
-    }
-
-    std::vector<int> result;
-    FittingResult fittedResult = bestFit(_set);
-    for(FittingResult::iterator iResult = fittedResult.begin(); iResult != fittedResult.end(); ++iResult) {
-      const Zone* zone = iResult->first;
-      FittingResultPerModulator res = iResult->second;
-      std::vector<Group*> groups = res.first;
-      for(vector<Group*>::iterator ipGroup = groups.begin(); ipGroup != groups.end(); ++ipGroup) {
-        sendCommand(_cmd, *zone, **ipGroup, _param);
-      }
-      Set& set = res.second;
-      for(int iDevice = 0; iDevice < set.length(); iDevice++) {
-        sendCommand(_cmd, set.get(iDevice).getDevice(), _param);
-      }
-    }
-    return result;
-  } // sendCommand
-
-  std::vector<int> DS485Proxy::sendCommand(DS485Command _cmd, const Zone& _zone, uint8_t _groupID, int _param) {
-    std::vector<int> result;
-
-    DS485CommandFrame frame;
-    frame.getHeader().setDestination(0);
-    frame.getHeader().setBroadcast(true);
-    frame.getHeader().setType(1);
-    frame.setCommand(CommandRequest);
-    int toZone = _zone.getID();
-    int param = _param;
-    const int kNoParam = -1;
-    if(_cmd == cmdTurnOn) {
-      frame.getPayload().add<uint8_t>(FunctionGroupCallScene);
-      param = SceneMax;
-      log("turn on: zone " + intToString(_zone.getID()) + " group: " + intToString(_groupID));
-    } else if(_cmd == cmdTurnOff) {
-      frame.getPayload().add<uint8_t>(FunctionGroupCallScene);
-      param = SceneMin;
-      log("turn off: zone " + intToString(_zone.getID()) + " group: " + intToString(_groupID));
-    } else if(_cmd == cmdCallScene) {
-      frame.getPayload().add<uint8_t>(FunctionGroupCallScene);
-      log("call scene: zone " + intToString(_zone.getID()) + " group: " + intToString(_groupID));
-    } else if(_cmd == cmdSaveScene) {
-      frame.getPayload().add<uint8_t>(FunctionGroupSaveScene);
-    } else if(_cmd == cmdUndoScene) {
-      frame.getPayload().add<uint8_t>(FunctionGroupUndoScene);
-    } else if(_cmd == cmdStartDimUp) {
-      frame.getPayload().add<uint8_t>(FunctionGroupStartDimInc);
-    } else if(_cmd == cmdStartDimDown) {
-      frame.getPayload().add<uint8_t>(FunctionGroupStartDimDec);
-    } else if(_cmd == cmdStopDim) {
-      frame.getPayload().add<uint8_t>(FunctionGroupEndDim);
-    } else if(_cmd == cmdIncreaseValue) {
-      frame.getPayload().add<uint8_t>(FunctionGroupIncreaseValue);
-      param = kNoParam;
-    } else if(_cmd == cmdDecreaseValue) {
-      frame.getPayload().add<uint8_t>(FunctionGroupDecreaseValue);
-      param = kNoParam;
-    } else if(_cmd == cmdSetValue) {
-      frame.getPayload().add<uint8_t>(FunctionGroupSetValue);
-    } else {
-      throw std::invalid_argument("DS485Proxy::sendCommand: Unknown command " + intToString(_cmd));
-    }
-    frame.getPayload().add<uint16_t>(toZone);
-    frame.getPayload().add<uint16_t>(_groupID);
-    if(param != kNoParam) {
-      frame.getPayload().add<uint16_t>(param);
-    }
-    sendFrame(frame);
-    return result;
-  } // sendCommand(zone, group)
-
-  std::vector<int> DS485Proxy::sendCommand(DS485Command _cmd, const Zone& _zone, Group& _group, int _param) {
-    return sendCommand(_cmd, _zone, _group.getID(), _param);
-  } // sendCommand
-
-  std::vector<int> DS485Proxy::sendCommand(DS485Command _cmd, const Device& _device, int _param) {
-    return sendCommand(_cmd, _device.getShortAddress(), _device.getModulatorID(), _param);
-  } // sendCommand
-
-  std::vector<int> DS485Proxy::sendCommand(DS485Command _cmd, devid_t _id, uint8_t _modulatorID, int _param) {
-    std::vector<int> result;
-    DS485CommandFrame frame;
-    frame.getHeader().setDestination(_modulatorID);
-    frame.getHeader().setBroadcast(false);
-    frame.getHeader().setType(1);
-    frame.setCommand(CommandRequest);
-    if(_cmd == cmdTurnOn) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceCallScene);
-      frame.getPayload().add<devid_t>(_id);
-      frame.getPayload().add<uint16_t>(SceneMax);
-      sendFrame(frame);
-    } else if(_cmd == cmdTurnOff) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceCallScene);
-      frame.getPayload().add<devid_t>(_id);
-      frame.getPayload().add<uint16_t>(SceneMin);
-      sendFrame(frame);
-    } else if(_cmd == cmdGetOnOff) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceGetOnOff);
-      frame.getPayload().add<uint16_t>(_id);
-      uint8_t res = receiveSingleResult(frame, FunctionDeviceGetOnOff);
-      result.push_back(res);
-    } else if(_cmd == cmdGetValue) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceGetParameterValue);
-      frame.getPayload().add<uint16_t>(_id);
-      frame.getPayload().add<uint16_t>(_param);
-      uint8_t res = receiveSingleResult(frame, FunctionDeviceGetParameterValue);
-      result.push_back(res);
-    } else if(_cmd == cmdGetFunctionID) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceGetFunctionID);
-      frame.getPayload().add<devid_t>(_id);
-
-      boost::shared_ptr<ReceivedFrame> resFrame = receiveSingleFrame(frame, FunctionDeviceGetFunctionID);
-      if(resFrame.get() != NULL) {
-        PayloadDissector pd(resFrame->getFrame()->getPayload());
-        pd.get<uint8_t>(); // skip the function id
-        if(pd.get<uint16_t>() == 0x0001) {
-          result.push_back(pd.get<uint16_t>());
-        }
-      }
-    } else if(_cmd == cmdCallScene) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceCallScene);
-      frame.getPayload().add<devid_t>(_id);
-      frame.getPayload().add<uint16_t>(_param);
-      sendFrame(frame);
-    } else if(_cmd == cmdSaveScene) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceSaveScene);
-      frame.getPayload().add<devid_t>(_id);
-      frame.getPayload().add<uint16_t>(_param);
-      sendFrame(frame);
-    } else if(_cmd == cmdUndoScene) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceUndoScene);
-      frame.getPayload().add<devid_t>(_id);
-      frame.getPayload().add<uint16_t>(_param);
-      sendFrame(frame);
-    } else if(_cmd == cmdIncreaseValue) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceIncreaseValue);
-      frame.getPayload().add<devid_t>(_id);
-      sendFrame(frame);
-    } else if(_cmd == cmdDecreaseValue) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceDecreaseValue);
-      frame.getPayload().add<devid_t>(_id);
-      sendFrame(frame);
-    } else if(_cmd == cmdSetValue) {
-      frame.getPayload().add<uint8_t>(FunctionDeviceSetValue);
-      frame.getPayload().add<devid_t>(_id);
-      frame.getPayload().add<devid_t>(_param);
-      sendFrame(frame);
-    }
-    return result;
-  } // sendCommand(device)
-
-  void DS485Proxy::sendFrame(DS485CommandFrame& _frame) {
-    _frame.setFrameSource(fsDSS);
-    bool broadcast = _frame.getHeader().isBroadcast();
-#ifdef WITH_SIM
-    bool sim = isSimAddress(_frame.getHeader().getDestination());
-    if(broadcast || sim) {
-      log("Sending packet to sim");
-      if(DSS::hasInstance()) {
-        getDSS().getSimulation().process(_frame);
-      }
-    }
-#else
-    bool sim = false;
-#endif
-    if(broadcast || !sim) {
-      if((m_DS485Controller.getState() == csSlave) || (m_DS485Controller.getState() == csMaster)) {
-        log("Sending packet to hardware");
-       	m_DS485Controller.enqueueFrame(_frame);
-      }
-    }
-    std::ostringstream sstream;
-    sstream << "Frame content: ";
-    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 << " to " << int(_frame.getHeader().getDestination());
-    if(broadcast) {
-      sstream << " as broadcast";
-    }
-    log(sstream.str());
-
-    boost::shared_ptr<DS485CommandFrame> pFrame(new DS485CommandFrame);
-    *pFrame = _frame;
-    // relay the frame to update our state
-    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);
-    result->addToProxy();
-    sendFrame(_frame);
-    return result;
-  } // sendFrameAndInstallBucket
-
-#ifdef WITH_SIM
-  bool DS485Proxy::isSimAddress(const uint8_t _addr) {
-    if(DSS::hasInstance()) {
-      return getDSS().getSimulation().isSimAddress(_addr);
-    } else {
-      return true;
-    }
-  } // isSimAddress
-#endif
-
-  void DS485Proxy::checkResultCode(const int _resultCode) {
-    if(_resultCode < 0) {
-      std::string message = "Unknown Error";
-      switch(_resultCode) {
-      case kDS485NoIDForIndexFound:
-        message = "No ID for index found";
-        break;
-      case kDS485ZoneNotFound:
-        message = "Zone not found";
-        break;
-      case kDS485IndexOutOfBounds:
-        message = "Index out of bounds";
-        break;
-      case kDS485GroupIDOutOfBounds:
-        message = "Group ID out of bounds";
-        break;
-      case kDS485ZoneCannotBeDeleted:
-        message = "Zone can not be deleted";
-        break;
-      case kDS485OutOfMemory:
-        message = "dSM is out of memory";
-        break;
-      case kDS485RoomAlreadyExists:
-        message = "Room already exists";
-        break;
-      case kDS485InvalidDeviceID:
-        message = "Invalid device id";
-        break;
-      case kDS485CannotRemoveFromStandardGroup:
-        message = "Cannot remove device from standard group";
-        break;
-      case kDS485CannotDeleteStandardGroup:
-        message = "Cannot delete standard group";
-        break;
-      case kDS485DSIDIsNull:
-        message = "DSID is null";
-        break;
-      case kDS485ReservedRoomNumber:
-        message = "Room number is reserved";
-        break;
-      case kDS485DeviceNotFound:
-        message = "Device not found";
-        break;
-      case kDS485GroupNotFound:
-        message = "Group not found";
-        break;
-      }
-      throw DS485ApiError(message);
-    }
-  } // checkResultCode
-
-  void DS485Proxy::setValueDevice(const Device& _device, const uint16_t _value, const uint16_t _parameterID, const int _size) {
-    DS485CommandFrame frame;
-    frame.getHeader().setDestination(_device.getModulatorID());
-    frame.getHeader().setBroadcast(false);
-    frame.getHeader().setType(1);
-    frame.setCommand(CommandRequest);
-    frame.getPayload().add<uint8_t>(FunctionDeviceSetParameterValue);
-    frame.getPayload().add<uint16_t>(_device.getShortAddress());
-    frame.getPayload().add<uint16_t>(_parameterID);
-    frame.getPayload().add<uint16_t>(_size - 1);
-    frame.getPayload().add<uint16_t>(_value);
-    sendFrame(frame);
-  } // setValueDevice
-  
-  ModulatorSpec_t DS485Proxy::modulatorSpecFromFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
-    int source = _frame->getHeader().getSource();
-
-    PayloadDissector pd(_frame->getPayload());
-    pd.get<uint8_t>();
-    uint16_t devID = pd.get<uint16_t>();
-    devID =  devID >> 8;
-    if(devID == 0) {
-      log("Found dSS");
-    } else if(devID == 1) {
-      log("Found dSM");
-    } else {
-      log(std::string("Found unknown device (") + intToString(devID, true) + ")");
-    }
-    uint16_t hwVersion = (pd.get<uint8_t>() << 8) | pd.get<uint8_t>();
-    uint16_t swVersion = (pd.get<uint8_t>() << 8) | pd.get<uint8_t>();
-
-    log(std::string("  HW-Version: ") + intToString(hwVersion >> 8) + "." + intToString(hwVersion & 0x00FF));
-    log(std::string("  SW-Version: ") + intToString(swVersion >> 8) + "." + intToString(swVersion & 0x00FF));
-
-    std::string name;
-    for(int i = 0; i < 6; i++) {
-      char c = char(pd.get<uint8_t>());
-      if(c != '\0') {
-        name += c;
-      }
-    }
-    log(std::string("  Name:      \"") + name + "\"");
-
-    // bus-id, sw-version, hw-version, name, device-id
-    ModulatorSpec_t spec(source, swVersion, hwVersion, name, devID);
-    return spec;
-  } // modulatorSpecFromFrame
-
-  std::vector<ModulatorSpec_t> DS485Proxy::getModulators() {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(0);
-    cmdFrame.getHeader().setBroadcast(true);
-    cmdFrame.setCommand(CommandRequest);
-    log("Proxy: GetModulators");
-
-    cmdFrame.getPayload().add<uint8_t>(FunctionGetTypeRequest);
-    boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionGetTypeRequest);
-    bucket->waitForFrames(1000);
-
-    std::map<int, bool> resultFrom;
-
-    std::vector<ModulatorSpec_t> result;
-    while(true) {
-      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
-      if(recFrame == NULL) {
-        break;
-      }
-      int source = recFrame->getFrame()->getHeader().getSource();
-      if(resultFrom[source]) {
-        log(std::string("already received result from ") + intToString(source));
-        continue;
-      }
-      ModulatorSpec_t spec = modulatorSpecFromFrame(recFrame->getFrame());
-      result.push_back(spec);
-    }
-
-    return result;
-  } // getModulators
-
-  ModulatorSpec_t DS485Proxy::getModulatorSpec(const int _modulatorID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.getHeader().setBroadcast(false);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionGetTypeRequest);
-    log("Proxy: getModulatorSpec");
-
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionGetTypeRequest);
-
-    if(recFrame == NULL) {
-      throw DS485ApiError("No frame received");
-    }
-
-    ModulatorSpec_t result = modulatorSpecFromFrame(recFrame->getFrame());
-
-    return result;
-  } // getModulatorSpec
-
-  int DS485Proxy::getGroupCount(const int _modulatorID, const int _zoneID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetGroupsSize);
-    cmdFrame.getPayload().add<uint16_t>(_zoneID);
-    int8_t res = int8_t(receiveSingleResult(cmdFrame, FunctionModulatorGetGroupsSize));
-    if(res < 0) {
-      log("GetGroupCount: Negative group count received '" + intToString(res) +
-          " on modulator " + intToString(_modulatorID) +
-          " with zone " + intToString(_zoneID));
-    }
-    checkResultCode(res);
-    // Every modulator should provide all standard-groups
-    if(res < GroupIDStandardMax) {
-      res = GroupIDStandardMax;
-    }
-    return res;
-  } // getGroupCount
-
-  std::vector<int> DS485Proxy::getGroups(const int _modulatorID, const int _zoneID) {
-    std::vector<int> result;
-
-    int numGroups = getGroupCount(_modulatorID, _zoneID);
-    log(std::string("Modulator has ") + intToString(numGroups) + " groups");
-    for(int iGroup = 0; iGroup < numGroups; iGroup++) {
-      DS485CommandFrame cmdFrame;
-      cmdFrame.getHeader().setDestination(_modulatorID);
-      cmdFrame.setCommand(CommandRequest);
-      cmdFrame.getPayload().add<uint8_t>(FunctionZoneGetGroupIdForInd);
-      cmdFrame.getPayload().add<uint16_t>(_zoneID);
-      cmdFrame.getPayload().add<uint16_t>(iGroup);
-
-      int8_t res = int8_t(receiveSingleResult(cmdFrame, FunctionZoneGetGroupIdForInd));
-      if(res < 0) {
-        log("GetGroups: Negative index received '" + intToString(res) + "' for index " + intToString(iGroup), lsFatal);
-      } else {
-        result.push_back(res);
-      }
-      //checkResultCode(res);
-    }
-
-    return result;
-  } // getGroups
-
-  int DS485Proxy::getDevicesInGroupCount(const int _modulatorID, const int _zoneID, const int _groupID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionGroupGetDeviceCount);
-    cmdFrame.getPayload().add<uint16_t>(_zoneID);
-    cmdFrame.getPayload().add<uint16_t>(_groupID);
-
-    int16_t res = int16_t(receiveSingleResult16(cmdFrame, FunctionGroupGetDeviceCount));
-    if(res < 0) {
-      log("GetDevicesInGroupCount: Negative count received '" + intToString(res) +
-          "' on modulator " + intToString(_modulatorID) +
-          " with zoneID " + intToString(_zoneID) + " in group " + intToString(_groupID));
-    }
-    checkResultCode(res);
-
-    return res;
-  } // getDevicesInGroupCount
-
-  std::vector<int> DS485Proxy::getDevicesInGroup(const int _modulatorID, const int _zoneID, const int _groupID) {
-    std::vector<int> result;
-
-    int numDevices = getDevicesInGroupCount(_modulatorID, _zoneID, _groupID);
-    for(int iDevice = 0; iDevice < numDevices; iDevice++) {
-      DS485CommandFrame cmdFrame;
-      cmdFrame.getHeader().setDestination(_modulatorID);
-      cmdFrame.setCommand(CommandRequest);
-      cmdFrame.getPayload().add<uint8_t>(FunctionGroupGetDevKeyForInd);
-      cmdFrame.getPayload().add<uint16_t>(_zoneID);
-      cmdFrame.getPayload().add<uint16_t>(_groupID);
-      cmdFrame.getPayload().add<uint16_t>(iDevice);
-      int16_t res = int16_t(receiveSingleResult16(cmdFrame, FunctionGroupGetDevKeyForInd));
-      if(res < 0) {
-        log("GetDevicesInGroup: Negative device id received '" + intToString(res) + "' for index " + intToString(iDevice), lsFatal);
-      } else {
-        result.push_back(res);
-      }
-      try {
-        checkResultCode(res);
-      } catch(DS485ApiError& err) {
-        log(std::string("Error reported back by dSM: ") + err.what(), lsFatal);
-      }
-    }
-
-    return result;
-  } // getDevicesInGroup
-
-  std::vector<int> DS485Proxy::getGroupsOfDevice(const int _modulatorID, const int _deviceID) {
-    std::vector<int> result;
-
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionDeviceGetGroups);
-    cmdFrame.getPayload().add<uint16_t>(_deviceID);
-
-    boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionDeviceGetGroups);
-
-    bucket->waitForFrame(1000);
-
-    while(true) {
-      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
-      if(recFrame == NULL) {
-        break;
-      }
-
-      PayloadDissector pd(recFrame->getFrame()->getPayload());
-      pd.get<uint8_t>(); // discard the function id
-      pd.get<uint16_t>(); // function result
-
-      for(int iByte = 0; iByte < 8; iByte++) {
-        uint8_t byte = pd.get<uint8_t>();
-        for(int iBit = 0; iBit < 8; iBit++) {
-          if(byte & (1 << iBit)) {
-            result.push_back((iByte * 8 + iBit) + 1);
-          }
-        }
-      }
-    }
-    return result;
-  } // getGroupsOfDevice
-
-  std::vector<int> DS485Proxy::getZones(const int _modulatorID) {
-    std::vector<int> result;
-
-    int numZones = getZoneCount(_modulatorID);
-    log(std::string("Modulator has ") + intToString(numZones) + " zones");
-    for(int iZone = 0; iZone < numZones; iZone++) {
-      DS485CommandFrame cmdFrame;
-      cmdFrame.getHeader().setDestination(_modulatorID);
-      cmdFrame.setCommand(CommandRequest);
-      cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetZoneIdForInd);
-      cmdFrame.getPayload().add<uint16_t>(iZone);
-      log("GetZoneID");
-      int16_t tempResult = int16_t(receiveSingleResult16(cmdFrame, FunctionModulatorGetZoneIdForInd));
-      // TODO: The following line is a workaround as described in #246
-      if((tempResult < 0) && (tempResult > -20)) {
-        log("GetZones: Negative zone id " + intToString(tempResult) + " received. Modulator: " + intToString(_modulatorID) + " index: " + intToString(iZone), lsError);
-        // TODO: take this line outside the if-clause after the dSM-API has been reworked
-        checkResultCode(tempResult);
-      } else {
-        result.push_back(tempResult);
-      }
-      log("received ZoneID: " + uintToString((unsigned int)tempResult));
-    }
-    return result;
-  } // getZones
-
-  int DS485Proxy::getZoneCount(const int _modulatorID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetZonesSize);
-    log("GetZoneCount");
-
-    int8_t result = int8_t(
-        receiveSingleResult(cmdFrame, FunctionModulatorGetZonesSize));
-    checkResultCode(result);
-    return result;
-  } // getZoneCount
-
-  int DS485Proxy::getDevicesCountInZone(const int _modulatorID, const int _zoneID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorCountDevInZone);
-    cmdFrame.getPayload().add<uint16_t>(_zoneID);
-    log("GetDevicesCountInZone");
-
-    log(intToString(_modulatorID) + " " + intToString(_zoneID));
-
-    int16_t result = int16_t(receiveSingleResult16(cmdFrame, FunctionModulatorCountDevInZone));
-    if(result < 0) {
-      log("GetDevicesCountInZone: negative count '" + intToString(result) + "'", lsError);
-    }
-    checkResultCode(result);
-
-    return result;
-  } // getDevicesCountInZone
-
-  std::vector<int> DS485Proxy::getDevicesInZone(const int _modulatorID, const int _zoneID) {
-    std::vector<int> result;
-
-    int numDevices = getDevicesCountInZone(_modulatorID, _zoneID);
-    log(std::string("Found ") + intToString(numDevices) + " in zone.");
-    for(int iDevice = 0; iDevice < numDevices; iDevice++) {
-      DS485CommandFrame cmdFrame;
-      cmdFrame.getHeader().setDestination(_modulatorID);
-      cmdFrame.setCommand(CommandRequest);
-      cmdFrame.getPayload().add<uint8_t>(FunctionModulatorDevKeyInZone);
-      cmdFrame.getPayload().add<uint16_t>(_zoneID);
-      cmdFrame.getPayload().add<uint16_t>(iDevice);
-
-      uint16_t devID = receiveSingleResult16(cmdFrame, FunctionModulatorDevKeyInZone);
-      checkResultCode(int16_t(devID));
-      result.push_back(devID);
-    }
-    return result;
-  } // getDevicesInZone
-
-  void DS485Proxy::setZoneID(const int _modulatorID, const devid_t _deviceID, const int _zoneID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionDeviceSetZoneID);
-    cmdFrame.getPayload().add<devid_t>(_deviceID);
-    cmdFrame.getPayload().add<uint16_t>(_zoneID);
-
-    int16_t res = int16_t(receiveSingleResult(cmdFrame, FunctionDeviceSetZoneID));
-    checkResultCode(res);
-  } // setZoneID
-
-  void DS485Proxy::createZone(const int _modulatorID, const int _zoneID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorAddZone);
-    cmdFrame.getPayload().add<uint16_t>(_zoneID);
-
-    int16_t res = int16_t(receiveSingleResult(cmdFrame, FunctionModulatorAddZone));
-    checkResultCode(res);
-  } // createZone
-
-  void DS485Proxy::removeZone(const int _modulatorID, const int _zoneID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorRemoveZone);
-    cmdFrame.getPayload().add<uint16_t>(_zoneID);
-
-    int16_t res = int16_t(receiveSingleResult(cmdFrame, FunctionModulatorAddZone));
-    checkResultCode(res);
-  } // removeZone
-
-  dsid_t DS485Proxy::getDSIDOfDevice(const int _modulatorID, const int _deviceID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionDeviceGetDSID);
-    cmdFrame.getPayload().add<uint16_t>(_deviceID);
-    log("Proxy: GetDSIDOfDevice");
-
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionDeviceGetDSID);
-    if(recFrame == NULL) {
-      throw DS485ApiError("No frame received");
-    }
-
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
-    pd.get<uint8_t>(); // discard the function id
-    int16_t res = int16_t(pd.get<uint16_t>());
-    checkResultCode(res);
-    return pd.get<dsid_t>();
-  } // getDSIDOfDevice
-
-  dsid_t DS485Proxy::getDSIDOfModulator(const int _modulatorID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetDSID);
-    log(std::string("Proxy: GetDSIDOfModulator ") + intToString(_modulatorID));
-
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionModulatorGetDSID);
-    if(recFrame == NULL) {
-      log("GetDSIDOfModulator: received no result from " + intToString(_modulatorID), lsError);
-      throw DS485ApiError("No frame received");
-    }
-
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
-    pd.get<uint8_t>(); // discard the function id
-    return pd.get<dsid_t>();
-  } // getDSIDOfModulator
-
-  int DS485Proxy::getLastCalledScene(const int _modulatorID, const int _zoneID, const int _groupID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionGroupGetLastCalledScene);
-    log(std::string("Proxy: GetLastCalledScene ") + intToString(_modulatorID));
-    cmdFrame.getPayload().add<uint16_t>(_zoneID);
-    cmdFrame.getPayload().add<uint16_t>(_groupID);
-
-    int16_t res = int16_t(receiveSingleResult16(cmdFrame, FunctionGroupGetLastCalledScene));
-    if(res < 0) {
-      log("DS485Proxy::getLastCalledScene: negative result received: " + intToString(res));
-    }
-    checkResultCode(res);
-    return res;
-  } // getLastCalledScene
-
-  unsigned long DS485Proxy::getPowerConsumption(const int _modulatorID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetPowerConsumption);
-    log(std::string("Proxy: GetPowerConsumption ") + intToString(_modulatorID));
-
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionModulatorGetPowerConsumption);
-    if(recFrame == NULL) {
-      log("DS485Proxy::getPowerConsumption: received no results", lsError);
-      throw DS485ApiError("No frame received");
-    }
-    if(recFrame->getFrame()->getHeader().getSource() != _modulatorID) {
-      log("GetPowerConsumption: received result from wrong source");
-    }
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
-    pd.get<uint8_t>(); // discard the function id
-    return pd.get<uint32_t>();
-  } // getPowerConsumption
-
-  unsigned long DS485Proxy::getEnergyMeterValue(const int _modulatorID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetEnergyMeterValue);
-    log(std::string("Proxy: GetEnergyMeterValue ") + intToString(_modulatorID));
-
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(cmdFrame, FunctionModulatorGetEnergyMeterValue);
-    if(recFrame == NULL) {
-      log("DS485Proxy::getEnergyMeterValue: received no results", lsError);
-      throw DS485ApiError("No frame received");
-    }
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
-    pd.get<uint8_t>(); // discard the function id
-    return pd.get<uint32_t>();
-  } // getEnergyMeterValue
-
-  bool DS485Proxy::getEnergyBorder(const int _modulatorID, int& _lower, int& _upper) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionModulatorGetEnergyLevel);
-
-    boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionModulatorGetEnergyLevel);
-
-    bucket->waitForFrame(1000);
-
-    boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
-    if(recFrame == NULL) {
-      throw DS485ApiError("No frame received");
-    }
-
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
-    pd.get<uint8_t>(); // discard the function id
-    _lower = pd.get<uint16_t>();
-    _upper = pd.get<uint16_t>();
-    return true;
-  } // getEnergyBorder
-
-  int DS485Proxy::getSensorValue(const Device& _device, const int _sensorID) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_device.getModulatorID());
-    cmdFrame.getHeader().setBroadcast(false);
-    cmdFrame.getHeader().setType(1);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionDeviceGetSensorValue);
-    cmdFrame.getPayload().add<uint16_t>(_device.getShortAddress());
-    cmdFrame.getPayload().add<uint16_t>(_sensorID);
-    log("GetSensorValue");
-
-    boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionDeviceGetSensorValue);
-    bucket->waitForFrame(2000);
-    boost::shared_ptr<ReceivedFrame> recFrame;
-    if(bucket->isEmpty()) {
-      log(std::string("received no ack for request getSensorValue"));
-      throw DS485ApiError("no Ack for sensorValue");
-    } else if(bucket->getFrameCount() == 1) {
-        // first frame received, wait for the next frame
-      recFrame= bucket->popFrame();
-      bucket->waitForFrame(2000);
-    } else
-        recFrame= bucket->popFrame();
-    // first frame is only request ack;
-
-    PayloadDissector pd(recFrame->getFrame()->getPayload());
-    pd.get<uint8_t>(); // discard functionID
-    checkResultCode((int)pd.get<uint16_t>()); // check first ack
-
-    if(bucket->isEmpty()) {
-        // no next frame after additional waiting.
-        throw DS485ApiError("no Answer for sensorValue");
-    }
-
-    recFrame = bucket->popFrame();
-
-    if(recFrame.get() != NULL) {
-        PayloadDissector pd(recFrame->getFrame()->getPayload());
-        pd.get<uint8_t>(); // discard functionID
-        pd.get<uint16_t>();
-        pd.get<uint16_t>();
-        checkResultCode((int)pd.get<uint16_t>()); // check sensorvalue
-        int result = int(pd.get<uint16_t>());
-        log(std::string("result ") + intToString(result));
-        return result;
-    } else {
-      throw std::runtime_error("received frame is NULL but bucket->isEmpty() returns false");
-    }
-  } // getSensorValue
-
-  uint8_t DS485Proxy::dSLinkSend(const int _modulatorID, devid_t _devAdr, uint8_t _value, uint8_t _flags) {
-    DS485CommandFrame cmdFrame;
-    cmdFrame.getHeader().setDestination(_modulatorID);
-    cmdFrame.setCommand(CommandRequest);
-    cmdFrame.getPayload().add<uint8_t>(FunctionDSLinkSendDevice);
-    cmdFrame.getPayload().add<uint16_t>(_devAdr);
-    cmdFrame.getPayload().add<uint16_t>(_value);
-    cmdFrame.getPayload().add<uint16_t>(_flags);
-
-    if((_flags & DSLinkSendWriteOnly) == 0) {
-      boost::shared_ptr<FrameBucketCollector> bucket = sendFrameAndInstallBucket(cmdFrame, FunctionDSLinkReceive);
-      bucket->waitForFrame(10000);
-      boost::shared_ptr<ReceivedFrame> recFrame = bucket->popFrame();
-      if(recFrame == NULL) {
-        log("dsLinkSend: No packet received", lsError);
-        throw DS485ApiError("No frame received");
-      }
-      PayloadDissector pd(recFrame->getFrame()->getPayload());
-      pd.get<uint8_t>(); // discard the function id
-      pd.get<uint16_t>(); // garbage
-      devid_t devAddress = pd.get<uint16_t>(); // device address
-      if(devAddress != _devAdr) {
-        std::string errStr =
-            "dSLinkSend: Received answer for wrong device expected: "+
-            intToString(_devAdr, true) +
-            " got: " + intToString(devAddress, true);
-        log(errStr, lsError);
-        throw DS485ApiError(errStr);
-      }
-      return pd.get<uint16_t>();
-    } else {
-      sendFrame(cmdFrame);
-      log("dsLinkSend: Not waiting for response (writeOnly is set)");
-      return 0;
-    }
-  } // dsLinkSend
-
-  void DS485Proxy::addToGroup(const int _modulatorID, const int _groupID, const int _deviceID) {
-
-  } // addToGroup
-
-  void DS485Proxy::removeFromGroup(const int _modulatorID, const int _groupID, const int _deviceID) {
-
-  } // removeFromGroup
-
-  int DS485Proxy::addUserGroup(const int _modulatorID) {
-    return 0;
-  } // addUserGroup
-
-  void DS485Proxy::removeUserGroup(const int _modulatorID, const int _groupID) {
-
-  } // removeUserGroup
-
-  boost::shared_ptr<ReceivedFrame> 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>();
-    } 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();
-
-    if(recFrame.get() != NULL) {
-      return recFrame;
-    } else {
-      throw std::runtime_error("received frame is NULL but bucket->isEmpty() returns false");
-    }
-  } // receiveSingleFrame
-
-  uint8_t DS485Proxy::receiveSingleResult(DS485CommandFrame& _frame, const uint8_t _functionID) {
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(_frame, _functionID);
-
-    if(recFrame.get() != NULL) {
-      PayloadDissector pd(recFrame->getFrame()->getPayload());
-      uint8_t functionID = pd.get<uint8_t>();
-      if(functionID != _functionID) {
-        log("function ids are different", lsFatal);
-      }
-      uint8_t result = pd.get<uint8_t>();
-      return result;
-    } else {
-      return 0;
-    }
-  } // receiveSingleResult
-
-  uint16_t DS485Proxy::receiveSingleResult16(DS485CommandFrame& _frame, const uint8_t _functionID) {
-    boost::shared_ptr<ReceivedFrame> recFrame = receiveSingleFrame(_frame, _functionID);
-
-    if(recFrame.get() != NULL) {
-      PayloadDissector pd(recFrame->getFrame()->getPayload());
-      uint8_t functionID = pd.get<uint8_t>();
-      if(functionID != _functionID) {
-        log("function ids are different");
-      }
-      uint16_t result = pd.get<uint8_t>();
-      if(!pd.isEmpty()) {
-        result |= (pd.get<uint8_t>() << 8);
-      } else {
-        log("receiveSingleResult16: only received half of the data (8bit)", lsFatal);
-      }
-      return result;
-    } else {
-      return 0;
-    }
-  } // receiveSingleResult16
-
-  void DS485Proxy::initialize() {
-    Subsystem::initialize();
-    m_DS485Controller.addFrameCollector(this);
-#ifdef WITH_SIM
-    if(DSS::hasInstance()) {
-      getDSS().getSimulation().addFrameCollector(this);
-    }
-#endif
-  }
-
-  void DS485Proxy::doStart() {
-    if(m_InitializeDS485Controller) {
-      try {
-        m_DS485Controller.setDSID(dsid_t::fromString(getDSS().getPropertySystem().getStringValue(getConfigPropertyBasePath() + "dsid")));
-        m_DS485Controller.run();
-      } 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  FunctionModulatorAddZone:
-      return "Modulator Add Zone";
-    case  FunctionModulatorRemoveZone:
-      return "Modulator Remove Zone";
-    case  FunctionModulatorRemoveAllZones:
-      return "Modulator Remove All Zones";
-    case  FunctionModulatorCountDevInZone:
-      return "Modulator Count Dev In Zone";
-    case  FunctionModulatorDevKeyInZone:
-      return "Modulator Dev Key In Zone";
-    case  FunctionModulatorGetGroupsSize:
-      return "Modulator Get Groups Size";
-    case  FunctionModulatorGetZonesSize:
-      return "Modulator Get Zones Size";
-    case  FunctionModulatorGetZoneIdForInd:
-      return "Modulator Get Zone Id For Index";
-    case  FunctionModulatorAddToGroup:
-      return "Modulator Add To Group";
-    case  FunctionModulatorRemoveFromGroup:
-      return "Modulator 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 FunctionModulatorGetDSID:
-      return "Function Modulator Get DSID";
-
-    case FunctionModulatorGetPowerConsumption:
-    	return "Function Modulator Get PowerConsumption";
-    case FunctionModulatorGetEnergyMeterValue:
-      return "Function Modulator Get Energy-Meter Value";
-    case FunctionModulatorGetEnergyLevel:
-      return "Function Modulator Get Energy-Level";
-    case FunctionModulatorSetEnergyLevel:
-      return "Function Modulator 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::etNewModulator);
-              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::etLostModulator);
-              pEvent->addParameter(modID);
-              raiseModelEvent(pEvent);
-            } else if(functionID == EventDeviceReady) {
-              int modID = frame->getHeader().getDestination();
-              ModelEvent* pEvent = new ModelEvent(ModelEvent::etModulatorReady);
-              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 == FunctionModulatorGetPowerConsumption) {   
-              /* hard optimized */
-              //getDSS().getApartment().getModulatorByBusID((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 == FunctionModulatorGetEnergyMeterValue) {
-              /* hard optimized */
-              //getDSS().getApartment().getModulatorByBusID((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 == FunctionModulatorGetDSID) {
-              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
-
-  bool FrameBucketCollector::isEmpty() const {
-    return m_Frames.empty();
-  } // isEmpty
-
-}
diff --git a/unix/ds485proxy.h b/unix/ds485proxy.h
deleted file mode 100644
index 03012f3..0000000
--- a/unix/ds485proxy.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
-    Copyright (c) 2009 digitalSTROM.org, Zurich, Switzerland
-    Copyright (c) 2009 futureLAB AG, Winterthur, Switzerland
-
-    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 _DS485_PROXY_H_INCLUDED
-#define _DS485_PROXY_H_INCLUDED
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <bitset>
-
-#include "core/model.h"
-
-#include "core/ds485types.h"
-#include "ds485.h"
-#include "core/syncevent.h"
-#include "core/DS485Interface.h"
-#include "core/subsystem.h"
-#include "core/mutex.h"
-
-#include <map>
-#include <vector>
-
-#ifndef WIN32
-  #include <ext/hash_map>
-#else
-  #include <hash_map>
-#endif
-
-#ifndef WIN32
-using namespace __gnu_cxx;
-#else
-using namespace stdext;
-#endif
-
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <boost/ptr_container/ptr_map.hpp>
-#include <boost/shared_ptr.hpp>
-
-namespace dss {
-
-  class DS485Proxy;
-  typedef hash_map<const Zone*, std::pair< std::vector<Group*>, Set> > FittingResult;
-
-
-  /** 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,
-                     public    DS485Interface,
-                     public    IDS485FrameCollector {
-  private:
-    FittingResult bestFit(const Set& _set);
-#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);
-    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();
-
-    DS485Controller m_DS485Controller;
-    SyncEvent m_ProxyEvent;
-    Apartment* m_pApartment;
-
-    SyncEvent m_PacketHere;
-    Mutex m_IncomingFramesGuard;
-    Mutex m_FrameBucketsGuard;
-    CommandFrameSharedPtrVector m_IncomingFrames;
-    bool m_InitializeDS485Controller;
-
-    ModulatorSpec_t modulatorSpecFromFrame(boost::shared_ptr<DS485CommandFrame> _frame);
-    void checkResultCode(const int _resultCode);
-    void raiseModelEvent(ModelEvent* _pEvent);
-  protected:
-    virtual void doStart();
-  public:
-    DS485Proxy(DSS* _pDSS, Apartment* _pApartment);
-    virtual ~DS485Proxy() {};
-
-    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<ModulatorSpec_t> getModulators();
-    virtual ModulatorSpec_t getModulatorSpec(const int _modulatorID);
-
-    virtual std::vector<int> getZones(const int _modulatorID);
-    virtual int getZoneCount(const int _modulatorID);
-    virtual std::vector<int> getDevicesInZone(const int _modulatorID, const int _zoneID);
-    virtual int getDevicesCountInZone(const int _modulatorID, const int _zoneID);
-
-    virtual void setZoneID(const int _modulatorID, const devid_t _deviceID, const int _zoneID);
-    virtual void createZone(const int _modulatorID, const int _zoneID);
-    virtual void removeZone(const int _modulatorID, const int _zoneID);
-
-    virtual int getGroupCount(const int _modulatorID, const int _zoneID);
-    virtual std::vector<int> getGroups(const int _modulatorID, const int _zoneID);
-    virtual int getDevicesInGroupCount(const int _modulatorID, const int _zoneID, const int _groupID);
-    virtual std::vector<int> getDevicesInGroup(const int _modulatorID, const int _zoneID, const int _groupID);
-
-    virtual std::vector<int> getGroupsOfDevice(const int _modulatorID, const int _deviceID);
-
-    virtual void addToGroup(const int _modulatorID, const int _groupID, const int _deviceID);
-    virtual void removeFromGroup(const int _modulatorID, const int _groupID, const int _deviceID);
-
-    virtual int addUserGroup(const int _modulatorID);
-    virtual void removeUserGroup(const int _modulatorID, const int _groupID);
-
-    virtual dsid_t getDSIDOfDevice(const int _modulatorID, const int _deviceID);
-    virtual dsid_t getDSIDOfModulator(const int _modulatorID);
-
-    virtual int getLastCalledScene(const int _modulatorID, const int _zoneID, const int _groupID);
-
-    virtual unsigned long getPowerConsumption(const int _modulatorID);
-    virtual unsigned long getEnergyMeterValue(const int _modulatorID);
-    virtual bool getEnergyBorder(const int _modulatorID, int& _lower, int& _upper);
-
-    //------------------------------------------------ UDI
-    virtual uint8_t dSLinkSend(const int _modulatorID, devid_t _devAdr, uint8_t _value, uint8_t _flags);
-
-    //------------------------------------------------ Device manipulation
-    virtual std::vector<int> sendCommand(DS485Command _cmd, const Set& _set, int _param);
-    virtual std::vector<int> sendCommand(DS485Command _cmd, const Device& _device, int _param);
-    virtual std::vector<int> sendCommand(DS485Command _cmd, devid_t _id, uint8_t _modulatorID, int _param);
-    virtual std::vector<int> sendCommand(DS485Command _cmd, const Zone& _zone, Group& _group, int _param);
-    virtual std::vector<int> sendCommand(DS485Command _cmd, const Zone& _zone, uint8_t _groupID, int _param = -1);
-
-    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
-
-#endif
diff --git a/webservices/dss.wsdl b/webservices/dss.wsdl
index 09152a3..51fd76f 100644
--- a/webservices/dss.wsdl
+++ b/webservices/dss.wsdl
@@ -24,7 +24,7 @@
   xmlns="http://www.w3.org/2001/XMLSchema"
   elementFormDefault="unqualified"
   attributeFormDefault="unqualified">
-  <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>
+  <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
   <complexType name="Event">
    <sequence>
      <element name="name" type="xsd:string" minOccurs="1" maxOccurs="1"/>
@@ -363,7 +363,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -381,7 +380,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -394,47 +392,12 @@
    </complexType>
   </element>
   <!-- operation request element -->
-  <element name="SetEnable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="SetEnableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
-  <element name="SetDisable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="SetDisableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
   <element name="SetStartDim">
    <complexType>
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
      <element name="directionUp" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -452,7 +415,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -471,7 +433,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
      <element name="value" type="xsd:double" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -559,7 +520,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -577,7 +537,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -590,47 +549,12 @@
    </complexType>
   </element>
   <!-- operation request element -->
-  <element name="ApartmentEnable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="ApartmentEnableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
-  <element name="ApartmentDisable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="ApartmentDisableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
   <element name="ApartmentStartDim">
    <complexType>
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="directionUp" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -648,7 +572,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -667,7 +590,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="value" type="xsd:double" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -791,7 +713,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -810,7 +731,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -823,42 +743,6 @@
    </complexType>
   </element>
   <!-- operation request element -->
-  <element name="ZoneEnable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="ZoneEnableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
-  <element name="ZoneDisable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="ZoneDisableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
   <element name="ZoneStartDim">
    <complexType>
     <sequence>
@@ -866,7 +750,6 @@
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="directionUp" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -885,7 +768,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -905,7 +787,6 @@
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="value" type="xsd:double" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -995,7 +876,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -1013,7 +893,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -1066,7 +945,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
      <element name="directionUp" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -1084,7 +962,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -1103,7 +980,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
      <element name="value" type="xsd:double" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -1811,22 +1687,6 @@
  <part name="parameters" element="dss:SetDecreaseValueResponse"/>
 </message>
 
-<message name="SetEnableRequest">
- <part name="parameters" element="dss:SetEnable"/>
-</message>
-
-<message name="SetEnableResponse">
- <part name="parameters" element="dss:SetEnableResponse"/>
-</message>
-
-<message name="SetDisableRequest">
- <part name="parameters" element="dss:SetDisable"/>
-</message>
-
-<message name="SetDisableResponse">
- <part name="parameters" element="dss:SetDisableResponse"/>
-</message>
-
 <message name="SetStartDimRequest">
  <part name="parameters" element="dss:SetStartDim"/>
 </message>
@@ -1899,22 +1759,6 @@
  <part name="parameters" element="dss:ApartmentDecreaseValueResponse"/>
 </message>
 
-<message name="ApartmentEnableRequest">
- <part name="parameters" element="dss:ApartmentEnable"/>
-</message>
-
-<message name="ApartmentEnableResponse">
- <part name="parameters" element="dss:ApartmentEnableResponse"/>
-</message>
-
-<message name="ApartmentDisableRequest">
- <part name="parameters" element="dss:ApartmentDisable"/>
-</message>
-
-<message name="ApartmentDisableResponse">
- <part name="parameters" element="dss:ApartmentDisableResponse"/>
-</message>
-
 <message name="ApartmentStartDimRequest">
  <part name="parameters" element="dss:ApartmentStartDim"/>
 </message>
@@ -2003,22 +1847,6 @@
  <part name="parameters" element="dss:ZoneDecreaseValueResponse"/>
 </message>
 
-<message name="ZoneEnableRequest">
- <part name="parameters" element="dss:ZoneEnable"/>
-</message>
-
-<message name="ZoneEnableResponse">
- <part name="parameters" element="dss:ZoneEnableResponse"/>
-</message>
-
-<message name="ZoneDisableRequest">
- <part name="parameters" element="dss:ZoneDisable"/>
-</message>
-
-<message name="ZoneDisableResponse">
- <part name="parameters" element="dss:ZoneDisableResponse"/>
-</message>
-
 <message name="ZoneStartDimRequest">
  <part name="parameters" element="dss:ZoneStartDim"/>
 </message>
@@ -2477,16 +2305,6 @@
   <input message="tns:SetDecreaseValueRequest"/>
   <output message="tns:SetDecreaseValueResponse"/>
  </operation>
- <operation name="SetEnable">
-  <documentation>Service definition of function dss__SetEnable</documentation>
-  <input message="tns:SetEnableRequest"/>
-  <output message="tns:SetEnableResponse"/>
- </operation>
- <operation name="SetDisable">
-  <documentation>Service definition of function dss__SetDisable</documentation>
-  <input message="tns:SetDisableRequest"/>
-  <output message="tns:SetDisableResponse"/>
- </operation>
  <operation name="SetStartDim">
   <documentation>Service definition of function dss__SetStartDim</documentation>
   <input message="tns:SetStartDimRequest"/>
@@ -2532,16 +2350,6 @@
   <input message="tns:ApartmentDecreaseValueRequest"/>
   <output message="tns:ApartmentDecreaseValueResponse"/>
  </operation>
- <operation name="ApartmentEnable">
-  <documentation>Service definition of function dss__ApartmentEnable</documentation>
-  <input message="tns:ApartmentEnableRequest"/>
-  <output message="tns:ApartmentEnableResponse"/>
- </operation>
- <operation name="ApartmentDisable">
-  <documentation>Service definition of function dss__ApartmentDisable</documentation>
-  <input message="tns:ApartmentDisableRequest"/>
-  <output message="tns:ApartmentDisableResponse"/>
- </operation>
  <operation name="ApartmentStartDim">
   <documentation>Service definition of function dss__ApartmentStartDim</documentation>
   <input message="tns:ApartmentStartDimRequest"/>
@@ -2597,16 +2405,6 @@
   <input message="tns:ZoneDecreaseValueRequest"/>
   <output message="tns:ZoneDecreaseValueResponse"/>
  </operation>
- <operation name="ZoneEnable">
-  <documentation>Service definition of function dss__ZoneEnable</documentation>
-  <input message="tns:ZoneEnableRequest"/>
-  <output message="tns:ZoneEnableResponse"/>
- </operation>
- <operation name="ZoneDisable">
-  <documentation>Service definition of function dss__ZoneDisable</documentation>
-  <input message="tns:ZoneDisableRequest"/>
-  <output message="tns:ZoneDisableResponse"/>
- </operation>
  <operation name="ZoneStartDim">
   <documentation>Service definition of function dss__ZoneStartDim</documentation>
   <input message="tns:ZoneStartDimRequest"/>
@@ -3020,24 +2818,6 @@
      <SOAP:body parts="parameters" use="literal"/>
   </output>
  </operation>
- <operation name="SetEnable">
-  <SOAP:operation soapAction=""/>
-  <input>
-     <SOAP:body parts="parameters" use="literal"/>
-  </input>
-  <output>
-     <SOAP:body parts="parameters" use="literal"/>
-  </output>
- </operation>
- <operation name="SetDisable">
-  <SOAP:operation soapAction=""/>
-  <input>
-     <SOAP:body parts="parameters" use="literal"/>
-  </input>
-  <output>
-     <SOAP:body parts="parameters" use="literal"/>
-  </output>
- </operation>
  <operation name="SetStartDim">
   <SOAP:operation soapAction=""/>
   <input>
@@ -3119,24 +2899,6 @@
      <SOAP:body parts="parameters" use="literal"/>
   </output>
  </operation>
- <operation name="ApartmentEnable">
-  <SOAP:operation soapAction=""/>
-  <input>
-     <SOAP:body parts="parameters" use="literal"/>
-  </input>
-  <output>
-     <SOAP:body parts="parameters" use="literal"/>
-  </output>
- </operation>
- <operation name="ApartmentDisable">
-  <SOAP:operation soapAction=""/>
-  <input>
-     <SOAP:body parts="parameters" use="literal"/>
-  </input>
-  <output>
-     <SOAP:body parts="parameters" use="literal"/>
-  </output>
- </operation>
  <operation name="ApartmentStartDim">
   <SOAP:operation soapAction=""/>
   <input>
@@ -3236,24 +2998,6 @@
      <SOAP:body parts="parameters" use="literal"/>
   </output>
  </operation>
- <operation name="ZoneEnable">
-  <SOAP:operation soapAction=""/>
-  <input>
-     <SOAP:body parts="parameters" use="literal"/>
-  </input>
-  <output>
-     <SOAP:body parts="parameters" use="literal"/>
-  </output>
- </operation>
- <operation name="ZoneDisable">
-  <SOAP:operation soapAction=""/>
-  <input>
-     <SOAP:body parts="parameters" use="literal"/>
-  </input>
-  <output>
-     <SOAP:body parts="parameters" use="literal"/>
-  </output>
- </operation>
  <operation name="ZoneStartDim">
   <SOAP:operation soapAction=""/>
   <input>
@@ -3653,7 +3397,7 @@
 </binding>
 
 <service name="dss">
- <documentation>gSOAP 2.7.10 generated service definition</documentation>
+ <documentation>gSOAP 2.7.9l generated service definition</documentation>
  <port name="dss" binding="tns:dss">
   <SOAP:address location="http://localhost:8081"/>
  </port>
diff --git a/webservices/dss.xsd b/webservices/dss.xsd
index 474f22d..69b4d1c 100644
--- a/webservices/dss.xsd
+++ b/webservices/dss.xsd
@@ -8,7 +8,7 @@
   xmlns="http://www.w3.org/2001/XMLSchema"
   elementFormDefault="unqualified"
   attributeFormDefault="unqualified">
-  <import namespace="http://schemas.xmlsoap.org/soap/encoding/" schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>
+  <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
   <complexType name="Event">
    <sequence>
      <element name="name" type="xsd:string" minOccurs="1" maxOccurs="1"/>
@@ -347,7 +347,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -365,7 +364,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -378,47 +376,12 @@
    </complexType>
   </element>
   <!-- operation request element -->
-  <element name="SetEnable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="SetEnableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
-  <element name="SetDisable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="SetDisableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
   <element name="SetStartDim">
    <complexType>
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
      <element name="directionUp" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -436,7 +399,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -455,7 +417,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="setSpec" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
      <element name="value" type="xsd:double" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -543,7 +504,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -561,7 +521,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -574,47 +533,12 @@
    </complexType>
   </element>
   <!-- operation request element -->
-  <element name="ApartmentEnable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="ApartmentEnableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
-  <element name="ApartmentDisable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="ApartmentDisableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
   <element name="ApartmentStartDim">
    <complexType>
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="directionUp" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -632,7 +556,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -651,7 +574,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="value" type="xsd:double" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -775,7 +697,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -794,7 +715,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -807,42 +727,6 @@
    </complexType>
   </element>
   <!-- operation request element -->
-  <element name="ZoneEnable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="ZoneEnableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
-  <element name="ZoneDisable">
-   <complexType>
-    <sequence>
-     <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation response element -->
-  <element name="ZoneDisableResponse">
-   <complexType>
-    <sequence>
-     <element name="result" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-    </sequence>
-   </complexType>
-  </element>
-  <!-- operation request element -->
   <element name="ZoneStartDim">
    <complexType>
     <sequence>
@@ -850,7 +734,6 @@
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="directionUp" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -869,7 +752,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -889,7 +771,6 @@
      <element name="zoneID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="groupID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="value" type="xsd:double" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -979,7 +860,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -997,7 +877,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -1050,7 +929,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
      <element name="directionUp" type="xsd:boolean" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -1068,7 +946,6 @@
     <sequence>
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
@@ -1087,7 +964,6 @@
      <element name="token" type="xsd:int" minOccurs="1" maxOccurs="1"/>
      <element name="deviceID" type="xsd:string" minOccurs="0" maxOccurs="1" nillable="true"/>
      <element name="value" type="xsd:double" minOccurs="1" maxOccurs="1"/>
-     <element name="paramID" type="xsd:int" minOccurs="1" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
diff --git a/webservices/model_soap.cpp b/webservices/model_soap.cpp
index daf8ff8..38a8656 100644
--- a/webservices/model_soap.cpp
+++ b/webservices/model_soap.cpp
@@ -1,3 +1,7 @@
+#include <vector>
+#include <string>
+#include <boost/shared_ptr.hpp>
+
 #include "soapH.h"
 #include "core/dss.h"
 #include "core/logger.h"
@@ -7,10 +11,14 @@
 #include "core/propertysystem.h"
 #include "core/setbuilder.h"
 #include "core/foreach.h"
-
-#include <vector>
-#include <string>
-#include <boost/shared_ptr.hpp>
+#include "core/model/apartment.h"
+#include "core/model/set.h"
+#include "core/model/device.h"
+#include "core/model/devicereference.h"
+#include "core/model/set.h"
+#include "core/model/zone.h"
+#include "core/model/group.h"
+#include "core/model/modulator.h"
 
 inline dss::dsid_t FromSOAP(const char* _dsid) {
   dss::dsid_t result = dss::dsid_t::fromString(_dsid);
@@ -58,7 +66,7 @@ int AuthorizeAndGetDevice(struct soap *soap, const int _token, char* _devID, dss
   }
 
   dss::Apartment& apt = dss::DSS::getInstance()->getApartment();
-  result = dss::DeviceReference(FromSOAP(_devID), apt);
+  result = dss::DeviceReference(FromSOAP(_devID), &apt);
   try {
     result.getDevice();
   } catch(dss::ItemNotFoundException& _ex) {
@@ -393,11 +401,7 @@ int dss__CircuitRescan(struct soap *soap, int _token, char* _dsid, bool& result)
   }
   try {
     dss::Modulator& mod = apt.getModulatorByDSID(dsid);
-    try {
-      result = apt.scanModulator(mod);
-    } catch(std::runtime_error&) {
-      soap_receiver_fault(soap, "Error scanning bus", NULL);
-    }
+    mod.setIsValid(false);
   } catch(dss::ItemNotFoundException&) {
     return soap_sender_fault(soap, "Could not find modulator", NULL);
   }
@@ -432,79 +436,57 @@ int dss__SetTurnOff(struct soap *soap, int _token, char* _setSpec, bool& result)
   return SOAP_OK;
 }
 
-int dss__SetIncreaseValue(struct soap *soap, int _token, char* _setSpec, int _paramID, bool& result) {
-  dss::Set set;
-  int getResult = AuthorizeAndGetSet(soap, _token, _setSpec, set);
-  if(getResult != SOAP_OK) {
-    return getResult;
-  }
-  set.increaseValue(_paramID);
-  result = true;
-  return SOAP_OK;
-}
-
-int dss__SetDecreaseValue(struct soap *soap, int _token, char* _setSpec, int _paramID, bool& result) {
-  dss::Set set;
-  int getResult = AuthorizeAndGetSet(soap, _token, _setSpec, set);
-  if(getResult != SOAP_OK) {
-    return getResult;
-  }
-  set.decreaseValue(_paramID);
-  result = true;
-  return SOAP_OK;
-}
-
-int dss__SetEnable(struct soap *soap, int _token, char* _setSpec, bool& result) {
+int dss__SetIncreaseValue(struct soap *soap, int _token, char* _setSpec, bool& result) {
   dss::Set set;
   int getResult = AuthorizeAndGetSet(soap, _token, _setSpec, set);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  set.enable();
+  set.increaseValue();
   result = true;
   return SOAP_OK;
 }
 
-int dss__SetDisable(struct soap *soap, int _token, char* _setSpec, bool& result) {
+int dss__SetDecreaseValue(struct soap *soap, int _token, char* _setSpec, bool& result) {
   dss::Set set;
   int getResult = AuthorizeAndGetSet(soap, _token, _setSpec, set);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  set.disable();
+  set.decreaseValue();
   result = true;
   return SOAP_OK;
 }
 
-int dss__SetStartDim(struct soap *soap, int _token, char* _setSpec, bool _directionUp, int _paramID, bool& result) {
+int dss__SetStartDim(struct soap *soap, int _token, char* _setSpec, bool _directionUp, bool& result) {
   dss::Set set;
   int getResult = AuthorizeAndGetSet(soap, _token, _setSpec, set);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  set.startDim(_directionUp, _paramID);
+  set.startDim(_directionUp);
   result = true;
   return SOAP_OK;
 }
 
-int dss__SetEndDim(struct soap *soap, int _token, char* _setSpec, int _paramID, bool& result) {
+int dss__SetEndDim(struct soap *soap, int _token, char* _setSpec, bool& result) {
   dss::Set set;
   int getResult = AuthorizeAndGetSet(soap, _token, _setSpec, set);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  set.endDim(_paramID);
+  set.endDim();
   result = true;
   return SOAP_OK;
 }
 
-int dss__SetSetValue(struct soap *soap, int _token, char* _setSpec, double _value, int _paramID, bool& result) {
+int dss__SetSetValue(struct soap *soap, int _token, char* _setSpec, double _value, bool& result) {
   dss::Set set;
   int getResult = AuthorizeAndGetSet(soap, _token, _setSpec, set);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  set.setValue(_value, _paramID);
+  set.setValue(_value);
   result = true;
   return SOAP_OK;
 }
@@ -566,79 +548,57 @@ int dss__ApartmentTurnOff(struct soap *soap, int _token, int _groupID, bool& res
   return SOAP_OK;
 }
 
-int dss__ApartmentIncreaseValue(struct soap *soap, int _token, int _groupID, int _paramID, bool& result) {
+int dss__ApartmentIncreaseValue(struct soap *soap, int _token, int _groupID, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroup(soap, _token, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.increaseValue(_paramID);
+  group.increaseValue();
   result = true;
   return SOAP_OK;
 }
 
-int dss__ApartmentDecreaseValue(struct soap *soap, int _token, int _groupID, int _paramID, bool& result) {
+int dss__ApartmentDecreaseValue(struct soap *soap, int _token, int _groupID, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroup(soap, _token, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.decreaseValue(_paramID);
+  group.decreaseValue();
   result = true;
   return SOAP_OK;
 }
 
-int dss__ApartmentEnable(struct soap *soap, int _token, int _groupID, bool& result) {
+int dss__ApartmentStartDim(struct soap *soap, int _token, int _groupID, bool _directionUp, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroup(soap, _token, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.enable();
+  group.startDim(_directionUp);
   result = true;
   return SOAP_OK;
 }
 
-int dss__ApartmentDisable(struct soap *soap, int _token, int _groupID, bool& result) {
+int dss__ApartmentEndDim(struct soap *soap, int _token, int _groupID, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroup(soap, _token, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.disable();
+  group.endDim();
   result = true;
   return SOAP_OK;
 }
 
-int dss__ApartmentStartDim(struct soap *soap, int _token, int _groupID, bool _directionUp, int _paramID, bool& result) {
+int dss__ApartmentSetValue(struct soap *soap, int _token, int _groupID, double _value, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroup(soap, _token, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.startDim(_directionUp, _paramID);
-  result = true;
-  return SOAP_OK;
-}
-
-int dss__ApartmentEndDim(struct soap *soap, int _token, int _groupID, int _paramID, bool& result) {
-  dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
-  int getResult = AuthorizeAndGetGroup(soap, _token, _groupID, group);
-  if(getResult != SOAP_OK) {
-    return getResult;
-  }
-  group.endDim(_paramID);
-  result = true;
-  return SOAP_OK;
-}
-
-int dss__ApartmentSetValue(struct soap *soap, int _token, int _groupID, double _value, int _paramID, bool& result) {
-  dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
-  int getResult = AuthorizeAndGetGroup(soap, _token, _groupID, group);
-  if(getResult != SOAP_OK) {
-    return getResult;
-  }
-  group.setValue(_value, _paramID);
+  group.setValue(_value);
   result = true;
   return SOAP_OK;
 }
@@ -700,79 +660,57 @@ int dss__ZoneTurnOff(struct soap *soap, int _token, int _zoneID, int _groupID, b
   return SOAP_OK;
 }
 
-int dss__ZoneIncreaseValue(struct soap *soap, int _token, int _zoneID, int _groupID, int _paramID, bool& result) {
-  dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
-  int getResult = AuthorizeAndGetGroupOfZone(soap, _token, _zoneID, _groupID, group);
-  if(getResult != SOAP_OK) {
-    return getResult;
-  }
-  group.increaseValue(_paramID);
-  result = true;
-  return SOAP_OK;
-}
-
-int dss__ZoneDecreaseValue(struct soap *soap, int _token, int _zoneID, int _groupID, int _paramID, bool& result) {
-  dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
-  int getResult = AuthorizeAndGetGroupOfZone(soap, _token, _zoneID, _groupID, group);
-  if(getResult != SOAP_OK) {
-    return getResult;
-  }
-  group.decreaseValue(_paramID);
-  result = true;
-  return SOAP_OK;
-}
-
-int dss__ZoneEnable(struct soap *soap, int _token, int _zoneID, int _groupID, bool& result) {
+int dss__ZoneIncreaseValue(struct soap *soap, int _token, int _zoneID, int _groupID, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroupOfZone(soap, _token, _zoneID, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.enable();
+  group.increaseValue();
   result = true;
   return SOAP_OK;
 }
 
-int dss__ZoneDisable(struct soap *soap, int _token, int _zoneID, int _groupID, bool& result) {
+int dss__ZoneDecreaseValue(struct soap *soap, int _token, int _zoneID, int _groupID, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroupOfZone(soap, _token, _zoneID, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.disable();
+  group.decreaseValue();
   result = true;
   return SOAP_OK;
 }
 
-int dss__ZoneStartDim(struct soap *soap, int _token, int _zoneID, int _groupID, bool _directionUp, int _paramID, bool& result) {
+int dss__ZoneStartDim(struct soap *soap, int _token, int _zoneID, int _groupID, bool _directionUp, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroupOfZone(soap, _token, _zoneID, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.startDim(_directionUp, _paramID);
+  group.startDim(_directionUp);
   result = true;
   return SOAP_OK;
 }
 
-int dss__ZoneEndDim(struct soap *soap, int _token, int _zoneID, int _groupID, int _paramID, bool& result) {
+int dss__ZoneEndDim(struct soap *soap, int _token, int _zoneID, int _groupID, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroupOfZone(soap, _token, _zoneID, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.endDim(_paramID);
+  group.endDim();
   result = true;
   return SOAP_OK;
 }
 
-int dss__ZoneSetValue(struct soap *soap, int _token, int _zoneID, int _groupID, double _value, int _paramID, bool& result) {
+int dss__ZoneSetValue(struct soap *soap, int _token, int _zoneID, int _groupID, double _value, bool& result) {
   dss::Group group(-1, 0, dss::DSS::getInstance()->getApartment());
   int getResult = AuthorizeAndGetGroupOfZone(soap, _token, _zoneID, _groupID, group);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  group.setValue(_value, _paramID);
+  group.setValue(_value);
   result = true;
   return SOAP_OK;
 }
@@ -834,24 +772,24 @@ int dss__DeviceTurnOff(struct soap *soap, int _token, char* _deviceID, bool& res
   return SOAP_OK;
 }
 
-int dss__DeviceIncreaseValue(struct soap *soap, int _token, char* _deviceID, int _paramID, bool& result) {
+int dss__DeviceIncreaseValue(struct soap *soap, int _token, char* _deviceID, bool& result) {
   dss::DeviceReference dev(dss::NullDSID, NULL);
   int getResult = AuthorizeAndGetDevice(soap, _token, _deviceID, dev);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  dev.increaseValue(_paramID);
+  dev.increaseValue();
   result = true;
   return SOAP_OK;
 }
 
-int dss__DeviceDecreaseValue(struct soap *soap, int _token, char* _deviceID, int _paramID, bool& result) {
+int dss__DeviceDecreaseValue(struct soap *soap, int _token, char* _deviceID, bool& result) {
   dss::DeviceReference dev(dss::NullDSID, NULL);
   int getResult = AuthorizeAndGetDevice(soap, _token, _deviceID, dev);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  dev.decreaseValue(_paramID);
+  dev.decreaseValue();
   result = true;
   return SOAP_OK;
 }
@@ -878,35 +816,35 @@ int dss__DeviceDisable(struct soap *soap, int _token, char* _deviceID, bool& res
   return SOAP_OK;
 }
 
-int dss__DeviceStartDim(struct soap *soap, int _token, char* _deviceID, bool _directionUp, int _paramID, bool& result) {
+int dss__DeviceStartDim(struct soap *soap, int _token, char* _deviceID, bool _directionUp, bool& result) {
   dss::DeviceReference dev(dss::NullDSID, NULL);
   int getResult = AuthorizeAndGetDevice(soap, _token, _deviceID, dev);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  dev.startDim(_directionUp, _paramID);
+  dev.startDim(_directionUp);
   result = true;
   return SOAP_OK;
 }
 
-int dss__DeviceEndDim(struct soap *soap, int _token, char* _deviceID, int _paramID, bool& result) {
+int dss__DeviceEndDim(struct soap *soap, int _token, char* _deviceID, bool& result) {
   dss::DeviceReference dev(dss::NullDSID, NULL);
   int getResult = AuthorizeAndGetDevice(soap, _token, _deviceID, dev);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  dev.endDim(_paramID);
+  dev.endDim();
   result = true;
   return SOAP_OK;
 }
 
-int dss__DeviceSetValue(struct soap *soap, int _token, char* _deviceID, double _value, int _paramID, bool& result) {
+int dss__DeviceSetValue(struct soap *soap, int _token, char* _deviceID, double _value, bool& result) {
   dss::DeviceReference dev(dss::NullDSID, NULL);
   int getResult = AuthorizeAndGetDevice(soap, _token, _deviceID, dev);
   if(getResult != SOAP_OK) {
     return getResult;
   }
-  dev.setValue(_value, _paramID);
+  dev.setValue(_value);
   result = true;
   return SOAP_OK;
 }
@@ -1132,11 +1070,11 @@ int dss__EventRaise(struct soap *soap, int _token, char* _eventName, char* _cont
       evt->setContext(_context);
     }
     if(_parameter != NULL && strlen(_parameter) > 0) {
-      vector<std::string> params = dss::splitString(_parameter, ';');
-      for(vector<std::string>::iterator iParam = params.begin(), e = params.end();
+      std::vector<std::string> params = dss::splitString(_parameter, ';');
+      for(std::vector<std::string>::iterator iParam = params.begin(), e = params.end();
           iParam != e; ++iParam)
       {
-        vector<std::string> nameValue = dss::splitString(*iParam, '=');
+        std::vector<std::string> nameValue = dss::splitString(*iParam, '=');
         if(nameValue.size() == 2) {
           dss::Logger::getInstance()->log("SOAP::eventRaise: Got parameter '" + nameValue[0] + "'='" + nameValue[1] + "'");
           evt->setProperty(nameValue[0], nameValue[1]);
diff --git a/webservices/model_soap.h b/webservices/model_soap.h
index 581348b..20dbaba 100644
--- a/webservices/model_soap.h
+++ b/webservices/model_soap.h
@@ -63,26 +63,19 @@ int dss__ApartmentGetZoneIDs(int _token, std::vector<int>& zoneIDs);
 int dss__SetTurnOn(int _token, char* _setSpec, bool& result);
 /** Sends a turn off command to all devices contained in the set */
 int dss__SetTurnOff(int _token, char* _setSpec, bool& result);
-/** Increases the param described by _paramID for each device contained in the set. If _paramID
- *  == -1 the default parameter will be increased. */
-int dss__SetIncreaseValue(int _token, char* _setSpec, int _paramID, bool& result);
-/** Decreases the param described by _paramID for each device contained in the set. If _paramID
- *  == -1 the default parameter will be decreased. */
-int dss__SetDecreaseValue(int _token, char* _setSpec, int _paramID, bool& result);
-
-/** Enables all previously disabled devices in the set. */
-int dss__SetEnable(int _token, char* _setSpec, bool& result);
-/** Disables all devices in the set. */
-int dss__SetDisable(int _token, char* _setSpec, bool& result);
-/** Starts dimming the given parameter on all devices contained in the set. If _directionUp is
- * true, the dimming will increase the parameter specified by _paramID. If _paramID == -1 the
- * default parameter will be dimmed */
-int dss__SetStartDim(int _token, char* _setSpec, bool _directionUp, int _paramID, bool& result);
-/** Stops dimming the given parameter on all devices contained in the set. */
-int dss__SetEndDim(int _token, char* _setSpec, int _paramID, bool& result);
+/** Increases the main value (e.g. brightness) for each device contained in the set. */
+int dss__SetIncreaseValue(int _token, char* _setSpec, bool& result);
+/** Decreases the main value (e.g. brightness) for each device contained in the set. */
+int dss__SetDecreaseValue(int _token, char* _setSpec, bool& result);
+
+/** Starts dimming the main parameter (e.g. brightness) on all devices contained in the set. If _directionUp is
+ * true, the dimming will increase the parameter */
+int dss__SetStartDim(int _token, char* _setSpec, bool _directionUp, bool& result);
+/** Stops dimming on all devices contained in the set. */
+int dss__SetEndDim(int _token, char* _setSpec, bool& result);
 /** Sets the parameter specified by _paramID to _value. If _paramID == -1 the default parameter
  * will be set. */
-int dss__SetSetValue(int _token, char* _setSpec, double _value, int _paramID, bool& result);
+int dss__SetSetValue(int _token, char* _setSpec, double _value, bool& result);
 
 /** Calls the scene _sceneNr on all devices contained int the set _setID. */
 int dss__SetCallScene(int _token, char* _setSpec, int _sceneNr, bool& result);
@@ -95,26 +88,19 @@ int dss__SetSaveScene(int _token, char* _setSpec, int _sceneNr, bool& result);
 int dss__ApartmentTurnOn(int _token, int _groupID, bool& result);
 /** Sends a turn off command to all devices contained in the group */
 int dss__ApartmentTurnOff(int _token, int _groupID, bool& result);
-/** Increases the param described by _paramID for each device contained in the group. If _paramID
- *  == -1 the default parameter will be increased. */
-int dss__ApartmentIncreaseValue(int _token, int _groupID, int _paramID, bool& result);
-/** Decreases the param described by _paramID for each device contained in the group. If _paramID
- *  == -1 the default parameter will be decreased. */
-int dss__ApartmentDecreaseValue(int _token, int _groupID, int _paramID, bool& result);
-
-/** Enables all previously disabled devices in the group. */
-int dss__ApartmentEnable(int _token, int _groupID, bool& result);
-/** Disables all devices in the group. */
-int dss__ApartmentDisable(int _token, int _groupID, bool& result);
-/** Starts dimming the given parameter on all devices contained in the group. If _directionUp is
- * true, the dimming will increase the parameter specified by _paramID. If _paramID == -1 the
- * default parameter will be dimmed */
-int dss__ApartmentStartDim(int _token, int _groupID, bool _directionUp, int _paramID, bool& result);
+/** Increases the main value (e.g. brightness) for each device contained in the group. */
+int dss__ApartmentIncreaseValue(int _token, int _groupID, bool& result);
+/** Decreases the main value (e.g. brightness) for each device contained in the group. */
+int dss__ApartmentDecreaseValue(int _token, int _groupID, bool& result);
+
+/** Starts dimming the main parameter on all devices contained in the group. If _directionUp is
+ * true, the dimming will increase the parameter. */
+int dss__ApartmentStartDim(int _token, int _groupID, bool _directionUp, bool& result);
 /** Stops dimming the given parameter on all devices contained in the group. */
-int dss__ApartmentEndDim(int _token, int _groupID, int _paramID, bool& result);
+int dss__ApartmentEndDim(int _token, int _groupID, bool& result);
 /** Sets the parameter specified by _paramID to _value. If _paramID == -1 the default parameter
  * will be set. */
-int dss__ApartmentSetValue(int _token, int _groupID, double _value, int _paramID, bool& result);
+int dss__ApartmentSetValue(int _token, int _groupID, double _value, bool& result);
 
 /** Calls the scene _sceneNr on all devices contained int the group _groupID. */
 int dss__ApartmentCallScene(int _token, int _groupID, int _sceneNr, bool& result);
@@ -134,26 +120,19 @@ int dss__CircuitRescan(int _token, char* _dsid, bool& result);
 int dss__ZoneTurnOn(int _token, int _zoneID, int _groupID, bool& result);
 /** Sends a turn off command to all devices contained in the group */
 int dss__ZoneTurnOff(int _token, int _zoneID, int _groupID, bool& result);
-/** Increases the param described by _paramID for each device contained in the zone/group. If _paramID
- *  == -1 the default parameter will be increased. */
-int dss__ZoneIncreaseValue(int _token, int _zoneID, int _groupID, int _paramID, bool& result);
-/** Decreases the param described by _paramID for each device contained in the zone/group. If _paramID
- *  == -1 the default parameter will be decreased. */
-int dss__ZoneDecreaseValue(int _token, int _zoneID, int _groupID, int _paramID, bool& result);
-
-/** Enables all previously disabled devices in the zone/group. */
-int dss__ZoneEnable(int _token, int _zoneID, int _groupID, bool& result);
-/** Disables all devices in the zone/group. */
-int dss__ZoneDisable(int _token, int _zoneID, int _groupID, bool& result);
-/** Starts dimming the given parameter on all devices contained in the group/zone. If _directionUp is
- * true, the dimming will increase the parameter specified by _paramID. If _paramID == -1 the
- * default parameter will be dimmed */
-int dss__ZoneStartDim(int _token, int _zoneID, int _groupID, bool _directionUp, int _paramID, bool& result);
-/** Stops dimming the given parameter on all devices contained in the zone/group. */
-int dss__ZoneEndDim(int _token, int _zoneID, int _groupID, int _paramID, bool& result);
+/** Increases the main value (e.g. brightness) for each device contained in the zone/group. */
+int dss__ZoneIncreaseValue(int _token, int _zoneID, int _groupID, bool& result);
+/** Decreases the main value (e.g. brightness) for each device contained in the zone/group. */
+int dss__ZoneDecreaseValue(int _token, int _zoneID, int _groupID, bool& result);
+
+/** Starts dimming the main parameter (e.g. brightness) on all devices contained in the group/zone. If _directionUp is
+ * true, the dimming will increase the parameter. */
+int dss__ZoneStartDim(int _token, int _zoneID, int _groupID, bool _directionUp, bool& result);
+/** Stops dimming on all devices contained in the zone/group. */
+int dss__ZoneEndDim(int _token, int _zoneID, int _groupID, bool& result);
 /** Sets the parameter specified by _paramID to _value. If _paramID == -1 the default parameter
  * will be set. */
-int dss__ZoneSetValue(int _token, int _zoneID, int _groupID, double _value, int _paramID, bool& result);
+int dss__ZoneSetValue(int _token, int _zoneID, int _groupID, double _value, bool& result);
 
 /** Calls the scene _sceneNr on all devices contained int the zone/group _groupID. */
 int dss__ZoneCallScene(int _token, int _zoneID, int _groupID, int _sceneNr, bool& result);
@@ -166,26 +145,22 @@ int dss__ZoneSaveScene(int _token, int _zoneID, int _groupID, int _sceneNr, bool
 int dss__DeviceTurnOn(int _token, char* _deviceID, bool& result);
 /** Sends a turn off command to the device. */
 int dss__DeviceTurnOff(int _token, char* _deviceID, bool& result);
-/** Increases the parameter specified by _paramID on the device. If _paramID == -1
- * the default parameter will be increased */
-int dss__DeviceIncreaseValue(int _token, char* _deviceID, int _paramID, bool& result);
-/** Decreases the parameter specified by _paramID on the device. If _paramID == -1
- * the default parameter will be decreased */
-int dss__DeviceDecreaseValue(int _token, char* _deviceID, int _paramID, bool& result);
+/** Increases the main value (e.g. brightness) on the device. */
+int dss__DeviceIncreaseValue(int _token, char* _deviceID, bool& result);
+/** Decreases the main value (e.g. brightness) on the device. */
+int dss__DeviceDecreaseValue(int _token, char* _deviceID, bool& result);
 /** Enables the device. */
 int dss__DeviceEnable(int _token, char* _deviceID, bool& result);
 /** Disables the device. */
 int dss__DeviceDisable(int _token, char* _deviceID, bool& result);
-/** Starts dimming the given parameter. If _directionUp is true, the dimming will increase
- * the parameter specified by _paramID. If _paramID == -1 the default parameter will be
- * dimmed. */
-int dss__DeviceStartDim(int _token, char* _deviceID, bool _directionUp, int _paramID, bool& result);
-/** Stops dimming the given parameter. If _parameterID == -1 dimming the default parameter
- * will be stopped. */
-int dss__DeviceEndDim(int _token, char* _deviceID, int _paramID, bool& result);
+/** Starts dimming the main parameter (e.g. brightness). If _directionUp is true, the dimming will increase
+ * the parameter. */
+int dss__DeviceStartDim(int _token, char* _deviceID, bool _directionUp, bool& result);
+/** Stops dimming. */
+int dss__DeviceEndDim(int _token, char* _deviceID, bool& result);
 /** Sets the value of the parameter _paramID to _value. If _paramID == -1 the default parameter
  * will be set. */
-int dss__DeviceSetValue(int _token, char* _deviceID, double _value, int _paramID, bool& result);
+int dss__DeviceSetValue(int _token, char* _deviceID, double _value, bool& result);
 /** Returns the value of the parameter _paramID. If _paramID == -1 the value of the default parameter
  * will be returned. */
 int dss__DeviceGetValue(int _token, char* _deviceID, int _paramID, double& result);
diff --git a/webservices/soapC.cpp b/webservices/soapC.cpp
index 1968b11..236864f 100644
--- a/webservices/soapC.cpp
+++ b/webservices/soapC.cpp
@@ -1,13 +1,13 @@
 /* soapC.cpp
-   Generated by gSOAP 2.7.10 from model_soap.h
-   Copyright(C) 2000-2008, Robert van Engelen, Genivia Inc. All Rights Reserved.
+   Generated by gSOAP 2.7.9l from model_soap.h
+   Copyright(C) 2000-2007, Robert van Engelen, Genivia Inc. All Rights Reserved.
    This part of the software is released under one of the following licenses:
    GPL, the gSOAP public license, or Genivia's license for commercial use.
 */
 
 #include "soapH.h"
 
-SOAP_SOURCE_STAMP("@(#) soapC.cpp ver 2.7.10 2009-10-06 15:04:05 GMT")
+SOAP_SOURCE_STAMP("@(#) soapC.cpp ver 2.7.9l 2010-01-02 16:20:00 GMT")
 
 
 #ifndef WITH_NOGLOBAL
@@ -357,14 +357,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, int *type)
 		return soap_in_dss__ZoneStartDim(soap, NULL, NULL, "dss:ZoneStartDim");
 	case SOAP_TYPE_dss__ZoneStartDimResponse:
 		return soap_in_dss__ZoneStartDimResponse(soap, NULL, NULL, "dss:ZoneStartDimResponse");
-	case SOAP_TYPE_dss__ZoneDisable:
-		return soap_in_dss__ZoneDisable(soap, NULL, NULL, "dss:ZoneDisable");
-	case SOAP_TYPE_dss__ZoneDisableResponse:
-		return soap_in_dss__ZoneDisableResponse(soap, NULL, NULL, "dss:ZoneDisableResponse");
-	case SOAP_TYPE_dss__ZoneEnable:
-		return soap_in_dss__ZoneEnable(soap, NULL, NULL, "dss:ZoneEnable");
-	case SOAP_TYPE_dss__ZoneEnableResponse:
-		return soap_in_dss__ZoneEnableResponse(soap, NULL, NULL, "dss:ZoneEnableResponse");
 	case SOAP_TYPE_dss__ZoneDecreaseValue:
 		return soap_in_dss__ZoneDecreaseValue(soap, NULL, NULL, "dss:ZoneDecreaseValue");
 	case SOAP_TYPE_dss__ZoneDecreaseValueResponse:
@@ -409,14 +401,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, int *type)
 		return soap_in_dss__ApartmentStartDim(soap, NULL, NULL, "dss:ApartmentStartDim");
 	case SOAP_TYPE_dss__ApartmentStartDimResponse:
 		return soap_in_dss__ApartmentStartDimResponse(soap, NULL, NULL, "dss:ApartmentStartDimResponse");
-	case SOAP_TYPE_dss__ApartmentDisable:
-		return soap_in_dss__ApartmentDisable(soap, NULL, NULL, "dss:ApartmentDisable");
-	case SOAP_TYPE_dss__ApartmentDisableResponse:
-		return soap_in_dss__ApartmentDisableResponse(soap, NULL, NULL, "dss:ApartmentDisableResponse");
-	case SOAP_TYPE_dss__ApartmentEnable:
-		return soap_in_dss__ApartmentEnable(soap, NULL, NULL, "dss:ApartmentEnable");
-	case SOAP_TYPE_dss__ApartmentEnableResponse:
-		return soap_in_dss__ApartmentEnableResponse(soap, NULL, NULL, "dss:ApartmentEnableResponse");
 	case SOAP_TYPE_dss__ApartmentDecreaseValue:
 		return soap_in_dss__ApartmentDecreaseValue(soap, NULL, NULL, "dss:ApartmentDecreaseValue");
 	case SOAP_TYPE_dss__ApartmentDecreaseValueResponse:
@@ -453,14 +437,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, int *type)
 		return soap_in_dss__SetStartDim(soap, NULL, NULL, "dss:SetStartDim");
 	case SOAP_TYPE_dss__SetStartDimResponse:
 		return soap_in_dss__SetStartDimResponse(soap, NULL, NULL, "dss:SetStartDimResponse");
-	case SOAP_TYPE_dss__SetDisable:
-		return soap_in_dss__SetDisable(soap, NULL, NULL, "dss:SetDisable");
-	case SOAP_TYPE_dss__SetDisableResponse:
-		return soap_in_dss__SetDisableResponse(soap, NULL, NULL, "dss:SetDisableResponse");
-	case SOAP_TYPE_dss__SetEnable:
-		return soap_in_dss__SetEnable(soap, NULL, NULL, "dss:SetEnable");
-	case SOAP_TYPE_dss__SetEnableResponse:
-		return soap_in_dss__SetEnableResponse(soap, NULL, NULL, "dss:SetEnableResponse");
 	case SOAP_TYPE_dss__SetDecreaseValue:
 		return soap_in_dss__SetDecreaseValue(soap, NULL, NULL, "dss:SetDecreaseValue");
 	case SOAP_TYPE_dss__SetDecreaseValueResponse:
@@ -960,22 +936,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, int *type)
 		{	*type = SOAP_TYPE_dss__ZoneStartDimResponse;
 			return soap_in_dss__ZoneStartDimResponse(soap, NULL, NULL, NULL);
 		}
-		if (!soap_match_tag(soap, t, "dss:ZoneDisable"))
-		{	*type = SOAP_TYPE_dss__ZoneDisable;
-			return soap_in_dss__ZoneDisable(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:ZoneDisableResponse"))
-		{	*type = SOAP_TYPE_dss__ZoneDisableResponse;
-			return soap_in_dss__ZoneDisableResponse(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:ZoneEnable"))
-		{	*type = SOAP_TYPE_dss__ZoneEnable;
-			return soap_in_dss__ZoneEnable(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:ZoneEnableResponse"))
-		{	*type = SOAP_TYPE_dss__ZoneEnableResponse;
-			return soap_in_dss__ZoneEnableResponse(soap, NULL, NULL, NULL);
-		}
 		if (!soap_match_tag(soap, t, "dss:ZoneDecreaseValue"))
 		{	*type = SOAP_TYPE_dss__ZoneDecreaseValue;
 			return soap_in_dss__ZoneDecreaseValue(soap, NULL, NULL, NULL);
@@ -1064,22 +1024,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, int *type)
 		{	*type = SOAP_TYPE_dss__ApartmentStartDimResponse;
 			return soap_in_dss__ApartmentStartDimResponse(soap, NULL, NULL, NULL);
 		}
-		if (!soap_match_tag(soap, t, "dss:ApartmentDisable"))
-		{	*type = SOAP_TYPE_dss__ApartmentDisable;
-			return soap_in_dss__ApartmentDisable(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:ApartmentDisableResponse"))
-		{	*type = SOAP_TYPE_dss__ApartmentDisableResponse;
-			return soap_in_dss__ApartmentDisableResponse(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:ApartmentEnable"))
-		{	*type = SOAP_TYPE_dss__ApartmentEnable;
-			return soap_in_dss__ApartmentEnable(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:ApartmentEnableResponse"))
-		{	*type = SOAP_TYPE_dss__ApartmentEnableResponse;
-			return soap_in_dss__ApartmentEnableResponse(soap, NULL, NULL, NULL);
-		}
 		if (!soap_match_tag(soap, t, "dss:ApartmentDecreaseValue"))
 		{	*type = SOAP_TYPE_dss__ApartmentDecreaseValue;
 			return soap_in_dss__ApartmentDecreaseValue(soap, NULL, NULL, NULL);
@@ -1152,22 +1096,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_getelement(struct soap *soap, int *type)
 		{	*type = SOAP_TYPE_dss__SetStartDimResponse;
 			return soap_in_dss__SetStartDimResponse(soap, NULL, NULL, NULL);
 		}
-		if (!soap_match_tag(soap, t, "dss:SetDisable"))
-		{	*type = SOAP_TYPE_dss__SetDisable;
-			return soap_in_dss__SetDisable(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:SetDisableResponse"))
-		{	*type = SOAP_TYPE_dss__SetDisableResponse;
-			return soap_in_dss__SetDisableResponse(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:SetEnable"))
-		{	*type = SOAP_TYPE_dss__SetEnable;
-			return soap_in_dss__SetEnable(soap, NULL, NULL, NULL);
-		}
-		if (!soap_match_tag(soap, t, "dss:SetEnableResponse"))
-		{	*type = SOAP_TYPE_dss__SetEnableResponse;
-			return soap_in_dss__SetEnableResponse(soap, NULL, NULL, NULL);
-		}
 		if (!soap_match_tag(soap, t, "dss:SetDecreaseValue"))
 		{	*type = SOAP_TYPE_dss__SetDecreaseValue;
 			return soap_in_dss__SetDecreaseValue(soap, NULL, NULL, NULL);
@@ -1364,7 +1292,6 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_ignore_element(struct soap *soap)
 {
 	if (!soap_peek_element(soap))
 	{	int t;
-		DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unexpected element '%s' in input (level=%u, %d)\n", soap->tag, soap->level, soap->body));
 		if (soap->mustUnderstand && !soap->other)
 			return soap->error = SOAP_MUSTUNDERSTAND;
 		if (((soap->mode & SOAP_XML_STRICT) && soap->part != SOAP_IN_HEADER) || !soap_match_tag(soap, soap->tag, "SOAP-ENV:"))
@@ -1373,6 +1300,7 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_ignore_element(struct soap *soap)
 		}
 		if (!*soap->id || !soap_getelement(soap, &t))
 		{	soap->peeked = 0;
+			DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unknown element '%s' (level=%u, %d)\n", soap->tag, soap->level, soap->body));
 			if (soap->fignore)
 				soap->error = soap->fignore(soap, soap->tag);
 			else
@@ -1616,14 +1544,6 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_putelement(struct soap *soap, const void *ptr, co
 		return soap_out_dss__ZoneStartDim(soap, tag, id, (const struct dss__ZoneStartDim *)ptr, "dss:ZoneStartDim");
 	case SOAP_TYPE_dss__ZoneStartDimResponse:
 		return soap_out_dss__ZoneStartDimResponse(soap, tag, id, (const struct dss__ZoneStartDimResponse *)ptr, "dss:ZoneStartDimResponse");
-	case SOAP_TYPE_dss__ZoneDisable:
-		return soap_out_dss__ZoneDisable(soap, tag, id, (const struct dss__ZoneDisable *)ptr, "dss:ZoneDisable");
-	case SOAP_TYPE_dss__ZoneDisableResponse:
-		return soap_out_dss__ZoneDisableResponse(soap, tag, id, (const struct dss__ZoneDisableResponse *)ptr, "dss:ZoneDisableResponse");
-	case SOAP_TYPE_dss__ZoneEnable:
-		return soap_out_dss__ZoneEnable(soap, tag, id, (const struct dss__ZoneEnable *)ptr, "dss:ZoneEnable");
-	case SOAP_TYPE_dss__ZoneEnableResponse:
-		return soap_out_dss__ZoneEnableResponse(soap, tag, id, (const struct dss__ZoneEnableResponse *)ptr, "dss:ZoneEnableResponse");
 	case SOAP_TYPE_dss__ZoneDecreaseValue:
 		return soap_out_dss__ZoneDecreaseValue(soap, tag, id, (const struct dss__ZoneDecreaseValue *)ptr, "dss:ZoneDecreaseValue");
 	case SOAP_TYPE_dss__ZoneDecreaseValueResponse:
@@ -1668,14 +1588,6 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_putelement(struct soap *soap, const void *ptr, co
 		return soap_out_dss__ApartmentStartDim(soap, tag, id, (const struct dss__ApartmentStartDim *)ptr, "dss:ApartmentStartDim");
 	case SOAP_TYPE_dss__ApartmentStartDimResponse:
 		return soap_out_dss__ApartmentStartDimResponse(soap, tag, id, (const struct dss__ApartmentStartDimResponse *)ptr, "dss:ApartmentStartDimResponse");
-	case SOAP_TYPE_dss__ApartmentDisable:
-		return soap_out_dss__ApartmentDisable(soap, tag, id, (const struct dss__ApartmentDisable *)ptr, "dss:ApartmentDisable");
-	case SOAP_TYPE_dss__ApartmentDisableResponse:
-		return soap_out_dss__ApartmentDisableResponse(soap, tag, id, (const struct dss__ApartmentDisableResponse *)ptr, "dss:ApartmentDisableResponse");
-	case SOAP_TYPE_dss__ApartmentEnable:
-		return soap_out_dss__ApartmentEnable(soap, tag, id, (const struct dss__ApartmentEnable *)ptr, "dss:ApartmentEnable");
-	case SOAP_TYPE_dss__ApartmentEnableResponse:
-		return soap_out_dss__ApartmentEnableResponse(soap, tag, id, (const struct dss__ApartmentEnableResponse *)ptr, "dss:ApartmentEnableResponse");
 	case SOAP_TYPE_dss__ApartmentDecreaseValue:
 		return soap_out_dss__ApartmentDecreaseValue(soap, tag, id, (const struct dss__ApartmentDecreaseValue *)ptr, "dss:ApartmentDecreaseValue");
 	case SOAP_TYPE_dss__ApartmentDecreaseValueResponse:
@@ -1712,14 +1624,6 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_putelement(struct soap *soap, const void *ptr, co
 		return soap_out_dss__SetStartDim(soap, tag, id, (const struct dss__SetStartDim *)ptr, "dss:SetStartDim");
 	case SOAP_TYPE_dss__SetStartDimResponse:
 		return soap_out_dss__SetStartDimResponse(soap, tag, id, (const struct dss__SetStartDimResponse *)ptr, "dss:SetStartDimResponse");
-	case SOAP_TYPE_dss__SetDisable:
-		return soap_out_dss__SetDisable(soap, tag, id, (const struct dss__SetDisable *)ptr, "dss:SetDisable");
-	case SOAP_TYPE_dss__SetDisableResponse:
-		return soap_out_dss__SetDisableResponse(soap, tag, id, (const struct dss__SetDisableResponse *)ptr, "dss:SetDisableResponse");
-	case SOAP_TYPE_dss__SetEnable:
-		return soap_out_dss__SetEnable(soap, tag, id, (const struct dss__SetEnable *)ptr, "dss:SetEnable");
-	case SOAP_TYPE_dss__SetEnableResponse:
-		return soap_out_dss__SetEnableResponse(soap, tag, id, (const struct dss__SetEnableResponse *)ptr, "dss:SetEnableResponse");
 	case SOAP_TYPE_dss__SetDecreaseValue:
 		return soap_out_dss__SetDecreaseValue(soap, tag, id, (const struct dss__SetDecreaseValue *)ptr, "dss:SetDecreaseValue");
 	case SOAP_TYPE_dss__SetDecreaseValueResponse:
@@ -2099,18 +2003,6 @@ SOAP_FMAC3 void SOAP_FMAC4 soap_markelement(struct soap *soap, const void *ptr,
 	case SOAP_TYPE_dss__ZoneStartDimResponse:
 		soap_serialize_dss__ZoneStartDimResponse(soap, (const struct dss__ZoneStartDimResponse *)ptr);
 		break;
-	case SOAP_TYPE_dss__ZoneDisable:
-		soap_serialize_dss__ZoneDisable(soap, (const struct dss__ZoneDisable *)ptr);
-		break;
-	case SOAP_TYPE_dss__ZoneDisableResponse:
-		soap_serialize_dss__ZoneDisableResponse(soap, (const struct dss__ZoneDisableResponse *)ptr);
-		break;
-	case SOAP_TYPE_dss__ZoneEnable:
-		soap_serialize_dss__ZoneEnable(soap, (const struct dss__ZoneEnable *)ptr);
-		break;
-	case SOAP_TYPE_dss__ZoneEnableResponse:
-		soap_serialize_dss__ZoneEnableResponse(soap, (const struct dss__ZoneEnableResponse *)ptr);
-		break;
 	case SOAP_TYPE_dss__ZoneDecreaseValue:
 		soap_serialize_dss__ZoneDecreaseValue(soap, (const struct dss__ZoneDecreaseValue *)ptr);
 		break;
@@ -2177,18 +2069,6 @@ SOAP_FMAC3 void SOAP_FMAC4 soap_markelement(struct soap *soap, const void *ptr,
 	case SOAP_TYPE_dss__ApartmentStartDimResponse:
 		soap_serialize_dss__ApartmentStartDimResponse(soap, (const struct dss__ApartmentStartDimResponse *)ptr);
 		break;
-	case SOAP_TYPE_dss__ApartmentDisable:
-		soap_serialize_dss__ApartmentDisable(soap, (const struct dss__ApartmentDisable *)ptr);
-		break;
-	case SOAP_TYPE_dss__ApartmentDisableResponse:
-		soap_serialize_dss__ApartmentDisableResponse(soap, (const struct dss__ApartmentDisableResponse *)ptr);
-		break;
-	case SOAP_TYPE_dss__ApartmentEnable:
-		soap_serialize_dss__ApartmentEnable(soap, (const struct dss__ApartmentEnable *)ptr);
-		break;
-	case SOAP_TYPE_dss__ApartmentEnableResponse:
-		soap_serialize_dss__ApartmentEnableResponse(soap, (const struct dss__ApartmentEnableResponse *)ptr);
-		break;
 	case SOAP_TYPE_dss__ApartmentDecreaseValue:
 		soap_serialize_dss__ApartmentDecreaseValue(soap, (const struct dss__ApartmentDecreaseValue *)ptr);
 		break;
@@ -2243,18 +2123,6 @@ SOAP_FMAC3 void SOAP_FMAC4 soap_markelement(struct soap *soap, const void *ptr,
 	case SOAP_TYPE_dss__SetStartDimResponse:
 		soap_serialize_dss__SetStartDimResponse(soap, (const struct dss__SetStartDimResponse *)ptr);
 		break;
-	case SOAP_TYPE_dss__SetDisable:
-		soap_serialize_dss__SetDisable(soap, (const struct dss__SetDisable *)ptr);
-		break;
-	case SOAP_TYPE_dss__SetDisableResponse:
-		soap_serialize_dss__SetDisableResponse(soap, (const struct dss__SetDisableResponse *)ptr);
-		break;
-	case SOAP_TYPE_dss__SetEnable:
-		soap_serialize_dss__SetEnable(soap, (const struct dss__SetEnable *)ptr);
-		break;
-	case SOAP_TYPE_dss__SetEnableResponse:
-		soap_serialize_dss__SetEnableResponse(soap, (const struct dss__SetEnableResponse *)ptr);
-		break;
 	case SOAP_TYPE_dss__SetDecreaseValue:
 		soap_serialize_dss__SetDecreaseValue(soap, (const struct dss__SetDecreaseValue *)ptr);
 		break;
@@ -2488,14 +2356,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_instantiate(struct soap *soap, int t, const ch
 		return (void*)soap_instantiate_dss__SetDecreaseValueResponse(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__SetDecreaseValue:
 		return (void*)soap_instantiate_dss__SetDecreaseValue(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__SetEnableResponse:
-		return (void*)soap_instantiate_dss__SetEnableResponse(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__SetEnable:
-		return (void*)soap_instantiate_dss__SetEnable(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__SetDisableResponse:
-		return (void*)soap_instantiate_dss__SetDisableResponse(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__SetDisable:
-		return (void*)soap_instantiate_dss__SetDisable(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__SetStartDimResponse:
 		return (void*)soap_instantiate_dss__SetStartDimResponse(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__SetStartDim:
@@ -2532,14 +2392,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_instantiate(struct soap *soap, int t, const ch
 		return (void*)soap_instantiate_dss__ApartmentDecreaseValueResponse(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__ApartmentDecreaseValue:
 		return (void*)soap_instantiate_dss__ApartmentDecreaseValue(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__ApartmentEnableResponse:
-		return (void*)soap_instantiate_dss__ApartmentEnableResponse(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__ApartmentEnable:
-		return (void*)soap_instantiate_dss__ApartmentEnable(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__ApartmentDisableResponse:
-		return (void*)soap_instantiate_dss__ApartmentDisableResponse(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__ApartmentDisable:
-		return (void*)soap_instantiate_dss__ApartmentDisable(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__ApartmentStartDimResponse:
 		return (void*)soap_instantiate_dss__ApartmentStartDimResponse(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__ApartmentStartDim:
@@ -2584,14 +2436,6 @@ SOAP_FMAC3 void * SOAP_FMAC4 soap_instantiate(struct soap *soap, int t, const ch
 		return (void*)soap_instantiate_dss__ZoneDecreaseValueResponse(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__ZoneDecreaseValue:
 		return (void*)soap_instantiate_dss__ZoneDecreaseValue(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__ZoneEnableResponse:
-		return (void*)soap_instantiate_dss__ZoneEnableResponse(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__ZoneEnable:
-		return (void*)soap_instantiate_dss__ZoneEnable(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__ZoneDisableResponse:
-		return (void*)soap_instantiate_dss__ZoneDisableResponse(soap, -1, type, arrayType, n);
-	case SOAP_TYPE_dss__ZoneDisable:
-		return (void*)soap_instantiate_dss__ZoneDisable(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__ZoneStartDimResponse:
 		return (void*)soap_instantiate_dss__ZoneStartDimResponse(soap, -1, type, arrayType, n);
 	case SOAP_TYPE_dss__ZoneStartDim:
@@ -3061,30 +2905,6 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_fdelete(struct soap_clist *p)
 		else
 			delete[] (struct dss__SetDecreaseValue*)p->ptr;
 		break;
-	case SOAP_TYPE_dss__SetEnableResponse:
-		if (p->size < 0)
-			delete (struct dss__SetEnableResponse*)p->ptr;
-		else
-			delete[] (struct dss__SetEnableResponse*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__SetEnable:
-		if (p->size < 0)
-			delete (struct dss__SetEnable*)p->ptr;
-		else
-			delete[] (struct dss__SetEnable*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__SetDisableResponse:
-		if (p->size < 0)
-			delete (struct dss__SetDisableResponse*)p->ptr;
-		else
-			delete[] (struct dss__SetDisableResponse*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__SetDisable:
-		if (p->size < 0)
-			delete (struct dss__SetDisable*)p->ptr;
-		else
-			delete[] (struct dss__SetDisable*)p->ptr;
-		break;
 	case SOAP_TYPE_dss__SetStartDimResponse:
 		if (p->size < 0)
 			delete (struct dss__SetStartDimResponse*)p->ptr;
@@ -3193,30 +3013,6 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_fdelete(struct soap_clist *p)
 		else
 			delete[] (struct dss__ApartmentDecreaseValue*)p->ptr;
 		break;
-	case SOAP_TYPE_dss__ApartmentEnableResponse:
-		if (p->size < 0)
-			delete (struct dss__ApartmentEnableResponse*)p->ptr;
-		else
-			delete[] (struct dss__ApartmentEnableResponse*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__ApartmentEnable:
-		if (p->size < 0)
-			delete (struct dss__ApartmentEnable*)p->ptr;
-		else
-			delete[] (struct dss__ApartmentEnable*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__ApartmentDisableResponse:
-		if (p->size < 0)
-			delete (struct dss__ApartmentDisableResponse*)p->ptr;
-		else
-			delete[] (struct dss__ApartmentDisableResponse*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__ApartmentDisable:
-		if (p->size < 0)
-			delete (struct dss__ApartmentDisable*)p->ptr;
-		else
-			delete[] (struct dss__ApartmentDisable*)p->ptr;
-		break;
 	case SOAP_TYPE_dss__ApartmentStartDimResponse:
 		if (p->size < 0)
 			delete (struct dss__ApartmentStartDimResponse*)p->ptr;
@@ -3349,30 +3145,6 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_fdelete(struct soap_clist *p)
 		else
 			delete[] (struct dss__ZoneDecreaseValue*)p->ptr;
 		break;
-	case SOAP_TYPE_dss__ZoneEnableResponse:
-		if (p->size < 0)
-			delete (struct dss__ZoneEnableResponse*)p->ptr;
-		else
-			delete[] (struct dss__ZoneEnableResponse*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__ZoneEnable:
-		if (p->size < 0)
-			delete (struct dss__ZoneEnable*)p->ptr;
-		else
-			delete[] (struct dss__ZoneEnable*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__ZoneDisableResponse:
-		if (p->size < 0)
-			delete (struct dss__ZoneDisableResponse*)p->ptr;
-		else
-			delete[] (struct dss__ZoneDisableResponse*)p->ptr;
-		break;
-	case SOAP_TYPE_dss__ZoneDisable:
-		if (p->size < 0)
-			delete (struct dss__ZoneDisable*)p->ptr;
-		else
-			delete[] (struct dss__ZoneDisable*)p->ptr;
-		break;
 	case SOAP_TYPE_dss__ZoneStartDimResponse:
 		if (p->size < 0)
 			delete (struct dss__ZoneStartDimResponse*)p->ptr;
@@ -4586,7 +4358,7 @@ SOAP_FMAC3 std::string * SOAP_FMAC4 soap_get_std__string(struct soap *soap, std:
 
 SOAP_FMAC1 std::string * SOAP_FMAC2 soap_in_std__string(struct soap *soap, const char *tag, std::string *s, const char *type)
 {
-	if (soap_element_begin_in(soap, tag, 1, NULL))
+	if (soap_element_begin_in(soap, tag, 1, type))
 		return NULL;
 	if (!s)
 		s = soap_new_std__string(soap, -1);
@@ -12445,7 +12217,6 @@ SOAP_FMAC3 void SOAP_FMAC4 soap_default_dss__DeviceSetValue(struct soap *soap, s
 	soap_default_int(soap, &a->_token);
 	soap_default_string(soap, &a->_deviceID);
 	soap_default_double(soap, &a->_value);
-	soap_default_int(soap, &a->_paramID);
 }
 
 SOAP_FMAC3 void SOAP_FMAC4 soap_serialize_dss__DeviceSetValue(struct soap *soap, const struct dss__DeviceSetValue *a)
@@ -12472,8 +12243,6 @@ SOAP_FMAC3 int SOAP_FMAC4 soap_out_dss__DeviceSetValue(struct s