RosBridgeClient.h 6.98 KB
Newer Older
Valentin Platzgummer's avatar
Valentin Platzgummer committed
1 2 3
#pragma once

/*
Valentin Platzgummer's avatar
Valentin Platzgummer committed
4 5 6
 *  Created on: Apr 16, 2018
 *      Author: Poom Pianpak
 */
Valentin Platzgummer's avatar
Valentin Platzgummer committed
7 8 9 10 11

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

#include "rapidjson/include/rapidjson/document.h"
#include "rapidjson/include/rapidjson/stringbuffer.h"
Valentin Platzgummer's avatar
Valentin Platzgummer committed
12
#include "rapidjson/include/rapidjson/writer.h"
Valentin Platzgummer's avatar
Valentin Platzgummer committed
13

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

20 21
bool is_valid_port_path(std::string server_port_path);

Valentin Platzgummer's avatar
Valentin Platzgummer committed
22
using WsClient = SimpleWeb::SocketClient<SimpleWeb::WS>;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
23 24
using InMessage = std::function<void(std::shared_ptr<WsClient::Connection>,
                                     std::shared_ptr<WsClient::InMessage>)>;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
25

26
template <typename T>
Valentin Platzgummer's avatar
Valentin Platzgummer committed
27 28
constexpr typename std::underlying_type<T>::type integral(T value) {
  return static_cast<typename std::underlying_type<T>::type>(value);
29 30
}

Valentin Platzgummer's avatar
Valentin Platzgummer committed
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
class RosbridgeWsClient {
  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
  std::unordered_map<std::string /*client name*/,
Valentin Platzgummer's avatar
Valentin Platzgummer committed
51 52
                     std::shared_ptr<WsClient> /*client*/>
      client_map;
53
  std::deque<EntryData> service_topic_list;
54
  std::mutex mutex;
55
  std::shared_ptr<std::atomic_bool> isConnected;
56
  std::shared_ptr<std::atomic_bool> stopped;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
57 58
  std::string available_topics;
  std::string available_services;
59
  std::shared_ptr<std::thread> periodic_thread;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
60

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

public:
Valentin Platzgummer's avatar
Valentin Platzgummer committed
65 66
  RosbridgeWsClient(const std::string &server_port_path);
  RosbridgeWsClient(const std::string &server_port_path, bool run);
67 68

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

Valentin Platzgummer's avatar
Valentin Platzgummer committed
70
  bool connected();
71

Valentin Platzgummer's avatar
Valentin Platzgummer committed
72 73 74 75
  void run();
  bool running();
  void stop();
  void reset();
76

77
  // Adds a client to the client_map.
Valentin Platzgummer's avatar
Valentin Platzgummer committed
78
  void addClient(const std::string &client_name);
79

Valentin Platzgummer's avatar
Valentin Platzgummer committed
80
  std::shared_ptr<WsClient> getClient(const std::string &client_name);
81

Valentin Platzgummer's avatar
Valentin Platzgummer committed
82
  void stopClient(const std::string &client_name);
83

Valentin Platzgummer's avatar
Valentin Platzgummer committed
84
  void removeClient(const std::string &client_name);
85

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

  //!
  //! \brief Returns a string containing all advertised services.
  //! \return Returns a string containing all advertised services.
  //!
Valentin Platzgummer's avatar
Valentin Platzgummer committed
101 102 103
  //! \note This function will wait until the /rosapi/services service is
  //! available. \note Call connected() in advance to ensure that a connection
  //! was established.
104
  //!
105 106 107
  std::string getAdvertisedServices();

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

Valentin Platzgummer's avatar
Valentin Platzgummer committed
109 110 111 112
  // Gets the client from client_map and starts it. Advertising is essentially
  // sending a message. One client per topic!
  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
113

114 115 116 117 118 119
  //!
  //! \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().
  //!
Valentin Platzgummer's avatar
Valentin Platzgummer committed
120
  void unadvertise(const std::string &topic, const std::string &id = "");
121 122

  void unadvertiseAll();
123

Valentin Platzgummer's avatar
Valentin Platzgummer committed
124 125 126 127 128 129 130 131 132
  //!
  //! \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().
  //!
  void publish(const std::string &topic, const rapidjson::Document &msg,
               const std::string &id = "");
133

134 135 136 137 138 139 140 141 142 143 144 145 146
  //!
  //! \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().
  //!
Valentin Platzgummer's avatar
Valentin Platzgummer committed
147 148 149 150 151
  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 = "");
152

Valentin Platzgummer's avatar
Valentin Platzgummer committed
153
  void unsubscribe(const std::string &topic, const std::string &id = "");
154 155 156

  void unsubscribeAll();

Valentin Platzgummer's avatar
Valentin Platzgummer committed
157 158 159
  void advertiseService(const std::string &client_name,
                        const std::string &service, const std::string &type,
                        const InMessage &callback);
160

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

163 164
  void unadvertiseAllServices();

Valentin Platzgummer's avatar
Valentin Platzgummer committed
165 166
  void serviceResponse(const std::string &service, const std::string &id,
                       bool result, const rapidjson::Document &values);
167

Valentin Platzgummer's avatar
Valentin Platzgummer committed
168 169 170 171
  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 = "");
172 173 174 175 176

  //!
  //! \brief Checks if the service \p service is available.
  //! \param service Service name.
  //! \return Returns true if the service is available, false either.
Valentin Platzgummer's avatar
Valentin Platzgummer committed
177 178
  //! \note Don't call this function to frequently. Use \fn waitForService()
  //! instead.
179
  //!
Valentin Platzgummer's avatar
Valentin Platzgummer committed
180
  bool serviceAvailable(const std::string &service);
181 182 183 184 185 186

  //!
  //! \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.
  //!
Valentin Platzgummer's avatar
Valentin Platzgummer committed
187
  void waitForService(const std::string &service);
188

189 190 191 192
  //!
  //! \brief Waits until the service with the name \p service is available.
  //! \param service Service name.
  //! \param stop Flag to stop waiting.
Valentin Platzgummer's avatar
Valentin Platzgummer committed
193 194
  //! @note This function will block as long as the service is not available or
  //! \p stop is false.
195
  //!
Valentin Platzgummer's avatar
Valentin Platzgummer committed
196 197
  void waitForService(const std::string &service,
                      const std::function<bool(void)> stop);
198

199 200 201 202 203
  //!
  //! \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.
  //!
Valentin Platzgummer's avatar
Valentin Platzgummer committed
204
  void waitForTopic(const std::string &topic);
205 206 207 208
  //!
  //! \brief Waits until the topic with the name \p topic is available.
  //! \param topic Topic name.
  //! \param stop Flag to stop waiting.
Valentin Platzgummer's avatar
Valentin Platzgummer committed
209 210
  //! @note This function will block as long as the topic is not available or \p
  //! stop is false.
211
  //!
Valentin Platzgummer's avatar
Valentin Platzgummer committed
212 213
  void waitForTopic(const std::string &topic,
                    const std::function<bool(void)> stop);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
214
};