[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", ¶m);
- 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