This commit is contained in:
Matthias Janetschek
2015-05-22 16:40:23 +02:00
parent feff4efc35
commit 3626b45dfc
23 changed files with 491 additions and 395 deletions
+3
View File
@@ -6,3 +6,6 @@
/install/
**/*.pyc
/env.bash
/env.sh
/src/hos_deps/deps-install/
/src/hos_deps/deps-tmp/
@@ -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... _Args> class Observable {};
/**
* Convenience template merging the Object class and the Observable template into a single template.
*/
template<class... _Args> 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<typename interface::Observable<_Event>::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<std::mutex> lock(_observersMutex);
virtual bool addObserver(typename interface::Observable<_Event>::observer_type* o) noexcept override {
std::lock_guard<std::recursive_mutex> 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<std::mutex> lock(_observersMutex);
virtual bool deleteObserver(typename interface::Observable<_Event>::observer_type* o) noexcept override {
std::lock_guard<std::recursive_mutex> 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<std::mutex> lock(_observersMutex);
virtual void deleteObservers() noexcept override {
std::lock_guard<std::recursive_mutex> lock(_observersMutex);
_observers.clear();
};
@@ -149,8 +170,8 @@ public:
*
* \return number of registered observers.
*/
virtual size_t countObservers() override {
std::lock_guard<std::mutex> lock(_observersMutex);
virtual size_t countObservers() noexcept override {
std::lock_guard<std::recursive_mutex> 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<std::mutex> lock(_observersMutex);
for (auto l : _observers) {
virtual size_t notifyObservers(const _Event* e) noexcept override {
std::lock_guard<std::recursive_mutex> 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<std::mutex> lock(_observersMutex);
virtual bool addObserver(const _Key& k, typename interface::Observable<_Key, _Event>::observer_type* o) noexcept override {
std::lock_guard<std::recursive_mutex> 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<std::mutex> lock(_observersMutex);
virtual bool deleteObserver(const _Key& k, typename interface::Observable<_Key, _Event>::observer_type* o) noexcept override {
std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> 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<std::mutex> lock(_observersMutex);
virtual void deleteObservers() noexcept override {
std::lock_guard<std::recursive_mutex> lock(_observersMutex);
_observers.clear();
}
@@ -247,8 +301,8 @@ public:
*
* \return number of registered observers.
*/
virtual size_t countObservers() override {
std::lock_guard<std::mutex> lock(_observersMutex);
virtual size_t countObservers() noexcept override {
std::lock_guard<std::recursive_mutex> 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<std::mutex> 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<std::recursive_mutex> 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;
}
};
@@ -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;
};
@@ -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;
@@ -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}
@@ -0,0 +1,174 @@
#ifndef _HOS_DEVICEREPOSITORY_SERVICE_H_
#define _HOS_DEVICEREPOSITORY_SERVICE_H_
#include <hos/cosgi/service/Interface.h>
#include <Variant/Variant.h>
#include <string>
#include <chrono>
#include <vector>
#include <memory>
// 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<DeviceEvent::EventType, DeviceEvent> {
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<DeviceEvent::EventType, DeviceEvent> {
public:
static constexpr const char* SERVICE_NAME = "hos_devicerepository_service";
virtual std::weak_ptr<Device> getDevice(const std::string& device_id) noexcept = 0;
virtual std::vector<std::weak_ptr<Device>> getDevices() noexcept = 0;
virtual size_t deviceCount() noexcept = 0;
virtual std::vector<std::string> getDeviceIDs() noexcept = 0;
};
} // namespace devicerepository
} // namespace service
} // namespace cosgi
} // namespace hos
#endif /* _HOS_DEVICEREPOSITORY_SERVICE_H_ */
@@ -1,148 +0,0 @@
#ifndef _HOS_DEVICEREPOSITORY_SERVICE_H_
#define _HOS_DEVICEREPOSITORY_SERVICE_H_
#include <hos/cosgi/service/Interface.h>
#include <Variant/Variant.h>
#include <string>
#include <set>
#include <chrono>
#include <vector>
#include <memory>
// 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<DeviceEvent> {
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<DeviceEvent> {
public:
static constexpr const char* SERVICE_NAME = "hos_devicerepository_service";
virtual std::shared_ptr<Device> getDevice(std::string device_id) = 0;
virtual size_t getDevices(std::vector<std::shared_ptr<Device>>& devices) = 0;
virtual size_t deviceCount() = 0;
virtual std::set<std::string> deviceIDs() = 0;
};
} // namespace devicerepository
} // namespace service
} // namespace cosgi
} // namespace hos
#endif /* _HOS_DEVICEREPOSITORY_SERVICE_H_ */
@@ -12,7 +12,7 @@ extern "C" {
}
#include <hos/cosgi/service/core/CoreService.h>
#include "hos/cosgi/service/devicerepository/devicerepository_serviceimpl.h"
#include "hos/cosgi/service/devicerepository/DeviceRepositoryServiceImpl.h"
#include <iostream>
#include <memory>
@@ -5,7 +5,7 @@
* Author: matzman
*/
#include "devicerepository_serviceimpl.h"
#include "DeviceRepositoryServiceImpl.h"
#include <hos/cosgi/service/core/CoreService.h>
#include <ros/ros.h>
@@ -23,31 +23,39 @@ namespace devicerepository {
template<> const char* implementation::ServiceInfo<DeviceRepositoryServiceImpl>::name = service::devicerepository::DeviceRepositoryService::SERVICE_NAME;
template<> const int implementation::ServiceInfo<DeviceRepositoryServiceImpl>::major = 0;
template<> const int implementation::ServiceInfo<DeviceRepositoryServiceImpl>::minor = 4;
template<> const int implementation::ServiceInfo<DeviceRepositoryServiceImpl>::major = 1;
template<> const int implementation::ServiceInfo<DeviceRepositoryServiceImpl>::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<std::mutex> lock(objMutex);
bool DeviceImpl::handleStatusMsg(const Variant& msg, const timestamp_t& stamp) {
std::lock_guard<std::recursive_mutex> lock(objMutex);
Variant tmp = currentState.Copy();
tmp.Merge(msg);
bool stateChanged = false;
if (tmp != currentState) { // state has changed
lastState = currentState.Copy();
currentState.Merge(msg);
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<std::mutex> lock(objMutex);
void DeviceImpl::handleCommandMsg(const Variant& msg, const timestamp_t& stamp) {
std::lock_guard<std::recursive_mutex> lock(objMutex);
DeviceCmdMsgEvent event(this, msg, stamp);
notifyObservers(&event);
notifyObservers(DeviceEvent::EventType::COMMAND_RECEIVED, &event);
}
void DeviceImpl::sendCommand(const Variant cmd) {
std::lock_guard<std::mutex> lock(objMutex);
void DeviceImpl::sendCommand(const Variant& cmd) {
std::lock_guard<std::recursive_mutex> 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<std::recursive_mutex> 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<std::recursive_mutex> 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<Device> DeviceRepositoryServiceImpl::getDevice(std::string device_id) {
return std::static_pointer_cast<Device>(this->devices[device_id]);
std::weak_ptr<Device> DeviceRepositoryServiceImpl::getDevice(const std::string& device_id) noexcept {
try {
return std::static_pointer_cast<Device>(this->devices.at(device_id));
} catch (...) {
return std::weak_ptr<Device>();
}
}
size_t DeviceRepositoryServiceImpl::getDevices(std::vector<std::shared_ptr<Device>>& devices) {
std::vector<std::weak_ptr<Device>> DeviceRepositoryServiceImpl::getDevices() noexcept {
std::lock_guard<std::recursive_mutex> lock(serviceMutex);
size_t retval = 0;
std::vector<std::weak_ptr<Device>> retval;
for (auto item : this->devices) {
devices.push_back(std::static_pointer_cast<Device>(item.second));
retval++;
retval.push_back(std::static_pointer_cast<Device>(item.second));
}
return retval;
}
size_t DeviceRepositoryServiceImpl::deviceCount() {
size_t DeviceRepositoryServiceImpl::deviceCount() noexcept {
return devices.size();
}
std::set<std::string> DeviceRepositoryServiceImpl::deviceIDs() {
std::set<std::string> retval;
std::vector<std::string> DeviceRepositoryServiceImpl::getDeviceIDs() noexcept {
std::lock_guard<std::recursive_mutex> lock(serviceMutex);
std::vector<std::string> retval;
for (auto d : devices) {
retval.insert(d.first);
retval.push_back(d.first);
}
return retval;
}
@@ -195,16 +206,20 @@ std::set<std::string> DeviceRepositoryServiceImpl::deviceIDs() {
void DeviceRepositoryServiceImpl::statusMsgCallback(const hos_core_msgs::DeviceStatusUpdate::ConstPtr& msg) {
std::lock_guard<std::recursive_mutex> 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<DeviceImpl> dev = std::static_pointer_cast<DeviceImpl>(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<std::recursive_mutex> 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<DeviceImpl> dev = std::static_pointer_cast<DeviceImpl>(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<std::recursive_mutex> 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);
@@ -14,10 +14,12 @@
#include <map>
#include <set>
#include <memory>
#include <functional>
#include <hos_core_msgs/DeviceCommand.h>
#include <hos_core_msgs/DeviceStatusUpdate.h>
#include <hos_core_msgs/HosStatusUpdate.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <hos/cosgi/service/core/CoreService.h>
#include <hos/cosgi/service/Implementation.h>
#include <ros/ros.h>
@@ -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 <hos::cosgi::service::devicerepository::DeviceEvent::EventType>{
public :
size_t operator()(const hos::cosgi::service::devicerepository::DeviceEvent::EventType& x) const {
return static_cast<size_t>(x);
}
};
} // namespace std
// Service Namespace
@@ -50,13 +49,19 @@ namespace devicerepository {
class DeviceRepositoryServiceImpl;
/**
* Device implementation
**/
class DeviceImpl : public virtual Device, public virtual implementation::Observable<DeviceEvent> {
class DeviceImpl
: public virtual Device,
public virtual implementation::ObservableObject<DeviceEvent::EventType, DeviceEvent> {
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<DeviceRepositoryServiceImpl>, public virtual implementation::Observable<DeviceEvent> {
class DeviceRepositoryServiceImpl
: public virtual DeviceRepositoryService,
public virtual implementation::ObservableService<DeviceRepositoryServiceImpl, DeviceEvent::EventType, DeviceEvent> {
private:
std::recursive_mutex serviceMutex;
ros::NodeHandle* nodehandle = nullptr;
@@ -111,18 +125,16 @@ private:
typedef std::map<std::string, std::pair<int, ros::Publisher>> publishedTopicMap_t;
subscripedTopicMap_t subscripedTopics;
publishedTopicMap_t publishedTopics;
long sequenceNumber = 0;
long msgSeqNumber = 0;
ros::Subscriber hosStatusSub;
std::unique_ptr<utils::SchemaLoader> 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<Device> getDevice(std::string device_id) override;
virtual size_t getDevices(std::vector<std::shared_ptr<Device>>& devices) override;
virtual size_t deviceCount() override;
virtual std::set<std::string> deviceIDs() override;
virtual std::weak_ptr<Device> getDevice(const std::string& device_id) noexcept override;
virtual std::vector<std::weak_ptr<Device>> getDevices() noexcept override;
virtual size_t deviceCount() noexcept override;
virtual std::vector<std::string> 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);
};
@@ -14,7 +14,7 @@
#include <ros/ros.h>
#include "RulePackage.h"
#include <hos/cosgi/service/ruleengine/ruleengine_service.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <hos/utils/SchemaLoader.h>
#include "../ruleengine_serviceimpl.h"
@@ -7,7 +7,7 @@
#include "RuleConditionImpl.h"
#include <hos/cosgi/service/ruleengine/rule/Rule.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <ros/ros.h>
namespace hos {
@@ -183,20 +183,22 @@ bool LogicalAndCondition::evaluate() {
void DeviceMsgCondition::notificationReceived(interface::Observer<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) {
switch (e->eventType) {
void DeviceMsgCondition::notificationReceived(interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent>::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<interface::Observer<devicerepository::DeviceEvent>*>(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<interface::Observer<devicerepository::DeviceEvent>*>(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::Observer<devicereposito
void DeviceMsgCondition::enable() {
auto repoService = parent->getDeviceRepository();
auto device = repoService->getDevice(deviceID);
if (device) {
this->device = device.get();
device->addObserver(dynamic_cast<interface::Observer<devicerepository::DeviceEvent>*>(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<interface::Observer<devicerepository::DeviceEvent>*>(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<rule::RuleCondition> DeviceStatusMsgConditionFactory::createCond
return retval;
}
void DeviceStatusMsgCondition::notificationReceived(interface::Observer<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) {
void DeviceStatusMsgCondition::notificationReceived(interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent>::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<const devicerepository::DeviceStatusMsgEvent*>(e);
bool notify = true;
@@ -281,7 +290,7 @@ void DeviceStatusMsgCondition::notificationReceived(interface::Observer<devicere
}
break;
default:
DeviceMsgCondition::notificationReceived(o, e);
DeviceMsgCondition::notificationReceived(o, key, e);
break;
}
}
@@ -311,7 +320,7 @@ std::shared_ptr<rule::RuleCondition> DeviceCommandMsgConditionFactory::createCon
return retval;
}
void DeviceCommandMsgCondition::notificationReceived(interface::Observer<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) {
void DeviceCommandMsgCondition::notificationReceived(interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent>::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<devicer
}
break;
default:
DeviceMsgCondition::notificationReceived(o, e);
DeviceMsgCondition::notificationReceived(o, key, e);
break;
}
}
@@ -375,9 +384,9 @@ std::shared_ptr<rule::RuleCondition> DeviceStateChangeConditionFactory::createCo
}
void DeviceStateChangeCondition::notificationReceived(interface::Observer<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) {
void DeviceStateChangeCondition::notificationReceived(interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent>::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<const devicerepository::DeviceStatusMsgEvent*>(e);
bool notify = true;
@@ -410,7 +419,7 @@ void DeviceStateChangeCondition::notificationReceived(interface::Observer<device
}
break;
default:
DeviceMsgCondition::notificationReceived(o, e);
DeviceMsgCondition::notificationReceived(o, key, e);
break;
}
}
@@ -10,17 +10,14 @@
#include <hos/cosgi/service/ruleengine/rule/RuleCondition.h>
#include <hos/cosgi/service/ruleengine/ruleengine_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <set>
// 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<devicerepository::DeviceEvent> {
class DeviceMsgCondition : public RuleCondition, public virtual interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent> {
protected:
const std::string deviceID;
devicerepository::Device* device = nullptr;
const std::string msgPointer;
const Variant msgValue;
std::set<devicerepository::DeviceEvent::EventType> _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<devicerepository::DeviceEvent::EventType> _listenerKeys) :
RuleCondition(parent, category, type), deviceID(deviceID), msgPointer(msgPointer), msgValue(msgValue), _listenerKeys(_listenerKeys) {}
virtual void notificationReceived(interface::Observer<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) override;
virtual void notificationReceived(interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent>::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<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) override;
virtual void notificationReceived(interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent>::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<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) override;
virtual void notificationReceived(interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent>::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<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) override;
virtual void notificationReceived(interface::Observer<devicerepository::DeviceEvent::EventType, devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent::EventType& key, const devicerepository::DeviceEvent* e) noexcept override;
};
class DeviceStateChangeConditionFactory : public virtual RuleConditionFactory {
@@ -13,7 +13,7 @@
#include <Variant/Variant.h>
#include <celix/bundle_context.h>
#include <hos/cosgi/service/core/CoreService.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <Variant/Variant.h>
#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<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) {
/*switch (e->eventType) {
case devicerepository::DeviceEvent::EventType::STATUS_UPDATED:
{
auto e2 = static_cast<const devicerepository::DeviceStatusMsgEvent*>(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<const devicerepository::DeviceCmdMsgEvent*>(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;
@@ -17,7 +17,7 @@
#include <hos/utils/SchemaLoader.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 <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <hos/cosgi/service/Implementation.h>
#include <ros/ros.h>
#include <memory>
@@ -54,8 +54,7 @@ class RulePackage;
class RuleEngineServiceImpl;
class RuleEngineServiceImpl :
public virtual RuleEngineService,
public virtual implementation::Service<RuleEngineServiceImpl>,
public virtual interface::Observer<devicerepository::DeviceEvent> {
public virtual implementation::Service<RuleEngineServiceImpl> {
private:
typedef std::map<std::string, std::shared_ptr<rule::RulePackage>> rulePkgMap_t;
typedef std::map<std::string, scripting::ScriptingService*> 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<RuleConditionFactory> factory) override;
/* Observer Callbacks */
virtual void notificationReceived(interface::Observer<devicerepository::DeviceEvent>::observable_type* o, const devicerepository::DeviceEvent* e) override;
/* Internal Stuff */
bool isInitialized() { return initialized; }
@@ -20,7 +20,7 @@ extern "C" {
}
#include <hos/cosgi/service/core/CoreService.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include "hos/cosgi/service/scripting/python/scripting_serviceimpl.h"
#include <memory>
@@ -10,7 +10,7 @@
#include <boost/python.hpp>
#include <hos/cosgi/service/scripting/scripting_service.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
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;
@@ -11,7 +11,7 @@
#include "PyHOSAPI.h"
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
@@ -12,7 +12,7 @@
#include <Variant/Variant.h>
#include <boost/python.hpp>
#include <hos/cosgi/service/scripting/scripting_service.h>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <hos/cosgi/service/Implementation.h>
#include <memory>
@@ -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<std::shared_ptr<devicerepository::Device>> 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<std::string> 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 {
@@ -4,7 +4,7 @@
#include <ros/ros.h>
#include <httpserver.hpp>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <Variant/Variant.h>
#include <string>
@@ -12,7 +12,7 @@
#include <mutex>
#include <map>
#include <set>
#include <hos/cosgi/service/devicerepository/devicerepository_service.h>
#include <hos/cosgi/service/devicerepository/DeviceRepositoryService.h>
#include <hos/cosgi/service/webserver/webserver_service.h>
#include <hos/cosgi/service/Implementation.h>
+10 -10
View File
@@ -2,16 +2,16 @@
<group ns="/hos/rules/ruleengine0">
<param name="rulepkg01" textfile="$(find hos_cosgi_ruleengine)/test/rulepkg01.json"/>
</group>
<node name="cosgi_devicerepository" pkg="hos_cosgi_launcher" type="hos_cosgi_launcher" output="screen">
<node name="cosgi_devicerepository" pkg="hos_cosgi_core" type="hos_cosgi_launcher" output="screen">
<param name="autostart_bundles"
value="$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_service.zip
$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer.zip
$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/log_writer_syslog.zip
$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell.zip
$(find hos_cosgi_launcher)/../../devel_isolated/hos_celix/share/celix/bundles/shell_tui.zip
$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_scripting_python/hos_cosgi_scripting_python.zip
$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_ruleengine/hos_cosgi_ruleengine.zip
$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_devicerepository/hos_cosgi_devicerepository.zip
$(find hos_cosgi_launcher)/../../build_isolated/hos_cosgi_webserver/hos_cosgi_webserver.zip"/>
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"/>
</node>
</launch>