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

git version control dss-commits at forum.digitalstrom.org
Fri Jan 8 15:13:02 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  d230e2248871dec73385c4d4ebd2ec8032ec602e (commit)
       via  ad6343fdc150481c0c3111b2453998541cbbdda6 (commit)
      from  8f1dcc572f7b3e0880e7b4bde854a7f2d08bfcba (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 d230e2248871dec73385c4d4ebd2ec8032ec602e
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Jan 8 15:11:51 2010 +0100

    Redirect output to Logger
    
    All output (except for output in all ds485* files and some in main() )
    has been redirected to the Logger.
    
    Patch by Sebastian Kohler, aizo ag

commit ad6343fdc150481c0c3111b2453998541cbbdda6
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Jan 8 14:51:13 2010 +0100

    Finalize split up of webserver

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

Changes:
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index 72df81f..56c82a5 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -13,7 +13,10 @@ web/webserverplugin.cpp web/webserver.cpp web/json.cpp
 web/handler/debugrequesthandler.cpp web/handler/simrequesthandler.cpp
 web/handler/systemrequesthandler.cpp web/handler/meteringrequesthandler.cpp
 web/handler/structurerequesthandler.cpp web/handler/eventrequesthandler.cpp
-web/handler/propertyrequesthandler.cpp)
+web/handler/propertyrequesthandler.cpp web/handler/deviceinterfacerequesthandler.cpp
+web/handler/circuitrequesthandler.cpp web/handler/zonerequesthandler.cpp
+web/handler/devicerequesthandler.cpp web/handler/apartmentrequesthandler.cpp 
+web/handler/setrequesthandler.cpp web/handler/jsonhelper.cpp)
 
 
 add_subdirectory(ds485)
diff --git a/core/bonjour.cpp b/core/bonjour.cpp
index 37fb973..e226529 100644
--- a/core/bonjour.cpp
+++ b/core/bonjour.cpp
@@ -25,6 +25,7 @@
 #include "core/propertysystem.h"
 #include "core/dss.h"
 #include "core/base.h"
+#include "core/logger.h"
 #include "core/model/apartment.h"
 
 #include <arpa/inet.h>
@@ -61,7 +62,7 @@ namespace dss {
     void *context )
   {
     if(errorCode != kDNSServiceErr_NoError) {
-      std::cerr << "error received in browse callback" << std::endl;
+      Logger::getInstance()->log("error received in browse callback", lsError);
     }
   } // registerCallback
 #endif
@@ -85,7 +86,7 @@ static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state,
     switch (state) {
         case AVAHI_ENTRY_GROUP_ESTABLISHED :
             /* The entry group has been established successfully */
-            fprintf(stderr, "Service '%s' successfully established.\n", name);
+            Logger::getInstance()->log(std::string("Service '") + name + "' successfully established.", lsInfo)
             break;
 
         case AVAHI_ENTRY_GROUP_COLLISION : {
@@ -97,7 +98,7 @@ static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state,
             avahi_free(name);
             name = n;
 
-            fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
+            Logger::getInstance()->log(std::string("Service name collision, renaming service to '") + name + "'", lsError);
 
             /* And recreate the services */
             create_services(avahi_entry_group_get_client(g));
@@ -106,7 +107,7 @@ static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state,
 
         case AVAHI_ENTRY_GROUP_FAILURE :
 
-            fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
+            Logger::getInstance()->log(std::string("Entry group failure: ") + avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))), lsError);
 
             /* Some kind of failure happened while we were registering our services */
             avahi_simple_poll_quit(simple_poll);
@@ -128,7 +129,7 @@ static void create_services(AvahiClient *c) {
 
     if (!group)
         if (!(group = avahi_entry_group_new(c, entry_group_callback, NULL))) {
-            fprintf(stderr, "avahi_entry_group_new() failed: %s\n", avahi_strerror(avahi_client_errno(c)));
+		Logger::getInstance()->log(std::string("avahi_entry_group_new() failed: ") + avahi_strerror(avahi_client_errno(c)), lsError);
             goto fail;
         }
 
@@ -136,7 +137,7 @@ static void create_services(AvahiClient *c) {
      * because it was reset previously, add our entries.  */
 
     if (avahi_entry_group_is_empty(group)) {
-        fprintf(stderr, "Adding service '%s'\n", name);
+        Logger::getInstance()->log("Adding service '" + name + "'", lsInfo);
 
         /* We will now add two services and one subtype to the entry
          * group. The two services have the same name, but differ in
@@ -151,13 +152,13 @@ static void create_services(AvahiClient *c) {
             if (ret == AVAHI_ERR_COLLISION)
                 goto collision;
 
-            fprintf(stderr, "Failed to add _dssweb._tcp service: %s\n", avahi_strerror(ret));
+            Logger::getInstance()->log(std::string("Failed to add _dssweb._tcp service: ") + avahi_strerror(ret), lsError);
             goto fail;
         }
 
         /* Tell the server to register the service */
         if ((ret = avahi_entry_group_commit(group)) < 0) {
-            fprintf(stderr, "Failed to commit entry group: %s\n", avahi_strerror(ret));
+            Logger::getInstance()->log(std::string("Failed to commit entry group: ") + avahi_strerror(ret), lsError);
             goto fail;
         }
     }
@@ -172,7 +173,7 @@ collision:
     avahi_free(name);
     name = n;
 
-    fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
+    Logger::getInstance()->log(std::string("Service name collision, renaming service to '") + name + "'", lsInfo);
 
     avahi_entry_group_reset(group);
 
@@ -198,7 +199,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UN
 
         case AVAHI_CLIENT_FAILURE:
 
-            fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
+            Logger::getInstance()->log(std::string("Client failure: ") + avahi_strerror(avahi_client_errno(c)), lsError);
             avahi_simple_poll_quit(simple_poll);
 
             break;
@@ -238,7 +239,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UN
 
     /* Allocate main loop object */
     if (!(simple_poll = avahi_simple_poll_new())) {
-        fprintf(stderr, "Failed to create simple poll object.\n");
+        Logger::getInstance->log("Failed to create simple poll object.", lsError);
         goto fail;
     }
 
@@ -249,7 +250,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UN
 
     /* Check wether creating the client object succeeded */
     if (!client) {
-        fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
+        Logger::getInstance()->log(std::string("Failed to create client: ") + avahi_strerror(error), lsError);
         goto fail;
     }
 
@@ -298,4 +299,3 @@ fail:
   } // execute
 
 }
-
diff --git a/core/event.cpp b/core/event.cpp
index b79bcdb..4b47029 100644
--- a/core/event.cpp
+++ b/core/event.cpp
@@ -34,6 +34,7 @@
 
 #include <set>
 #include <iostream>
+#include <sstream>
 
 #include <boost/filesystem.hpp>
 
@@ -58,7 +59,6 @@ using Poco::XML::InputSource;
 using Poco::XML::Node;
 
 using std::set;
-using std::cout;
 
 namespace dss {
 
@@ -648,9 +648,12 @@ namespace dss {
 
   bool EventRunner::raisePendingEvents(DateTime& _from, int _deltaSeconds) {
     bool result = false;
+    std::ostringstream logSStream;
     DateTime virtualNow = _from.addSeconds(-_deltaSeconds/2);
     if(DebugEventRunner) {
-      cout << "vNow:    " << virtualNow << std::endl;
+      logSStream << "vNow:    " << virtualNow;
+      Logger::getInstance()->log(logSStream.str());
+      logSStream.str("");
     }
 
     m_EventsMutex.lock();
@@ -659,8 +662,10 @@ namespace dss {
     {
       DateTime nextOccurence = ipSchedEvt->getSchedule().getNextOccurence(virtualNow);
       if(DebugEventRunner) {
-        cout << "nextOcc: " << nextOccurence << std::endl;
-        cout << "diff:    " << nextOccurence.difference(virtualNow) << std::endl;
+        logSStream << "nextOcc: " << nextOccurence << "; "
+                   << "diff:    " << nextOccurence.difference(virtualNow);
+        Logger::getInstance()->log(logSStream.str());
+        logSStream.str("");
       }
       if(abs(nextOccurence.difference(virtualNow)) <= _deltaSeconds/2) {
         result = true;
diff --git a/core/jshandler.cpp b/core/jshandler.cpp
index 1da56e1..b75ea07 100644
--- a/core/jshandler.cpp
+++ b/core/jshandler.cpp
@@ -115,10 +115,13 @@ namespace dss {
 
     while (len > 0 && (line[len-1] == '\r' || line[len-1] == '\n')){ line[len-1]='\0'; len--; }
 
-    printf("JS Error: %s\nFile: %s:%u\n", msg, er->filename, er->lineno);
+
+    std::ostringstream logSStream;
+    logSStream << "JS Error: " << msg << " in file: " << er->filename << ":" << er->lineno;
     if (line[0]){
-      printf("%s\n%s\n", line, pointer);
+      logSStream << "; line: " << line << "; pointer: " << pointer;
     }
+    Logger::getInstance()->log(logSStream.str(), lsError);
 
     free(pointer);
     free(line);
diff --git a/core/jshandler.h b/core/jshandler.h
index a7ad4c4..8a040bc 100644
--- a/core/jshandler.h
+++ b/core/jshandler.h
@@ -44,6 +44,7 @@
 
 #include "base.h"
 #include "mutex.h"
+#include "logger.h"
 
 namespace dss {
 
@@ -234,7 +235,7 @@ namespace dss {
   class ScriptContextAttachedObject {
   public:
     ~ScriptContextAttachedObject() {
-      std::cout << "destroying attached object" << std::endl;
+      Logger::getInstance()->log("destroying attached object");
     }
   }; // ScriptContextAttachedObject
 
diff --git a/core/metering/metering.cpp b/core/metering/metering.cpp
index ddfb8ca..86855d0 100644
--- a/core/metering/metering.cpp
+++ b/core/metering/metering.cpp
@@ -35,6 +35,10 @@
 
 #include <boost/filesystem.hpp>
 
+#ifdef LOG_TIMING
+  #include <sstream>
+#endif
+
 namespace dss {
 
   //================================================== Metering
@@ -77,6 +81,9 @@ namespace dss {
     SeriesWriter<CurrentValue> writer;
 
     _config->running();
+#ifdef LOG_TIMING
+    std::ostringstream logSStream;
+#endif
 
 #ifdef LOG_TIMING
     Timestamp checkingAll;
@@ -101,7 +108,9 @@ namespace dss {
           Timestamp startedLoadingSingle;
           boost::shared_ptr<Series<CurrentValue> > s = boost::shared_ptr<Series<CurrentValue> >(reader.readFromXML(fileName));
 #ifdef LOG_TIMING
-          cout << "loading single: " <<  Timestamp().getDifference(startedLoadingSingle) << endl;
+          logSStream << "loading single: " << Timestamp().getDifference(startedLoadingSingle);
+          log(logSStream.str());
+          logSStream.str("");
 #endif
           if(s.get() != NULL) {
             series.push_back(s);
@@ -118,7 +127,9 @@ namespace dss {
         }
       }
 #ifdef LOG_TIMING
-      cout << "loading: " << Timestamp().getDifference(startedLoading) << endl;
+      logSStream << "loading: " << Timestamp().getDifference(startedLoading);
+      log(logMessage.str());
+      logSStream.str("");
 #endif
 
       // stitch up chain
@@ -150,12 +161,19 @@ namespace dss {
           log("Could not poll dsMeter " + (*ipDSMeter)->getDSID().toString() + ". Message: " + err.what());
         }
 #ifdef LOG_TIMING
-        cout << "fetching value: " << Timestamp().getDifference(fetchingValue) << endl;
+        logSStream << "fetching value: " << Timestamp().getDifference(fetchingValue);
+        log(logSStream.str());
+        logSStream.str("");
+#endif
+
+#ifdef LOG_TIMING
         Timestamp startedAddingValue;
 #endif
         series[0]->addValue(value, timeRequested);
 #ifdef LOG_TIMING
-        cout << "adding value: " << Timestamp().getDifference(startedAddingValue) << endl;
+        logSStream << "adding value: " << Timestamp().getDifference(startedAddingValue);
+        log(logSStream.str());
+        logSStream.str("");
 #endif
 
 #ifdef LOG_TIMING
@@ -173,19 +191,27 @@ namespace dss {
           log("Metering::checkDSMeters: Trying to save series to '" + fileName + "'");
           writer.writeToXML(*s, fileName);
 #ifdef LOG_TIMING
-          cout << "writing single: " << Timestamp().getDifference(startedWritingSingle) << endl;
+          logSStream << "writing single: " << Timestamp().getDifference(startedWritingSingle) << endl;
+          log(logSStream.str());
+          logSStream.str("");
 #endif
         }
 #ifdef LOG_TIMING
-        cout << "writing: " << Timestamp().getDifference(startedWriting) << endl;
+        logSStream << "writing: " << Timestamp().getDifference(startedWriting) << endl;
+        log(logSStream.str());
+        logSStream.str("");
 #endif
       }
 #ifdef LOG_TIMING
-      cout << "checkingDSMeter: " << Timestamp().getDifference(checkingDSMeter) << endl;
+      logSStream << "checkingDSMeter: " << Timestamp().getDifference(checkingDSMeter) << endl;
+      log(logSStream.str());
+      logSStream.str("");
 #endif
     }
 #ifdef LOG_TIMING
-    cout << "checking all: " << Timestamp().getDifference(checkingAll) << endl;
+    logSStream << "checking all: " << Timestamp().getDifference(checkingAll) << endl;
+    log(logSStream.str());
+    logSStream.str("");
 #endif
   } // checkDSMeters
 
diff --git a/core/metering/seriespersistence.cpp b/core/metering/seriespersistence.cpp
index 940d444..7cfb0aa 100644
--- a/core/metering/seriespersistence.cpp
+++ b/core/metering/seriespersistence.cpp
@@ -144,6 +144,10 @@ namespace dss {
     AutoPtr<Document> pDoc = new Document;
 
 #ifdef LOG_TIMING
+    std::stringstream logSStream;
+#endif
+
+#ifdef LOG_TIMING
     Timestamp buildingXML;
 #endif
     AutoPtr<ProcessingInstruction> pXMLHeader = pDoc->createProcessingInstruction("xml", "version='1.0' encoding='utf-8'");
@@ -202,8 +206,12 @@ namespace dss {
       pValues->appendChild(elem);
     }
 #ifdef LOG_TIMING
-    std::cout << "building xml: " << Timestamp().getDifference(buildingXML) << std::endl;
+    logSStream << "building xml: " << Timestamp().getDifference(buildingXML);
+    Logger::getInstance()->log(logSStream.str());
+    logSStream.str("");
+#endif
 
+#ifdef LOG_TIMING
     Timestamp writingXML;
 #endif
     // write it to a temporary site first
@@ -225,14 +233,20 @@ namespace dss {
       ofs.close();
 
 #ifdef LOG_TIMING
-      std::cout << "writing xml: " << Timestamp().getDifference(writingXML) << std::endl;
+      logSStream << "writing xml: " << Timestamp().getDifference(writingXML);
+      Logger::getInstance()->log(logSStream.str());
+      logSStream.str("");
+#endif
 
+#ifdef LOG_TIMING
       Timestamp renaming;
 #endif
       // move it to the desired location
       rename(tmpOut.c_str(), _path.c_str());
 #ifdef LOG_TIMING
-      std::cout << "renaming: " << Timestamp().getDifference(renaming) << std::endl;
+      logSStream << "renaming: " << Timestamp().getDifference(renaming) << std::endl;
+      Logger::getInstance()->log(logSStream.str());
+      logSStream.str("");
 #endif
     } else {
       Logger::getInstance()->log("Could not open file '" + tmpOut + "' for writing", lsFatal);
diff --git a/core/propertysystem.cpp b/core/propertysystem.cpp
index b780d4e..9dbe408 100644
--- a/core/propertysystem.cpp
+++ b/core/propertysystem.cpp
@@ -472,7 +472,7 @@ namespace dss {
         if(m_PropVal.valueType == vTypeString) {
           m_Proxy.stringProxy->setValue(_value);
         } else {
-          std::cerr << "*** setting std::string on a non std::string property";
+          Logger::getInstance()->log("*** setting std::string on a non std::string property", lsError);
           throw PropertyTypeMismatch("Property-Type mismatch: " + m_Name);
         }
       } else {
@@ -498,7 +498,7 @@ namespace dss {
         if(m_PropVal.valueType == vTypeInteger) {
           m_Proxy.intProxy->setValue(_value);
         } else {
-          std::cerr << "*** setting integer on a non integer property";
+          Logger::getInstance()->log("*** setting integer on a non integer property", lsError);
           throw PropertyTypeMismatch("Property-Type mismatch: " + m_Name);
         }
       } else {
@@ -518,7 +518,7 @@ namespace dss {
         if(m_PropVal.valueType == vTypeBoolean) {
           m_Proxy.boolProxy->setValue(_value);
         } else {
-          std::cerr << "*** setting bool on a non booleanproperty";
+          Logger::getInstance()->log("*** setting bool on a non booleanproperty");
           throw PropertyTypeMismatch("Property-Type mismatch: " + m_Name);
         }
       } else {
@@ -541,7 +541,7 @@ namespace dss {
           return m_PropVal.actualValue.pString;
         }
       } else {
-        std::cerr << "Property-Type mismatch: " << m_Name << std::endl;
+//        std::cerr << "Property-Type mismatch: " << m_Name << std::endl;
         throw PropertyTypeMismatch("Property-Type mismatch: " + m_Name);
       }
     }
@@ -558,7 +558,7 @@ namespace dss {
           return m_PropVal.actualValue.integer;
         }
       } else {
-        std::cerr << "Property-Type mismatch: " << m_Name << std::endl;
+ //       std::cerr << "Property-Type mismatch: " << m_Name << std::endl;
         throw PropertyTypeMismatch("Property-Type mismatch: " + m_Name);
       }
     }
@@ -575,7 +575,7 @@ namespace dss {
           return m_PropVal.actualValue.boolean;
         }
       } else {
-        std::cerr << "Property-Type mismatch: " << m_Name << std::endl;
+//        std::cerr << "Property-Type mismatch: " << m_Name << std::endl;
         throw PropertyTypeMismatch("Property-Type mismatch: " + m_Name);
       }
     }
diff --git a/core/syncevent.cpp b/core/syncevent.cpp
index b1fe81c..6aaa5e5 100644
--- a/core/syncevent.cpp
+++ b/core/syncevent.cpp
@@ -109,7 +109,7 @@ bool SyncEvent::waitFor( int _timeoutMS ) {
   int result = pthread_cond_timedwait( &m_Condition, m_ConditionMutex.getMutex(), &timeout );
   m_ConditionMutex.unlock();
   if(result != ETIMEDOUT && result != 0) {
-    //perror("SyncEvent::waitFor");
+    //Logger::getInstance()->log("SyncEvent::waitFor", lsError);
   }
   return !(result == ETIMEDOUT);
 #else
diff --git a/core/web/handler/apartmentrequesthandler.cpp b/core/web/handler/apartmentrequesthandler.cpp
new file mode 100644
index 0000000..a44046e
--- /dev/null
+++ b/core/web/handler/apartmentrequesthandler.cpp
@@ -0,0 +1,162 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "apartmentrequesthandler.h"
+
+#include "core/foreach.h"
+#include "core/dss.h"
+#include "core/ds485const.h"
+
+#include "core/web/json.h"
+
+#include "core/model/apartment.h"
+#include "core/model/zone.h"
+#include "core/model/modulator.h"
+#include "core/model/device.h"
+#include "core/model/deviceinterface.h"
+#include "core/model/group.h"
+#include "core/model/set.h"
+
+#include "jsonhelper.h"
+
+namespace dss {
+
+  //=========================================== ApartmentRequestHandler
+
+  boost::shared_ptr<JSONObject> ApartmentRequestHandler::jsonHandleRequest(const RestfulRequest& _request, Session* _session) {
+    std::string errorMessage;
+    if(_request.getMethod() == "getConsumption") {
+      int accumulatedConsumption = 0;
+      foreach(DSMeter* pDSMeter, getDSS().getApartment().getDSMeters()) {
+        accumulatedConsumption += pDSMeter->getPowerConsumption();
+      }
+      boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+      resultObj->addProperty("consumption", accumulatedConsumption);
+      return success(resultObj);
+    } 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) {
+          return failure("Could not find group with name '" + groupName + "'");
+        }
+      } else if(!groupIDString.empty()) {
+        try {
+          int groupID = strToIntDef(groupIDString, -1);
+          if(groupID != -1) {
+            Group& grp = getDSS().getApartment().getGroup(groupID);
+            interface = &grp;
+          } else {
+            return failure("Could not parse group id '" + groupIDString + "'");
+          }
+        } catch(std::runtime_error& e) {
+          return failure("Could not find group with ID '" + groupIDString + "'");
+        }
+      }
+      if(interface != NULL) {
+        interface = &getDSS().getApartment().getGroup(GroupIDBroadcast);
+        return success();
+      }
+      return failure("No interface");
+    } else {
+      if(_request.getMethod() == "getStructure") {
+        return success(toJSON(getDSS().getApartment()));
+      } else if(_request.getMethod() == "getDevices") {
+        Set devices;
+        if(_request.getParameter("unassigned").empty()) {
+          devices = getDSS().getApartment().getDevices();
+        } else {
+          devices = getUnassignedDevices();
+        }
+
+        return success(toJSON(devices));
+/* TODO: re-enable
+      } else if(_request.getMethod() == "login") {
+        int token = m_LastSessionID;
+        m_Sessions[token] = Session(token);
+        return "{" + toJSON("token") + ": " + toJSON(token) + "}";
+*/
+      } else if(_request.getMethod() == "getCircuits") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        boost::shared_ptr<JSONArrayBase> circuits(new JSONArrayBase());
+
+        resultObj->addElement("circuits", circuits);
+        std::vector<DSMeter*>& dsMeters = getDSS().getApartment().getDSMeters();
+        foreach(DSMeter* dsMeter, dsMeters) {
+          boost::shared_ptr<JSONObject> circuit(new JSONObject());
+          circuits->addElement("", circuit);
+          circuit->addProperty("name", dsMeter->getName());
+          circuit->addProperty("dsid", dsMeter->getDSID().toString());
+          circuit->addProperty("busid", dsMeter->getBusID());
+          circuit->addProperty("hwVersion", dsMeter->getHardwareVersion());
+          circuit->addProperty("swVersion", dsMeter->getSoftwareVersion());
+          circuit->addProperty("hwName", dsMeter->getHardwareName());
+          circuit->addProperty("deviceType", dsMeter->getDeviceType());
+          circuit->addProperty("isPresent", dsMeter->isPresent());
+        }
+        return success(resultObj);
+      } else if(_request.getMethod() == "getName") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("name", getDSS().getApartment().getName());
+        return success(resultObj);
+      } else if(_request.getMethod() == "setName") {
+        getDSS().getApartment().setName(_request.getParameter("newName"));
+        return success();
+      } else if(_request.getMethod() == "rescan") {
+        std::vector<DSMeter*> mods = getDSS().getApartment().getDSMeters();
+        foreach(DSMeter* pDSMeter, mods) {
+          pDSMeter->setIsValid(false);
+        }
+        return success();
+      } else {
+        throw std::runtime_error("Unhandled function");
+      }
+    }
+  } // handleApartmentCall
+
+  Set ApartmentRequestHandler::getUnassignedDevices() {
+    Apartment& apt = DSS::getInstance()->getApartment();
+    Set devices = apt.getZone(0).getDevices();
+
+    std::vector<Zone*>& zones = apt.getZones();
+    for(std::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
+
+
+
+} // namespace dss
diff --git a/core/web/handler/apartmentrequesthandler.h b/core/web/handler/apartmentrequesthandler.h
new file mode 100644
index 0000000..b434ae6
--- /dev/null
+++ b/core/web/handler/apartmentrequesthandler.h
@@ -0,0 +1,41 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef APARTMENTREQUESTHANDLER_H_
+#define APARTMENTREQUESTHANDLER_H_
+
+#include "deviceinterfacerequesthandler.h"
+
+namespace dss {
+
+  class Set;
+
+  class ApartmentRequestHandler : public DeviceInterfaceRequestHandler {
+  public:
+    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
+  private:
+    Set getUnassignedDevices();
+  }; // ApartmentRequestHandler
+
+} // namespace dss
+
+#endif /* APARTMENTREQUESTHANDLER_H_ */
diff --git a/core/web/handler/circuitrequesthandler.cpp b/core/web/handler/circuitrequesthandler.cpp
new file mode 100644
index 0000000..5532e0c
--- /dev/null
+++ b/core/web/handler/circuitrequesthandler.cpp
@@ -0,0 +1,79 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "circuitrequesthandler.h"
+
+#include "core/dss.h"
+
+#include "core/model/modulator.h"
+#include "core/model/apartment.h"
+
+#include "core/web/json.h"
+
+namespace dss {
+
+
+  //=========================================== CircuitRequestHandler
+
+  boost::shared_ptr<JSONObject> CircuitRequestHandler::jsonHandleRequest(const RestfulRequest& _request, Session* _session) {
+    std::string idString = _request.getParameter("id");
+    if(idString.empty()) {
+      return failure("missing parameter id");
+    }
+    dsid_t dsid = dsid_t::fromString(idString);
+    if(dsid == NullDSID) {
+      return failure("could not parse dsid");
+    }
+    try {
+      DSMeter& dsMeter = getDSS().getApartment().getDSMeterByDSID(dsid);
+      if(_request.getMethod() == "getName") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("name", dsMeter.getName());
+        return success(resultObj);
+      } else if(_request.getMethod() == "setName") {
+        dsMeter.setName(_request.getParameter("newName"));
+        return success();
+      } else if(_request.getMethod() == "getEnergyBorder") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("orange", dsMeter.getEnergyLevelOrange());
+        resultObj->addProperty("red", dsMeter.getEnergyLevelRed());
+        return success(resultObj);
+      } else if(_request.getMethod() == "getConsumption") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("consumption", dsMeter.getPowerConsumption());
+        return success(resultObj);
+      } else if(_request.getMethod() == "getEnergyMeterValue") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("metervalue", dsMeter.getEnergyMeterValue());
+        return success(resultObj);
+      } else if(_request.getMethod() == "rescan") {
+        dsMeter.setIsValid(false);
+        return success();
+      } else {
+        throw std::runtime_error("Unhandled function");
+      }
+    } catch(std::runtime_error&) {
+      return failure("could not find dsMeter with given dsid");
+    }
+  } // handleRequest
+
+} // namespace dss
diff --git a/core/web/handler/circuitrequesthandler.h b/core/web/handler/circuitrequesthandler.h
new file mode 100644
index 0000000..64e94e6
--- /dev/null
+++ b/core/web/handler/circuitrequesthandler.h
@@ -0,0 +1,37 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef CIRCUITREQUESTHANDLER_H_
+#define CIRCUITREQUESTHANDLER_H_
+
+#include "core/web/webrequests.h"
+
+namespace dss {
+
+  class CircuitRequestHandler : public WebServerRequestHandlerJSON {
+  public:
+    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
+  }; // CircuitRequestHandler
+
+} // namespace dss
+
+#endif /* CIRCUITREQUESTHANDLER_H_ */
diff --git a/core/web/handler/debugrequesthandler.cpp b/core/web/handler/debugrequesthandler.cpp
index 6774c63..fb2c2be 100644
--- a/core/web/handler/debugrequesthandler.cpp
+++ b/core/web/handler/debugrequesthandler.cpp
@@ -22,6 +22,8 @@
 
 #include "debugrequesthandler.h"
 
+#include <sstream>
+
 #include "core/web/json.h"
 
 #include "core/ds485/ds485.h"
@@ -41,6 +43,7 @@ namespace dss {
   //=========================================== DebugRequestHandler
 
   boost::shared_ptr<JSONObject> DebugRequestHandler::jsonHandleRequest(const RestfulRequest& _request, Session* _session) {
+    std::ostringstream logSStream;
     if(_request.getMethod() == "sendFrame") {
       int destination = strToIntDef(_request.getParameter("destination"),0) & 0x3F;
       bool broadcast = _request.getParameter("broadcast") == "true";
@@ -48,13 +51,16 @@ namespace dss {
       int command = strToIntDef(_request.getParameter("command"), 0x09 /* request */) & 0x00FF;
       int length = strToIntDef(_request.getParameter("length"), 0x00) & 0x0F;
 
-      std::cout
+      logSStream
           << "sending frame: "
           << "\ndest:    " << destination
           << "\nbcst:    " << broadcast
           << "\ncntr:    " << counter
           << "\ncmd :    " << command
-          << "\nlen :    " << length << std::endl;
+          << "\nlen :    " << length;
+
+      Logger::getInstance()->log(logSStream.str());
+      logSStream.str("");
 
       DS485CommandFrame* frame = new DS485CommandFrame();
       frame->getHeader().setBroadcast(broadcast);
@@ -63,10 +69,18 @@ namespace dss {
       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";
+
+        logSStream << "b" << std::dec << iByte << ": " << std::hex << (int)byte << "\n";
+        Logger::getInstance()->log(logSStream.str());
+        logSStream.str("");
+
         frame->getPayload().add<uint8_t>(byte);
       }
-      std::cout << std::dec << "done" << std::endl;
+
+      logSStream << std::dec << "done" << std::endl;
+      Logger::getInstance()->log(logSStream.str());
+      logSStream.str("");
+
       DS485Interface* intf = &DSS::getInstance()->getDS485Interface();
       DS485Proxy* proxy = dynamic_cast<DS485Proxy*>(intf);
       if(proxy != NULL) {
diff --git a/core/web/handler/deviceinterfacerequesthandler.cpp b/core/web/handler/deviceinterfacerequesthandler.cpp
new file mode 100644
index 0000000..50b213e
--- /dev/null
+++ b/core/web/handler/deviceinterfacerequesthandler.cpp
@@ -0,0 +1,118 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "deviceinterfacerequesthandler.h"
+
+#include <stdexcept>
+
+#include "core/web/json.h"
+#include "core/model/deviceinterface.h"
+
+namespace dss {
+
+
+  //=========================================== DeviceInterfaceRequestHandler
+
+  boost::shared_ptr<JSONObject> DeviceInterfaceRequestHandler::handleDeviceInterfaceRequest(const RestfulRequest& _request, IDeviceInterface* _interface) {
+    assert(_interface != NULL);
+    if(_request.getMethod() == "turnOn") {
+      _interface->turnOn();
+      return success();
+    } else if(_request.getMethod() == "turnOff") {
+      _interface->turnOff();
+      return success();
+    } else if(_request.getMethod() == "increaseValue") {
+      _interface->increaseValue();
+      return success();
+    } else if(_request.getMethod() == "decreaseValue") {
+      _interface->decreaseValue();
+      return success();
+    } else if(_request.getMethod() == "startDim") {
+      std::string direction = _request.getParameter("direction");
+      if(direction == "up") {
+        _interface->startDim(true);
+      } else {
+        _interface->startDim(false);
+      }
+      return success();
+    } else if(_request.getMethod() == "endDim") {
+      _interface->endDim();
+      return success();
+    } else if(_request.getMethod() == "setValue") {
+      std::string valueStr = _request.getParameter("value");
+      int value = strToIntDef(valueStr, -1);
+      if(value == -1) {
+        return failure("invalid or missing parameter value: '" + valueStr + "'");
+      } else {
+        _interface->setValue(value);
+      }
+      return success();
+    } else if(_request.getMethod() == "callScene") {
+      std::string sceneStr = _request.getParameter("sceneNr");
+      int sceneID = strToIntDef(sceneStr, -1);
+      if(sceneID != -1) {
+        _interface->callScene(sceneID);
+      } else {
+        return failure("invalid sceneNr: '" + sceneStr + "'");
+      }
+      return success();
+    } else if(_request.getMethod() == "saveScene") {
+      std::string sceneStr = _request.getParameter("sceneNr");
+      int sceneID = strToIntDef(sceneStr, -1);
+      if(sceneID != -1) {
+        _interface->saveScene(sceneID);
+      } else {
+        return failure("invalid sceneNr: '" + sceneStr + "'");
+      }
+      return success();
+    } else if(_request.getMethod() == "undoScene") {
+      std::string sceneStr = _request.getParameter("sceneNr");
+      int sceneID = strToIntDef(sceneStr, -1);
+      if(sceneID != -1) {
+        _interface->undoScene(sceneID);
+      } else {
+        return failure("invalid sceneNr: '" + sceneStr + "'");
+      }
+      return success();
+    } else if(_request.getMethod() == "getConsumption") {
+      boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+      resultObj->addProperty("consumption", _interface->getPowerConsumption());
+      return success(resultObj);
+    }
+    throw std::runtime_error("Unknown function");
+  } // handleRequest
+
+  bool DeviceInterfaceRequestHandler::isDeviceInterfaceCall(const RestfulRequest& _request) {
+    return _request.getMethod() == "turnOn"
+        || _request.getMethod() == "turnOff"
+        || _request.getMethod() == "increaseValue"
+        || _request.getMethod() == "decreaseValue"
+        || _request.getMethod() == "startDim"
+        || _request.getMethod() == "endDim"
+        || _request.getMethod() == "setValue"
+        || _request.getMethod() == "callScene"
+        || _request.getMethod() == "saveScene"
+        || _request.getMethod() == "undoScene"
+        || _request.getMethod() == "getConsumption";
+  } // isDeviceInterfaceCall
+
+} // namespace dss
diff --git a/core/web/handler/deviceinterfacerequesthandler.h b/core/web/handler/deviceinterfacerequesthandler.h
new file mode 100644
index 0000000..75c5a69
--- /dev/null
+++ b/core/web/handler/deviceinterfacerequesthandler.h
@@ -0,0 +1,45 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DEVICEINTERFACEREQUESTHANDLER_H_
+#define DEVICEINTERFACEREQUESTHANDLER_H_
+
+#include <boost/shared_ptr.hpp>
+
+#include "core/web/webrequests.h"
+
+namespace dss {
+
+  class IDeviceInterface;
+  class RestfulRequest;
+
+  class DeviceInterfaceRequestHandler : public WebServerRequestHandlerJSON {
+  public:
+    boost::shared_ptr<JSONObject> handleDeviceInterfaceRequest(const RestfulRequest& _request, IDeviceInterface* _interface);
+
+  protected:
+    bool isDeviceInterfaceCall(const RestfulRequest& _request);
+  };
+
+} // namespace dss
+
+#endif /* DEVICEINTERFACEREQUESTHANDLER_H_ */
diff --git a/core/web/handler/devicerequesthandler.cpp b/core/web/handler/devicerequesthandler.cpp
new file mode 100644
index 0000000..44e0022
--- /dev/null
+++ b/core/web/handler/devicerequesthandler.cpp
@@ -0,0 +1,138 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "devicerequesthandler.h"
+
+#include "core/dss.h"
+
+#include "core/model/apartment.h"
+#include "core/model/device.h"
+
+#include "core/web/json.h"
+
+namespace dss {
+
+
+  //=========================================== DeviceRequestHandler
+
+  boost::shared_ptr<JSONObject> DeviceRequestHandler::jsonHandleRequest(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") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        int numGroups = pDevice->getGroupsCount();
+
+        boost::shared_ptr<JSONArrayBase> groups(new JSONArrayBase());
+        resultObj->addElement("groups", groups);
+        for(int iGroup = 0; iGroup < numGroups; iGroup++) {
+          try {
+            Group& group = pDevice->getGroupByIndex(iGroup);
+            boost::shared_ptr<JSONObject> groupObj(new JSONObject());
+            groups->addElement("", groupObj);
+
+            groupObj->addProperty("id", group.getID());
+            if(!group.getName().empty()) {
+              groupObj->addProperty("name", group.getName());
+            }
+          } catch(std::runtime_error&) {
+            Logger::getInstance()->log("DeviceRequestHandler: Group only present at device level");
+          }
+        }
+        return success(resultObj);
+      } else if(_request.getMethod() == "getState") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("isOn", pDevice->isOn());
+        return success(resultObj);
+      } else if(_request.getMethod() == "getName") {
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("name", pDevice->getName());
+        return success(resultObj);
+      } else if(_request.getMethod() == "setName") {
+        pDevice->setName(_request.getParameter("newName"));
+        return success();
+      } else if(_request.getMethod() == "enable") {
+        pDevice->enable();
+        return success();
+      } else if(_request.getMethod() == "disable") {
+        pDevice->disable();
+        return success();
+      } else if(_request.getMethod() == "setRawValue") {
+        int value = strToIntDef(_request.getParameter("value"), -1);
+        if(value == -1) {
+          return failure("Invalid or missing parameter 'value'");
+        }
+        int parameterID = strToIntDef(_request.getParameter("parameterID"), -1);
+        if(parameterID == -1) {
+          return failure("Invalid or missing parameter 'parameterID'");
+        }
+        int size = strToIntDef(_request.getParameter("size"), -1);
+        if(size == -1) {
+          return failure("Invalid or missing parameter 'size'");
+        }
+
+        pDevice->setRawValue(value, parameterID, size);
+        return success();
+      } else {
+        throw std::runtime_error("Unhandled function");
+      }
+    } else {
+      if(ok) {
+        return success();
+      } else {
+        return failure(errorMessage);
+      }
+    }
+  } // jsonHandleRequest
+
+} // namespace dss
diff --git a/core/web/handler/devicerequesthandler.h b/core/web/handler/devicerequesthandler.h
new file mode 100644
index 0000000..051263c
--- /dev/null
+++ b/core/web/handler/devicerequesthandler.h
@@ -0,0 +1,37 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DEVICEREQUESTHANDLER_H_
+#define DEVICEREQUESTHANDLER_H_
+
+#include "deviceinterfacerequesthandler.h"
+
+namespace dss {
+
+  class DeviceRequestHandler : public DeviceInterfaceRequestHandler {
+  public:
+    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
+  }; // DeviceRequestHandler
+
+}
+
+#endif /* DEVICEREQUESTHANDLER_H_ */
diff --git a/core/web/handler/jsonhelper.cpp b/core/web/handler/jsonhelper.cpp
new file mode 100644
index 0000000..f7b5fe7
--- /dev/null
+++ b/core/web/handler/jsonhelper.cpp
@@ -0,0 +1,118 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "jsonhelper.h"
+
+#include "core/foreach.h"
+
+#include "core/web/json.h"
+
+#include "core/model/devicereference.h"
+#include "core/model/device.h"
+#include "core/model/set.h"
+#include "core/model/group.h"
+#include "core/model/zone.h"
+#include "core/model/apartment.h"
+
+namespace dss {
+
+  boost::shared_ptr<JSONObject> toJSON(const DeviceReference& _device) {
+    boost::shared_ptr<JSONObject> result(new JSONObject());
+    result->addProperty("id", _device.getDSID().toString());
+    result->addProperty("isSwitch", _device.hasSwitch());
+    result->addProperty("name", _device.getName());
+    result->addProperty("fid", _device.getFunctionID());
+    result->addProperty("circuitID", _device.getDevice().getDSMeterID());
+    result->addProperty("busID", _device.getDevice().getShortAddress());
+    result->addProperty("isPresent", _device.getDevice().isPresent());
+    result->addProperty("lastDiscovered", _device.getDevice().getLastDiscovered());
+    result->addProperty("firstSeen", _device.getDevice().getFirstSeen());
+    result->addProperty("on", _device.getDevice().isOn());
+    return result;
+  } // toJSON(DeviceReference)
+
+  boost::shared_ptr<JSONArrayBase> toJSON(const Set& _set) {
+    boost::shared_ptr<JSONArrayBase> result(new JSONArrayBase());
+
+    for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
+      const DeviceReference& d = _set.get(iDevice);
+      result->addElement("", toJSON(d));
+    }
+    return result;
+  } // toJSON(Set,Name)
+
+  boost::shared_ptr<JSONObject> toJSON(const Group& _group) {
+    boost::shared_ptr<JSONObject> result(new JSONObject());
+    result->addProperty("id", _group.getID());
+    result->addProperty("name", _group.getName());
+    result->addProperty("isPresent", _group.isPresent());
+
+    boost::shared_ptr<JSONArrayBase> devicesArr(new JSONArrayBase());
+    result->addElement("devices", devicesArr);
+    Set devices = _group.getDevices();
+    for(int iDevice = 0; iDevice < devices.length(); iDevice++) {
+      boost::shared_ptr<JSONObject> dev(new JSONObject());
+      dev->addProperty("id", devices[iDevice].getDSID().toString());
+    }
+    return result;
+  } // toJSON(Group)
+
+  boost::shared_ptr<JSONObject> toJSON(Zone& _zone, bool _includeDevices) {
+    boost::shared_ptr<JSONObject> result(new JSONObject());
+    result->addProperty("id", _zone.getID());
+    std::string name = _zone.getName();
+    if(name.empty()) {
+      name = std::string("Zone ") + intToString(_zone.getID());
+    }
+    result->addProperty("name", name);
+    result->addProperty("isPresent", _zone.isPresent());
+    if(_zone.getFirstZoneOnDSMeter() != -1) {
+      result->addProperty("firstZoneOnDSMeter", _zone.getFirstZoneOnDSMeter());
+    }
+
+    if(_includeDevices) {
+      result->addElement("devices", toJSON(_zone.getDevices()));
+      boost::shared_ptr<JSONArrayBase> groups(new JSONArrayBase());
+      result->addElement("groups", groups);
+      foreach(Group* pGroup, _zone.getGroups()) {
+        groups->addElement("", toJSON(*pGroup));
+      }
+    }
+
+    return result;
+  } // toJSON(Zone)
+
+  boost::shared_ptr<JSONObject> toJSON(Apartment& _apartment) {
+    boost::shared_ptr<JSONObject> result(new JSONObject());
+    boost::shared_ptr<JSONObject> apartment(new JSONObject());
+    result->addElement("apartment", apartment);
+    boost::shared_ptr<JSONArrayBase> zonesArr(new JSONArrayBase());
+    apartment->addElement("zones", zonesArr);
+
+    std::vector<Zone*>& zones = _apartment.getZones();
+    foreach(Zone* pZone, zones) {
+      zonesArr->addElement("", toJSON(*pZone));
+    }
+    return result;
+  } // toJSON(Apartment)
+
+}
diff --git a/core/web/handler/jsonhelper.h b/core/web/handler/jsonhelper.h
new file mode 100644
index 0000000..972c189
--- /dev/null
+++ b/core/web/handler/jsonhelper.h
@@ -0,0 +1,47 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#ifndef JSONHELPER_H_
+#define JSONHELPER_H_
+
+#include <boost/shared_ptr.hpp>
+
+namespace dss {
+
+  class JSONObject;
+  class JSONArrayBase;
+  class DeviceReference;
+  class Set;
+  class Group;
+  class Zone;
+  class Apartment;
+
+  boost::shared_ptr<JSONObject> toJSON(const DeviceReference& _device);
+  boost::shared_ptr<JSONArrayBase> toJSON(const Set& _set);
+  boost::shared_ptr<JSONObject> toJSON(const Group& _group);
+  boost::shared_ptr<JSONObject> toJSON(Zone& _zone, bool _includeDevices = true);
+  boost::shared_ptr<JSONObject> toJSON(Apartment& _apartment);
+
+} // namespace dss
+
+#endif /* JSONHELPER_H_ */
diff --git a/core/web/handler/setrequesthandler.cpp b/core/web/handler/setrequesthandler.cpp
new file mode 100644
index 0000000..fb0abc1
--- /dev/null
+++ b/core/web/handler/setrequesthandler.cpp
@@ -0,0 +1,138 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "setrequesthandler.h"
+
+#include "core/web/json.h"
+#include "core/model/apartment.h"
+#include "core/model/set.h"
+
+#include "core/dss.h"
+#include "core/setbuilder.h"
+
+#include "jsonhelper.h"
+
+namespace dss {
+
+  //=========================================== SetRequestHandler
+
+  boost::shared_ptr<JSONObject> SetRequestHandler::jsonHandleRequest(const RestfulRequest& _request, Session* _session) {
+    if(_request.getMethod() == "fromApartment") {
+      boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+      resultObj->addProperty("self", ".");
+      return success(resultObj);
+    } else {
+      std::string self = trim(_request.getParameter("self"));
+      if(self.empty()) {
+        return failure("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 failure("missing either zoneID or zoneName");
+        }
+
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("self", self + additionalPart);
+        return success(resultObj);
+      } 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 failure("missing either groupID or groupName");
+        }
+
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("self", self + additionalPart);
+        return success(resultObj);
+      } else if(_request.getMethod() == "byDSID") {
+        std::string additionalPart;
+        if(self != ".") {
+          additionalPart = ".";
+        }
+        if(!_request.getParameter("dsid").empty()) {
+          additionalPart += "dsid(" + _request.getParameter("dsid") + ")";
+        } else {
+          return failure("missing parameter dsid");
+        }
+
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("self", self + additionalPart);
+        return success(resultObj);
+      } else if(_request.getMethod() == "getDevices") {
+        SetBuilder builder(getDSS().getApartment());
+        Set set = builder.buildSet(self, NULL);
+        return success(toJSON(set));
+      } else if(_request.getMethod() == "add") {
+        std::string other = _request.getParameter("other");
+        if(other.empty()) {
+          return failure("missing parameter other");
+        }
+        std::string additionalPart;
+        if(self != ".") {
+          additionalPart = ".";
+        }
+        additionalPart += "add(" + other + ")";
+
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("self", self + additionalPart);
+        return success(resultObj);
+      } else if(_request.getMethod() == "subtract") {
+        std::string other = _request.getParameter("other");
+        if(other.empty()) {
+          return failure("missing parameter other");
+        }
+        std::string additionalPart;
+        if(self != ".") {
+          additionalPart = ".";
+        }
+        additionalPart += "subtract(" + other + ")";
+
+        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+        resultObj->addProperty("self", self + additionalPart);
+        return success(resultObj);
+      } 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");
+      }
+    }
+  } // handleRequest
+
+
+} // namespace dss
diff --git a/core/web/handler/setrequesthandler.h b/core/web/handler/setrequesthandler.h
new file mode 100644
index 0000000..13cf58b
--- /dev/null
+++ b/core/web/handler/setrequesthandler.h
@@ -0,0 +1,37 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef SETREQUESTHANDLER_H_
+#define SETREQUESTHANDLER_H_
+
+#include "deviceinterfacerequesthandler.h"
+
+namespace dss {
+
+  class SetRequestHandler : public DeviceInterfaceRequestHandler {
+  public:
+    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
+  }; // SetRequestHandler
+
+} // namespace dss
+
+#endif /* SETREQUESTHANDLER_H_ */
diff --git a/core/web/handler/zonerequesthandler.cpp b/core/web/handler/zonerequesthandler.cpp
new file mode 100644
index 0000000..91e517f
--- /dev/null
+++ b/core/web/handler/zonerequesthandler.cpp
@@ -0,0 +1,147 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "zonerequesthandler.h"
+
+#include "core/dss.h"
+
+#include "core/model/zone.h"
+#include "core/model/apartment.h"
+
+#include "core/web/json.h"
+
+namespace dss {
+
+
+  //=========================================== ZoneRequestHandler
+
+  boost::shared_ptr<JSONObject> ZoneRequestHandler::jsonHandleRequest(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);
+          }
+          boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+          resultObj->addProperty("scene", lastScene);
+          return success(resultObj);
+        } else if(_request.getMethod() == "getName") {
+          boost::shared_ptr<JSONObject> resultObj(new JSONObject());
+          resultObj->addProperty("name", pZone->getName());
+          return success(resultObj);
+        } else if(_request.getMethod() == "setName") {
+          pZone->setName(_request.getParameter("newName"));
+          return success();
+        } else {
+          throw std::runtime_error("Unhandled function");
+        }
+      }
+    }
+    if(!ok) {
+      return failure(errorMessage);
+    } else {
+      return success(); // TODO: check this, we shouldn't get here
+    }
+  } // handleRequest
+
+} // namespace dss
diff --git a/core/web/handler/zonerequesthandler.h b/core/web/handler/zonerequesthandler.h
new file mode 100644
index 0000000..7088971
--- /dev/null
+++ b/core/web/handler/zonerequesthandler.h
@@ -0,0 +1,37 @@
+/*
+    Copyright (c) 2010 digitalSTROM.org, Zurich, Switzerland
+
+    Author: Patrick Staehlin, futureLAB AG <pstaehlin at futurelab.ch>
+
+    This file is part of digitalSTROM Server.
+
+    digitalSTROM Server is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    digitalSTROM Server is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with digitalSTROM Server. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef ZONEREQUESTHANDLER_H_
+#define ZONEREQUESTHANDLER_H_
+
+#include "deviceinterfacerequesthandler.h"
+
+namespace dss {
+
+  class ZoneRequestHandler : public DeviceInterfaceRequestHandler {
+  public:
+    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
+  }; // ZoneRequestHandler
+
+}
+
+#endif /* ZONEREQUESTHANDLER_H_ */
diff --git a/core/web/webrequests.cpp b/core/web/webrequests.cpp
index 218b381..f50a8af 100644
--- a/core/web/webrequests.cpp
+++ b/core/web/webrequests.cpp
@@ -22,688 +22,13 @@
 
 #include "webrequests.h"
 
-#include <sstream>
-#include <vector>
-
 #include <boost/shared_ptr.hpp>
 
-#include "core/event.h"
-#include "core/ds485/ds485proxy.h"
-#include "core/ds485/framebucketcollector.h"
-#include "core/sim/dssim.h"
-#include "core/propertysystem.h"
-#include "core/foreach.h"
-
-#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/model/modelmaintenance.h"
-
-#include "core/setbuilder.h"
-#include "core/structuremanipulator.h"
-
 #include "json.h"
 
-
 namespace dss {
 
 
-  //=========================================== Globals
-
-  boost::shared_ptr<JSONObject> ToJSONValue(const DeviceReference& _device) {
-    boost::shared_ptr<JSONObject> result(new JSONObject());
-    result->addProperty("id", _device.getDSID().toString());
-    result->addProperty("isSwitch", _device.hasSwitch());
-    result->addProperty("name", _device.getName());
-    result->addProperty("fid", _device.getFunctionID());
-    result->addProperty("circuitID", _device.getDevice().getDSMeterID());
-    result->addProperty("busID", _device.getDevice().getShortAddress());
-    result->addProperty("isPresent", _device.getDevice().isPresent());
-    result->addProperty("lastDiscovered", _device.getDevice().getLastDiscovered());
-    result->addProperty("firstSeen", _device.getDevice().getFirstSeen());
-    result->addProperty("on", _device.getDevice().isOn());
-    return result;
-  } // toJSONValue(DeviceReference)
-
-  boost::shared_ptr<JSONArrayBase> ToJSONValue(const Set& _set) {
-    boost::shared_ptr<JSONArrayBase> result(new JSONArrayBase());
-
-    for(int iDevice = 0; iDevice < _set.length(); iDevice++) {
-      const DeviceReference& d = _set.get(iDevice);
-      result->addElement("", ToJSONValue(d));
-    }
-    return result;
-  } // toJSONValue(Set,Name)
-
-  boost::shared_ptr<JSONObject> ToJSONValue(const Group& _group) {
-    boost::shared_ptr<JSONObject> result(new JSONObject());
-    result->addProperty("id", _group.getID());
-    result->addProperty("name", _group.getName());
-    result->addProperty("isPresent", _group.isPresent());
-
-    boost::shared_ptr<JSONArrayBase> devicesArr(new JSONArrayBase());
-    result->addElement("devices", devicesArr);
-    Set devices = _group.getDevices();
-    for(int iDevice = 0; iDevice < devices.length(); iDevice++) {
-      boost::shared_ptr<JSONObject> dev(new JSONObject());
-      dev->addProperty("id", devices[iDevice].getDSID().toString());
-    }
-    return result;
-  } // toJSONValue(Group)
-
-  boost::shared_ptr<JSONObject> ToJSONValue(Zone& _zone, bool _includeDevices = true) {
-    boost::shared_ptr<JSONObject> result(new JSONObject());
-    result->addProperty("id", _zone.getID());
-    std::string name = _zone.getName();
-    if(name.empty()) {
-      name = std::string("Zone ") + intToString(_zone.getID());
-    }
-    result->addProperty("name", name);
-    result->addProperty("isPresent", _zone.isPresent());
-    if(_zone.getFirstZoneOnDSMeter() != -1) {
-      result->addProperty("firstZoneOnDSMeter", _zone.getFirstZoneOnDSMeter());
-    }
-
-    if(_includeDevices) {
-      result->addElement("devices", ToJSONValue(_zone.getDevices()));
-      boost::shared_ptr<JSONArrayBase> groups(new JSONArrayBase());
-      result->addElement("groups", groups);
-      foreach(Group* pGroup, _zone.getGroups()) {
-        groups->addElement("", ToJSONValue(*pGroup));
-      }
-    }
-
-    return result;
-  } // toJSONValue(Zone)
-
-  boost::shared_ptr<JSONObject> ToJSONValue(Apartment& _apartment) {
-    boost::shared_ptr<JSONObject> result(new JSONObject());
-    boost::shared_ptr<JSONObject> apartment(new JSONObject());
-    result->addElement("apartment", apartment);
-    boost::shared_ptr<JSONArrayBase> zonesArr(new JSONArrayBase());
-    apartment->addElement("zones", zonesArr);
-
-    vector<Zone*>& zones = _apartment.getZones();
-    foreach(Zone* pZone, zones) {
-      zonesArr->addElement("", ToJSONValue(*pZone));
-    }
-    return result;
-  } // 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
-
-
-  //=========================================== DeviceInterfaceRequestHandler
-
-  boost::shared_ptr<JSONObject> DeviceInterfaceRequestHandler::handleDeviceInterfaceRequest(const RestfulRequest& _request, IDeviceInterface* _interface) {
-    assert(_interface != NULL);
-    if(_request.getMethod() == "turnOn") {
-      _interface->turnOn();
-      return success();
-    } else if(_request.getMethod() == "turnOff") {
-      _interface->turnOff();
-      return success();
-    } else if(_request.getMethod() == "increaseValue") {
-      _interface->increaseValue();
-      return success();
-    } else if(_request.getMethod() == "decreaseValue") {
-      _interface->decreaseValue();
-      return success();
-    } else if(_request.getMethod() == "startDim") {
-      std::string direction = _request.getParameter("direction");
-      if(direction == "up") {
-        _interface->startDim(true);
-      } else {
-        _interface->startDim(false);
-      }
-      return success();
-    } else if(_request.getMethod() == "endDim") {
-      _interface->endDim();
-      return success();
-    } else if(_request.getMethod() == "setValue") {
-      std::string valueStr = _request.getParameter("value");
-      int value = strToIntDef(valueStr, -1);
-      if(value == -1) {
-        return failure("invalid or missing parameter value: '" + valueStr + "'");
-      } else {
-        _interface->setValue(value);
-      }
-      return success();
-    } else if(_request.getMethod() == "callScene") {
-      std::string sceneStr = _request.getParameter("sceneNr");
-      int sceneID = strToIntDef(sceneStr, -1);
-      if(sceneID != -1) {
-        _interface->callScene(sceneID);
-      } else {
-        return failure("invalid sceneNr: '" + sceneStr + "'");
-      }
-      return success();
-    } else if(_request.getMethod() == "saveScene") {
-      std::string sceneStr = _request.getParameter("sceneNr");
-      int sceneID = strToIntDef(sceneStr, -1);
-      if(sceneID != -1) {
-        _interface->saveScene(sceneID);
-      } else {
-        return failure("invalid sceneNr: '" + sceneStr + "'");
-      }
-      return success();
-    } else if(_request.getMethod() == "undoScene") {
-      std::string sceneStr = _request.getParameter("sceneNr");
-      int sceneID = strToIntDef(sceneStr, -1);
-      if(sceneID != -1) {
-        _interface->undoScene(sceneID);
-      } else {
-        return failure("invalid sceneNr: '" + sceneStr + "'");
-      }
-      return success();
-    } else if(_request.getMethod() == "getConsumption") {
-      boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-      resultObj->addProperty("consumption", _interface->getPowerConsumption());
-      return success(resultObj);
-    }
-    throw std::runtime_error("Unknown function");
-  } // handleRequest
-
-  bool DeviceInterfaceRequestHandler::isDeviceInterfaceCall(const RestfulRequest& _request) {
-    return _request.getMethod() == "turnOn"
-        || _request.getMethod() == "turnOff"
-        || _request.getMethod() == "increaseValue"
-        || _request.getMethod() == "decreaseValue"
-        || _request.getMethod() == "startDim"
-        || _request.getMethod() == "endDim"
-        || _request.getMethod() == "setValue"
-        || _request.getMethod() == "callScene"
-        || _request.getMethod() == "saveScene"
-        || _request.getMethod() == "undoScene"
-        || _request.getMethod() == "getConsumption";
-  } // isDeviceInterfaceCall
-
-
-  //=========================================== ApartmentRequestHandler
-  
-  boost::shared_ptr<JSONObject> ApartmentRequestHandler::jsonHandleRequest(const RestfulRequest& _request, Session* _session) {
-    std::string errorMessage;
-    if(_request.getMethod() == "getConsumption") {
-      int accumulatedConsumption = 0;
-      foreach(DSMeter* pDSMeter, getDSS().getApartment().getDSMeters()) {
-        accumulatedConsumption += pDSMeter->getPowerConsumption();
-      }
-      boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-      resultObj->addProperty("consumption", accumulatedConsumption);
-      return success(resultObj);
-    } 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) {
-          return failure("Could not find group with name '" + groupName + "'");
-        }
-      } else if(!groupIDString.empty()) {
-        try {
-          int groupID = strToIntDef(groupIDString, -1);
-          if(groupID != -1) {
-            Group& grp = getDSS().getApartment().getGroup(groupID);
-            interface = &grp;
-          } else {
-            return failure("Could not parse group id '" + groupIDString + "'");
-          }
-        } catch(std::runtime_error& e) {
-          return failure("Could not find group with ID '" + groupIDString + "'");
-        }
-      }
-      if(interface != NULL) {
-        interface = &getDSS().getApartment().getGroup(GroupIDBroadcast);
-        return success();
-      }
-      return failure("No interface");
-    } else {
-      if(_request.getMethod() == "getStructure") {
-        return success(ToJSONValue(getDSS().getApartment()));
-      } else if(_request.getMethod() == "getDevices") {
-        Set devices;
-        if(_request.getParameter("unassigned").empty()) {
-          devices = getDSS().getApartment().getDevices();
-        } else {
-          devices = GetUnassignedDevices();
-        }
-
-        return success(ToJSONValue(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") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        boost::shared_ptr<JSONArrayBase> circuits(new JSONArrayBase());
-
-        resultObj->addElement("circuits", circuits);
-        vector<DSMeter*>& dsMeters = getDSS().getApartment().getDSMeters();
-        foreach(DSMeter* dsMeter, dsMeters) {
-          boost::shared_ptr<JSONObject> circuit(new JSONObject());
-          circuits->addElement("", circuit);
-          circuit->addProperty("name", dsMeter->getName());
-          circuit->addProperty("dsid", dsMeter->getDSID().toString());
-          circuit->addProperty("busid", dsMeter->getBusID());
-          circuit->addProperty("hwVersion", dsMeter->getHardwareVersion());
-          circuit->addProperty("swVersion", dsMeter->getSoftwareVersion());
-          circuit->addProperty("hwName", dsMeter->getHardwareName());
-          circuit->addProperty("deviceType", dsMeter->getDeviceType());
-          circuit->addProperty("isPresent", dsMeter->isPresent());
-        }
-        return success(resultObj);
-      } else if(_request.getMethod() == "getName") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("name", getDSS().getApartment().getName());
-        return success(resultObj);
-      } else if(_request.getMethod() == "setName") {
-        getDSS().getApartment().setName(_request.getParameter("newName"));
-        return success();
-      } else if(_request.getMethod() == "rescan") {
-        std::vector<DSMeter*> mods = getDSS().getApartment().getDSMeters();
-        foreach(DSMeter* pDSMeter, mods) {
-          pDSMeter->setIsValid(false);
-        }
-        return success();
-      } else {
-        throw std::runtime_error("Unhandled function");
-      }
-    }
-  } // handleApartmentCall
-
-
-  //=========================================== ZoneRequestHandler
-
-  boost::shared_ptr<JSONObject> ZoneRequestHandler::jsonHandleRequest(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);
-          }
-          boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-          resultObj->addProperty("scene", lastScene);
-          return success(resultObj);
-        } else if(_request.getMethod() == "getName") {
-          boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-          resultObj->addProperty("name", pZone->getName());
-          return success(resultObj);
-        } else if(_request.getMethod() == "setName") {
-          pZone->setName(_request.getParameter("newName"));
-          return success();
-        } else {
-          throw std::runtime_error("Unhandled function");
-        }
-      }
-    }
-    if(!ok) {
-      return failure(errorMessage);
-    } else {
-      return success(); // TODO: check this, we shouldn't get here
-    }
-  } // handleRequest
-
-
-  //=========================================== DeviceRequestHandler
-
-  boost::shared_ptr<JSONObject> DeviceRequestHandler::jsonHandleRequest(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") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        int numGroups = pDevice->getGroupsCount();
-
-        boost::shared_ptr<JSONArrayBase> groups(new JSONArrayBase());
-        resultObj->addElement("groups", groups);
-        for(int iGroup = 0; iGroup < numGroups; iGroup++) {
-          try {
-            Group& group = pDevice->getGroupByIndex(iGroup);
-            boost::shared_ptr<JSONObject> groupObj(new JSONObject());
-            groups->addElement("", groupObj);
-
-            groupObj->addProperty("id", group.getID());
-            if(!group.getName().empty()) {
-              groupObj->addProperty("name", group.getName());
-            }
-          } catch(std::runtime_error&) {
-            Logger::getInstance()->log("DeviceRequestHandler: Group only present at device level");
-          }
-        }
-        return success(resultObj);
-      } else if(_request.getMethod() == "getState") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("isOn", pDevice->isOn());
-        return success(resultObj);
-      } else if(_request.getMethod() == "getName") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("name", pDevice->getName());
-        return success(resultObj);
-      } else if(_request.getMethod() == "setName") {
-        pDevice->setName(_request.getParameter("newName"));
-        return success();
-      } else if(_request.getMethod() == "enable") {
-        pDevice->enable();
-        return success();
-      } else if(_request.getMethod() == "disable") {
-        pDevice->disable();
-        return success();
-      } else if(_request.getMethod() == "setRawValue") {
-        int value = strToIntDef(_request.getParameter("value"), -1);
-        if(value == -1) {
-          return failure("Invalid or missing parameter 'value'");
-        }
-        int parameterID = strToIntDef(_request.getParameter("parameterID"), -1);
-        if(parameterID == -1) {
-          return failure("Invalid or missing parameter 'parameterID'");
-        }
-        int size = strToIntDef(_request.getParameter("size"), -1);
-        if(size == -1) {
-          return failure("Invalid or missing parameter 'size'");
-        }
-
-        pDevice->setRawValue(value, parameterID, size);
-        return success();
-      } else {
-        throw std::runtime_error("Unhandled function");
-      }
-    } else {
-      if(ok) {
-        return success();
-      } else {
-        return failure(errorMessage);
-      }
-    }
-  } // handleRequest
-
-
-  //=========================================== CircuitRequestHandler
-
-  boost::shared_ptr<JSONObject> CircuitRequestHandler::jsonHandleRequest(const RestfulRequest& _request, Session* _session) {
-    std::string idString = _request.getParameter("id");
-    if(idString.empty()) {
-      return failure("missing parameter id");
-    }
-    dsid_t dsid = dsid_t::fromString(idString);
-    if(dsid == NullDSID) {
-      return failure("could not parse dsid");
-    }
-    try {
-      DSMeter& dsMeter = getDSS().getApartment().getDSMeterByDSID(dsid);
-      if(_request.getMethod() == "getName") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("name", dsMeter.getName());
-        return success(resultObj);
-      } else if(_request.getMethod() == "setName") {
-        dsMeter.setName(_request.getParameter("newName"));
-        return success();
-      } else if(_request.getMethod() == "getEnergyBorder") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("orange", dsMeter.getEnergyLevelOrange());
-        resultObj->addProperty("red", dsMeter.getEnergyLevelRed());
-        return success(resultObj);
-      } else if(_request.getMethod() == "getConsumption") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("consumption", dsMeter.getPowerConsumption());
-        return success(resultObj);
-      } else if(_request.getMethod() == "getEnergyMeterValue") {
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("metervalue", dsMeter.getEnergyMeterValue());
-        return success(resultObj);
-      } else if(_request.getMethod() == "rescan") {
-        dsMeter.setIsValid(false);
-        return success();
-      } else {
-        throw std::runtime_error("Unhandled function");
-      }
-    } catch(std::runtime_error&) {
-      return failure("could not find dsMeter with given dsid");
-    }
-  } // handleRequest
-
-
-  //=========================================== SetRequestHandler
-
-  boost::shared_ptr<JSONObject> SetRequestHandler::jsonHandleRequest(const RestfulRequest& _request, Session* _session) {
-    if(_request.getMethod() == "fromApartment") {
-      boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-      resultObj->addProperty("self", ".");
-      return success(resultObj);
-    } else {
-      std::string self = trim(_request.getParameter("self"));
-      if(self.empty()) {
-        return failure("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 failure("missing either zoneID or zoneName");
-        }
-
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("self", self + additionalPart);
-        return success(resultObj);
-      } 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 failure("missing either groupID or groupName");
-        }
-
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("self", self + additionalPart);
-        return success(resultObj);
-      } else if(_request.getMethod() == "byDSID") {
-        std::string additionalPart;
-        if(self != ".") {
-          additionalPart = ".";
-        }
-        if(!_request.getParameter("dsid").empty()) {
-          additionalPart += "dsid(" + _request.getParameter("dsid") + ")";
-        } else {
-          return failure("missing parameter dsid");
-        }
-
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("self", self + additionalPart);
-        return success(resultObj);
-      } else if(_request.getMethod() == "getDevices") {
-        SetBuilder builder(getDSS().getApartment());
-        Set set = builder.buildSet(self, NULL);
-        return success(ToJSONValue(set));
-      } else if(_request.getMethod() == "add") {
-        std::string other = _request.getParameter("other");
-        if(other.empty()) {
-          return failure("missing parameter other");
-        }
-        std::string additionalPart;
-        if(self != ".") {
-          additionalPart = ".";
-        }
-        additionalPart += "add(" + other + ")";
-
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("self", self + additionalPart);
-        return success(resultObj);
-      } else if(_request.getMethod() == "subtract") {
-        std::string other = _request.getParameter("other");
-        if(other.empty()) {
-          return failure("missing parameter other");
-        }
-        std::string additionalPart;
-        if(self != ".") {
-          additionalPart = ".";
-        }
-        additionalPart += "subtract(" + other + ")";
-
-        boost::shared_ptr<JSONObject> resultObj(new JSONObject());
-        resultObj->addProperty("self", self + additionalPart);
-        return success(resultObj);
-      } 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");
-      }
-    }
-  } // handleRequest
-
-
-
   //================================================== WebServerRequestHandlerJSON
 
   std::string WebServerRequestHandlerJSON::handleRequest(const RestfulRequest& _request, Session* _session) {
diff --git a/core/web/webrequests.h b/core/web/webrequests.h
index 8663dd4..3257ee4 100644
--- a/core/web/webrequests.h
+++ b/core/web/webrequests.h
@@ -33,7 +33,6 @@
 
 namespace dss {
 
-  class IDeviceInterface;
   class JSONObject;
   class JSONElement;
   
@@ -59,38 +58,6 @@ namespace dss {
     virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session) = 0;
   }; // WebServerRequestHandlerJSON
 
-  class DeviceInterfaceRequestHandler : public WebServerRequestHandlerJSON {
-  public:
-    boost::shared_ptr<JSONObject> handleDeviceInterfaceRequest(const RestfulRequest& _request, IDeviceInterface* _interface);
-
-  protected:
-    bool isDeviceInterfaceCall(const RestfulRequest& _request);
-  };
-
-  class ApartmentRequestHandler : public DeviceInterfaceRequestHandler {
-  public:
-    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
-  };
-
-  class ZoneRequestHandler : public DeviceInterfaceRequestHandler {
-  public:
-    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
-  }; // ZoneRequestHandler
-
-  class DeviceRequestHandler : public DeviceInterfaceRequestHandler {
-  public:
-    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
-  }; // DeviceRequestHandler
-
-  class CircuitRequestHandler : public WebServerRequestHandlerJSON {
-  public:
-    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
-  }; // CircuitRequestHandler
-
-  class SetRequestHandler : public DeviceInterfaceRequestHandler {
-  public:
-    virtual boost::shared_ptr<JSONObject> jsonHandleRequest(const RestfulRequest& _request, Session* _session);
-  }; // SetRequestHandler
 
 
 }
diff --git a/core/web/webserver.cpp b/core/web/webserver.cpp
index a6364d5..2e2c24f 100644
--- a/core/web/webserver.cpp
+++ b/core/web/webserver.cpp
@@ -40,6 +40,11 @@
 #include "core/web/handler/structurerequesthandler.h"
 #include "core/web/handler/eventrequesthandler.h"
 #include "core/web/handler/propertyrequesthandler.h"
+#include "core/web/handler/apartmentrequesthandler.h"
+#include "core/web/handler/circuitrequesthandler.h"
+#include "core/web/handler/devicerequesthandler.h"
+#include "core/web/handler/setrequesthandler.h"
+#include "core/web/handler/zonerequesthandler.h"
 
 #include "webserverapi.h"
 #include "json.h"
diff --git a/examples/plugins/vlc_remote/vlc_remote.cpp b/examples/plugins/vlc_remote/vlc_remote.cpp
index 54700da..3e4a6dd 100644
--- a/examples/plugins/vlc_remote/vlc_remote.cpp
+++ b/examples/plugins/vlc_remote/vlc_remote.cpp
@@ -34,10 +34,10 @@ public:
                Poco::Net::StreamSocket sock(sa);
                Poco::Net::SocketStream str(sock);
 
-               std::cout << "before sending: " << _command << std::endl;
+               Logger::getInstance()->log("before sending: " + _command);
                str << _command << "\r\n" << std::flush;
                str << "logout\r\n" << std::flush;
-               std::cout << "done sending" << std::endl;
+               Logger::getInstance()->log("done sending");
 
                sock.close();
        } catch (Poco::Exception& exc) {
diff --git a/external/slaves/slim_slave.cpp b/external/slaves/slim_slave.cpp
index 9108318..12c4d07 100644
--- a/external/slaves/slim_slave.cpp
+++ b/external/slaves/slim_slave.cpp
@@ -36,6 +36,7 @@
 #include "../../core/sim/plugin/pluginmedia.h"
 #include "../../core/ds485const.h"
 #include "../../core/base.h"
+#include "../../core/logger.h"
 
 class DSIDSlimSlaveRemote : public DSIDMedia {
 private:
@@ -53,23 +54,33 @@ public:
     virtual ~DSIDSlimSlaveRemote() {}
 
     virtual void sendCommand(const std::string& _command) {
+      std::stringstream logMessage;
       try {
         if(m_PlayerMACHeader.empty()) {
-         std::cerr << "Parameter playerMAC not specified. NOT sending command " << _command << std::endl;
+          logMessage << "Parameter playerMAC not specified. NOT sending command " << _command;
+          Logger::getInstance()->log(logMessage.str());
+          logMessage.str("");
         }
         Poco::Net::SocketAddress sa(m_RemoteHost, m_RemotePort);
         Poco::Net::StreamSocket sock(sa);
         Poco::Net::SocketStream str(sock);
 
-        std::cout << "before sending: " << _command << std::endl;
+        logMessage << "before sending: " << _command;
+        Logger::getInstance()->log(logMessage.str());
+        logMessage.str("");
+
         str << m_PlayerMACHeader << " ";
         str << _command << "\n" << std::flush;
-        std::cout << m_PlayerMACHeader << " " << _command << std::endl;
-        std::cout << "done sending" << std::endl;
+
+        logMessage << m_PlayerMACHeader << " " << _command;
+        Logger::getInstance()->log(logMessage.str());
+        logMessage.str("");
+
+        Logger::getInstance()->log("done sending");
 
         sock.close();
        } catch (Poco::Exception& exc) {
-               std::cerr << "******** [slim_slave.so] exception caught: " << exc.displayText() << std::endl;
+	   Logger::getInstance()->log("[slim_slave.so] exception caught: " + exc.displayText(), lsError);
        }
     }
 
@@ -117,10 +128,10 @@ public:
       } else if(_name == "host") {
         m_RemoteHost = _value;
       } else if(_name == "playermac") {
-        std::cout << "config-param: " << _value << std::endl;
+        Logger::getInstance()->log("config-param: " +  _value);
         m_PlayerMACHeader = _value;
         dss::replaceAll(m_PlayerMACHeader, ":", "%3A");
-        std::cout << "after: " << m_PlayerMACHeader << std::endl;
+        Logger::getInstance()->log("after: " + m_PlayerMACHeader);
       } else if(_name == "volume") {
         m_DefaultVolume = dss::strToInt(_value);
       }
diff --git a/main.cpp b/main.cpp
index ea987b5..53d5281 100644
--- a/main.cpp
+++ b/main.cpp
@@ -63,7 +63,7 @@ pair<string, string> parse_prop(const string& s) {
 int main (int argc, char* argv[]) {
 
   if (!setlocale(LC_CTYPE, "")) {
-    cerr << "Can't set the specified locale! Check LANG, LC_CTYPE, LC_ALL." << endl;
+    dss::Logger::getInstance()->log("Can't set the specified locale! Check LANG, LC_CTYPE, LC_ALL.", lsError);
     return 1;
   }
 
diff --git a/unix/serialcom.cpp b/unix/serialcom.cpp
index 3af3ddf..7f1184d 100644
--- a/unix/serialcom.cpp
+++ b/unix/serialcom.cpp
@@ -23,6 +23,7 @@
 #include "serialcom.h"
 
 #include "../core/base.h"
+#include "../core/logger.h"
 
 #include <fcntl.h>
 #include <sys/ioctl.h>
@@ -56,7 +57,7 @@ namespace dss {
     }
     m_Handle = ::open(_serialPort, flags);
     if(m_Handle == -1) {
-      perror("serial");
+      Logger::getInstance()->log("serial", lsError);
       throw std::runtime_error(std::string("could not open port ") + m_PortDevName);
     }
 
@@ -82,22 +83,22 @@ namespace dss {
       throw std::runtime_error("Invalid value of speed");
     }
     if(cfsetispeed(&m_CommSettings, rate) == -1) {
-      perror("cfsetispeed");
+      Logger::getInstance()->log("cfsetispeed", lsError);
       throw std::runtime_error(std::string("could not set input speed of port ") + m_PortDevName);
     }
     if(cfsetospeed(&m_CommSettings, rate) == -1) {
-      perror("cfsetospeed");
+      Logger::getInstance()->log("cfsetospeed", lsError);
       throw std::runtime_error(std::string("could not set ouput speed of port ") + m_PortDevName);
     }
 
     // flush remaining characters
     if(tcflush(m_Handle, TCIOFLUSH) == -1) {
-      perror("tcflush");
+      Logger::getInstance()->log("tcflush", lsError);
       throw std::runtime_error(std::string("could not flush port ") + m_PortDevName);
     }
 
     if(tcsetattr(m_Handle, TCSANOW, &m_CommSettings) == -1) {
-      perror("tcsetattr");
+      Logger::getInstance()->log("tcsetattr", lsError);
       throw std::runtime_error(std::string("could not set attributes of port ") + m_PortDevName);
     }
     return true;
@@ -134,7 +135,7 @@ namespace dss {
         } else {
           close(m_Handle);
           m_Handle = -1;
-          perror("SerialCom::getCharTimeout read");
+          Logger::getInstance()->log("SerialCom::getCharTimeout read", lsError);
           throw std::runtime_error("read failed");
         }
       }
@@ -144,7 +145,7 @@ namespace dss {
     } else {
       close(m_Handle);
       m_Handle = -1;
-      perror("SerialCom::getCharTimeout() select");
+      Logger::getInstance()->log("SerialCom::getCharTimeout() select", lsError);
       throw std::runtime_error("select failed");
     }
     return false;
@@ -164,7 +165,7 @@ namespace dss {
     if(ret != 1) {
       close(m_Handle);
       m_Handle = -1;
-      perror("SerialCom::putChar");
+      Logger::getInstance()->log("SerialCom::putChar", lsError);
       throw std::runtime_error("error writing to serial port");
     }
   } // putChar
diff --git a/unix/systeminfo.cpp b/unix/systeminfo.cpp
index 75e1b54..66bb2b7 100644
--- a/unix/systeminfo.cpp
+++ b/unix/systeminfo.cpp
@@ -81,7 +81,7 @@ namespace dss {
 
     sock = socket(PF_INET, SOCK_STREAM, 0);
     if(sock < 0) {
-      perror("socket()");
+      Logger::getInstance()->log("socket()", lsError);
       return;
     }
 
@@ -89,7 +89,7 @@ namespace dss {
     ifc.ifc_len = sizeof(buf);
     ifc.ifc_buf = buf;
     if(ioctl(sock,  SIOCGIFCONF, &ifc) < 0) {
-      perror("ioctl(SIOCGIFCONF)");
+      Logger::getInstance()->log("ioctl(SIOCGIFCONF)", lsError);
       return;
     }
 
@@ -109,7 +109,7 @@ namespace dss {
       mac[sizeof(mac)-1]='\0';
 
       if(ioctl(sock, SIOCGIFNETMASK, pRequest) < 0) {
-        perror("ioctl(SIOCGIFNETMASK)");
+        Logger::getInstance()->log("ioctl(SIOCGIFNETMASK)", lsError);
         continue;
       }
       sa = &(pRequest->ifr_netmask);


hooks/post-receive
-- 
digitalSTROM Server


More information about the dss-commits mailing list