.X
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"body": {
|
||||
"type": "string"
|
||||
"type": "object"
|
||||
},
|
||||
"conditions": {
|
||||
"type": "array",
|
||||
@@ -39,7 +39,7 @@
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [ "name", "conditions", "body" ]
|
||||
"required": [ "conditions", "body" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,6 @@ bundle(hos_cosgi_rulesengine
|
||||
${PROJECT_SOURCE_DIR}/src/bundle_activator
|
||||
${PROJECT_SOURCE_DIR}/src/hos_rulesengine_service_impl
|
||||
${PROJECT_SOURCE_DIR}/src/rulesengine/RulePackage
|
||||
${PROJECT_SOURCE_DIR}/src/rulesengine/GlobalContext
|
||||
${PROJECT_SOURCE_DIR}/src/rulesengine/Rule
|
||||
${PROJECT_SOURCE_DIR}/src/rulesengine/RuleCondition
|
||||
)
|
||||
|
||||
+6
-6
@@ -11,16 +11,15 @@
|
||||
|
||||
#include <hos_cosgi_common/cosgi_common.h>
|
||||
#include <memory>
|
||||
#include <Variant/Variant.h>
|
||||
|
||||
|
||||
// Forward declarations
|
||||
namespace XmlRpc {
|
||||
class XmlRpcValue;
|
||||
}
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
class RulePackage;
|
||||
class Rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +36,8 @@ class GlobalExecutionContext : public COSGI_Object_Interface {
|
||||
|
||||
|
||||
class RuleBody : public COSGI_Object_Interface {
|
||||
|
||||
public:
|
||||
virtual void exec(GlobalExecutionContext* gContext) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ public:
|
||||
|
||||
virtual std::string getLanguage() = 0;
|
||||
|
||||
virtual std::shared_ptr<GlobalExecutionContext> createGlobalExecutionContext(rulesengine::RulePackage* parent, XmlRpc::XmlRpcValue& raw) = 0;
|
||||
virtual std::shared_ptr<RuleBody> createRuleBody(rulesengine::RulePackage* parent, XmlRpc::XmlRpcValue& raw) = 0;
|
||||
virtual std::shared_ptr<GlobalExecutionContext> createGlobalExecutionContext(rulesengine::RulePackage* parent, libvariant::Variant raw) = 0;
|
||||
virtual std::shared_ptr<RuleBody> createRuleBody(rulesengine::Rule* parent, GlobalExecutionContext* gContext, libvariant::Variant raw) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <unordered_set>
|
||||
#include <hos_celix/bundle_context.h>
|
||||
#include "rulesengine/RulePackage.h"
|
||||
#include <Variant/Variant.h>
|
||||
|
||||
|
||||
namespace hos {
|
||||
@@ -49,6 +50,7 @@ void HOSRulesEngineServiceImpl::init() {
|
||||
nodehandle->getParam("rulesengine_prefix", ruleEnginePrefix);
|
||||
XmlRpc::XmlRpcValue rawValue;
|
||||
nodehandle->getParam(ruleEnginePrefix, rawValue);
|
||||
schemaLoader.reset(new libvariant::HosSchemaLoader());
|
||||
if (rawValue.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
|
||||
for (auto pkg : rawValue) {
|
||||
std::string pname = pkg.first;
|
||||
@@ -86,13 +88,27 @@ void HOSRulesEngineServiceImpl::addRulePkg(std::string name) {
|
||||
ss << ruleEnginePrefix << "/" << name;
|
||||
XmlRpc::XmlRpcValue rawValue;
|
||||
nodehandle->getParam(ss.str(), rawValue);
|
||||
addRulePkg(name, rawValue);
|
||||
addRulePkg(name, static_cast<std::string>(rawValue));
|
||||
}
|
||||
|
||||
void HOSRulesEngineServiceImpl::addRulePkg(std::string name, XmlRpc::XmlRpcValue& rawValue) {
|
||||
std::shared_ptr<RulePackage> pkg = RulePackage::createRulePackage(*this, name, rawValue);
|
||||
if (pkg) {
|
||||
rulePkgs.insert({name, pkg});
|
||||
void HOSRulesEngineServiceImpl::addRulePkg(std::string name, std::string rawValue) {
|
||||
::libvariant::Variant s = schemaLoader->GetSchema(std::string("hos:schema://core/configs/rulepackage"));
|
||||
::libvariant::Variant m = ::libvariant::Deserialize(rawValue, ::libvariant::SERIALIZE_JSON);
|
||||
::libvariant::SchemaResult sr = ::libvariant::SchemaValidate(s, m, schemaLoader.get());
|
||||
if (!sr.Error()) {
|
||||
std::shared_ptr<RulePackage> pkg = RulePackage::createRulePackage(this, name, m);
|
||||
if (pkg) {
|
||||
if (pkg->getState() == RulePackage::State::Ok) {
|
||||
rulePkgs.insert({name, pkg});
|
||||
} else if (pkg->getState() == RulePackage::State::NoExecService) {
|
||||
noExecRulePkgs.insert({name, pkg});
|
||||
std::cout << "No execution service found for rule package \"" << name << "\"" << std::endl;
|
||||
} else {
|
||||
throw std::runtime_error("Unknown state");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error(sr.PrettyPrintMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +123,16 @@ void HOSRulesEngineServiceImpl::addExecutionBackend(rulesexecution::HOSRulesExec
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rulesexecution::HOSRulesExecutionService* HOSRulesEngineServiceImpl::getExecutionBackend(std::string language) {
|
||||
auto s = execServices.find(language);
|
||||
if (s != execServices.end()) {
|
||||
return s->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
} // namespace rulesengine
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <hos_core_msgs/HosStatusUpdate.h>
|
||||
#include <hos_cpp_common/observable_impl.h>
|
||||
|
||||
#include <HosSchemaLoader/HosSchemaLoader.h>
|
||||
|
||||
#include <ros/ros.h>
|
||||
|
||||
#include <map>
|
||||
@@ -66,12 +68,15 @@ private:
|
||||
std::string ruleEnginePrefix = "/hos/rules/rulesengine0";
|
||||
|
||||
rulePkgMap_t rulePkgs;
|
||||
rulePkgMap_t noExecRulePkgs;
|
||||
execServiceMap_t execServices;
|
||||
|
||||
std::unique_ptr<libvariant::HosSchemaLoader> schemaLoader;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
void addRulePkg(std::string name);
|
||||
void addRulePkg(std::string name, XmlRpc::XmlRpcValue& rawValue);
|
||||
void addRulePkg(std::string name, std::string rawValue);
|
||||
void removeRulePkg(std::string name);
|
||||
|
||||
void init();
|
||||
@@ -97,6 +102,7 @@ public:
|
||||
bool isInitialized() { return initialized; }
|
||||
|
||||
void addExecutionBackend(rulesexecution::HOSRulesExecutionService* service);
|
||||
rulesexecution::HOSRulesExecutionService* getExecutionBackend(std::string language);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* GlobalContext.cpp
|
||||
*
|
||||
* Created on: 29.04.2015
|
||||
* Author: matzman
|
||||
*/
|
||||
|
||||
#include "GlobalContext.h"
|
||||
#include <ros/ros.h>
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
|
||||
GlobalContext::GlobalContext(RulePackage& parent)
|
||||
: parent(parent) {}
|
||||
|
||||
GlobalContext::~GlobalContext() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
std::shared_ptr<GlobalContext> GlobalContext::createGlobalContext(RulePackage& parent, const XmlRpc::XmlRpcValue& raw) {
|
||||
std::shared_ptr<GlobalContext> retval;
|
||||
if (raw.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
|
||||
retval = std::make_shared<GlobalContext>(parent);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
} /* namespace rulesengine */
|
||||
} /* namespace cosgi */
|
||||
} /* namespace hos */
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* GlobalContext.h
|
||||
*
|
||||
* Created on: 29.04.2015
|
||||
* Author: matzman
|
||||
*/
|
||||
|
||||
#ifndef SRC_RULESENGINE_GLOBALCONTEXT_H_
|
||||
#define SRC_RULESENGINE_GLOBALCONTEXT_H_
|
||||
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
// Forward declarations
|
||||
namespace XmlRpc {
|
||||
class XmlRpcValue;
|
||||
}
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
class RulePackage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
|
||||
class GlobalContext {
|
||||
private:
|
||||
RulePackage& parent;
|
||||
public:
|
||||
GlobalContext(RulePackage& parent);
|
||||
static std::shared_ptr<GlobalContext> createGlobalContext(RulePackage& parent, const XmlRpc::XmlRpcValue& raw);
|
||||
virtual ~GlobalContext();
|
||||
|
||||
RulePackage& getParent() { return parent; }
|
||||
};
|
||||
|
||||
} /* namespace rulesengine */
|
||||
} /* namespace cosgi */
|
||||
} /* namespace hos */
|
||||
|
||||
#endif /* SRC_RULESENGINE_GLOBALCONTEXT_H_ */
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
|
||||
#include "Rule.h"
|
||||
#include "RuleCondition.h"
|
||||
#include <hos_cosgi_rulesengine/hos_rulesexecution_service.h>
|
||||
#include <ros/ros.h>
|
||||
|
||||
|
||||
@@ -15,22 +17,23 @@ namespace cosgi {
|
||||
namespace rulesengine {
|
||||
|
||||
|
||||
Rule::Rule(RulePackage& parent, std::string name)
|
||||
: parent(parent), name(name) {}
|
||||
Rule::Rule(RulePackage* parent, std::string name, rulesexecution::HOSRulesExecutionService* executionService)
|
||||
: parent(parent), name(name), executionService(executionService) {}
|
||||
|
||||
Rule::~Rule() {}
|
||||
|
||||
std::shared_ptr<Rule> Rule::createRule(RulePackage& parent, std::string name, XmlRpc::XmlRpcValue& raw) {
|
||||
std::shared_ptr<Rule> Rule::createRule(RulePackage* parent, std::string name, rulesexecution::GlobalExecutionContext* gContext, libvariant::Variant raw, rulesexecution::HOSRulesExecutionService* executionService) {
|
||||
std::shared_ptr<Rule> retval;
|
||||
if (raw.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
|
||||
retval = std::make_shared<Rule>(parent, name);
|
||||
if (raw.hasMember("conditions") && raw["conditions"].getType() == XmlRpc::XmlRpcValue::TypeStruct) {
|
||||
if (raw.IsMap()) {
|
||||
retval = std::make_shared<Rule>(parent, name, executionService);
|
||||
if (raw.HasPath("conditions") && raw["conditions"].IsList()) {
|
||||
auto conditions = raw["conditions"];
|
||||
for (auto c : conditions) {
|
||||
|
||||
for (auto c : conditions.AsList()) {
|
||||
auto cond = RuleCondition::createRuleCondition(retval.get(), c);
|
||||
retval->conditions.push_back(cond);
|
||||
}
|
||||
if (raw.hasMember("body") && raw["body"].getType() == XmlRpc::XmlRpcValue::TypeString) {
|
||||
|
||||
if (raw.HasPath("body") && raw["body"].IsMap()) {
|
||||
retval->body = executionService->createRuleBody(retval.get(), gContext, raw["body"]);
|
||||
} else {
|
||||
ROS_ERROR_STREAM("Could not create rule \"" << name << "\".");
|
||||
retval.reset();
|
||||
@@ -43,6 +46,10 @@ std::shared_ptr<Rule> Rule::createRule(RulePackage& parent, std::string name, Xm
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Rule::exec(rulesexecution::GlobalExecutionContext* gContext) {
|
||||
body->exec(gContext);
|
||||
}
|
||||
|
||||
|
||||
} /* namespace rulesengine */
|
||||
} /* namespace cosgi */
|
||||
|
||||
@@ -12,19 +12,22 @@
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <Variant/Variant.h>
|
||||
|
||||
|
||||
// Forward declarations
|
||||
namespace XmlRpc {
|
||||
class XmlRpcValue;
|
||||
}
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
class RulePackage;
|
||||
class RuleBody;
|
||||
class Rule;
|
||||
class RuleCondition;
|
||||
}
|
||||
namespace rulesexecution {
|
||||
class HOSRulesExecutionService;
|
||||
class GlobalExecutionContext;
|
||||
class RuleBody;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,16 +39,19 @@ namespace rulesengine {
|
||||
|
||||
class Rule {
|
||||
private:
|
||||
RulePackage& parent;
|
||||
RulePackage* parent;
|
||||
std::string name;
|
||||
std::shared_ptr<RuleBody> body;
|
||||
std::shared_ptr<rulesexecution::RuleBody> body;
|
||||
std::vector<std::shared_ptr<RuleCondition>> conditions;
|
||||
rulesexecution::HOSRulesExecutionService* executionService;
|
||||
public:
|
||||
Rule(RulePackage& parent, std::string name);
|
||||
static std::shared_ptr<Rule> createRule(RulePackage& parent, std::string name, XmlRpc::XmlRpcValue& raw);
|
||||
Rule(RulePackage* parent, std::string name, rulesexecution::HOSRulesExecutionService* executionService);
|
||||
static std::shared_ptr<Rule> createRule(RulePackage* parent, std::string name, rulesexecution::GlobalExecutionContext* gContext, libvariant::Variant raw, rulesexecution::HOSRulesExecutionService* executionService);
|
||||
virtual ~Rule();
|
||||
|
||||
RulePackage& getParent() { return parent; }
|
||||
RulePackage* getParent() { return parent; }
|
||||
|
||||
virtual void exec(rulesexecution::GlobalExecutionContext* gContext);
|
||||
};
|
||||
|
||||
class RuleBody {
|
||||
|
||||
@@ -11,14 +11,12 @@ namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
|
||||
RuleCondition::RuleCondition() {
|
||||
// TODO Auto-generated constructor stub
|
||||
|
||||
std::shared_ptr<RuleCondition> RuleCondition::createRuleCondition(Rule* parent, libvariant::Variant raw) {
|
||||
std::shared_ptr<RuleCondition> retval;
|
||||
return retval;
|
||||
}
|
||||
|
||||
RuleCondition::~RuleCondition() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
} /* namespace rulesengine */
|
||||
} /* namespace cosgi */
|
||||
|
||||
@@ -8,16 +8,74 @@
|
||||
#ifndef SRC_RULESENGINE_RULECONDITION_H_
|
||||
#define SRC_RULESENGINE_RULECONDITION_H_
|
||||
|
||||
#include <memory>
|
||||
#include <Variant/Variant.h>
|
||||
|
||||
|
||||
// Forward declarations
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
class Rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
|
||||
|
||||
|
||||
class RuleCondition {
|
||||
public:
|
||||
RuleCondition();
|
||||
virtual ~RuleCondition();
|
||||
enum class Type : int { DeviceMsgCondition, DeviceStatusCondition, TimeEventCondition, SystemEventCondition};
|
||||
private:
|
||||
Rule* parent;
|
||||
const Type type;
|
||||
public:
|
||||
static std::shared_ptr<RuleCondition> createRuleCondition(Rule* parent, libvariant::Variant raw);
|
||||
public:
|
||||
RuleCondition(Rule* parent, Type type) : parent(parent), type(type) {}
|
||||
virtual ~RuleCondition() {}
|
||||
|
||||
const Type getType() { return type; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DeviceMsgCondition : public RuleCondition {
|
||||
friend class RuleCondition;
|
||||
public:
|
||||
DeviceMsgCondition(Rule* parent) : RuleCondition(parent, Type::DeviceMsgCondition) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DeviceStatusCondition : public RuleCondition {
|
||||
friend class RuleCondition;
|
||||
public:
|
||||
DeviceStatusCondition(Rule* parent) : RuleCondition(parent, Type::DeviceStatusCondition) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class TimeEventCondition : public RuleCondition {
|
||||
friend class RuleCondition;
|
||||
public:
|
||||
TimeEventCondition(Rule* parent) : RuleCondition(parent, Type::TimeEventCondition) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SystemEventCondition : public RuleCondition {
|
||||
friend class RuleCondition;
|
||||
public:
|
||||
SystemEventCondition(Rule* parent) : RuleCondition(parent, Type::SystemEventCondition) {}
|
||||
};
|
||||
|
||||
|
||||
} /* namespace rulesengine */
|
||||
} /* namespace cosgi */
|
||||
} /* namespace hos */
|
||||
|
||||
@@ -6,45 +6,52 @@
|
||||
*/
|
||||
|
||||
#include "RulePackage.h"
|
||||
#include "GlobalContext.h"
|
||||
#include "Rule.h"
|
||||
#include <ros/ros.h>
|
||||
#include <exception>
|
||||
#include <Variant/Variant.h>
|
||||
#include "../hos_rulesengine_service_impl.h"
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
|
||||
RulePackage::RulePackage(HOSRulesEngineServiceImpl& parent, std::string name)
|
||||
RulePackage::RulePackage(HOSRulesEngineServiceImpl* parent, std::string name)
|
||||
: parent(parent), name(name) {}
|
||||
|
||||
RulePackage::~RulePackage() {
|
||||
}
|
||||
|
||||
std::shared_ptr<RulePackage> RulePackage::createRulePackage(HOSRulesEngineServiceImpl& parent, std::string name, XmlRpc::XmlRpcValue& raw) {
|
||||
std::shared_ptr<RulePackage> RulePackage::createRulePackage(HOSRulesEngineServiceImpl* parent, std::string name, ::libvariant::Variant raw) {
|
||||
std::shared_ptr<RulePackage> retval;
|
||||
if (raw.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
|
||||
if (raw.IsMap()) {
|
||||
retval = std::make_shared<RulePackage>(parent, name);
|
||||
if (raw.hasMember("language") && raw["language"].getType() == XmlRpc::XmlRpcValue::TypeString) {
|
||||
retval->language = static_cast<std::string>(raw["language"]);
|
||||
if (raw.HasPath("language") && raw["language"].IsString()) {
|
||||
retval->language = raw["language"].AsString();
|
||||
} else {
|
||||
throw std::runtime_error("Rule package JSON is missing language parameter or parameter has wrong type.");
|
||||
}
|
||||
if (raw.hasMember("globalcontext")) {
|
||||
retval->globalContext = GlobalContext::createGlobalContext(*retval, raw["globalcontext"]);
|
||||
}
|
||||
if (raw.hasMember("rules") && raw["rules"].getType() == XmlRpc::XmlRpcValue::TypeStruct) {
|
||||
for (auto r : raw["rules"]) {
|
||||
std::shared_ptr<Rule> rule = Rule::createRule(*retval, r.first, r.second);
|
||||
if (rule) {
|
||||
retval->rules.insert({r.first, rule});
|
||||
retval->executionService = parent->getExecutionBackend(retval->language);
|
||||
if (retval->executionService) {
|
||||
if (raw.HasPath("globalcontext")) {
|
||||
retval->globalContext = retval->executionService->createGlobalExecutionContext(retval.get(), raw["globalcontext"]);
|
||||
}
|
||||
if (raw.HasPath("rules") && raw["rules"].IsMap()) {
|
||||
for (auto r : raw["rules"].AsMap()) {
|
||||
std::shared_ptr<Rule> rule = Rule::createRule(retval.get(), r.first, retval->globalContext.get(), r.second, retval->executionService);
|
||||
if (rule) {
|
||||
retval->rules.insert({r.first, rule});
|
||||
}
|
||||
}
|
||||
if (retval->rules.size() == 0) {
|
||||
throw std::runtime_error("Rule package has no rules.");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Rule package JSON is missing rules parameter or parameter has wrong type.");
|
||||
}
|
||||
if (retval->rules.size() == 0) {
|
||||
throw std::runtime_error("Rule package has no rules.");
|
||||
}
|
||||
retval->setState(State::Ok);
|
||||
} else {
|
||||
throw std::runtime_error("Rule package JSON is missing rules parameter or parameter has wrong type.");
|
||||
retval->setState(State::NoExecService);
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Rule package JSON is not valid.");
|
||||
|
||||
@@ -13,19 +13,20 @@
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <Variant/Variant.h>
|
||||
#include <hos_cosgi_rulesengine/hos_rulesexecution_service.h>
|
||||
|
||||
|
||||
// Forward declarations
|
||||
namespace XmlRpc {
|
||||
class XmlRpcValue;
|
||||
}
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesengine {
|
||||
class HOSRulesEngineServiceImpl;
|
||||
class GlobalContext;
|
||||
class Rule;
|
||||
}
|
||||
namespace rulesexecution {
|
||||
class GlobalExecutionContext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,25 +36,38 @@ namespace cosgi {
|
||||
namespace rulesengine {
|
||||
|
||||
class RulePackage {
|
||||
public:
|
||||
enum class State : int { Error = 0, NoExecService = 1, Ok = 2 };
|
||||
|
||||
private:
|
||||
typedef std::map<std::string, std::shared_ptr<Rule>> ruleMap_t;
|
||||
|
||||
std::string name;
|
||||
std::string language;
|
||||
State state = State::Error;
|
||||
ruleMap_t rules;
|
||||
std::shared_ptr<GlobalContext> globalContext;
|
||||
HOSRulesEngineServiceImpl& parent;
|
||||
std::shared_ptr<rulesexecution::GlobalExecutionContext> globalContext;
|
||||
HOSRulesEngineServiceImpl* parent;
|
||||
rulesexecution::HOSRulesExecutionService* executionService = nullptr;
|
||||
|
||||
|
||||
bool setState(State state) {
|
||||
this->state = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
RulePackage(HOSRulesEngineServiceImpl& parent, std::string name);
|
||||
static std::shared_ptr<RulePackage> createRulePackage(HOSRulesEngineServiceImpl& parent, std::string name, XmlRpc::XmlRpcValue& raw);
|
||||
RulePackage(HOSRulesEngineServiceImpl* parent, std::string name);
|
||||
static std::shared_ptr<RulePackage> createRulePackage(HOSRulesEngineServiceImpl* parent, std::string name, ::libvariant::Variant raw);
|
||||
virtual ~RulePackage();
|
||||
|
||||
std::shared_ptr<Rule> getRule(const std::string& name) { return rules[name]; }
|
||||
size_t getRules(std::vector<std::shared_ptr<Rule>>& rules);
|
||||
|
||||
HOSRulesEngineServiceImpl& getParent() { return parent; }
|
||||
HOSRulesEngineServiceImpl* getParent() { return parent; }
|
||||
|
||||
State getState() { return state; }
|
||||
};
|
||||
|
||||
} /* namespace rulesengine */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"language": "python",
|
||||
"globalcontext": {},
|
||||
"globalcontext": { "code": "print \"GlobalContext: Init!\"\nvar1 = 66.6"},
|
||||
"rules": {
|
||||
"rule01": {
|
||||
"conditions": [
|
||||
@@ -13,7 +13,7 @@
|
||||
"deviceid": "huelight1"
|
||||
}
|
||||
],
|
||||
"body": "print \"Hello World1\""
|
||||
"body": { "code": "print \"Hello World1\"" }
|
||||
},
|
||||
"rule02": {
|
||||
"conditions": [
|
||||
@@ -26,7 +26,7 @@
|
||||
"deviceid": "huelight2"
|
||||
}
|
||||
],
|
||||
"body": "print \"Hello World2\""
|
||||
"body": { "code": "print \"Hello World2\"" }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ find_package(catkin REQUIRED COMPONENTS
|
||||
|
||||
find_package(APR REQUIRED)
|
||||
find_package(CELIX REQUIRED)
|
||||
find_package(Boost REQUIRED)
|
||||
find_package(Boost REQUIRED COMPONENTS python)
|
||||
|
||||
|
||||
################################################
|
||||
@@ -111,6 +111,7 @@ include_directories(
|
||||
${APR_INCLUDE_DIR}/apr-1.0
|
||||
include
|
||||
${hos_libvariant_INCLUDE_DIRS}/hos_libvariant
|
||||
/usr/include/python2.7
|
||||
)
|
||||
|
||||
set(BUNDLE_SYMBOLICNAME "hos.hos_rulesexecution_python")
|
||||
@@ -125,6 +126,8 @@ bundle(hos_cosgi_rulesexecution_python
|
||||
target_link_libraries(hos_cosgi_rulesexecution_python
|
||||
${catkin_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
python2.7
|
||||
)
|
||||
|
||||
## Declare a cpp library
|
||||
|
||||
@@ -27,6 +27,7 @@ extern "C" {
|
||||
|
||||
using namespace hos::cosgi::rulesengine;
|
||||
using namespace hos::cosgi::rulesexecution;
|
||||
using namespace hos::cosgi::rulesexecution::python;
|
||||
using namespace hos::cosgi::devicerepository;
|
||||
using namespace hos::cosgi::core;
|
||||
using namespace hos::cosgi;
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
#include <hos_cosgi_launcher/hos_core_service.h>
|
||||
|
||||
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesexecution {
|
||||
namespace python {
|
||||
|
||||
void HOSRulesExecutionPythonImpl::setCoreService(core::HOSCoreService* coreService) {
|
||||
if (coreService && !this->coreService) {
|
||||
@@ -40,6 +42,12 @@ void HOSRulesExecutionPythonImpl::setRepoService(devicerepository::HOSDeviceRepo
|
||||
}
|
||||
|
||||
void HOSRulesExecutionPythonImpl::init() {
|
||||
Py_Initialize();
|
||||
boost::python::object main_module = boost::python::import("__main__");
|
||||
pyGlobalScope = main_module.attr("__dict__");// Load the sys module.
|
||||
boost::python::object sys = boost::python::import("sys");
|
||||
std::string version = boost::python::extract<std::string>(sys.attr("version"));
|
||||
ROS_INFO_STREAM("RulesExecutionPythonService: Python Version: " << version);
|
||||
initialized = true;
|
||||
ROS_INFO_STREAM("RulesExecutionPythonService: Initialized and Ready.");
|
||||
}
|
||||
@@ -51,19 +59,44 @@ void HOSRulesExecutionPythonImpl::getServiceVersion(int& major, int& minor) {
|
||||
minor = SERVICE_VERSION_MINOR;
|
||||
}
|
||||
|
||||
std::shared_ptr<GlobalExecutionContext> HOSRulesExecutionPythonImpl::createGlobalExecutionContext(rulesengine::RulePackage* parent, XmlRpc::XmlRpcValue& raw) {
|
||||
std::shared_ptr<GlobalExecutionContext> retval;
|
||||
return retval;
|
||||
std::shared_ptr<GlobalExecutionContext> HOSRulesExecutionPythonImpl::createGlobalExecutionContext(rulesengine::RulePackage* parent, libvariant::Variant raw) {
|
||||
std::shared_ptr<PyGlobalExecutionContext> retval;
|
||||
if (raw.HasPath("code") && raw["code"].IsString()) {
|
||||
retval = std::make_shared<PyGlobalExecutionContext>(this->pyGlobalScope, raw["code"].AsString());
|
||||
try {
|
||||
boost::python::object result = boost::python::exec(retval->getCode().c_str(), pyGlobalScope);
|
||||
} catch(boost::python::error_already_set const &) {
|
||||
PyErr_Print();
|
||||
throw std::runtime_error("Python error during global context creation.");
|
||||
}
|
||||
}
|
||||
return std::static_pointer_cast<GlobalExecutionContext>(retval);
|
||||
}
|
||||
|
||||
std::shared_ptr<RuleBody> HOSRulesExecutionPythonImpl::createRuleBody(rulesengine::RulePackage* parent, XmlRpc::XmlRpcValue& raw) {
|
||||
std::shared_ptr<RuleBody> HOSRulesExecutionPythonImpl::createRuleBody(rulesengine::Rule* parent, GlobalExecutionContext* gContext, libvariant::Variant raw) {
|
||||
std::shared_ptr<RuleBody> retval;
|
||||
return retval;
|
||||
if (raw.HasPath("code") && raw["code"].IsString()) {
|
||||
retval = std::make_shared<PyRuleBody>(raw["code"].AsString(), *this);
|
||||
}
|
||||
return std::static_pointer_cast<RuleBody>(retval);
|
||||
}
|
||||
|
||||
|
||||
void PyRuleBody::exec(GlobalExecutionContext* gContext) {
|
||||
try {
|
||||
boost::python::object& gcont = service.getPyGlobalScope();
|
||||
if (gContext) {
|
||||
gcont = static_cast<PyGlobalExecutionContext*>(gContext)->getPyGlobalContext();
|
||||
}
|
||||
boost::python::object result = boost::python::exec(code.c_str(), gcont);
|
||||
} catch(boost::python::error_already_set const &) {
|
||||
PyErr_Print();
|
||||
throw std::runtime_error("Python error during global context creation.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace python
|
||||
} // namespace rulesengine
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
#include <hos_cosgi_rulesengine/hos_rulesexecution_service.h>
|
||||
#include <hos_cosgi_devicerepository/hos_devicerepository_service.h>
|
||||
#include <ros/ros.h>
|
||||
#include <Variant/Variant.h>
|
||||
#include <boost/python.hpp>
|
||||
#include <memory>
|
||||
|
||||
|
||||
// Forward declarations
|
||||
namespace XmlRpc {
|
||||
class XmlRpcValue;
|
||||
}
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace core {
|
||||
@@ -26,6 +26,11 @@ namespace devicerepository {
|
||||
class HOSDeviceRepositoryService;
|
||||
class DeviceEvent;
|
||||
}
|
||||
namespace rulesexecution {
|
||||
namespace python {
|
||||
class HOSRulesExecutionPythonImpl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +38,33 @@ class DeviceEvent;
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace rulesexecution {
|
||||
namespace python {
|
||||
|
||||
|
||||
|
||||
class PyGlobalExecutionContext : public GlobalExecutionContext {
|
||||
private:
|
||||
boost::python::object& gContext;
|
||||
std::string code;
|
||||
public:
|
||||
PyGlobalExecutionContext(boost::python::object& gContext, std::string code)
|
||||
: gContext(gContext), code(code) {}
|
||||
std::string getCode() { return code; }
|
||||
boost::python::object& getPyGlobalContext() { return gContext; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
class PyRuleBody : public RuleBody {
|
||||
private:
|
||||
std::string code;
|
||||
HOSRulesExecutionPythonImpl& service;
|
||||
public:
|
||||
PyRuleBody(std::string code, HOSRulesExecutionPythonImpl& service) : code(code), service(service) {}
|
||||
std::string getCode() { return code; }
|
||||
virtual void exec(GlobalExecutionContext* gContext);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class HOSRulesExecutionPythonImpl : public HOSRulesExecutionService {
|
||||
@@ -41,6 +73,8 @@ private:
|
||||
devicerepository::HOSDeviceRepositoryService* repoService = nullptr;;
|
||||
ros::NodeHandle* nodehandle = nullptr;
|
||||
|
||||
boost::python::object pyGlobalScope;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
void init();
|
||||
@@ -62,17 +96,19 @@ public:
|
||||
|
||||
virtual std::string getLanguage() { return LANGUAGE; }
|
||||
|
||||
virtual std::shared_ptr<GlobalExecutionContext> createGlobalExecutionContext(rulesengine::RulePackage* parent, XmlRpc::XmlRpcValue& raw);
|
||||
virtual std::shared_ptr<RuleBody> createRuleBody(rulesengine::RulePackage* parent, XmlRpc::XmlRpcValue& raw);
|
||||
virtual std::shared_ptr<GlobalExecutionContext> createGlobalExecutionContext(rulesengine::RulePackage* parent, libvariant::Variant raw);
|
||||
virtual std::shared_ptr<RuleBody> createRuleBody(rulesengine::Rule* parent, GlobalExecutionContext* gContext, libvariant::Variant raw);
|
||||
|
||||
/* Internal Stuff */
|
||||
|
||||
bool isInitialized() { return initialized; }
|
||||
|
||||
boost::python::object& getPyGlobalScope() { return pyGlobalScope; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace python
|
||||
} // namespace rulesengine
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<launch>
|
||||
<group ns="/hos/rules/rulesengine0">
|
||||
<param name="rulepkg01" textfile="$(find hos_cosgi_rulesengine)/test/rulepkg01.json"/>
|
||||
</group>
|
||||
<node name="cosgi_devicerepository" pkg="hos_cosgi_launcher" type="hos_cosgi_launcher" output="screen">
|
||||
<param name="autostart_bundles"
|
||||
value="$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_service.zip
|
||||
|
||||
Reference in New Issue
Block a user