#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/stringbuffer.h" #include "rapidjson/include/rapidjson/writer.h" #include #include #include #include #include bool is_valid_port_path(std::string server_port_path); using WsClient = SimpleWeb::SocketClient; using InMessage = std::function, std::shared_ptr)>; template constexpr typename std::underlying_type::type integral(T value) { return static_cast::type>(value); } class RosbridgeWsClient { enum class EntryType { SubscribedTopic, AdvertisedTopic, AdvertisedService, }; using EntryData = std::tuple /*client*/>; enum class EntryEnum { EntryType = 0, ServiceTopicName = 1, ClientName = 2, WPClient = 3 }; const std::string server_port_path; std::unordered_map /*client*/> client_map; std::deque service_topic_list; std::mutex mutex; std::shared_ptr isConnected; std::shared_ptr stopped; std::string available_topics; std::string available_services; std::shared_ptr periodic_thread; void start(const std::string &client_name, std::shared_ptr client, const std::string &message); public: RosbridgeWsClient(const std::string &server_port_path); RosbridgeWsClient(const std::string &server_port_path, bool run); ~RosbridgeWsClient(); bool connected(); void run(); bool running(); void stop(); void reset(); // Adds a client to the client_map. void addClient(const std::string &client_name); std::shared_ptr getClient(const std::string &client_name); void stopClient(const std::string &client_name); void removeClient(const std::string &client_name); //! //! \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. \pre Connection must be established, \see \fn //! connected(). //! std::string getAdvertisedTopics(); //! //! \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. //! std::string getAdvertisedServices(); bool topicAvailable(const std::string &topic); // 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 = ""); //! //! \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, const std::string &id = ""); void unadvertiseAll(); //! //! \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 = ""); //! //! \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(). //! 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 = ""); void unsubscribe(const std::string &topic, 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); 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 = ""); //! //! \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. //! bool serviceAvailable(const std::string &service); //! //! \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. //! void waitForService(const std::string &service); //! //! \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. //! void waitForService(const std::string &service, const std::function stop); //! //! \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. //! void waitForTopic(const std::string &topic); //! //! \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. //! void waitForTopic(const std::string &topic, const std::function stop); };