This commit is contained in:
2015-05-04 00:54:03 +02:00
parent 782c00e296
commit 45b5d71c3f
566 changed files with 2806 additions and 804 deletions
Binary file not shown.
@@ -13,4 +13,8 @@
<group ns="/hos/types/repository/core/msgs"> <group ns="/hos/types/repository/core/msgs">
<param name="hosstatusupdate" textfile="$(find hos_core_types)/schema/core/msgs/hosstatusupdate.json"/> <param name="hosstatusupdate" textfile="$(find hos_core_types)/schema/core/msgs/hosstatusupdate.json"/>
</group> </group>
<group ns="/hos/types/repository/core/configs">
<param name="rulepackage" textfile="$(find hos_core_types)/schema/core/configs/rulepackage.json"/>
</group>
</launch> </launch>
@@ -0,0 +1,152 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Rule Package",
"description": "",
"version": "1.0.0",
"type": "object",
"properties": {
"language": {
"description": "",
"type": "string"
},
"globalcontext": {
"description": "",
"type": "object"
},
"rules": {
"description": "",
"type": "object",
"minProperties": 1,
"patternProperties": {
".*": {
"type": "object",
"properties": {
"body": {
"type": "string"
},
"conditions": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"anyOf": [
{ "$ref": "#/definitions/DeviceMsgCondition" },
{ "$ref": "#/definitions/DeviceStatusCondition" },
{ "$ref": "#/definitions/TimeCondition" },
{ "$ref": "#/definitions/SystemCondition" }
]
}
}
},
"additionalProperties": false,
"required": [ "name", "conditions", "body" ]
}
}
}
},
"definitions": {
"DeviceMsgCondition": {
"type": "object",
"properties": {
"type": {
"description": "",
"type": "string",
"pattern": "devicemsg"
},
"deviceid": {
"description": "",
"type": "string"
},
"msgtype": {
"description": "",
"type": "string",
"enum": ["status", "command"]
},
"msgpointer": {
"description": "",
"type": "string"
},
"msgvalue": {
"description": ""
}
},
"additionalProperties": false,
"anyOf": [
{ "required": [ "type", "deviceid" ] },
{ "required": [ "type", "deviceid", "msgtype", "msgvalue" ] },
{ "required": [ "type", "deviceid", "msgtype", "msgpointer" ] }
]
},
"DeviceStatusCondition": {
"type": "object",
"properties": {
"type": {
"description": "",
"type": "string",
"pattern": "devicestatus"
},
"deviceid": {
"description": "",
"type": "string"
},
"statuspointer": {
"description": "",
"type": "string"
},
"fromvalue": {
"description": ""
},
"tovalue": {
"description": ""
}
},
"additionalProperties": false,
"anyOf": [
{"required": [ "type", "deviceid" ] }
]
},
"TimeCondition": {
"type": "object",
"properties": {
"type": {
"description": "",
"type": "string",
"pattern": "time"
},
"cron": {
"description": "",
"type": "string"
},
"time": {
"description": ""
}
},
"additionalProperties": false,
"anyOf": [
{ "required": [ "type", "cron" ] },
{ "required": [ "type", "time" ] }
]
},
"SystemCondition": {
"type": "object",
"properties": {
"type": {
"description": "",
"type": "string",
"pattern": "systemevent"
},
"event": {
"description": "",
"type": "string",
"enum": [ "startup", "shutdown" ]
}
},
"additionalProperties": false,
"anyOf": [
{ "required": [ "type", "event" ] }
]
}
},
"additionalProperties": false,
"required": [ "language", "rules" ]
}
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 2.8.3) cmake_minimum_required(VERSION 2.8.3)
project(hos_cosgi_core) project(hos_cosgi_common)
## Find catkin macros and libraries ## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
@@ -79,7 +79,7 @@ find_package(catkin REQUIRED COMPONENTS
## DEPENDS: system dependencies of this project that dependent projects also need ## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package( catkin_package(
INCLUDE_DIRS include INCLUDE_DIRS include
# LIBRARIES hos_cosgi_core # LIBRARIES hos_cosgi_common
CATKIN_DEPENDS hos_celix CATKIN_DEPENDS hos_celix
# DEPENDS system_lib # DEPENDS system_lib
) )
@@ -96,19 +96,19 @@ include_directories(
) )
## Declare a cpp library ## Declare a cpp library
# add_library(hos_cosgi_core # add_library(hos_cosgi_common
# src/${PROJECT_NAME}/hos_cosgi_core.cpp # src/${PROJECT_NAME}/hos_cosgi_common.cpp
# ) # )
## Declare a cpp executable ## Declare a cpp executable
# add_executable(hos_cosgi_core_node src/hos_cosgi_core_node.cpp) # add_executable(hos_cosgi_common_node src/hos_cosgi_common_node.cpp)
## Add cmake target dependencies of the executable/library ## Add cmake target dependencies of the executable/library
## as an example, message headers may need to be generated before nodes ## as an example, message headers may need to be generated before nodes
# add_dependencies(hos_cosgi_core_node hos_cosgi_core_generate_messages_cpp) # add_dependencies(hos_cosgi_common_node hos_cosgi_common_generate_messages_cpp)
## Specify libraries to link a library or executable target against ## Specify libraries to link a library or executable target against
# target_link_libraries(hos_cosgi_core_node # target_link_libraries(hos_cosgi_common_node
# ${catkin_LIBRARIES} # ${catkin_LIBRARIES}
# ) # )
@@ -127,7 +127,7 @@ include_directories(
# ) # )
## Mark executables and/or libraries for installation ## Mark executables and/or libraries for installation
# install(TARGETS hos_cosgi_core hos_cosgi_core_node # install(TARGETS hos_cosgi_common hos_cosgi_common_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} # ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} # LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
@@ -152,7 +152,7 @@ install(DIRECTORY include/${PROJECT_NAME}/
############# #############
## Add gtest based cpp test target and link libraries ## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_hos_cosgi_core.cpp) # catkin_add_gtest(${PROJECT_NAME}-test test/test_hos_cosgi_common.cpp)
# if(TARGET ${PROJECT_NAME}-test) # if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) # target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif() # endif()
@@ -1,12 +1,12 @@
/* /*
* cosgi_core.h * cosgi_common.h
* *
* Created on: 19.04.2015 * Created on: 19.04.2015
* Author: matzman * Author: matzman
*/ */
#ifndef INCLUDE_HOS_COSGI_CORE_COSGI_CORE_H_ #ifndef INCLUDE_HOS_COSGI_COMMON_COSGI_CORE_H_
#define INCLUDE_HOS_COSGI_CORE_COSGI_CORE_H_ #define INCLUDE_HOS_COSGI_COMMON_COSGI_CORE_H_
namespace hos { namespace hos {
@@ -29,4 +29,4 @@ public:
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
#endif /* INCLUDE_HOS_COSGI_CORE_COSGI_CORE_H_ */ #endif /* INCLUDE_HOS_COSGI_COMMON_COSGI_CORE_H_ */
@@ -1,8 +1,8 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<package> <package>
<name>hos_cosgi_core</name> <name>hos_cosgi_common</name>
<version>0.0.0</version> <version>0.0.0</version>
<description>The hos_cosgi_core package</description> <description>The hos_cosgi_common package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag --> <!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: --> <!-- Example: -->
@@ -19,7 +19,7 @@
<!-- Url tags are optional, but mutiple are allowed, one per tag --> <!-- Url tags are optional, but mutiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository --> <!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: --> <!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/hos_cosgi_core</url> --> <!-- <url type="website">http://wiki.ros.org/hos_cosgi_common</url> -->
<!-- Author tags are optional, mutiple are allowed, one per tag --> <!-- Author tags are optional, mutiple are allowed, one per tag -->
@@ -8,7 +8,7 @@ find_package(catkin REQUIRED COMPONENTS
hos_celix hos_celix
hos_core_msgs hos_core_msgs
hos_cosgi_launcher hos_cosgi_launcher
hos_cosgi_core hos_cosgi_common
hos_libvariant hos_libvariant
hos_cpp_common hos_cpp_common
roscpp roscpp
@@ -91,7 +91,7 @@ find_package(Boost REQUIRED)
catkin_package( catkin_package(
INCLUDE_DIRS include INCLUDE_DIRS include
# LIBRARIES hos_cosgi_devicerepository # LIBRARIES hos_cosgi_devicerepository
CATKIN_DEPENDS hos_celix hos_core_msgs hos_cosgi_launcher roscpp hos_cosgi_core hos_libvariant hos_cpp_common CATKIN_DEPENDS hos_celix hos_core_msgs hos_cosgi_launcher roscpp hos_cosgi_common hos_libvariant hos_cpp_common
# DEPENDS system_lib # DEPENDS system_lib
) )
@@ -122,7 +122,6 @@ bundle(hos_cosgi_devicerepository
SOURCES SOURCES
${PROJECT_SOURCE_DIR}/src/bundle_activator ${PROJECT_SOURCE_DIR}/src/bundle_activator
${PROJECT_SOURCE_DIR}/src/hos_devicerepository_service_impl ${PROJECT_SOURCE_DIR}/src/hos_devicerepository_service_impl
${PROJECT_SOURCE_DIR}/src/HosSchemaLoader
) )
target_link_libraries(hos_cosgi_devicerepository target_link_libraries(hos_cosgi_devicerepository
${catkin_LIBRARIES} ${catkin_LIBRARIES}
@@ -2,64 +2,87 @@
#define _HOS_DEVICEREPOSITORY_SERVICE_H_ #define _HOS_DEVICEREPOSITORY_SERVICE_H_
#include <hos_cosgi_core/cosgi_core.h> #include <hos_cosgi_common/cosgi_common.h>
#include <hos_cpp_common/observable.h> #include <hos_cpp_common/observable.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <memory>
// Forward declarations
namespace libvariant { namespace libvariant {
class Variant; class Variant;
}
namespace hos {
namespace cosgi {
namespace devicerepository {
class Device;
}
}
} }
// Service Namespace
namespace hos { namespace hos {
namespace cosgi { namespace cosgi {
namespace devicerepository {
class DeviceEvent;
class GenericDevice;
/**
* Base class for device events
**/
class DeviceEvent { class DeviceEvent {
public: public:
enum class EventType : int { DEVICE_ADDED = 1, DEVICE_REMOVED = 2, STATUS_UPDATED = 3, COMMAND_RECEIVED = 4 }; enum class EventType : int { DEVICE_ADDED = 1, DEVICE_REMOVED = 2, STATUS_UPDATED = 3, COMMAND_RECEIVED = 4 };
DeviceEvent(GenericDevice* device, EventType type) : device(device), eventType(type) {} const EventType eventType;
GenericDevice* device; Device* const device;
EventType eventType; DeviceEvent(Device* device, EventType type) : device(device), eventType(type) {}
template<class T> T* as() { return (T*)this; }
template<class T> const T* as() const { return (T*)this; }
}; };
/**
* Device added
**/
class DeviceAddedEvent : public DeviceEvent { class DeviceAddedEvent : public DeviceEvent {
public: public:
DeviceAddedEvent(GenericDevice* device) DeviceAddedEvent(Device* device) : DeviceEvent(device, DeviceEvent::EventType::DEVICE_ADDED) {}
: DeviceEvent(device, DeviceEvent::EventType::DEVICE_ADDED) {}
}; };
/**
* Device removed
**/
class DeviceRemovedEvent : public DeviceEvent { class DeviceRemovedEvent : public DeviceEvent {
public: public:
DeviceRemovedEvent(GenericDevice* device) DeviceRemovedEvent(Device* device) : DeviceEvent(device, DeviceEvent::EventType::DEVICE_REMOVED) {}
: DeviceEvent(device, DeviceEvent::EventType::DEVICE_REMOVED) {}
}; };
class DeviceStatusEvent : public DeviceEvent { /**
* Device status message received
**/
class DeviceStatusMsgEvent : public DeviceEvent {
public: public:
DeviceStatusEvent(GenericDevice* device, const libvariant::Variant& statusMsg) DeviceStatusMsgEvent(Device* device, const libvariant::Variant& statusMsg)
: DeviceEvent(device, DeviceEvent::EventType::STATUS_UPDATED), statusMsg(statusMsg) {} : DeviceEvent(device, DeviceEvent::EventType::STATUS_UPDATED), statusMsg(statusMsg) {}
const libvariant::Variant& statusMsg; const libvariant::Variant& statusMsg;
}; };
class DeviceCmdEvent : public DeviceEvent { /**
* Device command message received
**/
class DeviceCmdMsgEvent : public DeviceEvent {
public: public:
DeviceCmdEvent(GenericDevice* device, const libvariant::Variant& cmdMsg) DeviceCmdMsgEvent(Device* device, const libvariant::Variant& cmdMsg)
: DeviceEvent(device, DeviceEvent::EventType::COMMAND_RECEIVED), cmdMsg(cmdMsg) {} : DeviceEvent(device, DeviceEvent::EventType::COMMAND_RECEIVED), cmdMsg(cmdMsg) {}
const libvariant::Variant& cmdMsg; const libvariant::Variant& cmdMsg;
}; };
class GenericDevice : public COSGI_Object_Interface, public common::IObservable<DeviceEvent> { /**
* Public interface of an device object
**/
class Device : public COSGI_Object_Interface, public common::IObservable<DeviceEvent> {
public: public:
virtual const std::string& getDeviceID() = 0; virtual const std::string& getDeviceID() = 0;
virtual const std::string& getDeviceType() = 0; virtual const std::string& getDeviceType() = 0;
@@ -71,18 +94,26 @@ public:
}; };
/**
* Public Interface of the device repository service
**/
class HOSDeviceRepositoryService : public COSGI_Service_Interface, public common::IObservable<DeviceEvent> { class HOSDeviceRepositoryService : public COSGI_Service_Interface, public common::IObservable<DeviceEvent> {
public: public:
static constexpr const char* SERVICE_NAME = "hos_devicerepository_service"; static constexpr const char* SERVICE_NAME = "hos_devicerepository_service";
static constexpr int SERVICE_VERSION_MAJOR = 1; static constexpr int SERVICE_VERSION_MAJOR = 1;
static constexpr int SERVICE_VERSION_MINOR = 0; static constexpr int SERVICE_VERSION_MINOR = 0;
virtual GenericDevice* getDevice(std::string device_id) = 0; virtual std::shared_ptr<Device> getDevice(std::string device_id) = 0;
virtual std::vector<GenericDevice*>& getDevices(std::vector<GenericDevice*>& devices) = 0; virtual size_t getDevices(std::vector<std::shared_ptr<Device>>& devices) = 0;
}; };
} // namespace devicerepository
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
#endif /* _HOS_DEVICEREPOSITORY_SERVICE_H_ */ #endif /* _HOS_DEVICEREPOSITORY_SERVICE_H_ */
@@ -1,5 +1,5 @@
<launch> <launch>
<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" value="$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_devicerepository/hos_cosgi_devicerepository.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell_tui.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_service.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer_syslog.zip"/> <param name="autostart_bundles" value="$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_devicerepository/hos_cosgi_devicerepository.zip $(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_rulesexecution_python/hos_cosgi_rulesexecution_python.zip $(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_rulesengine/hos_cosgi_rulesengine.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell_tui.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_service.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer_syslog.zip"/>
</node> </node>
</launch> </launch>
+2 -2
View File
@@ -44,14 +44,14 @@
<build_depend>hos_core_msgs</build_depend> <build_depend>hos_core_msgs</build_depend>
<build_depend>hos_cosgi_launcher</build_depend> <build_depend>hos_cosgi_launcher</build_depend>
<build_depend>roscpp</build_depend> <build_depend>roscpp</build_depend>
<build_depend>hos_cosgi_core</build_depend> <build_depend>hos_cosgi_common</build_depend>
<build_depend>hos_libvariant</build_depend> <build_depend>hos_libvariant</build_depend>
<build_depend>hos_cpp_common</build_depend> <build_depend>hos_cpp_common</build_depend>
<run_depend>hos_celix</run_depend> <run_depend>hos_celix</run_depend>
<run_depend>hos_core_msgs</run_depend> <run_depend>hos_core_msgs</run_depend>
<run_depend>hos_cosgi_launcher</run_depend> <run_depend>hos_cosgi_launcher</run_depend>
<run_depend>roscpp</run_depend> <run_depend>roscpp</run_depend>
<run_depend>hos_cosgi_core</run_depend> <run_depend>hos_cosgi_common</run_depend>
<run_depend>hos_libvariant</run_depend> <run_depend>hos_libvariant</run_depend>
<run_depend>hos_cpp_common</run_depend> <run_depend>hos_cpp_common</run_depend>
@@ -14,65 +14,18 @@ extern "C" {
#include <hos_cosgi_launcher/hos_core_service.h> #include <hos_cosgi_launcher/hos_core_service.h>
#include "hos_devicerepository_service_impl.h" #include "hos_devicerepository_service_impl.h"
using namespace hos::cosgi;
#include <hos_cpp_common/observable.h> #include <hos_cpp_common/observable.h>
#include <iostream> #include <iostream>
#include <memory>
class Test01 : public hos::common::IObserver<DeviceEvent> {
public:
void notificationReceived(hos::common::IObservable<DeviceEvent>& o, const DeviceEvent* e) {
switch (e->eventType) {
case DeviceEvent::EventType::DEVICE_ADDED:
{
std::cout << "DeviceEvent: Device added: " << e->device->getDeviceID() << std::endl;
}
break;
case DeviceEvent::EventType::DEVICE_REMOVED:
{
std::cout << "DeviceEvent: Device removed: " << e->device->getDeviceID() << std::endl;
}
break;
case DeviceEvent::EventType::STATUS_UPDATED:
{
auto event = e->as<DeviceStatusEvent>();
std::cout << "DeviceEvent: Device Updated: " << e->device->getDeviceID() << std::endl;
std::cout << "message: ";
libvariant::SerializeJSON(stdout, event->statusMsg, true);
std::cout << std::endl;
std::cout << "current: ";
libvariant::SerializeJSON(stdout, event->device->getCurrentState(), true);
std::cout << std::endl;
std::cout << "last: ";
libvariant::SerializeJSON(stdout, event->device->getLastState(), true);
std::cout << std::endl;
}
break;
case DeviceEvent::EventType::COMMAND_RECEIVED:
{
auto event = e->as<DeviceStatusEvent>();
std::cout << "DeviceEvent: Device Command: " << e->device->getDeviceID() << std::endl;
std::cout << "message: ";
libvariant::SerializeJSON(stdout, event->statusMsg, true);
std::cout << std::endl;
}
break;
default:
{
std::cout << "DeviceEvent: Unknown event." << std::endl;
}
break;
};
}
} test01;
using namespace hos::cosgi;
using namespace hos::cosgi::devicerepository;
struct UserData { struct UserData {
apr_pool_t* memoryPool = nullptr; apr_pool_t* memoryPool = nullptr;
hos::cosgi::HOSDeviceRepositoryServiceImpl* serviceImpl = nullptr; std::unique_ptr<HOSDeviceRepositoryServiceImpl> serviceImpl;
service_registration_pt serviceReg = nullptr; service_registration_pt serviceReg = nullptr;
}; };
@@ -100,33 +53,29 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData
} }
celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
celix_status_t status = CELIX_START_ERROR; celix_status_t status = CELIX_SUCCESS;
if (userData != nullptr) { if (userData != nullptr) {
UserData* myUserData = (UserData*)userData; UserData* myUserData = (UserData*)userData;
// Create hos-devicerepository-service
if (myUserData->serviceReg != nullptr) {
serviceRegistration_unregister(myUserData->serviceReg);
}
myUserData->serviceImpl.reset(new HOSDeviceRepositoryServiceImpl());
// Get HOS Core Service // Get HOS Core Service
service_reference_pt ref = nullptr; service_reference_pt ref = nullptr;
bundleContext_getServiceReference(context, (char*)HOSCoreService::SERVICE_NAME, &ref); bundleContext_getServiceReference(context, (char*)core::HOSCoreService::SERVICE_NAME, &ref);
hos::cosgi::HOSCoreService* coreService = nullptr; core::HOSCoreService* coreService = nullptr;
bundleContext_getService(context, ref, (void**)&coreService); bundleContext_getService(context, ref, (void**)&coreService);
if (coreService == nullptr) { if (coreService == nullptr) {
ROS_ERROR("DeviceRepositoryService: Could not retrieve HOSCoreService."); ROS_ERROR("DeviceRepositoryService: Could not retrieve HOSCoreService. Are you using hos_cosgi_launcher?");
} else { } else {
int major = 0, minor = 0; myUserData->serviceImpl->setCoreService(coreService);
coreService->getServiceVersion(major, minor);
ROS_INFO_STREAM("DeviceRepositoryService: Found HOSCoreService Version " << major << "." << minor);
// Create and register hos-devicerepository-service
if (myUserData->serviceReg != nullptr) {
serviceRegistration_unregister(myUserData->serviceReg);
}
if (myUserData->serviceImpl != nullptr) {
delete myUserData->serviceImpl;
}
myUserData->serviceImpl = new hos::cosgi::HOSDeviceRepositoryServiceImpl(*coreService);
myUserData->serviceImpl->addObserver(test01);
bundleContext_registerService(context, (char*)hos::cosgi::HOSDeviceRepositoryService::SERVICE_NAME, myUserData->serviceImpl, nullptr, &myUserData->serviceReg);
status = CELIX_SUCCESS;
ROS_INFO("DeviceRepositoryService: Bundle successfully started");
} }
// Register hos-devicerepository-service
if (myUserData->serviceImpl->isInitialized()) {
bundleContext_registerService(context, (char*)HOSDeviceRepositoryService::SERVICE_NAME, myUserData->serviceImpl.get(), nullptr, &myUserData->serviceReg);
}
ROS_INFO("DeviceRepositoryService: Bundle successfully started");
} else { } else {
ROS_ERROR("DeviceRepositoryService: Could not start bundle, user data struct is null"); ROS_ERROR("DeviceRepositoryService: Could not start bundle, user data struct is null");
} }
@@ -138,16 +87,11 @@ celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context)
if (userData != nullptr) { if (userData != nullptr) {
UserData* myUserData = (UserData*)userData; UserData* myUserData = (UserData*)userData;
if (myUserData->serviceReg != nullptr) { if (myUserData->serviceReg != nullptr) {
if (myUserData->serviceImpl->getRefCount() > 0) {
frameworkLogger_log(OSGI_FRAMEWORK_LOG_ERROR, 0, 0, 0, (char*)"RefCount > 0");
return status;
}
serviceRegistration_unregister(myUserData->serviceReg); serviceRegistration_unregister(myUserData->serviceReg);
myUserData->serviceReg = nullptr; myUserData->serviceReg = nullptr;
} }
if (myUserData->serviceImpl != nullptr) { if (myUserData->serviceImpl) {
delete myUserData->serviceImpl; myUserData->serviceImpl.reset();
myUserData->serviceImpl = nullptr;
} }
ROS_INFO("DeviceRepositoryService: Bundle successfully stopped"); ROS_INFO("DeviceRepositoryService: Bundle successfully stopped");
status = CELIX_SUCCESS; status = CELIX_SUCCESS;
@@ -7,44 +7,57 @@
#include "hos_devicerepository_service_impl.h" #include "hos_devicerepository_service_impl.h"
#include <hos_cosgi_launcher/hos_core_service.h> #include <hos_cosgi_launcher/hos_core_service.h>
#include "HosSchemaLoader.h"
#include <ros/ros.h> #include <ros/ros.h>
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <unordered_set> #include <unordered_set>
namespace hos { namespace hos {
namespace cosgi { namespace cosgi {
namespace devicerepository {
GenericDeviceImpl::GenericDeviceImpl(std::string deviceID, std::string type, std::string statusTopic, std::string cmdTopic) DeviceImpl::DeviceImpl(std::string deviceID, std::string type, std::string statusTopic, std::string cmdTopic)
: deviceID(deviceID), deviceType(type), statusTopic(statusTopic), cmdTopic(cmdTopic) { : deviceID(deviceID), deviceType(type), statusTopic(statusTopic), cmdTopic(cmdTopic) {
std::cout << "GenericDeviceImpl(" << deviceID << ", " << type << ", " << statusTopic << ", " << cmdTopic << ")" << std::endl; std::cout << "GenericDeviceImpl(" << deviceID << ", " << type << ", " << statusTopic << ", " << cmdTopic << ")" << std::endl;
} }
void GenericDeviceImpl::handleStatusMsg(libvariant::Variant& msg) { void DeviceImpl::handleStatusMsg(Variant& msg) {
std::lock_guard<std::mutex> lock(objMutex);
lastState = currentState.Copy(); lastState = currentState.Copy();
currentState.Merge(msg); currentState.Merge(msg);
DeviceStatusEvent event(this, msg); DeviceStatusMsgEvent event(this, msg);
notifyObservers(&event); notifyObservers(&event);
} }
void GenericDeviceImpl::handleCommandMsg(libvariant::Variant& msg) { void DeviceImpl::handleCommandMsg(Variant& msg) {
DeviceCmdEvent event(this, msg); std::lock_guard<std::mutex> lock(objMutex);
DeviceCmdMsgEvent event(this, msg);
notifyObservers(&event); notifyObservers(&event);
} }
void HOSDeviceRepositoryServiceImpl::setCoreService(core::HOSCoreService* coreService) {
if (coreService && !this->coreService) {
this->coreService = coreService;
this->nodehandle = coreService->getPrivateNodeHandle();
int major = 0, minor = 0;
coreService->getServiceVersion(major, minor);
ROS_INFO_STREAM("DeviceRepositoryService: Found HOSCoreService Version " << major << "." << minor);
init();
}
}
HOSDeviceRepositoryServiceImpl::HOSDeviceRepositoryServiceImpl(HOSCoreService& coreService) void HOSDeviceRepositoryServiceImpl::init() {
: coreService(coreService), nodehandle(coreService.getPrivateNodeHandle()) { nodehandle->getParam("device_repository_prefix", deviceRepositoryPrefix);
nodehandle.getParam("device_repository_prefix", deviceRepositoryPrefix); nodehandle->getParam("hos_status_topic", hosStatusTopic);
nodehandle.getParam("hos_status_topic", hosStatusTopic);
XmlRpc::XmlRpcValue rawValue; XmlRpc::XmlRpcValue rawValue;
nodehandle.getParam(deviceRepositoryPrefix, rawValue); nodehandle->getParam(deviceRepositoryPrefix, rawValue);
if (rawValue.getType() == XmlRpc::XmlRpcValue::TypeStruct) { if (rawValue.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
for (auto iter = rawValue.begin(); iter != rawValue.end(); iter++) { for (auto dev : rawValue) {
std::string devname = (*iter).first; std::string devname = dev.first;
XmlRpc::XmlRpcValue devRaw = (*iter).second; XmlRpc::XmlRpcValue devRaw = dev.second;
try { try {
addDevice(devname, devRaw); addDevice(devname, devRaw);
ROS_INFO_STREAM("Created device " << devname << "."); ROS_INFO_STREAM("Created device " << devname << ".");
@@ -53,47 +66,22 @@ HOSDeviceRepositoryServiceImpl::HOSDeviceRepositoryServiceImpl(HOSCoreService& c
} }
} }
} }
hosStatusSub = nodehandle.subscribe(hosStatusTopic, 1000, &HOSDeviceRepositoryServiceImpl::hosStatusMsgCallback, this); hosStatusSub = nodehandle->subscribe(hosStatusTopic, 1000, &HOSDeviceRepositoryServiceImpl::hosStatusMsgCallback, this);
schemaLoader = new HosSchemaLoader(); schemaLoader.reset(new libvariant::HosSchemaLoader());
initialized = true;
ROS_INFO_STREAM("DeviceRepositoryService: Initialized and Ready.");
} }
void HOSDeviceRepositoryServiceImpl::addDevice(std::string name) { void HOSDeviceRepositoryServiceImpl::addDevice(std::string name) {
std::stringstream ss; std::stringstream ss;
ss << deviceRepositoryPrefix << "/" << name; ss << deviceRepositoryPrefix << "/" << name;
XmlRpc::XmlRpcValue rawValue; XmlRpc::XmlRpcValue rawValue;
nodehandle.getParam(ss.str(), rawValue); nodehandle->getParam(ss.str(), rawValue);
addDevice(name, rawValue); addDevice(name, rawValue);
} }
void HOSDeviceRepositoryServiceImpl::addDevice(std::string name, XmlRpc::XmlRpcValue& rawValue) { void HOSDeviceRepositoryServiceImpl::addDevice(std::string name, XmlRpc::XmlRpcValue& rawValue) {
GenericDevice* dev = _createDevice(name, rawValue); std::lock_guard<std::recursive_mutex> lock(serviceMutex);
if (dev != nullptr) {
devices.insert({name, dev});
// cmd topic
auto& entry = subscripedTopics[dev->getCmdTopic()];
std::cout << "subCount1: " << entry.first << "." << std::endl;
if (entry.first <= 0) {
entry.second = nodehandle.subscribe(dev->getCmdTopic(), 1000, &HOSDeviceRepositoryServiceImpl::cmdMsgCallback, this);
std::cout << "subscriped to " << dev->getCmdTopic() << "." << std::endl;
}
entry.first= entry.first + 1;
subscripedTopics[dev->getCmdTopic()] = entry;
// status topic
entry = subscripedTopics[dev->getStatusTopic()];
std::cout << "subCount2: " << entry.first << "." << std::endl;
if (entry.first <= 0) {
entry.second = nodehandle.subscribe(dev->getStatusTopic(), 1000, &HOSDeviceRepositoryServiceImpl::statusMsgCallback, this);
std::cout << "subscriped to " << dev->getStatusTopic() << "." << std::endl;
}
entry.first= entry.first + 1;
subscripedTopics[dev->getStatusTopic()] = entry;
DeviceAddedEvent event(dev);
notifyObservers(&event);
}
}
GenericDevice* HOSDeviceRepositoryServiceImpl::_createDevice(std::string name, XmlRpc::XmlRpcValue& rawValue) {
std::string type, statusTopic, cmdTopic; std::string type, statusTopic, cmdTopic;
XmlRpc::XmlRpcValue& typeRaw = rawValue["type"]; XmlRpc::XmlRpcValue& typeRaw = rawValue["type"];
if (typeRaw.getType() != XmlRpc::XmlRpcValue::TypeString) { if (typeRaw.getType() != XmlRpc::XmlRpcValue::TypeString) {
@@ -110,31 +98,56 @@ GenericDevice* HOSDeviceRepositoryServiceImpl::_createDevice(std::string name, X
throw std::runtime_error("cmdTopic is not a string."); throw std::runtime_error("cmdTopic is not a string.");
} }
cmdTopic = static_cast<std::string>(cmdTopicRaw); cmdTopic = static_cast<std::string>(cmdTopicRaw);
return new GenericDeviceImpl(name, type, statusTopic, cmdTopic); std::shared_ptr<DeviceImpl> dev = std::make_shared<DeviceImpl>(name, type, statusTopic, cmdTopic);
devices.insert({name, dev});
// cmd topic
auto& entry = subscripedTopics[dev->getCmdTopic()];
std::cout << "subCount1: " << entry.first << "." << std::endl;
if (entry.first <= 0) {
entry.second = nodehandle->subscribe(dev->getCmdTopic(), 1000, &HOSDeviceRepositoryServiceImpl::cmdMsgCallback, this);
std::cout << "subscriped to " << dev->getCmdTopic() << "." << std::endl;
}
entry.first= entry.first + 1;
subscripedTopics[dev->getCmdTopic()] = entry;
// status topic
entry = subscripedTopics[dev->getStatusTopic()];
std::cout << "subCount2: " << entry.first << "." << std::endl;
if (entry.first <= 0) {
entry.second = nodehandle->subscribe(dev->getStatusTopic(), 1000, &HOSDeviceRepositoryServiceImpl::statusMsgCallback, this);
std::cout << "subscriped to " << dev->getStatusTopic() << "." << std::endl;
}
entry.first= entry.first + 1;
subscripedTopics[dev->getStatusTopic()] = entry;
// send device added event
DeviceAddedEvent event(dev.get());
notifyObservers(&event);
} }
void HOSDeviceRepositoryServiceImpl::removeDevice(std::string name) { void HOSDeviceRepositoryServiceImpl::removeDevice(std::string name) {
GenericDevice* dev = devices[name]; std::lock_guard<std::recursive_mutex> lock(serviceMutex);
if (dev != nullptr) { auto& dev = devices[name];
DeviceRemovedEvent event(dev); if (dev) {
DeviceRemovedEvent event(dev.get());
notifyObservers(&event); notifyObservers(&event);
dev->notifyObservers(&event); dev->notifyObservers(&event);
devices.erase(name); devices.erase(name);
delete dev;
} }
} }
GenericDevice* HOSDeviceRepositoryServiceImpl::getDevice(std::string device_id) { std::shared_ptr<Device> HOSDeviceRepositoryServiceImpl::getDevice(std::string device_id) {
return this->devices[device_id]; return std::static_pointer_cast<Device>(this->devices[device_id]);
} }
std::vector<GenericDevice*>& HOSDeviceRepositoryServiceImpl::getDevices(std::vector<GenericDevice*>& devices) { size_t HOSDeviceRepositoryServiceImpl::getDevices(std::vector<std::shared_ptr<Device>>& devices) {
std::lock_guard<std::recursive_mutex> lock(serviceMutex);
size_t retval = 0;
for (auto item : this->devices) { for (auto item : this->devices) {
devices.push_back(item.second); devices.push_back(std::static_pointer_cast<Device>(item.second));
retval++;
} }
return devices; return retval;
} }
@@ -143,21 +156,18 @@ void HOSDeviceRepositoryServiceImpl::getServiceVersion(int& major, int& minor) {
minor = SERVICE_VERSION_MINOR; minor = SERVICE_VERSION_MINOR;
} }
int HOSDeviceRepositoryServiceImpl::getRefCount() {
return 0;
}
void HOSDeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::DeviceStatusUpdate::ConstPtr& msg) { void HOSDeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::DeviceStatusUpdate::ConstPtr& msg) {
std::lock_guard<std::recursive_mutex> lock(serviceMutex);
std::cout << "HOSDeviceRepositoryServiceImpl::statusMsgCallback" << std::endl; std::cout << "HOSDeviceRepositoryServiceImpl::statusMsgCallback" << std::endl;
libvariant::Variant s = schemaLoader->GetSchema(std::string("hos:schema://").append(msg->device_type).append("/status")); Variant s = schemaLoader->GetSchema(std::string("hos:schema://").append(msg->device_type).append("/status"));
libvariant::Variant m = libvariant::Deserialize(msg->msg_body, libvariant::SERIALIZE_JSON); Variant m = Deserialize(msg->msg_body, SERIALIZE_JSON);
libvariant::SchemaResult sr = libvariant::SchemaValidate(s, m, schemaLoader); SchemaResult sr = SchemaValidate(s, m, schemaLoader.get());
if (!sr.Error()) { if (!sr.Error()) {
GenericDevice* dev = devices[msg->device_id]; std::shared_ptr<DeviceImpl> dev = std::static_pointer_cast<DeviceImpl>(devices[msg->device_id]);
if (dev != nullptr) { if (dev) {
((GenericDeviceImpl*)dev)->handleStatusMsg(m); dev->handleStatusMsg(m);
DeviceStatusEvent event(dev, m); DeviceStatusMsgEvent event(dev.get(), m);
notifyObservers(&event); notifyObservers(&event);
} }
} else { } else {
@@ -166,15 +176,16 @@ void HOSDeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::Devi
} }
void HOSDeviceRepositoryServiceImpl::cmdMsgCallback(const hos_core_msgs::DeviceCommand::ConstPtr& msg) { void HOSDeviceRepositoryServiceImpl::cmdMsgCallback(const hos_core_msgs::DeviceCommand::ConstPtr& msg) {
std::lock_guard<std::recursive_mutex> lock(serviceMutex);
std::cout << "HOSDeviceRepositoryServiceImpl::cmdMsgCallback" << std::endl; std::cout << "HOSDeviceRepositoryServiceImpl::cmdMsgCallback" << std::endl;
libvariant::Variant s = schemaLoader->GetSchema(std::string("hos:schema://").append(msg->device_type).append("/command")); Variant s = schemaLoader->GetSchema(std::string("hos:schema://").append(msg->device_type).append("/command"));
libvariant::Variant m = libvariant::Deserialize(msg->msg_body, libvariant::SERIALIZE_JSON); Variant m = Deserialize(msg->msg_body, SERIALIZE_JSON);
libvariant::SchemaResult sr = libvariant::SchemaValidate(s, m, schemaLoader); SchemaResult sr = SchemaValidate(s, m, schemaLoader.get());
if (!sr.Error()) { if (!sr.Error()) {
GenericDevice* dev = devices[msg->device_id]; std::shared_ptr<DeviceImpl> dev = std::static_pointer_cast<DeviceImpl>(devices[msg->device_id]);
if (dev != nullptr) { if (dev != nullptr) {
((GenericDeviceImpl*)dev)->handleCommandMsg(m); dev->handleCommandMsg(m);
DeviceCmdEvent event(dev, m); DeviceCmdMsgEvent event(dev.get(), m);
notifyObservers(&event); notifyObservers(&event);
} }
} else { } else {
@@ -183,10 +194,11 @@ void HOSDeviceRepositoryServiceImpl::cmdMsgCallback(const hos_core_msgs::DeviceC
} }
void HOSDeviceRepositoryServiceImpl::hosStatusMsgCallback(const hos_core_msgs::HosStatusUpdate::ConstPtr& msg) { void HOSDeviceRepositoryServiceImpl::hosStatusMsgCallback(const hos_core_msgs::HosStatusUpdate::ConstPtr& msg) {
std::lock_guard<std::recursive_mutex> lock(serviceMutex);
std::cout << "HOSDeviceRepositoryServiceImpl::hosStatusMsgCallback" << std::endl; std::cout << "HOSDeviceRepositoryServiceImpl::hosStatusMsgCallback" << std::endl;
libvariant::Variant s = schemaLoader->GetSchema(std::string("hos:schema://core/msgs/hosstatusupdate")); Variant s = schemaLoader->GetSchema(std::string("hos:schema://core/msgs/hosstatusupdate"));
libvariant::Variant m = libvariant::Deserialize(msg->msg_body, libvariant::SERIALIZE_JSON); Variant m = Deserialize(msg->msg_body, SERIALIZE_JSON);
libvariant::SchemaResult sr = libvariant::SchemaValidate(s, m, schemaLoader); SchemaResult sr = SchemaValidate(s, m, schemaLoader.get());
if (!sr.Error()) { if (!sr.Error()) {
if (m.Contains("devices")) { if (m.Contains("devices")) {
auto d = m["devices"]; auto d = m["devices"];
@@ -217,6 +229,7 @@ void HOSDeviceRepositoryServiceImpl::hosStatusMsgCallback(const hos_core_msgs::H
} }
} // namespace devicerepository
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
@@ -10,94 +10,136 @@
#include <Variant/Variant.h> #include <Variant/Variant.h>
#include <hos_cosgi_devicerepository/hos_devicerepository_service.h> #include <hos_cosgi_devicerepository/hos_devicerepository_service.h>
#include <HosSchemaLoader/HosSchemaLoader.h>
#include <mutex> #include <mutex>
#include <map> #include <map>
#include <set> #include <set>
#include <memory>
#include <hos_core_msgs/DeviceCommand.h> #include <hos_core_msgs/DeviceCommand.h>
#include <hos_core_msgs/DeviceStatusUpdate.h> #include <hos_core_msgs/DeviceStatusUpdate.h>
#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>
namespace XmlRpc {
class XmlRpcValue;
}
#include <ros/ros.h> #include <ros/ros.h>
using namespace libvariant;
// Forward declarations
namespace XmlRpc {
class XmlRpcValue;
}
namespace hos { namespace hos {
namespace cosgi {
namespace core {
class HOSCoreService;
}
}
}
class HosSchemaLoader;
// Service Namespace
namespace hos {
namespace cosgi { namespace cosgi {
namespace devicerepository {
class HOSCoreService;
class GenericDeviceImpl : public GenericDevice {
/**
* Device implementation
**/
class DeviceImpl : public Device {
OBSERVABLE_IMPL(DeviceEvent) OBSERVABLE_IMPL(DeviceEvent)
private: private:
std::mutex objMutex;
std::string deviceID; std::string deviceID;
std::string deviceType; std::string deviceType;
std::string statusTopic; std::string statusTopic;
std::string cmdTopic; std::string cmdTopic;
libvariant::Variant currentState; Variant currentState;
libvariant::Variant lastState; Variant lastState;
public: public:
GenericDeviceImpl(std::string deviceID, std::string deviceType, std::string statusTopic, std::string cmdTopic); DeviceImpl(std::string deviceID, std::string deviceType, std::string statusTopic, std::string cmdTopic);
/* Public Service Implementations */
virtual const std::string& getDeviceID() { return deviceID; } virtual const std::string& getDeviceID() { return deviceID; }
virtual const std::string& getDeviceType() { return deviceType; } virtual const std::string& getDeviceType() { return deviceType; }
virtual const std::string& getCmdTopic() { return cmdTopic; } virtual const std::string& getCmdTopic() { return cmdTopic; }
virtual const std::string& getStatusTopic() { return statusTopic; } virtual const std::string& getStatusTopic() { return statusTopic; }
virtual const libvariant::Variant& getCurrentState() { return currentState; } virtual const Variant& getCurrentState() { return currentState; }
virtual const libvariant::Variant& getLastState() { return lastState; } virtual const Variant& getLastState() { return lastState; }
void handleStatusMsg(libvariant::Variant& msg); /* Internal Stuff */
void handleCommandMsg(libvariant::Variant& msg);
void handleStatusMsg(Variant& msg);
void handleCommandMsg(Variant& msg);
}; };
/**
* Implementation of device repository service
**/
class HOSDeviceRepositoryServiceImpl : public HOSDeviceRepositoryService { class HOSDeviceRepositoryServiceImpl : public HOSDeviceRepositoryService {
OBSERVABLE_IMPL(DeviceEvent) OBSERVABLE_IMPL(DeviceEvent)
private: private:
typedef std::map<std::string, GenericDevice*> devicesMap_t; typedef std::map<std::string, std::shared_ptr<DeviceImpl>> devicesMap_t;
typedef std::map<std::string, std::pair<int, ros::Subscriber>> subscripedTopicMap_t;
ros::NodeHandle& nodehandle; std::recursive_mutex serviceMutex;
HOSCoreService& coreService;
devicesMap_t devices; ros::NodeHandle* nodehandle = nullptr;
std::map<std::string, std::pair<int, ros::Subscriber>> subscripedTopics; core::HOSCoreService* coreService = nullptr;
std::string deviceRepositoryPrefix = "/hos/devices/repository"; std::string deviceRepositoryPrefix = "/hos/devices/repository";
std::string hosStatusTopic = "/hos/status/updates"; std::string hosStatusTopic = "/hos/status/updates";
devicesMap_t devices;
subscripedTopicMap_t subscripedTopics;
ros::Subscriber hosStatusSub; ros::Subscriber hosStatusSub;
HosSchemaLoader* schemaLoader = nullptr; std::unique_ptr<libvariant::HosSchemaLoader> schemaLoader;
bool initialized = false;
void init();
void addDevice(std::string name); void addDevice(std::string name);
void addDevice(std::string name, XmlRpc::XmlRpcValue& rawValue); void addDevice(std::string name, XmlRpc::XmlRpcValue& rawValue);
GenericDevice* _createDevice(std::string name, XmlRpc::XmlRpcValue& rawValue);
void removeDevice(std::string name); void removeDevice(std::string name);
public: public:
HOSDeviceRepositoryServiceImpl(HOSCoreService& coreService); /* Initialization */
virtual GenericDevice* getDevice(std::string device_id); void setCoreService(core::HOSCoreService* coreService);
virtual std::vector<GenericDevice*>& getDevices(std::vector<GenericDevice*>& devices);
/* Public Service Implementations */
virtual std::shared_ptr<Device> getDevice(std::string device_id);
virtual size_t getDevices(std::vector<std::shared_ptr<Device>>& devices);
virtual const char* getServiceName() { return SERVICE_NAME; } virtual const char* getServiceName() { return SERVICE_NAME; }
virtual void getServiceVersion(int& major, int& minor); virtual void getServiceVersion(int& major, int& minor);
virtual int getRefCount(); /* Message Callbacks */
void statusMsgCallback(const hos_core_msgs::DeviceStatusUpdate::ConstPtr& msg); void statusMsgCallback(const hos_core_msgs::DeviceStatusUpdate::ConstPtr& msg);
void cmdMsgCallback(const hos_core_msgs::DeviceCommand::ConstPtr& msg); void cmdMsgCallback(const hos_core_msgs::DeviceCommand::ConstPtr& msg);
void hosStatusMsgCallback(const hos_core_msgs::HosStatusUpdate::ConstPtr& msg); void hosStatusMsgCallback(const hos_core_msgs::HosStatusUpdate::ConstPtr& msg);
/* Internal Stuff */
bool isInitialized() { return initialized; }
}; };
} // namespace devicerepository
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
+3 -2
View File
@@ -7,7 +7,8 @@ project(hos_cosgi_launcher)
find_package(catkin REQUIRED COMPONENTS find_package(catkin REQUIRED COMPONENTS
hos_celix hos_celix
roscpp roscpp
hos_cosgi_core hos_cosgi_common
hos_cpp_common
) )
## System dependencies are found with CMake's conventions ## System dependencies are found with CMake's conventions
@@ -83,7 +84,7 @@ find_package(APR REQUIRED)
catkin_package( catkin_package(
INCLUDE_DIRS include INCLUDE_DIRS include
# LIBRARIES hos_cosgi_launcher # LIBRARIES hos_cosgi_launcher
CATKIN_DEPENDS hos_celix hos_cosgi_core CATKIN_DEPENDS hos_celix hos_cosgi_common
# DEPENDS system_lib # DEPENDS system_lib
) )
@@ -2,29 +2,52 @@
#define SRC_HOS_CORE_SERVICE_H_ #define SRC_HOS_CORE_SERVICE_H_
#include <hos_cosgi_core/cosgi_core.h> #include <hos_cosgi_common/cosgi_common.h>
#include <hos_cpp_common/observable.h>
// Forward declarations
namespace ros { namespace ros {
class NodeHandle; class NodeHandle;
} }
// Service Namespace
namespace hos { namespace hos {
namespace cosgi{ namespace cosgi {
namespace core {
class HOSCoreService : public COSGI_Service_Interface {
class CoreEvent {
public:
enum class EventType : int { STARTUP_FINISHED = 1 };
const EventType eventType;
CoreEvent(EventType type) : eventType(type) {}
};
class StartupFinishedEvent : public CoreEvent {
public:
StartupFinishedEvent() : CoreEvent(EventType::STARTUP_FINISHED) {}
};
class HOSCoreService : public COSGI_Service_Interface, public common::IObservable<CoreEvent> {
public: public:
static constexpr const char* SERVICE_NAME = "hos_core_service"; static constexpr const char* SERVICE_NAME = "hos_core_service";
static constexpr int SERVICE_VERSION_MAJOR = 1; static constexpr int SERVICE_VERSION_MAJOR = 1;
static constexpr int SERVICE_VERSION_MINOR = 0; static constexpr int SERVICE_VERSION_MINOR = 0;
virtual ros::NodeHandle& getPublicNodeHandle() = 0; virtual ros::NodeHandle* getPublicNodeHandle() = 0;
virtual ros::NodeHandle& getPrivateNodeHandle() = 0; virtual ros::NodeHandle* getPrivateNodeHandle() = 0;
virtual void requestShutdown() = 0; virtual void requestShutdown() = 0;
}; };
} // namespace core
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
+4 -2
View File
@@ -42,10 +42,12 @@
<buildtool_depend>catkin</buildtool_depend> <buildtool_depend>catkin</buildtool_depend>
<build_depend>hos_celix</build_depend> <build_depend>hos_celix</build_depend>
<build_depend>roscpp</build_depend> <build_depend>roscpp</build_depend>
<build_depend>hos_cosgi_core</build_depend> <build_depend>hos_cosgi_common</build_depend>
<build_depend>hos_cpp_common</build_depend>
<run_depend>hos_celix</run_depend> <run_depend>hos_celix</run_depend>
<run_depend>roscpp</run_depend> <run_depend>roscpp</run_depend>
<run_depend>hos_cosgi_core</run_depend> <run_depend>hos_cosgi_common</run_depend>
<run_depend>hos_cpp_common</run_depend>
<!-- The export tag contains other, unspecified, tags --> <!-- The export tag contains other, unspecified, tags -->
@@ -10,17 +10,18 @@
namespace hos { namespace hos {
namespace cosgi{ namespace cosgi{
namespace core {
HOSCoreServiceImpl::HOSCoreServiceImpl(ros::NodeHandle& publicNodeHandle, ros::NodeHandle& privateNodeHandle) HOSCoreServiceImpl::HOSCoreServiceImpl(ros::NodeHandle* publicNodeHandle, ros::NodeHandle* privateNodeHandle)
: publicNodeHandle(publicNodeHandle), privateNodeHandle(privateNodeHandle) {} : publicNodeHandle(publicNodeHandle), privateNodeHandle(privateNodeHandle) {}
ros::NodeHandle& HOSCoreServiceImpl::getPublicNodeHandle() { ros::NodeHandle* HOSCoreServiceImpl::getPublicNodeHandle() {
return publicNodeHandle; return publicNodeHandle;
} }
ros::NodeHandle& HOSCoreServiceImpl::getPrivateNodeHandle() { ros::NodeHandle* HOSCoreServiceImpl::getPrivateNodeHandle() {
return privateNodeHandle; return privateNodeHandle;
} }
@@ -36,6 +37,7 @@ void HOSCoreServiceImpl::getServiceVersion(int& major, int& minor) {
} }
} // namespace core
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
@@ -9,26 +9,33 @@
#define SRC_HOS_CORE_SERVICE_IMPL_H_ #define SRC_HOS_CORE_SERVICE_IMPL_H_
#include <hos_cosgi_launcher/hos_core_service.h> #include <hos_cosgi_launcher/hos_core_service.h>
#include <hos_cpp_common/observable_impl.h>
// Service Namespace
namespace hos { namespace hos {
namespace cosgi{ namespace cosgi{
namespace core {
class HOSCoreServiceImpl : public HOSCoreService { class HOSCoreServiceImpl : public HOSCoreService {
OBSERVABLE_IMPL(CoreEvent)
private: private:
ros::NodeHandle& publicNodeHandle; ros::NodeHandle* publicNodeHandle;
ros::NodeHandle& privateNodeHandle; ros::NodeHandle* privateNodeHandle;
public: public:
HOSCoreServiceImpl(ros::NodeHandle& publicNodeHandle, ros::NodeHandle& privateNodeHandle); HOSCoreServiceImpl(ros::NodeHandle* publicNodeHandle, ros::NodeHandle* privateNodeHandle);
virtual ros::NodeHandle& getPublicNodeHandle(); virtual ros::NodeHandle* getPublicNodeHandle();
virtual ros::NodeHandle& getPrivateNodeHandle(); virtual ros::NodeHandle* getPrivateNodeHandle();
virtual void requestShutdown(); virtual void requestShutdown();
virtual const char* getServiceName() { return SERVICE_NAME; } virtual const char* getServiceName() { return SERVICE_NAME; }
virtual void getServiceVersion(int& major, int& minor); virtual void getServiceVersion(int& major, int& minor);
}; };
} // namespace core
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
@@ -18,7 +18,7 @@ extern "C" { // celix does not provide C++ ready headers
#include <string> #include <string>
using namespace hos::cosgi; using namespace hos::cosgi::core;
std::function<void(int)> signalHandler; std::function<void(int)> signalHandler;
@@ -101,8 +101,9 @@ int main(int argc, char **argv) {
// Create bundle context // Create bundle context
bundle_context_pt context = nullptr; bundle_context_pt context = nullptr;
bundle_getContext(fwBundle, &context); bundle_getContext(fwBundle, &context);
// Create and register hos-core-service // Create and register hos-core-service
HOSCoreServiceImpl hosCoreService(rosPublicNodeHandle, rosPrivateNodeHandle); HOSCoreServiceImpl hosCoreService(&rosPublicNodeHandle, &rosPrivateNodeHandle);
service_registration_pt reg = nullptr; service_registration_pt reg = nullptr;
bundleContext_registerService(context, (char*)HOSCoreService::SERVICE_NAME, static_cast<HOSCoreService*>(&hosCoreService), nullptr, &reg); bundleContext_registerService(context, (char*)HOSCoreService::SERVICE_NAME, static_cast<HOSCoreService*>(&hosCoreService), nullptr, &reg);
ROS_INFO("HOS core service registered"); ROS_INFO("HOS core service registered");
@@ -177,6 +178,12 @@ int main(int argc, char **argv) {
throw std::runtime_error((boost::format("Could not create temporary APR memory pool.") % cstatus).str()); throw std::runtime_error((boost::format("Could not create temporary APR memory pool.") % cstatus).str());
} }
// Send startup finished event
{
StartupFinishedEvent event;
hosCoreService.notifyObservers(&event);
}
// main loop // main loop
ROS_INFO("Entering main loop"); ROS_INFO("Entering main loop");
signalHandler = [&](int signum) { signalHandler = [&](int signum) {
+6 -2
View File
@@ -6,7 +6,7 @@ project(hos_cosgi_rulesengine)
## is used, also find other catkin packages ## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS find_package(catkin REQUIRED COMPONENTS
hos_celix hos_celix
hos_cosgi_core hos_cosgi_common
hos_cosgi_devicerepository hos_cosgi_devicerepository
hos_cosgi_launcher hos_cosgi_launcher
hos_cpp_common hos_cpp_common
@@ -90,7 +90,7 @@ find_package(Boost REQUIRED)
catkin_package( catkin_package(
INCLUDE_DIRS include INCLUDE_DIRS include
# LIBRARIES hos_cosgi_rulesengine # LIBRARIES hos_cosgi_rulesengine
CATKIN_DEPENDS hos_celix hos_cosgi_core hos_cosgi_devicerepository hos_cosgi_launcher hos_cpp_common hos_libvariant roscpp CATKIN_DEPENDS hos_celix hos_cosgi_common hos_cosgi_devicerepository hos_cosgi_launcher hos_cpp_common hos_libvariant roscpp
# DEPENDS system_lib # DEPENDS system_lib
) )
@@ -121,6 +121,10 @@ bundle(hos_cosgi_rulesengine
SOURCES SOURCES
${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/GlobalContext
${PROJECT_SOURCE_DIR}/src/rulesengine/Rule
${PROJECT_SOURCE_DIR}/src/rulesengine/RuleCondition
) )
target_link_libraries(hos_cosgi_rulesengine target_link_libraries(hos_cosgi_rulesengine
${catkin_LIBRARIES} ${catkin_LIBRARIES}
@@ -9,12 +9,13 @@
#define INCLUDE_HOS_COSGI_RULESENGINE_HOS_RULESENGINE_SERVICE_H_ #define INCLUDE_HOS_COSGI_RULESENGINE_HOS_RULESENGINE_SERVICE_H_
#include <hos_cosgi_core/cosgi_core.h> #include <hos_cosgi_common/cosgi_common.h>
#include <hos_cpp_common/observable.h> #include <hos_cpp_common/observable.h>
namespace hos { namespace hos {
namespace cosgi { namespace cosgi {
namespace rulesengine {
class RulesEngineEvent; class RulesEngineEvent;
@@ -28,6 +29,7 @@ public:
}; };
} // namespace rulesengine
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
@@ -0,0 +1,62 @@
/*
* hos_rulesexecution_service.h
*
* Created on: 01.05.2015
* Author: matzman
*/
#ifndef INCLUDE_HOS_COSGI_RULESENGINE_HOS_RULESEXECUTION_SERVICE_H_
#define INCLUDE_HOS_COSGI_RULESENGINE_HOS_RULESEXECUTION_SERVICE_H_
#include <hos_cosgi_common/cosgi_common.h>
#include <memory>
// Forward declarations
namespace XmlRpc {
class XmlRpcValue;
}
namespace hos {
namespace cosgi {
namespace rulesengine {
class RulePackage;
}
}
}
namespace hos {
namespace cosgi {
namespace rulesexecution {
class GlobalExecutionContext : public COSGI_Object_Interface {
};
class RuleBody : public COSGI_Object_Interface {
};
class HOSRulesExecutionService : public COSGI_Service_Interface {
public:
static constexpr const char* SERVICE_NAME = "hos_rulesexecution_service";
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;
};
} // namespace rulesengine
} // namespace cosgi
} // namespace hos
#endif /* INCLUDE_HOS_COSGI_RULESENGINE_HOS_RULESEXECUTION_SERVICE_H_ */
@@ -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_rulesengine" pkg="hos_cosgi_launcher" type="hos_cosgi_launcher" output="screen"> <node name="cosgi_rulesengine" pkg="hos_cosgi_launcher" type="hos_cosgi_launcher" output="screen">
<param name="autostart_bundles" value="$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_devicerepository/hos_cosgi_devicerepository.zip $(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_rulesengine/hos_cosgi_rulesengine.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell_tui.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_service.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer_syslog.zip"/> <param name="autostart_bundles" value="$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_devicerepository/hos_cosgi_devicerepository.zip $(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_rulesengine/hos_cosgi_rulesengine.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell_tui.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_service.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer.zip $(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer_syslog.zip"/>
</node> </node>
+35
View File
@@ -0,0 +1,35 @@
{
"language" : "python",
"globalcontext" : "?",
"rules" : [
{
"name" : "rule0",
"conditions" : [
{
"type" : "devicestatus",
"deviceid" : "<deviceid>",
"jsonpath" : "<jsonpath>",
"from": <json-value>,
"to": <json-value>,
},
{
"type" : "devicemsg",
"deviceid" : "<deviceid>",
"jsonpath" : "<jsonpath>",
"msgtype": "status",
"msgvalue": <json-value>,
},
{
"type" : "time",
"cron" : "<cronpattern>",
"timepoint" : "<timepoint>"
},
{
"type": "system",
"event": "startup"
}
],
"body" : "<body>"
}
]
}
@@ -1,34 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="rulesengine" nsURI="rulesengine" nsPrefix="rulesengine">
<eClassifiers xsi:type="ecore:EClass" name="RulesUnit"> <eClassifiers xsi:type="ecore:EClass" name="RulesengineService">
<eStructuralFeatures xsi:type="ecore:EReference" name="rules" lowerBound="1" upperBound="-1" <eStructuralFeatures xsi:type="ecore:EReference" upperBound="-1" eType="#//RulePackage"
containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="RulePackage">
<eStructuralFeatures xsi:type="ecore:EReference" eType="#//GlobalContext" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" lowerBound="1" upperBound="-1"
eType="#//Rule" containment="true"/> eType="#//Rule" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="context" eType="#//GlobalContext"
containment="true"/>
</eClassifiers> </eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="GlobalContext" abstract="true" interface="true"/>
<eClassifiers xsi:type="ecore:EClass" name="Rule"> <eClassifiers xsi:type="ecore:EClass" name="Rule">
<eOperations name="evaluate"/> <eStructuralFeatures xsi:type="ecore:EReference" lowerBound="1" upperBound="-1"
<eOperations name="execute"/> eType="#//RuleCondition" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="conditions" lowerBound="1" <eStructuralFeatures xsi:type="ecore:EReference" lowerBound="1" eType="#//RuleBody"
upperBound="-1" eType="#//Condition" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" name="body" lowerBound="1" eType="#//RuleBody"
containment="true"/> containment="true"/>
</eClassifiers> </eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="Condition"> <eClassifiers xsi:type="ecore:EClass" name="RuleCondition" abstract="true" interface="true"/>
<eOperations name="evaluate"/> <eClassifiers xsi:type="ecore:EClass" name="RuleBody" abstract="true" interface="true"/>
<eClassifiers xsi:type="ecore:EClass" name="DeviceRepositoryService">
<eStructuralFeatures xsi:type="ecore:EReference" upperBound="-1" eType="#//Device"
containment="true"/>
</eClassifiers> </eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="ItemCondition" eSuperTypes="#//Condition"/> <eClassifiers xsi:type="ecore:EClass" name="Device"/>
<eClassifiers xsi:type="ecore:EClass" name="TimeCondition" eSuperTypes="#//Condition"/> <eClassifiers xsi:type="ecore:EClass" name="DeviceCondition" eSuperTypes="#//RuleCondition">
<eClassifiers xsi:type="ecore:EClass" name="SystemCondition" eSuperTypes="#//Condition"/> <eStructuralFeatures xsi:type="ecore:EReference" eType="#//Device"/>
<eClassifiers xsi:type="ecore:EClass" name="GlobalContext"/>
<eClassifiers xsi:type="ecore:EClass" name="RuleBody">
<eOperations name="execute"/>
</eClassifiers> </eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="TimeCondition" eSuperTypes="#//RuleCondition"/>
<eClassifiers xsi:type="ecore:EClass" name="SystemCondition" eSuperTypes="#//RuleCondition"/>
<eClassifiers xsi:type="ecore:EClass" name="GlobalPythonContext" eSuperTypes="#//GlobalContext"/> <eClassifiers xsi:type="ecore:EClass" name="GlobalPythonContext" eSuperTypes="#//GlobalContext"/>
<eClassifiers xsi:type="ecore:EClass" name="RulePythonBody" eSuperTypes="#//RuleBody"/> <eClassifiers xsi:type="ecore:EClass" name="PythonRuleBody" eSuperTypes="#//RuleBody"/>
<eClassifiers xsi:type="ecore:EClass" name="RulesEngine">
<eStructuralFeatures xsi:type="ecore:EReference" name="units" upperBound="-1"
eType="#//RulesUnit" containment="true"/>
</eClassifiers>
</ecore:EPackage> </ecore:EPackage>
@@ -1,294 +1,462 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmi:id="_9vHMAOxeEeSeBazpeuC4MQ" type="Ecore" measurementUnit="Pixel"> <notation:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmi:id="_khfdwPATEeSxkrcRRJC36Q" type="Ecore" name="rulesengine.ecore_diagram" measurementUnit="Pixel">
<children xmi:type="notation:Shape" xmi:id="_9xiN4OxeEeSeBazpeuC4MQ" type="2001" fontName="Sans"> <children xmi:type="notation:Shape" xmi:id="_91SdQPATEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" fillColor="13369343" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:DecorationNode" xmi:id="_9xi08OxeEeSeBazpeuC4MQ" type="5001"/> <children xmi:type="notation:BasicDecorationNode" xmi:id="_91TrYPATEeSxkrcRRJC36Q" type="DiagramName">
<children xmi:type="notation:BasicCompartment" xmi:id="_9xi08exeEeSeBazpeuC4MQ" type="7001"> <element xsi:nil="true"/>
<styles xmi:type="notation:SortingStyle" xmi:id="_9xi08uxeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xi08-xeEeSeBazpeuC4MQ"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_JFWEcOxfEeSeBazpeuC4MQ" value="0.23076923076923078"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xi09OxeEeSeBazpeuC4MQ" type="7002"> <children xmi:type="notation:BasicDecorationNode" xmi:id="_91TrYfATEeSxkrcRRJC36Q" type="Description">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xi09exeEeSeBazpeuC4MQ"/> <element xsi:nil="true"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xi09uxeEeSeBazpeuC4MQ"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_JFWEcexfEeSeBazpeuC4MQ" value="0.23076923076923078"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xi09-xeEeSeBazpeuC4MQ" type="7003"> <styles xmi:type="notation:TextStyle" xmi:id="_91SdQfATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:SortingStyle" xmi:id="_9xi0-OxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:LineTypeStyle" xmi:id="_91SdQvATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xi0-exeEeSeBazpeuC4MQ"/> <element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_JFWEcuxfEeSeBazpeuC4MQ" value="0.23076923076923078"/> <layoutConstraint xmi:type="notation:Bounds" xmi:id="_91SdQ_ATEeSxkrcRRJC36Q" x="260" y="175" width="736" height="316"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//RulesUnit"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xiN4exeEeSeBazpeuC4MQ" x="115" y="115"/>
</children> </children>
<children xmi:type="notation:Shape" xmi:id="_9xi0-uxeEeSeBazpeuC4MQ" type="2001" fontName="Sans"> <children xmi:type="notation:Shape" xmi:id="_0XNZQPATEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_9xi0_OxeEeSeBazpeuC4MQ" type="5001"/> <children xmi:type="notation:DecorationNode" xmi:id="_0XNZQvATEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xi0_exeEeSeBazpeuC4MQ" type="7001"> <children xmi:type="notation:BasicCompartment" xmi:id="_0XNZQ_ATEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xi0_uxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_0XNZRPATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xi0_-xeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_0XNZRfATEeSxkrcRRJC36Q"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xi1AOxeEeSeBazpeuC4MQ" type="7002"> <children xmi:type="notation:BasicCompartment" xmi:id="_0XOAUPATEeSxkrcRRJC36Q" type="7002">
<children xmi:type="notation:Node" xmi:id="_al57sOxgEeSeBazpeuC4MQ" type="3002"> <styles xmi:type="notation:SortingStyle" xmi:id="_0XOAUfATEeSxkrcRRJC36Q"/>
<element xmi:type="ecore:EOperation" href="rulesengine.ecore#//Rule/evaluate"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_0XOAUvATEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Location" xmi:id="_al57sexgEeSeBazpeuC4MQ"/>
</children>
<children xmi:type="notation:Node" xmi:id="_cYeFgOxgEeSeBazpeuC4MQ" type="3002">
<element xmi:type="ecore:EOperation" href="rulesengine.ecore#//Rule/execute"/>
<layoutConstraint xmi:type="notation:Location" xmi:id="_cYeFgexgEeSeBazpeuC4MQ"/>
</children>
<styles xmi:type="notation:SortingStyle" xmi:id="_9xi1AexeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xi1AuxeEeSeBazpeuC4MQ"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xi1A-xeEeSeBazpeuC4MQ" type="7003"> <children xmi:type="notation:BasicCompartment" xmi:id="_0XOAU_ATEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xi1BOxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_0XOAVPATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xi1BexeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_0XOAVfATEeSxkrcRRJC36Q"/>
</children> </children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//Rule"/> <element xmi:type="ecore:EClass" href="rulesengine.ecore#//RulesengineService"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xi0--xeEeSeBazpeuC4MQ" x="335" y="110"/> <layoutConstraint xmi:type="notation:Bounds" xmi:id="_0XNZQfATEeSxkrcRRJC36Q" x="320" y="195"/>
</children> </children>
<children xmi:type="notation:Shape" xmi:id="_9xjcAOxeEeSeBazpeuC4MQ" type="2001" fontName="Sans"> <children xmi:type="notation:Shape" xmi:id="_0XOAVvATEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_9xjcAuxeEeSeBazpeuC4MQ" type="5001"/> <children xmi:type="notation:DecorationNode" xmi:id="_0XOAWPATEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xjcA-xeEeSeBazpeuC4MQ" type="7001"> <children xmi:type="notation:BasicCompartment" xmi:id="_0XOAWfATEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xjcBOxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_0XOAWvATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xjcBexeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_0XOAW_ATEeSxkrcRRJC36Q"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xjcBuxeEeSeBazpeuC4MQ" type="7002"> <children xmi:type="notation:BasicCompartment" xmi:id="_0XOAXPATEeSxkrcRRJC36Q" type="7002">
<children xmi:type="notation:Node" xmi:id="_RZeoYOxgEeSeBazpeuC4MQ" type="3002"> <styles xmi:type="notation:SortingStyle" xmi:id="_0XOAXfATEeSxkrcRRJC36Q"/>
<element xmi:type="ecore:EOperation" href="rulesengine.ecore#//Condition/evaluate"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_0XOAXvATEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Location" xmi:id="_RZeoYexgEeSeBazpeuC4MQ"/>
</children>
<styles xmi:type="notation:SortingStyle" xmi:id="_9xjcB-xeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xjcCOxeEeSeBazpeuC4MQ"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xjcCexeEeSeBazpeuC4MQ" type="7003"> <children xmi:type="notation:BasicCompartment" xmi:id="_0XOnYPATEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xjcCuxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_0XOnYfATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xjcC-xeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_0XOnYvATEeSxkrcRRJC36Q"/>
</children> </children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//Condition"/> <element xmi:type="ecore:EClass" href="rulesengine.ecore#//RulePackage"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xjcAexeEeSeBazpeuC4MQ" x="525" y="120"/> <layoutConstraint xmi:type="notation:Bounds" xmi:id="_0XOAV_ATEeSxkrcRRJC36Q" x="340" y="285"/>
</children> </children>
<children xmi:type="notation:Shape" xmi:id="_9xjcDOxeEeSeBazpeuC4MQ" type="2001" fontName="Sans"> <children xmi:type="notation:Shape" xmi:id="_PWqCQPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_9xjcDuxeEeSeBazpeuC4MQ" type="5001"/> <children xmi:type="notation:DecorationNode" xmi:id="_PWqpUPAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xjcD-xeEeSeBazpeuC4MQ" type="7001"> <children xmi:type="notation:BasicCompartment" xmi:id="_PWqpUfAUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xjcEOxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_PWqpUvAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xjcEexeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_PWqpU_AUEeSxkrcRRJC36Q"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xjcEuxeEeSeBazpeuC4MQ" type="7002"> <children xmi:type="notation:BasicCompartment" xmi:id="_PWrQYPAUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xjcE-xeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_PWrQYfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xjcFOxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_PWrQYvAUEeSxkrcRRJC36Q"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xjcFexeEeSeBazpeuC4MQ" type="7003"> <children xmi:type="notation:BasicCompartment" xmi:id="_PWrQY_AUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xjcFuxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_PWrQZPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xjcF-xeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_PWrQZfAUEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//ItemCondition"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xjcDexeEeSeBazpeuC4MQ" x="685" y="150"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_9xkDEOxeEeSeBazpeuC4MQ" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_9xkDEuxeEeSeBazpeuC4MQ" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkDE-xeEeSeBazpeuC4MQ" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkDFOxeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkDFexeEeSeBazpeuC4MQ"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkDFuxeEeSeBazpeuC4MQ" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkDF-xeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkDGOxeEeSeBazpeuC4MQ"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkDGexeEeSeBazpeuC4MQ" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkDGuxeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkDG-xeEeSeBazpeuC4MQ"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//TimeCondition"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xkDEexeEeSeBazpeuC4MQ" x="685" y="60"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_9xkDHOxeEeSeBazpeuC4MQ" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_9xkDHuxeEeSeBazpeuC4MQ" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkDH-xeEeSeBazpeuC4MQ" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkDIOxeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkDIexeEeSeBazpeuC4MQ"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkDIuxeEeSeBazpeuC4MQ" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkDI-xeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkDJOxeEeSeBazpeuC4MQ"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkDJexeEeSeBazpeuC4MQ" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkDJuxeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkDJ-xeEeSeBazpeuC4MQ"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//SystemCondition"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xkDHexeEeSeBazpeuC4MQ" x="690" y="240"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_9xkqIOxeEeSeBazpeuC4MQ" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_9xkqIuxeEeSeBazpeuC4MQ" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkqI-xeEeSeBazpeuC4MQ" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkqJOxeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkqJexeEeSeBazpeuC4MQ"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkqJuxeEeSeBazpeuC4MQ" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkqJ-xeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkqKOxeEeSeBazpeuC4MQ"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkqKexeEeSeBazpeuC4MQ" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkqKuxeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkqK-xeEeSeBazpeuC4MQ"/>
</children> </children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//GlobalContext"/> <element xmi:type="ecore:EClass" href="rulesengine.ecore#//GlobalContext"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xkqIexeEeSeBazpeuC4MQ" x="100" y="270"/> <layoutConstraint xmi:type="notation:Bounds" xmi:id="_PWqCQfAUEeSxkrcRRJC36Q" x="340" y="375"/>
</children> </children>
<children xmi:type="notation:Shape" xmi:id="_9xkqLOxeEeSeBazpeuC4MQ" type="2001" fontName="Sans"> <children xmi:type="notation:Shape" xmi:id="_TCtdQPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_9xkqLuxeEeSeBazpeuC4MQ" type="5001"/> <children xmi:type="notation:DecorationNode" xmi:id="_TCtdQvAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkqL-xeEeSeBazpeuC4MQ" type="7001"> <children xmi:type="notation:BasicCompartment" xmi:id="_TCuEUPAUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkqMOxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_TCuEUfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkqMexeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_TCuEUvAUEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_CAJjYOxfEeSeBazpeuC4MQ" value="0.23076923076923078"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkqMuxeEeSeBazpeuC4MQ" type="7002"> <children xmi:type="notation:BasicCompartment" xmi:id="_TCuEU_AUEeSxkrcRRJC36Q" type="7002">
<children xmi:type="notation:Node" xmi:id="_NsA4IOxgEeSeBazpeuC4MQ" type="3002"> <styles xmi:type="notation:SortingStyle" xmi:id="_TCuEVPAUEeSxkrcRRJC36Q"/>
<element xmi:type="ecore:EOperation" href="rulesengine.ecore#//RuleBody/execute"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_TCuEVfAUEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Location" xmi:id="_NsA4IexgEeSeBazpeuC4MQ"/>
</children>
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkqM-xeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkqNOxeEeSeBazpeuC4MQ"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_CAJjYexfEeSeBazpeuC4MQ" value="0.23076923076923078"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xkqNexeEeSeBazpeuC4MQ" type="7003"> <children xmi:type="notation:BasicCompartment" xmi:id="_TCuEVvAUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xkqNuxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_TCuEV_AUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xkqN-xeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_TCuEWPAUEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_CAJjYuxfEeSeBazpeuC4MQ" value="0.23076923076923078"/> </children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//Rule"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_TCtdQfAUEeSxkrcRRJC36Q" x="535" y="285"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_WagfgPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_WahGkPAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_WahGkfAUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_WahGkvAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_WahGk_AUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_WahGlPAUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_WahGlfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_WahGlvAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_WahGl_AUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_WahGmPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_WahGmfAUEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//RuleCondition"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_WagfgfAUEeSxkrcRRJC36Q" x="665" y="275"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_d_GSUPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_d_G5YPAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_d_G5YfAUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_d_G5YvAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_d_G5Y_AUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_d_G5ZPAUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_d_G5ZfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_d_G5ZvAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_d_G5Z_AUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_d_G5aPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_d_G5afAUEeSxkrcRRJC36Q"/>
</children> </children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//RuleBody"/> <element xmi:type="ecore:EClass" href="rulesengine.ecore#//RuleBody"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xkqLexeEeSeBazpeuC4MQ" x="335" y="240"/> <layoutConstraint xmi:type="notation:Bounds" xmi:id="_d_GSUfAUEeSxkrcRRJC36Q" x="525" y="390"/>
</children> </children>
<children xmi:type="notation:Shape" xmi:id="_9xkqOOxeEeSeBazpeuC4MQ" type="2001" fontName="Sans"> <children xmi:type="notation:Shape" xmi:id="_xqbNcPAUEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" fillColor="13369343" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:DecorationNode" xmi:id="_9xlRMOxeEeSeBazpeuC4MQ" type="5001"/> <children xmi:type="notation:BasicDecorationNode" xmi:id="_xqb0gPAUEeSxkrcRRJC36Q" type="DiagramName">
<children xmi:type="notation:BasicCompartment" xmi:id="_9xlRMexeEeSeBazpeuC4MQ" type="7001"> <element xsi:nil="true"/>
<styles xmi:type="notation:SortingStyle" xmi:id="_9xlRMuxeEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xlRM-xeEeSeBazpeuC4MQ"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xlRNOxeEeSeBazpeuC4MQ" type="7002"> <children xmi:type="notation:BasicDecorationNode" xmi:id="_xqb0gfAUEeSxkrcRRJC36Q" type="Description">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xlRNexeEeSeBazpeuC4MQ"/> <element xsi:nil="true"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xlRNuxeEeSeBazpeuC4MQ"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xlRN-xeEeSeBazpeuC4MQ" type="7003"> <styles xmi:type="notation:TextStyle" xmi:id="_xqbNcfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:SortingStyle" xmi:id="_9xlROOxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:LineTypeStyle" xmi:id="_xqbNcvAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xlROexeEeSeBazpeuC4MQ"/> <element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_xqbNc_AUEeSxkrcRRJC36Q" x="260" y="55" width="736" height="96"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_1x0goPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_1x0govAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_1x0go_AUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_1x0gpPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_1x0gpfAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_1x0gpvAUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_1x0gp_AUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_1x0gqPAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_1x0gqfAUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_1x0gqvAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_1x0gq_AUEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//DeviceRepositoryService"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_1x0gofAUEeSxkrcRRJC36Q" x="310" y="70"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_6VdD4PAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_6VdD4vAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_6VdD4_AUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_6VdD5PAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_6VdD5fAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_6VdD5vAUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_6VdD5_AUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_6VdD6PAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_6VdD6fAUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_6VdD6vAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_6VdD6_AUEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//Device"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_6VdD4fAUEeSxkrcRRJC36Q" x="850" y="70"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_-EWXgPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_-EW-kPAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_-EW-kfAUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_-EW-kvAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_-EW-k_AUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_-EW-lPAUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_-EW-lfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_-EW-lvAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_-EW-l_AUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_-EW-mPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_-EW-mfAUEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//DeviceCondition"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_-EWXgfAUEeSxkrcRRJC36Q" x="820" y="215"/>
</children>
<children xmi:type="notation:Shape" xmi:id="__xTBgPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="__xTBgvAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="__xTBg_AUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="__xTBhPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="__xTBhfAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="__xTokPAUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="__xTokfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="__xTokvAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="__xTok_AUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="__xTolPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="__xTolfAUEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//TimeCondition"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="__xTBgfAUEeSxkrcRRJC36Q" x="820" y="275"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_BixmMPAVEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_BiyNQPAVEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_BiyNQfAVEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_BiyNQvAVEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_BiyNQ_AVEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_BiyNRPAVEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_BiyNRfAVEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_BiyNRvAVEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_BiyNR_AVEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_BiyNSPAVEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_BiyNSfAVEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//SystemCondition"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_BixmMfAVEeSxkrcRRJC36Q" x="820" y="335"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_ZCIXIPAWEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" fillColor="13369343" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:BasicDecorationNode" xmi:id="_ZCIXJPAWEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_ZCI-MPAWEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<styles xmi:type="notation:TextStyle" xmi:id="_ZCIXIfAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_ZCIXIvAWEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_ZCIXI_AWEeSxkrcRRJC36Q" x="260" y="520" width="736" height="296"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_b1wVUPAWEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_b1wVUvAWEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_b1wVU_AWEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_b1wVVPAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_b1wVVfAWEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_b1wVVvAWEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_b1wVV_AWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_b1wVWPAWEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_b1wVWfAWEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_b1wVWvAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_b1wVW_AWEeSxkrcRRJC36Q"/>
</children> </children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//GlobalPythonContext"/> <element xmi:type="ecore:EClass" href="rulesengine.ecore#//GlobalPythonContext"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xkqOexeEeSeBazpeuC4MQ" x="85" y="375"/> <layoutConstraint xmi:type="notation:Bounds" xmi:id="_b1wVUfAWEeSxkrcRRJC36Q" x="315" y="555"/>
</children> </children>
<children xmi:type="notation:Shape" xmi:id="_9xlROuxeEeSeBazpeuC4MQ" type="2001" fontName="Sans"> <children xmi:type="notation:Shape" xmi:id="_fg_4APAWEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_9xlRPOxeEeSeBazpeuC4MQ" type="5001"/> <children xmi:type="notation:DecorationNode" xmi:id="_fg_4AvAWEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xlRPexeEeSeBazpeuC4MQ" type="7001"> <children xmi:type="notation:BasicCompartment" xmi:id="_fg_4A_AWEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xlRPuxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_fg_4BPAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xlRP-xeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_fg_4BfAWEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_aJ8zcPAZEeSxkrcRRJC36Q" value="0.23076923076923078"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xlRQOxeEeSeBazpeuC4MQ" type="7002"> <children xmi:type="notation:BasicCompartment" xmi:id="_fhAfEPAWEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xlRQexeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_fhAfEfAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xlRQuxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_fhAfEvAWEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_aJ9agPAZEeSxkrcRRJC36Q" value="0.23076923076923078"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_9xlRQ-xeEeSeBazpeuC4MQ" type="7003"> <children xmi:type="notation:BasicCompartment" xmi:id="_fhAfE_AWEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_9xlRROxeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:SortingStyle" xmi:id="_fhAfFPAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_9xlRRexeEeSeBazpeuC4MQ"/> <styles xmi:type="notation:FilteringStyle" xmi:id="_fhAfFfAWEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_aJ-BkPAZEeSxkrcRRJC36Q" value="0.23076923076923078"/>
</children> </children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//RulePythonBody"/> <element xmi:type="ecore:EClass" href="rulesengine.ecore#//PythonRuleBody"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_9xlRO-xeEeSeBazpeuC4MQ" x="320" y="350"/> <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fg_4AfAWEeSxkrcRRJC36Q" x="500" y="555"/>
</children> </children>
<children xmi:type="notation:Shape" xmi:id="_yt0zYOxfEeSeBazpeuC4MQ" type="2001" fontName="Sans"> <children xmi:type="notation:Shape" xmi:id="_Vgc4wPAZEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" description="FactoryService" fillColor="10011046" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:DecorationNode" xmi:id="_yt1acOxfEeSeBazpeuC4MQ" type="5001"/> <children xmi:type="notation:BasicDecorationNode" xmi:id="_Vgdf0PAZEeSxkrcRRJC36Q" type="DiagramName">
<children xmi:type="notation:BasicCompartment" xmi:id="_yt1acexfEeSeBazpeuC4MQ" type="7001"> <element xsi:nil="true"/>
<styles xmi:type="notation:SortingStyle" xmi:id="_yt1acuxfEeSeBazpeuC4MQ"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_yt1ac-xfEeSeBazpeuC4MQ"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_yt1adOxfEeSeBazpeuC4MQ" type="7002"> <children xmi:type="notation:BasicDecorationNode" xmi:id="_VgeG4PAZEeSxkrcRRJC36Q" type="Description">
<styles xmi:type="notation:SortingStyle" xmi:id="_yt1adexfEeSeBazpeuC4MQ"/> <element xsi:nil="true"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_yt1aduxfEeSeBazpeuC4MQ"/>
</children> </children>
<children xmi:type="notation:BasicCompartment" xmi:id="_yt1ad-xfEeSeBazpeuC4MQ" type="7003"> <styles xmi:type="notation:TextStyle" xmi:id="_Vgc4wfAZEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:SortingStyle" xmi:id="_yt1aeOxfEeSeBazpeuC4MQ"/> <styles xmi:type="notation:LineTypeStyle" xmi:id="_Vgc4wvAZEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_yt1aeexfEeSeBazpeuC4MQ"/> <element xsi:nil="true"/>
</children> <layoutConstraint xmi:type="notation:Bounds" xmi:id="_Vgc4w_AZEeSxkrcRRJC36Q" x="425" y="510" width="96" height="28"/>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//RulesEngine"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_yt0zYexfEeSeBazpeuC4MQ" x="-55" y="115"/>
</children> </children>
<styles xmi:type="notation:DiagramStyle" xmi:id="_9vHMAexeEeSeBazpeuC4MQ"/> <children xmi:type="notation:Shape" xmi:id="_OrCNMPAmEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" fillColor="12632256" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:BasicDecorationNode" xmi:id="_OrDbUPAmEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_OrDbUfAmEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<styles xmi:type="notation:TextStyle" xmi:id="_OrCNMfAmEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_OrCNMvAmEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_OrCNM_AmEeSxkrcRRJC36Q" x="380" y="635" width="241" height="166"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_WySBIPAmEeSxkrcRRJC36Q" type="Text" fontName="Sans" description="Python Interpreter">
<children xmi:type="notation:BasicDecorationNode" xmi:id="_WySoMPAmEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_WySoMfAmEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_WySBIfAmEeSxkrcRRJC36Q" x="385" y="640"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_sdPRsPAmEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" fillColor="10011046" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:BasicDecorationNode" xmi:id="_sdP4wPAmEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_sdP4wfAmEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<styles xmi:type="notation:TextStyle" xmi:id="_sdPRsfAmEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_sdPRsvAmEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_sdPRs_AmEeSxkrcRRJC36Q" x="590" y="670" height="96"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_K24wsPAnEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" fillColor="10011046" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:BasicDecorationNode" xmi:id="_K25XwPAnEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_K25XwfAnEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<styles xmi:type="notation:TextStyle" xmi:id="_K24wsfAnEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_K24wsvAnEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_K24ws_AnEeSxkrcRRJC36Q" x="730" y="465" width="120" height="40"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_aFxVsPAnEeSxkrcRRJC36Q" type="Note" fontName="Sans" description="Get Device Status&#xA;Send Device Command" fillColor="13369343" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:BasicDecorationNode" xmi:id="_aFyj0PAnEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_aFzK4PAnEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<styles xmi:type="notation:TextStyle" xmi:id="_aFxVsfAnEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_aFxVsvAnEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_aFxVs_AnEeSxkrcRRJC36Q" x="800" y="580"/>
</children>
<styles xmi:type="notation:DiagramStyle" xmi:id="_khfdwfATEeSxkrcRRJC36Q"/>
<element xmi:type="ecore:EPackage" href="rulesengine.ecore#/"/> <element xmi:type="ecore:EPackage" href="rulesengine.ecore#/"/>
<edges xmi:type="notation:Connector" xmi:id="_9yG1oOxeEeSeBazpeuC4MQ" type="4003" source="_9xiN4OxeEeSeBazpeuC4MQ" target="_9xi0-uxeEeSeBazpeuC4MQ"> <edges xmi:type="notation:Connector" xmi:id="_Mc8qMPAUEeSxkrcRRJC36Q" type="4003" source="_0XNZQPATEeSxkrcRRJC36Q" target="_0XOAVvATEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_9yHcsOxeEeSeBazpeuC4MQ" type="6002"> <children xmi:type="notation:DecorationNode" xmi:id="_Mc94UPAUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_9yHcsexeEeSeBazpeuC4MQ" x="56" y="-14"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_Mc94UfAUEeSxkrcRRJC36Q" y="40"/>
</children> </children>
<children xmi:type="notation:DecorationNode" xmi:id="_9yHcsuxeEeSeBazpeuC4MQ" type="6004"> <children xmi:type="notation:DecorationNode" xmi:id="_Mc94UvAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_9yHcs-xeEeSeBazpeuC4MQ" x="-7" y="11"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_Mc94U_AUEeSxkrcRRJC36Q" x="-3" y="23"/>
</children> </children>
<styles xmi:type="notation:FontStyle" xmi:id="_9yG1oexeEeSeBazpeuC4MQ" fontName="Sans"/> <styles xmi:type="notation:FontStyle" xmi:id="_Mc8qMfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulesUnit/rules"/> <element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulesengineService/%"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yG1ouxeEeSeBazpeuC4MQ" points="[0, 0, 0, -60]$[0, 60, 0, 0]"/> <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_Mc8qMvAUEeSxkrcRRJC36Q" points="[3, 26, 4, -94]$[39, 94, 40, -26]"/>
</edges> </edges>
<edges xmi:type="notation:Connector" xmi:id="_9yJR4OxeEeSeBazpeuC4MQ" type="4003" source="_9xiN4OxeEeSeBazpeuC4MQ" target="_9xkqIOxeEeSeBazpeuC4MQ"> <edges xmi:type="notation:Connector" xmi:id="_RxHSgPAUEeSxkrcRRJC36Q" type="4003" source="_0XOAVvATEeSxkrcRRJC36Q" target="_PWqCQPAUEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_9yJ48OxeEeSeBazpeuC4MQ" type="6002"> <children xmi:type="notation:DecorationNode" xmi:id="_RxHSg_AUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_9yJ48exeEeSeBazpeuC4MQ" x="23" y="30"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_RxHShPAUEeSxkrcRRJC36Q" y="40"/>
</children> </children>
<children xmi:type="notation:DecorationNode" xmi:id="_9yJ48uxeEeSeBazpeuC4MQ" type="6004"> <children xmi:type="notation:DecorationNode" xmi:id="_RxHShfAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_9yJ48-xeEeSeBazpeuC4MQ" x="-13" y="-19"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_RxHShvAUEeSxkrcRRJC36Q" y="60"/>
</children> </children>
<styles xmi:type="notation:FontStyle" xmi:id="_9yJR4exeEeSeBazpeuC4MQ" fontName="Sans"/> <styles xmi:type="notation:FontStyle" xmi:id="_RxHSgfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulesUnit/context"/> <element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulePackage/%"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yJR4uxeEeSeBazpeuC4MQ" points="[0, 0, 90, -60]$[-90, 60, 0, 0]"/> <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_RxHSgvAUEeSxkrcRRJC36Q" points="[2, 26, 3, -94]$[2, 146, 3, 26]"/>
</edges> </edges>
<edges xmi:type="notation:Connector" xmi:id="_9yMVMOxeEeSeBazpeuC4MQ" type="4003" source="_9xi0-uxeEeSeBazpeuC4MQ" target="_9xjcAOxeEeSeBazpeuC4MQ"> <edges xmi:type="notation:Connector" xmi:id="_UwwTcPAUEeSxkrcRRJC36Q" type="4003" source="_0XOAVvATEeSxkrcRRJC36Q" target="_TCtdQPAUEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_9yMVM-xeEeSeBazpeuC4MQ" type="6002"> <children xmi:type="notation:DecorationNode" xmi:id="_UwwTc_AUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_9yMVNOxeEeSeBazpeuC4MQ" x="13" y="-12"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_UwwTdPAUEeSxkrcRRJC36Q" y="40"/>
</children> </children>
<children xmi:type="notation:DecorationNode" xmi:id="_9yMVNexeEeSeBazpeuC4MQ" type="6004"> <children xmi:type="notation:DecorationNode" xmi:id="_UwwTdfAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_9yMVNuxeEeSeBazpeuC4MQ" x="-15" y="13"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_UwwTdvAUEeSxkrcRRJC36Q" y="11"/>
</children> </children>
<styles xmi:type="notation:FontStyle" xmi:id="_9yMVMexeEeSeBazpeuC4MQ" fontName="Sans"/> <styles xmi:type="notation:FontStyle" xmi:id="_UwwTcfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//Rule/conditions"/> <element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulePackage/%.1"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yMVMuxeEeSeBazpeuC4MQ" points="[0, 0, 335, -60]$[-335, 60, 0, 0]"/> <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_UwwTcvAUEeSxkrcRRJC36Q" points="[49, -6, -149, -6]$[203, -26, 5, -26]"/>
</edges> </edges>
<edges xmi:type="notation:Connector" xmi:id="_9yQmoOxeEeSeBazpeuC4MQ" type="4003" source="_9xi0-uxeEeSeBazpeuC4MQ" target="_9xkqLOxeEeSeBazpeuC4MQ"> <edges xmi:type="notation:Connector" xmi:id="_Y_PGEPAUEeSxkrcRRJC36Q" type="4003" source="_TCtdQPAUEeSxkrcRRJC36Q" target="_WagfgPAUEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_9yRNsOxeEeSeBazpeuC4MQ" type="6002"> <children xmi:type="notation:DecorationNode" xmi:id="_Y_PGE_AUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_9yRNsexeEeSeBazpeuC4MQ" x="21" y="22"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_Y_PGFPAUEeSxkrcRRJC36Q" y="40"/>
</children> </children>
<children xmi:type="notation:DecorationNode" xmi:id="_9yRNsuxeEeSeBazpeuC4MQ" type="6004"> <children xmi:type="notation:DecorationNode" xmi:id="_Y_PGFfAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_9yRNs-xeEeSeBazpeuC4MQ" x="-3" y="-20"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_Y_PGFvAUEeSxkrcRRJC36Q" x="-1" y="30"/>
</children> </children>
<styles xmi:type="notation:FontStyle" xmi:id="_9yQmoexeEeSeBazpeuC4MQ" fontName="Sans"/> <styles xmi:type="notation:FontStyle" xmi:id="_Y_PGEfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//Rule/body"/> <element xmi:type="ecore:EReference" href="rulesengine.ecore#//Rule/%"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yQmouxeEeSeBazpeuC4MQ" points="[0, 0, -51, -60]$[51, 60, 0, 0]"/> <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_Y_PGEvAUEeSxkrcRRJC36Q" points="[22, 2, -147, -19]$[117, 19, -52, -2]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_Y_RiUPAUEeSxkrcRRJC36Q" id="(0.5111111111111111,0.19230769230769232)"/>
</edges> </edges>
<edges xmi:type="notation:Connector" xmi:id="_9yTC4OxeEeSeBazpeuC4MQ" type="4004" source="_9xjcDOxeEeSeBazpeuC4MQ" target="_9xjcAOxeEeSeBazpeuC4MQ"> <edges xmi:type="notation:Connector" xmi:id="_fgudIPAUEeSxkrcRRJC36Q" type="4003" source="_TCtdQPAUEeSxkrcRRJC36Q" target="_d_GSUPAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_9yTC4exeEeSeBazpeuC4MQ" fontName="Sans"/> <children xmi:type="notation:DecorationNode" xmi:id="_fgvEMPAUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_fgvEMfAUEeSxkrcRRJC36Q" y="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_fgvEMvAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_fgvEM_AUEeSxkrcRRJC36Q" x="-4" y="22"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_fgudIfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//Rule/%.1"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_fgudIvAUEeSxkrcRRJC36Q" points="[-7, 26, -17, -89]$[-25, 89, -35, -26]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_7EBaEPAUEeSxkrcRRJC36Q" type="4003" source="_1x0goPAUEeSxkrcRRJC36Q" target="_6VdD4PAUEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_7ECBIPAUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_7ECBIfAUEeSxkrcRRJC36Q" y="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_7ECBIvAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_7ECBI_AUEeSxkrcRRJC36Q" x="3" y="16"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_7EBaEfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//DeviceRepositoryService/%"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_7EBaEvAUEeSxkrcRRJC36Q" points="[35, 5, -184, -31]$[249, 39, 30, 3]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_7EEdYPAUEeSxkrcRRJC36Q" id="(0.7941176470588235,0.36538461538461536)"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_IWWLwPAVEeSxkrcRRJC36Q" type="4004" source="__xTBgPAUEeSxkrcRRJC36Q" target="_WagfgPAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_IWWLwfAVEeSxkrcRRJC36Q" fontName="Sans"/>
<element xsi:nil="true"/> <element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yTC4uxeEeSeBazpeuC4MQ" points="[-52, 0, 121, 30]$[-97, 0, 76, 30]$[-97, -30, 76, 0]$[-134, -30, 39, 0]"/> <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_IWWLwvAVEeSxkrcRRJC36Q" points="[-53, -5, 103, -5]$[-104, -5, 52, -5]"/>
</edges> </edges>
<edges xmi:type="notation:Connector" xmi:id="_9yURAOxeEeSeBazpeuC4MQ" type="4004" source="_9xkDEOxeEeSeBazpeuC4MQ" target="_9xjcAOxeEeSeBazpeuC4MQ"> <edges xmi:type="notation:Connector" xmi:id="_Irc5EPAVEeSxkrcRRJC36Q" type="4004" source="_BixmMPAVEeSxkrcRRJC36Q" target="_WagfgPAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_9yURAexeEeSeBazpeuC4MQ" fontName="Sans"/> <styles xmi:type="notation:FontStyle" xmi:id="_Irc5EfAVEeSxkrcRRJC36Q" fontName="Sans"/>
<element xsi:nil="true"/> <element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yURAuxeEeSeBazpeuC4MQ" points="[-53, -6, 121, -66]$[-98, -6, 76, -66]$[-98, 60, 76, 0]$[-135, 60, 39, 0]"/> <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_Irc5EvAVEeSxkrcRRJC36Q" points="[-13, -8, 103, 51]$[-64, -52, 52, 7]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_IreHMPAVEeSxkrcRRJC36Q" id="(0.10569105691056911,0.4807692307692308)"/>
</edges> </edges>
<edges xmi:type="notation:Connector" xmi:id="_9yVfIOxeEeSeBazpeuC4MQ" type="4004" source="_9xkDHOxeEeSeBazpeuC4MQ" target="_9xjcAOxeEeSeBazpeuC4MQ"> <edges xmi:type="notation:Connector" xmi:id="_JBCukPAVEeSxkrcRRJC36Q" type="4004" source="_-EWXgPAUEeSxkrcRRJC36Q" target="_WagfgPAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_9yVfIexeEeSeBazpeuC4MQ" fontName="Sans"/> <styles xmi:type="notation:FontStyle" xmi:id="_JBCukfAVEeSxkrcRRJC36Q" fontName="Sans"/>
<element xsi:nil="true"/> <element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yVfIuxeEeSeBazpeuC4MQ" points="[-61, 0, 126, 120]$[-111, 0, 76, 120]$[-111, -120, 76, 0]$[-148, -120, 39, 0]"/> <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_JBCukvAVEeSxkrcRRJC36Q" points="[-19, 7, 103, -50]$[-174, 51, -52, -6]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_JBDVoPAVEeSxkrcRRJC36Q" id="(0.15966386554621848,0.5576923076923077)"/>
</edges> </edges>
<edges xmi:type="notation:Connector" xmi:id="_9yWtQOxeEeSeBazpeuC4MQ" type="4004" source="_9xkqOOxeEeSeBazpeuC4MQ" target="_9xkqIOxeEeSeBazpeuC4MQ"> <edges xmi:type="notation:Connector" xmi:id="_KiM_UPAVEeSxkrcRRJC36Q" type="4002" source="_-EWXgPAUEeSxkrcRRJC36Q" target="_6VdD4PAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_9yWtQexeEeSeBazpeuC4MQ" fontName="Sans"/> <children xmi:type="notation:DecorationNode" xmi:id="_KiNmYPAVEeSxkrcRRJC36Q" type="6001">
<element xsi:nil="true"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_KiNmYfAVEeSxkrcRRJC36Q" y="40"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yWtQuxeEeSeBazpeuC4MQ" points="[0, 0, 0, -60]$[0, 60, 0, 0]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_9yXUUOxeEeSeBazpeuC4MQ" type="4004" source="_9xlROuxeEeSeBazpeuC4MQ" target="_9xkqLOxeEeSeBazpeuC4MQ">
<styles xmi:type="notation:FontStyle" xmi:id="_9yXUUexeEeSeBazpeuC4MQ" fontName="Sans"/>
<element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_9yXUUuxeEeSeBazpeuC4MQ" points="[0, 0, 58, -60]$[-58, 60, 0, 0]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_1U_p8OxfEeSeBazpeuC4MQ" type="4003" source="_yt0zYOxfEeSeBazpeuC4MQ" target="_9xiN4OxeEeSeBazpeuC4MQ">
<children xmi:type="notation:DecorationNode" xmi:id="_1U_p8-xfEeSeBazpeuC4MQ" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_1U_p9OxfEeSeBazpeuC4MQ" x="10" y="-14"/>
</children> </children>
<children xmi:type="notation:DecorationNode" xmi:id="_1U_p9exfEeSeBazpeuC4MQ" type="6004"> <children xmi:type="notation:DecorationNode" xmi:id="_KiNmYvAVEeSxkrcRRJC36Q" type="6003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_1U_p9uxfEeSeBazpeuC4MQ" x="-9" y="11"/> <layoutConstraint xmi:type="notation:Location" xmi:id="_KiNmY_AVEeSxkrcRRJC36Q" x="-3" y="23"/>
</children> </children>
<styles xmi:type="notation:FontStyle" xmi:id="_1U_p8exfEeSeBazpeuC4MQ" fontName="Sans"/> <styles xmi:type="notation:FontStyle" xmi:id="_KiM_UfAVEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulesEngine/units"/> <element xmi:type="ecore:EReference" href="rulesengine.ecore#//DeviceCondition/%"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_1U_p8uxfEeSeBazpeuC4MQ" points="[48, 8, -98, 8]$[137, 26, -9, 26]"/> <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_KiM_UvAVEeSxkrcRRJC36Q" points="[-15, -16, 112, 119]$[-119, -109, 8, 26]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_e50jQPAWEeSxkrcRRJC36Q" type="4004" source="_b1wVUPAWEeSxkrcRRJC36Q" target="_PWqCQPAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_e50jQfAWEeSxkrcRRJC36Q" fontName="Sans"/>
<element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_e50jQvAWEeSxkrcRRJC36Q" points="[9, -10, 18, 134]$[44, -148, 53, -4]"/>
<sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_e52_gPAWEeSxkrcRRJC36Q" id="(0.5838926174496645,0.19230769230769232)"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_hlbN4PAWEeSxkrcRRJC36Q" type="4004" source="_fg_4APAWEeSxkrcRRJC36Q" target="_d_GSUPAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_hlbN4fAWEeSxkrcRRJC36Q" fontName="Sans"/>
<element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_hlbN4vAWEeSxkrcRRJC36Q" points="[2, -26, -1, 124]$[13, -176, 10, -26]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_eh6SMPAZEeSxkrcRRJC36Q" type="line" source="_Vgc4wPAZEeSxkrcRRJC36Q" target="_fg_4APAWEeSxkrcRRJC36Q" lineWidth="1">
<styles xmi:type="notation:ArrowStyle" xmi:id="_eh6SMfAZEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_eh6SMvAZEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_eh6SM_AZEeSxkrcRRJC36Q" points="[0, 0, -44, -39]$[18, 39, -26, 0]"/>
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_eiA_4fAZEeSxkrcRRJC36Q" id="(0.22033898305084745,0.5192307692307693)"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_faxM0PAZEeSxkrcRRJC36Q" type="line" source="_Vgc4wPAZEeSxkrcRRJC36Q" target="_b1wVUPAWEeSxkrcRRJC36Q" lineWidth="1">
<styles xmi:type="notation:ArrowStyle" xmi:id="_faxM0fAZEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_faxM0vAZEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_faxM0_AZEeSxkrcRRJC36Q" points="[0, 0, 59, -36]$[-44, 35, 15, -1]"/>
<targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fa0QIfAZEeSxkrcRRJC36Q" id="(0.8993288590604027,0.46153846153846156)"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_PbSwAPAnEeSxkrcRRJC36Q" type="line" source="_sdPRsPAmEeSxkrcRRJC36Q" target="_K24wsPAnEeSxkrcRRJC36Q" lineWidth="1">
<styles xmi:type="notation:ArrowStyle" xmi:id="_PbTXEPAnEeSxkrcRRJC36Q" arrowTarget="OpenArrow"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_PbTXEfAnEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_PbTXEvAnEeSxkrcRRJC36Q" points="[25, 0, -150, 233]$[175, 0, 0, 233]$[175, -213, 0, 20]"/>
</edges> </edges>
</notation:Diagram> </notation:Diagram>
+2 -2
View File
@@ -41,14 +41,14 @@
<!-- <test_depend>gtest</test_depend> --> <!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend> <buildtool_depend>catkin</buildtool_depend>
<build_depend>hos_celix</build_depend> <build_depend>hos_celix</build_depend>
<build_depend>hos_cosgi_core</build_depend> <build_depend>hos_cosgi_common</build_depend>
<build_depend>hos_cosgi_devicerepository</build_depend> <build_depend>hos_cosgi_devicerepository</build_depend>
<build_depend>hos_cosgi_launcher</build_depend> <build_depend>hos_cosgi_launcher</build_depend>
<build_depend>hos_cpp_common</build_depend> <build_depend>hos_cpp_common</build_depend>
<build_depend>hos_libvariant</build_depend> <build_depend>hos_libvariant</build_depend>
<build_depend>roscpp</build_depend> <build_depend>roscpp</build_depend>
<run_depend>hos_celix</run_depend> <run_depend>hos_celix</run_depend>
<run_depend>hos_cosgi_core</run_depend> <run_depend>hos_cosgi_common</run_depend>
<run_depend>hos_cosgi_devicerepository</run_depend> <run_depend>hos_cosgi_devicerepository</run_depend>
<run_depend>hos_cosgi_launcher</run_depend> <run_depend>hos_cosgi_launcher</run_depend>
<run_depend>hos_cpp_common</run_depend> <run_depend>hos_cpp_common</run_depend>
@@ -15,21 +15,58 @@
extern "C" { extern "C" {
#include "hos_celix/bundle_activator.h" #include "hos_celix/bundle_activator.h"
#include "hos_celix/bundle_context.h" #include "hos_celix/bundle_context.h"
#include "hos_celix/service_listener.h"
#include "hos_celix/service_reference.h"
#include "hos_celix/constants.h"
} }
#include <hos_cosgi_launcher/hos_core_service.h> #include <hos_cosgi_launcher/hos_core_service.h>
#include "hos_rulesengine_service_impl.h" #include "hos_rulesengine_service_impl.h"
#include <memory>
#include <mutex>
using namespace hos::cosgi::rulesengine;
using namespace hos::cosgi::rulesexecution;
using namespace hos::cosgi::devicerepository;
using namespace hos::cosgi::core;
using namespace hos::cosgi; using namespace hos::cosgi;
struct UserData { struct UserData {
apr_pool_t* memoryPool = nullptr; apr_pool_t* memoryPool = nullptr;
hos::cosgi::HOSRulesEngineServiceImpl* serviceImpl = nullptr; std::unique_ptr<HOSRulesEngineServiceImpl> serviceImpl = nullptr;
service_registration_pt serviceReg = nullptr; service_registration_pt serviceReg = nullptr;
serviceListener myServiceListener;
bundle_context_pt bundleContext;
}; };
celix_status_t cb_serviceChanged(void* listener, service_event_pt event) {
UserData* myUserData = (UserData*) ((serviceListener*)listener)->handle;
if (event->type == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) {
char* serviceName = nullptr;
bool checkReg = false;
serviceReference_getProperty(event->reference, (char*)OSGI_FRAMEWORK_OBJECTCLASS, &serviceName);
if (serviceName && std::strcmp(serviceName, HOSDeviceRepositoryService::SERVICE_NAME) == 0) {
HOSDeviceRepositoryService *service = nullptr;
bundleContext_getService(myUserData->bundleContext, event->reference, (void**)&service);
myUserData->serviceImpl->setRepoService(service);
checkReg = true;
} else if (serviceName && std::strcmp(serviceName, HOSRulesExecutionService::SERVICE_NAME) == 0) {
HOSRulesExecutionService *service = nullptr;
bundleContext_getService(myUserData->bundleContext, event->reference, (void**)&service);
myUserData->serviceImpl->addExecutionBackend(service);
checkReg = true;
}
// Register hos-devicerepository-service
if (checkReg && !myUserData->serviceReg && myUserData->serviceImpl->isInitialized()) {
bundleContext_registerService(myUserData->bundleContext, (char*)HOSRulesEngineServiceImpl::SERVICE_NAME, myUserData->serviceImpl.get(), nullptr, &myUserData->serviceReg);
}
} else if (event->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) {
}
return CELIX_SUCCESS;
}
celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) { celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
celix_status_t status = CELIX_START_ERROR; celix_status_t status = CELIX_START_ERROR;
apr_pool_t* memoryPool = nullptr; apr_pool_t* memoryPool = nullptr;
@@ -42,6 +79,7 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData
UserData* myUserData = (UserData*)apr_palloc(memoryPool, sizeof(UserData)); UserData* myUserData = (UserData*)apr_palloc(memoryPool, sizeof(UserData));
if (myUserData != nullptr) { if (myUserData != nullptr) {
myUserData->memoryPool = memoryPool; myUserData->memoryPool = memoryPool;
myUserData->bundleContext = context;
*userData = (void*)myUserData; *userData = (void*)myUserData;
status = CELIX_SUCCESS; status = CELIX_SUCCESS;
ROS_INFO("RulesEngineService: Bundle successfully created"); ROS_INFO("RulesEngineService: Bundle successfully created");
@@ -54,44 +92,45 @@ celix_status_t bundleActivator_create(bundle_context_pt context, void **userData
} }
celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) { celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
celix_status_t status = CELIX_START_ERROR; celix_status_t status = CELIX_SUCCESS;
if (userData != nullptr) { if (userData != nullptr) {
UserData* myUserData = (UserData*)userData; UserData* myUserData = (UserData*)userData;
// Create hos-devicerepository-service
if (myUserData->serviceReg != nullptr) {
serviceRegistration_unregister(myUserData->serviceReg);
myUserData->serviceReg = nullptr;
}
myUserData->serviceImpl.reset(new HOSRulesEngineServiceImpl());
// Get HOS Core Service // Get HOS Core Service
service_reference_pt ref = nullptr; service_reference_pt ref = nullptr;
bundleContext_getServiceReference(context, (char*)HOSCoreService::SERVICE_NAME, &ref); bundleContext_getServiceReference(context, (char*)HOSCoreService::SERVICE_NAME, &ref);
hos::cosgi::HOSCoreService* coreService = nullptr; HOSCoreService* coreService = nullptr;
bundleContext_getService(context, ref, (void**)&coreService); bundleContext_getService(context, ref, (void**)&coreService);
if (coreService == nullptr) { if (coreService == nullptr) {
ROS_ERROR("RulesEngineService: Could not retrieve HOSCoreService."); ROS_ERROR("RulesEngineService: Could not retrieve HOSCoreService. Are you using hos_cosgi_launcher?");
} else { } else {
int major = 0, minor = 0; myUserData->serviceImpl->setCoreService(coreService);
coreService->getServiceVersion(major, minor);
ROS_INFO_STREAM("RulesEngineService: Found HOSCoreService Version " << major << "." << minor);
// Get HOS DeviceRepository Service
service_reference_pt ref2 = nullptr;
bundleContext_getServiceReference(context, (char*)HOSDeviceRepositoryService::SERVICE_NAME, &ref2);
hos::cosgi::HOSDeviceRepositoryService* repoService = nullptr;
bundleContext_getService(context, ref2, (void**)&repoService);
if (repoService == nullptr) {
ROS_ERROR("RulesEngineService: Could not retrieve HOSDeviceRepositoryService.");
} else {
int major2 = 0, minor2 = 0;
repoService->getServiceVersion(major2, minor2);
ROS_INFO_STREAM("RulesEngineService: Found HOSDeviceRepositoryService Version " << major2 << "." << minor2);
// Create and register hos-devicerepository-service
if (myUserData->serviceReg != nullptr) {
serviceRegistration_unregister(myUserData->serviceReg);
}
if (myUserData->serviceImpl != nullptr) {
delete myUserData->serviceImpl;
}
myUserData->serviceImpl = new hos::cosgi::HOSRulesEngineServiceImpl(*coreService, *repoService);
bundleContext_registerService(context, (char*)hos::cosgi::HOSRulesEngineServiceImpl::SERVICE_NAME, &myUserData->serviceImpl, nullptr, &myUserData->serviceReg);
status = CELIX_SUCCESS;
ROS_INFO("RulesEngineService: Bundle successfully started");
}
} }
// Get HOS Core Service
service_reference_pt ref2 = nullptr;
bundleContext_getServiceReference(context, (char*)HOSDeviceRepositoryService::SERVICE_NAME, &ref2);
HOSDeviceRepositoryService* repoService = nullptr;
bundleContext_getService(context, ref2, (void**)&repoService);
if (repoService) {
myUserData->serviceImpl->setRepoService(repoService);
}
// Register hos-devicerepository-service
if (myUserData->serviceImpl->isInitialized()) {
bundleContext_registerService(context, (char*)HOSRulesEngineServiceImpl::SERVICE_NAME, myUserData->serviceImpl.get(), nullptr, &myUserData->serviceReg);
}
// Register service listener
myUserData->myServiceListener.handle = myUserData;
myUserData->myServiceListener.serviceChanged = cb_serviceChanged;
char filter[256];
std::snprintf(filter, 256, "(objectClass=%s|objectClass=%s)", HOSDeviceRepositoryService::SERVICE_NAME, HOSRulesExecutionService::SERVICE_NAME);
//bundleContext_addServiceListener(context, &myUserData->myServiceListener, filter);
bundleContext_addServiceListener(context, &myUserData->myServiceListener, nullptr);
ROS_INFO("RulesEngineService: Bundle successfully started");
} else { } else {
ROS_ERROR("RulesEngineService: Could not start bundle, user data struct is null"); ROS_ERROR("RulesEngineService: Could not start bundle, user data struct is null");
} }
@@ -102,13 +141,13 @@ celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context)
celix_status_t status = CELIX_ILLEGAL_STATE; celix_status_t status = CELIX_ILLEGAL_STATE;
if (userData != nullptr) { if (userData != nullptr) {
UserData* myUserData = (UserData*)userData; UserData* myUserData = (UserData*)userData;
status = bundleContext_removeServiceListener(context, &myUserData->myServiceListener);
if (myUserData->serviceReg != nullptr) { if (myUserData->serviceReg != nullptr) {
serviceRegistration_unregister(myUserData->serviceReg); serviceRegistration_unregister(myUserData->serviceReg);
myUserData->serviceReg = nullptr; myUserData->serviceReg = nullptr;
} }
if (myUserData->serviceImpl != nullptr) { if (myUserData->serviceImpl) {
delete myUserData->serviceImpl; myUserData->serviceImpl.reset();
myUserData->serviceImpl = nullptr;
} }
ROS_INFO("RulesEngineService: Bundle successfully stopped"); ROS_INFO("RulesEngineService: Bundle successfully stopped");
status = CELIX_SUCCESS; status = CELIX_SUCCESS;
@@ -136,5 +175,3 @@ celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt contex
} }
@@ -12,18 +12,62 @@
#include <exception> #include <exception>
#include <iostream> #include <iostream>
#include <unordered_set> #include <unordered_set>
#include <hos_celix/bundle_context.h>
#include "rulesengine/RulePackage.h"
namespace hos { namespace hos {
namespace cosgi { namespace cosgi {
namespace rulesengine {
HOSRulesEngineServiceImpl::HOSRulesEngineServiceImpl(HOSCoreService& coreService, HOSDeviceRepositoryService& repoService) void HOSRulesEngineServiceImpl::setCoreService(core::HOSCoreService* coreService) {
: coreService(coreService), repoService(repoService), nodehandle(coreService.getPrivateNodeHandle()) { if (coreService && !this->coreService) {
this->repoService.addObserver(*this); this->coreService = coreService;
this->nodehandle = coreService->getPrivateNodeHandle();
int major = 0, minor = 0;
coreService->getServiceVersion(major, minor);
ROS_INFO_STREAM("RulesEngineService: Found HOSCoreService Version " << major << "." << minor);
if (repoService) {
init();
}
}
}
void HOSRulesEngineServiceImpl::setRepoService(devicerepository::HOSDeviceRepositoryService* repoService) {
if (repoService && !this->repoService) {
this->repoService = repoService;
int major = 0, minor = 0;
repoService->getServiceVersion(major, minor);
ROS_INFO_STREAM("RulesEngineService: Found HOSDeviceRepositoryService Version " << major << "." << minor);
if (coreService) {
init();
}
}
}
void HOSRulesEngineServiceImpl::init() {
nodehandle->getParam("rulesengine_prefix", ruleEnginePrefix);
XmlRpc::XmlRpcValue rawValue;
nodehandle->getParam(ruleEnginePrefix, rawValue);
if (rawValue.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
for (auto pkg : rawValue) {
std::string pname = pkg.first;
XmlRpc::XmlRpcValue pRaw = pkg.second;
try {
addRulePkg(pname, pRaw);
ROS_INFO_STREAM("Created rule package " << pname << ".");
} catch (std::exception& e) {
ROS_ERROR_STREAM("Could not create rule package " << pname << ": " << e.what());
}
}
}
repoService->addObserver(*this);
initialized = true;
ROS_INFO_STREAM("RulesEngineService: Initialized and Ready.");
} }
HOSRulesEngineServiceImpl::~HOSRulesEngineServiceImpl() { HOSRulesEngineServiceImpl::~HOSRulesEngineServiceImpl() {
repoService.deleteObserver(*this); repoService->deleteObserver(*this);
} }
@@ -33,11 +77,37 @@ void HOSRulesEngineServiceImpl::getServiceVersion(int& major, int& minor) {
} }
void HOSRulesEngineServiceImpl::notificationReceived(IObservable<DeviceEvent>& o, const DeviceEvent* e) { void HOSRulesEngineServiceImpl::notificationReceived(IObservable<devicerepository::DeviceEvent>* o, const devicerepository::DeviceEvent* e) {
} }
void HOSRulesEngineServiceImpl::addRulePkg(std::string name) {
std::stringstream ss;
ss << ruleEnginePrefix << "/" << name;
XmlRpc::XmlRpcValue rawValue;
nodehandle->getParam(ss.str(), rawValue);
addRulePkg(name, 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::removeRulePkg(std::string name) {
rulePkgs.erase(name);
}
void HOSRulesEngineServiceImpl::addExecutionBackend(rulesexecution::HOSRulesExecutionService* service) {
if (execServices.find(service->getLanguage()) == execServices.end()) {
execServices.insert({service->getLanguage(), service});
ROS_INFO_STREAM("RulesEngineService: Added execution service \"" << service->getLanguage() << "\".");
}
}
} // namespace rulesengine
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
@@ -10,6 +10,7 @@
#include <Variant/Variant.h> #include <Variant/Variant.h>
#include <hos_cosgi_rulesengine/hos_rulesengine_service.h> #include <hos_cosgi_rulesengine/hos_rulesengine_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 <mutex> #include <mutex>
#include <map> #include <map>
@@ -19,37 +20,87 @@
#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 <ros/ros.h>
#include <map>
#include <memory>
// Forward declarations
namespace XmlRpc { namespace XmlRpc {
class XmlRpcValue; class XmlRpcValue;
} }
#include <ros/ros.h>
namespace hos { namespace hos {
namespace cosgi { namespace cosgi {
namespace core {
class HOSCoreService; class HOSCoreService;
}
namespace devicerepository {
class HOSDeviceRepositoryService;
class DeviceEvent;
}
namespace rulesengine {
class RulePackage;
}
}
}
class HOSRulesEngineServiceImpl : public HOSRulesEngineService, public common::IObserver<DeviceEvent> {
// Service Namespace
namespace hos {
namespace cosgi {
namespace rulesengine {
class HOSRulesEngineServiceImpl : public HOSRulesEngineService, public common::IObserver<devicerepository::DeviceEvent> {
OBSERVABLE_IMPL(RulesEngineEvent) OBSERVABLE_IMPL(RulesEngineEvent)
private: private:
HOSCoreService& coreService; typedef std::map<std::string, std::shared_ptr<RulePackage>> rulePkgMap_t;
HOSDeviceRepositoryService& repoService; typedef std::map<std::string, rulesexecution::HOSRulesExecutionService*> execServiceMap_t;
ros::NodeHandle& nodehandle;
core::HOSCoreService* coreService = nullptr;
devicerepository::HOSDeviceRepositoryService* repoService = nullptr;
ros::NodeHandle* nodehandle = nullptr;
std::string ruleEnginePrefix = "/hos/rules/rulesengine0";
rulePkgMap_t rulePkgs;
execServiceMap_t execServices;
bool initialized = false;
void addRulePkg(std::string name);
void addRulePkg(std::string name, XmlRpc::XmlRpcValue& rawValue);
void removeRulePkg(std::string name);
void init();
public: public:
HOSRulesEngineServiceImpl(HOSCoreService& coreService, HOSDeviceRepositoryService& repoService);
~HOSRulesEngineServiceImpl(); ~HOSRulesEngineServiceImpl();
/* Initialization */
virtual void notificationReceived(IObservable<DeviceEvent>& o, const DeviceEvent* e); void setCoreService(core::HOSCoreService* coreService);
void setRepoService(devicerepository::HOSDeviceRepositoryService* repoService);
/* Public Service Implementations */
virtual const char* getServiceName() { return SERVICE_NAME; } virtual const char* getServiceName() { return SERVICE_NAME; }
virtual void getServiceVersion(int& major, int& minor); virtual void getServiceVersion(int& major, int& minor);
/* Observer Callback */
virtual void notificationReceived(IObservable<devicerepository::DeviceEvent>* o, const devicerepository::DeviceEvent* e);
/* Internal Stuff */
bool isInitialized() { return initialized; }
void addExecutionBackend(rulesexecution::HOSRulesExecutionService* service);
}; };
} // namespace rulesengine
} // namespace cosgi } // namespace cosgi
} // namespace hos } // namespace hos
@@ -0,0 +1,32 @@
/*
* 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 */
@@ -0,0 +1,47 @@
/*
* 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_ */
@@ -0,0 +1,49 @@
/*
* Rule.cpp
*
* Created on: 29.04.2015
* Author: matzman
*/
#include "Rule.h"
#include <ros/ros.h>
namespace hos {
namespace cosgi {
namespace rulesengine {
Rule::Rule(RulePackage& parent, std::string name)
: parent(parent), name(name) {}
Rule::~Rule() {}
std::shared_ptr<Rule> Rule::createRule(RulePackage& parent, std::string name, XmlRpc::XmlRpcValue& raw) {
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) {
auto conditions = raw["conditions"];
for (auto c : conditions) {
}
if (raw.hasMember("body") && raw["body"].getType() == XmlRpc::XmlRpcValue::TypeString) {
} else {
ROS_ERROR_STREAM("Could not create rule \"" << name << "\".");
retval.reset();
}
} else {
ROS_ERROR_STREAM("Could not create rule \"" << name << "\".");
retval.reset();
}
}
return retval;
}
} /* namespace rulesengine */
} /* namespace cosgi */
} /* namespace hos */
@@ -0,0 +1,61 @@
/*
* Rule.h
*
* Created on: 29.04.2015
* Author: matzman
*/
#ifndef SRC_RULESENGINE_RULE_H_
#define SRC_RULESENGINE_RULE_H_
#include <string>
#include <memory>
#include <vector>
// Forward declarations
namespace XmlRpc {
class XmlRpcValue;
}
namespace hos {
namespace cosgi {
namespace rulesengine {
class RulePackage;
class RuleBody;
class RuleCondition;
}
}
}
namespace hos {
namespace cosgi {
namespace rulesengine {
class Rule {
private:
RulePackage& parent;
std::string name;
std::shared_ptr<RuleBody> body;
std::vector<std::shared_ptr<RuleCondition>> conditions;
public:
Rule(RulePackage& parent, std::string name);
static std::shared_ptr<Rule> createRule(RulePackage& parent, std::string name, XmlRpc::XmlRpcValue& raw);
virtual ~Rule();
RulePackage& getParent() { return parent; }
};
class RuleBody {
};
} /* namespace rulesengine */
} /* namespace cosgi */
} /* namespace hos */
#endif /* SRC_RULESENGINE_RULE_H_ */
@@ -0,0 +1,25 @@
/*
* RuleCondition.cpp
*
* Created on: 29.04.2015
* Author: matzman
*/
#include "RuleCondition.h"
namespace hos {
namespace cosgi {
namespace rulesengine {
RuleCondition::RuleCondition() {
// TODO Auto-generated constructor stub
}
RuleCondition::~RuleCondition() {
// TODO Auto-generated destructor stub
}
} /* namespace rulesengine */
} /* namespace cosgi */
} /* namespace hos */
@@ -0,0 +1,25 @@
/*
* RuleCondition.h
*
* Created on: 29.04.2015
* Author: matzman
*/
#ifndef SRC_RULESENGINE_RULECONDITION_H_
#define SRC_RULESENGINE_RULECONDITION_H_
namespace hos {
namespace cosgi {
namespace rulesengine {
class RuleCondition {
public:
RuleCondition();
virtual ~RuleCondition();
};
} /* namespace rulesengine */
} /* namespace cosgi */
} /* namespace hos */
#endif /* SRC_RULESENGINE_RULECONDITION_H_ */
@@ -0,0 +1,66 @@
/*
* RulePackage.cpp
*
* Created on: 29.04.2015
* Author: matzman
*/
#include "RulePackage.h"
#include "GlobalContext.h"
#include "Rule.h"
#include <ros/ros.h>
#include <exception>
namespace hos {
namespace cosgi {
namespace rulesengine {
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> retval;
if (raw.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
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"]);
} 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});
}
}
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.");
}
} else {
throw std::runtime_error("Rule package JSON is not valid.");
}
return retval;
}
size_t RulePackage::getRules(std::vector<std::shared_ptr<Rule>>& rules) {
size_t retval = 0;
for (auto item : this->rules) {
rules.push_back(item.second);
retval++;
}
return retval;
}
} /* namespace rulesengine */
} /* namespace cosgi */
} /* namespace hos */
@@ -0,0 +1,63 @@
/*
* RulePackage.h
*
* Created on: 29.04.2015
* Author: matzman
*/
#ifndef SRC_RULESENGINE_RULEPACKAGE_H_
#define SRC_RULESENGINE_RULEPACKAGE_H_
#include <vector>
#include <map>
#include <memory>
#include <string>
// Forward declarations
namespace XmlRpc {
class XmlRpcValue;
}
namespace hos {
namespace cosgi {
namespace rulesengine {
class HOSRulesEngineServiceImpl;
class GlobalContext;
class Rule;
}
}
}
namespace hos {
namespace cosgi {
namespace rulesengine {
class RulePackage {
private:
typedef std::map<std::string, std::shared_ptr<Rule>> ruleMap_t;
std::string name;
std::string language;
ruleMap_t rules;
std::shared_ptr<GlobalContext> globalContext;
HOSRulesEngineServiceImpl& parent;
public:
RulePackage(HOSRulesEngineServiceImpl& parent, std::string name);
static std::shared_ptr<RulePackage> createRulePackage(HOSRulesEngineServiceImpl& parent, std::string name, XmlRpc::XmlRpcValue& 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; }
};
} /* namespace rulesengine */
} /* namespace cosgi */
} /* namespace hos */
#endif /* SRC_RULESENGINE_RULEPACKAGE_H_ */
@@ -0,0 +1,32 @@
{
"language": "python",
"globalcontext": {},
"rules": {
"rule01": {
"conditions": [
{
"type": "devicemsg",
"deviceid": "huelight1"
},
{
"type": "devicestatus",
"deviceid": "huelight1"
}
],
"body": "print \"Hello World1\""
},
"rule02": {
"conditions": [
{
"type": "devicemsg",
"deviceid": "huelight2"
},
{
"type": "devicestatus",
"deviceid": "huelight2"
}
],
"body": "print \"Hello World2\""
}
}
}
@@ -0,0 +1,205 @@
cmake_minimum_required(VERSION 2.8.3)
project(hos_cosgi_rulesexecution_python)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
hos_celix
hos_cosgi_common
hos_cosgi_launcher
hos_cosgi_rulesengine
hos_cpp_common
hos_libvariant
)
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()
find_package(APR REQUIRED)
find_package(CELIX REQUIRED)
find_package(Boost REQUIRED)
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn't empty the following dependencies might have been
## pulled in transitively but can be declared for certainty nonetheless:
## * add a build_depend tag for "message_generation"
## * add a run_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
## * add "message_generation" and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS ...)
## * add "message_runtime" and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS ...)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
## Generate messages in the 'msg' folder
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )
## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )
## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# std_msgs # Or other packages containing msgs
# )
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if you package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES hos_cosgi_rulesexecution_python
CATKIN_DEPENDS hos_celix hos_cosgi_common hos_cosgi_launcher hos_cosgi_rulesengine hos_cpp_common hos_libvariant
# DEPENDS system_lib
)
###########
## Build ##
###########
add_definitions(
-std=c++11
)
## Specify additional locations of header files
## Your package locations should be listed before other locations
# include_directories(include)
include_directories(
${catkin_INCLUDE_DIRS}
${APR_INCLUDE_DIR}
${APR_INCLUDE_DIR}/apr-1.0
include
${hos_libvariant_INCLUDE_DIRS}/hos_libvariant
)
set(BUNDLE_SYMBOLICNAME "hos.hos_rulesexecution_python")
set(BUNDLE_VERSION "1.0.0")
set(BUNDLE_NAME "hos_rulesexecution_python")
bundle(hos_cosgi_rulesexecution_python
SOURCES
${PROJECT_SOURCE_DIR}/src/bundle_activator
${PROJECT_SOURCE_DIR}/src/hos_rulesexecution_python_impl
)
target_link_libraries(hos_cosgi_rulesexecution_python
${catkin_LIBRARIES}
${APR_LIBRARIES}
)
## Declare a cpp library
# add_library(hos_cosgi_rulesexecution_python
# src/${PROJECT_NAME}/hos_cosgi_rulesexecution_python.cpp
# )
## Declare a cpp executable
# add_executable(hos_cosgi_rulesexecution_python_node src/hos_cosgi_rulesexecution_python_node.cpp)
## Add cmake target dependencies of the executable/library
## as an example, message headers may need to be generated before nodes
# add_dependencies(hos_cosgi_rulesexecution_python_node hos_cosgi_rulesexecution_python_generate_messages_cpp)
## Specify libraries to link a library or executable target against
# target_link_libraries(hos_cosgi_rulesexecution_python_node
# ${catkin_LIBRARIES}
# )
#############
## Install ##
#############
## Mark cpp header files for installation
#install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
#)
install(FILES
${CMAKE_BINARY_DIR}/hos_cosgi_rulesexecution_python.zip
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/bundles
)
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
# install(TARGETS hos_cosgi_rulesexecution_python hos_cosgi_rulesexecution_python_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_hos_cosgi_rulesexecution_python.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)
@@ -0,0 +1,62 @@
<?xml version="1.0"?>
<package>
<name>hos_cosgi_rulesexecution_python</name>
<version>0.0.0</version>
<description>The hos_cosgi_rulesexecution_python package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="matzman@todo.todo">matzman</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/hos_cosgi_rulesexecution_python</url> -->
<!-- Author tags are optional, mutiple are allowed, one per tag -->
<!-- Authors do not have to be maintianers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *_depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use run_depend for packages you need at runtime: -->
<!-- <run_depend>message_runtime</run_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>hos_celix</build_depend>
<build_depend>hos_cosgi_common</build_depend>
<build_depend>hos_cosgi_launcher</build_depend>
<build_depend>hos_cosgi_rulesengine</build_depend>
<build_depend>hos_cpp_common</build_depend>
<build_depend>hos_libvariant</build_depend>
<run_depend>hos_celix</run_depend>
<run_depend>hos_cosgi_common</run_depend>
<run_depend>hos_cosgi_launcher</run_depend>
<run_depend>hos_cosgi_rulesengine</run_depend>
<run_depend>hos_cpp_common</run_depend>
<run_depend>hos_libvariant</run_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>
@@ -0,0 +1,170 @@
/*
* bundle_activator.cpp
*
* Created on: 26.04.2015
* Author: matzman
*/
#include <cstdlib>
#include <cstdio>
#include <apr_general.h>
#include "ros/ros.h"
extern "C" {
#include "hos_celix/bundle_activator.h"
#include "hos_celix/bundle_context.h"
#include "hos_celix/service_reference.h"
#include "hos_celix/constants.h"
}
#include <hos_cosgi_launcher/hos_core_service.h>
#include <hos_cosgi_devicerepository/hos_devicerepository_service.h>
#include "hos_rulesexecution_python_impl.h"
#include <memory>
using namespace hos::cosgi::rulesengine;
using namespace hos::cosgi::rulesexecution;
using namespace hos::cosgi::devicerepository;
using namespace hos::cosgi::core;
using namespace hos::cosgi;
struct UserData {
apr_pool_t* memoryPool = nullptr;
std::unique_ptr<HOSRulesExecutionPythonImpl> serviceImpl = nullptr;
service_registration_pt serviceReg = nullptr;
serviceListener myServiceListener;
bundle_context_pt bundleContext;
};
celix_status_t cb_serviceChanged(void* listener, service_event_pt event) {
UserData* myUserData = (UserData*) ((serviceListener*)listener)->handle;
if (event->type == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) {
char* serviceName = nullptr;
bool checkReg = false;
serviceReference_getProperty(event->reference, (char*)OSGI_FRAMEWORK_OBJECTCLASS, &serviceName);
if (serviceName && std::strcmp(serviceName, HOSDeviceRepositoryService::SERVICE_NAME) == 0) {
HOSDeviceRepositoryService *service = nullptr;
bundleContext_getService(myUserData->bundleContext, event->reference, (void**)&service);
myUserData->serviceImpl->setRepoService(service);
checkReg = true;
}
// Register hos-devicerepository-service
if (checkReg && !myUserData->serviceReg && myUserData->serviceImpl->isInitialized()) {
bundleContext_registerService(myUserData->bundleContext, (char*)HOSRulesExecutionPythonImpl::SERVICE_NAME, myUserData->serviceImpl.get(), nullptr, &myUserData->serviceReg);
}
} else if (event->type == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) {
}
return CELIX_SUCCESS;
}
celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
celix_status_t status = CELIX_SUCCESS;
apr_pool_t* memoryPool = nullptr;
// Create APR memory pool
apr_status_t astatus = apr_pool_create(&memoryPool, NULL);
if (astatus != APR_SUCCESS) {
ROS_ERROR("RulesExecutionPythonService: Could not create APR memory pool (%i).", astatus);
} else {
// Create user data
UserData* myUserData = (UserData*)apr_palloc(memoryPool, sizeof(UserData));
if (myUserData != nullptr) {
myUserData->memoryPool = memoryPool;
myUserData->bundleContext = context;
*userData = (void*)myUserData;
status = CELIX_SUCCESS;
ROS_INFO("RulesExecutionPythonService: Bundle successfully created");
} else {
ROS_ERROR("RulesExecutionPythonService: Could not create user data struct");
apr_pool_destroy(memoryPool);
}
}
return status;
}
celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
celix_status_t status = CELIX_SUCCESS;
if (userData != nullptr) {
UserData* myUserData = (UserData*)userData;
// Create hos-rulesexecution-python-service
if (myUserData->serviceReg != nullptr) {
serviceRegistration_unregister(myUserData->serviceReg);
myUserData->serviceReg = nullptr;
}
myUserData->serviceImpl.reset(new HOSRulesExecutionPythonImpl());
// Get HOS Core Service
service_reference_pt ref = nullptr;
bundleContext_getServiceReference(context, (char*)HOSCoreService::SERVICE_NAME, &ref);
HOSCoreService* coreService = nullptr;
bundleContext_getService(context, ref, (void**)&coreService);
if (coreService == nullptr) {
ROS_ERROR("RulesExecutionPythonService: Could not retrieve HOSCoreService. Are you using hos_cosgi_launcher?");
} else {
myUserData->serviceImpl->setCoreService(coreService);
}
// Get HOS Core Service
service_reference_pt ref2 = nullptr;
bundleContext_getServiceReference(context, (char*)HOSDeviceRepositoryService::SERVICE_NAME, &ref2);
HOSDeviceRepositoryService* repoService = nullptr;
bundleContext_getService(context, ref2, (void**)&repoService);
if (repoService) {
myUserData->serviceImpl->setRepoService(repoService);
}
// Register hos-rulesexecution-python-service
if (myUserData->serviceImpl->isInitialized()) {
bundleContext_registerService(context, (char*)HOSRulesExecutionPythonImpl::SERVICE_NAME, myUserData->serviceImpl.get(), nullptr, &myUserData->serviceReg);
}
// Register service listener
myUserData->myServiceListener.handle = myUserData;
myUserData->myServiceListener.serviceChanged = cb_serviceChanged;
char filter[256];
std::snprintf(filter, 256, "(objectClass=%s)", HOSDeviceRepositoryService::SERVICE_NAME);
bundleContext_addServiceListener(context, &myUserData->myServiceListener, filter);
ROS_INFO("RulesExecutionPythonService: Bundle successfully started");
} else {
ROS_ERROR("RulesExecutionPythonService: Could not start bundle, user data struct is null");
}
return status;
}
celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
celix_status_t status = CELIX_ILLEGAL_STATE;
if (userData != nullptr) {
UserData* myUserData = (UserData*)userData;
status = bundleContext_removeServiceListener(context, &myUserData->myServiceListener);
if (myUserData->serviceReg != nullptr) {
serviceRegistration_unregister(myUserData->serviceReg);
myUserData->serviceReg = nullptr;
}
if (myUserData->serviceImpl) {
myUserData->serviceImpl.reset();
}
ROS_INFO("RulesExecutionPythonService: Bundle successfully stopped");
status = CELIX_SUCCESS;
} else {
ROS_ERROR("RulesExecutionPythonService: Could not stop bundle, user data struct is null");
}
return status;
}
celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
celix_status_t status = CELIX_ILLEGAL_STATE;
if (userData != nullptr) {
apr_pool_t* memoryPool = ((UserData*)userData)->memoryPool;
if (memoryPool != nullptr) {
apr_pool_destroy(memoryPool);
ROS_INFO("RulesExecutionPythonService: Bundle successfully destroyed");
} else {
ROS_ERROR("RulesExecutionPythonService: Could not destroy bundle, there is no APR memory pool");
}
status = CELIX_SUCCESS;
} else {
ROS_ERROR("RulesExecutionPythonService: Could not destroy bundle, user data struct is null");
}
return status;
}
@@ -0,0 +1,71 @@
/*
* hos_cosgi_rulesexecution_python_impl.cpp
*
* Created on: 01.05.2015
* Author: matzman
*/
#include "hos_rulesexecution_python_impl.h"
#include <hos_cosgi_devicerepository/hos_devicerepository_service.h>
#include <hos_cosgi_launcher/hos_core_service.h>
namespace hos {
namespace cosgi {
namespace rulesexecution {
void HOSRulesExecutionPythonImpl::setCoreService(core::HOSCoreService* coreService) {
if (coreService && !this->coreService) {
this->coreService = coreService;
this->nodehandle = coreService->getPrivateNodeHandle();
int major = 0, minor = 0;
coreService->getServiceVersion(major, minor);
ROS_INFO_STREAM("RulesExecutionPythonService: Found HOSCoreService Version " << major << "." << minor);
if (repoService) {
init();
}
}
}
void HOSRulesExecutionPythonImpl::setRepoService(devicerepository::HOSDeviceRepositoryService* repoService) {
if (repoService && !this->repoService) {
this->repoService = repoService;
int major = 0, minor = 0;
repoService->getServiceVersion(major, minor);
ROS_INFO_STREAM("RulesExecutionPythonService: Found HOSDeviceRepositoryService Version " << major << "." << minor);
if (coreService) {
init();
}
}
}
void HOSRulesExecutionPythonImpl::init() {
initialized = true;
ROS_INFO_STREAM("RulesExecutionPythonService: Initialized and Ready.");
}
void HOSRulesExecutionPythonImpl::getServiceVersion(int& major, int& minor) {
major = SERVICE_VERSION_MAJOR;
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<RuleBody> HOSRulesExecutionPythonImpl::createRuleBody(rulesengine::RulePackage* parent, XmlRpc::XmlRpcValue& raw) {
std::shared_ptr<RuleBody> retval;
return retval;
}
} // namespace rulesengine
} // namespace cosgi
} // namespace hos
@@ -0,0 +1,81 @@
/*
* hos_cosgi_rulesexecution_python_impl.h
*
* Created on: 01.05.2015
* Author: matzman
*/
#ifndef SRC_HOS_RULESEXECUTION_PYTHON_IMPL_H_
#define SRC_HOS_RULESEXECUTION_PYTHON_IMPL_H_
#include <hos_cosgi_rulesengine/hos_rulesexecution_service.h>
#include <hos_cosgi_devicerepository/hos_devicerepository_service.h>
#include <ros/ros.h>
// Forward declarations
namespace XmlRpc {
class XmlRpcValue;
}
namespace hos {
namespace cosgi {
namespace core {
class HOSCoreService;
}
namespace devicerepository {
class HOSDeviceRepositoryService;
class DeviceEvent;
}
}
}
namespace hos {
namespace cosgi {
namespace rulesexecution {
class HOSRulesExecutionPythonImpl : public HOSRulesExecutionService {
private:
core::HOSCoreService* coreService = nullptr;;
devicerepository::HOSDeviceRepositoryService* repoService = nullptr;;
ros::NodeHandle* nodehandle = nullptr;
bool initialized = false;
void init();
public:
static constexpr int SERVICE_VERSION_MAJOR = 1;
static constexpr int SERVICE_VERSION_MINOR = 0;
static constexpr const char* LANGUAGE = "python";
/* Initialization */
void setCoreService(core::HOSCoreService* coreService);
void setRepoService(devicerepository::HOSDeviceRepositoryService* repoService);
/* Public Service Implementations */
virtual const char* getServiceName() { return SERVICE_NAME; }
virtual void getServiceVersion(int& major, int& minor);
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);
/* Internal Stuff */
bool isInitialized() { return initialized; }
};
} // namespace rulesengine
} // namespace cosgi
} // namespace hos
#endif /* SRC_HOS_RULESEXECUTION_PYTHON_IMPL_H_ */
@@ -8,6 +8,7 @@
#ifndef INCLUDE_HOS_CPP_COMMON_OBSERVABLE_H_ #ifndef INCLUDE_HOS_CPP_COMMON_OBSERVABLE_H_
#define INCLUDE_HOS_CPP_COMMON_OBSERVABLE_H_ #define INCLUDE_HOS_CPP_COMMON_OBSERVABLE_H_
#include <cstddef>
namespace hos { namespace hos {
namespace common { namespace common {
@@ -20,7 +21,7 @@ template<class Event>
class IObserver { class IObserver {
public: public:
virtual ~IObserver() {} virtual ~IObserver() {}
virtual void notificationReceived(IObservable<Event>& o, const Event* e) = 0; virtual void notificationReceived(IObservable<Event>* o, const Event* e) = 0;
}; };
@@ -30,11 +31,13 @@ public:
virtual ~IObservable() {} virtual ~IObservable() {}
virtual void addObserver(IObserver<Event>& o) = 0; virtual void addObserver(IObserver<Event>& o) = 0;
virtual void deleteObserver(IObserver<Event>& o) = 0; virtual void deleteObserver(IObserver<Event>& o) = 0;
virtual void deleteObservers() = 0; virtual void deleteObservers(Event* e = nullptr) = 0; // The only purpose of the argument is to enable function overloading
virtual size_t countObservers() = 0; virtual size_t countObservers(Event* e = nullptr) = 0; // The only purpose of the argument is to enable function overloading
virtual void notifyObservers(const Event* e = nullptr) = 0; virtual void notifyObservers(const Event* e = nullptr) = 0;
}; };
#define OBSERVABLE_SELECT(Event) (Event*)nullptr
} // namespace common } // namespace common
} // namespace hos } // namespace hos
@@ -16,36 +16,39 @@
namespace hos { namespace hos {
namespace common { namespace common {
#define OBSERVABLE_IMPL(Event) \ #define OBSERVABLE_IMPL(Event) OBSERVABLE_IMPL2(Event, observers)
#define OBSERVABLE_IMPL2(Event, memberBaseName) \
protected: \ protected: \
std::mutex __listenersLock; \ std::mutex __ ## memberBaseName ## Mutex; \
std::unordered_set<hos::common::IObserver<Event>*> __listeners; \ std::unordered_set<hos::common::IObserver<Event>*> __ ## memberBaseName; \
public: \ public: \
virtual void addObserver(hos::common::IObserver<Event>& o) { \ virtual void addObserver(hos::common::IObserver<Event>& o) { \
std::lock_guard<std::mutex> lock(__listenersLock); \ std::lock_guard<std::mutex> lock(__ ## memberBaseName ## Mutex); \
auto elem = __listeners.find(&o); \ auto elem = __ ## memberBaseName.find(&o); \
if (elem == __listeners.end()) { \ if (elem == __ ## memberBaseName.end()) { \
__listeners.insert(&o); \ __ ## memberBaseName.insert(&o); \
} \ } \
} \ } \
virtual void deleteObserver(hos::common::IObserver<Event>& o) { \ virtual void deleteObserver(hos::common::IObserver<Event>& o) { \
std::lock_guard<std::mutex> lock(__listenersLock); \ std::lock_guard<std::mutex> lock(__ ## memberBaseName ## Mutex); \
auto elem = __listeners.find(&o); \ auto elem = __ ## memberBaseName.find(&o); \
if (elem != __listeners.end()) { \ if (elem != __ ## memberBaseName.end()) { \
__listeners.erase(elem); \ __ ## memberBaseName.erase(elem); \
} \ } \
} \ } \
virtual void deleteObservers() { \ virtual void deleteObservers(Event* e = nullptr) { \
std::lock_guard<std::mutex> lock(__listenersLock); \ std::lock_guard<std::mutex> lock(__ ## memberBaseName ## Mutex); \
__listeners.clear(); \ __ ## memberBaseName.clear(); \
} \ } \
virtual size_t countObservers() { \ virtual size_t countObservers(Event* e = nullptr) { \
return __listeners.size(); \ std::lock_guard<std::mutex> lock(__ ## memberBaseName ## Mutex); \
return __ ## memberBaseName.size(); \
} \ } \
virtual void notifyObservers(const Event* e = nullptr) { \ virtual void notifyObservers(const Event* e = nullptr) { \
std::lock_guard<std::mutex> lock(__listenersLock); \ std::lock_guard<std::mutex> lock(__ ## memberBaseName ## Mutex); \
for (hos::common::IObserver<Event>* l : __listeners) { \ for (hos::common::IObserver<Event>* l : __ ## memberBaseName) { \
l->notificationReceived(*this, e); \ l->notificationReceived(this, e); \
} \ } \
} }
+170
View File
@@ -0,0 +1,170 @@
cmake_minimum_required(VERSION 2.8.3)
project(hos_launch)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
hos_core_types
hos_cosgi_devicerepository
hos_cosgi_launcher
hos_cosgi_rulesengine
hos_cosgi_rulesexecution_python
hos_philips_hue
)
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)
## Uncomment this if the package has a setup.py. This macro ensures
## modules and global scripts declared therein get installed
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
# catkin_python_setup()
################################################
## Declare ROS messages, services and actions ##
################################################
## To declare and build messages, services or actions from within this
## package, follow these steps:
## * Let MSG_DEP_SET be the set of packages whose message types you use in
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
## * In the file package.xml:
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
## * If MSG_DEP_SET isn't empty the following dependencies might have been
## pulled in transitively but can be declared for certainty nonetheless:
## * add a build_depend tag for "message_generation"
## * add a run_depend tag for "message_runtime"
## * In this file (CMakeLists.txt):
## * add "message_generation" and every package in MSG_DEP_SET to
## find_package(catkin REQUIRED COMPONENTS ...)
## * add "message_runtime" and every package in MSG_DEP_SET to
## catkin_package(CATKIN_DEPENDS ...)
## * uncomment the add_*_files sections below as needed
## and list every .msg/.srv/.action file to be processed
## * uncomment the generate_messages entry below
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
## Generate messages in the 'msg' folder
# add_message_files(
# FILES
# Message1.msg
# Message2.msg
# )
## Generate services in the 'srv' folder
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
## Generate actions in the 'action' folder
# add_action_files(
# FILES
# Action1.action
# Action2.action
# )
## Generate added messages and services with any dependencies listed here
# generate_messages(
# DEPENDENCIES
# std_msgs # Or other packages containing msgs
# )
###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if you package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES hos_launch
# CATKIN_DEPENDS hos_core_types hos_cosgi_devicerepository hos_cosgi_launcher hos_cosgi_rulesengine hos_cosgi_rulesexecution_python hos_philips_hue
# DEPENDS system_lib
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
# include_directories(include)
include_directories(
${catkin_INCLUDE_DIRS}
)
## Declare a cpp library
# add_library(hos_launch
# src/${PROJECT_NAME}/hos_launch.cpp
# )
## Declare a cpp executable
# add_executable(hos_launch_node src/hos_launch_node.cpp)
## Add cmake target dependencies of the executable/library
## as an example, message headers may need to be generated before nodes
# add_dependencies(hos_launch_node hos_launch_generate_messages_cpp)
## Specify libraries to link a library or executable target against
# target_link_libraries(hos_launch_node
# ${catkin_LIBRARIES}
# )
#############
## Install ##
#############
install(DIRECTORY launch
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/
)
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
# install(TARGETS hos_launch hos_launch_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark other files for installation (e.g. launch and bag files, etc.)
# install(FILES
# # myfile1
# # myfile2
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
# )
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_hos_launch.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)
+4
View File
@@ -0,0 +1,4 @@
<launch>
<include file="$(find hos_core_types)/launch/setup_core_types.launch" />
<include file="$(find hos_philips_hue)/launch/hue_bridge.launch" />
</launch>
+13
View File
@@ -0,0 +1,13 @@
<launch>
<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
$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer.zip
$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer_syslog.zip
$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell.zip
$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell_tui.zip
$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_rulesexecution_python/hos_cosgi_rulesexecution_python.zip
$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_rulesengine/hos_cosgi_rulesengine.zip
$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_devicerepository/hos_cosgi_devicerepository.zip"/>
</node>
</launch>
+62
View File
@@ -0,0 +1,62 @@
<?xml version="1.0"?>
<package>
<name>hos_launch</name>
<version>0.0.0</version>
<description>The hos_launch package</description>
<!-- One maintainer tag required, multiple allowed, one person per tag -->
<!-- Example: -->
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
<maintainer email="matzman@todo.todo">matzman</maintainer>
<!-- One license tag required, multiple allowed, one license per tag -->
<!-- Commonly used license strings: -->
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
<license>TODO</license>
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
<!-- Optional attribute type can be: website, bugtracker, or repository -->
<!-- Example: -->
<!-- <url type="website">http://wiki.ros.org/hos_launch</url> -->
<!-- Author tags are optional, mutiple are allowed, one per tag -->
<!-- Authors do not have to be maintianers, but could be -->
<!-- Example: -->
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
<!-- The *_depend tags are used to specify dependencies -->
<!-- Dependencies can be catkin packages or system dependencies -->
<!-- Examples: -->
<!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> -->
<!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use run_depend for packages you need at runtime: -->
<!-- <run_depend>message_runtime</run_depend> -->
<!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend>
<build_depend>hos_core_types</build_depend>
<build_depend>hos_cosgi_devicerepository</build_depend>
<build_depend>hos_cosgi_launcher</build_depend>
<build_depend>hos_cosgi_rulesengine</build_depend>
<build_depend>hos_cosgi_rulesexecution_python</build_depend>
<build_depend>hos_philips_hue</build_depend>
<run_depend>hos_core_types</run_depend>
<run_depend>hos_cosgi_devicerepository</run_depend>
<run_depend>hos_cosgi_launcher</run_depend>
<run_depend>hos_cosgi_rulesengine</run_depend>
<run_depend>hos_cosgi_rulesexecution_python</run_depend>
<run_depend>hos_philips_hue</run_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>
+29 -13
View File
@@ -4,7 +4,9 @@ project(hos_libvariant)
## Find catkin macros and libraries ## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz) ## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages ## is used, also find other catkin packages
find_package(catkin REQUIRED) find_package(catkin REQUIRED COMPONENTS
roscpp
)
## System dependencies are found with CMake's conventions ## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system) # find_package(Boost REQUIRED COMPONENTS system)
@@ -77,8 +79,8 @@ find_package(catkin REQUIRED)
## DEPENDS: system dependencies of this project that dependent projects also need ## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package( catkin_package(
INCLUDE_DIRS include/hos_libvariant INCLUDE_DIRS include/hos_libvariant
LIBRARIES Variant LIBRARIES Variant hos_cpp_json
# CATKIN_DEPENDS other_catkin_pkg CATKIN_DEPENDS roscpp
# DEPENDS system_lib # DEPENDS system_lib
) )
@@ -89,8 +91,8 @@ catkin_package(
include(ExternalProject) include(ExternalProject)
ExternalProject_Add( libvariant_project ExternalProject_Add( libvariant_project
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/libvariant
CONFIGURE_COMMAND cmake ${CMAKE_CURRENT_SOURCE_DIR}/src CONFIGURE_COMMAND cmake ${CMAKE_CURRENT_SOURCE_DIR}/src/libvariant
-DCMAKE_INSTALL_PREFIX=${CATKIN_DEVEL_PREFIX} -DCMAKE_INSTALL_PREFIX=${CATKIN_DEVEL_PREFIX}
-DBUILD_SHARED_LIBS=TRUE -DBUILD_SHARED_LIBS=TRUE
-DLIBVARIANT_BUILD_EXAMPLES=FALSE -DLIBVARIANT_BUILD_EXAMPLES=FALSE
@@ -104,6 +106,17 @@ ExternalProject_Add( libvariant_project
INSTALL_COMMAND make install INSTALL_COMMAND make install
) )
add_definitions(
-std=c++11
-fPIC
)
include_directories(
${catkin_INCLUDE_DIRS}
include
include/hos_libvariant
)
add_library( Variant SHARED IMPORTED ) add_library( Variant SHARED IMPORTED )
set_property( TARGET Variant PROPERTY IMPORTED_LOCATION "${CATKIN_DEVEL_PREFIX}/lib/libVariant.so") set_property( TARGET Variant PROPERTY IMPORTED_LOCATION "${CATKIN_DEVEL_PREFIX}/lib/libVariant.so")
add_dependencies( Variant libvariant_project ) add_dependencies( Variant libvariant_project )
@@ -113,9 +126,12 @@ add_dependencies( Variant libvariant_project )
# include_directories(include) # include_directories(include)
## Declare a cpp library ## Declare a cpp library
# add_library(hos_libvariant add_library(hos_cpp_json STATIC
# src/${PROJECT_NAME}/hos_libvariant.cpp src/HosSchemaLoader/HosSchemaLoader.cpp
# ) )
target_link_libraries(hos_cpp_json
${catkin_LIBRARIES}
)
## Declare a cpp executable ## Declare a cpp executable
# add_executable(hos_libvariant_node src/hos_libvariant_node.cpp) # add_executable(hos_libvariant_node src/hos_libvariant_node.cpp)
@@ -159,11 +175,11 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake/
# ) # )
## Mark executables and/or libraries for installation ## Mark executables and/or libraries for installation
# install(TARGETS hos_libvariant hos_libvariant_node install(TARGETS hos_cpp_json
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# ) )
## Mark cpp header files for installation ## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/ # install(DIRECTORY include/${PROJECT_NAME}/
@@ -12,21 +12,26 @@
#include <ros/ros.h> #include <ros/ros.h>
#include <string> #include <string>
namespace hos {
class HosSchemaLoader: public libvariant::SchemaLoader { namespace hos {
namespace libvariant {
class HosSchemaLoader: public ::libvariant::SchemaLoader {
private: private:
std::string ros_param_ns; std::string ros_param_ns;
std::string prefix; std::string prefix;
ros::NodeHandle nodeHandle; ros::NodeHandle nodeHandle;
bool loadTypeSchema(std::string schema); bool loadTypeSchema(std::string schema);
public: public:
HosSchemaLoader(std::string ns = "/hos/types/repository", HosSchemaLoader(std::string ns = "/hos/types/repository", std::string prefix = "hos:schema://")
std::string prefix = "hos:schema://")
: ros_param_ns(ns), prefix(prefix), nodeHandle("~") {} : ros_param_ns(ns), prefix(prefix), nodeHandle("~") {}
virtual bool HandleMissing(const std::string &uri, LoaderError &error); virtual bool HandleMissing(const std::string &uri, LoaderError &error);
}; };
}
} // namespace libvariant
} // namespace hos
#endif /* SRC_HOSSCHEMALOADER_H_ */ #endif /* SRC_HOSSCHEMALOADER_H_ */
+2
View File
@@ -33,10 +33,12 @@
<!-- Examples: --> <!-- Examples: -->
<!-- Use build_depend for packages you need at compile time: --> <!-- Use build_depend for packages you need at compile time: -->
<!-- <build_depend>message_generation</build_depend> --> <!-- <build_depend>message_generation</build_depend> -->
<build_depend>roscpp</build_depend>
<!-- Use buildtool_depend for build tool packages: --> <!-- Use buildtool_depend for build tool packages: -->
<!-- <buildtool_depend>catkin</buildtool_depend> --> <!-- <buildtool_depend>catkin</buildtool_depend> -->
<!-- Use run_depend for packages you need at runtime: --> <!-- Use run_depend for packages you need at runtime: -->
<!-- <run_depend>message_runtime</run_depend> --> <!-- <run_depend>message_runtime</run_depend> -->
<run_depend>roscpp</run_depend>
<!-- Use test_depend for packages you need only for testing: --> <!-- Use test_depend for packages you need only for testing: -->
<!-- <test_depend>gtest</test_depend> --> <!-- <test_depend>gtest</test_depend> -->
<buildtool_depend>catkin</buildtool_depend> <buildtool_depend>catkin</buildtool_depend>
@@ -5,10 +5,12 @@
* Author: matzman * Author: matzman
*/ */
#include "HosSchemaLoader.h" #include <HosSchemaLoader/HosSchemaLoader.h>
namespace hos { namespace hos {
namespace libvariant {
bool HosSchemaLoader::HandleMissing(const std::string &uri, LoaderError &error) { bool HosSchemaLoader::HandleMissing(const std::string &uri, LoaderError &error) {
if (uri.compare(0, prefix.size(), prefix) == 0) { if (uri.compare(0, prefix.size(), prefix) == 0) {
@@ -23,7 +25,7 @@ bool HosSchemaLoader::loadTypeSchema(std::string schema) {
std::string pvalue; std::string pvalue;
nodeHandle.getParam(pkey, pvalue); nodeHandle.getParam(pkey, pvalue);
if (!pvalue.empty()) { if (!pvalue.empty()) {
libvariant::Variant v = libvariant::Deserialize(pvalue, libvariant::SERIALIZE_JSON); ::libvariant::Variant v = ::libvariant::Deserialize(pvalue, ::libvariant::SERIALIZE_JSON);
if (v.IsMap()) { if (v.IsMap()) {
std::string sk = std::string(prefix).append(schema); std::string sk = std::string(prefix).append(schema);
AddSchema(sk, v); AddSchema(sk, v);
@@ -36,5 +38,7 @@ bool HosSchemaLoader::loadTypeSchema(std::string schema) {
} }
} }
}
} }

Some files were not shown because too many files have changed in this diff Show More