RosBridgeClient.h 6.72 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
bool is_valid_port_path(std::string server_port_path);

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

25 26 27 28 29 30
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
31 32
class RosbridgeWsClient
{
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
    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
49
    };
50

51
  const std::string server_port_path;
52 53
  std::unordered_map<std::string /*client name*/,
                     std::shared_ptr<WsClient> /*client*/> client_map;
54
  std::deque<EntryData> service_topic_list;
55
  std::mutex mutex;
56
  std::shared_ptr<std::atomic_bool> isConnected;
57
  std::shared_ptr<std::atomic_bool> stopped;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
58 59
  std::string available_topics;
  std::string available_services;
60
  std::shared_ptr<std::thread> periodic_thread;
Valentin Platzgummer's avatar
Valentin Platzgummer committed
61 62


Valentin Platzgummer's avatar
Valentin Platzgummer committed
63

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

public:
67
  RosbridgeWsClient(const std::string& server_port_path);
68
  RosbridgeWsClient(const std::string& server_port_path, bool run);
69 70

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

72
 bool connected();
73

74 75 76 77
 void run();
 void stop();
 void reset();

78
  // Adds a client to the client_map.
79 80 81 82 83 84 85
  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);
86

87 88 89 90 91 92
  //!
  //! \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.
93
  //! \pre Connection must be established, \see \fn connected().
94
  //!
95
  std::string getAdvertisedTopics();
96 97 98 99 100 101 102 103

  //!
  //! \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.
  //!
104 105 106
  std::string getAdvertisedServices();

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

108 109
  // Gets the client from client_map and starts it. Advertising is essentially sending a message.
  // One client per topic!
110
  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
111

112 113 114 115 116 117 118
  //!
  //! \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,
119 120 121
                   const std::string& id = "");

  void unadvertiseAll();
122

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

132 133 134 135 136 137 138 139 140 141 142 143 144
  //!
  //! \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().
  //!
145
  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 = "");
146

147
  void unsubscribe(const std::string& topic,
148 149 150 151 152 153 154
                   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
155

156 157 158 159 160
  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 = "");
161 162 163 164 165 166 167

  //!
  //! \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.
  //!
168
  bool serviceAvailable(const std::string& service);
169 170 171 172 173 174

  //!
  //! \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.
  //!
175
  void waitForService(const std::string& service);
176

177 178 179 180 181 182
  //!
  //! \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.
  //!
183
  void waitForService(const std::string& service, const std::function<bool(void)> stop);
184

185 186 187 188 189
  //!
  //! \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.
  //!
190
  void waitForTopic(const std::string& topic);
191 192 193 194 195 196
  //!
  //! \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.
  //!
197
  void waitForTopic(const std::string& topic, const std::function<bool(void)> stop);
Valentin Platzgummer's avatar
Valentin Platzgummer committed
198
};