[dss-commits] r8768 - in dss/trunk/core: . scripting sim

dss-commits at forum.digitalstrom.org dss-commits at forum.digitalstrom.org
Thu Sep 17 16:54:20 CEST 2009


Author: pstaehlin
Date: 2009-09-17 16:54:20 +0200 (Thu, 17 Sep 2009)
New Revision: 8768

Modified:
   dss/trunk/core/eventinterpreterplugins.cpp
   dss/trunk/core/eventinterpreterplugins.h
   dss/trunk/core/jshandler.cpp
   dss/trunk/core/jshandler.h
   dss/trunk/core/scripting/modeljs.cpp
   dss/trunk/core/sim/dsid_js.cpp
   dss/trunk/core/sim/dsid_js.h
   dss/trunk/core/sim/dssim.cpp
   dss/trunk/core/sim/dssim.h
Log:
- Scripts executed by a event may be kept in memory
- Support for dSLinkInterrupt for simulated (js) devices
- Various fixes


Modified: dss/trunk/core/eventinterpreterplugins.cpp
===================================================================
--- dss/trunk/core/eventinterpreterplugins.cpp	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/eventinterpreterplugins.cpp	2009-09-17 14:54:20 UTC (rev 8768)
@@ -85,17 +85,33 @@
         }
 
         try {
-          boost::scoped_ptr<ScriptContext> ctx(m_Environment.getContext());
+          boost::shared_ptr<ScriptContext> ctx(m_Environment.getContext());
           ScriptObject raisedEvent(*ctx, NULL);
           raisedEvent.setProperty<const std::string&>("name", _event.getName());
+          ctx->getRootObject().setProperty("raisedEvent", &raisedEvent);
+
+          // add raisedEvent.parameter
           ScriptObject param(*ctx, NULL);
-          // TODO: add parameter
           raisedEvent.setProperty("parameter", &param);
-          ctx->getRootObject().setProperty("raisedEvent", &raisedEvent);
-          // TODO: add subscription
+          const HashMapConstStringString& props =  _event.getProperties().getContainer();
+          for(HashMapConstStringString::const_iterator iParam = props.begin(), e = props.end();
+              iParam != e; ++iParam)
+          {
+            param.setProperty<const std::string&>(iParam->first, iParam->second);
+          }
+
+          // add raisedEvent.subscription
+          ScriptObject subscriptionObj(*ctx, NULL);
+          raisedEvent.setProperty("subscription", &subscriptionObj);
+          subscriptionObj.setProperty<const std::string&>("name", _subscription.getEventName());
           
           ctx->loadFromFile(scriptName);
           ctx->evaluate<void>();
+
+          if(ctx->getKeepContext()) {
+            m_KeptContexts.push_back(ctx);
+            Logger::getInstance()->log("EventInterpreterPluginJavascript::handleEvent: keeping script " + scriptName + " in memory", lsInfo);
+          }
         } catch(ScriptException& e) {
           Logger::getInstance()->log(string("EventInterpreterPluginJavascript::handleEvent: Cought event while running/parsing script '")
                               + scriptName + "'. Message: " + e.what(), lsError);

Modified: dss/trunk/core/eventinterpreterplugins.h
===================================================================
--- dss/trunk/core/eventinterpreterplugins.h	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/eventinterpreterplugins.h	2009-09-17 14:54:20 UTC (rev 8768)
@@ -23,6 +23,9 @@
 #define EVENTINTERPRETERPLUGINS_H_
 
 #include "event.h"
+
+#include <boost/shared_ptr.hpp>
+
 #include "jshandler.h"
 
 namespace dss {
@@ -34,9 +37,11 @@
     virtual void handleEvent(Event& _event, const EventSubscription& _subscription);
   }; // EventInterpreterPluginRaiseEvent
 
+
   class EventInterpreterPluginJavascript : public EventInterpreterPlugin {
   private:
     ScriptEnvironment m_Environment;
+    std::vector<boost::shared_ptr<ScriptContext> > m_KeptContexts;
   public:
     EventInterpreterPluginJavascript(EventInterpreter* _pInterpreter);
 

Modified: dss/trunk/core/jshandler.cpp
===================================================================
--- dss/trunk/core/jshandler.cpp	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/jshandler.cpp	2009-09-17 14:54:20 UTC (rev 8768)
@@ -144,8 +144,14 @@
       Logger::getInstance()->log(sstream.str());
     }
     return JS_TRUE;
-  }
+  } // global_print
 
+  JSBool global_keepContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
+    ScriptContext* ctx = static_cast<ScriptContext*>(JS_GetContextPrivate(cx));
+    ctx->setKeepContext(true);
+    return JS_TRUE;
+} // global_print
+
   static JSClass global_class = {
     "global", JSCLASS_NEW_RESOLVE, /* use the new resolve hook */
     JS_PropertyStub,  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
@@ -156,6 +162,7 @@
 
   JSFunctionSpec global_methods[] = {
     {"print", global_print, 1, 0, 0},
+    {"keepContext", global_keepContext, 0, 0, 0},
     {NULL},
   };
 

Modified: dss/trunk/core/jshandler.h
===================================================================
--- dss/trunk/core/jshandler.h	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/jshandler.h	2009-09-17 14:54:20 UTC (rev 8768)
@@ -82,6 +82,7 @@
     JSObject* m_pSourceObject;
     ScriptEnvironment& m_Environment;
     JSContext* m_pContext;
+    bool m_KeepContext;
     static void jsErrorHandler(JSContext *ctx, const char *msg, JSErrorReport *er);
   public:
     ScriptContext(ScriptEnvironment& _env, JSContext* _pContext);
@@ -116,6 +117,8 @@
     ScriptEnvironment& getEnvironment() { return m_Environment; }
     ScriptObject& getRootObject() { return *m_RootObject; }
     bool raisePendingExceptions();
+    bool getKeepContext() { return m_KeepContext; };
+    void setKeepContext(bool _value) { m_KeepContext = _value; }
   public:
 
     /** Helper function to convert a jsval to a t. */

Modified: dss/trunk/core/scripting/modeljs.cpp
===================================================================
--- dss/trunk/core/scripting/modeljs.cpp	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/scripting/modeljs.cpp	2009-09-17 14:54:20 UTC (rev 8768)
@@ -906,20 +906,26 @@
       std::string propName = ctx->convertTo<std::string>(argv[0]);
       
       PropertyNodePtr node = ext->getPropertySystem().createProperty(propName);
-      try {
-        if(JSVAL_IS_STRING(argv[1])) {
-          node->setStringValue(ctx->convertTo<std::string>(argv[1]));
-        } else if(JSVAL_IS_BOOLEAN(argv[1])) {
-          node->setBooleanValue(ctx->convertTo<bool>(argv[1]));
-        } else if(JSVAL_IS_INT(argv[1])) {
-          node->setIntegerValue(ctx->convertTo<int>(argv[1]));
-        } else {
-          Logger::getInstance()->log("JS: global_prop_setProperty: unknown type of argument 2", lsError);
+      if(node != NULL) {
+        try {
+          if(JSVAL_IS_STRING(argv[1])) {
+            node->setStringValue(ctx->convertTo<std::string>(argv[1]));
+          } else if(JSVAL_IS_BOOLEAN(argv[1])) {
+            node->setBooleanValue(ctx->convertTo<bool>(argv[1]));
+          } else if(JSVAL_IS_INT(argv[1])) {
+            node->setIntegerValue(ctx->convertTo<int>(argv[1]));
+          } else {
+            Logger::getInstance()->log("JS: global_prop_setProperty: unknown type of argument 2", lsError);
+          }
+          *rval = JSVAL_TRUE;
+          return JS_TRUE;
+        } catch(PropertyTypeMismatch&) {
+          Logger::getInstance()->log("Error setting value of " + propName, lsFatal);
         }
-        *rval = JSVAL_TRUE;
+      } else {
+        Logger::getInstance()->log("Coule not create property " + propName, lsFatal);
+        *rval = JSVAL_FALSE;
         return JS_TRUE;
-      } catch(PropertyTypeMismatch&) {
-        Logger::getInstance()->log("Error setting value of " + propName, lsFatal);
       }
     }
     return JS_FALSE;

Modified: dss/trunk/core/sim/dsid_js.cpp
===================================================================
--- dss/trunk/core/sim/dsid_js.cpp	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/sim/dsid_js.cpp	2009-09-17 14:54:20 UTC (rev 8768)
@@ -21,6 +21,8 @@
 
 #include "dsid_js.h"
 #include "core/jshandler.h"
+#include "core/scripting/modeljs.h"
+#include "core/dss.h"
 
 namespace dss {
 
@@ -200,7 +202,7 @@
       if(m_pSelf != NULL) {
         try {
           ScriptFunctionParameterList param(*m_pContext);
-          m_pSelf->callFunctionByName<int>("getFunctionID", param);
+          return m_pSelf->callFunctionByName<int>("getFunctionID", param);
         } catch(ScriptException& e) {
           Logger::getInstance()->log(std::string("DSIDJS: Error calling 'getFunctionID'") + e.what(), lsError);
         }
@@ -254,14 +256,75 @@
   }; // DSIDJS
 
 
+  //================================================== DSIDScriptExtension
+
+  const char* DSIDScriptExtensionName = "dsidextension";
+
+  class DSIDScriptExtension : public ScriptExtension {
+  public:
+    DSIDScriptExtension(DSSim& _simulation)
+    : ScriptExtension(DSIDScriptExtensionName),
+      m_Simulation(_simulation)
+    { } // ctor
+
+    virtual ~DSIDScriptExtension() {}
+
+    virtual void extendContext(ScriptContext& _context);
+
+    void dSLinkInterrupt(const dsid_t& _dsid) {
+      DSIDInterface* intf = m_Simulation.getSimulatedDevice(_dsid);
+      if(intf != NULL) {
+        intf->dSLinkInterrupt();
+      }
+    } // dSLinkInterrupt
+
+  private:
+    DSSim& m_Simulation;
+  }; // PropertyScriptExtension
+
+  JSBool global_dsid_dSLinkInterrupt(JSContext* cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
+    if(argc < 1) {
+      Logger::getInstance()->log("JS: glogal_dsid_dSLinkInterrupt: need argument dsid", lsError);
+    } else {
+      ScriptContext* ctx = static_cast<ScriptContext*>(JS_GetContextPrivate(cx));
+
+      DSIDScriptExtension* ext = dynamic_cast<DSIDScriptExtension*>(ctx->getEnvironment().getExtension(DSIDScriptExtensionName));
+      std::string dsidString = ctx->convertTo<std::string>(argv[0]);
+
+      try {
+        dsid_t dsid = dsid_t::fromString(dsidString);
+        ext->dSLinkInterrupt(dsid);
+      } catch(std::runtime_error&) {
+        Logger::getInstance()->log("Could not parse DSID");
+      }
+
+      *rval = JSVAL_TRUE;
+      return JS_TRUE;
+    }
+    return JS_FALSE;
+  } // global_prop_setListener
+
+  JSFunctionSpec dsid_global_methods[] = {
+    {"dSLinkInterrupt", global_dsid_dSLinkInterrupt, 1, 0, 0},
+    {NULL},
+  };
+
+  void DSIDScriptExtension::extendContext(ScriptContext& _context) {
+    JS_DefineFunctions(_context.getJSContext(), JS_GetGlobalObject(_context.getJSContext()), dsid_global_methods);
+  } // extendContext
+
+
   //================================================== DSIDJSCreator
 
-  DSIDJSCreator::DSIDJSCreator(const std::string& _fileName, const std::string& _pluginName)
+  DSIDJSCreator::DSIDJSCreator(const std::string& _fileName, const std::string& _pluginName, DSSim& _simulator)
   : DSIDCreator(_pluginName),
     m_pScriptEnvironment(new ScriptEnvironment()),
-    m_FileName(_fileName)
+    m_FileName(_fileName),
+    m_Simulator(_simulator)
   {
     m_pScriptEnvironment->initialize();
+    m_pScriptEnvironment->addExtension(new PropertyScriptExtension(DSS::getInstance()->getPropertySystem()));
+    m_pScriptEnvironment->addExtension(new DSIDScriptExtension(m_Simulator));
   } // ctor
 
   DSIDInterface* DSIDJSCreator::createDSID(const dsid_t _dsid, const devid_t _shortAddress, const DSModulatorSim& _modulator) {

Modified: dss/trunk/core/sim/dsid_js.h
===================================================================
--- dss/trunk/core/sim/dsid_js.h	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/sim/dsid_js.h	2009-09-17 14:54:20 UTC (rev 8768)
@@ -33,11 +33,12 @@
 
   class DSIDJSCreator : public DSIDCreator {
   public:
-    DSIDJSCreator(const std::string& _fileName, const std::string& _pluginName);
+    DSIDJSCreator(const std::string& _fileName, const std::string& _pluginName, DSSim& _simulator);
     virtual DSIDInterface* createDSID(const dsid_t _dsid, const devid_t _shortAddress, const DSModulatorSim& _modulator);
   private:
     boost::scoped_ptr<ScriptEnvironment> m_pScriptEnvironment;
     std::string m_FileName;
+    DSSim& m_Simulator;
   }; // DSIDPluginCreator
 
 }

Modified: dss/trunk/core/sim/dssim.cpp
===================================================================
--- dss/trunk/core/sim/dssim.cpp	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/sim/dssim.cpp	2009-09-17 14:54:20 UTC (rev 8768)
@@ -102,7 +102,7 @@
               continue;
             }
             log("Found js-device with script '" + scriptFile + "' and id: '" + simIDNode->getAsString() + "'", lsInfo);
-            m_DSIDFactory.registerCreator(new DSIDJSCreator(scriptFile, simIDNode->getAsString()));
+            m_DSIDFactory.registerCreator(new DSIDJSCreator(scriptFile, simIDNode->getAsString(), *this));
           } else {
             log("DSSim::initialize: Missing property id", lsError);
           }
@@ -229,6 +229,18 @@
     DS485FrameProvider::distributeFrame(_frame);
   } // distributeFrame
 
+  DSIDInterface* DSSim::getSimulatedDevice(const dsid_t& _dsid) {
+    DSIDInterface* result = NULL;
+    foreach(DSModulatorSim& modulator, m_Modulators) {
+      result = modulator.getSimulatedDevice(_dsid);
+      if(result != NULL) {
+        break;
+      }
+    }
+    return result;
+  } // getSimulatedDevice
+
+
   //================================================== DSModulatorSim
 
   DSModulatorSim::DSModulatorSim(DSSim* _pSimulation)
@@ -953,12 +965,24 @@
     }
   } // process
 
-  void DSModulatorSim::distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame) {
+  void DSModulatorSim::distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame) const {
     m_pSimulation->distributeFrame(_frame);
   } // distributeFrame
 
-  boost::shared_ptr<DS485CommandFrame> DSModulatorSim::createReply(DS485CommandFrame& _request) {
+  void DSModulatorSim::dSLinkInterrupt(devid_t _shortAddress) const {
     boost::shared_ptr<DS485CommandFrame> result(new DS485CommandFrame());
+    result->getHeader().setDestination(0);
+    result->getHeader().setSource(m_ID);
+    result->getHeader().setBroadcast(true);
+    result->getHeader().setCounter(0);
+    result->setCommand(CommandEvent);
+    result->getPayload().add<uint8_t>(FunctionDSLinkInterrupt);
+    result->getPayload().add<devid_t>(_shortAddress);
+    distributeFrame(result);
+  } // dSLinkInterrupt
+
+  boost::shared_ptr<DS485CommandFrame> DSModulatorSim::createReply(DS485CommandFrame& _request) const {
+    boost::shared_ptr<DS485CommandFrame> result(new DS485CommandFrame());
     result->getHeader().setDestination(_request.getHeader().getSource());
     result->getHeader().setSource(m_ID);
     result->getHeader().setBroadcast(false);
@@ -966,22 +990,20 @@
     return result;
   } // createReply
 
-
-  boost::shared_ptr<DS485CommandFrame> DSModulatorSim::createAck(DS485CommandFrame& _request, uint8_t _functionID) {
+  boost::shared_ptr<DS485CommandFrame> DSModulatorSim::createAck(DS485CommandFrame& _request, uint8_t _functionID) const {
     boost::shared_ptr<DS485CommandFrame> result = createReply(_request);
     result->setCommand(CommandAck);
     result->getPayload().add(_functionID);
     return result;
-  }
+  } // createAck
 
-  boost::shared_ptr<DS485CommandFrame> DSModulatorSim::createResponse(DS485CommandFrame& _request, uint8_t _functionID) {
+  boost::shared_ptr<DS485CommandFrame> DSModulatorSim::createResponse(DS485CommandFrame& _request, uint8_t _functionID) const {
     boost::shared_ptr<DS485CommandFrame> result = createReply(_request);
     result->setCommand(CommandResponse);
     result->getPayload().add(_functionID);
     return result;
   } // createResponse
 
-
   DSIDInterface& DSModulatorSim::lookupDevice(const devid_t _shortAddress) {
     for(vector<DSIDInterface*>::iterator ipSimDev = m_SimulatedDevices.begin(); ipSimDev != m_SimulatedDevices.end(); ++ipSimDev) {
       if((*ipSimDev)->getShortAddress() == _shortAddress)  {
@@ -994,6 +1016,7 @@
   int DSModulatorSim::getID() const {
     return m_ID;
   } // getID
+
   DSIDInterface* DSModulatorSim::getSimulatedDevice(const dsid_t _dsid) {
     for(vector<DSIDInterface*>::iterator iDSID = m_SimulatedDevices.begin(), e = m_SimulatedDevices.end();
         iDSID != e; ++iDSID)
@@ -1027,10 +1050,10 @@
     }
     Logger::getInstance()->log(string("Could not find creator for DSID type '") + _identifier + "'");
     throw new runtime_error(string("Could not find creator for DSID type '") + _identifier + "'");
-  }
+  } // createDSID
 
   void DSIDFactory::registerCreator(DSIDCreator* _creator) {
     m_RegisteredCreators.push_back(_creator);
-  }
+  } // registerCreator
 
 }

Modified: dss/trunk/core/sim/dssim.h
===================================================================
--- dss/trunk/core/sim/dssim.h	2009-09-16 15:46:04 UTC (rev 8767)
+++ dss/trunk/core/sim/dssim.h	2009-09-17 14:54:20 UTC (rev 8768)
@@ -83,6 +83,7 @@
     DSIDFactory& getDSIDFactory() { return m_DSIDFactory; }
 
     void distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame);
+    DSIDInterface* getSimulatedDevice(const dsid_t& _dsid);
   }; // DSSim
 
   typedef std::map< const pair<const int, const int>,  std::vector<DSIDInterface*> > IntPairToDSIDSimVector;
@@ -111,11 +112,11 @@
     void loadZones(XMLNodeList& _nodes);
 
     DSIDInterface& lookupDevice(const devid_t _id);
-    boost::shared_ptr<DS485CommandFrame> createResponse(DS485CommandFrame& _request, uint8_t _functionID);
-    boost::shared_ptr<DS485CommandFrame> createAck(DS485CommandFrame& _request, uint8_t _functionID);
-    boost::shared_ptr<DS485CommandFrame> createReply(DS485CommandFrame& _request);
+    boost::shared_ptr<DS485CommandFrame> createResponse(DS485CommandFrame& _request, uint8_t _functionID) const;
+    boost::shared_ptr<DS485CommandFrame> createAck(DS485CommandFrame& _request, uint8_t _functionID) const;
+    boost::shared_ptr<DS485CommandFrame> createReply(DS485CommandFrame& _request) const;
 
-    void distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame);
+    void distributeFrame(boost::shared_ptr<DS485CommandFrame> _frame) const;
   private:
     void deviceCallScene(const int _deviceID, const int _sceneID);
     void groupCallScene(const int _zoneID, const int _groupID, const int _sceneID);
@@ -142,6 +143,7 @@
     void process(DS485Frame& _frame);
 
     DSIDInterface* getSimulatedDevice(const dsid_t _dsid);
+    void dSLinkInterrupt(devid_t _shortAddress) const;
   }; // DSModulatorSim
 
   class DSIDInterface {
@@ -192,6 +194,11 @@
     virtual void setZoneID(const int _value) { m_ZoneID = _value; }
     virtual int getZoneID() const { return m_ZoneID; }
     virtual uint8_t dsLinkSend(uint8_t _value, uint8_t _flags) { return 0; }
+
+    /** Signals the modulator that a interrupt has occurred */
+    void dSLinkInterrupt() {
+      m_Simulator.dSLinkInterrupt(m_ShortAddress);
+    }
   }; // DSIDInterface
 
 



More information about the dss-commits mailing list