RTC Toolkit 6.0.0
Loading...
Searching...
No Matches
clientLib.hpp
Go to the documentation of this file.
1
11
12#ifndef RTCTK_CLIENT_CLIENTLIB_HPP
13#define RTCTK_CLIENT_CLIENTLIB_HPP
14
19
20#include <boost/program_options.hpp>
21
22#include <chrono>
23#include <iostream>
24#include <thread>
25
26namespace rtctk::client {
27
28boost::program_options::variables_map ParseOptions(int argc, char* argv[]);
29
33template <typename CommandRequestorType = rtctk::componentFramework::CommandRequestor>
34int RunClient(int argc, char** argv) {
35 static_assert(
36 std::is_base_of_v<rtctk::componentFramework::CommandRequestor, CommandRequestorType>,
37 "'CommandRequestorType must extend 'rtctk::componentFramework::CommandRequestor'");
38 using namespace std;
39 using namespace rtctk::componentFramework;
40 using elt::mal::Uri;
41 using std::chrono::duration;
42 using std::chrono::duration_cast;
43 using std::chrono::milliseconds;
44 using std::chrono::seconds;
45
46 LogInitializer initializer;
47 LogConfigureTool("rtctkClient");
48 auto& logger = GetLogger("rtctk");
49
50 auto args = ParseOptions(argc, argv);
51 string cid = args["cid"].as<string>();
52 string cmd = args["cmd"].as<string>();
53 string cmd_arg = args["cmd_arg"].as<string>();
54 Uri sde = args["sde"].as<Uri>();
55 ServiceDiscovery serv_disc(sde, cid);
56
57 std::optional<milliseconds> timeout;
58 if (args.count("timeout")) {
59 timeout = duration_cast<milliseconds>(duration<double>(args["timeout"].as<double>()));
60 }
61
62 try {
63 if (cmd == "Listen") {
64 Uri subscribe_uri = serv_disc.GetPubSubEndpoint();
65 LOG4CPLUS_DEBUG(logger, "Subscribe URI is '" << subscribe_uri << "'.");
66
67 StateSubscriber subscriber(subscribe_uri,
68 [&](const taiclock::TaiClock::time_point timestamp,
69 const string& name,
70 const string& state) {
71 LOG4CPLUS_INFO(logger,
72 name << " changed state to: " << state);
73 });
74
75 while (true) {
76 this_thread::sleep_for(seconds(1));
77 }
78
79 } else {
80 Uri request_uri = serv_disc.GetReqRepEndpoint();
81 LOG4CPLUS_DEBUG(logger, "Request URI is '" << request_uri << "'.");
82
83 CommandRequestorType requestor(request_uri, timeout);
84 auto reply = requestor.SendCommandSync(cmd, cmd_arg);
85 cout << reply << endl;
86 }
87 } catch (const elt::mal::TimeoutException& e) {
88 LOG4CPLUS_ERROR(logger, "Request timed out.");
89 return EXIT_FAILURE;
90 } catch (const std::exception& e) {
91 LOG4CPLUS_FATAL(logger, e.what());
92 return EXIT_FAILURE;
93 } catch (...) {
94 LOG4CPLUS_FATAL(logger, "Unknown exception");
95 return EXIT_FAILURE;
96 }
97
98 return EXIT_SUCCESS;
99}
100
101boost::program_options::variables_map ParseOptions(int argc, char* argv[]) {
102 using namespace std;
103 namespace bpo = boost::program_options;
104 using elt::mal::Uri;
106 auto& logger = GetLogger("rtctk");
107
108 bpo::positional_options_description pos_opts_desc;
109 pos_opts_desc.add("cid", 1);
110 pos_opts_desc.add("cmd", 1);
111 pos_opts_desc.add("cmd_arg", -1);
112
113 bpo::options_description opts_desc("Options");
114 // clang-format off
115 opts_desc.add_options()
116 ("help,h", "Print help messages")
117 ("timeout,t", bpo::value<double>()->default_value(30.0), "timeout [sec]")
118 ("cid,i", bpo::value<string>(), "component identity")
119 ("cmd,c", bpo::value<string>(), "command name")
120 ("cmd_arg,a", bpo::value<string>()->default_value(""), "command arguments")
121 ("sde,s", bpo::value<Uri>()->default_value(Uri("consul://localhost:8500")),
122 "service discovery endpoint");
123 // clang-format on
124
125 try {
126 bpo::variables_map vm;
127
128 bpo::store(
129 bpo::command_line_parser(argc, argv).options(opts_desc).positional(pos_opts_desc).run(),
130 vm);
131
132 bpo::notify(vm);
133
134 if (vm.count("help")) {
135 cout << opts_desc << endl;
136 exit(EXIT_SUCCESS);
137 }
138 if (vm.count("cid")) {
139 LOG4CPLUS_DEBUG(logger, "Component identity is '" << vm["cid"].as<string>() << "'.");
140 } else {
141 LOG4CPLUS_FATAL(logger, "Component identity not specified !");
142 exit(EXIT_FAILURE);
143 }
144 if (vm.count("cmd")) {
145 LOG4CPLUS_DEBUG(logger, "Command is '" << vm["cmd"].as<string>() << "'.");
146 } else {
147 LOG4CPLUS_FATAL(logger, "Command name not specified !");
148 exit(EXIT_FAILURE);
149 }
150 if (vm.count("cmd_arg")) {
151 LOG4CPLUS_DEBUG(logger, "Command Arg is '" << vm["cmd_arg"].as<string>() << "'.");
152 }
153 if (vm.count("sde")) {
154 LOG4CPLUS_DEBUG(logger,
155 "Service Discovery Endpoint is '" << vm["sde"].as<Uri>() << "'.");
156 } else {
157 LOG4CPLUS_FATAL(logger, "Service Discovery Endpoint not specified !");
158 exit(EXIT_FAILURE);
159 }
160 if (vm.count("timeout")) {
161 LOG4CPLUS_DEBUG(logger,
162 "Request reply timeout is " << vm["timeout"].as<double>() << "s.");
163 }
164
165 return vm;
166
167 } catch (bpo::error& e) {
168 LOG4CPLUS_FATAL(logger, e.what() << endl << endl);
169 LOG4CPLUS_INFO(logger, opts_desc << endl);
170 exit(EXIT_FAILURE);
171 }
172}
173
174} // namespace rtctk::client
175
176#endif // RTCTK_CLIENT_CLIENTLIB_HPP
RAII class to clean-up logging without leaking memory.
Definition logger.hpp:27
Class that implements a very basic service discovery mechanism.
Definition serviceDiscovery.hpp:32
Class used to subscribe to state-changed-topic using MAL.
Definition stateSubscriber.hpp:40
Send commands using MAL.
log4cplus::Logger & GetLogger(const std::string &name="app")
Get handle to a specific logger.
Definition logger.cpp:191
int RunClient(int argc, char **argv)
Definition clientLib.hpp:34
log4cplus::Logger & GetLogger(const std::string &name="app")
Get handle to a specific logger.
Definition logger.cpp:191
void LogConfigureTool(const std::string &app_name, log4cplus::LogLevel default_log_level=log4cplus::ERROR_LOG_LEVEL, bool log_to_file=false)
Performs default logging configuration for Client Applications and Standalone Tools.
Definition logger.cpp:144
Logging Support Library based on log4cplus.
Definition clientLib.hpp:26
boost::program_options::variables_map ParseOptions(int argc, char *argv[])
Definition clientLib.hpp:101
Definition commandReplier.cpp:21
Definition ddsSub.hpp:155
Class that implements a very basic service discover mechanism.
Subscribes to stdif state topic via MAL.