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

git version control dss-commits at forum.digitalstrom.org
Fri Dec 18 18:44:16 CET 2009


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  e66d9ae3b6cb709f6cc7aa3b49213bfa4adbad03 (commit)
       via  b94a3bc568f76c16615cd372f8b88e24ca94b94c (commit)
      from  e3061ebca87df0d068d141f64f58cea02da09d59 (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 e66d9ae3b6cb709f6cc7aa3b49213bfa4adbad03
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Dec 18 18:43:53 2009 +0100

    Use Poco::XML instead of xmlwrapper

commit b94a3bc568f76c16615cd372f8b88e24ca94b94c
Author: Patrick Stählin <pstaehlin at futurelab.ch>
Date:   Fri Dec 18 17:51:05 2009 +0100

    Added check that callScene actually does something

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

Changes:
diff --git a/core/dss.cpp b/core/dss.cpp
index 3378dd4..2ea5540 100644
--- a/core/dss.cpp
+++ b/core/dss.cpp
@@ -155,12 +155,12 @@ const char* WebrootDirectory = "data/webroot";
   bool DSS::initialize(const vector<std::string>& _properties) {
     m_State = ssCreatingSubsystems;
 
-    m_pDS485Interface = boost::shared_ptr<DS485Proxy>(new DS485Proxy(this));
-    m_Subsystems.push_back(dynamic_cast<DS485Proxy*>(m_pDS485Interface.get()));
-
     m_pApartment = boost::shared_ptr<Apartment>(new Apartment(this));
     m_Subsystems.push_back(m_pApartment.get());
 
+    m_pDS485Interface = boost::shared_ptr<DS485Proxy>(new DS485Proxy(this, m_pApartment.get()));
+    m_Subsystems.push_back(dynamic_cast<DS485Proxy*>(m_pDS485Interface.get()));
+
     m_pWebServer = boost::shared_ptr<WebServer>(new WebServer(this));
     m_Subsystems.push_back(m_pWebServer.get());
 
diff --git a/core/model.cpp b/core/model.cpp
index 796d97d..7aefe10 100644
--- a/core/model.cpp
+++ b/core/model.cpp
@@ -696,8 +696,7 @@ namespace dss {
   : Subsystem(_pDSS, "Apartment"),
     Thread("Apartment"),
     m_IsInitializing(true),
-    m_pPropertyNode(),
-    m_RescanBusIn(-1)
+    m_pPropertyNode()
   { } // ctor
 
   Apartment::~Apartment() {
@@ -917,7 +916,7 @@ namespace dss {
         if(scanModulator(mod)) {
           boost::shared_ptr<Event> modulatorReadyEvent(new Event("modulator_ready"));
           modulatorReadyEvent->setProperty("modulator", mod.getDSID().toString());
-          getDSS().getEventQueue().pushEvent(modulatorReadyEvent);
+          raiseEvent(modulatorReadyEvent);
         }
       } catch(DS485ApiError& e) {
         log(std::string("Exception caught while scanning modulator " + intToString(_modulatorBusID) + " : ") + e.what(), lsFatal);
@@ -952,9 +951,17 @@ namespace dss {
     requestFrame.getHeader().setDestination(0);
     requestFrame.setCommand(CommandRequest);
     requestFrame.getPayload().add<uint8_t>(FunctionModulatorGetDSID);
-    DSS::getInstance()->getDS485Interface().sendFrame(requestFrame);
+    if(DSS::hasInstance()) {
+      DSS::getInstance()->getDS485Interface().sendFrame(requestFrame);
+    }
   } // discoverDS485Devices
 
+  void Apartment::writeConfiguration() {
+    if(DSS::hasInstance()) {
+      writeConfigurationToXML(DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile"));
+    }
+  } // writeConfiguration
+
   void Apartment::handleModelEvents() {
     if(!m_ModelEvents.empty()) {
       ModelEvent& event = m_ModelEvents.front();
@@ -981,7 +988,7 @@ namespace dss {
         }
         break;
       case ModelEvent::etModelDirty:
-        writeConfigurationToXML(DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile"));
+        writeConfiguration();
         break;
       case ModelEvent::etDSLinkInterrupt:
         if(event.getParameterCount() != 3) {
@@ -1084,45 +1091,60 @@ namespace dss {
 
         {
           boost::shared_ptr<Event> readyEvent(new Event("model_ready"));
-          getDSS().getEventQueue().pushEvent(readyEvent);
+          raiseEvent(readyEvent);
         }
       }
     }
   } // handleModelEvents
 
-  void Apartment::execute() {
-    {
-      boost::shared_ptr<Event> runningEvent(new Event("running"));
-      getDSS().getEventQueue().pushEvent(runningEvent);
+  void Apartment::readConfiguration() {
+    if(DSS::hasInstance()) {
+      std::string configFileName = DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile");
+      if(!boost::filesystem::exists(configFileName)) {
+        log(std::string("Apartment::execute: Could not open config-file for apartment: '") + configFileName + "'", lsWarning);
+      } else {
+        readConfigurationFromXML(configFileName);
+      }
     }
+  } // readConfiguration
 
-    // load devices/modulators/etc. from a config-file
-    std::string configFileName = DSS::getInstance()->getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile");
-    if(!boost::filesystem::exists(configFileName)) {
-      log(std::string("Apartment::execute: Could not open config-file for apartment: '") + configFileName + "'", lsWarning);
-    } else {
-      readConfigurationFromXML(configFileName);
-    }
-    
-    {
-      boost::shared_ptr<Event> configReadEvent(new Event("config_read"));
-      getDSS().getEventQueue().pushEvent(configReadEvent);
+  void Apartment::raiseEvent(boost::shared_ptr<Event> _pEvent) {
+    if(DSS::hasInstance()) {
+      getDSS().getEventQueue().pushEvent(_pEvent);
     }
+  } // raiseEvent
+
+  void Apartment::waitForInterface() {
+    if(DSS::hasInstance()) {
+      DS485Interface& interface = DSS::getInstance()->getDS485Interface();
 
+      log("Apartment::execute: Waiting for interface to get ready", lsInfo);
 
-    DS485Interface& interface = DSS::getInstance()->getDS485Interface();
+      while(!interface.isReady() && !m_Terminated) {
+        sleepMS(1000);
+      }
+    }
 
-    log("Apartment::execute: Waiting for interface to get ready", lsInfo);
+    boost::shared_ptr<Event> readyEvent(new Event("interface_ready"));
+    raiseEvent(readyEvent);
+  } // waitForInterface
 
-    while(!interface.isReady() && !m_Terminated) {
-      sleepMS(1000);
+  void Apartment::execute() {
+    {
+      boost::shared_ptr<Event> runningEvent(new Event("running"));
+      raiseEvent(runningEvent);
     }
 
+    // load devices/modulators/etc. from a config-file
+    readConfiguration();
+
     {
-      boost::shared_ptr<Event> readyEvent(new Event("interface_ready"));
-      getDSS().getEventQueue().pushEvent(readyEvent);
+      boost::shared_ptr<Event> configReadEvent(new Event("config_read"));
+      raiseEvent(configReadEvent);
     }
 
+    waitForInterface();
+
     log("Apartment::execute: Interface is ready, enumerating model", lsInfo);
     discoverDS485Devices();
 
@@ -1697,7 +1719,7 @@ namespace dss {
       boost::shared_ptr<Event> readyEvent(new Event("new_device"));
       readyEvent->setProperty("device", dsid.toString());
       readyEvent->setProperty("zone", intToString(_zoneID));
-      getDSS().getEventQueue().pushEvent(readyEvent);
+      raiseEvent(readyEvent);
     }
   } // onAddDevice
 
@@ -1744,7 +1766,7 @@ namespace dss {
             priorityString = "high";
           }
           evt->setProperty("priority", priorityString);
-          getDSS().getEventQueue().pushEvent(evt);
+          raiseEvent(evt);
         } else {
           log("unknown interrupt mode '" + mode + "'", lsError);
         }
diff --git a/core/model.h b/core/model.h
index cc14fb7..4a053fc 100644
--- a/core/model.h
+++ b/core/model.h
@@ -55,6 +55,7 @@ namespace dss {
   class Group;
   class Modulator;
   class PropertyNode;
+  class Event;
   typedef boost::shared_ptr<PropertyNode> PropertyNodePtr;
 
   class PhysicalModelItem {
@@ -802,7 +803,7 @@ namespace dss {
                     public DeviceContainer,
                     public Subsystem,
                     public LockableObject,
-                    private Thread
+                    public Thread
   {
   private:
     std::vector<Zone*> m_Zones;
@@ -815,20 +816,20 @@ namespace dss {
     boost::ptr_vector<ModelEvent> m_ModelEvents;
     Mutex m_ModelEventsMutex;
     SyncEvent m_NewModelEvent;
-    int m_RescanBusIn;
   private:
     void loadDevices(Poco::XML::Node* _node);
     void loadModulators(Poco::XML::Node* _node);
     void loadZones(Poco::XML::Node* _node);
 
     void addDefaultGroupsToZone(Zone& _zone);
-    /** Starts the event-processing */
-    virtual void execute();
     void handleModelEvents();
     void modulatorReady(int _modulatorBusID);
     void setPowerConsumption(int _modulatorBusID, unsigned long _value);
     void setEnergyMeterValue(int _modulatorBusID, unsigned long _value);
     void discoverDS485Devices();
+
+    void raiseEvent(boost::shared_ptr<Event> _pEvent);
+    void waitForInterface();
   protected:
     virtual void doStart();
   public:
@@ -842,8 +843,10 @@ namespace dss {
 
     /** Loads the datamodel and marks the contained items as "stale" */
     void readConfigurationFromXML(const std::string& _fileName);
+    void readConfiguration();
 
     void writeConfigurationToXML(const std::string& _fileName);
+    void writeConfiguration();
 
     /** Returns a reference to the device with the DSID \a _dsid */
     Device& getDeviceByDSID(const dsid_t _dsid) const;
@@ -920,6 +923,8 @@ namespace dss {
      *  Adds the device to the model. */
     void onAddDevice(const int _modID, const int _zoneID, const int _devID, const int _functionID);
     void onDSLinkInterrupt(const int _modID, const int _devID, const int _priority);
+    /** Starts the event-processing */
+    virtual void execute();
   }; // Apartment
 
   //============================================= Helper definitions
diff --git a/core/sim/dsidsim.h b/core/sim/dsidsim.h
index e183731..f971ee8 100644
--- a/core/sim/dsidsim.h
+++ b/core/sim/dsidsim.h
@@ -24,6 +24,8 @@
 
 #include "dssim.h"
 
+#include "core/base.h"
+
 namespace dss {
 
   class DSIDSim : public DSIDInterface {
diff --git a/core/sim/dssim.cpp b/core/sim/dssim.cpp
index de4a8c2..ad68199 100644
--- a/core/sim/dssim.cpp
+++ b/core/sim/dssim.cpp
@@ -41,6 +41,25 @@
 #include "dsid_js.h"
 #include "dsid_plugin.h"
 
+#include <Poco/DOM/Document.h>
+#include <Poco/DOM/Element.h>
+#include <Poco/DOM/Node.h>
+#include <Poco/DOM/Attr.h>
+#include <Poco/DOM/Text.h>
+#include <Poco/DOM/AutoPtr.h>
+#include <Poco/DOM/DOMParser.h>
+#include <Poco/SAX/InputSource.h>
+#include <Poco/SAX/SAXException.h>
+
+using Poco::XML::Document;
+using Poco::XML::Element;
+using Poco::XML::Attr;
+using Poco::XML::Text;
+using Poco::XML::ProcessingInstruction;
+using Poco::XML::AutoPtr;
+using Poco::XML::DOMParser;
+using Poco::XML::InputSource;
+using Poco::XML::Node;
 
 namespace fs = boost::filesystem;
 
@@ -121,31 +140,37 @@ namespace dss {
 
   void DSSim::loadFromConfig() {
     const int theConfigFileVersion = 1;
-    std::string filename = getConfigPropertyBasePath() + "configfile";
-    XMLDocumentFileReader reader(getDSS().getPropertySystem().getStringValue(filename));
-    XMLNode rootNode = reader.getDocument().getRootNode();
-
-    if(rootNode.getName() == "simulation") {
-      std::string fileVersionStr = rootNode.getAttributes()["version"];
-      if(strToIntDef(fileVersionStr, -1) == theConfigFileVersion) {
-        XMLNodeList& modulators = rootNode.getChildren();
-        foreach(XMLNode& node, modulators) {
-          if(node.getName() == "modulator") {
-            DSModulatorSim* modulator = NULL;
-            try {
-              modulator = new DSModulatorSim(this);
-              modulator->initializeFromNode(node);
-              m_Modulators.push_back(modulator);
-            } catch(std::runtime_error&) {
-              delete modulator;
+    std::string filename = getDSS().getPropertySystem().getStringValue(getConfigPropertyBasePath() + "configfile");
+    std::ifstream inFile(filename.c_str());
+
+    try {
+      InputSource input(inFile);
+      DOMParser parser;
+      AutoPtr<Document> pDoc = parser.parse(&input);
+      Element* rootNode = pDoc->documentElement();
+
+      if(rootNode->localName() == "simulation") {
+        if(rootNode->hasAttribute("version") && (strToInt(rootNode->getAttribute("version")) == theConfigFileVersion)) {
+          Node* curNode = rootNode->firstChild();
+          while(curNode != NULL) {
+            if(curNode->localName() == "modulator") {
+              DSModulatorSim* modulator = NULL;
+              try {
+                modulator = new DSModulatorSim(this);
+                modulator->initializeFromNode(curNode);
+                m_Modulators.push_back(modulator);
+              } catch(std::runtime_error&) {
+                delete modulator;
+              }
             }
+            curNode = curNode->nextSibling();
           }
         }
       } else {
-        log("Version mismatch, or missing version attribute. Expected ''" + intToString(theConfigFileVersion) + "'" + fileVersionStr + "' ");
+        log(filename + " must have a root-node named 'simulation'", lsFatal);
       }
-    } else {
-      log(filename + " must have a root-node named 'simulation'", lsFatal);
+    } catch(Poco::XML::SAXParseException& e) {
+      log("Error parsing file: " + filename + ". message: " + e.message());
     }
   } // loadFromConfig
 
@@ -256,75 +281,77 @@ namespace dss {
     m_pSimulation->log(_message, _severity);
   } // log
 
-  bool DSModulatorSim::initializeFromNode(XMLNode& _node) {
-    HashMapConstStringString& attrs = _node.getAttributes();
-    if(attrs["busid"].size() != 0) {
-      m_ID = strToIntDef(attrs["busid"], 70);
+  bool DSModulatorSim::initializeFromNode(Node* _node) {
+    Element* elem = dynamic_cast<Element*>(_node);
+    if(elem == NULL) {
+      return false;
     }
-    if(attrs["dsid"].size() != 0) {
-      m_ModulatorDSID = dsid_t::fromString(attrs["dsid"]);
+    if(elem->hasAttribute("busid")) {
+      m_ID = strToIntDef(elem->getAttribute("busid"), 70);
+    }
+    if(elem->hasAttribute("dsid")) {
+      m_ModulatorDSID = dsid_t::fromString(elem->getAttribute("dsid"));
       m_ModulatorDSID.upper = (m_ModulatorDSID.upper & 0x000000000000000Fll) | DSIDHeader;
       m_ModulatorDSID.lower = (m_ModulatorDSID.lower & 0x002FFFFF) | SimulationPrefix;
     }
-    m_EnergyLevelOrange = strToIntDef(attrs["orange"], m_EnergyLevelOrange);
-    m_EnergyLevelRed = strToIntDef(attrs["red"], m_EnergyLevelRed);
-    try {
-      XMLNode& nameNode = _node.getChildByName("name");
-      if(!nameNode.getChildren().empty()) {
-        m_Name = nameNode.getChildren()[0].getContent();
-      }
-    } catch(XMLException&) {
+    if(elem->hasAttribute("orange")) {
+      m_EnergyLevelOrange = strToIntDef(elem->getAttribute("orange"), m_EnergyLevelOrange);
+    }
+    if(elem->hasAttribute("red")) {
+      m_EnergyLevelRed = strToIntDef(elem->getAttribute("red"), m_EnergyLevelRed);
+    }
+    Element* nameElem = elem->getChildElement("name");
+    if(nameElem != NULL && nameElem->hasChildNodes()) {
+      m_Name = nameElem->firstChild()->nodeValue();
     }
 
-    XMLNodeList& nodes = _node.getChildren();
-    loadDevices(nodes, 0);
-    loadGroups(nodes, 0);
-    loadZones(nodes);
+    loadDevices(_node, 0);
+    loadGroups(_node, 0);
+    loadZones(_node);
     return true;
   } // initializeFromNode
 
-  void DSModulatorSim::loadDevices(XMLNodeList& _nodes, const int _zoneID) {
-    for(XMLNodeList::iterator iNode = _nodes.begin(), e = _nodes.end();
-        iNode != e; ++iNode)
-    {
-      if(iNode->getName() == "device") {
-        HashMapConstStringString& attrs = iNode->getAttributes();
+  void DSModulatorSim::loadDevices(Node* _node, const int _zoneID) {
+    Node* curNode = _node->firstChild();
+    while(curNode != NULL) {
+      Element* elem = dynamic_cast<Element*>(curNode);
+      if(curNode->localName() == "device" && elem != NULL) {
         dsid_t dsid = NullDSID;
         int busid = -1;
-        if(!attrs["dsid"].empty()) {
-          dsid = dsid_t::fromString(attrs["dsid"]);
+        if(elem->hasAttribute("dsid")) {
+          dsid = dsid_t::fromString(elem->getAttribute("dsid"));
           dsid.upper = (dsid.upper & 0x000000000000000Fll) | DSIDHeader;
           dsid.lower = (dsid.lower & 0x002FFFFF) | SimulationPrefix;
         }
-        if(!attrs["busid"].empty()) {
-          busid = strToInt(attrs["busid"]);
+        if(elem->hasAttribute("busid")) {
+          busid = strToInt(elem->getAttribute("busid"));
         }
         if((dsid == NullDSID) || (busid == -1)) {
           log("missing dsid or busid of device");
           continue;
         }
         std::string type = "standard.simple";
-        if(!attrs["type"].empty()) {
-          type = attrs["type"];
+        if(elem->hasAttribute("type")) {
+          type = elem->getAttribute("type");
         }
 
         DSIDInterface* newDSID = m_pSimulation->getDSIDFactory().createDSID(type, dsid, busid, *this);
-        try {
-          foreach(XMLNode& iParam, iNode->getChildren()) {
-            if(iParam.getName() == "parameter") {
-              std::string paramName = iParam.getAttributes()["name"];
-              std::string paramValue = iParam.getChildren()[0].getContent();
-              if(paramName.empty()) {
-                log("Missing attribute name of parameter node");
-                continue;
+        Node* childNode = curNode->firstChild();
+        while(childNode != NULL) {
+          if(childNode->localName() == "parameter") {
+            Element* childElem = dynamic_cast<Element*>(childNode);
+            if(childElem != NULL) {
+              if(childElem->hasAttribute("name") && childElem->hasChildNodes()) {
+                std::string paramName = childElem->getAttribute("name");
+                std::string paramValue = childElem->firstChild()->getNodeValue();
+                log("LoadDevices:   Found parameter '" + paramName + "' with value '" + paramValue + "'");
+                newDSID->setConfigParameter(paramName, paramValue);
               }
-              log("LoadDevices:   Found parameter '" + paramName + "' with value '" + paramValue + "'");
-              newDSID->setConfigParameter(paramName, paramValue);
-            } else if(iParam.getName() == "name") {
-              m_DeviceNames[busid] = iParam.getChildren()[0].getContent();
             }
+          } else if(childNode->localName() == "name" && childNode->hasChildNodes()) {
+            m_DeviceNames[busid] = childNode->firstChild()->nodeValue();
           }
-        } catch(std::runtime_error&) {
+          childNode = childNode->nextSibling();
         }
         if(newDSID != NULL) {
           m_SimulatedDevices.push_back(newDSID);
@@ -337,9 +364,11 @@ namespace dss {
           DSIDSimSwitch* sw = dynamic_cast<DSIDSimSwitch*>(newDSID);
           if(sw != NULL) {
             log("LoadDevices:   it's a switch");
-            if(attrs["bell"] == "true") {
-              sw->setIsBell(true);
-              log("LoadDevices:   switch is bell");
+            if(elem->hasAttribute("bell")) {
+              sw->setIsBell(elem->getAttribute("bell") == "true");
+              if(sw->isBell()) {
+                log("LoadDevices:   switch is bell");
+              }
             }
           }
 
@@ -349,35 +378,37 @@ namespace dss {
           log("LoadDevices: could not create instance for type \"" + type + "\"");
         }
       }
+      curNode = curNode->nextSibling();
     }
   } // loadDevices
 
-  void DSModulatorSim::loadGroups(XMLNodeList& _nodes, const int _zoneID) {
-    for(XMLNodeList::iterator iNode = _nodes.begin(), e = _nodes.end();
-        iNode != e; ++iNode)
-    {
-      if(iNode->getName() == "group") {
-        HashMapConstStringString& attrs = iNode->getAttributes();
-        if(!attrs["id"].empty()) {
-          int groupID = strToIntDef(attrs["id"], -1);
-          XMLNodeList& children = iNode->getChildren();
-          for(XMLNodeList::iterator iChildNode = children.begin(), e = children.end();
-              iChildNode != e; ++iChildNode)
-          {
-            if(iChildNode->getName() == "device") {
-              attrs = iChildNode->getAttributes();
-              if(!attrs["busid"].empty()) {
-                unsigned long busID = strToUInt(attrs["busid"]);
-                DSIDInterface& dev = lookupDevice(busID);
-                addDeviceToGroup(&dev, groupID);
-                log("LoadGroups: Adding device " + attrs["busid"] + " to group " + intToString(groupID) + " in zone " + intToString(_zoneID));
+  void DSModulatorSim::loadGroups(Node* _node, const int _zoneID) {
+    Node* curNode = _node->firstChild();
+    while(curNode != NULL) {
+      if(curNode->localName() == "group") {
+        Element* elem = dynamic_cast<Element*>(curNode);
+        if(elem != NULL) {
+          if(elem->hasAttribute("id")) {
+            int groupID = strToIntDef(elem->getAttribute("id"), -1);
+            Node* childNode = curNode->firstChild();
+            while(childNode != NULL) {
+              if(childNode->localName() == "device") {
+                Element* childElem = dynamic_cast<Element*>(childNode);
+                if(childElem->hasAttribute("busid")) {
+                  unsigned long busID = strToUInt(childElem->getAttribute("busid"));
+                  DSIDInterface& dev = lookupDevice(busID);
+                  addDeviceToGroup(&dev, groupID);
+                  log("LoadGroups: Adding device " + intToString(busID) + " to group " + intToString(groupID) + " in zone " + intToString(_zoneID));
+                }
               }
+              childNode = childNode->nextSibling();
             }
+          } else {
+            log("LoadGroups: Could not find attribute id of group, skipping entry", lsError);
           }
-        } else {
-          log("LoadGroups: Could not find attribute id of group, skipping entry", lsError);
         }
       }
+      curNode = curNode->nextSibling();
     }
   } // loadGroups
 
@@ -386,24 +417,24 @@ namespace dss {
     m_GroupsPerDevice[_device->getShortAddress()].push_back(_groupID);
   } // addDeviceToGroup
 
-  void DSModulatorSim::loadZones(XMLNodeList& _nodes) {
-    for(XMLNodeList::iterator iNode = _nodes.begin(), e = _nodes.end();
-        iNode != e; ++iNode)
-    {
-      if(iNode->getName() == "zone") {
-        HashMapConstStringString& attrs = iNode->getAttributes();
+  void DSModulatorSim::loadZones(Node* _node) {
+    Node* curNode = _node->firstChild();
+    while(curNode != NULL) {
+      if(curNode->localName() == "zone") {
+        Element* elem = dynamic_cast<Element*>(curNode);
         int zoneID = -1;
-        if(!attrs["id"].empty()) {
-          zoneID = strToIntDef(attrs["id"], -1);
+        if(elem != NULL && elem->hasAttribute("id")) {
+          zoneID = strToIntDef(elem->getAttribute("id"), -1);
         }
         if(zoneID != -1) {
           log("LoadZones: found zone (" + intToString(zoneID) + ")");
-          loadDevices(iNode->getChildren(), zoneID);
-          loadGroups(iNode->getChildren(), zoneID);
+          loadDevices(curNode, zoneID);
+          loadGroups(curNode, zoneID);
         } else {
           log("LoadZones: could not find/parse id for zone");
         }
       }
+      curNode = curNode->nextSibling();
     }
   } // loadZones
 
diff --git a/core/sim/dssim.h b/core/sim/dssim.h
index ad3fc84..a4b9a11 100644
--- a/core/sim/dssim.h
+++ b/core/sim/dssim.h
@@ -25,7 +25,6 @@
 #include "core/ds485types.h"
 #include "core/ds485const.h"
 #include "unix/ds485.h"
-#include "core/xmlwrapper.h"
 #include "core/subsystem.h"
 
 #include <map>
@@ -33,6 +32,12 @@
 
 #include <boost/ptr_container/ptr_vector.hpp>
 
+namespace Poco {
+  namespace XML {
+    class Node;
+  }
+}
+
 namespace dss {
   class DS485Frame;
   class DSIDInterface;
@@ -107,9 +112,9 @@ namespace dss {
     std::string m_Name;
   private:
     void addDeviceToGroup(DSIDInterface* _device, int _groupID);
-    void loadDevices(XMLNodeList& _nodes, const int _zoneID);
-    void loadGroups(XMLNodeList& _nodes, const int _zoneID);
-    void loadZones(XMLNodeList& _nodes);
+    void loadDevices(Poco::XML::Node* _node, const int _zoneID);
+    void loadGroups(Poco::XML::Node* _node, const int _zoneID);
+    void loadZones(Poco::XML::Node* _node);
 
     DSIDInterface& lookupDevice(const devid_t _id);
     boost::shared_ptr<DS485CommandFrame> createResponse(DS485CommandFrame& _request, uint8_t _functionID) const;
@@ -136,7 +141,7 @@ namespace dss {
     DSModulatorSim(DSSim* _pSimulator);
     virtual ~DSModulatorSim() {}
 
-    bool initializeFromNode(XMLNode& _node);
+    bool initializeFromNode(Poco::XML::Node* _node);
 
     int getID() const;
 
diff --git a/tests/eventtests.cpp b/tests/eventtests.cpp
index 52eb49e..b11e485 100644
--- a/tests/eventtests.cpp
+++ b/tests/eventtests.cpp
@@ -211,13 +211,13 @@ BOOST_AUTO_TEST_CASE(testDS485Events) {
   queue.setEventRunner(&runner);
   runner.setEventQueue(&queue);
 
-  DSModulatorSim modSim(NULL);
-  DS485Proxy proxy(NULL);
-  proxy.initialize();
-
   Apartment apt(NULL);
   apt.initialize();
 
+  DSModulatorSim modSim(NULL);
+  DS485Proxy proxy(NULL, &apt);
+  proxy.initialize();
+
   Device& dev1 = apt.allocateDevice(dsid_t(0,1));
   dev1.setName("dev1");
   dev1.setShortAddress(1);
diff --git a/tests/modeltests.cpp b/tests/modeltests.cpp
index c7ef87d..5d9a389 100644
--- a/tests/modeltests.cpp
+++ b/tests/modeltests.cpp
@@ -26,11 +26,74 @@
 #include "core/model.h"
 #include "core/setbuilder.h"
 #include "core/ds485const.h"
+#include "unix/ds485proxy.h"
+#include "core/sim/dssim.h"
+#include "core/dss.h"
 
 using namespace dss;
 
 BOOST_AUTO_TEST_SUITE(Model)
 
+BOOST_AUTO_TEST_CASE(testApartmentAllocateDeviceReturnsTheSameDeviceForDSID) {
+  Apartment apt(NULL);
+  apt.initialize();
+
+  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+  dev1.setShortAddress(1);
+  dev1.setName("dev1");
+  dev1.setModulatorID(1);
+
+  Device& dev2 = apt.allocateDevice(dsid_t(0,1));
+  BOOST_CHECK_EQUAL(dev1.getShortAddress(), dev2.getShortAddress());
+  BOOST_CHECK_EQUAL(dev1.getName(), dev2.getName());
+  BOOST_CHECK_EQUAL(dev1.getModulatorID(), dev2.getModulatorID());
+} // testApartmentAllocateDeviceReturnsTheSameDeviceForDSID
+
+BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByShortAddress) {
+  Apartment apt(NULL);
+  apt.initialize();
+
+  Modulator& mod = apt.allocateModulator(dsid_t(0,2));
+  mod.setBusID(1);
+
+  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+  dev1.setShortAddress(1);
+  dev1.setName("dev1");
+  dev1.setModulatorID(1);
+
+  BOOST_CHECK_EQUAL("dev1", apt.getDeviceByShortAddress(mod, 1).getName());
+} // testApartmentGetDeviceByShortAddress
+
+BOOST_AUTO_TEST_CASE(testApartmentGetDeviceByName) {
+  Apartment apt(NULL);
+  apt.initialize();
+
+  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+  dev1.setName("dev1");
+
+  BOOST_CHECK_EQUAL("dev1", apt.getDeviceByName("dev1").getName());
+} // testApartmentGetDeviceByName
+
+BOOST_AUTO_TEST_CASE(testApartmentGetModulatorByName) {
+  Apartment apt(NULL);
+  apt.initialize();
+
+  Modulator& mod = apt.allocateModulator(dsid_t(0,2));
+  mod.setName("mod1");
+
+  BOOST_CHECK_EQUAL("mod1", apt.getModulator("mod1").getName());
+} // testApartmentGetModulatorByName
+
+BOOST_AUTO_TEST_CASE(testApartmentGetModulatorByBusID) {
+  Apartment apt(NULL);
+  apt.initialize();
+
+  Modulator& mod = apt.allocateModulator(dsid_t(0,2));
+  mod.setBusID(1);
+
+  BOOST_CHECK_EQUAL(1, apt.getModulatorByBusID(1).getBusID());
+} // testApartmentGetModulatorByBusID
+
 BOOST_AUTO_TEST_CASE(testZoneMoving) {
   Apartment apt(NULL);
   apt.initialize();
@@ -341,4 +404,46 @@ BOOST_AUTO_TEST_CASE(testRemoval) {
   }
 } // testRemoval
 
+BOOST_AUTO_TEST_CASE(testCallScenePropagation) {
+  Apartment apt(NULL);
+  apt.initialize();
+
+  DSModulatorSim modSim(NULL);
+  DS485Proxy proxy(NULL, &apt);
+  proxy.setInitializeDS485Controller(false);
+  proxy.initialize();
+
+  proxy.start();
+  apt.start();
+  while(apt.isInitializing()) {
+    sleepMS(100);
+  }
+
+  Modulator& mod = apt.allocateModulator(dsid_t(0,3));
+  mod.setBusID(76);
+  Device& dev1 = apt.allocateDevice(dsid_t(0,1));
+  dev1.setName("dev1");
+  dev1.setShortAddress(1);
+  dev1.setModulatorID(76);
+  DeviceReference devRef1(dev1, apt);
+  mod.addDevice(devRef1);
+  Device& dev2 = apt.allocateDevice(dsid_t(0,2));
+  dev2.setName("dev2");
+  dev2.setShortAddress(2);
+  dev2.setModulatorID(76);
+
+//  dev1.callScene(Scene1);
+  proxy.sendCommand(cmdCallScene, dev1, Scene1);
+  sleepMS(500);
+  BOOST_CHECK_EQUAL(Scene1, dev1.getLastCalledScene());
+  proxy.sendCommand(cmdCallScene, apt.getZone(0), apt.getGroup(0), Scene2);
+  sleepMS(500);
+  BOOST_CHECK_EQUAL(Scene2, dev1.getLastCalledScene());
+  BOOST_CHECK_EQUAL(Scene2, dev2.getLastCalledScene());
+  proxy.terminate();
+  apt.terminate();
+  sleepMS(1500);
+  DSS::teardown();
+} // testCallScenePropagation
+
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/unix/ds485proxy.cpp b/unix/ds485proxy.cpp
index 95af480..755d3d5 100644
--- a/unix/ds485proxy.cpp
+++ b/unix/ds485proxy.cpp
@@ -223,10 +223,13 @@ namespace dss {
     return FittingResultPerModulator(fittingGroups, singleDevices);
   } // bestFit
 
-  DS485Proxy::DS485Proxy(DSS* _pDSS)
+  DS485Proxy::DS485Proxy(DSS* _pDSS, Apartment* _pApartment)
   : Thread("DS485Proxy"),
-    Subsystem(_pDSS, "DS485Proxy")
+    Subsystem(_pDSS, "DS485Proxy"),
+    m_pApartment(_pApartment),
+    m_InitializeDS485Controller(true)
   {
+    assert(_pApartment != NULL);
     if(_pDSS != NULL) {
       _pDSS->getPropertySystem().createProperty(getConfigPropertyBasePath() + "rs485devicename")
             ->linkToProxy(PropertyProxyMemberFunction<DS485Controller, std::string>(m_DS485Controller, &DS485Controller::getRS485DeviceName, &DS485Controller::setRS485DeviceName));
@@ -1166,11 +1169,13 @@ namespace dss {
   }
 
   void DS485Proxy::doStart() {
-    try {
-      m_DS485Controller.setDSID(dsid_t::fromString(getDSS().getPropertySystem().getStringValue(getConfigPropertyBasePath() + "dsid")));
-      m_DS485Controller.run();
-    } catch (const std::runtime_error& _ex) {
-    	log(std::string("Caught exception while starting DS485Controller: ") + _ex.what(), lsFatal);
+    if(m_InitializeDS485Controller) {
+      try {
+        m_DS485Controller.setDSID(dsid_t::fromString(getDSS().getPropertySystem().getStringValue(getConfigPropertyBasePath() + "dsid")));
+        m_DS485Controller.run();
+      } catch (const std::runtime_error& _ex) {
+        log(std::string("Caught exception while starting DS485Controller: ") + _ex.what(), lsFatal);
+      }
     }
     // call Thread::run()
     run();
@@ -1323,6 +1328,10 @@ namespace dss {
     return "";
   } // functionIDToString
 
+  void DS485Proxy::raiseModelEvent(ModelEvent* _pEvent) {
+    m_pApartment->addModelEvent(_pEvent);
+  } // raiseModelEvent
+
   void DS485Proxy::execute() {
     signalEvent();
     
@@ -1333,7 +1342,7 @@ namespace dss {
       if(currentState != lastState) {
         if((currentState == csSlave) || (currentState == csMaster)) {
           ModelEvent* pEvent = new ModelEvent(ModelEvent::etBusReady);
-          getDSS().getApartment().addModelEvent(pEvent);
+          raiseModelEvent(pEvent);
         }
         lastState = currentState;
       }
@@ -1396,7 +1405,7 @@ namespace dss {
               pEvent->addParameter(zoneID);
               pEvent->addParameter(devID);
               pEvent->addParameter(functionID);
-              getDSS().getApartment().addModelEvent(pEvent);
+              raiseModelEvent(pEvent);
             } else if(functionID == FunctionGroupCallScene) {
               pd.get<uint8_t>(); // function id
               uint16_t zoneID = pd.get<uint16_t>();
@@ -1407,13 +1416,15 @@ namespace dss {
                 sceneEvent->setProperty("sceneID", intToString(sceneID & 0x00ff));
                 sceneEvent->setProperty("groupID", intToString(groupID));
                 sceneEvent->setProperty("zoneID", intToString(zoneID));
-                getDSS().getEventQueue().pushEvent(sceneEvent);
+                if(DSS::hasInstance()) {
+                  getDSS().getEventQueue().pushEvent(sceneEvent);
+                }
               }
               ModelEvent* pEvent = new ModelEvent(ModelEvent::etCallSceneGroup);
               pEvent->addParameter(zoneID);
               pEvent->addParameter(groupID);
               pEvent->addParameter(sceneID);
-              getDSS().getApartment().addModelEvent(pEvent);
+              raiseModelEvent(pEvent);
             } else if(functionID == FunctionDeviceCallScene) {
               pd.get<uint8_t>(); // functionID
               uint16_t devID = pd.get<uint16_t>();
@@ -1423,7 +1434,7 @@ namespace dss {
               pEvent->addParameter(modID);
               pEvent->addParameter(devID);
               pEvent->addParameter(sceneID);
-              getDSS().getApartment().addModelEvent(pEvent);
+              raiseModelEvent(pEvent);
             } else if(functionID == EventDSLinkInterrupt) {
               pd.get<uint8_t>(); // functionID
               uint16_t devID = pd.get<uint16_t>();
@@ -1433,7 +1444,7 @@ namespace dss {
               pEvent->addParameter(modID);
               pEvent->addParameter(devID);
               pEvent->addParameter(priority);
-              getDSS().getApartment().addModelEvent(pEvent);
+              raiseModelEvent(pEvent);
             } else if(functionID == EventDeviceReceivedTelegramShort) {
               pd.get<uint8_t>(); // function id
               uint16_t p1 = pd.get<uint16_t>();
@@ -1471,18 +1482,18 @@ namespace dss {
               int modID = pd.get<uint16_t>();
               ModelEvent* pEvent = new ModelEvent(ModelEvent::etNewModulator);
               pEvent->addParameter(modID);
-              getDSS().getApartment().addModelEvent(pEvent);
+              raiseModelEvent(pEvent);
             } else if(functionID == EventLostDS485Device) {
               pd.get<uint8_t>(); // functionID
               int modID = pd.get<uint16_t>();
               ModelEvent* pEvent = new ModelEvent(ModelEvent::etLostModulator);
               pEvent->addParameter(modID);
-              getDSS().getApartment().addModelEvent(pEvent);
+              raiseModelEvent(pEvent);
             } else if(functionID == EventDeviceReady) {
               int modID = frame->getHeader().getDestination();
               ModelEvent* pEvent = new ModelEvent(ModelEvent::etModulatorReady);
               pEvent->addParameter(modID);
-              getDSS().getApartment().addModelEvent(pEvent);
+              raiseModelEvent(pEvent);
             }
           } else {
             std::ostringstream sstream;
@@ -1508,7 +1519,7 @@ namespace dss {
                 ModelEvent* pEvent = new ModelEvent(ModelEvent::etPowerConsumption);
                 pEvent->addParameter(modID);
                 pEvent->addParameter(pd2.get<uint32_t>());
-                getDSS().getApartment().addModelEvent(pEvent);
+                raiseModelEvent(pEvent);
             } else if (functionID == FunctionModulatorGetEnergyMeterValue) {
               /* hard optimized */
               //getDSS().getApartment().getModulatorByBusID((int)(frame->getHeader().getSource())).setEnergyMeterValue(pd2.get<uint32_t>());
@@ -1516,7 +1527,7 @@ namespace dss {
                 ModelEvent* pEvent = new ModelEvent(ModelEvent::etEnergyMeterValue);
                 pEvent->addParameter(modID);
                 pEvent->addParameter(pd2.get<uint32_t>());
-                getDSS().getApartment().addModelEvent(pEvent);
+                raiseModelEvent(pEvent);
             } else if (functionID == FunctionModulatorGetDSID) {
               int sourceID = frame->getHeader().getSource();
               ModelEvent* pEvent = new ModelEvent(ModelEvent::etDS485DeviceDiscovered);
@@ -1527,7 +1538,7 @@ namespace dss {
               pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
               pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
               pEvent->addParameter(((pd2.get<uint8_t>() << 8) & 0xff00) | (pd2.get<uint8_t>() & 0x00ff));
-              getDSS().getApartment().addModelEvent(pEvent);
+              raiseModelEvent(pEvent);
             }
 
             bool bucketFound = false;
diff --git a/unix/ds485proxy.h b/unix/ds485proxy.h
index f4b036d..03012f3 100644
--- a/unix/ds485proxy.h
+++ b/unix/ds485proxy.h
@@ -135,7 +135,7 @@ namespace dss {
 
   typedef std::vector<boost::shared_ptr<DS485CommandFrame> > CommandFrameSharedPtrVector;
 
-  class DS485Proxy : protected Thread,
+  class DS485Proxy : public    Thread,
                      public    Subsystem,
                      public    DS485Interface,
                      public    IDS485FrameCollector {
@@ -156,22 +156,26 @@ namespace dss {
 
     DS485Controller m_DS485Controller;
     SyncEvent m_ProxyEvent;
+    Apartment* m_pApartment;
 
     SyncEvent m_PacketHere;
     Mutex m_IncomingFramesGuard;
     Mutex m_FrameBucketsGuard;
     CommandFrameSharedPtrVector m_IncomingFrames;
+    bool m_InitializeDS485Controller;
 
     ModulatorSpec_t modulatorSpecFromFrame(boost::shared_ptr<DS485CommandFrame> _frame);
     void checkResultCode(const int _resultCode);
+    void raiseModelEvent(ModelEvent* _pEvent);
   protected:
-    virtual void execute();
     virtual void doStart();
   public:
-    DS485Proxy(DSS* _pDSS);
+    DS485Proxy(DSS* _pDSS, Apartment* _pApartment);
     virtual ~DS485Proxy() {};
 
     virtual bool isReady();
+    void setInitializeDS485Controller(const bool _value) { m_InitializeDS485Controller = _value; }
+    virtual void execute();
 
     virtual void sendFrame(DS485CommandFrame& _frame);
     boost::shared_ptr<FrameBucketCollector> sendFrameAndInstallBucket(DS485CommandFrame& _frame, const int _functionID);


hooks/post-receive
-- 
digitalSTROM Server


More information about the dss-commits mailing list