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