00001 #ifndef SUBSCRIPTION_HPP 00002 #define SUBSCRIPTION_HPP 00003 00004 #include <functional> 00005 #include "Client.hpp" 00006 #include "Message.hpp" 00007 #include "PeriodicTimer.hpp" 00008 00009 namespace msp { 00010 namespace client { 00011 00012 class SubscriptionBase { 00013 public: 00014 SubscriptionBase() {} 00015 00016 virtual ~SubscriptionBase() {} 00017 00018 virtual void decode(msp::ByteVector& data) const = 0; 00019 00020 virtual void makeRequest() const = 0; 00021 00022 virtual void handleResponse() const = 0; 00023 00024 virtual const msp::Message& getMsgObject() const = 0; 00025 00030 bool isAutomatic() const { 00031 return hasTimer() && (timer_->getPeriod() > 0.0); 00032 } 00033 00038 bool hasTimer() const { return timer_ ? true : false; } 00039 00044 bool start() const { return this->timer_->start(); } 00045 00050 bool stop() const { return this->timer_->stop(); } 00051 00056 void setTimerPeriod(const double& period_seconds) { 00057 if(timer_) { 00058 timer_->setPeriod(period_seconds); 00059 } 00060 else if(period_seconds > 0.0) { 00061 timer_ = std::unique_ptr<PeriodicTimer>(new PeriodicTimer( 00062 std::bind(&SubscriptionBase::makeRequest, this), 00063 period_seconds)); 00064 this->timer_->start(); 00065 } 00066 } 00067 00072 void setTimerFrequency(const double& rate_hz) { 00073 if(timer_) { 00074 timer_->setPeriod(1.0 / rate_hz); 00075 } 00076 else if(rate_hz > 0.0) { 00077 timer_ = std::unique_ptr<PeriodicTimer>(new PeriodicTimer( 00078 std::bind(&SubscriptionBase::makeRequest, this), 00079 1.0 / rate_hz)); 00080 this->timer_->start(); 00081 } 00082 } 00083 00084 protected: 00085 std::unique_ptr<PeriodicTimer> timer_; 00086 }; 00087 00088 template <typename T> class Subscription : public SubscriptionBase { 00089 public: 00090 typedef std::function<void(const T&)> CallbackT; 00091 typedef std::function<void(const msp::Message&)> CallbackM; 00092 00096 Subscription() {} 00097 00105 Subscription(const CallbackT& recv_callback, const CallbackM& send_callback, 00106 std::unique_ptr<T>&& io_object, const double& period = 0.0) : 00107 recv_callback_(recv_callback), 00108 send_callback_(send_callback), 00109 io_object_(std::move(io_object)) { 00110 if(period > 0.0) { 00111 timer_ = std::unique_ptr<PeriodicTimer>(new PeriodicTimer( 00112 std::bind(&Subscription<T>::makeRequest, this), period)); 00113 this->timer_->start(); 00114 } 00115 } 00116 00121 virtual void decode(msp::ByteVector& data) const override { 00122 io_object_->decode(data); 00123 recv_callback_(*io_object_); 00124 } 00125 00130 void setIoObject(std::unique_ptr<T>&& obj) const { 00131 io_object_ = std::move(obj); 00132 } 00133 00138 const T& getIoObject() const { return *io_object_; } 00139 00144 virtual const msp::Message& getMsgObject() const override { 00145 return *io_object_; 00146 } 00147 00152 void setReceiveCallback(const CallbackT& recv_callback) const { 00153 recv_callback_ = recv_callback; 00154 } 00155 00159 virtual void handleResponse() const override { 00160 if(recv_callback_) recv_callback_(*io_object_); 00161 } 00162 00167 void setSendCallback(const CallbackM& send_callback) const { 00168 send_callback_ = send_callback; 00169 } 00170 00174 virtual void makeRequest() const override { 00175 if(send_callback_) send_callback_(*io_object_); 00176 } 00177 00178 protected: 00179 CallbackT recv_callback_; 00180 CallbackM send_callback_; 00181 std::unique_ptr<T> io_object_; 00182 }; 00183 00184 } // namespace client 00185 } // namespace msp 00186 00187 #endif