From 3626b45dfc1d7fe5dd5b2e954152dc170649d41f Mon Sep 17 00:00:00 2001 From: Matthias Janetschek Date: Fri, 22 May 2015 16:40:23 +0200 Subject: [PATCH] . --- .gitignore | 3 + .../hos/cosgi/service/Implementation.h | 124 +++++++++---- .../hos/cosgi/service/Interface.h | 37 ++-- .../hos/cosgi/service/core/CoreService.h | 2 + src/hos_cosgi_devicerepository/CMakeLists.txt | 4 +- .../DeviceRepositoryService.h | 174 ++++++++++++++++++ .../devicerepository_service.h | 148 --------------- ...ndle_activator.cpp => BundleActivator.cpp} | 2 +- ...pl.cpp => DeviceRepositoryServiceImpl.cpp} | 131 +++++++------ ...ceimpl.h => DeviceRepositoryServiceImpl.h} | 93 +++++----- .../cosgi/service/ruleengine/rule/Rule.cpp | 2 +- .../ruleengine/rule/RuleConditionImpl.cpp | 43 +++-- .../ruleengine/rule/RuleConditionImpl.h | 30 +-- .../ruleengine/ruleengine_serviceimpl.cpp | 33 +--- .../ruleengine/ruleengine_serviceimpl.h | 10 +- .../src/bundle_activator.cpp | 2 +- .../cosgi/service/scripting/python/PyHOSAPI.h | 6 +- .../python/scripting_serviceimpl.cpp | 2 +- .../scripting/python/scripting_serviceimpl.h | 2 +- .../resources/DevicesHTTPResource.cpp | 12 +- .../webserver/resources/DevicesHTTPResource.h | 2 +- .../service/webserver/webserver_serviceimpl.h | 2 +- src/hos_launch/launch/hos_cosgi.launch | 22 +-- 23 files changed, 491 insertions(+), 395 deletions(-) create mode 100644 src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/DeviceRepositoryService.h delete mode 100644 src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/devicerepository_service.h rename src/hos_cosgi_devicerepository/src/{bundle_activator.cpp => BundleActivator.cpp} (98%) rename src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/{devicerepository_serviceimpl.cpp => DeviceRepositoryServiceImpl.cpp} (66%) rename src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/{devicerepository_serviceimpl.h => DeviceRepositoryServiceImpl.h} (50%) diff --git a/.gitignore b/.gitignore index 4ae88f35..6f7c248c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,6 @@ /install/ **/*.pyc /env.bash +/env.sh +/src/hos_deps/deps-install/ +/src/hos_deps/deps-tmp/ diff --git a/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/Implementation.h b/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/Implementation.h index 408d09fc..dfa476f3 100644 --- a/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/Implementation.h +++ b/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/Implementation.h @@ -34,6 +34,14 @@ struct ServiceInfo { +/** + * Implementation of interface::Object. + */ +class Object + : public virtual interface::Object {}; + + + /** * Implementation of interface::Service. */ @@ -48,7 +56,7 @@ public: * * \return service name. **/ - virtual const char* getServiceName() { + virtual const char* getServiceName() noexcept override { return ServiceInfo<_Service>::name; }; @@ -58,7 +66,7 @@ public: * \param[out] major version major number. * \param[out] minor version minor number. */ - virtual void getServiceVersion(int& major, int& minor) override { + virtual void getServiceVersion(int& major, int& minor) noexcept override { major = ServiceInfo<_Service>::major; minor = ServiceInfo<_Service>::minor; } @@ -76,6 +84,15 @@ template class Observable {}; +/** + * Convenience template merging the Object class and the Observable template into a single template. + */ +template class ObservableObject + : public virtual Object, + public virtual Observable<_Args...> {}; + + + /** * Convenience template merging the Service class and the Observable template into a single template. */ @@ -98,7 +115,7 @@ protected: typedef std::unordered_set::observer_type*> observers_type; - std::mutex _observersMutex; + std::recursive_mutex _observersMutex; observers_type _observers; @@ -111,14 +128,16 @@ public: * * \param[in] o observer to be registered. */ - virtual void addObserver(typename interface::Observable<_Event>::observer_type* o) override { - std::lock_guard lock(_observersMutex); + virtual bool addObserver(typename interface::Observable<_Event>::observer_type* o) noexcept override { + std::lock_guard lock(_observersMutex); if (o != nullptr) { auto elem = _observers.find(o); if (elem == _observers.end()) { _observers.insert(o); + return true; } } + return false; } /** @@ -126,21 +145,23 @@ public: * * \param[in] o observer to be unregistered. */ - virtual void deleteObserver(typename interface::Observable<_Event>::observer_type* o) override { - std::lock_guard lock(_observersMutex); + virtual bool deleteObserver(typename interface::Observable<_Event>::observer_type* o) noexcept override { + std::lock_guard lock(_observersMutex); if (o != nullptr) { auto elem = _observers.find(o); if (elem != _observers.end()) { _observers.erase(elem); + return true; } } + return false; } /** * Unregisters all observers. */ - virtual void deleteObservers() override { - std::lock_guard lock(_observersMutex); + virtual void deleteObservers() noexcept override { + std::lock_guard lock(_observersMutex); _observers.clear(); }; @@ -149,8 +170,8 @@ public: * * \return number of registered observers. */ - virtual size_t countObservers() override { - std::lock_guard lock(_observersMutex); + virtual size_t countObservers() noexcept override { + std::lock_guard lock(_observersMutex); return _observers.size(); } @@ -158,12 +179,18 @@ public: * Notify observers of a new event. * * \param[in] e event. + * \return notified observer count. */ - virtual void notifyObservers(const _Event* e) override { - std::lock_guard lock(_observersMutex); - for (auto l : _observers) { + virtual size_t notifyObservers(const _Event* e) noexcept override { + std::lock_guard lock(_observersMutex); + size_t retval = 0; + // We work with a copy so that we can insert/remove observers within a callback. + observers_type tmp = _observers; + for (auto l : tmp) { l->notificationReceived(this, e); + retval++; } + return retval; } }; @@ -183,7 +210,7 @@ protected: typedef std::unordered_multimap<_Key, typename interface::Observable<_Key, _Event>::observer_type*> observers_type; - std::mutex _observersMutex; + std::recursive_mutex _observersMutex; observers_type _observers; @@ -197,21 +224,23 @@ public: * \param[in] k filter key. * \param[in] o observer to be registered. */ - virtual void addObserver(_Key k, typename interface::Observable<_Key, _Event>::observer_type* o) override { - std::lock_guard lock(_observersMutex); + virtual bool addObserver(const _Key& k, typename interface::Observable<_Key, _Event>::observer_type* o) noexcept override { + std::lock_guard lock(_observersMutex); if (o != nullptr) { bool _found = false; auto range = _observers.equal_range(k); for (auto i = range.first; i != range.second; i++) { - if (i.second == o) { + if (i->second == o) { _found = true; break; } } if (!_found) { _observers.insert({k, o}); + return true; } } + return false; } /** @@ -220,25 +249,50 @@ public: * \param[in] k filter key. * \param[in] o observer to be unregistered. */ - virtual void deleteObserver(_Key k, typename interface::Observable<_Key, _Event>::observer_type* o) override { - std::lock_guard lock(_observersMutex); + virtual bool deleteObserver(const _Key& k, typename interface::Observable<_Key, _Event>::observer_type* o) noexcept override { + std::lock_guard lock(_observersMutex); if (o != nullptr) { bool _found = false; auto range = _observers.equal_range(k); for (auto i = range.first; i != range.second; i++) { - if (i.second == o) { + if (i->second == o) { _observers.erase(i); - break; + return true; } } } + return false; + } + + /** + * Unregisters an observer from all filter keys. + * + * \param[in] o observer to be unregistered. + */ + virtual bool deleteObserver(typename interface::Observable<_Key, _Event>::observer_type* o) noexcept override { + std::lock_guard lock(_observersMutex); + bool retval = false; + if (o != nullptr) { + // Quick and dirty, needs to be replaced with a proper implementation + auto found = std::find_if(_observers.begin(), _observers.end(), [=](const typename Observable<_Key, _Event>::observers_type::value_type& v)->bool { + return v.second == o; + }); + while ( found != _observers.end()) { + _observers.erase(found); + retval = true; + found = std::find_if(_observers.begin(), _observers.end(), [=](const typename Observable<_Key, _Event>::observers_type::value_type& v)->bool { + return v.second == o; + }); + } + } + return retval; } /** * Unregisters all observers. */ - virtual void deleteObservers() override { - std::lock_guard lock(_observersMutex); + virtual void deleteObservers() noexcept override { + std::lock_guard lock(_observersMutex); _observers.clear(); } @@ -247,8 +301,8 @@ public: * * \return number of registered observers. */ - virtual size_t countObservers() override { - std::lock_guard lock(_observersMutex); + virtual size_t countObservers() noexcept override { + std::lock_guard lock(_observersMutex); return _observers.size(); } @@ -257,13 +311,19 @@ public: * * \param[in] k observer filter key. * \param[in] e event. + * \return notified observer count. */ - void notifyObservers(_Key k, const _Event* e) override { - std::lock_guard lock(_observersMutex); - auto ol = _observers.equal_range(k); - std::for_each(ol.first, ol.second, [&](const typename interface::Observable<_Key, _Event>::observer_type::value_type& o) { - o.second->notificationReceived(this, k, e); - }); + size_t notifyObservers(const _Key& k, const _Event* e) noexcept override { + std::lock_guard lock(_observersMutex); + size_t retval = 0; + // We work with a copy so that we can insert/remove observers within a callback. + observers_type tmp = _observers; + auto ol = tmp.equal_range(k); + for (auto i = ol.first; i != ol.second; i++) { + i->second->notificationReceived(this, k, e); + retval++; + } + return retval; } }; diff --git a/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/Interface.h b/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/Interface.h index 95d273ec..463e047c 100644 --- a/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/Interface.h +++ b/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/Interface.h @@ -46,7 +46,7 @@ public: * * \return service name. **/ - virtual const char* getServiceName() = 0; + virtual const char* getServiceName() noexcept = 0 ; /** * Returns the version of the service. @@ -58,7 +58,7 @@ public: * \param[out] major version major number. * \param[out] minor version minor number. */ - virtual void getServiceVersion(int& major, int& minor) = 0; + virtual void getServiceVersion(int& major, int& minor) noexcept = 0; }; @@ -120,7 +120,7 @@ public: * \param[in] o observable object emitting the event. * \param[in] e the event (can be null). */ - virtual void notificationReceived(observable_type* o, const _Event* e) = 0; + virtual void notificationReceived(observable_type* o, const _Event* e) noexcept = 0; }; @@ -148,7 +148,7 @@ public: * \param[in] key the filter key. * \param[in] e the event (can be null). */ - virtual void notificationReceived(observable_type* o, const _Key& key, const _Event* e) = 0; + virtual void notificationReceived(observable_type* o, const _Key& key, const _Event* e) noexcept = 0; }; @@ -175,33 +175,34 @@ public: * * \param[in] o observer to be registered. */ - virtual void addObserver(observer_type* o) = 0; + virtual bool addObserver(observer_type* o) noexcept = 0; /** * Unregisters an observer. * * \param[in] o observer to be unregistered. */ - virtual void deleteObserver(observer_type* o) = 0; + virtual bool deleteObserver(observer_type* o) noexcept = 0; /** * Unregisters all observers. */ - virtual void deleteObservers() = 0; + virtual void deleteObservers() noexcept = 0; /** * Returns the number of registered observers. * * \return number of registered observers. */ - virtual size_t countObservers() = 0; + virtual size_t countObservers() noexcept = 0; /** * Notify observers of a new event. * * \param[in] e event. + * \return notified observer count. */ - virtual void notifyObservers(const _Event* e) = 0; + virtual size_t notifyObservers(const _Event* e) noexcept = 0; }; @@ -230,7 +231,7 @@ public: * \param[in] key filter key. * \param[in] o observer to be registered. */ - virtual void addObserver(_Key& key, observer_type* o) = 0; + virtual bool addObserver(const _Key& key, observer_type* o) noexcept = 0; /** * Unregisters an observer. @@ -238,27 +239,35 @@ public: * \param[in] key filter key. * \param[in] o observer to be unregistered. */ - virtual void deleteObserver(_Key& key, observer_type* o) = 0; + virtual bool deleteObserver(const _Key& key, observer_type* o) noexcept = 0; + + /** + * Unregisters an observer from all filter keys. + * + * \param[in] o observer to be unregistered. + */ + virtual bool deleteObserver(observer_type* o) noexcept = 0; /** * Unregisters all observers. */ - virtual void deleteObservers() = 0; + virtual void deleteObservers() noexcept = 0; /** * Returns the number of registered observers. * * \return number of registered observers. */ - virtual size_t countObservers() = 0; + virtual size_t countObservers() noexcept = 0; /** * Notify observers of a new event. * * \param[in] key observer filter key. * \param[in] e event. + * \return notified observer count. */ - virtual void notifyObservers(const _Key& key, const _Event* e) = 0; + virtual size_t notifyObservers(const _Key& key, const _Event* e) noexcept = 0; }; diff --git a/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/core/CoreService.h b/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/core/CoreService.h index 32a5aacb..7409c2d0 100644 --- a/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/core/CoreService.h +++ b/src/hos_cosgi_core/include/hos_cosgi_core/hos/cosgi/service/core/CoreService.h @@ -28,7 +28,9 @@ namespace core { class CoreServiceEvent { public: typedef std::chrono::system_clock::time_point timestamp_t; + enum class EventType : int { STARTUP_FINISHED = 1, SHUTDOWN = 2 }; + const EventType eventType; const timestamp_t timestamp; diff --git a/src/hos_cosgi_devicerepository/CMakeLists.txt b/src/hos_cosgi_devicerepository/CMakeLists.txt index 9a8c42b7..35bda688 100644 --- a/src/hos_cosgi_devicerepository/CMakeLists.txt +++ b/src/hos_cosgi_devicerepository/CMakeLists.txt @@ -120,8 +120,8 @@ set(BUNDLE_NAME "hos_devicerepository") bundle(hos_cosgi_devicerepository SOURCES - ${PROJECT_SOURCE_DIR}/src/bundle_activator - ${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl + ${PROJECT_SOURCE_DIR}/src/BundleActivator + ${PROJECT_SOURCE_DIR}/src/hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl ) target_link_libraries(hos_cosgi_devicerepository ${catkin_LIBRARIES} diff --git a/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/DeviceRepositoryService.h b/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/DeviceRepositoryService.h new file mode 100644 index 00000000..53b9890f --- /dev/null +++ b/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/DeviceRepositoryService.h @@ -0,0 +1,174 @@ +#ifndef _HOS_DEVICEREPOSITORY_SERVICE_H_ +#define _HOS_DEVICEREPOSITORY_SERVICE_H_ + + +#include +#include +#include +#include +#include +#include + + + +// Service Namespace +namespace hos { +namespace cosgi { +namespace service { +namespace devicerepository { + + +// Forward declarations +class Device; + + +using namespace libvariant; + + + +/** + * Base class for device events. + */ +class DeviceEvent { +public: + typedef std::chrono::system_clock::time_point timestamp_t; + + enum class EventType : int { + DEVICE_ADDED = 1, + DEVICE_REMOVED = 2, + STATUS_UPDATE_RECEIVED = 3, + COMMAND_RECEIVED = 4, + STATE_CHANGED = 5 + }; + + Device* const device; + const timestamp_t timestamp; + const EventType eventType; + + DeviceEvent(Device* device, const EventType& type, const timestamp_t& timestamp) + : device(device), timestamp(timestamp), eventType(type) {} +}; + + + + /** + * Device added event. + */ +class DeviceAddedEvent + : public DeviceEvent { +public: + DeviceAddedEvent(Device* device, const timestamp_t& timestamp) + : DeviceEvent(device, DeviceEvent::EventType::DEVICE_ADDED, timestamp) {} +}; + + + +/** + * Device removed event. + */ +class DeviceRemovedEvent + : public DeviceEvent { +public: + DeviceRemovedEvent(Device* device, const timestamp_t& timestamp) + : DeviceEvent(device, DeviceEvent::EventType::DEVICE_REMOVED, timestamp) {} +}; + + + +/** + * Device status message received event. + */ +class DeviceStatusMsgEvent + : public DeviceEvent { +public: + const Variant statusMsg; + + DeviceStatusMsgEvent(Device* device, const Variant& statusMsg, const timestamp_t& timestamp) + : DeviceEvent(device, DeviceEvent::EventType::STATUS_UPDATE_RECEIVED, timestamp), statusMsg(statusMsg) {} +}; + + + +/** + * Device command message received event. + */ +class DeviceCmdMsgEvent + : public DeviceEvent { +public: + const Variant cmdMsg; + + DeviceCmdMsgEvent(Device* device, const Variant& cmdMsg, const timestamp_t& timestamp) + : DeviceEvent(device, DeviceEvent::EventType::COMMAND_RECEIVED, timestamp), cmdMsg(cmdMsg) {} +}; + + + +/** + * Device state change event. + */ +class DeviceStateChangeEvent + : public DeviceEvent { +public: + const Variant statusMsg; + + DeviceStateChangeEvent(Device* device, const Variant& statusMsg, const timestamp_t& timestamp) + : DeviceEvent(device, DeviceEvent::EventType::STATE_CHANGED, timestamp), statusMsg(statusMsg) {} +}; + + + +/** + * Public COSGI interface of an device object. + */ +class Device + : public virtual interface::ObservableObject { + +public: + + typedef std::chrono::system_clock::time_point timestamp_t; + + virtual const std::string& getDeviceID() noexcept = 0; + virtual const std::string& getDeviceType() noexcept = 0; + + virtual const std::string& getCmdTopic() noexcept = 0; + virtual const std::string& getStatusTopic() noexcept = 0; + + virtual const Variant& getCurrentState() noexcept = 0; + virtual const timestamp_t& getCurrentStateTimestamp() noexcept = 0; + + virtual const Variant& getLastState() noexcept = 0; + virtual const timestamp_t& getLastStateTimestamp() noexcept = 0; + + virtual void sendCommand(const Variant& cmd) = 0; + +}; + + + +/** + * Public COSGI interface of the device repository service + **/ +class DeviceRepositoryService + : public virtual interface::ObservableService { + +public: + + static constexpr const char* SERVICE_NAME = "hos_devicerepository_service"; + + virtual std::weak_ptr getDevice(const std::string& device_id) noexcept = 0; + virtual std::vector> getDevices() noexcept = 0; + virtual size_t deviceCount() noexcept = 0; + virtual std::vector getDeviceIDs() noexcept = 0; + +}; + + + +} // namespace devicerepository +} // namespace service +} // namespace cosgi +} // namespace hos + + + +#endif /* _HOS_DEVICEREPOSITORY_SERVICE_H_ */ diff --git a/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/devicerepository_service.h b/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/devicerepository_service.h deleted file mode 100644 index 20b25f8e..00000000 --- a/src/hos_cosgi_devicerepository/include/hos_cosgi_devicerepository/hos/cosgi/service/devicerepository/devicerepository_service.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef _HOS_DEVICEREPOSITORY_SERVICE_H_ -#define _HOS_DEVICEREPOSITORY_SERVICE_H_ - - -#include -#include -#include -#include -#include -#include -#include - - - -// Service Namespace -namespace hos { -namespace cosgi { -namespace service { -namespace devicerepository { - - -// Forward declarations -class Device; - - -using namespace libvariant; - - - -/** - * Base class for device events. - */ -class DeviceEvent { -public: - typedef std::chrono::system_clock::time_point timestamp_t; - enum class EventType : int { DEVICE_ADDED = 1, DEVICE_REMOVED = 2, STATUS_UPDATED = 3, COMMAND_RECEIVED = 4 }; - Device* const device; - const timestamp_t timestamp; - const EventType eventType; - - DeviceEvent(Device* device, EventType type, const timestamp_t timestamp) - : device(device), timestamp(timestamp), eventType(type) {} -}; - - - - /** - * Device added event. - */ -class DeviceAddedEvent - : public DeviceEvent { -public: - DeviceAddedEvent(Device* device, const timestamp_t timestamp) - : DeviceEvent(device, DeviceEvent::EventType::DEVICE_ADDED, timestamp) {} -}; - - - -/** - * Device removed event. - */ -class DeviceRemovedEvent - : public DeviceEvent { -public: - DeviceRemovedEvent(Device* device, const timestamp_t timestamp) - : DeviceEvent(device, DeviceEvent::EventType::DEVICE_REMOVED, timestamp) {} -}; - - - -/** - * Device status message received event. - */ -class DeviceStatusMsgEvent - : public DeviceEvent { -public: - DeviceStatusMsgEvent(Device* device, const Variant statusMsg, const timestamp_t timestamp) - : DeviceEvent(device, DeviceEvent::EventType::STATUS_UPDATED, timestamp), statusMsg(statusMsg) {} - const Variant statusMsg; -}; - - - -/** - * Device command message received event. - */ -class DeviceCmdMsgEvent - : public DeviceEvent { -public: - DeviceCmdMsgEvent(Device* device, const Variant cmdMsg, const timestamp_t timestamp) - : DeviceEvent(device, DeviceEvent::EventType::COMMAND_RECEIVED, timestamp), cmdMsg(cmdMsg) {} - const Variant cmdMsg; -}; - - - -/** - * Public COSGI interface of an device object. - */ -class Device - : public virtual interface::ObservableObject { - -public: - - typedef std::chrono::system_clock::time_point timestamp_t; - - virtual const std::string& getDeviceID() = 0; - virtual const std::string& getDeviceType() = 0; - - virtual const std::string& getCmdTopic() = 0; - virtual const std::string& getStatusTopic() = 0; - - virtual const Variant& getCurrentState() = 0; - virtual const timestamp_t& getCurrentStateTimestamp() = 0; - - virtual const Variant& getLastState() = 0; - virtual const timestamp_t& getLastStateTimestamp() = 0; - - virtual void sendCommand(const Variant cmd) = 0; - -}; - - - -/** - * Public Interface of the device repository service - **/ -class DeviceRepositoryService - : public virtual interface::ObservableService { -public: - static constexpr const char* SERVICE_NAME = "hos_devicerepository_service"; - - virtual std::shared_ptr getDevice(std::string device_id) = 0; - virtual size_t getDevices(std::vector>& devices) = 0; - virtual size_t deviceCount() = 0; - virtual std::set deviceIDs() = 0; -}; - - - -} // namespace devicerepository -} // namespace service -} // namespace cosgi -} // namespace hos - - - -#endif /* _HOS_DEVICEREPOSITORY_SERVICE_H_ */ diff --git a/src/hos_cosgi_devicerepository/src/bundle_activator.cpp b/src/hos_cosgi_devicerepository/src/BundleActivator.cpp similarity index 98% rename from src/hos_cosgi_devicerepository/src/bundle_activator.cpp rename to src/hos_cosgi_devicerepository/src/BundleActivator.cpp index 82c16af8..5a9e4ca1 100644 --- a/src/hos_cosgi_devicerepository/src/bundle_activator.cpp +++ b/src/hos_cosgi_devicerepository/src/BundleActivator.cpp @@ -12,7 +12,7 @@ extern "C" { } #include -#include "hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h" +#include "hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl.h" #include #include diff --git a/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.cpp b/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl.cpp similarity index 66% rename from src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.cpp rename to src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl.cpp index b0abdb61..6bd098a4 100644 --- a/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.cpp +++ b/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl.cpp @@ -5,7 +5,7 @@ * Author: matzman */ -#include "devicerepository_serviceimpl.h" +#include "DeviceRepositoryServiceImpl.h" #include #include @@ -23,31 +23,39 @@ namespace devicerepository { template<> const char* implementation::ServiceInfo::name = service::devicerepository::DeviceRepositoryService::SERVICE_NAME; -template<> const int implementation::ServiceInfo::major = 0; -template<> const int implementation::ServiceInfo::minor = 4; +template<> const int implementation::ServiceInfo::major = 1; +template<> const int implementation::ServiceInfo::minor = 0; -DeviceImpl::DeviceImpl(DeviceRepositoryServiceImpl* parent, std::string deviceID, std::string type, std::string statusTopic, std::string cmdTopic) - : parent(parent), deviceID(deviceID), deviceType(type), statusTopic(statusTopic), cmdTopic(cmdTopic) { - std::cout << "GenericDeviceImpl(" << deviceID << ", " << type << ", " << statusTopic << ", " << cmdTopic << ")" << std::endl; -} - -void DeviceImpl::handleStatusMsg(Variant& msg, const timestamp_t& stamp) { - std::lock_guard lock(objMutex); - lastState = currentState.Copy(); - currentState.Merge(msg); +bool DeviceImpl::handleStatusMsg(const Variant& msg, const timestamp_t& stamp) { + std::lock_guard lock(objMutex); + Variant tmp = currentState.Copy(); + tmp.Merge(msg); + bool stateChanged = false; + if (tmp != currentState) { // state has changed + lastState = currentState.Copy(); + lastStamp = currentStamp; + currentState = std::move(tmp); + currentStamp = stamp; + stateChanged = true; + } DeviceStatusMsgEvent event(this, msg, stamp); - notifyObservers(&event); + notifyObservers(DeviceEvent::EventType::STATUS_UPDATE_RECEIVED, &event); + if (stateChanged){ + DeviceStateChangeEvent event(this, msg, stamp); + notifyObservers(DeviceEvent::EventType::STATE_CHANGED, &event); + } + return stateChanged; } -void DeviceImpl::handleCommandMsg(Variant& msg, const timestamp_t& stamp) { - std::lock_guard lock(objMutex); +void DeviceImpl::handleCommandMsg(const Variant& msg, const timestamp_t& stamp) { + std::lock_guard lock(objMutex); DeviceCmdMsgEvent event(this, msg, stamp); - notifyObservers(&event); + notifyObservers(DeviceEvent::EventType::COMMAND_RECEIVED, &event); } -void DeviceImpl::sendCommand(const Variant cmd) { - std::lock_guard lock(objMutex); +void DeviceImpl::sendCommand(const Variant& cmd) { + std::lock_guard lock(objMutex); parent->sendDeviceCommand(this, cmd); } @@ -80,12 +88,11 @@ void DeviceRepositoryServiceImpl::init() { } } hosStatusSub = nodehandle->subscribe(hosStatusTopic, 1000, &DeviceRepositoryServiceImpl::hosStatusMsgCallback, this); - schemaLoader.reset(new utils::SchemaLoader()); initialized = true; ROS_INFO_STREAM("DeviceRepositoryService: Initialized and Ready."); } -void DeviceRepositoryServiceImpl::addDevice(std::string name) { +void DeviceRepositoryServiceImpl::addDevice(const std::string& name) { std::stringstream ss; ss << deviceRepositoryPrefix << "/" << name; XmlRpc::XmlRpcValue rawValue; @@ -93,7 +100,7 @@ void DeviceRepositoryServiceImpl::addDevice(std::string name) { addDevice(name, rawValue); } -void DeviceRepositoryServiceImpl::addDevice(std::string name, XmlRpc::XmlRpcValue& rawValue) { +void DeviceRepositoryServiceImpl::addDevice(const std::string& name, XmlRpc::XmlRpcValue& rawValue) { std::lock_guard lock(serviceMutex); std::string type, statusTopic, cmdTopic; XmlRpc::XmlRpcValue& typeRaw = rawValue["type"]; @@ -147,46 +154,50 @@ void DeviceRepositoryServiceImpl::addDevice(std::string name, XmlRpc::XmlRpcValu // send device added event DeviceAddedEvent event(dev.get(), std::chrono::system_clock::now()); - notifyObservers(&event); + notifyObservers(DeviceEvent::EventType::DEVICE_ADDED, &event); } -void DeviceRepositoryServiceImpl::removeDevice(std::string name) { +void DeviceRepositoryServiceImpl::removeDevice(const std::string& name) { std::lock_guard lock(serviceMutex); - auto& dev = devices[name]; - if (dev) { - DeviceRemovedEvent event(dev.get(), std::chrono::system_clock::now()); - notifyObservers(&event); - dev->notifyObservers(&event); + auto dev = devices.find(name); + if (dev != devices.end()) { + DeviceRemovedEvent event(dev->second.get(), std::chrono::system_clock::now()); + notifyObservers(DeviceEvent::EventType::DEVICE_REMOVED, &event); + dev->second->notifyObservers(DeviceEvent::EventType::DEVICE_REMOVED, &event); devices.erase(name); } } -std::shared_ptr DeviceRepositoryServiceImpl::getDevice(std::string device_id) { - return std::static_pointer_cast(this->devices[device_id]); +std::weak_ptr DeviceRepositoryServiceImpl::getDevice(const std::string& device_id) noexcept { + try { + return std::static_pointer_cast(this->devices.at(device_id)); + } catch (...) { + return std::weak_ptr(); + } } -size_t DeviceRepositoryServiceImpl::getDevices(std::vector>& devices) { +std::vector> DeviceRepositoryServiceImpl::getDevices() noexcept { std::lock_guard lock(serviceMutex); - size_t retval = 0; + std::vector> retval; for (auto item : this->devices) { - devices.push_back(std::static_pointer_cast(item.second)); - retval++; + retval.push_back(std::static_pointer_cast(item.second)); } return retval; } -size_t DeviceRepositoryServiceImpl::deviceCount() { +size_t DeviceRepositoryServiceImpl::deviceCount() noexcept { return devices.size(); } -std::set DeviceRepositoryServiceImpl::deviceIDs() { - std::set retval; +std::vector DeviceRepositoryServiceImpl::getDeviceIDs() noexcept { + std::lock_guard lock(serviceMutex); + std::vector retval; for (auto d : devices) { - retval.insert(d.first); + retval.push_back(d.first); } return retval; } @@ -195,16 +206,20 @@ std::set DeviceRepositoryServiceImpl::deviceIDs() { void DeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::DeviceStatusUpdate::ConstPtr& msg) { std::lock_guard lock(serviceMutex); std::cout << "HOSDeviceRepositoryServiceImpl::statusMsgCallback" << std::endl; - Variant s = schemaLoader->GetSchema(std::string("hos:schema://").append(msg->device_type).append("/status")); + Variant s = coreService->getSchemaLoader().GetSchema(std::string("hos:schema://").append(msg->device_type).append("/status")); Variant m = Deserialize(msg->msg_body, SERIALIZE_JSON); - SchemaResult sr = SchemaValidate(s, m, schemaLoader.get()); + SchemaResult sr = SchemaValidate(s, m, &coreService->getSchemaLoader()); if (!sr.Error()) { - std::shared_ptr dev = std::static_pointer_cast(devices[msg->device_id]); - if (dev) { + auto dev = devices.find(msg->device_id); + if (dev != devices.end()) { auto stamp = std::chrono::system_clock::now(); - dev->handleStatusMsg(m, stamp); - DeviceStatusMsgEvent event(dev.get(), m, stamp); - notifyObservers(&event); + bool stateChanged = dev->second->handleStatusMsg(m, stamp); + DeviceStatusMsgEvent event(dev->second.get(), m, stamp); + notifyObservers(DeviceEvent::EventType::STATUS_UPDATE_RECEIVED, &event); + if (stateChanged) { + DeviceStateChangeEvent event(dev->second.get(), m, stamp); + notifyObservers(DeviceEvent::EventType::STATE_CHANGED, &event); + } } } else { ROS_ERROR_STREAM("Could not validate status message: " << sr.PrettyPrintMessage()); @@ -214,17 +229,17 @@ void DeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::DeviceS void DeviceRepositoryServiceImpl::cmdMsgCallback(const hos_core_msgs::DeviceCommand::ConstPtr& msg) { std::lock_guard lock(serviceMutex); std::cout << "HOSDeviceRepositoryServiceImpl::cmdMsgCallback" << std::endl; - Variant s = schemaLoader->GetSchema(std::string("hos:schema://").append(msg->device_type).append("/command")); + Variant s = coreService->getSchemaLoader().GetSchema(std::string("hos:schema://").append(msg->device_type).append("/command")); Variant m = Deserialize(msg->msg_body, SERIALIZE_JSON); auto test = msg->stamp; - SchemaResult sr = SchemaValidate(s, m, schemaLoader.get()); + SchemaResult sr = SchemaValidate(s, m, &coreService->getSchemaLoader()); if (!sr.Error()) { - std::shared_ptr dev = std::static_pointer_cast(devices[msg->device_id]); - if (dev != nullptr) { + auto dev = devices.find(msg->device_id); + if (dev != devices.end()) { auto stamp = std::chrono::system_clock::now(); - dev->handleCommandMsg(m, stamp); - DeviceCmdMsgEvent event(dev.get(), m, stamp); - notifyObservers(&event); + dev->second->handleCommandMsg(m, stamp); + DeviceCmdMsgEvent event(dev->second.get(), m, stamp); + notifyObservers(DeviceEvent::EventType::STATUS_UPDATE_RECEIVED, &event); } } else { ROS_ERROR_STREAM("Could not validate command message: " << sr.PrettyPrintMessage()); @@ -234,9 +249,9 @@ void DeviceRepositoryServiceImpl::cmdMsgCallback(const hos_core_msgs::DeviceComm void DeviceRepositoryServiceImpl::hosStatusMsgCallback(const hos_core_msgs::HosStatusUpdate::ConstPtr& msg) { std::lock_guard lock(serviceMutex); std::cout << "HOSDeviceRepositoryServiceImpl::hosStatusMsgCallback" << std::endl; - Variant s = schemaLoader->GetSchema(std::string("hos:schema://core/msgs/hosstatusupdate")); + Variant s = coreService->getSchemaLoader().GetSchema(std::string("hos:schema://core/msgs/hosstatusupdate")); Variant m = Deserialize(msg->msg_body, SERIALIZE_JSON); - SchemaResult sr = SchemaValidate(s, m, schemaLoader.get()); + SchemaResult sr = SchemaValidate(s, m, &coreService->getSchemaLoader()); if (!sr.Error()) { if (m.Contains("devices")) { auto d = m["devices"]; @@ -254,7 +269,7 @@ void DeviceRepositoryServiceImpl::hosStatusMsgCallback(const hos_core_msgs::HosS for (auto dev : d["removed"].AsList()) { if (dev.IsString()) { std::string devname = dev.AsString(); - if (devices.find(devname) == devices.end()) { + if (devices.find(devname) != devices.end()) { removeDevice(devname); } } @@ -269,15 +284,15 @@ void DeviceRepositoryServiceImpl::hosStatusMsgCallback(const hos_core_msgs::HosS void DeviceRepositoryServiceImpl::sendDeviceCommand(Device* device, const Variant& cmd) { auto schemaUrl = (boost::format("hos:schema://%1%/command") % device->getDeviceType()).str(); - Variant s = schemaLoader->GetSchema(schemaUrl); - SchemaResult sr = SchemaValidate(s, cmd, schemaLoader.get()); + Variant s = coreService->getSchemaLoader().GetSchema(schemaUrl); + SchemaResult sr = SchemaValidate(s, cmd, &coreService->getSchemaLoader()); if (!sr.Error()) { auto entry = publishedTopics[device->getCmdTopic()]; if (entry.first > 0) { hos_core_msgs::DeviceCommand command; command.device_id = device->getDeviceID(); command.device_type = device->getDeviceType(); - command.seq = sequenceNumber++; + command.seq = msgSeqNumber++; command.msg_body = Serialize(cmd, SERIALIZE_JSON); command.stamp = ros::Time::now(); entry.second.publish(command); diff --git a/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h b/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl.h similarity index 50% rename from src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h rename to src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl.h index 15d0d6eb..ffe0022b 100644 --- a/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h +++ b/src/hos_cosgi_devicerepository/src/hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl.h @@ -14,10 +14,12 @@ #include #include #include +#include #include #include #include -#include +#include +#include #include #include @@ -26,19 +28,16 @@ using namespace libvariant; -// Forward declarations -namespace XmlRpc { - class XmlRpcValue; -} -namespace hos { -namespace cosgi { -namespace service { -namespace core { -class CoreService; -} -} -} -} +namespace std { +template <> +class hash { +public : + size_t operator()(const hos::cosgi::service::devicerepository::DeviceEvent::EventType& x) const { + return static_cast(x); + } +}; +} // namespace std + // Service Namespace @@ -50,13 +49,19 @@ namespace devicerepository { class DeviceRepositoryServiceImpl; + + /** * Device implementation **/ -class DeviceImpl : public virtual Device, public virtual implementation::Observable { +class DeviceImpl + : public virtual Device, + public virtual implementation::ObservableObject { + private: + DeviceRepositoryServiceImpl* parent; - std::mutex objMutex; + std::recursive_mutex objMutex; std::string deviceID; std::string deviceType; std::string statusTopic; @@ -67,26 +72,31 @@ private: timestamp_t lastStamp; public: - DeviceImpl(DeviceRepositoryServiceImpl* parent, std::string deviceID, std::string deviceType, std::string statusTopic, std::string cmdTopic); + DeviceImpl( DeviceRepositoryServiceImpl* parent, + const std::string& deviceID, + const std::string& deviceType, + const std::string& statusTopic, + const std::string& cmdTopic ) + : parent(parent), deviceID(deviceID), deviceType(deviceType), statusTopic(statusTopic), cmdTopic(cmdTopic) {} /* Public Service Implementations */ - virtual const std::string& getDeviceID() override { return deviceID; } - virtual const std::string& getDeviceType() override { return deviceType; } - virtual const std::string& getCmdTopic() override { return cmdTopic; } - virtual const std::string& getStatusTopic() override { return statusTopic; } + virtual const std::string& getDeviceID() noexcept override { return deviceID; } + virtual const std::string& getDeviceType() noexcept override { return deviceType; } + virtual const std::string& getCmdTopic() noexcept override { return cmdTopic; } + virtual const std::string& getStatusTopic() noexcept override { return statusTopic; } - virtual const Variant& getCurrentState() override { return currentState; } - virtual const timestamp_t& getCurrentStateTimestamp() { return currentStamp; } - virtual const Variant& getLastState() override { return lastState; } - virtual const timestamp_t& getLastStateTimestamp() { return lastStamp; } + virtual const Variant& getCurrentState() noexcept override { return currentState; } + virtual const timestamp_t& getCurrentStateTimestamp() noexcept override { return currentStamp; } + virtual const Variant& getLastState() noexcept override { return lastState; } + virtual const timestamp_t& getLastStateTimestamp() noexcept override { return lastStamp; } - virtual void sendCommand(const Variant cmd) override; + virtual void sendCommand(const Variant& cmd) override; /* Internal Stuff */ - void handleStatusMsg(Variant& msg, const timestamp_t& stamp); - void handleCommandMsg(Variant& msg, const timestamp_t& stamp); + bool handleStatusMsg(const Variant& msg, const timestamp_t& stamp); + void handleCommandMsg(const Variant& msg, const timestamp_t& stamp); }; @@ -95,8 +105,12 @@ public: /** * Implementation of device repository service **/ -class DeviceRepositoryServiceImpl : public virtual DeviceRepositoryService, public virtual implementation::Service, public virtual implementation::Observable { +class DeviceRepositoryServiceImpl + : public virtual DeviceRepositoryService, + public virtual implementation::ObservableService { + private: + std::recursive_mutex serviceMutex; ros::NodeHandle* nodehandle = nullptr; @@ -111,18 +125,16 @@ private: typedef std::map> publishedTopicMap_t; subscripedTopicMap_t subscripedTopics; publishedTopicMap_t publishedTopics; - long sequenceNumber = 0; + long msgSeqNumber = 0; ros::Subscriber hosStatusSub; - std::unique_ptr schemaLoader; - bool initialized = false; void init(); - void addDevice(std::string name); - void addDevice(std::string name, XmlRpc::XmlRpcValue& rawValue); - void removeDevice(std::string name); + void addDevice(const std::string& name); + void addDevice(const std::string& name, XmlRpc::XmlRpcValue& rawValue); + void removeDevice(const std::string& name); public: /* Initialization */ @@ -131,10 +143,10 @@ public: /* Public Service Implementations */ - virtual std::shared_ptr getDevice(std::string device_id) override; - virtual size_t getDevices(std::vector>& devices) override; - virtual size_t deviceCount() override; - virtual std::set deviceIDs() override; + virtual std::weak_ptr getDevice(const std::string& device_id) noexcept override; + virtual std::vector> getDevices() noexcept override; + virtual size_t deviceCount() noexcept override; + virtual std::vector getDeviceIDs() noexcept override; /* Message Callbacks */ @@ -144,8 +156,7 @@ public: /* Internal Stuff */ - bool isInitialized() { return initialized; } - utils::SchemaLoader* getHosSchemaLoader() { return schemaLoader.get(); } + bool isInitialized() noexcept { return initialized; } void sendDeviceCommand(Device* device, const Variant& cmd); }; diff --git a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/Rule.cpp b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/Rule.cpp index 2ee15c05..ea367f30 100644 --- a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/Rule.cpp +++ b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/Rule.cpp @@ -14,7 +14,7 @@ #include #include "RulePackage.h" #include -#include +#include #include #include "../ruleengine_serviceimpl.h" diff --git a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.cpp b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.cpp index 84f8e53f..50c05f20 100644 --- a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.cpp +++ b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/rule/RuleConditionImpl.cpp @@ -7,7 +7,7 @@ #include "RuleConditionImpl.h" #include -#include +#include #include namespace hos { @@ -183,20 +183,22 @@ bool LogicalAndCondition::evaluate() { -void DeviceMsgCondition::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) { - switch (e->eventType) { +void DeviceMsgCondition::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept { + switch (key) { case devicerepository::DeviceEvent::EventType::DEVICE_ADDED: if (!device && this->deviceID.compare(e->device->getDeviceID()) == 0) { ROS_INFO_STREAM("Rule " << parent->name << ": Device " << deviceID << " appeared."); device = e->device; - device->addObserver(dynamic_cast*>(this)); + parent->getDeviceRepository()->deleteObserver(devicerepository::DeviceEvent::EventType::DEVICE_ADDED, this); + _registerAsListener(); } break; case devicerepository::DeviceEvent::EventType::DEVICE_REMOVED: if (device && device->getDeviceID().compare(e->device->getDeviceID()) == 0) { ROS_ERROR_STREAM("Rule " << parent->name << ": Device " << deviceID << " disappeared."); - device->deleteObserver(dynamic_cast*>(this)); + device->deleteObserver(this); device = nullptr; + parent->getDeviceRepository()->addObserver(devicerepository::DeviceEvent::EventType::DEVICE_ADDED, this); } break; default: @@ -207,12 +209,12 @@ void DeviceMsgCondition::notificationReceived(interface::ObservergetDeviceRepository(); auto device = repoService->getDevice(deviceID); - if (device) { - this->device = device.get(); - device->addObserver(dynamic_cast*>(this)); + if (!device.expired()) { + this->device = device.lock().get(); + _registerAsListener(); } else { ROS_ERROR_STREAM("Rule " << parent->name << ": Could not find device " << deviceID); - repoService->addObserver(dynamic_cast*>(this)); + parent->getDeviceRepository()->addObserver(devicerepository::DeviceEvent::EventType::DEVICE_ADDED, this); } } @@ -224,6 +226,13 @@ void DeviceMsgCondition::disable() { parent->getDeviceRepository()->deleteObserver(this); } +void DeviceMsgCondition::_registerAsListener() { + if (device) { + for (auto k : _listenerKeys) { + device->addObserver(k, this); + } + } +} @@ -252,9 +261,9 @@ std::shared_ptr DeviceStatusMsgConditionFactory::createCond return retval; } -void DeviceStatusMsgCondition::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) { +void DeviceStatusMsgCondition::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept { switch (e->eventType) { - case devicerepository::DeviceEvent::EventType::STATUS_UPDATED: + case devicerepository::DeviceEvent::EventType::STATUS_UPDATE_RECEIVED: if (device && device == e->device) { auto e2 = static_cast(e); bool notify = true; @@ -281,7 +290,7 @@ void DeviceStatusMsgCondition::notificationReceived(interface::Observer DeviceCommandMsgConditionFactory::createCon return retval; } -void DeviceCommandMsgCondition::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) { +void DeviceCommandMsgCondition::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept { switch (e->eventType) { case devicerepository::DeviceEvent::EventType::COMMAND_RECEIVED: if (device && device == e->device) { @@ -340,7 +349,7 @@ void DeviceCommandMsgCondition::notificationReceived(interface::Observer DeviceStateChangeConditionFactory::createCo } -void DeviceStateChangeCondition::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) { +void DeviceStateChangeCondition::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept { switch (e->eventType) { - case devicerepository::DeviceEvent::EventType::STATUS_UPDATED: + case devicerepository::DeviceEvent::EventType::STATE_CHANGED: if (device && device == e->device) { auto e2 = static_cast(e); bool notify = true; @@ -410,7 +419,7 @@ void DeviceStateChangeCondition::notificationReceived(interface::Observer #include +#include +#include // Service Namespace namespace hos { namespace cosgi { namespace service { -namespace devicerepository { -class Device; -class DeviceEvent; -class DeviceRepositoryService; -} namespace ruleengine { namespace rule { @@ -69,18 +66,21 @@ public: }; -class DeviceMsgCondition : public RuleCondition, public virtual interface::Observer { +class DeviceMsgCondition : public RuleCondition, public virtual interface::Observer { protected: const std::string deviceID; devicerepository::Device* device = nullptr; const std::string msgPointer; const Variant msgValue; + std::set _listenerKeys; + + virtual void _registerAsListener(); public: - DeviceMsgCondition(Rule* parent, Category category, std::string type, const std::string deviceID, const std::string msgPointer, const Variant msgValue) : - RuleCondition(parent, category, type), deviceID(deviceID), msgPointer(msgPointer), msgValue(msgValue) {} + DeviceMsgCondition(Rule* parent, Category category, std::string type, const std::string deviceID, const std::string msgPointer, const Variant msgValue, std::set _listenerKeys) : + RuleCondition(parent, category, type), deviceID(deviceID), msgPointer(msgPointer), msgValue(msgValue), _listenerKeys(_listenerKeys) {} - virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) override; + virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept override; virtual void enable() override; virtual void disable() override; }; @@ -89,9 +89,9 @@ public: class DeviceStatusMsgCondition : public DeviceMsgCondition { public: DeviceStatusMsgCondition(Rule* parent, const std::string deviceID, const std::string msgPointer, const Variant msgValue) : - DeviceMsgCondition(parent, Category::Event, "devicestatusmsg", deviceID, msgPointer, msgValue) {} + DeviceMsgCondition(parent, Category::Event, "devicestatusmsg", deviceID, msgPointer, msgValue, {devicerepository::DeviceEvent::EventType::STATUS_UPDATE_RECEIVED}) {} - virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) override; + virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept override; }; class DeviceStatusMsgConditionFactory : public virtual RuleConditionFactory { @@ -103,9 +103,9 @@ public: class DeviceCommandMsgCondition : public DeviceMsgCondition { public: DeviceCommandMsgCondition(Rule* parent, const std::string deviceID, const std::string msgPointer, const Variant msgValue) : - DeviceMsgCondition(parent, Category::Event, "devicecommandmsg", deviceID, msgPointer, msgValue) {} + DeviceMsgCondition(parent, Category::Event, "devicecommandmsg", deviceID, msgPointer, msgValue, {devicerepository::DeviceEvent::EventType::COMMAND_RECEIVED}) {} - virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) override; + virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept override; }; class DeviceCommandMsgConditionFactory : public virtual RuleConditionFactory { @@ -119,9 +119,9 @@ protected: const Variant fromValue; public: DeviceStateChangeCondition(Rule* parent, const std::string deviceID, const std::string statePointer, const Variant fromValue, const Variant toValue) : - DeviceMsgCondition(parent, Category::Event, "devicestatechange", deviceID, statePointer, toValue), fromValue(fromValue) {} + DeviceMsgCondition(parent, Category::Event, "devicestatechange", deviceID, statePointer, toValue, {devicerepository::DeviceEvent::EventType::STATE_CHANGED}), fromValue(fromValue) {} - virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) override; + virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept override; }; class DeviceStateChangeConditionFactory : public virtual RuleConditionFactory { diff --git a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl.cpp b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl.cpp index 7023a58e..208e37aa 100644 --- a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl.cpp +++ b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include "rule/RulePackage.h" @@ -79,41 +79,10 @@ void RuleEngineServiceImpl::init() { } } } - repoService->addObserver(this); initialized = true; ROS_INFO_STREAM("RuleEngineService: Initialized and Ready."); } -RuleEngineServiceImpl::~RuleEngineServiceImpl() { - repoService->deleteObserver(this); -} - - -void RuleEngineServiceImpl::notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) { - /*switch (e->eventType) { - case devicerepository::DeviceEvent::EventType::STATUS_UPDATED: - { - auto e2 = static_cast(e); - rule::DeviceStatusMsgEvent event(e2->device, e2->statusMsg, std::chrono::system_clock::now()); - this->notifyObservers(&event, (int)rule::RuleEvent::EventType::DeviceStatusMsgEvent); - if (e2->device->getCurrentState() != e2->device->getLastState()) { - rule::DeviceStateChangeEvent event2(e2->device, std::chrono::system_clock::now()); - this->notifyObservers(&event2, (int)rule::RuleEvent::EventType::DeviceStateChangeEvent); - } - } - break; - case devicerepository::DeviceEvent::EventType::COMMAND_RECEIVED: - { - auto e2 = static_cast(e); - rule::DeviceCommandMsgEvent event(e2->device, e2->cmdMsg, std::chrono::system_clock::now()); - this->notifyObservers(&event, (int)rule::RuleEvent::EventType::DeviceCommandMsgEvent); - } - break; - default: - break; - }*/ -} - void RuleEngineServiceImpl::addRulePkg(std::string name) { std::stringstream ss; ss << ruleEnginePrefix << "/" << name; diff --git a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl.h b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl.h index 8919d36b..d93d463b 100644 --- a/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl.h +++ b/src/hos_cosgi_ruleengine/src/hos/cosgi/service/ruleengine/ruleengine_serviceimpl.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -54,8 +54,7 @@ class RulePackage; class RuleEngineServiceImpl; class RuleEngineServiceImpl : public virtual RuleEngineService, - public virtual implementation::Service, - public virtual interface::Observer { + public virtual implementation::Service { private: typedef std::map> rulePkgMap_t; typedef std::map execServiceMap_t; @@ -83,7 +82,6 @@ private: void init(); public: - ~RuleEngineServiceImpl(); /* Initialization */ void setCoreService(service::core::CoreService* coreService); @@ -93,10 +91,6 @@ public: virtual void registerRuleConditionFactory(std::string type, std::shared_ptr factory) override; - /* Observer Callbacks */ - - virtual void notificationReceived(interface::Observer::observable_type* o, const devicerepository::DeviceEvent* e) override; - /* Internal Stuff */ bool isInitialized() { return initialized; } diff --git a/src/hos_cosgi_scripting_python/src/bundle_activator.cpp b/src/hos_cosgi_scripting_python/src/bundle_activator.cpp index 84d872d3..52c67c44 100644 --- a/src/hos_cosgi_scripting_python/src/bundle_activator.cpp +++ b/src/hos_cosgi_scripting_python/src/bundle_activator.cpp @@ -20,7 +20,7 @@ extern "C" { } #include -#include +#include #include "hos/cosgi/service/scripting/python/scripting_serviceimpl.h" #include diff --git a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.h b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.h index d15fb23a..521ae38b 100644 --- a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.h +++ b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/PyHOSAPI.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace hos { @@ -48,7 +48,7 @@ public: PyDeviceRepositoryWrapper(devicerepository::DeviceRepositoryService* service) : service(service) {} PyDeviceWrapper getDevice(std::string name) { - return PyDeviceWrapper(service->getDevice(name).get()); + return PyDeviceWrapper(service->getDevice(name).lock().get()); } size_t deviceCount() { @@ -57,7 +57,7 @@ public: boost::python::list deviceIDs() { boost::python::list retval; - for (auto d : service->deviceIDs()) { + for (auto d : service->getDeviceIDs()) { retval.append(d); } return retval; diff --git a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.cpp b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.cpp index 147230e5..1a860c64 100644 --- a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.cpp +++ b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.cpp @@ -11,7 +11,7 @@ #include "PyHOSAPI.h" -#include +#include diff --git a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.h b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.h index bb0dd3fc..a9a3fe56 100644 --- a/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.h +++ b/src/hos_cosgi_scripting_python/src/hos/cosgi/service/scripting/python/scripting_serviceimpl.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/resources/DevicesHTTPResource.cpp b/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/resources/DevicesHTTPResource.cpp index 5ec010fe..d05b9c3d 100644 --- a/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/resources/DevicesHTTPResource.cpp +++ b/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/resources/DevicesHTTPResource.cpp @@ -66,23 +66,21 @@ void DevicesHTTPResource::render_GET(const httpserver::http_request& req, httpse if (isSetCommand) { throw ResourceException("No device given for set command.", 400); } - std::vector> devices; - repoService->getDevices(devices); Variant result; - for (auto d : devices) { - result[d->getDeviceID()] = getDeviceInfo(d.get()); + for (auto d : repoService->getDevices()) { + result[d.lock()->getDeviceID()] = getDeviceInfo(d.lock().get()); } *res = new http_response(http_response_builder(SerializeJSON(result, true), 200).string_response()); } else { std::string devid = req.get_path_piece(prefixPathPieces); auto device = repoService->getDevice(devid); - if (device) { + if (!device.expired()) { if (isSetCommand) { std::vector path; for (int i = prefixPathPieces+1; i < req.get_path_pieces_size(); i++) { path.push_back(req.get_path_piece(i)); } - setDeviceState(device.get(), setValue, path); + setDeviceState(device.lock().get(), setValue, path); *res = new http_response(http_response_builder("OK", 200).string_response()); } else { std::string info; @@ -94,7 +92,7 @@ void DevicesHTTPResource::render_GET(const httpserver::http_request& req, httpse ss << "/" << req.get_path_piece(i); } std::string path = ss.str(); - Variant result = getDeviceInfo(device.get(), info, path); + Variant result = getDeviceInfo(device.lock().get(), info, path); *res = new http_response(http_response_builder(SerializeJSON(result, true), 200).string_response()); } } else { diff --git a/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/resources/DevicesHTTPResource.h b/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/resources/DevicesHTTPResource.h index 7334a133..e67ae97c 100644 --- a/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/resources/DevicesHTTPResource.h +++ b/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/resources/DevicesHTTPResource.h @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include diff --git a/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/webserver_serviceimpl.h b/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/webserver_serviceimpl.h index aa05faa1..60633004 100644 --- a/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/webserver_serviceimpl.h +++ b/src/hos_cosgi_webserver/src/hos/cosgi/service/webserver/webserver_serviceimpl.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/src/hos_launch/launch/hos_cosgi.launch b/src/hos_launch/launch/hos_cosgi.launch index 81ef721a..19c90dd7 100644 --- a/src/hos_launch/launch/hos_cosgi.launch +++ b/src/hos_launch/launch/hos_cosgi.launch @@ -2,16 +2,16 @@ - + + value="$(find hos_cosgi_core)/../../devel_isolated/hos_celix/share/celix/bundles/log_service.zip + $(find hos_cosgi_core)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer.zip + $(find hos_cosgi_core)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer_syslog.zip + $(find hos_cosgi_core)/../../devel_isolated/hos_celix/share/celix/bundles/shell.zip + $(find hos_cosgi_core)/../../devel_isolated/hos_celix/share/celix/bundles/shell_tui.zip + $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_scripting_python/hos_cosgi_scripting_python.zip + $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_ruleengine/hos_cosgi_ruleengine.zip + $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_devicerepository/hos_cosgi_devicerepository.zip + $(find hos_cosgi_core)/../../build_isolated/hos_cosgi_webserver/hos_cosgi_webserver.zip"/> - \ No newline at end of file +