This commit is contained in:
2015-05-09 17:13:01 +02:00
parent 9c132de686
commit 4e2fe033c9
145 changed files with 7213 additions and 1252 deletions
+208
View File
@@ -0,0 +1,208 @@
cmake_minimum_required(VERSION 2.8.3)
project(hos_cosgi_ruleengine)
## 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_devicerepository
hos_cosgi_launcher
hos_cosgi_scripting
hos_cpp_common
hos_libvariant
roscpp
hos_cpp_cron
)
## 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/${PROJECT_NAME}/
# LIBRARIES hos_cosgi_ruleengine
CATKIN_DEPENDS hos_celix hos_cosgi_common hos_cosgi_devicerepository hos_cosgi_launcher hos_cpp_common hos_libvariant roscpp hos_cpp_cron hos_cosgi_scripting
# 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/${PROJECT_NAME}/
${hos_libvariant_INCLUDE_DIRS}/hos_libvariant
)
set(BUNDLE_SYMBOLICNAME "hos.hos_ruleengine")
set(BUNDLE_VERSION "1.0.0")
set(BUNDLE_NAME "hos_ruleengine")
bundle(hos_cosgi_ruleengine
SOURCES
${PROJECT_SOURCE_DIR}/src/bundle_activator
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/ruleengine/rule/RulePackage
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/ruleengine/rule/Rule
${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/ruleengine/rule/RuleCondition
)
target_link_libraries(hos_cosgi_ruleengine
${catkin_LIBRARIES}
${APR_LIBRARIES}
)
## Declare a cpp library
# add_library(hos_cosgi_ruleengine
# src/${PROJECT_NAME}/hos_cosgi_ruleengine.cpp
# )
## Declare a cpp executable
# add_executable(hos_cosgi_ruleengine_node src/hos_cosgi_ruleengine_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_ruleengine_node hos_cosgi_ruleengine_generate_messages_cpp)
## Specify libraries to link a library or executable target against
# target_link_libraries(hos_cosgi_ruleengine_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_ruleengine.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_ruleengine hos_cosgi_ruleengine_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_ruleengine.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,36 @@
/*
* hos_ruleengine_service.h
*
* Created on: 26.04.2015
* Author: matzman
*/
#ifndef INCLUDE_HOS_COSGI_RULEENGINE_HOS_COSGI_SERVICE_RULEENGINE_RULEENGINE_SERVICE_H_
#define INCLUDE_HOS_COSGI_RULEENGINE_HOS_COSGI_SERVICE_RULEENGINE_RULEENGINE_SERVICE_H_
#include <hos/common/observable.h>
#include <hos/cosgi/service/interface.h>
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
class RuleEngineService : public virtual interface::Service {
public:
static constexpr const char* SERVICE_NAME = "hos_ruleengine_service";
};
} // namespace ruleengine
} // namespace service
} // namespace cosgi
} // namespace hos
#endif /* INCLUDE_HOS_COSGI_RULEENGINE_HOS_COSGI_SERVICE_RULEENGINE_RULEENGINE_SERVICE_H_ */
@@ -0,0 +1,8 @@
<launch>
<group ns="/hos/rules/ruleengine0">
<param name="rulepkg01" textfile="$(find hos_cosgi_ruleengine)/test/rulepkg01.json"/>
</group>
<node name="cosgi_ruleengine" 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_ruleengine/hos_cosgi_rulesngine.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>
</launch>
+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>"
}
]
}
@@ -0,0 +1,34 @@
<?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"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="rulesengine" nsURI="rulesengine" nsPrefix="rulesengine">
<eClassifiers xsi:type="ecore:EClass" name="RulesengineService">
<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"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="GlobalContext" abstract="true" interface="true"/>
<eClassifiers xsi:type="ecore:EClass" name="Rule">
<eStructuralFeatures xsi:type="ecore:EReference" lowerBound="1" upperBound="-1"
eType="#//RuleCondition" containment="true"/>
<eStructuralFeatures xsi:type="ecore:EReference" lowerBound="1" eType="#//RuleBody"
containment="true"/>
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="RuleCondition" abstract="true" interface="true"/>
<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 xsi:type="ecore:EClass" name="Device"/>
<eClassifiers xsi:type="ecore:EClass" name="DeviceCondition" eSuperTypes="#//RuleCondition">
<eStructuralFeatures xsi:type="ecore:EReference" eType="#//Device"/>
</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="PythonRuleBody" eSuperTypes="#//RuleBody"/>
</ecore:EPackage>
@@ -0,0 +1,462 @@
<?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="_khfdwPATEeSxkrcRRJC36Q" type="Ecore" name="rulesengine.ecore_diagram" measurementUnit="Pixel">
<children xmi:type="notation:Shape" xmi:id="_91SdQPATEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" fillColor="13369343" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:BasicDecorationNode" xmi:id="_91TrYPATEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_91TrYfATEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<styles xmi:type="notation:TextStyle" xmi:id="_91SdQfATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_91SdQvATEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_91SdQ_ATEeSxkrcRRJC36Q" x="260" y="175" width="736" height="316"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_0XNZQPATEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_0XNZQvATEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_0XNZQ_ATEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_0XNZRPATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_0XNZRfATEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_0XOAUPATEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_0XOAUfATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_0XOAUvATEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_0XOAU_ATEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_0XOAVPATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_0XOAVfATEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//RulesengineService"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_0XNZQfATEeSxkrcRRJC36Q" x="320" y="195"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_0XOAVvATEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_0XOAWPATEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_0XOAWfATEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_0XOAWvATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_0XOAW_ATEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_0XOAXPATEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_0XOAXfATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_0XOAXvATEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_0XOnYPATEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_0XOnYfATEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_0XOnYvATEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//RulePackage"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_0XOAV_ATEeSxkrcRRJC36Q" x="340" y="285"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_PWqCQPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_PWqpUPAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_PWqpUfAUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_PWqpUvAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_PWqpU_AUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_PWrQYPAUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_PWrQYfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_PWrQYvAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_PWrQY_AUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_PWrQZPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_PWrQZfAUEeSxkrcRRJC36Q"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//GlobalContext"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_PWqCQfAUEeSxkrcRRJC36Q" x="340" y="375"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_TCtdQPAUEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_TCtdQvAUEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_TCuEUPAUEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_TCuEUfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_TCuEUvAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_TCuEU_AUEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_TCuEVPAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_TCuEVfAUEeSxkrcRRJC36Q"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_TCuEVvAUEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_TCuEV_AUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_TCuEWPAUEeSxkrcRRJC36Q"/>
</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>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//RuleBody"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_d_GSUfAUEeSxkrcRRJC36Q" x="525" y="390"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_xqbNcPAUEeSxkrcRRJC36Q" type="rectangle" fontName="Sans" fillColor="13369343" transparency="0" lineColor="6737151" lineWidth="1">
<children xmi:type="notation:BasicDecorationNode" xmi:id="_xqb0gPAUEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_xqb0gfAUEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<styles xmi:type="notation:TextStyle" xmi:id="_xqbNcfAUEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_xqbNcvAUEeSxkrcRRJC36Q"/>
<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>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//GlobalPythonContext"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_b1wVUfAWEeSxkrcRRJC36Q" x="315" y="555"/>
</children>
<children xmi:type="notation:Shape" xmi:id="_fg_4APAWEeSxkrcRRJC36Q" type="2001" fontName="Sans">
<children xmi:type="notation:DecorationNode" xmi:id="_fg_4AvAWEeSxkrcRRJC36Q" type="5001"/>
<children xmi:type="notation:BasicCompartment" xmi:id="_fg_4A_AWEeSxkrcRRJC36Q" type="7001">
<styles xmi:type="notation:SortingStyle" xmi:id="_fg_4BPAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_fg_4BfAWEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_aJ8zcPAZEeSxkrcRRJC36Q" value="0.23076923076923078"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_fhAfEPAWEeSxkrcRRJC36Q" type="7002">
<styles xmi:type="notation:SortingStyle" xmi:id="_fhAfEfAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_fhAfEvAWEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_aJ9agPAZEeSxkrcRRJC36Q" value="0.23076923076923078"/>
</children>
<children xmi:type="notation:BasicCompartment" xmi:id="_fhAfE_AWEeSxkrcRRJC36Q" type="7003">
<styles xmi:type="notation:SortingStyle" xmi:id="_fhAfFPAWEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:FilteringStyle" xmi:id="_fhAfFfAWEeSxkrcRRJC36Q"/>
<layoutConstraint xmi:type="notation:Ratio" xmi:id="_aJ-BkPAZEeSxkrcRRJC36Q" value="0.23076923076923078"/>
</children>
<element xmi:type="ecore:EClass" href="rulesengine.ecore#//PythonRuleBody"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_fg_4AfAWEeSxkrcRRJC36Q" x="500" y="555"/>
</children>
<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:BasicDecorationNode" xmi:id="_Vgdf0PAZEeSxkrcRRJC36Q" type="DiagramName">
<element xsi:nil="true"/>
</children>
<children xmi:type="notation:BasicDecorationNode" xmi:id="_VgeG4PAZEeSxkrcRRJC36Q" type="Description">
<element xsi:nil="true"/>
</children>
<styles xmi:type="notation:TextStyle" xmi:id="_Vgc4wfAZEeSxkrcRRJC36Q"/>
<styles xmi:type="notation:LineTypeStyle" xmi:id="_Vgc4wvAZEeSxkrcRRJC36Q"/>
<element xsi:nil="true"/>
<layoutConstraint xmi:type="notation:Bounds" xmi:id="_Vgc4w_AZEeSxkrcRRJC36Q" x="425" y="510" width="96" height="28"/>
</children>
<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#/"/>
<edges xmi:type="notation:Connector" xmi:id="_Mc8qMPAUEeSxkrcRRJC36Q" type="4003" source="_0XNZQPATEeSxkrcRRJC36Q" target="_0XOAVvATEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_Mc94UPAUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_Mc94UfAUEeSxkrcRRJC36Q" y="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_Mc94UvAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_Mc94U_AUEeSxkrcRRJC36Q" x="-3" y="23"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_Mc8qMfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulesengineService/%"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_Mc8qMvAUEeSxkrcRRJC36Q" points="[3, 26, 4, -94]$[39, 94, 40, -26]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_RxHSgPAUEeSxkrcRRJC36Q" type="4003" source="_0XOAVvATEeSxkrcRRJC36Q" target="_PWqCQPAUEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_RxHSg_AUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_RxHShPAUEeSxkrcRRJC36Q" y="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_RxHShfAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_RxHShvAUEeSxkrcRRJC36Q" y="60"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_RxHSgfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulePackage/%"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_RxHSgvAUEeSxkrcRRJC36Q" points="[2, 26, 3, -94]$[2, 146, 3, 26]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_UwwTcPAUEeSxkrcRRJC36Q" type="4003" source="_0XOAVvATEeSxkrcRRJC36Q" target="_TCtdQPAUEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_UwwTc_AUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_UwwTdPAUEeSxkrcRRJC36Q" y="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_UwwTdfAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_UwwTdvAUEeSxkrcRRJC36Q" y="11"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_UwwTcfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//RulePackage/%.1"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_UwwTcvAUEeSxkrcRRJC36Q" points="[49, -6, -149, -6]$[203, -26, 5, -26]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_Y_PGEPAUEeSxkrcRRJC36Q" type="4003" source="_TCtdQPAUEeSxkrcRRJC36Q" target="_WagfgPAUEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_Y_PGE_AUEeSxkrcRRJC36Q" type="6002">
<layoutConstraint xmi:type="notation:Location" xmi:id="_Y_PGFPAUEeSxkrcRRJC36Q" y="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_Y_PGFfAUEeSxkrcRRJC36Q" type="6004">
<layoutConstraint xmi:type="notation:Location" xmi:id="_Y_PGFvAUEeSxkrcRRJC36Q" x="-1" y="30"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_Y_PGEfAUEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//Rule/%"/>
<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 xmi:type="notation:Connector" xmi:id="_fgudIPAUEeSxkrcRRJC36Q" type="4003" source="_TCtdQPAUEeSxkrcRRJC36Q" target="_d_GSUPAUEeSxkrcRRJC36Q">
<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"/>
<bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_IWWLwvAVEeSxkrcRRJC36Q" points="[-53, -5, 103, -5]$[-104, -5, 52, -5]"/>
</edges>
<edges xmi:type="notation:Connector" xmi:id="_Irc5EPAVEeSxkrcRRJC36Q" type="4004" source="_BixmMPAVEeSxkrcRRJC36Q" target="_WagfgPAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_Irc5EfAVEeSxkrcRRJC36Q" fontName="Sans"/>
<element xsi:nil="true"/>
<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 xmi:type="notation:Connector" xmi:id="_JBCukPAVEeSxkrcRRJC36Q" type="4004" source="_-EWXgPAUEeSxkrcRRJC36Q" target="_WagfgPAUEeSxkrcRRJC36Q">
<styles xmi:type="notation:FontStyle" xmi:id="_JBCukfAVEeSxkrcRRJC36Q" fontName="Sans"/>
<element xsi:nil="true"/>
<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 xmi:type="notation:Connector" xmi:id="_KiM_UPAVEeSxkrcRRJC36Q" type="4002" source="_-EWXgPAUEeSxkrcRRJC36Q" target="_6VdD4PAUEeSxkrcRRJC36Q">
<children xmi:type="notation:DecorationNode" xmi:id="_KiNmYPAVEeSxkrcRRJC36Q" type="6001">
<layoutConstraint xmi:type="notation:Location" xmi:id="_KiNmYfAVEeSxkrcRRJC36Q" y="40"/>
</children>
<children xmi:type="notation:DecorationNode" xmi:id="_KiNmYvAVEeSxkrcRRJC36Q" type="6003">
<layoutConstraint xmi:type="notation:Location" xmi:id="_KiNmY_AVEeSxkrcRRJC36Q" x="-3" y="23"/>
</children>
<styles xmi:type="notation:FontStyle" xmi:id="_KiM_UfAVEeSxkrcRRJC36Q" fontName="Sans"/>
<element xmi:type="ecore:EReference" href="rulesengine.ecore#//DeviceCondition/%"/>
<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>
</notation:Diagram>
+68
View File
@@ -0,0 +1,68 @@
<?xml version="1.0"?>
<package>
<name>hos_cosgi_ruleengine</name>
<version>0.0.0</version>
<description>The hos_cosgi_ruleengine 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_ruleengine</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_devicerepository</build_depend>
<build_depend>hos_cosgi_launcher</build_depend>
<build_depend>hos_cosgi_scripting</build_depend>
<build_depend>hos_cpp_common</build_depend>
<build_depend>hos_libvariant</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>hos_cpp_cron</build_depend>
<run_depend>hos_celix</run_depend>
<run_depend>hos_cosgi_common</run_depend>
<run_depend>hos_cosgi_devicerepository</run_depend>
<run_depend>hos_cosgi_launcher</run_depend>
<run_depend>hos_cpp_common</run_depend>
<run_depend>hos_libvariant</run_depend>
<run_depend>roscpp</run_depend>
<run_depend>hos_cpp_cron</run_depend>
<run_depend>hos_cosgi_scripting</run_depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
</export>
</package>
@@ -0,0 +1,174 @@
/*
* 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 "celix/bundle_activator.h"
#include "celix/bundle_context.h"
#include "celix/service_listener.h"
#include "celix/service_reference.h"
#include "celix/constants.h"
}
#include <hos/cosgi/service/core/core_service.h>
#include "hos/cosgi/service/ruleengine/ruleengine_serviceimpl.h"
#include <memory>
#include <mutex>
using namespace hos::cosgi::service::ruleengine;
using namespace hos::cosgi::service::scripting;
using namespace hos::cosgi::service::devicerepository;
using namespace hos::cosgi::service::core;
using namespace hos::cosgi;
struct UserData {
apr_pool_t* memoryPool = nullptr;
std::unique_ptr<RuleEngineServiceImpl> 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, DeviceRepositoryService::SERVICE_NAME) == 0) {
DeviceRepositoryService *service = nullptr;
bundleContext_getService(myUserData->bundleContext, event->reference, (void**)&service);
myUserData->serviceImpl->setRepoService(service);
checkReg = true;
} else if (serviceName && std::strcmp(serviceName, ScriptingService::SERVICE_NAME) == 0) {
ScriptingService *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*)RuleEngineServiceImpl::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_START_ERROR;
apr_pool_t* memoryPool = nullptr;
// Create APR memory pool
apr_status_t astatus = apr_pool_create(&memoryPool, NULL);
if (astatus != APR_SUCCESS) {
ROS_ERROR("RuleEngineService: 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("RuleEngineService: Bundle successfully created");
} else {
ROS_ERROR("RuleEngineService: 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-devicerepository-service
if (myUserData->serviceReg != nullptr) {
serviceRegistration_unregister(myUserData->serviceReg);
myUserData->serviceReg = nullptr;
}
myUserData->serviceImpl.reset(new RuleEngineServiceImpl());
// Get HOS Core Service
service_reference_pt ref = nullptr;
bundleContext_getServiceReference(context, (char*)CoreService::SERVICE_NAME, &ref);
CoreService* coreService = nullptr;
bundleContext_getService(context, ref, (void**)&coreService);
if (coreService == nullptr) {
ROS_ERROR("RuleEngineService: 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*)DeviceRepositoryService::SERVICE_NAME, &ref2);
DeviceRepositoryService* 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*)RuleEngineServiceImpl::SERVICE_NAME, myUserData->serviceImpl.get(), nullptr, &myUserData->serviceReg);
}
// Register service listener
myUserData->myServiceListener.handle = myUserData;
myUserData->myServiceListener.serviceChanged = cb_serviceChanged;
bundleContext_addServiceListener(context, &myUserData->myServiceListener, nullptr);
ROS_INFO("RuleEngineService: Bundle successfully started");
} else {
ROS_ERROR("RuleEngineService: 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("RuleEngineService: Bundle successfully stopped");
status = CELIX_SUCCESS;
} else {
ROS_ERROR("RuleEngineService: 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("RuleEngineService: Bundle successfully destroyed");
} else {
ROS_ERROR("RuleEngineService: Could not destroy bundle, there is no APR memory pool");
}
status = CELIX_SUCCESS;
} else {
ROS_ERROR("RuleEngineService: Could not destroy bundle, user data struct is null");
}
return status;
}
@@ -0,0 +1,62 @@
/*
* Rule.cpp
*
* Created on: 29.04.2015
* Author: matzman
*/
#include "Rule.h"
#include <hos/cosgi/service/scripting/scripting_service.h>
#include "RuleCondition.h"
#include <ros/ros.h>
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
namespace rule {
Rule::Rule(RulePackage* parent, std::string name, scripting::ScriptingService* executionService)
: parent(parent), name(name), executionService(executionService) {}
Rule::~Rule() {}
std::shared_ptr<Rule> Rule::createRule(RulePackage* parent, std::string name, scripting::GlobalScriptContext* gContext, Variant raw, scripting::ScriptingService* executionService) {
std::shared_ptr<Rule> retval;
if (raw.IsMap()) {
retval = std::make_shared<Rule>(parent, name, executionService);
if (raw.HasPath("conditions") && raw["conditions"].IsList()) {
auto conditions = raw["conditions"];
for (auto c : conditions.AsList()) {
auto cond = RuleCondition::createRuleCondition(retval.get(), c);
retval->conditions.push_back(cond);
}
if (raw.HasPath("body") && raw["body"].IsMap()) {
retval->body = executionService->createScript(gContext, raw["body"]);
} else {
ROS_ERROR_STREAM("Could not create rule \"" << name << "\".");
retval.reset();
}
} else {
ROS_ERROR_STREAM("Could not create rule \"" << name << "\".");
retval.reset();
}
}
return retval;
}
void Rule::exec(scripting::GlobalScriptContext* gContext) {
body->exec(gContext);
}
} /* namespace rule */
} /* namespace ruleengine */
} /* namespace service */
} /* namespace cosgi */
} /* namespace hos */
@@ -0,0 +1,75 @@
/*
* Rule.h
*
* Created on: 29.04.2015
* Author: matzman
*/
#ifndef SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULE_H_
#define SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULE_H_
#include <string>
#include <memory>
#include <vector>
#include <Variant/Variant.h>
// Forward declarations
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
namespace rule {
class RulePackage;
class RuleCondition;
}
}
namespace scripting {
class ScriptingService;
class GlobalScriptContext;
class Script;
}
}
}
}
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
namespace rule {
using namespace libvariant;
class Rule {
private:
RulePackage* parent;
std::string name;
std::shared_ptr<scripting::Script> body;
std::vector<std::shared_ptr<RuleCondition>> conditions;
scripting::ScriptingService* executionService;
public:
Rule(RulePackage* parent, std::string name, scripting::ScriptingService* executionService);
static std::shared_ptr<Rule> createRule(RulePackage* parent, std::string name, scripting::GlobalScriptContext* gContext, Variant raw, scripting::ScriptingService* executionService);
virtual ~Rule();
RulePackage* getParent() { return parent; }
virtual void exec(scripting::GlobalScriptContext* gContext);
};
class RuleBody {
};
} /* namespace rule */
} /* namespace ruleengine */
} /* namespace service */
} /* namespace cosgi */
} /* namespace hos */
#endif /* SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULE_H_ */
@@ -0,0 +1,27 @@
/*
* RuleCondition.cpp
*
* Created on: 29.04.2015
* Author: matzman
*/
#include "RuleCondition.h"
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
namespace rule {
std::shared_ptr<RuleCondition> RuleCondition::createRuleCondition(Rule* parent, Variant raw) {
std::shared_ptr<RuleCondition> retval;
return retval;
}
} /* namespace rule */
} /* namespace ruleengine */
} /* namespace service */
} /* namespace cosgi */
} /* namespace hos */
@@ -0,0 +1,125 @@
/*
* RuleCondition.h
*
* Created on: 29.04.2015
* Author: matzman
*/
#ifndef SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULECONDITION_H_
#define SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULECONDITION_H_
#include <memory>
#include <Variant/Variant.h>
#include <hos/common/observable.h>
// Forward declarations
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
namespace rule {
class Rule;
class ConditionDeviceStatusMsgEvent;
class ConditionDeviceCommandMsgEvent;
class ConditionDeviceStateChangedEvent;
class ConditionSystemEvent;
}
}
}
}
}
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
namespace rule {
using namespace libvariant;
class RuleCondition {
public:
enum class Type : int { DeviceStatusMsg, DeviceCommandMsg, DeviceStateChange, TimeEventCondition, SystemEventCondition};
protected:
Rule* parent;
const Type type;
public:
static std::shared_ptr<RuleCondition> createRuleCondition(Rule* parent, libvariant::Variant raw);
RuleCondition(Rule* parent, Type type) : parent(parent), type(type) {}
public:
virtual ~RuleCondition() {}
const Type getType() { return type; }
};
class DeviceMsgCondition : public RuleCondition {
friend class RuleCondition;
protected:
Variant msgValue;
std::string msgPath;
std::string deviceID;
DeviceMsgCondition(Rule* parent, Type type, const Variant msgValue, const std::string msgPath, std::string deviceID)
: RuleCondition(parent, type) {}
};
class DeviceStatusMsgCondition : public DeviceMsgCondition, public common::IObserver<std::string, ConditionDeviceStatusMsgEvent> {
friend class RuleCondition;
protected:
DeviceStatusMsgCondition(Rule* parent, const Variant msgValue, const std::string msgPath, std::string deviceID)
: DeviceMsgCondition(parent, Type::DeviceStatusMsg, msgValue, msgPath, deviceID) {}
public:
virtual void notificationReceived(common::Observable<std::string, ConditionDeviceStatusMsgEvent>* o, const std::string key, const ConditionDeviceStatusMsgEvent* e) override;
};
class DeviceCommandMsgCondition : public DeviceMsgCondition, public common::IObserver<std::string, ConditionDeviceCommandMsgEvent> {
friend class RuleCondition;
protected:
public:
DeviceCommandMsgCondition(Rule* parent, const Variant msgValue, const std::string msgPath, std::string deviceID)
: DeviceMsgCondition(parent, Type::DeviceCommandMsg, msgValue, msgPath, deviceID) {}
virtual void notificationReceived(common::Observable<std::string, ConditionDeviceCommandMsgEvent>* o, const std::string key, const ConditionDeviceCommandMsgEvent* e) override;
};
class DeviceStateChangeCondition : public RuleCondition, public common::IObserver<std::string, ConditionDeviceStateChangedEvent> {
friend class RuleCondition;
protected:
public:
DeviceStateChangeCondition(Rule* parent) : RuleCondition(parent, Type::DeviceStateChange) {}
virtual void notificationReceived(common::Observable<std::string, ConditionDeviceStateChangedEvent>* o, const std::string key, const ConditionDeviceStateChangedEvent* e) override;
};
class TimeEventCondition : public RuleCondition {
friend class RuleCondition;
protected:
public:
TimeEventCondition(Rule* parent) : RuleCondition(parent, Type::TimeEventCondition) {}
};
class SystemEventCondition : public RuleCondition, public common::IObserver<std::string, ConditionSystemEvent> {
friend class RuleCondition;
protected:
public:
SystemEventCondition(Rule* parent) : RuleCondition(parent, Type::SystemEventCondition) {}
virtual void notificationReceived(common::Observable<std::string, ConditionSystemEvent>* o, const std::string key, const ConditionSystemEvent* e) override;
};
} /* namespace rule */
} /* namespace ruleengine */
} /* namespace service */
} /* namespace cosgi */
} /* namespace hos */
#endif /* SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULECONDITION_H_ */
@@ -0,0 +1,79 @@
/*
* RulePackage.cpp
*
* Created on: 29.04.2015
* Author: matzman
*/
#include "RulePackage.h"
#include <ros/ros.h>
#include <exception>
#include <Variant/Variant.h>
#include "../ruleengine_serviceimpl.h"
#include "Rule.h"
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
namespace rule {
RulePackage::RulePackage(service::ruleengine::RuleEngineServiceImpl* parent, std::string name)
: parent(parent), name(name) {}
RulePackage::~RulePackage() {
}
std::shared_ptr<RulePackage> RulePackage::createRulePackage(service::ruleengine::RuleEngineServiceImpl* parent, std::string name, Variant raw) {
std::shared_ptr<RulePackage> retval;
if (raw.IsMap()) {
retval = std::make_shared<RulePackage>(parent, name);
if (raw.HasPath("language") && raw["language"].IsString()) {
retval->language = raw["language"].AsString();
} else {
throw std::runtime_error("Rule package JSON is missing language parameter or parameter has wrong type.");
}
retval->executionService = parent->getExecutionBackend(retval->language);
if (retval->executionService) {
if (raw.HasPath("globalcontext")) {
retval->globalContext = retval->executionService->createGlobalScriptContext(raw["globalcontext"]);
}
if (raw.HasPath("rules") && raw["rules"].IsMap()) {
for (auto r : raw["rules"].AsMap()) {
std::shared_ptr<Rule> rule = Rule::createRule(retval.get(), r.first, retval->globalContext.get(), r.second, retval->executionService);
if (rule) {
retval->rules.insert({r.first, rule});
}
}
if (retval->rules.size() == 0) {
throw std::runtime_error("Rule package has no rules.");
}
} else {
throw std::runtime_error("Rule package JSON is missing rules parameter or parameter has wrong type.");
}
retval->setState(State::Ok);
} else {
retval->setState(State::NoExecService);
}
} 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 rule */
} /* namespace ruleengine */
} /* namespace service */
} /* namespace cosgi */
} /* namespace hos */
@@ -0,0 +1,87 @@
/*
* RulePackage.h
*
* Created on: 29.04.2015
* Author: matzman
*/
#ifndef SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULEPACKAGE_H_
#define SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULEPACKAGE_H_
#include <hos/cosgi/service/scripting/scripting_service.h>
#include <vector>
#include <map>
#include <memory>
#include <string>
#include <Variant/Variant.h>
// Forward declarations
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
class RuleEngineServiceImpl;
namespace rule {
class Rule;
}
}
namespace scripting {
class GlobalScriptContext;
}
}
}
}
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
namespace rule {
using namespace ::libvariant;
class RulePackage {
public:
enum class State : int { Error = 0, NoExecService = 1, Ok = 2 };
private:
typedef std::map<std::string, std::shared_ptr<Rule>> ruleMap_t;
std::string name;
std::string language;
State state = State::Error;
ruleMap_t rules;
std::shared_ptr<scripting::GlobalScriptContext> globalContext;
service::ruleengine::RuleEngineServiceImpl* parent;
service::scripting::ScriptingService* executionService = nullptr;
bool setState(State state) {
this->state = state;
return true;
}
public:
RulePackage(service::ruleengine::RuleEngineServiceImpl* parent, std::string name);
static std::shared_ptr<RulePackage> createRulePackage(service::ruleengine::RuleEngineServiceImpl* parent, std::string name, Variant raw);
virtual ~RulePackage();
std::shared_ptr<Rule> getRule(const std::string& name) { return rules[name]; }
size_t getRules(std::vector<std::shared_ptr<Rule>>& rules);
service::ruleengine::RuleEngineServiceImpl* getParent() { return parent; }
State getState() { return state; }
};
} /* namespace rule */
} /* namespace ruleengine */
} /* namespace service */
} /* namespace cosgi */
} /* namespace hos */
#endif /* SRC_HOS_COSGI_SERVICE_RULEENGINE_RULE_RULEPACKAGE_H_ */
@@ -0,0 +1,165 @@
/*
* hos_ruleengine_service_impl.cpp
*
* Created on: 26.04.2015
* Author: matzman
*/
#include "ruleengine_serviceimpl.h"
#include <ros/ros.h>
#include <exception>
#include <iostream>
#include <unordered_set>
#include <celix/bundle_context.h>
#include <hos/cosgi/service/core/core_service.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <Variant/Variant.h>
#include "rule/RulePackage.h"
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
template<> const char* implementation::ServiceInfo<RuleEngineServiceImpl>::name = service::ruleengine::RuleEngineService::SERVICE_NAME;
template<> const int implementation::ServiceInfo<RuleEngineServiceImpl>::major = 0;
template<> const int implementation::ServiceInfo<RuleEngineServiceImpl>::minor = 6;
void RuleEngineServiceImpl::setCoreService(service::core::CoreService* coreService) {
if (coreService && !this->coreService) {
this->coreService = coreService;
this->nodehandle = coreService->getPrivateNodeHandle();
int major = 0, minor = 0;
coreService->getServiceVersion(major, minor);
ROS_INFO_STREAM("RuleEngineService: Found HOSCoreService Version " << major << "." << minor);
if (repoService) {
init();
}
}
}
void RuleEngineServiceImpl::setRepoService(devicerepository::DeviceRepositoryService* repoService) {
if (repoService && !this->repoService) {
this->repoService = repoService;
int major = 0, minor = 0;
repoService->getServiceVersion(major, minor);
ROS_INFO_STREAM("RuleEngineService: Found HOSDeviceRepositoryService Version " << major << "." << minor);
if (coreService) {
init();
}
}
}
void RuleEngineServiceImpl::init() {
nodehandle->getParam("ruleengine_prefix", ruleEnginePrefix);
XmlRpc::XmlRpcValue rawValue;
nodehandle->getParam(ruleEnginePrefix, rawValue);
schemaLoader.reset(new libvariant::HosSchemaLoader());
if (rawValue.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
for (auto pkg : rawValue) {
std::string pname = pkg.first;
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("RuleEngineService: Initialized and Ready.");
}
RuleEngineServiceImpl::~RuleEngineServiceImpl() {
repoService->deleteObserver(this);
}
void RuleEngineServiceImpl::notificationReceived(interface::Observer<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) {
switch (e->eventType) {
case devicerepository::DeviceEvent::EventType::STATUS_UPDATED:
{
ConditionDeviceStatusMsgEvent event;
common::Observable<std::string, ConditionDeviceStatusMsgEvent>::notifyObservers(e->device->getDeviceID(), &event);
if (e->device->stateChanged()) {
ConditionDeviceStateChangedEvent event;
common::Observable<std::string, ConditionDeviceStateChangedEvent>::notifyObservers(e->device->getDeviceID(), &event);
}
}
break;
case devicerepository::DeviceEvent::EventType::COMMAND_RECEIVED:
{
ConditionDeviceCommandMsgEvent event;
common::Observable<std::string, ConditionDeviceCommandMsgEvent>::notifyObservers(e->device->getDeviceID(), &event);
}
break;
default:
break;
}
}
void RuleEngineServiceImpl::addRulePkg(std::string name) {
std::stringstream ss;
ss << ruleEnginePrefix << "/" << name;
XmlRpc::XmlRpcValue rawValue;
nodehandle->getParam(ss.str(), rawValue);
addRulePkg(name, static_cast<std::string>(rawValue));
}
void RuleEngineServiceImpl::addRulePkg(std::string name, std::string rawValue) {
::libvariant::Variant s = schemaLoader->GetSchema(std::string("hos:schema://core/configs/rulepackage"));
::libvariant::Variant m = ::libvariant::Deserialize(rawValue, ::libvariant::SERIALIZE_JSON);
::libvariant::SchemaResult sr = ::libvariant::SchemaValidate(s, m, schemaLoader.get());
if (!sr.Error()) {
std::shared_ptr<rule::RulePackage> pkg = rule::RulePackage::createRulePackage(this, name, m);
if (pkg) {
if (pkg->getState() == rule::RulePackage::State::Ok) {
rulePkgs.insert({name, pkg});
} else if (pkg->getState() == rule::RulePackage::State::NoExecService) {
noExecRulePkgs.insert({name, pkg});
std::cout << "No execution service found for rule package \"" << name << "\"" << std::endl;
} else {
throw std::runtime_error("Unknown state");
}
}
} else {
throw std::runtime_error(sr.PrettyPrintMessage());
}
}
void RuleEngineServiceImpl::removeRulePkg(std::string name) {
rulePkgs.erase(name);
}
void RuleEngineServiceImpl::addExecutionBackend(scripting::ScriptingService* service) {
if (execServices.find(service->getLanguage()) == execServices.end()) {
execServices.insert({service->getLanguage(), service});
ROS_INFO_STREAM("RuleEngineService: Added execution service \"" << service->getLanguage() << "\".");
}
}
scripting::ScriptingService* RuleEngineServiceImpl::getExecutionBackend(std::string language) {
auto s = execServices.find(language);
if (s != execServices.end()) {
return s->second;
}
return nullptr;
}
} // namespace ruleengine
} // namespace service
} // namespace cosgi
} // namespace hos
@@ -0,0 +1,140 @@
/*
* hos_ruleengine_service_impl.h
*
* Created on: 26.04.2015
* Author: matzman
*/
#ifndef INCLUDE_HOS_COSGI_RULEENGINE_HOS_RULEENGINE_SERVICE_IMPL_H_
#define INCLUDE_HOS_COSGI_RULEENGINE_HOS_RULEENGINE_SERVICE_IMPL_H_
#include <hos/cosgi/service/implementation.h>
#include <Variant/Variant.h>
#include <mutex>
#include <map>
#include <set>
#include <hos_core_msgs/DeviceCommand.h>
#include <hos_core_msgs/DeviceStatusUpdate.h>
#include <hos_core_msgs/HosStatusUpdate.h>
#include <hos/cosgi/service/ruleengine/ruleengine_service.h>
#include <hos/cosgi/service/scripting/scripting_service.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <HosSchemaLoader/HosSchemaLoader.h>
#include <ros/ros.h>
#include <map>
#include <memory>
// Forward declarations
namespace XmlRpc {
class XmlRpcValue;
}
namespace hos {
namespace cosgi {
namespace service {
namespace core {
class CoreService;
}
namespace ruleengine {
namespace rule {
class RulePackage;
}
}
}
namespace devicerepository {
class DeviceRepositoryService;
class DeviceEvent;
}
}
}
// Service Namespace
namespace hos {
namespace cosgi {
namespace service {
namespace ruleengine {
class ConditionDeviceStatusMsgEvent {
};
class ConditionDeviceCommandMsgEvent {
};
class ConditionDeviceStateChangedEvent {
};
class ConditionSystemEvent {
};
class RuleEngineServiceImpl;
class RuleEngineServiceImpl : public virtual RuleEngineService,
public virtual implementation::Service<RuleEngineServiceImpl>,
public virtual interface::Observer<devicerepository::DeviceEvent>,
public common::Observable<std::string, ConditionDeviceStatusMsgEvent>,
public common::Observable<std::string, ConditionDeviceCommandMsgEvent>,
public common::Observable<std::string, ConditionDeviceStateChangedEvent>,
public common::Observable<std::string, ConditionSystemEvent> {
private:
typedef std::map<std::string, std::shared_ptr<rule::RulePackage>> rulePkgMap_t;
typedef std::map<std::string, scripting::ScriptingService*> execServiceMap_t;
service::core::CoreService* coreService = nullptr;
devicerepository::DeviceRepositoryService* repoService = nullptr;
ros::NodeHandle* nodehandle = nullptr;
std::string ruleEnginePrefix = "/hos/rules/ruleengine0";
rulePkgMap_t rulePkgs;
rulePkgMap_t noExecRulePkgs;
execServiceMap_t execServices;
std::unique_ptr<libvariant::HosSchemaLoader> schemaLoader;
bool initialized = false;
void addRulePkg(std::string name);
void addRulePkg(std::string name, std::string rawValue);
void removeRulePkg(std::string name);
void init();
public:
~RuleEngineServiceImpl();
/* Initialization */
void setCoreService(service::core::CoreService* coreService);
void setRepoService(devicerepository::DeviceRepositoryService* repoService);
/* Public Service Implementations */
/* Observer Callbacks */
virtual void notificationReceived(interface::Observer<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) override;
/* Internal Stuff */
bool isInitialized() { return initialized; }
void addExecutionBackend(scripting::ScriptingService* service);
scripting::ScriptingService* getExecutionBackend(std::string language);
};
} // namespace ruleengine
} // namespace service
} // namespace cosgi
} // namespace hos
#endif /* INCLUDE_HOS_COSGI_RULEENGINE_HOS_RULEENGINE_SERVICE_IMPL_H_ */
@@ -0,0 +1,32 @@
{
"language": "python",
"globalcontext": { "code": "print \"GlobalContext: Init!\"\nvar1 = 66.6"},
"rules": {
"rule01": {
"conditions": [
{
"type": "devicemsg",
"deviceid": "huelight1"
},
{
"type": "devicestatus",
"deviceid": "huelight1"
}
],
"body": { "code": "print \"Hello World1\"" }
},
"rule02": {
"conditions": [
{
"type": "devicemsg",
"deviceid": "huelight2"
},
{
"type": "devicestatus",
"deviceid": "huelight2"
}
],
"body": { "code": "print \"Hello World2\"" }
}
}
}