RosBridgeClient.h 6.58 KB
Newer Older
Valentin Platzgummer's avatar
Valentin Platzgummer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#pragma once

/*
*  Created on: Apr 16, 2018
*      Author: Poom Pianpak
*/

#include "Simple-WebSocket-Server/client_ws.hpp"

#include "rapidjson/include/rapidjson/document.h"
#include "rapidjson/include/rapidjson/writer.h"
#include "rapidjson/include/rapidjson/stringbuffer.h"

#include <functional>
15
#include <mutex>
16 17
#include <tuple>
#include <deque>
Valentin Platzgummer's avatar
Valentin Platzgummer committed
18
#include <thread>
Valentin Platzgummer's avatar
Valentin Platzgummer committed
19 20 21 22

using WsClient = SimpleWeb::SocketClient<SimpleWeb::WS>;
using InMessage =  std::function<void(std::shared_ptr<WsClient::Connection>, std::shared_ptr<WsClient::InMessage>)>;

23 24 25 26 27 28
template <typename T>
constexpr typename std::underlying_type<T>::type integral(T value)
{
    return static_cast<typename std::underlying_type<T>::type>(value);
}

Valentin Platzgummer's avatar
Valentin Platzgummer committed
29 30
class RosbridgeWsClient
{
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
    enum class EntryType{
        SubscribedTopic,
        AdvertisedTopic,
        AdvertisedService,
    };

    using EntryData = std::tuple<EntryType,
                             std::string /*service/topic name*/,
                             std::string /*client name*/,
                             std::weak_ptr<WsClient> /*client*/>;

    enum class EntryEnum{
        EntryType = 0,
        ServiceTopicName = 1,
        ClientName = 2,
        WPClient = 3
    };
48

49
  const std::string server_port_path;
50 51
  std::unordered_map<std::string /*client name*/,
                     std::shared_ptr<WsClient> /*client*/> client_map;
52
  std::deque<EntryData> service_topic_list;
53
  std::mutex mutex;
54 55
  std::shared_ptr<std::atomic_bool> hasConnection;
  std::shared_ptr<std::atomic_bool> stopped;
56

Valentin Platzgummer's avatar
Valentin Platzgummer committed
57 58 59 60 61 62
  std::shared_ptr<std::thread> pPoll_thread;
  std::string available_topics;
  std::string available_services;



63
  void start(const std::string& client_name, std::shared_ptr<WsClient> client, const std::string& message);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
64 65

public:
66 67 68
  RosbridgeWsClient(const std::string& server_port_path);

  ~RosbridgeWsClient();
Valentin Platzgummer's avatar
Valentin Platzgummer committed
69

70
 bool connected();
71

72
  // Adds a client to the client_map.
73 74 75 76 77 78 79
  void addClient(const std::string& client_name);

  std::shared_ptr<WsClient> getClient(const std::string& client_name);

  void stopClient(const std::string& client_name);

  void removeClient(const std::string& client_name);
80

81 82 83 84 85 86
  //!
  //! \brief Returns a string containing all advertised topics.
  //! \return Returns a string containing all advertised topics.
  //!
  //! \note This function will wait until the /rosapi/topics service is available.
  //! \note Call connected() in advance to ensure that a connection was established.
87
  //! \pre Connection must be established, \see \fn connected().
88
  //!
89
  std::string getAdvertisedTopics();
90 91 92 93 94 95 96 97

  //!
  //! \brief Returns a string containing all advertised services.
  //! \return Returns a string containing all advertised services.
  //!
  //! \note This function will wait until the /rosapi/services service is available.
  //! \note Call connected() in advance to ensure that a connection was established.
  //!
98 99 100
  std::string getAdvertisedServices();

  bool topicAvailable(const std::string &topic);
101

102 103
  // Gets the client from client_map and starts it. Advertising is essentially sending a message.
  // One client per topic!
104
  void advertise(const std::string& client_name, const std::string& topic, const std::string& type, const std::string& id = "");
Valentin Platzgummer's avatar
Valentin Platzgummer committed
105

106 107 108 109 110 111 112
  //!
  //! \brief Unadvertises the topice \p topic
  //! \param topic The topic to be unadvertised
  //! \param id
  //! \pre The topic \p topic must be advertised, \see topicAvailable().
  //!
  void unadvertise(const std::string& topic,
113 114 115
                   const std::string& id = "");

  void unadvertiseAll();
116

117 118 119 120 121 122 123
    //!
    //! \brief Publishes the message \p msg to the topic \p topic.
    //! \param topic The topic to publish the message.
    //! \param msg The message to publish.
    //! \param id
    //! \pre The topic \p topic must be advertised, \see topicAvailable().
    //!
124
  void publish(const std::string& topic, const rapidjson::Document& msg, const std::string& id = "");
125

126 127 128 129 130 131 132 133 134 135 136 137 138
  //!
  //! \brief Subscribes the client \p client_name to the topic \p topic.
  //! \param client_name
  //! \param topic
  //! \param callback
  //! \param id
  //! \param type
  //! \param throttle_rate
  //! \param queue_length
  //! \param fragment_size
  //! \param compression
  //! \pre The topic \p topic must be advertised, \see topicAvailable().
  //!
139
  void subscribe(const std::string& client_name, const std::string& topic, const InMessage& callback, const std::string& id = "", const std::string& type = "", int throttle_rate = -1, int queue_length = -1, int fragment_size = -1, const std::string& compression = "");
140

141
  void unsubscribe(const std::string& topic,
142 143 144 145 146 147 148
                   const std::string& id = "");

  void unsubscribeAll();

  void advertiseService(const std::string& client_name, const std::string& service, const std::string& type, const InMessage& callback);

  void unadvertiseService(const std::string& service);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
149

150 151 152 153 154
  void unadvertiseAllServices();

  void serviceResponse(const std::string& service, const std::string& id, bool result, const rapidjson::Document& values);

  void callService(const std::string& service, const InMessage& callback, const rapidjson::Document& args = {}, const std::string& id = "", int fragment_size = -1, const std::string& compression = "");
155 156 157 158 159 160 161

  //!
  //! \brief Checks if the service \p service is available.
  //! \param service Service name.
  //! \return Returns true if the service is available, false either.
  //! \note Don't call this function to frequently. Use \fn waitForService() instead.
  //!
162
  bool serviceAvailable(const std::string& service);
163 164 165 166 167 168

  //!
  //! \brief Waits until the service with the name \p service is available.
  //! \param service Service name.
  //! @note This function will block as long as the service is not available.
  //!
169
  void waitForService(const std::string& service);
170

171 172 173 174 175 176
  //!
  //! \brief Waits until the service with the name \p service is available.
  //! \param service Service name.
  //! \param stop Flag to stop waiting.
  //! @note This function will block as long as the service is not available or \p stop is false.
  //!
177
  void waitForService(const std::string& service, const std::shared_ptr<std::atomic_bool> stop);
178

179 180 181 182 183
  //!
  //! \brief Waits until the topic with the name \p topic is available.
  //! \param topic Topic name.
  //! @note This function will block as long as the topic is not available.
  //!
184
  void waitForTopic(const std::string& topic);
185 186 187 188 189 190
  //!
  //! \brief Waits until the topic with the name \p topic is available.
  //! \param topic Topic name.
  //! \param stop Flag to stop waiting.
  //! @note This function will block as long as the topic is not available or \p stop is false.
  //!
191
  void waitForTopic(const std::string& topic, const std::shared_ptr<std::atomic_bool> stop);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
192
};